From e442e94e3d947868974c622d6008cde5a54064fc Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Mon, 5 May 2025 00:15:35 +1000 Subject: [PATCH] * SensorManager: now can influence advert lat/lon, new custom name:value pairs for custom settings (eg, gps on/off) * companion: new CMD_GET_CUSTOM_VARS, CMD_SET_CUSTOM_VAR * T1000e: now supports "gps" custom setting (value "0" or "1") --- examples/companion_radio/NodePrefs.h | 1 - examples/companion_radio/main.cpp | 47 ++++++++++++++++++++++------ src/helpers/SensorManager.h | 7 +++++ variants/t1000-e/target.cpp | 37 ++++++++++++++++------ variants/t1000-e/target.h | 16 ++++++---- 5 files changed, 82 insertions(+), 26 deletions(-) diff --git a/examples/companion_radio/NodePrefs.h b/examples/companion_radio/NodePrefs.h index 691eec42..37a170b5 100644 --- a/examples/companion_radio/NodePrefs.h +++ b/examples/companion_radio/NodePrefs.h @@ -6,7 +6,6 @@ struct NodePrefs { // persisted to file float airtime_factor; char node_name[32]; - double node_lat, node_lon; float freq; uint8_t sf; uint8_t cr; diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 1ca5c650..7ab94619 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -140,6 +140,8 @@ static uint32_t _atoi(const char* sp) { #define CMD_SET_DEVICE_PIN 37 #define CMD_SET_OTHER_PARAMS 38 #define CMD_SEND_TELEMETRY_REQ 39 +#define CMD_GET_CUSTOM_VARS 40 +#define CMD_SET_CUSTOM_VAR 41 #define RESP_CODE_OK 0 #define RESP_CODE_ERR 1 @@ -162,6 +164,7 @@ static uint32_t _atoi(const char* sp) { #define RESP_CODE_CHANNEL_INFO 18 // a reply to CMD_GET_CHANNEL #define RESP_CODE_SIGN_START 19 #define RESP_CODE_SIGNATURE 20 +#define RESP_CODE_CUSTOM_VARS 21 // these are _pushed_ to client app at any time #define PUSH_CODE_ADVERT 0x80 @@ -801,8 +804,8 @@ public: file.read((uint8_t *) &_prefs.airtime_factor, sizeof(float)); // 0 file.read((uint8_t *) _prefs.node_name, sizeof(_prefs.node_name)); // 4 file.read(pad, 4); // 36 - file.read((uint8_t *) &_prefs.node_lat, sizeof(_prefs.node_lat)); // 40 - file.read((uint8_t *) &_prefs.node_lon, sizeof(_prefs.node_lon)); // 48 + file.read((uint8_t *) &sensors.node_lat, sizeof(sensors.node_lat)); // 40 + file.read((uint8_t *) &sensors.node_lon, sizeof(sensors.node_lon)); // 48 file.read((uint8_t *) &_prefs.freq, sizeof(_prefs.freq)); // 56 file.read((uint8_t *) &_prefs.sf, sizeof(_prefs.sf)); // 60 file.read((uint8_t *) &_prefs.cr, sizeof(_prefs.cr)); // 61 @@ -910,8 +913,8 @@ public: file.write((uint8_t *) &_prefs.airtime_factor, sizeof(float)); // 0 file.write((uint8_t *) _prefs.node_name, sizeof(_prefs.node_name)); // 4 file.write(pad, 4); // 36 - file.write((uint8_t *) &_prefs.node_lat, sizeof(_prefs.node_lat)); // 40 - file.write((uint8_t *) &_prefs.node_lon, sizeof(_prefs.node_lon)); // 48 + file.write((uint8_t *) &sensors.node_lat, sizeof(sensors.node_lat)); // 40 + file.write((uint8_t *) &sensors.node_lon, sizeof(sensors.node_lon)); // 48 file.write((uint8_t *) &_prefs.freq, sizeof(_prefs.freq)); // 56 file.write((uint8_t *) &_prefs.sf, sizeof(_prefs.sf)); // 60 file.write((uint8_t *) &_prefs.cr, sizeof(_prefs.cr)); // 61 @@ -958,8 +961,8 @@ public: memcpy(&out_frame[i], self_id.pub_key, PUB_KEY_SIZE); i += PUB_KEY_SIZE; int32_t lat, lon; - lat = (_prefs.node_lat * 1000000.0); - lon = (_prefs.node_lon * 1000000.0); + lat = (sensors.node_lat * 1000000.0); + lon = (sensors.node_lon * 1000000.0); memcpy(&out_frame[i], &lat, 4); i += 4; memcpy(&out_frame[i], &lon, 4); i += 4; out_frame[i++] = 0; // reserved @@ -1072,8 +1075,8 @@ public: memcpy(&alt, &cmd_frame[9], 4); // for FUTURE support } if (lat <= 90*1E6 && lat >= -90*1E6 && lon <= 180*1E6 && lon >= -180*1E6) { - _prefs.node_lat = ((double)lat) / 1000000.0; - _prefs.node_lon = ((double)lon) / 1000000.0; + sensors.node_lat = ((double)lat) / 1000000.0; + sensors.node_lon = ((double)lon) / 1000000.0; savePrefs(); writeOKFrame(); } else { @@ -1096,7 +1099,7 @@ public: writeErrFrame(ERR_CODE_ILLEGAL_ARG); } } else if (cmd_frame[0] == CMD_SEND_SELF_ADVERT) { - auto pkt = createSelfAdvert(_prefs.node_name, _prefs.node_lat, _prefs.node_lon); + auto pkt = createSelfAdvert(_prefs.node_name, sensors.node_lat, sensors.node_lon); if (pkt) { if (len >= 2 && cmd_frame[1] == 1) { // optional param (1 = flood, 0 = zero hop) sendFlood(pkt); @@ -1170,7 +1173,7 @@ public: } else if (cmd_frame[0] == CMD_EXPORT_CONTACT) { if (len < 1 + PUB_KEY_SIZE) { // export SELF - auto pkt = createSelfAdvert(_prefs.node_name, _prefs.node_lat, _prefs.node_lon); + auto pkt = createSelfAdvert(_prefs.node_name, sensors.node_lat, sensors.node_lon); if (pkt) { pkt->header |= ROUTE_TYPE_FLOOD; // would normally be sent in this mode @@ -1456,6 +1459,30 @@ public: memcpy(&_prefs.ble_pin, &cmd_frame[1], 4); savePrefs(); writeOKFrame(); + } else if (cmd_frame[0] == CMD_GET_CUSTOM_VARS) { + out_frame[0] = RESP_CODE_CUSTOM_VARS; + char* dp = (char *) &out_frame[1]; + for (int i = 0; i < sensors.getNumSettings() && dp - (char *) &out_frame[1] < 140; i++) { + if (i > 0) { *dp++ = ','; } + strcpy(dp, sensors.getSettingName(i)); dp = strchr(dp, 0); + *dp++ = ':'; + strcpy(dp, sensors.getSettingValue(i)); dp = strchr(dp, 0); + } + _serial->writeFrame(out_frame, dp - (char *)out_frame); + } else if (cmd_frame[0] == CMD_SET_CUSTOM_VAR && len >= 4) { + char* sp = (char *) &cmd_frame[1]; + char* np = strchr(sp, ':'); // look for separator char + if (np) { + *np++ = 0; // modify 'cmd_frame', replace ':' with null + bool success = sensors.setSettingValue(sp, np); + if (success) { + writeOKFrame(); + } else { + writeErrFrame(ERR_CODE_ILLEGAL_ARG); + } + } else { + writeErrFrame(ERR_CODE_ILLEGAL_ARG); + } } else { writeErrFrame(ERR_CODE_UNSUPPORTED_CMD); MESH_DEBUG_PRINTLN("ERROR: unknown command: %02X", cmd_frame[0]); diff --git a/src/helpers/SensorManager.h b/src/helpers/SensorManager.h index 84d6c7b0..eb58fa78 100644 --- a/src/helpers/SensorManager.h +++ b/src/helpers/SensorManager.h @@ -8,7 +8,14 @@ class SensorManager { public: + double node_lat, node_lon; // modify these, if you want to affect Advert location + + SensorManager() { node_lat = 0; node_lon = 0; } virtual bool begin() { return false; } virtual bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) { return false; } virtual void loop() { } + virtual int getNumSettings() const { return 0; } + virtual const char* getSettingName(int i) const { return NULL; } + virtual const char* getSettingValue(int i) const { return NULL; } + virtual bool setSettingValue(const char* name, const char* value) { return false; } }; diff --git a/variants/t1000-e/target.cpp b/variants/t1000-e/target.cpp index 770227f1..6a058545 100644 --- a/variants/t1000-e/target.cpp +++ b/variants/t1000-e/target.cpp @@ -137,7 +137,7 @@ void T1000SensorManager::stop_gps() { bool T1000SensorManager::begin() { - // TODO: init GPS + // init GPS Serial1.begin(115200); // make sure gps pin are off @@ -148,31 +148,50 @@ bool T1000SensorManager::begin() { pinMode(GPS_RESETB, OUTPUT); digitalWrite(GPS_RESETB, LOW); - start_gps(); - - return true; } bool T1000SensorManager::querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) { if (requester_permissions & TELEM_PERM_LOCATION) { // does requester have permission? - telemetry.addGPS(TELEM_CHANNEL_SELF, _lat, _lon, _alt); + telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, 0.0f); } return true; } void T1000SensorManager::loop() { - // TODO: poll GPS serial, set _lat, _lon, _alt static long next_gps_update = 0; _nmea->loop(); if (millis() > next_gps_update) { if (_nmea->isValid()) { - _lat = ((double)_nmea->getLatitude())/1000000.; - _lon = ((double)_nmea->getLongitude())/1000000.; + node_lat = ((double)_nmea->getLatitude())/1000000.; + node_lon = ((double)_nmea->getLongitude())/1000000.; //Serial.printf("lat %f lon %f\r\n", _lat, _lon); } - next_gps_update = millis() + 5000; + next_gps_update = millis() + 1000; } } + +int T1000SensorManager::getNumSettings() const { return 1; } // just one supported: "gps" (power switch) + +const char* T1000SensorManager::getSettingName(int i) const { + return i == 0 ? "gps" : NULL; +} +const char* T1000SensorManager::getSettingValue(int i) const { + if (i == 0) { + return gps_active ? "1" : "0"; + } + return NULL; +} +bool T1000SensorManager::setSettingValue(const char* name, const char* value) { + if (strcmp(name, "gps") == 0) { + if (strcmp(value, "0") == 0) { + stop_gps(); // or should this be sleep_gps() ?? + } else { + start_gps(); + } + return true; + } + return false; // not supported +} diff --git a/variants/t1000-e/target.h b/variants/t1000-e/target.h index a8cbcb84..4fc4c94e 100644 --- a/variants/t1000-e/target.h +++ b/variants/t1000-e/target.h @@ -11,17 +11,21 @@ #include class T1000SensorManager: public SensorManager { - float _lat, _lon, _alt; bool gps_active = false; LocationProvider * _nmea; -public: - T1000SensorManager(LocationProvider &nmea): _nmea(&nmea), _lat(0), _lon(0), _alt(0) { } - bool begin() override; - bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override; - void loop() override; + void start_gps(); void sleep_gps(); void stop_gps(); +public: + T1000SensorManager(LocationProvider &nmea): _nmea(&nmea) { } + bool begin() override; + bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override; + void loop() override; + int getNumSettings() const override; + const char* getSettingName(int i) const override; + const char* getSettingValue(int i) const override; + bool setSettingValue(const char* name, const char* value) override; }; extern T1000eBoard board;