From 3c0429deee844421a6f7a783613520a9d76691c3 Mon Sep 17 00:00:00 2001 From: geeksville Date: Sat, 19 Sep 2020 11:19:42 -0700 Subject: [PATCH 1/6] Add new factory_reset preferences option clients can set --- proto | 2 +- src/mesh/MeshService.cpp | 6 ++++-- src/mesh/MeshService.h | 6 ++++-- src/mesh/NodeDB.cpp | 23 ++++++++++++++++++----- src/mesh/NodeDB.h | 9 +++++++-- src/mesh/PhoneAPI.cpp | 5 ++++- src/mesh/mesh.pb.c | 2 +- src/mesh/mesh.pb.h | 20 +++++++++++++------- 8 files changed, 52 insertions(+), 21 deletions(-) diff --git a/proto b/proto index ce422b7c4..4e431c841 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit ce422b7c448906c6fee3eef64bbd41adfbc990f0 +Subproject commit 4e431c841015edfdde925acf5ee4ac0a2272edff diff --git a/src/mesh/MeshService.cpp b/src/mesh/MeshService.cpp index 3356e0922..8baed24c1 100644 --- a/src/mesh/MeshService.cpp +++ b/src/mesh/MeshService.cpp @@ -197,12 +197,14 @@ void MeshService::loop() } /// The radioConfig object just changed, call this to force the hw to change to the new settings -void MeshService::reloadConfig() +bool MeshService::reloadConfig() { // If we can successfully set this radio to these settings, save them to disk - nodeDB.resetRadioConfig(); // Don't let the phone send us fatally bad settings + bool didReset = nodeDB.resetRadioConfig(); // Don't let the phone send us fatally bad settings configChanged.notifyObservers(NULL); nodeDB.saveToDisk(); + + return didReset; } /// The owner User record just got updated, update our node DB and broadcast the info into the mesh diff --git a/src/mesh/MeshService.h b/src/mesh/MeshService.h index a12f087b3..a30f3d4ec 100644 --- a/src/mesh/MeshService.h +++ b/src/mesh/MeshService.h @@ -63,8 +63,10 @@ class MeshService */ void handleToRadio(MeshPacket &p); - /// The radioConfig object just changed, call this to force the hw to change to the new settings - void reloadConfig(); + /** The radioConfig object just changed, call this to force the hw to change to the new settings + * @return true if client devices should be sent a new set of radio configs + */ + bool reloadConfig(); /// The owner User record just got updated, update our node DB and broadcast the info into the mesh void reloadOwner(); diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 634bd9515..0bed24004 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -102,14 +102,23 @@ const char *getChannelName() NodeDB::NodeDB() : nodes(devicestate.node_db), numNodes(&devicestate.node_db_count) {} -void NodeDB::resetRadioConfig() +bool NodeDB::resetRadioConfig() { + bool didFactoryReset = false; + /// 16 bytes of random PSK for our _public_ default channel that all devices power up on (AES128) static const uint8_t defaultpsk[] = {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59, 0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0xbf}; - if (radioConfig.preferences.sds_secs == 0) { - DEBUG_MSG("RadioConfig reset!\n"); + if (radioConfig.preferences.factory_reset) { + DEBUG_MSG("Performing factory reset!\n"); + installDefaultDeviceState(); + didFactoryReset = true; + } else if (radioConfig.preferences.sds_secs == 0) { + DEBUG_MSG("Fixing bogus RadioConfig!\n"); + + radioConfig.preferences.factory_reset = false; // never save this to disk + radioConfig.preferences.send_owner_interval = 4; // per sw-design.md radioConfig.preferences.position_broadcast_secs = 15 * 60; radioConfig.preferences.wait_bluetooth_secs = 120; @@ -123,8 +132,8 @@ void NodeDB::resetRadioConfig() radioConfig.has_preferences = true; // radioConfig.modem_config = RadioConfig_ModemConfig_Bw125Cr45Sf128; // medium range and fast - // channelSettings.modem_config = ChannelSettings_ModemConfig_Bw500Cr45Sf128; // short range and fast, but wide bandwidth - // so incompatible radios can talk together + // channelSettings.modem_config = ChannelSettings_ModemConfig_Bw500Cr45Sf128; // short range and fast, but wide + // bandwidth so incompatible radios can talk together channelSettings.modem_config = ChannelSettings_ModemConfig_Bw125Cr48Sf4096; // slow and long range channelSettings.tx_power = 0; // default @@ -147,12 +156,16 @@ void NodeDB::resetRadioConfig() radioConfig.preferences.position_broadcast_secs = 6 * 60; radioConfig.preferences.ls_secs = 60; } + + return didFactoryReset; } void NodeDB::installDefaultDeviceState() { memset(&devicestate, 0, sizeof(devicestate)); + *numNodes = 0; // Forget node DB + // init our devicestate with valid flags so protobuf writing/reading will work devicestate.has_my_node = true; devicestate.has_radio = true; diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index bd22f730f..e1a1b77d6 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -46,8 +46,13 @@ class NodeDB /// write to flash void saveToDisk(); - // Reinit radio config if needed, because sometimes a buggy android app might send us bogus settings - void resetRadioConfig(); + /** Reinit radio config if needed, because either: + * a) sometimes a buggy android app might send us bogus settings or + * b) the client set factory_reset + * + * @return true if the config was completely reset, in that case, we should send it back to the client + */ + bool resetRadioConfig(); /// given a subpacket sniffed from the network, update our DB state /// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index caadf8563..9ae5955d5 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -243,7 +243,10 @@ void PhoneAPI::handleSetRadio(const RadioConfig &r) { radioConfig = r; - service.reloadConfig(); + bool didReset = service.reloadConfig(); + if (didReset) { + state = STATE_SEND_MY_INFO; // Squirt a completely new set of configs to the client + } } /** diff --git a/src/mesh/mesh.pb.c b/src/mesh/mesh.pb.c index ddc720cf3..b2d1ceb23 100644 --- a/src/mesh/mesh.pb.c +++ b/src/mesh/mesh.pb.c @@ -27,7 +27,7 @@ PB_BIND(MeshPacket, MeshPacket, 2) PB_BIND(ChannelSettings, ChannelSettings, AUTO) -PB_BIND(RadioConfig, RadioConfig, AUTO) +PB_BIND(RadioConfig, RadioConfig, 2) PB_BIND(RadioConfig_UserPreferences, RadioConfig_UserPreferences, 2) diff --git a/src/mesh/mesh.pb.h b/src/mesh/mesh.pb.h index 64b2758c3..6fbc79f7c 100644 --- a/src/mesh/mesh.pb.h +++ b/src/mesh/mesh.pb.h @@ -108,6 +108,8 @@ typedef struct _RadioConfig_UserPreferences { char wifi_ssid[33]; char wifi_password[64]; bool wifi_ap_mode; + char region[6]; + bool factory_reset; pb_size_t ignore_incoming_count; uint32_t ignore_incoming[3]; } RadioConfig_UserPreferences; @@ -248,7 +250,7 @@ typedef struct _ToRadio { #define MeshPacket_init_default {0, 0, 0, {SubPacket_init_default}, 0, 0, 0, 0, 0} #define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0} #define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default, false, ChannelSettings_init_default} -#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, {0, 0, 0}} +#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, "", 0, 0, {0, 0, 0}} #define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0} #define MyNodeInfo_init_default {0, 0, 0, "", "", "", 0, 0, 0, 0, 0, 0, 0, 0} #define DeviceState_init_default {false, RadioConfig_init_default, false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0} @@ -264,7 +266,7 @@ typedef struct _ToRadio { #define MeshPacket_init_zero {0, 0, 0, {SubPacket_init_zero}, 0, 0, 0, 0, 0} #define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0} #define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero, false, ChannelSettings_init_zero} -#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, {0, 0, 0}} +#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, "", 0, 0, {0, 0, 0}} #define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0} #define MyNodeInfo_init_zero {0, 0, 0, "", "", "", 0, 0, 0, 0, 0, 0, 0, 0} #define DeviceState_init_zero {false, RadioConfig_init_zero, false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0} @@ -322,7 +324,9 @@ typedef struct _ToRadio { #define RadioConfig_UserPreferences_wifi_ssid_tag 12 #define RadioConfig_UserPreferences_wifi_password_tag 13 #define RadioConfig_UserPreferences_wifi_ap_mode_tag 14 -#define RadioConfig_UserPreferences_ignore_incoming_tag 102 +#define RadioConfig_UserPreferences_region_tag 15 +#define RadioConfig_UserPreferences_factory_reset_tag 100 +#define RadioConfig_UserPreferences_ignore_incoming_tag 103 #define RouteDiscovery_route_tag 2 #define User_id_tag 1 #define User_long_name_tag 2 @@ -477,7 +481,9 @@ X(a, STATIC, SINGULAR, UINT32, min_wake_secs, 11) \ X(a, STATIC, SINGULAR, STRING, wifi_ssid, 12) \ X(a, STATIC, SINGULAR, STRING, wifi_password, 13) \ X(a, STATIC, SINGULAR, BOOL, wifi_ap_mode, 14) \ -X(a, STATIC, REPEATED, UINT32, ignore_incoming, 102) +X(a, STATIC, SINGULAR, STRING, region, 15) \ +X(a, STATIC, SINGULAR, BOOL, factory_reset, 100) \ +X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103) #define RadioConfig_UserPreferences_CALLBACK NULL #define RadioConfig_UserPreferences_DEFAULT NULL @@ -613,11 +619,11 @@ extern const pb_msgdesc_t ManufacturingData_msg; #define SubPacket_size 274 #define MeshPacket_size 313 #define ChannelSettings_size 84 -#define RadioConfig_size 277 -#define RadioConfig_UserPreferences_size 188 +#define RadioConfig_size 287 +#define RadioConfig_UserPreferences_size 198 #define NodeInfo_size 132 #define MyNodeInfo_size 110 -#define DeviceState_size 5429 +#define DeviceState_size 5439 #define DebugString_size 258 #define FromRadio_size 322 #define ToRadio_size 316 From 3352fae64ce2ff67da9d83479dcd3de5285cd0cf Mon Sep 17 00:00:00 2001 From: geeksville Date: Mon, 21 Sep 2020 12:41:39 -0700 Subject: [PATCH 2/6] fix #371 allow button while using API. also don't let tbeams sleep if they have USB power --- docs/software/power.md | 10 ++++++++-- src/Power.cpp | 3 +++ src/PowerFSM.cpp | 29 +++++++++++++++++++++++++---- src/PowerFSM.h | 4 +++- src/SerialConsole.cpp | 2 ++ src/main.cpp | 2 +- 6 files changed, 42 insertions(+), 8 deletions(-) diff --git a/docs/software/power.md b/docs/software/power.md index cd0d2c913..e98e5bd0d 100644 --- a/docs/software/power.md +++ b/docs/software/power.md @@ -32,11 +32,15 @@ From lower to higher power consumption. onEntry: setBluetoothOn(true) onExit: -- full on (ON) - Everything is on +- serial API usage (SERIAL) - Screen is on, device doesn't sleep, bluetooth off + onEntry: setBluetooth off, screen on + onExit: + +- full on (ON) - Everything is on, can eventually timeout and lower to a lower power state onEntry: setBluetoothOn(true), screen.setOn(true) onExit: screen.setOn(false) -- serial API usage (SERIAL) - Screen is on, device doesn't sleep, bluetooth off +- has power (POWER) - Screen is on, device doesn't sleep, bluetooth on, will stay in this state as long as we have power onEntry: setBluetooth off, screen on onExit: @@ -56,9 +60,11 @@ From lower to higher power consumption. - While in NB/DARK/ON: If we receive EVENT_NODEDB_UPDATED we transition to ON (so the new screen can be shown) - While in DARK: While the phone talks to us over BLE (EVENT_CONTACT_FROM_PHONE) reset any sleep timers and stay in DARK (needed for bluetooth sw update and nice user experience if the user is reading/replying to texts) - while in LS/NB/DARK: if SERIAL_CONNECTED, go to serial +- while in any state: if we have AC power, go to POWER ### events that decrease cpu activity +- While in POWER: if lose AC go to ON - While in SERIAL: if SERIAL_DISCONNECTED, go to NB - While in ON: If PRESS event occurs, reset screen_on_secs timer and tell the screen to handle the pess - While in ON: If it has been more than screen_on_secs since a press, lower to DARK diff --git a/src/Power.cpp b/src/Power.cpp index 1145c51c4..7d032b666 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -119,6 +119,7 @@ void Power::readPowerStatus() const PowerStatus powerStatus = PowerStatus(hasBattery ? OptTrue : OptFalse, batteryLevel->isVBUSPlug() ? OptTrue : OptFalse, batteryLevel->isChargeing() ? OptTrue : OptFalse, batteryVoltageMv, batteryChargePercent); + DEBUG_MSG("Read power stat %d\n", powerStatus.getHasUSB()); newStatus.notifyObservers(&powerStatus); // If we have a battery at all and it is less than 10% full, force deep sleep @@ -237,9 +238,11 @@ void Power::loop() } if (axp.isVbusRemoveIRQ()) { DEBUG_MSG("USB unplugged\n"); + powerFSM.trigger(EVENT_POWER_DISCONNECTED); } if (axp.isVbusPlugInIRQ()) { DEBUG_MSG("USB plugged In\n"); + powerFSM.trigger(EVENT_POWER_CONNECTED); } if (axp.isBattPlugInIRQ()) { DEBUG_MSG("Battery inserted\n"); diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 128947bcd..f72e5842a 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -4,8 +4,8 @@ #include "MeshService.h" #include "NodeDB.h" #include "configuration.h" -#include "main.h" #include "graphics/Screen.h" +#include "main.h" #include "sleep.h" #include "target_specific.h" @@ -123,6 +123,12 @@ static void serialEnter() screen.setOn(true); } +static void powerEnter() +{ + screen.setOn(true); + setBluetoothEnable(true); +} + static void onEnter() { screen.setOn(true); @@ -155,16 +161,20 @@ State stateDARK(darkEnter, NULL, NULL, "DARK"); State stateSERIAL(serialEnter, NULL, NULL, "SERIAL"); State stateBOOT(bootEnter, NULL, NULL, "BOOT"); State stateON(onEnter, NULL, NULL, "ON"); +State statePOWER(powerEnter, NULL, NULL, "POWER"); Fsm powerFSM(&stateBOOT); void PowerFSM_setup() { - powerFSM.add_timed_transition(&stateBOOT, &stateON, 3 * 1000, NULL, "boot timeout"); + // If we already have AC power go to POWER state after init, otherwise go to ON + bool hasPower = powerStatus && powerStatus->getHasUSB(); + DEBUG_MSG("PowerFSM init, USB power=%d\n", hasPower); + powerFSM.add_timed_transition(&stateBOOT, hasPower ? &statePOWER : &stateON, 3 * 1000, NULL, "boot timeout"); powerFSM.add_transition(&stateLS, &stateDARK, EVENT_WAKE_TIMER, wakeForPing, "Wake timer"); - // Note we don't really use this transition, because when we wake from light sleep we _always_ transition to NB and then it - // handles things powerFSM.add_transition(&stateLS, &stateNB, EVENT_RECEIVED_PACKET, NULL, "Received packet"); + // Note we don't really use this transition, because when we wake from light sleep we _always_ transition to NB and then + // it handles things powerFSM.add_transition(&stateLS, &stateNB, EVENT_RECEIVED_PACKET, NULL, "Received packet"); powerFSM.add_transition(&stateNB, &stateNB, EVENT_RECEIVED_PACKET, NULL, "Received packet, resetting win wake"); @@ -172,7 +182,10 @@ void PowerFSM_setup() powerFSM.add_transition(&stateLS, &stateON, EVENT_PRESS, NULL, "Press"); powerFSM.add_transition(&stateNB, &stateON, EVENT_PRESS, NULL, "Press"); powerFSM.add_transition(&stateDARK, &stateON, EVENT_PRESS, NULL, "Press"); + powerFSM.add_transition(&statePOWER, &statePOWER, EVENT_PRESS, screenPress, "Press"); powerFSM.add_transition(&stateON, &stateON, EVENT_PRESS, screenPress, "Press"); // reenter On to restart our timers + powerFSM.add_transition(&stateSERIAL, &stateSERIAL, EVENT_PRESS, screenPress, + "Press"); // Allow button to work while in serial API // Handle critically low power battery by forcing deep sleep powerFSM.add_transition(&stateBOOT, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); @@ -199,6 +212,14 @@ void PowerFSM_setup() powerFSM.add_transition(&stateDARK, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "serial API"); powerFSM.add_transition(&stateON, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "serial API"); + powerFSM.add_transition(&stateLS, &statePOWER, EVENT_POWER_CONNECTED, NULL, "power connect"); + powerFSM.add_transition(&stateNB, &statePOWER, EVENT_POWER_CONNECTED, NULL, "power connect"); + powerFSM.add_transition(&stateDARK, &statePOWER, EVENT_POWER_CONNECTED, NULL, "power connect"); + powerFSM.add_transition(&stateON, &statePOWER, EVENT_POWER_CONNECTED, NULL, "power connect"); + + powerFSM.add_transition(&statePOWER, &stateON, EVENT_POWER_DISCONNECTED, NULL, "power disconnected"); + powerFSM.add_transition(&stateSERIAL, &stateON, EVENT_POWER_DISCONNECTED, NULL, "power disconnected"); + powerFSM.add_transition(&stateSERIAL, &stateNB, EVENT_SERIAL_DISCONNECTED, NULL, "serial disconnect"); powerFSM.add_transition(&stateDARK, &stateDARK, EVENT_CONTACT_FROM_PHONE, NULL, "Contact from phone"); diff --git a/src/PowerFSM.h b/src/PowerFSM.h index c89ad9148..4a219f570 100644 --- a/src/PowerFSM.h +++ b/src/PowerFSM.h @@ -13,9 +13,11 @@ #define EVENT_BLUETOOTH_PAIR 7 #define EVENT_NODEDB_UPDATED 8 // NodeDB has a big enough change that we think you should turn on the screen #define EVENT_CONTACT_FROM_PHONE 9 // the phone just talked to us over bluetooth -#define EVENT_LOW_BATTERY 10 // Battery is critically low, go to sleep +#define EVENT_LOW_BATTERY 10 // Battery is critically low, go to sleep #define EVENT_SERIAL_CONNECTED 11 #define EVENT_SERIAL_DISCONNECTED 12 +#define EVENT_POWER_CONNECTED 13 +#define EVENT_POWER_DISCONNECTED 14 extern Fsm powerFSM; diff --git a/src/SerialConsole.cpp b/src/SerialConsole.cpp index 683886ed5..f246b607c 100644 --- a/src/SerialConsole.cpp +++ b/src/SerialConsole.cpp @@ -40,6 +40,8 @@ void SerialConsole::onConnectionChanged(bool connected) if (connected) { // To prevent user confusion, turn off bluetooth while using the serial port api powerFSM.trigger(EVENT_SERIAL_CONNECTED); } else { + // FIXME, we get no notice of serial going away, we should instead automatically generate this event if we haven't + // received a packet in a while powerFSM.trigger(EVENT_SERIAL_DISCONNECTED); } } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 207ae7b12..dc188809d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -213,9 +213,9 @@ void setup() // Currently only the tbeam has a PMU power = new Power(); - power->setup(); power->setStatusHandler(powerStatus); powerStatus->observe(&power->newStatus); + power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration #ifdef NRF52_SERIES nrf52Setup(); From 1f36139e996a707e3c5ed084a3ac5551dfc77cea Mon Sep 17 00:00:00 2001 From: geeksville Date: Fri, 25 Sep 2020 09:14:44 -0700 Subject: [PATCH 3/6] remove Signal --- docs/_config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_config.yml b/docs/_config.yml index 9c1ecd436..1cb1a55ba 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,7 +1,7 @@ theme: jekyll-theme-cayman title: Meshtastic -description: An opensource hiking, pilot, skiing, Signal-App-extending GPS mesh communicator +description: An opensource hiking, pilot, skiing, secure GPS mesh communicator google_analytics: G-DRZ5H5EXHV include: [".well-known"] From 3e5f81bf2abb594ac6b9bb3a4ea0f517ca127c10 Mon Sep 17 00:00:00 2001 From: geeksville Date: Fri, 25 Sep 2020 12:52:08 -0700 Subject: [PATCH 4/6] move region into userpreferences, to end region specific firmwares --- .vscode/settings.json | 1 + proto | 2 +- src/mesh/MeshRadio.h | 93 ++++--------------------------------- src/mesh/NodeDB.cpp | 45 ++++++++++++++---- src/mesh/RadioInterface.cpp | 41 +++++++++++++--- src/mesh/mesh.pb.c | 3 +- src/mesh/mesh.pb.h | 30 +++++++++--- 7 files changed, 107 insertions(+), 108 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9b72a2a2f..8ea4339da 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -56,6 +56,7 @@ "HFSR", "Meshtastic", "NEMAGPS", + "RDEF", "Ublox", "bkpt", "cfsr", diff --git a/proto b/proto index 4e431c841..5cdd7bff5 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 4e431c841015edfdde925acf5ee4ac0a2272edff +Subproject commit 5cdd7bff56b0ea54351e5ea0e358e864b061078f diff --git a/src/mesh/MeshRadio.h b/src/mesh/MeshRadio.h index 070c7c9a7..2cee8f89a 100644 --- a/src/mesh/MeshRadio.h +++ b/src/mesh/MeshRadio.h @@ -6,87 +6,14 @@ #include "configuration.h" #include "mesh.pb.h" -// US channel settings -#define CH0_US 903.08f // MHz -#define CH_SPACING_US 2.16f // MHz -#define NUM_CHANNELS_US 13 +// Map from old region names to new region enums +struct RegionInfo { + RegionCode code; + uint8_t numChannels; + uint8_t powerLimit; // Or zero for not set + float freq; + float spacing; + const char *name; // EU433 etc +}; -// EU433 channel settings -#define CH0_EU433 433.175f // MHz -#define CH_SPACING_EU433 0.2f // MHz -#define NUM_CHANNELS_EU433 8 - -// EU865 channel settings -#define CH0_EU865 865.2f // MHz -#define CH_SPACING_EU865 0.3f // MHz -#define NUM_CHANNELS_EU865 10 - -// CN channel settings -#define CH0_CN 470.0f // MHz -#define CH_SPACING_CN 2.0f // MHz FIXME, this is just a guess for 470-510 -#define NUM_CHANNELS_CN 20 - -// JP channel settings (AS1 bandplan) -#define CH0_JP 920.0f // MHz -#define CH_SPACING_JP 0.5f -#define NUM_CHANNELS_JP 10 - -// TW channel settings (AS2 bandplan 923-925MHz) -#define CH0_TW 923.0f // MHz -#define CH_SPACING_TW 0.2 -#define NUM_CHANNELS_TW 10 - -// AU/NZ channel settings 915-928MHz -#define CH0_ANZ 916.0f // MHz - avoid overcrowding on 915.0 -#define CH_SPACING_ANZ 0.5f -#define NUM_CHANNELS_ANZ 20 - -// KR channel settings (KR920-923) -// Start from TTN download channel freq. (921.9f is for download, others are for uplink) -#define CH0_KR 921.9f // MHz -#define CH_SPACING_KR 0.2f -#define NUM_CHANNELS_KR 8 - -// FIXME add defs for other regions and use them here -#ifdef HW_VERSION_US -#define CH0 CH0_US -#define CH_SPACING CH_SPACING_US -#define NUM_CHANNELS NUM_CHANNELS_US -#elif defined(HW_VERSION_EU433) -#define CH0 CH0_EU433 -#define CH_SPACING CH_SPACING_EU433 -#define NUM_CHANNELS NUM_CHANNELS_EU433 -#elif defined(HW_VERSION_EU865) -#define CH0 CH0_EU865 -#define CH_SPACING CH_SPACING_EU865 -#define NUM_CHANNELS NUM_CHANNELS_EU865 -#elif defined(HW_VERSION_CN) -#define CH0 CH0_CN -#define CH_SPACING CH_SPACING_CN -#define NUM_CHANNELS NUM_CHANNELS_CN -#elif defined(HW_VERSION_JP) -// Also called AS1 bandplan -#define CH0 CH0_JP -#define CH_SPACING CH_SPACING_JP -#define NUM_CHANNELS NUM_CHANNELS_JP -#elif defined(HW_VERSION_TW) -// Also called AS2 bandplan -#define CH0 CH0_TW -#define CH_SPACING CH_SPACING_TW -#define NUM_CHANNELS NUM_CHANNELS_TW -#elif defined(HW_VERSION_ANZ) -// Australia and NZ -#define CH0 CH0_ANZ -#define CH_SPACING CH_SPACING_ANZ -#define NUM_CHANNELS NUM_CHANNELS_ANZ -#elif defined(HW_VERSION_KR) -// Republic of Korea -#define CH0 CH0_KR -#define CH_SPACING CH_SPACING_KR -#define NUM_CHANNELS NUM_CHANNELS_KR -#else -// HW version not set - assume US -#define CH0 CH0_US -#define CH_SPACING CH_SPACING_US -#define NUM_CHANNELS NUM_CHANNELS_US -#endif \ No newline at end of file +extern const RegionInfo regions[]; \ No newline at end of file diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 9f545a3fa..1f34eb5df 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -6,6 +6,7 @@ #include "CryptoEngine.h" #include "GPS.h" +#include "MeshRadio.h" #include "NodeDB.h" #include "PacketHistory.h" #include "PowerFSM.h" @@ -13,9 +14,9 @@ #include "configuration.h" #include "error.h" #include "mesh-pb-constants.h" +#include "meshwifi/meshwifi.h" #include #include -#include "meshwifi/meshwifi.h" NodeDB nodeDB; @@ -118,8 +119,6 @@ bool NodeDB::resetRadioConfig() } else if (radioConfig.preferences.sds_secs == 0) { DEBUG_MSG("Fixing bogus RadioConfig!\n"); - radioConfig.preferences.factory_reset = false; // never save this to disk - radioConfig.preferences.send_owner_interval = 4; // per sw-design.md radioConfig.preferences.position_broadcast_secs = 15 * 60; radioConfig.preferences.wait_bluetooth_secs = 120; @@ -163,6 +162,10 @@ bool NodeDB::resetRadioConfig() void NodeDB::installDefaultDeviceState() { + // We try to preserve the region setting because it will really bum users out if we discard it + String oldRegion = myNodeInfo.region; + RegionCode oldRegionCode = radioConfig.preferences.region; + memset(&devicestate, 0, sizeof(devicestate)); *numNodes = 0; // Forget node DB @@ -195,6 +198,12 @@ void NodeDB::installDefaultDeviceState() // owner.short_name now sprintf(owner.long_name, "Unknown %02x%02x", ourMacAddr[4], ourMacAddr[5]); sprintf(owner.short_name, "?%02X", (unsigned)(myNodeInfo.my_node_num & 0xff)); + + // Restore region if possible + if (oldRegionCode != RegionCode_Unset) + radioConfig.preferences.region = oldRegionCode; + if (oldRegion.length()) + strcpy(myNodeInfo.region, oldRegion.c_str()); } void NodeDB::init() @@ -227,13 +236,29 @@ void NodeDB::init() // We set these _after_ loading from disk - because they come from the build and are more trusted than // what is stored in flash - strncpy(myNodeInfo.region, optstr(HW_VERSION), sizeof(myNodeInfo.region)); + if (xstr(HW_VERSION)[0]) + strncpy(myNodeInfo.region, optstr(HW_VERSION), sizeof(myNodeInfo.region)); + else + DEBUG_MSG("This build does not specify a HW_VERSION\n"); // Eventually new builds will no longer include this build flag + + // Check for the old style of region code strings, if found, convert to the new enum. + // Those strings will look like "1.0-EU433" + if (radioConfig.preferences.region == RegionCode_Unset && strncmp(myNodeInfo.region, "1.0-", 4) == 0) { + const char *regionStr = myNodeInfo.region + 4; // EU433 or whatever + for (const RegionInfo *r = regions; r->code != RegionCode_Unset; r++) + if (strcmp(r->name, regionStr) == 0) { + radioConfig.preferences.region = r->code; + break; + } + } + strncpy(myNodeInfo.firmware_version, optstr(APP_VERSION), sizeof(myNodeInfo.firmware_version)); strncpy(myNodeInfo.hw_model, HW_VENDOR, sizeof(myNodeInfo.hw_model)); resetRadioConfig(); // If bogus settings got saved, then fix them - DEBUG_MSG("NODENUM=0x%x, dbsize=%d\n", myNodeInfo.my_node_num, *numNodes); + DEBUG_MSG("legacy_region=%s, region=%d, NODENUM=0x%x, dbsize=%d\n", myNodeInfo.region, radioConfig.preferences.region, + myNodeInfo.my_node_num, *numNodes); } // We reserve a few nodenums for future use @@ -421,11 +446,11 @@ void NodeDB::updateFrom(const MeshPacket &mp) powerFSM.trigger(EVENT_RECEIVED_TEXT_MSG); notifyObservers(true); // Force an update whether or not our node counts have changed -// This is going into the wifidev feature branch -// Only update the WebUI if WiFi is enabled -//#if WiFi_MODE != 0 -// notifyWebUI(); -//#endif + // This is going into the wifidev feature branch + // Only update the WebUI if WiFi is enabled + //#if WiFi_MODE != 0 + // notifyWebUI(); + //#endif } } break; diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 1a08f282e..1fcee0dc3 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -10,6 +10,24 @@ #include #include +#define RDEF(name, freq, spacing, num_ch, power_limit) \ + { \ + RegionCode_##name, num_ch, power_limit, freq, spacing, #name \ + } + +const RegionInfo regions[] = { + RDEF(US, 903.08f, 2.16f, 13, 0), RDEF(EU433, 433.175f, 0.2f, 8, 0), RDEF(EU865, 865.2f, 0.3f, 10, 0), + RDEF(CN, 470.0f, 2.0f, 20, 0), + RDEF(JP, 920.0f, 0.5f, 10, 13), // See https://github.com/meshtastic/Meshtastic-device/issues/346 power level 13 + RDEF(ANZ, 916.0f, 0.5f, 20, 0), // AU/NZ channel settings 915-928MHz + RDEF(KR, 921.9f, 0.2f, 8, 0), // KR channel settings (KR920-923) Start from TTN download channel + // freq. (921.9f is for download, others are for uplink) + RDEF(TW, 923.0f, 0.2f, 10, 0), // TW channel settings (AS2 bandplan 923-925MHz) + RDEF(Unset, 903.08f, 2.16f, 13, 0) // Assume US freqs if unset, Must be last +}; + +static const RegionInfo *myRegion; + /** * ## LoRaWAN for North America @@ -77,7 +95,15 @@ RadioInterface::RadioInterface() { assert(sizeof(PacketHeader) == 4 || sizeof(PacketHeader) == 16); // make sure the compiler did what we expected - myNodeInfo.num_channels = NUM_CHANNELS; + if (!myRegion) { + const RegionInfo *r = regions; + for (; r->code != RegionCode_Unset && r->code != radioConfig.preferences.region; r++) + ; + myRegion = r; + DEBUG_MSG("Wanted region %d, using %s\n", radioConfig.preferences.region, r->name); + + myNodeInfo.num_channels = myRegion->numChannels; // Tell our android app how many channels we have + } // Can't print strings this early - serial not setup yet // DEBUG_MSG("Set meshradio defaults name=%s\n", channelSettings.name); @@ -127,9 +153,12 @@ void RadioInterface::applyModemConfig() power = channelSettings.tx_power; + assert(myRegion); // Should have been found in init + // If user has manually specified a channel num, then use that, otherwise generate one by hashing the name - int channel_num = (channelSettings.channel_num ? channelSettings.channel_num - 1 : hash(channelSettings.name)) % NUM_CHANNELS; - freq = CH0 + CH_SPACING * channel_num; + int channel_num = + (channelSettings.channel_num ? channelSettings.channel_num - 1 : hash(channelSettings.name)) % myRegion->numChannels; + freq = myRegion->freq + myRegion->spacing * channel_num; DEBUG_MSG("Set radio: name=%s, config=%u, ch=%d, power=%d\n", channelSettings.name, channelSettings.modem_config, channel_num, power); @@ -143,9 +172,9 @@ void RadioInterface::limitPower() { uint8_t maxPower = 255; // No limit -#ifdef HW_VERSION_JP - maxPower = 13; // See https://github.com/meshtastic/Meshtastic-device/issues/346 -#endif + if (myRegion->powerLimit) + maxPower = myRegion->powerLimit; + if (power > maxPower) { DEBUG_MSG("Lowering transmit power because of regulatory limits\n"); power = maxPower; diff --git a/src/mesh/mesh.pb.c b/src/mesh/mesh.pb.c index b2d1ceb23..11ec3f49f 100644 --- a/src/mesh/mesh.pb.c +++ b/src/mesh/mesh.pb.c @@ -27,7 +27,7 @@ PB_BIND(MeshPacket, MeshPacket, 2) PB_BIND(ChannelSettings, ChannelSettings, AUTO) -PB_BIND(RadioConfig, RadioConfig, 2) +PB_BIND(RadioConfig, RadioConfig, AUTO) PB_BIND(RadioConfig_UserPreferences, RadioConfig_UserPreferences, 2) @@ -59,3 +59,4 @@ PB_BIND(ManufacturingData, ManufacturingData, AUTO) + diff --git a/src/mesh/mesh.pb.h b/src/mesh/mesh.pb.h index 6fbc79f7c..b726ab6e1 100644 --- a/src/mesh/mesh.pb.h +++ b/src/mesh/mesh.pb.h @@ -25,6 +25,18 @@ typedef enum _Constants { Constants_Unused = 0 } Constants; +typedef enum _RegionCode { + RegionCode_Unset = 0, + RegionCode_US = 1, + RegionCode_EU433 = 2, + RegionCode_EU865 = 3, + RegionCode_CN = 4, + RegionCode_JP = 5, + RegionCode_ANZ = 6, + RegionCode_KR = 7, + RegionCode_TW = 8 +} RegionCode; + typedef enum _Data_Type { Data_Type_OPAQUE = 0, Data_Type_CLEAR_TEXT = 1, @@ -108,7 +120,7 @@ typedef struct _RadioConfig_UserPreferences { char wifi_ssid[33]; char wifi_password[64]; bool wifi_ap_mode; - char region[6]; + RegionCode region; bool factory_reset; pb_size_t ignore_incoming_count; uint32_t ignore_incoming[3]; @@ -232,6 +244,10 @@ typedef struct _ToRadio { #define _Constants_MAX Constants_Unused #define _Constants_ARRAYSIZE ((Constants)(Constants_Unused+1)) +#define _RegionCode_MIN RegionCode_Unset +#define _RegionCode_MAX RegionCode_TW +#define _RegionCode_ARRAYSIZE ((RegionCode)(RegionCode_TW+1)) + #define _Data_Type_MIN Data_Type_OPAQUE #define _Data_Type_MAX Data_Type_CLEAR_READACK #define _Data_Type_ARRAYSIZE ((Data_Type)(Data_Type_CLEAR_READACK+1)) @@ -250,7 +266,7 @@ typedef struct _ToRadio { #define MeshPacket_init_default {0, 0, 0, {SubPacket_init_default}, 0, 0, 0, 0, 0} #define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0} #define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default, false, ChannelSettings_init_default} -#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, "", 0, 0, {0, 0, 0}} +#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, 0, 0, {0, 0, 0}} #define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0} #define MyNodeInfo_init_default {0, 0, 0, "", "", "", 0, 0, 0, 0, 0, 0, 0, 0} #define DeviceState_init_default {false, RadioConfig_init_default, false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0} @@ -266,7 +282,7 @@ typedef struct _ToRadio { #define MeshPacket_init_zero {0, 0, 0, {SubPacket_init_zero}, 0, 0, 0, 0, 0} #define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0} #define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero, false, ChannelSettings_init_zero} -#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, "", 0, 0, {0, 0, 0}} +#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, 0, 0, {0, 0, 0}} #define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0} #define MyNodeInfo_init_zero {0, 0, 0, "", "", "", 0, 0, 0, 0, 0, 0, 0, 0} #define DeviceState_init_zero {false, RadioConfig_init_zero, false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0} @@ -481,7 +497,7 @@ X(a, STATIC, SINGULAR, UINT32, min_wake_secs, 11) \ X(a, STATIC, SINGULAR, STRING, wifi_ssid, 12) \ X(a, STATIC, SINGULAR, STRING, wifi_password, 13) \ X(a, STATIC, SINGULAR, BOOL, wifi_ap_mode, 14) \ -X(a, STATIC, SINGULAR, STRING, region, 15) \ +X(a, STATIC, SINGULAR, UENUM, region, 15) \ X(a, STATIC, SINGULAR, BOOL, factory_reset, 100) \ X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103) #define RadioConfig_UserPreferences_CALLBACK NULL @@ -619,11 +635,11 @@ extern const pb_msgdesc_t ManufacturingData_msg; #define SubPacket_size 274 #define MeshPacket_size 313 #define ChannelSettings_size 84 -#define RadioConfig_size 287 -#define RadioConfig_UserPreferences_size 198 +#define RadioConfig_size 282 +#define RadioConfig_UserPreferences_size 193 #define NodeInfo_size 132 #define MyNodeInfo_size 110 -#define DeviceState_size 5439 +#define DeviceState_size 5434 #define DebugString_size 258 #define FromRadio_size 322 #define ToRadio_size 316 From d1c30786983ae2803e41a079747748a2d127cf17 Mon Sep 17 00:00:00 2001 From: geeksville Date: Fri, 25 Sep 2020 12:52:26 -0700 Subject: [PATCH 5/6] shrink guard for channel settings lock --- src/graphics/Screen.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 0b57bfb3e..14a202458 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -31,8 +31,8 @@ along with this program. If not, see . #include "graphics/images.h" #include "main.h" #include "mesh-pb-constants.h" -#include "target_specific.h" #include "meshwifi/meshwifi.h" +#include "target_specific.h" #include "utils.h" using namespace meshtastic; /** @todo remove */ @@ -809,18 +809,18 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 { concurrency::LockGuard guard(&lock); snprintf(channelStr, sizeof(channelStr), "%s", channelName.c_str()); - - // Display power status - if (powerStatus->getHasBattery()) - drawBattery(display, x, y + 2, imgBattery, powerStatus); - else if (powerStatus->knowsUSB()) - display->drawFastImage(x, y + 2, 16, 8, powerStatus->getHasUSB() ? imgUSB : imgPower); - // Display nodes status - drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 2, nodeStatus); - // Display GPS status - drawGPS(display, x + (SCREEN_WIDTH * 0.63), y + 2, gpsStatus); } + // Display power status + if (powerStatus->getHasBattery()) + drawBattery(display, x, y + 2, imgBattery, powerStatus); + else if (powerStatus->knowsUSB()) + display->drawFastImage(x, y + 2, 16, 8, powerStatus->getHasUSB() ? imgUSB : imgPower); + // Display nodes status + drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 2, nodeStatus); + // Display GPS status + drawGPS(display, x + (SCREEN_WIDTH * 0.63), y + 2, gpsStatus); + // Draw the channel name display->drawString(x, y + FONT_HEIGHT, channelStr); // Draw our hardware ID to assist with bluetooth pairing From 2996c7c8e26472e69686a4221ca446f7ad9b7370 Mon Sep 17 00:00:00 2001 From: geeksville Date: Fri, 25 Sep 2020 16:18:30 -0700 Subject: [PATCH 6/6] Make tcp API now work. Sample usage and caveats below: Sample usage: First configure device to use @mc-hamster's new wifi stuff: meshtastic --set wifi_ssid mylanname --set wifi_password mylanpassword Then reboot the device (so wifi starts up). (assuming device was assigned addr 192.168.81.45) meshtastic --info --host 192.168.81.45 (See the usual device info you previously had to get over USB) Caveats: * Currently we are limiting to one active TCP connection open at once, if you open a new session the old one is closed automatically * There are no access controls/authentication needed to open a TCP connection to the device * Currently main.cpp is kinda dumb about how we should schedule work and we rely on too many helper loop() functions. Very soon in my queue (related to all the other cleanup) is to add a basic notion of coroutines, so that we can get away from freertos threads and this old school arduino loop function. Once that cleanup happens we can the a) have much lower battery consumption (always) and b) super fast response for all operations. --- src/esp32/WiFiServerAPI.cpp | 10 +++++++++- src/esp32/WiFiServerAPI.h | 7 +++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/esp32/WiFiServerAPI.cpp b/src/esp32/WiFiServerAPI.cpp index 974b0f3c1..109340bff 100644 --- a/src/esp32/WiFiServerAPI.cpp +++ b/src/esp32/WiFiServerAPI.cpp @@ -52,6 +52,14 @@ void WiFiServerPort::loop() { auto client = available(); if (client) { - new WiFiServerAPI(client); + // Close any previous connection (see FIXME in header file) + if (openAPI) + delete openAPI; + + openAPI = new WiFiServerAPI(client); } + + if (openAPI) + // Allow idle processing so the API can read from its incoming stream + openAPI->loop(); } \ No newline at end of file diff --git a/src/esp32/WiFiServerAPI.h b/src/esp32/WiFiServerAPI.h index dcafa419d..a9b1e39b4 100644 --- a/src/esp32/WiFiServerAPI.h +++ b/src/esp32/WiFiServerAPI.h @@ -29,6 +29,13 @@ class WiFiServerAPI : public StreamAPI */ class WiFiServerPort : public WiFiServer { + /** The currently open port + * + * FIXME: We currently only allow one open TCP connection at a time, because we depend on the loop() call in this class to + * delegate to the worker. Once coroutines are implemented we can relax this restriction. + */ + WiFiServerAPI *openAPI = NULL; + public: WiFiServerPort();