commit 36f5485422a6695bbf6ceba200c430fe0bb73ad4
parent d555132119962605dbb47e692725ba10632e57d2
Author: Friedel Schön <[email protected]>
Date: Tue, 21 Jun 2022 19:53:44 +0200
refactoring client-code
Diffstat:
28 files changed, 632 insertions(+), 509 deletions(-)
diff --git a/.vscode/arduino.json b/.vscode/arduino.json
@@ -1,6 +1,6 @@
{
- "sketch": "5g-client/5g-client.ino",
+ "sketch": "client/client.ino",
"board": "SODAQ:samd:sodaq_sara",
- "port": "/dev/tty.usbmodem142301",
+ "port": "/dev/tty.usbmodem14201",
"output": "build"
}
\ No newline at end of file
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
@@ -23,6 +23,7 @@
"/Users/friedel/Library/Arduino15/packages/arduino/tools/CMSIS-Atmel/1.2.0/CMSIS/Device/ATMEL/",
"/Users/friedel/Library/Arduino15/packages/SODAQ/hardware/samd/1.8.9/cores/arduino",
"/Users/friedel/Library/Arduino15/packages/SODAQ/hardware/samd/1.8.9/variants/sodaq_sara",
+ "/Users/friedel/Documents/Arduino/libraries/FlashStorage/src",
"/Users/friedel/Documents/Arduino/libraries/Arduino_JSON/src",
"/Users/friedel/Documents/Arduino/libraries/Sodaq_LSM303AGR/src",
"/Users/friedel/Library/Arduino15/packages/SODAQ/hardware/samd/1.8.9/libraries/Wire",
diff --git a/.vscode/settings.json b/.vscode/settings.json
@@ -5,6 +5,7 @@
".clangd": "yaml",
".yabairc": "shellscript",
"v.mod": "plaintext",
- "limits": "cpp"
+ "limits": "cpp",
+ "typeinfo": "cpp"
},
}
\ No newline at end of file
diff --git a/5g-client/5g-client.ino b/5g-client/5g-client.ino
@@ -1,80 +0,0 @@
-#include "include/config.h"
-#include "include/http.h"
-#include "include/led.h"
-
-#include <Sodaq_LSM303AGR.h>
-#include <Sodaq_UBlox_GPS.h>
-#include <Wire.h>
-
-#define ADC_AREF 3.3f
-#define BATVOLT_R1 4.7f
-#define BATVOLT_R2 10.0f
-#define BATVOLT_PIN BAT_VOLT
-
-#define statusDelay 1.0 // seconds
-
-#define batteryFactor (0.978 * (BATVOLT_R1 / BATVOLT_R2 + 1) / ADC_AREF)
-
-http_client http;
-Sodaq_LSM303AGR accel;
-
-void setup() {
- led.begin();
- http.begin();
-
- pinMode(BATVOLT_PIN, INPUT);
- pinMode(CHARGER_STATUS, INPUT);
-
- Wire.begin();
- delay(1000);
- sodaq_gps.init(GPS_ENABLE);
-
- accel.rebootAccelerometer();
- delay(1000);
-
- // Enable the Accelerometer
- accel.enableAccelerometer();
-}
-
-void loop() {
- led.blink();
-
- static int last = 0;
- int now = millis();
-
- static double lat = 0, lon = 0, accuracy = 0;
-
- if (now - last > statusDelay * 1000) {
- if (sodaq_gps.scan(true, gpsTimeout * 1000)) {
- led.set(status_led::COLOR_GREEN);
-
- lat = sodaq_gps.getLat();
- lon = sodaq_gps.getLon();
- accuracy = 1.0 / sodaq_gps.getHDOP() * 100;
- // -> 100% the best, 0% the worst
- } else {
- led.set(status_led::COLOR_BLUE);
- }
-
- json req;
- // req.method = "POST";
- // req.endpoint = "/api/update";
- req["latitude"] = lat;
- req["longitude"] = lon;
- req["accuracy"] = accuracy;
- req["battery"] = batteryVoltage();
- req["temperature"] = temperature();
- req["charging"] = (bool) digitalRead(CHARGER_STATUS);
-
- http.send(http_client::HTTP_POST, "/api/update", req);
- last = now;
- }
-}
-
-int temperature() {
- return accel.getTemperature();
-}
-
-int batteryVoltage() {
- return batteryFactor * (float) analogRead(BATVOLT_PIN);
-}
diff --git a/5g-client/http.ino b/5g-client/http.ino
@@ -1,79 +0,0 @@
-#include "include/config.h"
-#include "include/http.h"
-#include "include/led.h"
-
-json null_response;
-
-void http_client::begin() {
- led.set(status_led::COLOR_NONE, status_led::COLOR_CYAN);
-
- if (remoteForce) {
- fallback();
- return;
- }
-}
-
-void http_client::fallback() {
- led.set(status_led::COLOR_RED, status_led::COLOR_YELLOW);
- remote = true;
-
- usbSerial.begin(remoteBaud);
- while (!usbSerial)
- led.blink();
-
- led.set(status_led::COLOR_YELLOW);
-}
-
-int http_client::send(http_client::method method, const char* endpoint, json body, json& response) {
- static char buffer[512];
- json::stringify(body).toCharArray(buffer, 512);
- return send(method, endpoint, buffer, response);
-}
-
-int http_client::send(http_client::method method, const char* endpoint, const char* body, json& response) {
- int code;
- if (!remote) {
-
- } else {
- switch (method) {
- case http_client::HTTP_GET:
- usbSerial.print("GET ");
- break;
- case http_client::HTTP_POST:
- usbSerial.print("POST ");
- }
- usbSerial.print(endpoint);
- usbSerial.print(" ");
- usbSerial.println(body);
- // body.printTo(usbSerial);
- usbSerial.println();
-
- char buffer[256];
- int i = 0;
- int state = 0; // 0 = status-code; 1 = json
- char c;
-
- for (;;) {
- if (usbSerial.available()) {
- c = usbSerial.read();
- if (c == '\r') {
- // do nothing
- } else if (state == 0 && c == ' ') {
- buffer[i++] = '\0';
- code = atoi(buffer);
- i = 0;
- state = 1;
- } else if (state == 1 && c == '\n') {
- buffer[i++] = '\0';
- response = json::parse(buffer);
- break;
- } else {
- buffer[i++] = c;
- }
- }
-
- led.blink();
- }
- }
- return code;
-}
-\ No newline at end of file
diff --git a/5g-client/include/config.h b/5g-client/include/config.h
@@ -1,39 +0,0 @@
-#pragma once
-
-// -*- hardware stuff -*-
-#define usbSerial SerialUSB // usb serial port
-#define modemSerial Serial1 // modem serial port
-#define modemPowerPin SARA_ENABLE // modem power pin
-#define modemEnablePin SARA_TX_ENABLE // modem enable pin
-#define modemVoltagePin SARA_R4XX_TOGGLE // modem voltage pin
-
-// -*- behaviour settings -*-
-#define remoteBaud 115200 // baud-rate of usb-serial
-#define modemBaud 115200 // baud-rate of modem-serial
-#define remoteForce true // do not try connect to modem
-#define remoteFirstTimeout 5.0 // seconds to wait for the first timeout
-#define remoteTimeout 1.0 // seconds to wait for remote to timeout
-#define lineBuffer 512 // buffer-size (bytes) to use to store lines
-#define commandTimeout 10.0 // seconds to cancel a command
-#define commandDelay 0.1 // delay after every command
-#define ignoreDelay 2.0 // seconds to wait if command is run with COMMAND_IGNORE
-#define commandDebug true // send debug information about command requests
-#define eventDebug true // print '+'-events
-#define lineDebug false // print each line to debug
-#define blockDebug true // print if command is blocking
-#define blinkInterval 0.25 // seconds to wait for blink
-#define gpsTimeout 10 // seconds to gps-timeout
-
-// -*- sim settings -*-
-#define macAddress "CAFEBABE01234567" // the boards mac-address
-#define simPin "0000" // PIN of the sim
-#define simAPN "lpwa.vodafone.iot" // APN-network of the sim
-#define apiHostname "muizenval.tk"
-
-// -*- prefixes -*-
-#define prefixInfo "info | "
-#define prefixDebug "debug | "
-#define prefixError "error | "
-#define prefixLine "line | "
-#define prefixWarn "warn | "
-#define prefixEvent "event | "
diff --git a/5g-client/include/http.h b/5g-client/include/http.h
@@ -1,28 +0,0 @@
-#pragma once
-
-#include <Arduino_JSON.h>
-
-
-typedef JSONVar json;
-
-extern json null_response;
-
-struct http_client {
- enum method {
- HTTP_GET,
- HTTP_POST
- };
-
- protected:
- bool remote = false;
-
- void fallback();
-
- public:
- bool ready = false;
-
- void begin();
-
- int send(method method, const char* endpoint, const char* body = "{}", json& response = null_response);
- int send(method method, const char* endpoint, json body = nullptr, json& response = null_response);
-};
-\ No newline at end of file
diff --git a/5g-client/include/led.h b/5g-client/include/led.h
@@ -1,26 +0,0 @@
-#pragma once
-
-
-struct status_led {
- enum color {
- COLOR_NONE,
- COLOR_RED,
- COLOR_GREEN,
- COLOR_BLUE,
- COLOR_YELLOW,
- COLOR_CYAN,
- COLOR_MAGENTA,
- COLOR_WHITE,
- };
-
- protected:
- color color0 = COLOR_NONE, color1 = COLOR_NONE;
-
- public:
- void begin();
- void set(color c);
- void set(color c0, color c1);
- void blink();
-};
-
-extern status_led led;
-\ No newline at end of file
diff --git a/5g-client/led.ino b/5g-client/led.ino
@@ -1,51 +0,0 @@
-#include "include/config.h"
-#include "include/led.h"
-
-static bool colors[][3] = {
- [status_led::COLOR_NONE] = { 0, 0, 0 },
- [status_led::COLOR_RED] = { 1, 0, 0 },
- [status_led::COLOR_GREEN] = { 0, 1, 0 },
- [status_led::COLOR_BLUE] = { 0, 0, 1 },
- [status_led::COLOR_YELLOW] = { 1, 1, 0 },
- [status_led::COLOR_CYAN] = { 0, 1, 1 },
- [status_led::COLOR_MAGENTA] = { 1, 0, 1 },
- [status_led::COLOR_WHITE] = { 1, 1, 1 },
-};
-
-static void writeLED(bool red, bool green, bool blue) {
- digitalWrite(LED_RED, !red);
- digitalWrite(LED_GREEN, !green);
- digitalWrite(LED_BLUE, !blue);
-}
-
-void status_led::begin() {
- pinMode(LED_RED, OUTPUT);
- pinMode(LED_GREEN, OUTPUT);
- pinMode(LED_BLUE, OUTPUT);
-}
-
-void status_led::set(color c) {
- color0 = color1 = c;
-}
-
-void status_led::set(color c0, color c1) {
- color0 = c0;
- color1 = c1;
-}
-
-void status_led::blink() {
- static int last = 0;
- static bool first = false;
- int now = millis();
-
- if (now - last > blinkInterval * 1000) {
- if (first)
- writeLED(colors[color0][0], colors[color0][1], colors[color0][2]);
- else
- writeLED(colors[color1][0], colors[color1][1], colors[color1][2]);
- first = !first;
- last = now;
- }
-}
-
-status_led led;
-\ No newline at end of file
diff --git a/client/client.ino b/client/client.ino
@@ -0,0 +1,85 @@
+#include "include/config.h"
+#include "include/interface.h"
+#include "include/led.h"
+
+#include <Sodaq_LSM303AGR.h>
+#include <Sodaq_UBlox_GPS.h>
+#include <Wire.h>
+
+interface client;
+Sodaq_LSM303AGR accel;
+
+void (*reset)() = 0;
+
+void setup() {
+ pinMode(LED_RED, OUTPUT);
+ pinMode(LED_GREEN, OUTPUT);
+ pinMode(LED_BLUE, OUTPUT);
+ pinMode(trapPin, INPUT_PULLUP);
+ pinMode(BATVOLT_PIN, INPUT);
+ pinMode(CHARGER_STATUS, INPUT);
+
+ config_current = config_flash.read();
+
+ client.begin();
+
+ json req;
+ // req["mac"] = macAddress;
+ client.send(interface::METHOD_POST, "/api/hello", req);
+
+ Wire.begin();
+ delay(1000);
+ sodaq_gps.init(GPS_ENABLE);
+
+ accel.rebootAccelerometer();
+ delay(1000);
+
+ // Enable the Accelerometer
+ accel.enableAccelerometer();
+}
+
+void loop() {
+ static int last = 0;
+ int now = millis();
+
+ if (now - last > statusInterval * 1000) {
+ json gps;
+ if (sodaq_gps.scan(true, gpsTimeout * 1000)) {
+ gps["signal"] = true;
+ gps["latitude"] = sodaq_gps.getLat();
+ gps["longitude"] = sodaq_gps.getLon();
+ gps["accuracy"] = getAccuracy(); // -> 100% the best, 0% the worst
+ } else {
+ gps["signal"] = false;
+ }
+
+ gps["satellites"] = sodaq_gps.getNumberOfSatellites();
+
+ json req;
+ req["battery"] = batteryVoltage();
+ req["temperature"] = accel.getTemperature();
+ req["charging"] = getCharging();
+ req["trap"] = getTrapStatus();
+ req["gps"] = gps;
+
+ client.send(interface::METHOD_POST, "/api/update", req);
+ last = now;
+ }
+}
+
+double batteryVoltage() {
+ return batteryFactor * (double) analogRead(BATVOLT_PIN);
+}
+
+double getAccuracy() {
+ double hdop = sodaq_gps.getHDOP();
+ return hdop > 1 ? 1.0 / hdop * 100 : hdop * 100;
+}
+
+bool getTrapStatus() {
+ return digitalRead(trapPin);
+}
+
+bool getCharging() {
+ return digitalRead(CHARGER_STATUS);
+}
+\ No newline at end of file
diff --git a/client/config.ino b/client/config.ino
@@ -0,0 +1,14 @@
+#include "include/config.h"
+
+FlashStorage(config_flash, configuration);
+
+configuration default_config{
+ /*.valid =*/true,
+ /*.simPIN =*/"",
+ /*.simPUK =*/"",
+ /*.simAPN =*/"",
+ /*.domain =*/"muizenval.tk",
+ /*.userToken =*/""
+};
+
+configuration config_current;
+\ No newline at end of file
diff --git a/client/include/config.h b/client/include/config.h
@@ -0,0 +1,65 @@
+#pragma once
+
+#include <FlashStorage.h>
+
+// -*- hardware stuff -*-
+#define usbSerial SerialUSB // usb serial port
+#define modemSerial Serial1 // modem serial port
+#define modemPowerPin SARA_ENABLE // modem power pin
+#define modemEnablePin SARA_TX_ENABLE // modem enable pin
+#define modemVoltagePin SARA_R4XX_TOGGLE // modem voltage pin
+#define trapPin 10 // pin of magnet-sensor
+
+// -*- behaviour settings -*-
+#define remoteBaud 115200 // baud-rate of usb-serial
+#define modemBaud 115200 // baud-rate of modem-serial
+#define remoteForce true // do not try connect to modem
+#define remoteFirstTimeout 5.0 // seconds to wait for the first timeout
+#define remoteTimeout 1.0 // seconds to wait for remote to timeout
+#define lineBuffer 512 // buffer-size (bytes) to use to store lines
+#define commandTimeout 10.0 // seconds to cancel a command
+#define commandDelay 0.1 // delay after every command
+#define ignoreDelay 2.0 // seconds to wait if command is run with COMMAND_IGNORE
+#define commandDebug true // send debug information about command requests
+#define eventDebug true // print '+'-events
+#define lineDebug false // print each line to debug
+#define blockDebug true // print if command is blocking
+#define blinkInterval 0.25 // seconds to wait for blink
+#define gpsTimeout 5 // seconds to gps-timeout
+#define statusInterval 5 // send status every n seconds
+
+#define ADC_AREF 3.3f
+#define BATVOLT_R1 4.7f
+#define BATVOLT_R2 10.0f
+#define BATVOLT_PIN BAT_VOLT
+#define batteryFactor (0.978 * (BATVOLT_R1 / BATVOLT_R2 + 1) / ADC_AREF)
+
+// -*- sim settings -*-
+//#define simPin "0000" // PIN of the sim
+//#define simAPN "lpwa.vodafone.iot" // APN-network of the sim
+//#define apiHostname "muizenval.tk"
+
+// -*- prefixes -*-
+#define prefixInfo "info | "
+#define prefixDebug "debug | "
+#define prefixError "error | "
+#define prefixLine "line | "
+#define prefixWarn "warn | "
+#define prefixEvent "event | "
+
+
+struct configuration {
+ bool valid;
+
+ char simPIN[4];
+ char simPUK[8];
+ char simAPN[50];
+ char domain[50];
+
+ char userToken[16];
+};
+
+extern FlashStorageClass<configuration> config_flash;
+
+extern configuration config_default;
+extern configuration config_current;
diff --git a/client/include/interface.h b/client/include/interface.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include <Arduino_JSON.h>
+
+
+typedef JSONVar json;
+
+extern json null_response;
+
+struct interface {
+ enum method {
+ METHOD_GET,
+ METHOD_POST
+ };
+
+ enum command_status {
+ STATUS_OK = 0, // command succeed
+ STATUS_ERROR = 1, // command returned an error
+ STATUS_TIMEOUT = 2, // command timed out
+ STATUS_NOT_READY = 3, // interface is not ready
+ };
+
+ enum command_flags {
+ COMMAND_NONE, // none of them underneath
+ COMMAND_FORCE = 1 << 0, // ignore modemReady/remoteReady
+ COMMAND_BLOCK = 1 << 1, // no time-out (for waiting commands)
+ COMMAND_IGNORE = 1 << 2, // don't wait for response, just wait $ignoreDelay secounds
+ };
+
+ protected:
+ bool remoteReady = false;
+ bool modemReady = false;
+
+ char debugToken[16];
+
+ void beginModem();
+
+ void beginRemote();
+ void endRemote();
+
+ public:
+ void begin();
+
+ int send(method method, const char* endpoint, json body = nullptr, json& response = null_response);
+
+ command_status remote(const char* command, json params = nullptr, json& response = null_response, command_flags flags = COMMAND_NONE);
+
+ command_status modem(const char* request, char* response, command_flags flags = COMMAND_NONE);
+ command_status modem(const char* request, command_flags flags = COMMAND_NONE);
+};
+\ No newline at end of file
diff --git a/client/include/led.h b/client/include/led.h
@@ -0,0 +1,14 @@
+#pragma once
+
+enum color {
+ COLOR_NONE,
+ COLOR_RED,
+ COLOR_GREEN,
+ COLOR_BLUE,
+ COLOR_YELLOW,
+ COLOR_CYAN,
+ COLOR_MAGENTA,
+ COLOR_WHITE,
+};
+
+void writeLED(color c);
diff --git a/client/interface.ino b/client/interface.ino
@@ -0,0 +1,152 @@
+#include "include/config.h"
+#include "include/interface.h"
+#include "include/led.h"
+
+json null_response;
+
+static const char* method_strings[] = {
+ [interface::METHOD_GET] = "GET",
+ [interface::METHOD_POST] = "POST",
+};
+
+void interface::begin() {
+ writeLED(COLOR_MAGENTA);
+
+ usbSerial.begin(remoteBaud);
+ usbSerial.setTimeout(remoteTimeout);
+
+ if (remoteForce)
+ return;
+
+ pinMode(modemPowerPin, OUTPUT); // Put voltage on the nb-iot module
+ pinMode(modemVoltagePin, OUTPUT); // Switch module voltage
+ pinMode(modemEnablePin, OUTPUT); // Set state to active
+
+ digitalWrite(modemPowerPin, HIGH);
+ digitalWrite(modemVoltagePin, LOW);
+ digitalWrite(modemEnablePin, HIGH);
+ modemSerial.begin(modemBaud);
+
+ while (!modemSerial)
+ ;
+
+ // -*- module initialization -*-
+ for (;;) {
+ modemSerial.write("AT\r\n");
+ delay(1000);
+ if (modemSerial.available())
+ break;
+ }
+
+ while (modemSerial.available()) // clear cache
+ modemSerial.read();
+
+ // commands...
+
+ modemReady = true;
+
+ writeLED(COLOR_BLUE);
+}
+
+void interface::beginRemote() {
+ if (remoteReady) // already initalizised
+ return;
+
+ writeLED(COLOR_RED);
+ while (!usbSerial)
+ ;
+ writeLED(COLOR_YELLOW);
+
+ remoteReady = true;
+}
+
+void interface::endRemote() {
+ if (!remoteReady)
+ return;
+
+ writeLED(COLOR_BLUE);
+
+ json response;
+ remote("hello", nullptr, response, COMMAND_FORCE);
+ const char* debug = response["debugToken"];
+ memcpy(debugToken, debug, sizeof(debugToken));
+
+ remoteReady = false;
+}
+
+int interface::send(interface::method method, const char* endpoint, json body, json& response) {
+ int code;
+
+ if (usbSerial || !modemReady) {
+ beginRemote();
+
+ json request;
+
+ body["debugToken"] = debugToken;
+
+ request["method"] = method_strings[method];
+ request["endpoint"] = endpoint;
+ request["body"] = body;
+
+ json cmd_response;
+ if (remote("send", request, cmd_response))
+ return 0;
+
+ response = cmd_response["body"];
+ return cmd_response["code"];
+ } else {
+ endRemote();
+ // modem
+ }
+ return code;
+}
+
+interface::command_status interface::remote(const char* command, json params, json& response, command_flags flags) {
+ bool force = flags & COMMAND_FORCE;
+
+ if (!force && !remoteReady)
+ return interface::STATUS_NOT_READY;
+
+ usbSerial.print(command);
+ usbSerial.print(" ");
+ params.printTo(usbSerial);
+ usbSerial.print("\n");
+
+ String status = usbSerial.readStringUntil(' ');
+ if (!status.length()) {
+ return interface::STATUS_TIMEOUT;
+ } else if (status == "ok") {
+ response = json::parse(usbSerial.readStringUntil('\n'));
+ return interface::STATUS_OK;
+ } else {
+ response = status;
+ return interface::STATUS_ERROR;
+ }
+}
+
+interface::command_status interface::modem(const char* request, char* response, command_flags flags) {
+ char line[lineBuffer];
+ size_t lineLen;
+ char buf;
+
+ bool force = flags & COMMAND_FORCE,
+ block = flags & COMMAND_BLOCK,
+ ignore = flags & COMMAND_IGNORE;
+
+ if (!force && !modemReady)
+ return interface::STATUS_NOT_READY;
+
+ if (response)
+ response[0] = '\0';
+
+ modemSerial.write("AT");
+ modemSerial.write(request);
+ modemSerial.write("\r\n");
+
+
+ delay(commandDelay * 1000);
+}
+
+interface::command_status interface::modem(const char* request, command_flags flags) {
+ return modem(request, NULL, flags);
+}
diff --git a/client/led.ino b/client/led.ino
@@ -0,0 +1,18 @@
+#include "include/led.h"
+
+static const bool colors[][3] = {
+ [COLOR_NONE] = { 0, 0, 0 },
+ [COLOR_RED] = { 1, 0, 0 },
+ [COLOR_GREEN] = { 0, 1, 0 },
+ [COLOR_BLUE] = { 0, 0, 1 },
+ [COLOR_YELLOW] = { 1, 1, 0 },
+ [COLOR_CYAN] = { 0, 1, 1 },
+ [COLOR_MAGENTA] = { 1, 0, 1 },
+ [COLOR_WHITE] = { 1, 1, 1 },
+};
+
+void writeLED(color c) {
+ digitalWrite(LED_RED, !colors[c][0]);
+ digitalWrite(LED_GREEN, !colors[c][1]);
+ digitalWrite(LED_BLUE, !colors[c][2]);
+}
+\ No newline at end of file
diff --git a/5g-client/include/modem.h b/dump/modem.h
diff --git a/5g-client/modem.ino b/dump/modem.ino
diff --git a/dump/old_client.ino b/dump/old_client.ino
@@ -0,0 +1,175 @@
+#include "include/config.h"
+#include "include/http.h"
+#include "include/modem.h"
+#include "include/remote.h"
+
+#include <Sodaq_LSM303AGR.h>
+#include <Sodaq_UBlox_GPS.h>
+#include <Wire.h>
+
+#define ADC_AREF 3.3f
+#define BATVOLT_R1 4.7f
+#define BATVOLT_R2 10.0f
+#define BATVOLT_PIN BAT_VOLT
+
+#define statusDelay 0.5 // seconds
+
+#define batteryFactor (0.978 * (BATVOLT_R1 / BATVOLT_R2 + 1) / ADC_AREF)
+
+interface http;
+
+sara_modem modem;
+Sodaq_LSM303AGR accel;
+serial_remote remote;
+
+void setup() {
+ // -*- hardware initiation -*-
+
+ usbSerial.begin(remoteBaud);
+ while (true && !usbSerial)
+ ;
+
+ pinMode(BATVOLT_PIN, INPUT);
+ pinMode(CHARGER_STATUS, INPUT);
+
+ // modem.init();
+ remote.begin();
+
+ Wire.begin();
+ delay(1000);
+ sodaq_gps.init(GPS_ENABLE);
+
+ accel.rebootAccelerometer();
+ delay(1000);
+
+ // Enable the Accelerometer
+ accel.enableAccelerometer();
+
+ remote.connect("127.0.0.1", 5000);
+
+ // modem.send("ATE0"); // disable command-echo
+
+ // if (modem.send("AT+CPIN=\"" SIM_PIN "\"") == sara_modem::COMMAND_ERROR) {
+ // // usbSerial.println("[EROR] sim can't be unlocked, wrong PIN");
+ // return;
+ // }
+ // usbSerial.println(prefixInfo "sim successful unlocked");
+ /*
+
+ modem.send("AT+CPSMS=0"); // Disable Power Saving Mode
+ modem.send("AT+CEDRXS=0"); // Disable eDRX
+ // usbSerial.println(prefixInfo "disabled power safe");
+
+
+ // -*- internet initialization -*-
+ char info[100];
+
+ modem.send("AT+CFUN=15", sara_modem::COMMAND_BLOCK); // Reset the module
+ modem.send("AT+UMNOPROF=1", sara_modem::COMMAND_BLOCK); // Set MNO profile (1=automatic,100=standard europe)
+ modem.send("AT+URAT?", info);
+ // usbSerial.print(prefixInfo "urat: ");
+ // usbSerial.println(info);
+ modem.send("AT+URAT=8", sara_modem::COMMAND_IGNORE); // Set URAT to LTE-M/NB-IOT
+ modem.send("AT+CEREG=3", sara_modem::COMMAND_IGNORE); // Enable URCs
+ modem.send("AT+CGDCONT=1,\"IP\",\"" simAPN "\"", sara_modem::COMMAND_BLOCK); // Set the APN
+ modem.send("AT+CFUN=1"); // enable radio
+ modem.send("AT+COPS=0,2", sara_modem::COMMAND_BLOCK); // Autoselect the operator
+
+ // usbSerial.print(prefixInfo "waiting for connection");
+
+ char response[100];
+
+ // Check Siganl strenght, repeat till you have a valid CSQ (99,99 means no signal)
+ while (modem.send("AT+CSQ", response, sara_modem::COMMAND_SILENT) == sara_modem::COMMAND_OK && !strcmp(response, "+CSQ: 99,99")) {
+ delay(1000);
+ // usbSerial.print(".");
+ }
+
+ // Wait for attach, 1 = attached
+ while (modem.send("AT+CGATT?", response, sara_modem::COMMAND_SILENT) == sara_modem::COMMAND_OK && strcmp(response, "+CGATT: 1")) {
+ delay(1000);
+ // usbSerial.print(".");
+ }
+ // usbSerial.println();
+
+ // usbSerial.println(prefixInfo "connected!");
+
+ // -*- server connection -*-
+
+
+ //AT+UHTTP=0,0,"86.92.67.21"
+ //AT+UHTTP=0,5,80
+ //AT+UHTTPC=0,5,"/api/search_connect","","TEST!",1
+
+ modem.send("AT+UHTTP=0,0,\"86.92.67.21\"");
+ modem.send("AT+UHTTP=0,5,80");
+ modem.send("AT+UHTTPC=0,5,\"/api/search_connect\",\"\",\"TEST!\",1");*/
+
+
+ // usbSerial.println(prefixInfo "initiation completed, starting remote:");
+}
+
+
+void loop() {
+ /* // -*- remote for custom commands -*-
+ while (usbSerial.available())
+ modemSerial.write(usbSerial.read());
+
+ while (modemSerial.available())
+ usbSerial.write(modemSerial.read());
+
+ char buffer[512];
+ gps.read(buffer);
+
+ if (buffer[0] != '\0') {
+ // usbSerial.print("gps | ");
+ // usbSerial.println(buffer);
+ }*/
+
+ static int last = 0;
+ int now = millis();
+
+ static double lat = 0, lon = 0, accuracy = 0;
+
+ if (now - last > statusDelay * 1000) {
+ if (sodaq_gps.scan(true, 10000)) {
+ lat = sodaq_gps.getLat();
+ lon = sodaq_gps.getLon();
+ accuracy = 1.0 / sodaq_gps.getHDOP() * 100;
+ // -> 100% the best, 0% the worst
+ // usbSerial.print(sodaq_gps.getLat(), 13);
+ // usbSerial.print(" - ");
+ // usbSerial.print(sodaq_gps.getLon(), 13);
+ // usbSerial.print(" ~ accuracy ");
+ // usbSerial.print(1.0 / sodaq_gps.getHDOP() * 100, 1);
+ // usbSerial.println("%");
+ }
+
+ serial_remote::http_packet req, res;
+ req.method = "POST";
+ req.endpoint = "/api/update";
+ req.body["charging"] = (bool) digitalRead(CHARGER_STATUS);
+ req.body["latitude"] = lat;
+ req.body["longitude"] = lon;
+ req.body["accuracy"] = accuracy;
+ req.body["battery"] = batteryVoltage();
+ req.body["temperature"] = temperature();
+
+ remote.send(req);
+ last = now;
+ }
+
+ // usbSerial.print(batteryVoltage());
+ // usbSerial.println("V battery");
+
+ // usbSerial.print(temperature());
+ // usbSerial.println(" deg celsius");
+}
+
+int temperature() {
+ return accel.getTemperature();
+}
+
+int batteryVoltage() {
+ return batteryFactor * (float) analogRead(BATVOLT_PIN);
+}
diff --git a/5g-client/include/remote.h b/dump/remote.h
diff --git a/5g-client/remote.ino b/dump/remote.ino
diff --git a/remote.md b/dump/remote.md
diff --git a/led-codes.txt b/led-codes.txt
@@ -0,0 +1,7 @@
+NONE = off
+CYAN = starting up
+
+BLUE = idle modem
+MAGENTA = idle remote
+YELLOW = idle modem with warnings
+RED = no interface
+\ No newline at end of file
diff --git a/old_client.ino b/old_client.ino
@@ -1,175 +0,0 @@
-#include "include/config.h"
-#include "include/http.h"
-#include "include/modem.h"
-#include "include/remote.h"
-
-#include <Sodaq_LSM303AGR.h>
-#include <Sodaq_UBlox_GPS.h>
-#include <Wire.h>
-
-#define ADC_AREF 3.3f
-#define BATVOLT_R1 4.7f
-#define BATVOLT_R2 10.0f
-#define BATVOLT_PIN BAT_VOLT
-
-#define statusDelay 0.5 // seconds
-
-#define batteryFactor (0.978 * (BATVOLT_R1 / BATVOLT_R2 + 1) / ADC_AREF)
-
-http_client http;
-
-sara_modem modem;
-Sodaq_LSM303AGR accel;
-serial_remote remote;
-
-void setup() {
- // -*- hardware initiation -*-
-
- usbSerial.begin(remoteBaud);
- while (usbWait && !usbSerial)
- ;
-
- pinMode(BATVOLT_PIN, INPUT);
- pinMode(CHARGER_STATUS, INPUT);
-
- // modem.init();
- remote.begin();
-
- Wire.begin();
- delay(1000);
- sodaq_gps.init(GPS_ENABLE);
-
- accel.rebootAccelerometer();
- delay(1000);
-
- // Enable the Accelerometer
- accel.enableAccelerometer();
-
- remote.connect("127.0.0.1", 5000);
-
- // modem.send("ATE0"); // disable command-echo
-
- // if (modem.send("AT+CPIN=\"" SIM_PIN "\"") == sara_modem::COMMAND_ERROR) {
- // // usbSerial.println("[EROR] sim can't be unlocked, wrong PIN");
- // return;
- // }
- // usbSerial.println(prefixInfo "sim successful unlocked");
- /*
-
- modem.send("AT+CPSMS=0"); // Disable Power Saving Mode
- modem.send("AT+CEDRXS=0"); // Disable eDRX
- // usbSerial.println(prefixInfo "disabled power safe");
-
-
- // -*- internet initialization -*-
- char info[100];
-
- modem.send("AT+CFUN=15", sara_modem::COMMAND_BLOCK); // Reset the module
- modem.send("AT+UMNOPROF=1", sara_modem::COMMAND_BLOCK); // Set MNO profile (1=automatic,100=standard europe)
- modem.send("AT+URAT?", info);
- // usbSerial.print(prefixInfo "urat: ");
- // usbSerial.println(info);
- modem.send("AT+URAT=8", sara_modem::COMMAND_IGNORE); // Set URAT to LTE-M/NB-IOT
- modem.send("AT+CEREG=3", sara_modem::COMMAND_IGNORE); // Enable URCs
- modem.send("AT+CGDCONT=1,\"IP\",\"" simAPN "\"", sara_modem::COMMAND_BLOCK); // Set the APN
- modem.send("AT+CFUN=1"); // enable radio
- modem.send("AT+COPS=0,2", sara_modem::COMMAND_BLOCK); // Autoselect the operator
-
- // usbSerial.print(prefixInfo "waiting for connection");
-
- char response[100];
-
- // Check Siganl strenght, repeat till you have a valid CSQ (99,99 means no signal)
- while (modem.send("AT+CSQ", response, sara_modem::COMMAND_SILENT) == sara_modem::COMMAND_OK && !strcmp(response, "+CSQ: 99,99")) {
- delay(1000);
- // usbSerial.print(".");
- }
-
- // Wait for attach, 1 = attached
- while (modem.send("AT+CGATT?", response, sara_modem::COMMAND_SILENT) == sara_modem::COMMAND_OK && strcmp(response, "+CGATT: 1")) {
- delay(1000);
- // usbSerial.print(".");
- }
- // usbSerial.println();
-
- // usbSerial.println(prefixInfo "connected!");
-
- // -*- server connection -*-
-
-
- //AT+UHTTP=0,0,"86.92.67.21"
- //AT+UHTTP=0,5,80
- //AT+UHTTPC=0,5,"/api/search_connect","","TEST!",1
-
- modem.send("AT+UHTTP=0,0,\"86.92.67.21\"");
- modem.send("AT+UHTTP=0,5,80");
- modem.send("AT+UHTTPC=0,5,\"/api/search_connect\",\"\",\"TEST!\",1");*/
-
-
- // usbSerial.println(prefixInfo "initiation completed, starting remote:");
-}
-
-
-void loop() {
- /* // -*- remote for custom commands -*-
- while (usbSerial.available())
- modemSerial.write(usbSerial.read());
-
- while (modemSerial.available())
- usbSerial.write(modemSerial.read());
-
- char buffer[512];
- gps.read(buffer);
-
- if (buffer[0] != '\0') {
- // usbSerial.print("gps | ");
- // usbSerial.println(buffer);
- }*/
-
- static int last = 0;
- int now = millis();
-
- static double lat = 0, lon = 0, accuracy = 0;
-
- if (now - last > statusDelay * 1000) {
- if (sodaq_gps.scan(true, 10000)) {
- lat = sodaq_gps.getLat();
- lon = sodaq_gps.getLon();
- accuracy = 1.0 / sodaq_gps.getHDOP() * 100;
- // -> 100% the best, 0% the worst
- // usbSerial.print(sodaq_gps.getLat(), 13);
- // usbSerial.print(" - ");
- // usbSerial.print(sodaq_gps.getLon(), 13);
- // usbSerial.print(" ~ accuracy ");
- // usbSerial.print(1.0 / sodaq_gps.getHDOP() * 100, 1);
- // usbSerial.println("%");
- }
-
- serial_remote::http_packet req, res;
- req.method = "POST";
- req.endpoint = "/api/update";
- req.body["charging"] = (bool) digitalRead(CHARGER_STATUS);
- req.body["latitude"] = lat;
- req.body["longitude"] = lon;
- req.body["accuracy"] = accuracy;
- req.body["battery"] = batteryVoltage();
- req.body["temperature"] = temperature();
-
- remote.send(req);
- last = now;
- }
-
- // usbSerial.print(batteryVoltage());
- // usbSerial.println("V battery");
-
- // usbSerial.print(temperature());
- // usbSerial.println(" deg celsius");
-}
-
-int temperature() {
- return accel.getTemperature();
-}
-
-int batteryVoltage() {
- return batteryFactor * (float) analogRead(BATVOLT_PIN);
-}
diff --git a/remote.py b/remote.py
@@ -1,6 +1,7 @@
from http.client import HTTPConnection
import serial
+import random
import sys
import json
@@ -9,19 +10,28 @@ if len(sys.argv) < 2:
server_address = 'localhost', 5000
serial_port = serial.Serial(port=sys.argv[1], baudrate=115200)
+debug_chars = '0123456789abcdefghijklmnopqrstuvwxyz'
client = HTTPConnection(server_address[0], server_address[1])
+debug_token = ''.join(random.choice(debug_chars) for _ in range(16))
+
while serial_port.is_open:
try:
- method, endpoint, body = serial_port.readline().decode().split(' ', 2)
- print(f'-> {method} {endpoint} {body}')
+ command, params_raw = serial_port.readline().decode().split(' ', 1)
+ params = json.loads(params_raw)
+
+ if command == 'hello':
+ serial_port.write(f'ok {json.dumps(dict(debugToken=debug_token))}\n'.encode())
+ elif command == 'send':
+ method, endpoint, body = params["method"], params["endpoint"], params["body"]
+ print(f'-> {method} {endpoint} {body}')
- client.request(method, endpoint, body)
- res = client.getresponse()
- response = res.read().decode()
- print(f'<- {res.status} {response}')
+ client.request(method, endpoint, json.dumps(body))
+ res = client.getresponse()
+ response = res.read().decode()
+ print(f'<- {res.status} {response}')
- serial_port.write(f'{res.status} {response}'.encode())
+ serial_port.write(f'ok {json.dumps(dict(code=res.status, body=response))}\n'.encode())
except:
serial_port.write(b'0 {}\n')
diff --git a/remote.txt b/remote.txt
@@ -0,0 +1,7 @@
+request: <command:string> <parameters:json>
+response: <status:string> [parameters:json]
+
+status:
+- ok
+- not-ready
+- not-connected
diff --git a/test-server.py b/test-server.py
@@ -1,27 +1,19 @@
-from typing import cast
-from flask import Flask, request, jsonify
+from flask import json
+from werkzeug.exceptions import HTTPException
+from flask import Flask, request
app = Flask(__name__)
-latitude = 0
-longitude = 0
-accuracy = 0
-battery = 0
-temperature = 0
-
+status = {}
@app.post("/api/update")
def update():
- global latitude, longitude, accuracy, battery, temperature
+ global status
req = request.get_json(True)
if not req:
return
- latitude = req['latitude']
- longitude = req['longitude']
- accuracy = req['accuracy']
- battery = req['battery']
- temperature = req['temperature']
+ status = req
return {}
@app.get("/")
@@ -35,7 +27,7 @@ def index():
crossorigin=""></script>
<h1>Status update</h1>
- <p>latitude: <code>{latitude:.10f}</code></p>
+ <p>latitude: <code>{status['']:.10f}</code></p>
<p>longitude: <code>{longitude:.10f}</code></p>
<p>accuracy: <code>{accuracy:.2f}%</code></p>
<p>battery: <code>{battery}V</code></p>
@@ -53,4 +45,15 @@ def index():
</script>
'''
[email protected](HTTPException)
+def handle_exception(e):
+ response = e.get_response()
+ response.data = json.dumps({
+ "code": e.code,
+ "name": e.name,
+ "description": e.description,
+ })
+ response.content_type = "application/json"
+ return response
+
app.run('0.0.0.0', 5000)
diff --git a/test.txt b/test.txt
@@ -1 +0,0 @@
-hallo!
-\ No newline at end of file