diff --git a/examples/simple_repeater/MyMesh.cpp b/examples/simple_repeater/MyMesh.cpp index b2b47ac3..de8072f1 100644 --- a/examples/simple_repeater/MyMesh.cpp +++ b/examples/simple_repeater/MyMesh.cpp @@ -289,8 +289,16 @@ mesh::Packet *MyMesh::createSelfAdvert() { uint8_t app_data[MAX_ADVERT_DATA_SIZE]; uint8_t app_data_len; { - AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name, _prefs.node_lat, _prefs.node_lon); - app_data_len = builder.encodeTo(app_data); + if (_prefs.advert_loc_policy == ADVERT_LOC_NONE) { + AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name); + app_data_len = builder.encodeTo(app_data); + } else if (_prefs.advert_loc_policy == ADVERT_LOC_SHARE) { + AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name, sensors.node_lat, sensors.node_lon); + app_data_len = builder.encodeTo(app_data); + } else { + AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name, _prefs.node_lat, _prefs.node_lon); + app_data_len = builder.encodeTo(app_data); + } } return createAdvert(self_id, app_data, app_data_len); @@ -631,7 +639,12 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc _prefs.bridge_pkt_src = 0; // logTx _prefs.bridge_baud = 115200; // baud rate _prefs.bridge_channel = 1; // channel 1 + StrHelper::strncpy(_prefs.bridge_secret, "LVSITANOS", sizeof(_prefs.bridge_secret)); + + // GPS defaults + _prefs.gps_enabled = 0; + _prefs.gps_interval = 0; } void MyMesh::begin(FILESYSTEM *fs) { @@ -653,6 +666,10 @@ void MyMesh::begin(FILESYSTEM *fs) { updateAdvertTimer(); updateFloodAdvertTimer(); + +#if ENV_INCLUDE_GPS == 1 + applyGpsPrefs(); +#endif } void MyMesh::applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) { diff --git a/examples/simple_repeater/MyMesh.h b/examples/simple_repeater/MyMesh.h index d77b74d8..c45c141d 100644 --- a/examples/simple_repeater/MyMesh.h +++ b/examples/simple_repeater/MyMesh.h @@ -135,6 +135,12 @@ protected: return _prefs.multi_acks; } +#if ENV_INCLUDE_GPS == 1 + void applyGpsPrefs() { + sensors.setSettingByKey("gps", _prefs.gps_enabled?"1":"0"); + } +#endif + void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override; int searchPeersByHash(const uint8_t* hash) override; void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override; diff --git a/examples/simple_room_server/MyMesh.cpp b/examples/simple_room_server/MyMesh.cpp index 89f2afb3..00736820 100644 --- a/examples/simple_room_server/MyMesh.cpp +++ b/examples/simple_room_server/MyMesh.cpp @@ -116,8 +116,16 @@ mesh::Packet *MyMesh::createSelfAdvert() { uint8_t app_data[MAX_ADVERT_DATA_SIZE]; uint8_t app_data_len; { - AdvertDataBuilder builder(ADV_TYPE_ROOM, _prefs.node_name, _prefs.node_lat, _prefs.node_lon); - app_data_len = builder.encodeTo(app_data); + if (_prefs.advert_loc_policy == ADVERT_LOC_NONE) { + AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name); + app_data_len = builder.encodeTo(app_data); + } else if (_prefs.advert_loc_policy == ADVERT_LOC_SHARE) { + AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name, sensors.node_lat, sensors.node_lon); + app_data_len = builder.encodeTo(app_data); + } else { + AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name, _prefs.node_lat, _prefs.node_lon); + app_data_len = builder.encodeTo(app_data); + } } return createAdvert(self_id, app_data, app_data_len); @@ -632,6 +640,10 @@ void MyMesh::begin(FILESYSTEM *fs) { updateAdvertTimer(); updateFloodAdvertTimer(); + +#if ENV_INCLUDE_GPS == 1 + applyGpsPrefs(); +#endif } void MyMesh::applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) { diff --git a/examples/simple_room_server/MyMesh.h b/examples/simple_room_server/MyMesh.h index b2df60c3..60ef1e73 100644 --- a/examples/simple_room_server/MyMesh.h +++ b/examples/simple_room_server/MyMesh.h @@ -149,6 +149,12 @@ protected: bool onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override; void onAckRecv(mesh::Packet* packet, uint32_t ack_crc) override; +#if ENV_INCLUDE_GPS == 1 + void applyGpsPrefs() { + sensors.setSettingByKey("gps", _prefs.gps_enabled?"1":"0"); + } +#endif + public: MyMesh(mesh::MainBoard& board, mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::MeshTables& tables); diff --git a/examples/simple_sensor/SensorMesh.cpp b/examples/simple_sensor/SensorMesh.cpp index ba41ca45..97d95d5f 100644 --- a/examples/simple_sensor/SensorMesh.cpp +++ b/examples/simple_sensor/SensorMesh.cpp @@ -241,8 +241,16 @@ mesh::Packet* SensorMesh::createSelfAdvert() { uint8_t app_data[MAX_ADVERT_DATA_SIZE]; uint8_t app_data_len; { - AdvertDataBuilder builder(ADV_TYPE_SENSOR, _prefs.node_name, _prefs.node_lat, _prefs.node_lon); - app_data_len = builder.encodeTo(app_data); + if (_prefs.advert_loc_policy == ADVERT_LOC_NONE) { + AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name); + app_data_len = builder.encodeTo(app_data); + } else if (_prefs.advert_loc_policy == ADVERT_LOC_SHARE) { + AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name, sensors.node_lat, sensors.node_lon); + app_data_len = builder.encodeTo(app_data); + } else { + AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name, _prefs.node_lat, _prefs.node_lon); + app_data_len = builder.encodeTo(app_data); + } } return createAdvert(self_id, app_data, app_data_len); @@ -697,6 +705,10 @@ void SensorMesh::begin(FILESYSTEM* fs) { updateAdvertTimer(); updateFloodAdvertTimer(); + +#if ENV_INCLUDE_GPS == 1 + applyGpsPrefs(); +#endif } bool SensorMesh::formatFileSystem() { diff --git a/examples/simple_sensor/SensorMesh.h b/examples/simple_sensor/SensorMesh.h index d26bcb14..cdc3940c 100644 --- a/examples/simple_sensor/SensorMesh.h +++ b/examples/simple_sensor/SensorMesh.h @@ -149,4 +149,9 @@ private: void sendAlert(const ClientInfo* c, Trigger* t); + #if ENV_INCLUDE_GPS == 1 + void applyGpsPrefs() { + sensors.setSettingByKey("gps", _prefs.gps_enabled?"1":"0"); + } +#endif }; diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index ddf693c5..757180f8 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -62,8 +62,15 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) { file.read((uint8_t *)&_prefs->bridge_delay, sizeof(_prefs->bridge_delay)); // 128 file.read((uint8_t *)&_prefs->bridge_pkt_src, sizeof(_prefs->bridge_pkt_src)); // 130 file.read((uint8_t *)&_prefs->bridge_baud, sizeof(_prefs->bridge_baud)); // 131 - file.read((uint8_t *)&_prefs->bridge_channel, sizeof(_prefs->bridge_channel)); // 132 - file.read((uint8_t *)&_prefs->bridge_secret, sizeof(_prefs->bridge_secret)); // 133 + file.read((uint8_t *)&_prefs->bridge_channel, sizeof(_prefs->bridge_channel)); // 135 + file.read((uint8_t *)&_prefs->bridge_secret, sizeof(_prefs->bridge_secret)); // 136 + file.read(pad, 4); // 152 + file.read((uint8_t *)&_prefs->gps_enabled, sizeof(_prefs->gps_enabled)); // 156 + file.read((uint8_t *)&_prefs->gps_interval, sizeof(_prefs->gps_interval)); // 157 + if (file.read((uint8_t *)&_prefs->advert_loc_policy, sizeof (_prefs->advert_loc_policy)) == -1) { + _prefs->advert_loc_policy = ADVERT_LOC_PREFS; // default value + } // 161 + // 162 // sanitise bad pref values _prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f); @@ -84,6 +91,9 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) { _prefs->bridge_baud = constrain(_prefs->bridge_baud, 9600, 115200); _prefs->bridge_channel = constrain(_prefs->bridge_channel, 0, 14); + _prefs->gps_enabled = constrain(_prefs->gps_enabled, 0, 1); + _prefs->advert_loc_policy = constrain(_prefs->advert_loc_policy, 0, 2); + file.close(); } } @@ -131,8 +141,13 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) { file.write((uint8_t *)&_prefs->bridge_delay, sizeof(_prefs->bridge_delay)); // 128 file.write((uint8_t *)&_prefs->bridge_pkt_src, sizeof(_prefs->bridge_pkt_src)); // 130 file.write((uint8_t *)&_prefs->bridge_baud, sizeof(_prefs->bridge_baud)); // 131 - file.write((uint8_t *)&_prefs->bridge_channel, sizeof(_prefs->bridge_channel)); // 132 - file.write((uint8_t *)&_prefs->bridge_secret, sizeof(_prefs->bridge_secret)); // 133 + file.write((uint8_t *)&_prefs->bridge_channel, sizeof(_prefs->bridge_channel)); // 135 + file.write((uint8_t *)&_prefs->bridge_secret, sizeof(_prefs->bridge_secret)); // 136 + file.write(pad, 4); // 152 + file.write((uint8_t *)&_prefs->gps_enabled, sizeof(_prefs->gps_enabled)); // 156 + file.write((uint8_t *)&_prefs->gps_interval, sizeof(_prefs->gps_interval)); // 157 + file.write((uint8_t *)&_prefs->advert_loc_policy, sizeof(_prefs->advert_loc_policy)); // 161 + // 162 file.close(); } @@ -504,6 +519,126 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch sprintf(reply, "%s (Build: %s)", _callbacks->getFirmwareVer(), _callbacks->getBuildDate()); } else if (memcmp(command, "board", 5) == 0) { sprintf(reply, "%s", _board->getManufacturerName()); + } else if (memcmp(command, "sensor get ", 11) == 0) { + const char* key = command + 11; + const char* val = sensors.getSettingByKey(key); + if (val != NULL) { + sprintf(reply, "> %s", val); + } else { + strcpy(reply, "null"); + } + } else if (memcmp(command, "sensor set ", 11) == 0) { + strcpy(tmp, &command[11]); + const char *parts[2]; + int num = mesh::Utils::parseTextParts(tmp, parts, 2, ' '); + const char *key = (num > 0) ? parts[0] : ""; + const char *value = (num > 1) ? parts[1] : "null"; + if (sensors.setSettingByKey(key, value)) { + strcpy(reply, "ok"); + } else { + strcpy(reply, "can't find custom var"); + } + } else if (memcmp(command, "sensor list", 11) == 0) { + char* dp = reply; + int start = 0; + int end = sensors.getNumSettings(); + if (strlen(command) > 11) { + start = _atoi(command+12); + } + if (start >= end) { + strcpy(reply, "no custom var"); + } else { + sprintf(dp, "%d vars\n", end); + dp = strchr(dp, 0); + int i; + for (i = start; i < end && (dp-reply < 134); i++) { + sprintf(dp, "%s=%s\n", + sensors.getSettingName(i), + sensors.getSettingValue(i)); + dp = strchr(dp, 0); + } + if (i < end) { + sprintf(dp, "... next:%d", i); + } else { + *(dp-1) = 0; // remove last CR + } + } +#if ENV_INCLUDE_GPS == 1 + } else if (memcmp(command, "gps on", 6) == 0) { + if (sensors.setSettingByKey("gps", "1")) { + _prefs->gps_enabled = 1; + savePrefs(); + strcpy(reply, "ok"); + } else { + strcpy(reply, "gps toggle not found"); + } + } else if (memcmp(command, "gps off", 7) == 0) { + if (sensors.setSettingByKey("gps", "0")) { + _prefs->gps_enabled = 0; + savePrefs(); + strcpy(reply, "ok"); + } else { + strcpy(reply, "gps toggle not found"); + } + } else if (memcmp(command, "gps sync", 8) == 0) { + LocationProvider * l = sensors.getLocationProvider(); + if (l != NULL) { + l->syncTime(); + } + } else if (memcmp(command, "gps setloc", 10) == 0) { + _prefs->node_lat = sensors.node_lat; + _prefs->node_lon = sensors.node_lon; + savePrefs(); + strcpy(reply, "ok"); + } else if (memcmp(command, "gps advert", 10) == 0) { + if (strlen(command) == 10) { + switch (_prefs->advert_loc_policy) { + case ADVERT_LOC_NONE: + strcpy(reply, "> none"); + break; + case ADVERT_LOC_PREFS: + strcpy(reply, "> prefs"); + break; + case ADVERT_LOC_SHARE: + strcpy(reply, "> share"); + break; + default: + strcpy(reply, "error"); + } + } else if (memcmp(command+11, "none", 4) == 0) { + _prefs->advert_loc_policy = ADVERT_LOC_NONE; + savePrefs(); + strcpy(reply, "ok"); + } else if (memcmp(command+11, "share", 5) == 0) { + _prefs->advert_loc_policy = ADVERT_LOC_SHARE; + savePrefs(); + strcpy(reply, "ok"); + } else if (memcmp(command+11, "prefs", 4) == 0) { + _prefs->advert_loc_policy = ADVERT_LOC_PREFS; + savePrefs(); + strcpy(reply, "ok"); + } else { + strcpy(reply, "error"); + } + } else if (memcmp(command, "gps", 3) == 0) { + LocationProvider * l = sensors.getLocationProvider(); + if (l != NULL) { + bool enabled = l->isEnabled(); // is EN pin on ? + bool fix = l->isValid(); // has fix ? + int sats = l->satellitesCount(); + bool active = !strcmp(sensors.getSettingByKey("gps"), "1"); + if (enabled) { + sprintf(reply, "on, %s, %s, %d sats", + active?"active":"deactivated", + fix?"fix":"no fix", + sats); + } else { + strcpy(reply, "off"); + } + } else { + strcpy(reply, "Can't find GPS"); + } +#endif } else if (memcmp(command, "log start", 9) == 0) { _callbacks->setLoggingOn(true); strcpy(reply, " logging on"); diff --git a/src/helpers/CommonCLI.h b/src/helpers/CommonCLI.h index 227a9efb..68489913 100644 --- a/src/helpers/CommonCLI.h +++ b/src/helpers/CommonCLI.h @@ -2,11 +2,16 @@ #include "Mesh.h" #include +#include #if defined(WITH_RS232_BRIDGE) || defined(WITH_ESPNOW_BRIDGE) #define WITH_BRIDGE #endif +#define ADVERT_LOC_NONE 0 +#define ADVERT_LOC_SHARE 1 +#define ADVERT_LOC_PREFS 2 + struct NodePrefs { // persisted to file float airtime_factor; char node_name[32]; @@ -37,6 +42,10 @@ struct NodePrefs { // persisted to file uint32_t bridge_baud; // 9600, 19200, 38400, 57600, 115200 (default 115200) uint8_t bridge_channel; // 1-14 (ESP-NOW only) char bridge_secret[16]; // for XOR encryption of bridge packets (ESP-NOW only) + // Gps settings + uint8_t gps_enabled; + uint32_t gps_interval; // in seconds + uint8_t advert_loc_policy; }; class CommonCLICallbacks { diff --git a/src/helpers/SensorManager.h b/src/helpers/SensorManager.h index 1ace6220..38c1d806 100644 --- a/src/helpers/SensorManager.h +++ b/src/helpers/SensorManager.h @@ -23,4 +23,25 @@ public: virtual const char* getSettingValue(int i) const { return NULL; } virtual bool setSettingValue(const char* name, const char* value) { return false; } virtual LocationProvider* getLocationProvider() { return NULL; } + + // Helper functions to manage setting by keys (useful in many places ...) + const char* getSettingByKey(const char* key) { + int num = getNumSettings(); + for (int i = 0; i < num; i++) { + if (strcmp(getSettingName(i), key) == 0) { + return getSettingValue(i); + } + } + return NULL; + } + + bool setSettingByKey(const char* key, const char* value) { + int num = getNumSettings(); + for (int i = 0; i < num; i++) { + if (strcmp(getSettingName(i), key) == 0) { + return setSettingValue(key, value); + } + } + return false; + } }; diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index 99605ff3..aa51c85a 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -387,27 +387,34 @@ bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, Cayen int EnvironmentSensorManager::getNumSettings() const { + int settings = 0; #if ENV_INCLUDE_GPS - return gps_detected ? 1 : 0; // only show GPS setting if GPS is detected - #else - return 0; + if (gps_detected) settings++; // only show GPS setting if GPS is detected #endif + return settings; } const char* EnvironmentSensorManager::getSettingName(int i) const { + int settings = 0; #if ENV_INCLUDE_GPS - return (gps_detected && i == 0) ? "gps" : NULL; - #else - return NULL; + if (gps_detected && i == settings++) { + return "gps"; + } #endif + // convenient way to add params (needed for some tests) +// if (i == settings++) return "param.2"; + return NULL; } const char* EnvironmentSensorManager::getSettingValue(int i) const { + int settings = 0; #if ENV_INCLUDE_GPS - if (gps_detected && i == 0) { - return gps_active ? "1" : "0"; - } + if (gps_detected && i == settings++) { + return gps_active ? "1" : "0"; + } #endif + // convenient way to add params ... +// if (i == settings++) return "2"; return NULL; } diff --git a/src/helpers/sensors/LocationProvider.h b/src/helpers/sensors/LocationProvider.h index f93dec48..81d08652 100644 --- a/src/helpers/sensors/LocationProvider.h +++ b/src/helpers/sensors/LocationProvider.h @@ -21,4 +21,5 @@ public: virtual void begin() = 0; virtual void stop() = 0; virtual void loop() = 0; + virtual bool isEnabled() = 0; }; diff --git a/src/helpers/sensors/MicroNMEALocationProvider.h b/src/helpers/sensors/MicroNMEALocationProvider.h index ec82f25e..fb29fd79 100644 --- a/src/helpers/sensors/MicroNMEALocationProvider.h +++ b/src/helpers/sensors/MicroNMEALocationProvider.h @@ -78,6 +78,16 @@ public : } } + bool isEnabled() override { + // directly read the enable pin if present as gps can be + // activated/deactivated outside of here ... + if (_pin_en != -1) { + return digitalRead(_pin_en) == PIN_GPS_EN_ACTIVE; + } else { + return true; // no enable so must be active + } + } + void syncTime() override { nmea.clear(); LocationProvider::syncTime(); } long getLatitude() override { return nmea.getLatitude(); } long getLongitude() override { return nmea.getLongitude(); }