From 45caf394f0fa84c37b731d04b98cfb8c2d4120e3 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Tue, 16 Feb 2021 15:41:52 +0800 Subject: [PATCH 01/35] WIP multichannel support --- .vscode/settings.json | 10 +- docs/software/TODO.md | 18 +++ proto | 2 +- src/graphics/Screen.cpp | 11 +- src/graphics/Screen.h | 9 -- src/mesh/Channels.cpp | 228 +++++++++++++++++++++++++++++ src/mesh/Channels.h | 51 +++++++ src/mesh/NodeDB.cpp | 165 ++------------------- src/mesh/NodeDB.h | 19 --- src/mesh/PhoneAPI.cpp | 5 +- src/mesh/PhoneAPI.h | 12 +- src/mesh/RadioInterface.cpp | 13 +- src/mesh/Router.cpp | 1 - src/mesh/generated/deviceonly.pb.h | 18 +-- src/mesh/generated/mesh.pb.c | 4 + src/mesh/generated/mesh.pb.h | 122 ++++++++------- src/mesh/mesh-pb-constants.h | 3 + src/plugins/RangeTestPlugin.cpp | 5 +- 18 files changed, 421 insertions(+), 275 deletions(-) create mode 100644 src/mesh/Channels.cpp create mode 100644 src/mesh/Channels.h diff --git a/.vscode/settings.json b/.vscode/settings.json index f78fe51b8..965532c24 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -68,5 +68,13 @@ "protobufs", "wifi" ], - "C_Cpp.dimInactiveRegions": true + "C_Cpp.dimInactiveRegions": true, + "protoc": { + "compile_on_save": false, + "compile_all_path": "/home/kevinh/development/meshtastic/meshtastic-esp32/proto", + "options": [ + "--java_out=/tmp", + "-I=/home/kevinh/development/meshtastic/meshtastic-esp32/proto" + ] + } } \ No newline at end of file diff --git a/docs/software/TODO.md b/docs/software/TODO.md index f6df164b0..ded8796de 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -2,6 +2,24 @@ You probably don't care about this section - skip to the next one. +1.2 cleanup & multichannel: + +* remove deprecated +* allow chaning packets in single transmission +* fix setchannel in phoneapi.cpp +* set mynodeinfo.max_channels +* set mynodeinfo.num_bands (formerly num_channels) +* send a hint that can be used to select which channel to try and hash against with each message +* change syncword +* move acks into routing +* make all subpackets different versions of data +* move routing control into a data packet +* make a primaryChannel global and properly maintain it when the phone sends setChannel +* move setCrypto call into packet send and packet decode code +* implement'small locations' change? +* move battery level out of position? +* DOUBLE CHECK android app can still upgrade 1.1 and 1.0 loads + eink: * new battery level sensing diff --git a/proto b/proto index 0cadaed39..481beb41b 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 0cadaed3953f66cf1edc99d0fa53e4fd5ebf56d6 +Subproject commit 481beb41ba8c8f39bfc6b3f397d6107af04dfb93 diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 40ea25237..f7193260f 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -32,6 +32,7 @@ along with this program. If not, see . #include "main.h" #include "mesh-pb-constants.h" #include "plugins/TextMessagePlugin.h" +#include "mesh/Channels.h" #include "target_specific.h" #include "utils.h" @@ -790,9 +791,6 @@ int32_t Screen::runOnce() showingBootScreen = false; } - // Update the screen last, after we've figured out what to show. - debug_info()->setChannelNameStatus(getChannelName()); - // Process incoming commands. for (;;) { ScreenCmd cmd; @@ -1022,7 +1020,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 char channelStr[20]; { concurrency::LockGuard guard(&lock); - snprintf(channelStr, sizeof(channelStr), "%s", channelName.c_str()); + auto chName = channels.getPrimaryName(); + snprintf(channelStr, sizeof(channelStr), "%s", chName); } // Display power status @@ -1229,8 +1228,8 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat display->drawString(x, y, String("USB")); } - display->drawString(x + SCREEN_WIDTH - display->getStringWidth("Mode " + String(channelSettings.modem_config)), y, - "Mode " + String(channelSettings.modem_config)); + auto mode = "Mode " + String(channels.getPrimary().modem_config); + display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode), y, mode); // Line 2 uint32_t currentMillis = millis(); diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index 041da4865..9be119a48 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -39,13 +39,6 @@ class DebugInfo DebugInfo(const DebugInfo &) = delete; DebugInfo &operator=(const DebugInfo &) = delete; - /// Sets the name of the channel. - void setChannelNameStatus(const char *name) - { - concurrency::LockGuard guard(&lock); - channelName = name; - } - private: friend Screen; @@ -56,8 +49,6 @@ class DebugInfo void drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); void drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); - std::string channelName; - /// Protects all of internal state. concurrency::Lock lock; }; diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp new file mode 100644 index 000000000..584a83bc8 --- /dev/null +++ b/src/mesh/Channels.cpp @@ -0,0 +1,228 @@ +#include "Channels.h" +#include "NodeDB.h" +#include "CryptoEngine.h" + +#include + +/// A usable psk - which has been constructed based on the (possibly short psk) in channelSettings +static uint8_t activePSK[32]; +static uint8_t activePSKSize; + +/// 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}; + +Channels channels; + +/** + * Validate a channel, fixing any errors as needed + */ +Channel &fixupChannel(size_t chIndex) +{ + assert(chIndex < devicestate.channels_count); + + Channel *ch = devicestate.channels + chIndex; + + ch->index = chIndex; // Preinit the index so it be ready to share with the phone (we'll never change it later) + + if (!ch->has_settings) { + // No settings! Must disable and skip + ch->role = Channel_Role_DISABLED; + } else { + ChannelSettings &channelSettings = ch->settings; + + // Convert the old string "Default" to our new short representation + if (strcmp(channelSettings.name, "Default") == 0) + *channelSettings.name = '\0'; + + // Convert any old usage of the defaultpsk into our new short representation. + if (channelSettings.psk.size == sizeof(defaultpsk) && + memcmp(channelSettings.psk.bytes, defaultpsk, sizeof(defaultpsk)) == 0) { + *channelSettings.psk.bytes = 1; + channelSettings.psk.size = 1; + } + } + + return *ch; +} + + + +/** + * Write a default channel to the specified channel index + */ +void initDefaultChannel(size_t chIndex) +{ + assert(chIndex < devicestate.channels_count); + Channel *ch = devicestate.channels + chIndex; + ChannelSettings &channelSettings = ch->settings; + + // 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_Bw125Cr48Sf4096; // slow and long range + + channelSettings.tx_power = 0; // default + uint8_t defaultpskIndex = 1; + channelSettings.psk.bytes[0] = defaultpskIndex; + channelSettings.psk.size = 1; + strcpy(channelSettings.name, ""); + + ch->has_settings = true; + ch->role = Channel_Role_PRIMARY; +} + +/** Given a channel index, change to use the crypto key specified by that index + */ +void setCrypto(size_t chIndex) +{ + + assert(chIndex < devicestate.channels_count); + Channel *ch = devicestate.channels + chIndex; + ChannelSettings &channelSettings = ch->settings; + + memset(activePSK, 0, sizeof(activePSK)); // In case the user provided a short key, we want to pad the rest with zeros + memcpy(activePSK, channelSettings.psk.bytes, channelSettings.psk.size); + activePSKSize = channelSettings.psk.size; + if (activePSKSize == 0) + DEBUG_MSG("Warning: User disabled encryption\n"); + else if (activePSKSize == 1) { + // Convert the short single byte variants of psk into variant that can be used more generally + + uint8_t pskIndex = activePSK[0]; + DEBUG_MSG("Expanding short PSK #%d\n", pskIndex); + if (pskIndex == 0) + activePSKSize = 0; // Turn off encryption + else { + memcpy(activePSK, defaultpsk, sizeof(defaultpsk)); + activePSKSize = sizeof(defaultpsk); + // Bump up the last byte of PSK as needed + uint8_t *last = activePSK + sizeof(defaultpsk) - 1; + *last = *last + pskIndex - 1; // index of 1 means no change vs defaultPSK + } + } else if (activePSKSize < 16) { + // Error! The user specified only the first few bits of an AES128 key. So by convention we just pad the rest of the key + // with zeros + DEBUG_MSG("Warning: User provided a too short AES128 key - padding\n"); + activePSKSize = 16; + } else if (activePSKSize < 32 && activePSKSize != 16) { + // Error! The user specified only the first few bits of an AES256 key. So by convention we just pad the rest of the key + // with zeros + DEBUG_MSG("Warning: User provided a too short AES256 key - padding\n"); + activePSKSize = 32; + } + + // Tell our crypto engine about the psk + crypto->setKey(activePSKSize, activePSK); +} + +void Channels::initDefaults() +{ + devicestate.channels_count = MAX_CHANNELS; + for (int i = 0; i < devicestate.channels_count; i++) + fixupChannel(i); + initDefaultChannel(0); +} + +void Channels::onConfigChanged() +{ + // Make sure the phone hasn't mucked anything up + for (int i = 0; i < devicestate.channels_count; i++) { + auto ch = fixupChannel(i); + + if(ch.role == Channel_Role_PRIMARY) + primaryIndex = i; + } + + setCrypto(0); // FIXME: for the time being (still single channel - just use our only channel as the crypto key) +} + +Channel &Channels::getChannel(size_t chIndex) +{ + assert(chIndex < devicestate.channels_count); + Channel *ch = devicestate.channels + chIndex; + return *ch; +} + +void Channels::setChannel(const Channel &c) { + Channel &old = getChannel(c.index); + + // if this is the new primary, demote any existing roles + if(c.role == Channel_Role_PRIMARY) + for (int i = 0; i < devicestate.channels_count; i++) + if(devicestate.channels[i].role == Channel_Role_PRIMARY) + devicestate.channels[i].role = Channel_Role_SECONDARY; + + old = c; // slam in the new settings/role +} + +const char *Channels::getName(size_t chIndex) +{ + // Convert the short "" representation for Default into a usable string + ChannelSettings &channelSettings = getChannel(chIndex).settings; + const char *channelName = channelSettings.name; + if (!*channelName) { // emptystring + // Per mesh.proto spec, if bandwidth is specified we must ignore modemConfig enum, we assume that in that case + // the app fucked up and forgot to set channelSettings.name + + if (channelSettings.bandwidth != 0) + channelName = "Unset"; + else + switch (channelSettings.modem_config) { + case ChannelSettings_ModemConfig_Bw125Cr45Sf128: + channelName = "Medium"; + break; + case ChannelSettings_ModemConfig_Bw500Cr45Sf128: + channelName = "ShortFast"; + break; + case ChannelSettings_ModemConfig_Bw31_25Cr48Sf512: + channelName = "LongAlt"; + break; + case ChannelSettings_ModemConfig_Bw125Cr48Sf4096: + channelName = "LongSlow"; + break; + default: + channelName = "Invalid"; + break; + } + } + + return channelName; +} + +/** +* Generate a short suffix used to disambiguate channels that might have the same "name" entered by the human but different PSKs. +* The ideas is that the PSK changing should be visible to the user so that they see they probably messed up and that's why they +their nodes +* aren't talking to each other. +* +* This string is of the form "#name-X". +* +* Where X is either: +* (for custom PSKS) a letter from A to Z (base26), and formed by xoring all the bytes of the PSK together, +* OR (for the standard minimially secure PSKs) a number from 0 to 9. +* +* This function will also need to be implemented in GUI apps that talk to the radio. +* +* https://github.com/meshtastic/Meshtastic-device/issues/269 +*/ +const char *Channels::getPrimaryName() +{ + static char buf[32]; + + char suffix; + auto channelSettings = getPrimary(); + if (channelSettings.psk.size != 1) { + // We have a standard PSK, so generate a letter based hash. + uint8_t code = 0; + for (int i = 0; i < activePSKSize; i++) + code ^= activePSK[i]; + + suffix = 'A' + (code % 26); + } else { + suffix = '0' + channelSettings.psk.bytes[0]; + } + + snprintf(buf, sizeof(buf), "#%s-%c", channelSettings.name, suffix); + return buf; +} \ No newline at end of file diff --git a/src/mesh/Channels.h b/src/mesh/Channels.h new file mode 100644 index 000000000..5654fb1f2 --- /dev/null +++ b/src/mesh/Channels.h @@ -0,0 +1,51 @@ +#pragma once + +#include "mesh-pb-constants.h" +#include + +class Channels +{ + size_t primaryIndex = 0; + + public: + const ChannelSettings &getPrimary() { return getChannel(getPrimaryIndex()).settings; } + + Channel &getChannel(size_t chIndex); + + /** Using the index inside the channel, update the specified channel's settings and role. If this channel is being promoted to be + * primary, force all other channels to be secondary. + */ + void setChannel(const Channel &c); + + const char *getName(size_t chIndex); + + /** The index of the primary channel */ + size_t getPrimaryIndex() const { return primaryIndex; } + + /** + * Generate a short suffix used to disambiguate channels that might have the same "name" entered by the human but different PSKs. + * The ideas is that the PSK changing should be visible to the user so that they see they probably messed up and that's why they +their nodes + * aren't talking to each other. + * + * This string is of the form "#name-X". + * + * Where X is either: + * (for custom PSKS) a letter from A to Z (base26), and formed by xoring all the bytes of the PSK together, + * OR (for the standard minimially secure PSKs) a number from 0 to 9. + * + * This function will also need to be implemented in GUI apps that talk to the radio. + * + * https://github.com/meshtastic/Meshtastic-device/issues/269 + */ + const char *getPrimaryName(); + + /// Called by NodeDB on initial boot when the radio config settings are unset. Set a default single channel config. + void initDefaults(); + + /// called when the user has just changed our radio config and we might need to change channel keys + void onConfigChanged(); +}; + +/// Singleton channel table +extern Channels channels; \ No newline at end of file diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index b8f0b5697..9347ef0fd 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -7,7 +7,6 @@ #include "CryptoEngine.h" #include "FSCommon.h" #include "GPS.h" -#include "main.h" #include "MeshRadio.h" #include "NodeDB.h" #include "PacketHistory.h" @@ -16,6 +15,8 @@ #include "Router.h" #include "configuration.h" #include "error.h" +#include "main.h" +#include "Channels.h" #include "mesh-pb-constants.h" #include #include @@ -30,7 +31,6 @@ NodeDB nodeDB; EXT_RAM_ATTR DeviceState devicestate; MyNodeInfo &myNodeInfo = devicestate.my_node; RadioConfig &radioConfig = devicestate.radio; -ChannelSettings &channelSettings = radioConfig.channel_settings; /** The current change # for radio settings. Starts at 0 on boot and any time the radio settings * might have changed is incremented. Allows others to detect they might now be on a new channel. @@ -64,49 +64,6 @@ static uint8_t ourMacAddr[6]; */ NodeNum displayedNodeNum; -/// A usable (but bigger) version of the channel name in the channelSettings object -const char *channelName; - -/// A usable psk - which has been constructed based on the (possibly short psk) in channelSettings -static uint8_t activePSK[32]; -static uint8_t activePSKSize; - -/** - * Generate a short suffix used to disambiguate channels that might have the same "name" entered by the human but different PSKs. - * The ideas is that the PSK changing should be visible to the user so that they see they probably messed up and that's why they -their nodes - * aren't talking to each other. - * - * This string is of the form "#name-X". - * - * Where X is either: - * (for custom PSKS) a letter from A to Z (base26), and formed by xoring all the bytes of the PSK together, - * OR (for the standard minimially secure PSKs) a number from 0 to 9. - * - * This function will also need to be implemented in GUI apps that talk to the radio. - * - * https://github.com/meshtastic/Meshtastic-device/issues/269 - */ -const char *getChannelName() -{ - static char buf[32]; - - char suffix; - if (channelSettings.psk.size != 1) { - // We have a standard PSK, so generate a letter based hash. - uint8_t code = 0; - for (int i = 0; i < activePSKSize; i++) - code ^= activePSK[i]; - - suffix = 'A' + (code % 26); - } else { - suffix = '0' + channelSettings.psk.bytes[0]; - } - - snprintf(buf, sizeof(buf), "#%s-%c", channelName, suffix); - return buf; -} - NodeDB::NodeDB() : nodes(devicestate.node_db), numNodes(&devicestate.node_db_count) {} bool NodeDB::resetRadioConfig() @@ -115,104 +72,19 @@ bool NodeDB::resetRadioConfig() radioGeneration++; - /// 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.factory_reset) { DEBUG_MSG("Performing factory reset!\n"); installDefaultDeviceState(); didFactoryReset = true; - } else if (!channelSettings.psk.size) { - DEBUG_MSG("Setting default preferences!\n"); + } else if (devicestate.channels_count == 0) { + DEBUG_MSG("Setting default channel and radio preferences!\n"); + + channels.initDefaults(); - radioConfig.has_channel_settings = true; 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_Bw125Cr48Sf4096; // slow and long range - - channelSettings.tx_power = 0; // default - uint8_t defaultpskIndex = 1; - channelSettings.psk.bytes[0] = defaultpskIndex; - channelSettings.psk.size = 1; - strcpy(channelSettings.name, ""); } - // Convert the old string "Default" to our new short representation - if (strcmp(channelSettings.name, "Default") == 0) - *channelSettings.name = '\0'; - - // Convert the short "" representation for Default into a usable string - channelName = channelSettings.name; - if (!*channelName) { // emptystring - // Per mesh.proto spec, if bandwidth is specified we must ignore modemConfig enum, we assume that in that case - // the app fucked up and forgot to set channelSettings.name - - if (channelSettings.bandwidth != 0) - channelName = "Unset"; - else - switch (channelSettings.modem_config) { - case ChannelSettings_ModemConfig_Bw125Cr45Sf128: - channelName = "Medium"; - break; - case ChannelSettings_ModemConfig_Bw500Cr45Sf128: - channelName = "ShortFast"; - break; - case ChannelSettings_ModemConfig_Bw31_25Cr48Sf512: - channelName = "LongAlt"; - break; - case ChannelSettings_ModemConfig_Bw125Cr48Sf4096: - channelName = "LongSlow"; - break; - default: - channelName = "Invalid"; - break; - } - } - - // Convert any old usage of the defaultpsk into our new short representation. - if (channelSettings.psk.size == sizeof(defaultpsk) && - memcmp(channelSettings.psk.bytes, defaultpsk, sizeof(defaultpsk)) == 0) { - *channelSettings.psk.bytes = 1; - channelSettings.psk.size = 1; - } - - memset(activePSK, 0, sizeof(activePSK)); // In case the user provided a short key, we want to pad the rest with zeros - memcpy(activePSK, channelSettings.psk.bytes, channelSettings.psk.size); - activePSKSize = channelSettings.psk.size; - if(activePSKSize == 0) - DEBUG_MSG("Warning: User disabled encryption\n"); - else if (activePSKSize == 1) { - // Convert the short single byte variants of psk into variant that can be used more generally - - uint8_t pskIndex = activePSK[0]; - DEBUG_MSG("Expanding short PSK #%d\n", pskIndex); - if (pskIndex == 0) - activePSKSize = 0; // Turn off encryption - else { - memcpy(activePSK, defaultpsk, sizeof(defaultpsk)); - activePSKSize = sizeof(defaultpsk); - // Bump up the last byte of PSK as needed - uint8_t *last = activePSK + sizeof(defaultpsk) - 1; - *last = *last + pskIndex - 1; // index of 1 means no change vs defaultPSK - } - } else if(activePSKSize < 16) { - // Error! The user specified only the first few bits of an AES128 key. So by convention we just pad the rest of the key - // with zeros - DEBUG_MSG("Warning: User provided a too short AES128 key - padding\n"); - activePSKSize = 16; - } else if(activePSKSize < 32 && activePSKSize != 16) { - // Error! The user specified only the first few bits of an AES256 key. So by convention we just pad the rest of the key - // with zeros - DEBUG_MSG("Warning: User provided a too short AES256 key - padding\n"); - activePSKSize = 32; - } - - // Tell our crypto engine about the psk - crypto->setKey(activePSKSize, activePSK); + channels.onConfigChanged(); // temp hack for quicker testing // devicestate.no_save = true; @@ -251,7 +123,6 @@ void NodeDB::installDefaultDeviceState() devicestate.has_my_node = true; devicestate.has_radio = true; devicestate.has_owner = true; - devicestate.radio.has_channel_settings = true; devicestate.radio.has_preferences = true; devicestate.node_db_count = 0; devicestate.receive_queue_count = 0; // Not yet implemented FIXME @@ -289,17 +160,14 @@ void NodeDB::init() loadFromDisk(); // saveToDisk(); - // We set node_num and packet_id _after_ loading from disk, because we always want to use the values this - // rom was compiled for, not what happens to be in the save file. - myNodeInfo.node_num_bits = sizeof(NodeNum) * 8; - myNodeInfo.packet_id_bits = sizeof(PacketId) * 8; + myNodeInfo.max_channels = MAX_CHANNELS; // tell others the max # of channels we can understand myNodeInfo.error_code = CriticalErrorCode_None; // For the error code, only show values from this boot (discard value from flash) myNodeInfo.error_address = 0; // likewise - we always want the app requirements to come from the running appload - myNodeInfo.min_app_version = 20120; // format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20 + myNodeInfo.min_app_version = 20200; // format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20 // Note! We do this after loading saved settings, so that if somehow an invalid nodenum was stored in preferences we won't // keep using that nodenum forever. Crummy guess at our nodenum (but we will check against the nodedb to avoid conflicts) @@ -539,12 +407,6 @@ void NodeDB::updateFrom(const MeshPacket &mp) info->snr = mp.rx_snr; // keep the most recent SNR we received for this node. switch (p.which_payloadVariant) { - case SubPacket_position_tag: { - // handle a legacy position packet - DEBUG_MSG("WARNING: Processing a (deprecated) position packet from %d\n", mp.from); - updatePosition(mp.from, p.position); - break; - } case SubPacket_data_tag: { if (mp.to == NODENUM_BROADCAST || mp.to == nodeDB.getNodeNum()) @@ -552,12 +414,6 @@ void NodeDB::updateFrom(const MeshPacket &mp) break; } - case SubPacket_user_tag: { - DEBUG_MSG("WARNING: Processing a (deprecated) user packet from %d\n", mp.from); - updateUser(mp.from, p.user); - break; - } - default: { notifyObservers(); // If the node counts have changed, notify observers } @@ -601,10 +457,9 @@ void recordCriticalError(CriticalErrorCode code, uint32_t address) String lcd = String("Critical error ") + code + "!\n"; screen->print(lcd.c_str()); DEBUG_MSG("NOTE! Recording critical error %d, address=%lx\n", code, address); - + // Record error to DB myNodeInfo.error_code = code; myNodeInfo.error_address = address; myNodeInfo.error_count++; - } diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index 5174f5642..29c35369f 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -11,9 +11,7 @@ extern DeviceState devicestate; extern MyNodeInfo &myNodeInfo; extern RadioConfig &radioConfig; -extern ChannelSettings &channelSettings; extern User &owner; -extern const char *channelName; /// Given a node, return how many seconds in the past (vs now) that we last heard from it uint32_t sinceLastSeen(const NodeInfo *n); @@ -130,23 +128,6 @@ extern NodeNum displayedNodeNum; extern NodeDB nodeDB; -/** - * Generate a short suffix used to disambiguate channels that might have the same "name" entered by the human but different PSKs. - * The ideas is that the PSK changing should be visible to the user so that they see they probably messed up and that's why they -their nodes - * aren't talking to each other. - * - * This string is of the form "#name-XY". - * - * Where X is a letter from A to Z (base26), and formed by xoring all the bytes of the PSK together. - * Y is not yet used but should eventually indicate 'speed/range' of the link - * - * This function will also need to be implemented in GUI apps that talk to the radio. - * - * https://github.com/meshtastic/Meshtastic-device/issues/269 - */ -const char *getChannelName(); - /* If is_router is set, we use a number of different default values diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index f9c9b6175..6ec09b2ca 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -4,6 +4,7 @@ #include "NodeDB.h" #include "PowerFSM.h" #include "RadioInterface.h" +#include "Channels.h" #include #if FromRadio_size > MAX_TO_FROM_RADIO_SIZE @@ -279,9 +280,9 @@ void PhoneAPI::handleSetOwner(const User &o) service.reloadOwner(); } -void PhoneAPI::handleSetChannel(const ChannelSettings &cc) +void PhoneAPI::handleSetChannel(const Channel &cc) { - radioConfig.channel_settings = cc; + channels.setChannel(cc); bool didReset = service.reloadConfig(); if (didReset) { diff --git a/src/mesh/PhoneAPI.h b/src/mesh/PhoneAPI.h index 663d6824c..6d4e8d626 100644 --- a/src/mesh/PhoneAPI.h +++ b/src/mesh/PhoneAPI.h @@ -83,14 +83,6 @@ class PhoneAPI */ bool available(); - // - // The following routines are only public for now - until the rev1 bluetooth API is removed - // - - void handleSetOwner(const User &o); - void handleSetChannel(const ChannelSettings &cc); - void handleSetRadio(const RadioConfig &r); - protected: /// Are we currently connected to a client? bool isConnected = false; @@ -109,6 +101,10 @@ class PhoneAPI */ virtual void onNowHasData(uint32_t fromRadioNum) {} + void handleSetOwner(const User &o); + void handleSetChannel(const Channel &cc); + void handleSetRadio(const RadioConfig &r); + private: /** * Handle a packet that the phone wants us to send. It is our responsibility to free the packet to the pool diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 0884c260d..0d99ca2ff 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -6,6 +6,7 @@ #include "assert.h" #include "configuration.h" #include "sleep.h" +#include "Channels.h" #include #include #include @@ -36,7 +37,7 @@ void initRegion() 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 + myNodeInfo.num_bands = myRegion->numChannels; // Tell our android app how many channels we have } /** @@ -125,12 +126,6 @@ void printPacket(const char *prefix, const MeshPacket *p) case SubPacket_data_tag: DEBUG_MSG(" Portnum=%d", s.data.portnum); break; - case SubPacket_position_tag: - DEBUG_MSG(" Payload:Position"); - break; - case SubPacket_user_tag: - DEBUG_MSG(" Payload:User"); - break; case 0: DEBUG_MSG(" Payload:None"); break; @@ -252,6 +247,7 @@ void RadioInterface::applyModemConfig() // Set up default configuration // No Sync Words in LORA mode + auto channelSettings = channels.getPrimary(); if (channelSettings.spread_factor == 0) { switch (channelSettings.modem_config) { case ChannelSettings_ModemConfig_Bw125Cr45Sf128: ///< Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. Default medium @@ -296,7 +292,8 @@ void RadioInterface::applyModemConfig() 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(channelName)) % myRegion->numChannels; + const char *channelName = channels.getName(channels.getPrimaryIndex()); + int channel_num = channelSettings.channel_num ? channelSettings.channel_num - 1 : hash(channelName) % myRegion->numChannels; freq = myRegion->freq + myRegion->spacing * channel_num; DEBUG_MSG("Set radio: name=%s, config=%u, ch=%d, power=%d\n", channelName, channelSettings.modem_config, channel_num, power); diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 43d939c31..5178e229b 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -80,7 +80,6 @@ PacketId generatePacketId() i++; PacketId id = (i % numPacketId) + 1; // return number between 1 and numPacketId (ie - never zero) - myNodeInfo.current_packet_id = id; // Kinda crufty - we keep updating this so the phone can see a current value return id; } diff --git a/src/mesh/generated/deviceonly.pb.h b/src/mesh/generated/deviceonly.pb.h index 99d838d39..e1f4c4010 100644 --- a/src/mesh/generated/deviceonly.pb.h +++ b/src/mesh/generated/deviceonly.pb.h @@ -27,8 +27,8 @@ typedef struct _DeviceState { uint32_t version; bool no_save; bool did_gps_reset; - pb_size_t secondary_channels_count; - ChannelSettings secondary_channels[7]; + pb_size_t channels_count; + Channel channels[8]; } DeviceState; @@ -37,8 +37,8 @@ extern "C" { #endif /* Initializer values for message structs */ -#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, 0, {ChannelSettings_init_default, ChannelSettings_init_default, ChannelSettings_init_default, ChannelSettings_init_default, ChannelSettings_init_default, ChannelSettings_init_default, ChannelSettings_init_default}} -#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, 0, {ChannelSettings_init_zero, ChannelSettings_init_zero, ChannelSettings_init_zero, ChannelSettings_init_zero, ChannelSettings_init_zero, ChannelSettings_init_zero, ChannelSettings_init_zero}} +#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, 0, {Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default}} +#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, 0, {Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero}} /* Field tags (for use in manual encoding/decoding) */ #define DeviceState_radio_tag 1 @@ -50,7 +50,7 @@ extern "C" { #define DeviceState_version_tag 8 #define DeviceState_no_save_tag 9 #define DeviceState_did_gps_reset_tag 11 -#define DeviceState_secondary_channels_tag 12 +#define DeviceState_channels_tag 12 /* Struct field encoding specification for nanopb */ #define DeviceState_FIELDLIST(X, a) \ @@ -63,7 +63,7 @@ X(a, STATIC, OPTIONAL, MESSAGE, rx_text_message, 7) \ X(a, STATIC, SINGULAR, UINT32, version, 8) \ X(a, STATIC, SINGULAR, BOOL, no_save, 9) \ X(a, STATIC, SINGULAR, BOOL, did_gps_reset, 11) \ -X(a, STATIC, REPEATED, MESSAGE, secondary_channels, 12) +X(a, STATIC, REPEATED, MESSAGE, channels, 12) #define DeviceState_CALLBACK NULL #define DeviceState_DEFAULT NULL #define DeviceState_radio_MSGTYPE RadioConfig @@ -72,7 +72,7 @@ X(a, STATIC, REPEATED, MESSAGE, secondary_channels, 12) #define DeviceState_node_db_MSGTYPE NodeInfo #define DeviceState_receive_queue_MSGTYPE MeshPacket #define DeviceState_rx_text_message_MSGTYPE MeshPacket -#define DeviceState_secondary_channels_MSGTYPE ChannelSettings +#define DeviceState_channels_MSGTYPE Channel extern const pb_msgdesc_t DeviceState_msg; @@ -80,10 +80,10 @@ extern const pb_msgdesc_t DeviceState_msg; #define DeviceState_fields &DeviceState_msg /* Maximum encoded size of messages (where known) */ -#define DeviceState_size 6266 +#define DeviceState_size 6265 #ifdef __cplusplus } /* extern "C" */ #endif -#endif \ No newline at end of file +#endif diff --git a/src/mesh/generated/mesh.pb.c b/src/mesh/generated/mesh.pb.c index 0bf5fbe38..872447623 100644 --- a/src/mesh/generated/mesh.pb.c +++ b/src/mesh/generated/mesh.pb.c @@ -27,6 +27,9 @@ PB_BIND(MeshPacket, MeshPacket, 2) PB_BIND(ChannelSettings, ChannelSettings, AUTO) +PB_BIND(Channel, Channel, AUTO) + + PB_BIND(RadioConfig, RadioConfig, 2) @@ -59,3 +62,4 @@ PB_BIND(ToRadio, ToRadio, 2) + diff --git a/src/mesh/generated/mesh.pb.h b/src/mesh/generated/mesh.pb.h index 397a313ea..691b4cd78 100644 --- a/src/mesh/generated/mesh.pb.h +++ b/src/mesh/generated/mesh.pb.h @@ -100,6 +100,12 @@ typedef enum _ChannelSettings_ModemConfig { ChannelSettings_ModemConfig_Bw125Cr48Sf4096 = 3 } ChannelSettings_ModemConfig; +typedef enum _Channel_Role { + Channel_Role_DISABLED = 0, + Channel_Role_PRIMARY = 1, + Channel_Role_SECONDARY = 2 +} Channel_Role; + typedef enum _LogRecord_Level { LogRecord_Level_UNSET = 0, LogRecord_Level_CRITICAL = 50, @@ -142,25 +148,23 @@ typedef struct _LogRecord { typedef struct _MyNodeInfo { uint32_t my_node_num; bool has_gps; - int32_t num_channels; + uint32_t num_bands; char region[12]; char hw_model[16]; char firmware_version[12]; CriticalErrorCode error_code; uint32_t error_address; uint32_t error_count; - uint32_t packet_id_bits; - uint32_t current_packet_id; - uint32_t node_num_bits; uint32_t message_timeout_msec; uint32_t min_app_version; + uint32_t max_channels; } MyNodeInfo; typedef struct _Position { - int32_t altitude; - int32_t battery_level; int32_t latitude_i; int32_t longitude_i; + int32_t altitude; + int32_t battery_level; uint32_t time; } Position; @@ -222,6 +226,13 @@ typedef struct _User { pb_byte_t macaddr[6]; } User; +typedef struct _Channel { + uint32_t index; + bool has_settings; + ChannelSettings settings; + Channel_Role role; +} Channel; + typedef struct _NodeInfo { uint32_t num; bool has_user; @@ -235,21 +246,17 @@ typedef struct _NodeInfo { typedef struct _RadioConfig { bool has_preferences; RadioConfig_UserPreferences preferences; - bool has_channel_settings; - ChannelSettings channel_settings; } RadioConfig; typedef struct _SubPacket { + uint32_t original_id; pb_size_t which_payloadVariant; union { - Position position; Data data; - User user; RouteDiscovery route_request; RouteDiscovery route_reply; ErrorReason error_reason; }; - uint32_t original_id; bool want_response; uint32_t dest; pb_size_t which_ackVariant; @@ -289,7 +296,7 @@ typedef struct _FromRadio { LogRecord log_record; uint32_t config_complete_id; bool rebooted; - ChannelSettings channel; + Channel channel; }; } FromRadio; @@ -300,7 +307,7 @@ typedef struct _ToRadio { uint32_t want_config_id; RadioConfig set_radio; User set_owner; - ChannelSettings set_channel; + Channel set_channel; }; } ToRadio; @@ -342,6 +349,10 @@ typedef struct _ToRadio { #define _ChannelSettings_ModemConfig_MAX ChannelSettings_ModemConfig_Bw125Cr48Sf4096 #define _ChannelSettings_ModemConfig_ARRAYSIZE ((ChannelSettings_ModemConfig)(ChannelSettings_ModemConfig_Bw125Cr48Sf4096+1)) +#define _Channel_Role_MIN Channel_Role_DISABLED +#define _Channel_Role_MAX Channel_Role_SECONDARY +#define _Channel_Role_ARRAYSIZE ((Channel_Role)(Channel_Role_SECONDARY+1)) + #define _LogRecord_Level_MIN LogRecord_Level_UNSET #define _LogRecord_Level_MAX LogRecord_Level_CRITICAL #define _LogRecord_Level_ARRAYSIZE ((LogRecord_Level)(LogRecord_Level_CRITICAL+1)) @@ -356,13 +367,14 @@ extern "C" { #define Data_init_default {_PortNum_MIN, {0, {0}}} #define User_init_default {"", "", "", {0}} #define RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}} -#define SubPacket_init_default {0, {Position_init_default}, 0, 0, 0, 0, {0}, 0} +#define SubPacket_init_default {0, 0, {Data_init_default}, 0, 0, 0, {0}, 0} #define MeshPacket_init_default {0, 0, 0, {SubPacket_init_default}, 0, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} #define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} -#define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default, false, ChannelSettings_init_default} +#define Channel_init_default {0, false, ChannelSettings_init_default, _Channel_Role_MIN} +#define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default} #define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 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, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0} +#define MyNodeInfo_init_default {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0} #define LogRecord_init_default {"", 0, "", _LogRecord_Level_MIN} #define FromRadio_init_default {0, 0, {MeshPacket_init_default}} #define ToRadio_init_default {0, {MeshPacket_init_default}} @@ -370,13 +382,14 @@ extern "C" { #define Data_init_zero {_PortNum_MIN, {0, {0}}} #define User_init_zero {"", "", "", {0}} #define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}} -#define SubPacket_init_zero {0, {Position_init_zero}, 0, 0, 0, 0, {0}, 0} +#define SubPacket_init_zero {0, 0, {Data_init_zero}, 0, 0, 0, {0}, 0} #define MeshPacket_init_zero {0, 0, 0, {SubPacket_init_zero}, 0, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} #define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} -#define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero, false, ChannelSettings_init_zero} +#define Channel_init_zero {0, false, ChannelSettings_init_zero, _Channel_Role_MIN} +#define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero} #define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 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, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0} +#define MyNodeInfo_init_zero {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0} #define LogRecord_init_zero {"", 0, "", _LogRecord_Level_MIN} #define FromRadio_init_zero {0, 0, {MeshPacket_init_zero}} #define ToRadio_init_zero {0, {MeshPacket_init_zero}} @@ -401,22 +414,20 @@ extern "C" { #define LogRecord_level_tag 4 #define MyNodeInfo_my_node_num_tag 1 #define MyNodeInfo_has_gps_tag 2 -#define MyNodeInfo_num_channels_tag 3 +#define MyNodeInfo_num_bands_tag 3 #define MyNodeInfo_region_tag 4 #define MyNodeInfo_hw_model_tag 5 #define MyNodeInfo_firmware_version_tag 6 #define MyNodeInfo_error_code_tag 7 #define MyNodeInfo_error_address_tag 8 #define MyNodeInfo_error_count_tag 9 -#define MyNodeInfo_packet_id_bits_tag 10 -#define MyNodeInfo_current_packet_id_tag 11 -#define MyNodeInfo_node_num_bits_tag 12 #define MyNodeInfo_message_timeout_msec_tag 13 #define MyNodeInfo_min_app_version_tag 14 +#define MyNodeInfo_max_channels_tag 15 +#define Position_latitude_i_tag 1 +#define Position_longitude_i_tag 2 #define Position_altitude_tag 3 #define Position_battery_level_tag 4 -#define Position_latitude_i_tag 7 -#define Position_longitude_i_tag 8 #define Position_time_tag 9 #define RadioConfig_UserPreferences_position_broadcast_secs_tag 1 #define RadioConfig_UserPreferences_send_owner_interval_tag 2 @@ -465,20 +476,20 @@ extern "C" { #define User_long_name_tag 2 #define User_short_name_tag 3 #define User_macaddr_tag 4 +#define Channel_index_tag 1 +#define Channel_settings_tag 2 +#define Channel_role_tag 3 #define NodeInfo_num_tag 1 #define NodeInfo_user_tag 2 #define NodeInfo_position_tag 3 #define NodeInfo_next_hop_tag 5 #define NodeInfo_snr_tag 7 #define RadioConfig_preferences_tag 1 -#define RadioConfig_channel_settings_tag 2 -#define SubPacket_position_tag 1 +#define SubPacket_original_id_tag 2 #define SubPacket_data_tag 3 -#define SubPacket_user_tag 4 #define SubPacket_route_request_tag 6 #define SubPacket_route_reply_tag 7 #define SubPacket_error_reason_tag 13 -#define SubPacket_original_id_tag 2 #define SubPacket_want_response_tag 5 #define SubPacket_dest_tag 9 #define SubPacket_success_id_tag 10 @@ -508,14 +519,14 @@ extern "C" { #define ToRadio_want_config_id_tag 100 #define ToRadio_set_radio_tag 101 #define ToRadio_set_owner_tag 102 -#define ToRadio_set_channel_tag 103 +#define ToRadio_set_channel_tag 104 /* Struct field encoding specification for nanopb */ #define Position_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, SFIXED32, latitude_i, 1) \ +X(a, STATIC, SINGULAR, SFIXED32, longitude_i, 2) \ X(a, STATIC, SINGULAR, INT32, altitude, 3) \ X(a, STATIC, SINGULAR, INT32, battery_level, 4) \ -X(a, STATIC, SINGULAR, SINT32, latitude_i, 7) \ -X(a, STATIC, SINGULAR, SINT32, longitude_i, 8) \ X(a, STATIC, SINGULAR, FIXED32, time, 9) #define Position_CALLBACK NULL #define Position_DEFAULT NULL @@ -540,13 +551,11 @@ X(a, STATIC, REPEATED, INT32, route, 2) #define RouteDiscovery_DEFAULT NULL #define SubPacket_FIELDLIST(X, a) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,position,position), 1) \ +X(a, STATIC, SINGULAR, UINT32, original_id, 2) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,data,data), 3) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,user,user), 4) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,route_request,route_request), 6) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,route_reply,route_reply), 7) \ X(a, STATIC, ONEOF, UENUM, (payloadVariant,error_reason,error_reason), 13) \ -X(a, STATIC, SINGULAR, UINT32, original_id, 2) \ X(a, STATIC, SINGULAR, BOOL, want_response, 5) \ X(a, STATIC, SINGULAR, UINT32, dest, 9) \ X(a, STATIC, ONEOF, UINT32, (ackVariant,success_id,ackVariant.success_id), 10) \ @@ -554,9 +563,7 @@ X(a, STATIC, ONEOF, UINT32, (ackVariant,fail_id,ackVariant.fail_id), 11) X(a, STATIC, SINGULAR, UINT32, source, 12) #define SubPacket_CALLBACK NULL #define SubPacket_DEFAULT NULL -#define SubPacket_payloadVariant_position_MSGTYPE Position #define SubPacket_payloadVariant_data_MSGTYPE Data -#define SubPacket_payloadVariant_user_MSGTYPE User #define SubPacket_payloadVariant_route_request_MSGTYPE RouteDiscovery #define SubPacket_payloadVariant_route_reply_MSGTYPE RouteDiscovery @@ -591,13 +598,19 @@ X(a, STATIC, SINGULAR, BOOL, downlink_enabled, 17) #define ChannelSettings_CALLBACK NULL #define ChannelSettings_DEFAULT NULL +#define Channel_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, index, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, settings, 2) \ +X(a, STATIC, SINGULAR, UENUM, role, 3) +#define Channel_CALLBACK NULL +#define Channel_DEFAULT NULL +#define Channel_settings_MSGTYPE ChannelSettings + #define RadioConfig_FIELDLIST(X, a) \ -X(a, STATIC, OPTIONAL, MESSAGE, preferences, 1) \ -X(a, STATIC, OPTIONAL, MESSAGE, channel_settings, 2) +X(a, STATIC, OPTIONAL, MESSAGE, preferences, 1) #define RadioConfig_CALLBACK NULL #define RadioConfig_DEFAULT NULL #define RadioConfig_preferences_MSGTYPE RadioConfig_UserPreferences -#define RadioConfig_channel_settings_MSGTYPE ChannelSettings #define RadioConfig_UserPreferences_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, position_broadcast_secs, 1) \ @@ -659,18 +672,16 @@ X(a, STATIC, SINGULAR, FLOAT, snr, 7) #define MyNodeInfo_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, my_node_num, 1) \ X(a, STATIC, SINGULAR, BOOL, has_gps, 2) \ -X(a, STATIC, SINGULAR, INT32, num_channels, 3) \ +X(a, STATIC, SINGULAR, UINT32, num_bands, 3) \ X(a, STATIC, SINGULAR, STRING, region, 4) \ X(a, STATIC, SINGULAR, STRING, hw_model, 5) \ X(a, STATIC, SINGULAR, STRING, firmware_version, 6) \ X(a, STATIC, SINGULAR, UENUM, error_code, 7) \ X(a, STATIC, SINGULAR, UINT32, error_address, 8) \ X(a, STATIC, SINGULAR, UINT32, error_count, 9) \ -X(a, STATIC, SINGULAR, UINT32, packet_id_bits, 10) \ -X(a, STATIC, SINGULAR, UINT32, current_packet_id, 11) \ -X(a, STATIC, SINGULAR, UINT32, node_num_bits, 12) \ X(a, STATIC, SINGULAR, UINT32, message_timeout_msec, 13) \ -X(a, STATIC, SINGULAR, UINT32, min_app_version, 14) +X(a, STATIC, SINGULAR, UINT32, min_app_version, 14) \ +X(a, STATIC, SINGULAR, UINT32, max_channels, 15) #define MyNodeInfo_CALLBACK NULL #define MyNodeInfo_DEFAULT NULL @@ -699,20 +710,20 @@ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,channel,channel), 10) #define FromRadio_payloadVariant_node_info_MSGTYPE NodeInfo #define FromRadio_payloadVariant_radio_MSGTYPE RadioConfig #define FromRadio_payloadVariant_log_record_MSGTYPE LogRecord -#define FromRadio_payloadVariant_channel_MSGTYPE ChannelSettings +#define FromRadio_payloadVariant_channel_MSGTYPE Channel #define ToRadio_FIELDLIST(X, a) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,packet,packet), 1) \ X(a, STATIC, ONEOF, UINT32, (payloadVariant,want_config_id,want_config_id), 100) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,set_radio,set_radio), 101) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,set_owner,set_owner), 102) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,set_channel,set_channel), 103) +X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,set_channel,set_channel), 104) #define ToRadio_CALLBACK NULL #define ToRadio_DEFAULT NULL #define ToRadio_payloadVariant_packet_MSGTYPE MeshPacket #define ToRadio_payloadVariant_set_radio_MSGTYPE RadioConfig #define ToRadio_payloadVariant_set_owner_MSGTYPE User -#define ToRadio_payloadVariant_set_channel_MSGTYPE ChannelSettings +#define ToRadio_payloadVariant_set_channel_MSGTYPE Channel extern const pb_msgdesc_t Position_msg; extern const pb_msgdesc_t Data_msg; @@ -721,6 +732,7 @@ extern const pb_msgdesc_t RouteDiscovery_msg; extern const pb_msgdesc_t SubPacket_msg; extern const pb_msgdesc_t MeshPacket_msg; extern const pb_msgdesc_t ChannelSettings_msg; +extern const pb_msgdesc_t Channel_msg; extern const pb_msgdesc_t RadioConfig_msg; extern const pb_msgdesc_t RadioConfig_UserPreferences_msg; extern const pb_msgdesc_t NodeInfo_msg; @@ -737,6 +749,7 @@ extern const pb_msgdesc_t ToRadio_msg; #define SubPacket_fields &SubPacket_msg #define MeshPacket_fields &MeshPacket_msg #define ChannelSettings_fields &ChannelSettings_msg +#define Channel_fields &Channel_msg #define RadioConfig_fields &RadioConfig_msg #define RadioConfig_UserPreferences_fields &RadioConfig_UserPreferences_msg #define NodeInfo_fields &NodeInfo_msg @@ -746,20 +759,21 @@ extern const pb_msgdesc_t ToRadio_msg; #define ToRadio_fields &ToRadio_msg /* Maximum encoded size of messages (where known) */ -#define Position_size 39 +#define Position_size 37 #define Data_size 246 #define User_size 72 #define RouteDiscovery_size 88 #define SubPacket_size 275 #define MeshPacket_size 322 #define ChannelSettings_size 95 -#define RadioConfig_size 405 +#define Channel_size 105 +#define RadioConfig_size 308 #define RadioConfig_UserPreferences_size 305 -#define NodeInfo_size 132 -#define MyNodeInfo_size 106 +#define NodeInfo_size 130 +#define MyNodeInfo_size 89 #define LogRecord_size 81 -#define FromRadio_size 414 -#define ToRadio_size 409 +#define FromRadio_size 331 +#define ToRadio_size 325 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/mesh-pb-constants.h b/src/mesh/mesh-pb-constants.h index fd3b2cedf..ed1c4f7e8 100644 --- a/src/mesh/mesh-pb-constants.h +++ b/src/mesh/mesh-pb-constants.h @@ -16,6 +16,9 @@ /// max number of nodes allowed in the mesh #define MAX_NUM_NODES (member_size(DeviceState, node_db) / member_size(DeviceState, node_db[0])) +/// Max number of channels allowed +#define MAX_CHANNELS (member_size(DeviceState, channels) / member_size(DeviceState, channels[0])) + /// helper function for encoding a record as a protobuf, any failures to encode are fatal and we will panic /// returns the encoded packet size size_t pb_encode_to_bytes(uint8_t *destbuf, size_t destbufsize, const pb_msgdesc_t *fields, const void *src_struct); diff --git a/src/plugins/RangeTestPlugin.cpp b/src/plugins/RangeTestPlugin.cpp index 8f03589c2..58150f5bb 100644 --- a/src/plugins/RangeTestPlugin.cpp +++ b/src/plugins/RangeTestPlugin.cpp @@ -145,8 +145,9 @@ bool RangeTestPluginRadio::handleReceived(const MeshPacket &mp) DEBUG_MSG("mp.from %d\n", mp.from); DEBUG_MSG("mp.rx_snr %f\n", mp.rx_snr); DEBUG_MSG("mp.hop_limit %d\n", mp.hop_limit); - DEBUG_MSG("mp.decoded.position.latitude_i %d\n", mp.decoded.position.latitude_i); - DEBUG_MSG("mp.decoded.position.longitude_i %d\n", mp.decoded.position.longitude_i); + //deprecated and unpopulated for sometime + //DEBUG_MSG("mp.decoded.position.latitude_i %d\n", mp.decoded.position.latitude_i); + //DEBUG_MSG("mp.decoded.position.longitude_i %d\n", mp.decoded.position.longitude_i); DEBUG_MSG("---- Node Information of Received Packet (mp.from):\n"); DEBUG_MSG("n->user.long_name %s\n", n->user.long_name); DEBUG_MSG("n->user.short_name %s\n", n->user.short_name); From 205282c4bcd13160cada7f3cd0e40774a21bff44 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Wed, 17 Feb 2021 10:08:33 +0800 Subject: [PATCH 02/35] show hwvendor at boot --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index bb3ec4820..985bec808 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -356,7 +356,7 @@ void setup() #endif // Hello - DEBUG_MSG("Meshtastic swver=%s, hwver=%s\n", optstr(APP_VERSION), optstr(HW_VERSION)); + DEBUG_MSG("Meshtastic hwvendor=%s, swver=%s, hwver=%s\n", HW_VENDOR, optstr(APP_VERSION), optstr(HW_VERSION)); #ifndef NO_ESP32 // Don't init display if we don't have one or we are waking headless due to a timer event From 42ae27973e977bdc5e5739f48a011a13f47b8355 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Wed, 17 Feb 2021 13:06:23 +0800 Subject: [PATCH 03/35] WIP 1.2 move routing into plugin --- docs/software/TODO.md | 24 +++- proto | 2 +- src/graphics/Screen.cpp | 3 +- src/mesh/Channels.cpp | 2 +- src/mesh/DSRRouter.cpp | 30 ++-- src/mesh/DSRRouter.h | 4 +- src/mesh/FloodingRouter.cpp | 4 +- src/mesh/FloodingRouter.h | 2 +- src/mesh/MeshPacketQueue.cpp | 2 +- src/mesh/MeshPlugin.cpp | 4 +- src/mesh/MeshPlugin.h | 6 + src/mesh/NodeDB.cpp | 20 +-- src/mesh/ProtobufPlugin.h | 8 +- src/mesh/RadioInterface.cpp | 23 ++- src/mesh/ReliableRouter.cpp | 14 +- src/mesh/ReliableRouter.h | 2 +- src/mesh/Router.cpp | 39 ++---- src/mesh/Router.h | 8 +- src/mesh/SinglePortPlugin.h | 3 +- src/mesh/generated/apponly.pb.c | 3 + src/mesh/generated/apponly.pb.h | 16 +++ src/mesh/generated/deviceonly.pb.h | 2 +- src/mesh/generated/mesh.pb.c | 8 +- src/mesh/generated/mesh.pb.h | 215 ++++++++++++++--------------- src/mesh/generated/portnums.pb.h | 1 + src/mesh/mesh-pb-constants.h | 2 +- src/plugins/Plugins.cpp | 2 + src/plugins/RangeTestPlugin.cpp | 4 +- src/plugins/ReplyPlugin.cpp | 6 +- src/plugins/RoutingPlugin.cpp | 54 ++++++++ src/plugins/RoutingPlugin.h | 31 +++++ src/plugins/SerialPlugin.cpp | 4 +- src/plugins/TextMessagePlugin.cpp | 2 +- 33 files changed, 317 insertions(+), 233 deletions(-) create mode 100644 src/plugins/RoutingPlugin.cpp create mode 100644 src/plugins/RoutingPlugin.h diff --git a/docs/software/TODO.md b/docs/software/TODO.md index ded8796de..c4569cbda 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -4,16 +4,26 @@ You probably don't care about this section - skip to the next one. 1.2 cleanup & multichannel: -* remove deprecated +* DONE remove deprecated * allow chaning packets in single transmission -* fix setchannel in phoneapi.cpp -* set mynodeinfo.max_channels -* set mynodeinfo.num_bands (formerly num_channels) +* DONE fix setchannel in phoneapi.cpp +* DONE set mynodeinfo.max_channels +* DONE set mynodeinfo.num_bands (formerly num_channels) +* fix sniffing of non Routing packets +* move portnum up? +* scrub protobufs to make sure they are absoloute minimum wiresize (in particular packets, ChannelSets and positions) * send a hint that can be used to select which channel to try and hash against with each message * change syncword -* move acks into routing -* make all subpackets different versions of data -* move routing control into a data packet +* DONE move acks into routing +* DONE make all subpackets different versions of data +* DONE move routing control into a data packet +* have phoneapi done via plugin +* figure out how to add micro_delta to position, make it so that phone apps don't need to understand it? +* only send battery updates a max of once a minute +* add multichannel support in python +* add channel selection for sending +* record recevied channel in meshpacket +* add channel restrictions for plugins (and restrict routing plugin to the "control" channel) * make a primaryChannel global and properly maintain it when the phone sends setChannel * move setCrypto call into packet send and packet decode code * implement'small locations' change? diff --git a/proto b/proto index 481beb41b..65914b84f 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 481beb41ba8c8f39bfc6b3f397d6107af04dfb93 +Subproject commit 65914b84f1ee8f25807187d60b43ad29dfbaedc3 diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index f7193260f..a2c74ba7e 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -216,8 +216,7 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state // the max length of this buffer is much longer than we can possibly print static char tempBuf[96]; - assert(mp.decoded.which_payloadVariant == SubPacket_data_tag); - snprintf(tempBuf, sizeof(tempBuf), " %s", mp.decoded.data.payload.bytes); + snprintf(tempBuf, sizeof(tempBuf), " %s", mp.decoded.payload.bytes); display->drawStringMaxWidth(4 + x, 10 + y, SCREEN_WIDTH - (6 + x), tempBuf); } diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp index 584a83bc8..510510ca3 100644 --- a/src/mesh/Channels.cpp +++ b/src/mesh/Channels.cpp @@ -118,7 +118,7 @@ void setCrypto(size_t chIndex) void Channels::initDefaults() { - devicestate.channels_count = MAX_CHANNELS; + devicestate.channels_count = MAX_NUM_CHANNELS; for (int i = 0; i < devicestate.channels_count; i++) fixupChannel(i); initDefaultChannel(0); diff --git a/src/mesh/DSRRouter.cpp b/src/mesh/DSRRouter.cpp index 8b1e6f67e..04d4a2bef 100644 --- a/src/mesh/DSRRouter.cpp +++ b/src/mesh/DSRRouter.cpp @@ -62,7 +62,7 @@ ErrorCode DSRRouter::send(MeshPacket *p) return ReliableRouter::send(p); } -void DSRRouter::sniffReceived(const MeshPacket *p) +void DSRRouter::sniffReceived(const MeshPacket *p, const Routing &c) { // Learn 0 hop routes by just hearing any adjacent nodes // But treat broadcasts carefully, because when flood broadcasts go out they keep the same original "from". So we want to @@ -72,25 +72,25 @@ void DSRRouter::sniffReceived(const MeshPacket *p) addRoute(p->from, p->from, 0); // We are adjacent with zero hops } - switch (p->decoded.which_payloadVariant) { - case SubPacket_route_request_tag: + switch (c.which_variant) { + case Routing_route_request_tag: // Handle route discovery packets (will be a broadcast message) // FIXME - always start request with the senders nodenum - if (weAreInRoute(p->decoded.route_request)) { + if (weAreInRoute(c.route_request)) { DEBUG_MSG("Ignoring a route request that contains us\n"); } else { - updateRoutes(p->decoded.route_request, + updateRoutes(c.route_request, true); // Update our routing tables based on the route that came in so far on this request if (p->decoded.dest == getNodeNum()) { // They were looking for us, send back a route reply (the sender address will be first in the list) - sendRouteReply(p->decoded.route_request); + sendRouteReply(c.route_request); } else { // They were looking for someone else, forward it along (as a zero hop broadcast) NodeNum nextHop = getNextHop(p->decoded.dest); if (nextHop) { // in our route cache, reply to the requester (the sender address will be first in the list) - sendRouteReply(p->decoded.route_request, nextHop); + sendRouteReply(c.route_request, nextHop); } else { // Not in our route cache, rebroadcast on their behalf (after adding ourselves to the request route) resendRouteRequest(p); @@ -98,14 +98,14 @@ void DSRRouter::sniffReceived(const MeshPacket *p) } } break; - case SubPacket_route_reply_tag: - updateRoutes(p->decoded.route_reply, false); + case Routing_route_reply_tag: + updateRoutes(c.route_reply, false); // FIXME, if any of our current pending packets were waiting for this route, send them (and leave them as regular pending // packets until ack arrives) // FIXME, if we don't get a route reply at all (or a route error), timeout and generate a routeerror TIMEOUT on our own... break; - case SubPacket_error_reason_tag: + case Routing_error_reason_tag: removeRoute(p->decoded.dest); // FIXME: if any pending packets were waiting on this route, delete them @@ -131,7 +131,7 @@ void DSRRouter::sniffReceived(const MeshPacket *p) assert(p->decoded.source); // I think this is guaranteed by now // FIXME - what if the current packet _is_ a route error packet? - sendRouteError(p, ErrorReason_NO_ROUTE); + sendRouteError(p, Routing_Error_NO_ROUTE); } // FIXME, stop local processing of this packet @@ -139,18 +139,18 @@ void DSRRouter::sniffReceived(const MeshPacket *p) // handle naks - convert them to route error packets // All naks are generated locally, because we failed resending the packet too many times - PacketId nakId = p->decoded.which_ackVariant == SubPacket_fail_id_tag ? p->decoded.ackVariant.fail_id : 0; + PacketId nakId = c.fail_id; if (nakId) { auto pending = findPendingPacket(p->to, nakId); if (pending && pending->packet->decoded.source) { // if source not set, this was not a multihop packet, just ignore removeRoute(pending->packet->decoded.dest); // We no longer have a route to the specified node - sendRouteError(p, ErrorReason_GOT_NAK); + sendRouteError(p, Routing_Error_GOT_NAK); } } } - return ReliableRouter::sniffReceived(p); + ReliableRouter::sniffReceived(p, c); } /** @@ -230,7 +230,7 @@ void DSRRouter::sendNextHop(NodeNum n, const MeshPacket *p) /** * Send a route error packet towards whoever originally sent this message */ -void DSRRouter::sendRouteError(const MeshPacket *p, ErrorReason err) +void DSRRouter::sendRouteError(const MeshPacket *p, Routing_Error err) { DEBUG_MSG("FIXME not implemented sendRouteError\n"); } diff --git a/src/mesh/DSRRouter.h b/src/mesh/DSRRouter.h index 02c0f2775..eef1a991c 100644 --- a/src/mesh/DSRRouter.h +++ b/src/mesh/DSRRouter.h @@ -8,7 +8,7 @@ class DSRRouter : public ReliableRouter * Every (non duplicate) packet this node receives will be passed through this method. This allows subclasses to * update routing tables etc... based on what we overhear (even for messages not destined to our node) */ - virtual void sniffReceived(const MeshPacket *p); + virtual void sniffReceived(const MeshPacket *p, const Routing &c); /** * Send a packet on a suitable interface. This routine will @@ -70,7 +70,7 @@ class DSRRouter : public ReliableRouter /** * Send a route error packet towards whoever originally sent this message */ - void sendRouteError(const MeshPacket *p, ErrorReason err); + void sendRouteError(const MeshPacket *p, Routing_Error err); /** make a copy of p, start discovery, but only if we don't * already a discovery in progress for that node number. Caller has already scheduled this message for retransmission diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index f2b718835..777178c41 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -27,7 +27,7 @@ bool FloodingRouter::shouldFilterReceived(const MeshPacket *p) return Router::shouldFilterReceived(p); } -void FloodingRouter::sniffReceived(const MeshPacket *p) +void FloodingRouter::sniffReceived(const MeshPacket *p, const Routing &c) { // If a broadcast, possibly _also_ send copies out into the mesh. // (FIXME, do something smarter than naive flooding here) @@ -48,5 +48,5 @@ void FloodingRouter::sniffReceived(const MeshPacket *p) } // handle the packet as normal - Router::sniffReceived(p); + Router::sniffReceived(p, c); } diff --git a/src/mesh/FloodingRouter.h b/src/mesh/FloodingRouter.h index ca7ee489f..3e4f5de6e 100644 --- a/src/mesh/FloodingRouter.h +++ b/src/mesh/FloodingRouter.h @@ -55,5 +55,5 @@ class FloodingRouter : public Router, protected PacketHistory /** * Look for broadcasts we need to rebroadcast */ - virtual void sniffReceived(const MeshPacket *p); + virtual void sniffReceived(const MeshPacket *p, const Routing &c); }; diff --git a/src/mesh/MeshPacketQueue.cpp b/src/mesh/MeshPacketQueue.cpp index 363e83ba7..56db3feb3 100644 --- a/src/mesh/MeshPacketQueue.cpp +++ b/src/mesh/MeshPacketQueue.cpp @@ -33,7 +33,7 @@ void fixPriority(MeshPacket *p) if (p->priority == MeshPacket_Priority_UNSET) { // if acks give high priority // if a reliable message give a bit higher default priority - p->priority = p->decoded.which_ackVariant ? MeshPacket_Priority_ACK : + p->priority = (p->decoded.portnum == PortNum_ROUTING_APP) ? MeshPacket_Priority_ACK : (p->want_ack ? MeshPacket_Priority_RELIABLE : MeshPacket_Priority_DEFAULT); } } diff --git a/src/mesh/MeshPlugin.cpp b/src/mesh/MeshPlugin.cpp index ebaee49a6..7befb6623 100644 --- a/src/mesh/MeshPlugin.cpp +++ b/src/mesh/MeshPlugin.cpp @@ -32,7 +32,7 @@ void MeshPlugin::callPlugins(const MeshPacket &mp) auto &pi = **i; pi.currentRequest = ∓ - if (pi.wantPortnum(mp.decoded.data.portnum)) { + if (pi.wantPortnum(mp.decoded.portnum)) { pluginFound = true; bool handled = pi.handleReceived(mp); @@ -50,7 +50,7 @@ void MeshPlugin::callPlugins(const MeshPacket &mp) } if(!pluginFound) - DEBUG_MSG("No plugins interested in portnum=%d\n", mp.decoded.data.portnum); + DEBUG_MSG("No plugins interested in portnum=%d\n", mp.decoded.portnum); } /** Messages can be received that have the want_response bit set. If set, this callback will be invoked diff --git a/src/mesh/MeshPlugin.h b/src/mesh/MeshPlugin.h index 01af58114..1c90f8829 100644 --- a/src/mesh/MeshPlugin.h +++ b/src/mesh/MeshPlugin.h @@ -31,6 +31,12 @@ class MeshPlugin protected: const char *name; + /* Most plugins only care about packets that are destined for their node (i.e. broadcasts or has their node as the specific recipient) + But some plugs might want to 'sniff' packets that are merely being routed (passing through the current node). Those plugins can set this to + true and their handleReceived() will be called for every packet. + */ + bool isPromiscuous = false; + /** * If this plugin is currently handling a request currentRequest will be preset * to the packet with the request. This is mostly useful for reply handlers. diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 9347ef0fd..3cc6b000b 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -4,6 +4,7 @@ #include "FS.h" +#include "Channels.h" #include "CryptoEngine.h" #include "FSCommon.h" #include "GPS.h" @@ -16,7 +17,6 @@ #include "configuration.h" #include "error.h" #include "main.h" -#include "Channels.h" #include "mesh-pb-constants.h" #include #include @@ -160,7 +160,7 @@ void NodeDB::init() loadFromDisk(); // saveToDisk(); - myNodeInfo.max_channels = MAX_CHANNELS; // tell others the max # of channels we can understand + myNodeInfo.max_channels = MAX_NUM_CHANNELS; // tell others the max # of channels we can understand myNodeInfo.error_code = CriticalErrorCode_None; // For the error code, only show values from this boot (discard value from flash) @@ -394,7 +394,7 @@ void NodeDB::updateUser(uint32_t nodeId, const User &p) void NodeDB::updateFrom(const MeshPacket &mp) { if (mp.which_payloadVariant == MeshPacket_decoded_tag) { - const SubPacket &p = mp.decoded; + const Data &p = mp.decoded; DEBUG_MSG("Update DB node 0x%x, rx_time=%u\n", mp.from, mp.rx_time); NodeInfo *info = getOrCreateNode(mp.from); @@ -406,18 +406,8 @@ void NodeDB::updateFrom(const MeshPacket &mp) info->snr = mp.rx_snr; // keep the most recent SNR we received for this node. - switch (p.which_payloadVariant) { - - case SubPacket_data_tag: { - if (mp.to == NODENUM_BROADCAST || mp.to == nodeDB.getNodeNum()) - MeshPlugin::callPlugins(mp); - break; - } - - default: { - notifyObservers(); // If the node counts have changed, notify observers - } - } + if (mp.to == NODENUM_BROADCAST || mp.to == nodeDB.getNodeNum()) + MeshPlugin::callPlugins(mp); } } diff --git a/src/mesh/ProtobufPlugin.h b/src/mesh/ProtobufPlugin.h index a5c0aea15..d931185e0 100644 --- a/src/mesh/ProtobufPlugin.h +++ b/src/mesh/ProtobufPlugin.h @@ -8,7 +8,7 @@ * If you are using protobufs to encode your packets (recommended) you can use this as a baseclass for your plugin * and avoid a bunch of boilerplate code. */ -template class ProtobufPlugin : private SinglePortPlugin +template class ProtobufPlugin : protected SinglePortPlugin { const pb_msgdesc_t *fields; @@ -38,8 +38,8 @@ template class ProtobufPlugin : private SinglePortPlugin // Update our local node info with our position (even if we don't decide to update anyone else) MeshPacket *p = allocDataPacket(); - p->decoded.data.payload.size = - pb_encode_to_bytes(p->decoded.data.payload.bytes, sizeof(p->decoded.data.payload.bytes), fields, &payload); + p->decoded.payload.size = + pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), fields, &payload); // DEBUG_MSG("did encode\n"); return p; } @@ -54,7 +54,7 @@ template class ProtobufPlugin : private SinglePortPlugin // FIXME - we currently update position data in the DB only if the message was a broadcast or destined to us // it would be better to update even if the message was destined to others. - auto &p = mp.decoded.data; + auto &p = mp.decoded; DEBUG_MSG("Received %s from=0x%0x, id=0x%x, payloadlen=%d\n", name, mp.from, mp.id, p.payload.size); T scratch; diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 0d99ca2ff..08ac40d5d 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -1,12 +1,12 @@ #include "RadioInterface.h" +#include "Channels.h" #include "MeshRadio.h" #include "MeshService.h" #include "NodeDB.h" #include "assert.h" #include "configuration.h" #include "sleep.h" -#include "Channels.h" #include #include #include @@ -122,17 +122,9 @@ void printPacket(const char *prefix, const MeshPacket *p) p->hop_limit); if (p->which_payloadVariant == MeshPacket_decoded_tag) { auto &s = p->decoded; - switch (s.which_payloadVariant) { - case SubPacket_data_tag: - DEBUG_MSG(" Portnum=%d", s.data.portnum); - break; - case 0: - DEBUG_MSG(" Payload:None"); - break; - default: - DEBUG_MSG(" Payload:%d", s.which_payloadVariant); - break; - } + + DEBUG_MSG(" Portnum=%d", s.portnum); + if (s.want_response) DEBUG_MSG(" WANTRESP"); @@ -142,10 +134,11 @@ void printPacket(const char *prefix, const MeshPacket *p) if (s.dest != 0) DEBUG_MSG(" dest=%08x", s.dest); + /* now inside Data and therefore kinda opaque if (s.which_ackVariant == SubPacket_success_id_tag) DEBUG_MSG(" successId=%08x", s.ackVariant.success_id); else if (s.which_ackVariant == SubPacket_fail_id_tag) - DEBUG_MSG(" failId=%08x", s.ackVariant.fail_id); + DEBUG_MSG(" failId=%08x", s.ackVariant.fail_id); */ } else { DEBUG_MSG(" encrypted"); } @@ -156,9 +149,9 @@ void printPacket(const char *prefix, const MeshPacket *p) if (p->rx_snr != 0.0) { DEBUG_MSG(" rxSNR=%g", p->rx_snr); } - if(p->priority != 0) + if (p->priority != 0) DEBUG_MSG(" priority=%d", p->priority); - + DEBUG_MSG(")\n"); } diff --git a/src/mesh/ReliableRouter.cpp b/src/mesh/ReliableRouter.cpp index 3bc8bfde5..3dc07c9c9 100644 --- a/src/mesh/ReliableRouter.cpp +++ b/src/mesh/ReliableRouter.cpp @@ -34,7 +34,7 @@ bool ReliableRouter::shouldFilterReceived(const MeshPacket *p) // the original sending process. if (stopRetransmission(p->from, p->id)) { DEBUG_MSG("Someone is retransmitting for us, generate implicit ack\n"); - sendAckNak(ErrorReason_NONE, p->from, p->id); + sendAckNak(Routing_Error_NONE, p->from, p->id); } } @@ -53,20 +53,20 @@ bool ReliableRouter::shouldFilterReceived(const MeshPacket *p) * * Otherwise, let superclass handle it. */ -void ReliableRouter::sniffReceived(const MeshPacket *p) +void ReliableRouter::sniffReceived(const MeshPacket *p, const Routing &c) { NodeNum ourNode = getNodeNum(); if (p->to == ourNode) { // ignore ack/nak/want_ack packets that are not address to us (we only handle 0 hop reliability // - not DSR routing) if (p->want_ack) { - sendAckNak(ErrorReason_NONE, p->from, p->id); + sendAckNak(Routing_Error_NONE, p->from, p->id); } // If the payload is valid, look for ack/nak - PacketId ackId = p->decoded.which_ackVariant == SubPacket_success_id_tag ? p->decoded.ackVariant.success_id : 0; - PacketId nakId = p->decoded.which_ackVariant == SubPacket_fail_id_tag ? p->decoded.ackVariant.fail_id : 0; + PacketId ackId = c.success_id; + PacketId nakId = c.fail_id; // We intentionally don't check wasSeenRecently, because it is harmless to delete non existent retransmission records if (ackId || nakId) { @@ -81,7 +81,7 @@ void ReliableRouter::sniffReceived(const MeshPacket *p) } // handle the packet as normal - FloodingRouter::sniffReceived(p); + FloodingRouter::sniffReceived(p, c); } #define NUM_RETRANSMISSIONS 3 @@ -155,7 +155,7 @@ int32_t ReliableRouter::doRetransmissions() if (p.numRetransmissions == 0) { DEBUG_MSG("Reliable send failed, returning a nak fr=0x%x,to=0x%x,id=%d\n", p.packet->from, p.packet->to, p.packet->id); - sendAckNak(ErrorReason_MAX_RETRANSMIT, p.packet->from, p.packet->id); + sendAckNak(Routing_Error_MAX_RETRANSMIT, p.packet->from, p.packet->id); // Note: we don't stop retransmission here, instead the Nak packet gets processed in sniffReceived - which // allows the DSR version to still be able to look at the PendingPacket stopRetransmission(it->first); diff --git a/src/mesh/ReliableRouter.h b/src/mesh/ReliableRouter.h index 62d555389..bf0338f9b 100644 --- a/src/mesh/ReliableRouter.h +++ b/src/mesh/ReliableRouter.h @@ -90,7 +90,7 @@ class ReliableRouter : public FloodingRouter /** * Look for acks/naks or someone retransmitting us */ - virtual void sniffReceived(const MeshPacket *p); + virtual void sniffReceived(const MeshPacket *p, const Routing &c); /** * Try to find the pending packet record for this ID (or NULL if not found) diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 5178e229b..f20cf02bf 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -4,6 +4,7 @@ #include "configuration.h" #include "mesh-pb-constants.h" #include +#include "plugins/RoutingPlugin.h" /** * Router todo @@ -101,27 +102,9 @@ MeshPacket *Router::allocForSending() /** * Send an ack or a nak packet back towards whoever sent idFrom */ -void Router::sendAckNak(ErrorReason err, NodeNum to, PacketId idFrom) +void Router::sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom) { - auto p = allocForSending(); - p->hop_limit = 0; // Assume just immediate neighbors for now - p->to = to; - DEBUG_MSG("Sending an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id); - - if (!err) { - p->decoded.ackVariant.success_id = idFrom; - p->decoded.which_ackVariant = SubPacket_success_id_tag; - } else { - p->decoded.ackVariant.fail_id = idFrom; - p->decoded.which_ackVariant = SubPacket_fail_id_tag; - - // Also send back the error reason - p->decoded.which_payloadVariant = SubPacket_error_reason_tag; - p->decoded.error_reason = err; - } - p->priority = MeshPacket_Priority_ACK; - - sendLocal(p); // we sometimes send directly to the local node + routingPlugin->sendAckNak(err, to, idFrom); } @@ -138,7 +121,7 @@ ErrorCode Router::sendLocal(MeshPacket *p) // ERROR! no radio found, report failure back to the client and drop the packet DEBUG_MSG("Error: No interface, returning NAK and dropping packet.\n"); - sendAckNak(ErrorReason_NO_INTERFACE, p->from, p->id); + sendAckNak(Routing_Error_NO_INTERFACE, p->from, p->id); packetPool.release(p); return ERRNO_NO_INTERFACES; @@ -162,9 +145,8 @@ ErrorCode Router::send(MeshPacket *p) { assert(p->to != nodeDB.getNodeNum()); // should have already been handled by sendLocal - PacketId nakId = p->decoded.which_ackVariant == SubPacket_fail_id_tag ? p->decoded.ackVariant.fail_id : 0; - assert( - !nakId); // I don't think we ever send 0hop naks over the wire (other than to the phone), test that assumption with assert + // PacketId nakId = p->decoded.which_ackVariant == SubPacket_fail_id_tag ? p->decoded.ackVariant.fail_id : 0; + // assert(!nakId); // I don't think we ever send 0hop naks over the wire (other than to the phone), test that assumption with assert // Never set the want_ack flag on broadcast packets sent over the air. if (p->to == NODENUM_BROADCAST) @@ -179,7 +161,7 @@ ErrorCode Router::send(MeshPacket *p) if (p->which_payloadVariant == MeshPacket_decoded_tag) { static uint8_t bytes[MAX_RHPACKETLEN]; // we have to use a scratch buffer because a union - size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), SubPacket_fields, &p->decoded); + size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), Data_fields, &p->decoded); assert(numbytes <= MAX_RHPACKETLEN); crypto->encrypt(p->from, p->id, numbytes, bytes); @@ -212,7 +194,7 @@ bool Router::cancelSending(NodeNum from, PacketId id) { * Every (non duplicate) packet this node receives will be passed through this method. This allows subclasses to * update routing tables etc... based on what we overhear (even for messages not destined to our node) */ -void Router::sniffReceived(const MeshPacket *p) +void Router::sniffReceived(const MeshPacket *p, const Routing &c) { DEBUG_MSG("FIXME-update-db Sniffing packet\n"); // FIXME, update nodedb here for any packet that passes through us @@ -234,7 +216,7 @@ bool Router::perhapsDecode(MeshPacket *p) crypto->decrypt(p->from, p->id, p->encrypted.size, bytes); // Take those raw bytes and convert them back into a well structured protobuf we can understand - if (!pb_decode_from_bytes(bytes, p->encrypted.size, SubPacket_fields, &p->decoded)) { + if (!pb_decode_from_bytes(bytes, p->encrypted.size, Data_fields, &p->decoded)) { DEBUG_MSG("Invalid protobufs in received mesh packet!\n"); return false; } else { @@ -262,7 +244,8 @@ void Router::handleReceived(MeshPacket *p) if (perhapsDecode(p)) { // parsing was successful, queue for our recipient - sniffReceived(p); + assert(0); // FIXME, call any promiscious plugins here, make a (non promisiocous) plugin for forwarding messages to phone api + // sniffReceived(p); if (p->to == NODENUM_BROADCAST || p->to == getNodeNum()) { printPacket("Delivering rx packet", p); diff --git a/src/mesh/Router.h b/src/mesh/Router.h index 3951f3062..e9a10dae1 100644 --- a/src/mesh/Router.h +++ b/src/mesh/Router.h @@ -68,6 +68,8 @@ class Router : protected concurrency::OSThread NodeNum getNodeNum(); protected: + friend class RoutingPlugin; + /** * Send a packet on a suitable interface. This routine will * later free() the packet to pool. This routine is not allowed to stall. @@ -79,6 +81,8 @@ class Router : protected concurrency::OSThread /** * Should this incoming filter be dropped? + * + * FIXME, move this into the new RoutingPlugin and do the filtering there using the regular plugin logic * * Called immedately on receiption, before any further processing. * @return true to abandon the packet @@ -89,7 +93,7 @@ class Router : protected concurrency::OSThread * Every (non duplicate) packet this node receives will be passed through this method. This allows subclasses to * update routing tables etc... based on what we overhear (even for messages not destined to our node) */ - virtual void sniffReceived(const MeshPacket *p); + virtual void sniffReceived(const MeshPacket *p, const Routing &c); /** * Remove any encryption and decode the protobufs inside this packet (if necessary). @@ -101,7 +105,7 @@ class Router : protected concurrency::OSThread /** * Send an ack or a nak packet back towards whoever sent idFrom */ - void sendAckNak(ErrorReason err, NodeNum to, PacketId idFrom); + void sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom); private: /** diff --git a/src/mesh/SinglePortPlugin.h b/src/mesh/SinglePortPlugin.h index d182579b7..5fa609dd4 100644 --- a/src/mesh/SinglePortPlugin.h +++ b/src/mesh/SinglePortPlugin.h @@ -32,8 +32,7 @@ class SinglePortPlugin : public MeshPlugin { // Update our local node info with our position (even if we don't decide to update anyone else) MeshPacket *p = router->allocForSending(); - p->decoded.which_payloadVariant = SubPacket_data_tag; - p->decoded.data.portnum = ourPortNum; + p->decoded.portnum = ourPortNum; return p; } diff --git a/src/mesh/generated/apponly.pb.c b/src/mesh/generated/apponly.pb.c index c93d63292..d6f17d7f7 100644 --- a/src/mesh/generated/apponly.pb.c +++ b/src/mesh/generated/apponly.pb.c @@ -9,4 +9,7 @@ PB_BIND(ServiceEnvelope, ServiceEnvelope, 2) +PB_BIND(ChannelSet, ChannelSet, AUTO) + + diff --git a/src/mesh/generated/apponly.pb.h b/src/mesh/generated/apponly.pb.h index fbf80324b..af527f0c8 100644 --- a/src/mesh/generated/apponly.pb.h +++ b/src/mesh/generated/apponly.pb.h @@ -11,6 +11,10 @@ #endif /* Struct definitions */ +typedef struct _ChannelSet { + pb_callback_t settings; +} ChannelSet; + typedef struct _ServiceEnvelope { bool has_packet; MeshPacket packet; @@ -25,9 +29,12 @@ extern "C" { /* Initializer values for message structs */ #define ServiceEnvelope_init_default {false, MeshPacket_init_default, {{NULL}, NULL}, {{NULL}, NULL}} +#define ChannelSet_init_default {{{NULL}, NULL}} #define ServiceEnvelope_init_zero {false, MeshPacket_init_zero, {{NULL}, NULL}, {{NULL}, NULL}} +#define ChannelSet_init_zero {{{NULL}, NULL}} /* Field tags (for use in manual encoding/decoding) */ +#define ChannelSet_settings_tag 1 #define ServiceEnvelope_packet_tag 1 #define ServiceEnvelope_channel_id_tag 2 #define ServiceEnvelope_gateway_id_tag 3 @@ -41,13 +48,22 @@ X(a, CALLBACK, SINGULAR, STRING, gateway_id, 3) #define ServiceEnvelope_DEFAULT NULL #define ServiceEnvelope_packet_MSGTYPE MeshPacket +#define ChannelSet_FIELDLIST(X, a) \ +X(a, CALLBACK, REPEATED, MESSAGE, settings, 1) +#define ChannelSet_CALLBACK pb_default_field_callback +#define ChannelSet_DEFAULT NULL +#define ChannelSet_settings_MSGTYPE ChannelSettings + extern const pb_msgdesc_t ServiceEnvelope_msg; +extern const pb_msgdesc_t ChannelSet_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define ServiceEnvelope_fields &ServiceEnvelope_msg +#define ChannelSet_fields &ChannelSet_msg /* Maximum encoded size of messages (where known) */ /* ServiceEnvelope_size depends on runtime parameters */ +/* ChannelSet_size depends on runtime parameters */ #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/deviceonly.pb.h b/src/mesh/generated/deviceonly.pb.h index e1f4c4010..47ffe2ae3 100644 --- a/src/mesh/generated/deviceonly.pb.h +++ b/src/mesh/generated/deviceonly.pb.h @@ -80,7 +80,7 @@ extern const pb_msgdesc_t DeviceState_msg; #define DeviceState_fields &DeviceState_msg /* Maximum encoded size of messages (where known) */ -#define DeviceState_size 6265 +#define DeviceState_size 6225 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/mesh.pb.c b/src/mesh/generated/mesh.pb.c index 872447623..c4fd0d8e5 100644 --- a/src/mesh/generated/mesh.pb.c +++ b/src/mesh/generated/mesh.pb.c @@ -9,16 +9,16 @@ PB_BIND(Position, Position, AUTO) -PB_BIND(Data, Data, AUTO) - - PB_BIND(User, User, AUTO) PB_BIND(RouteDiscovery, RouteDiscovery, AUTO) -PB_BIND(SubPacket, SubPacket, 2) +PB_BIND(Routing, Routing, AUTO) + + +PB_BIND(Data, Data, 2) PB_BIND(MeshPacket, MeshPacket, 2) diff --git a/src/mesh/generated/mesh.pb.h b/src/mesh/generated/mesh.pb.h index 691b4cd78..ca47ffa89 100644 --- a/src/mesh/generated/mesh.pb.h +++ b/src/mesh/generated/mesh.pb.h @@ -11,15 +11,6 @@ #endif /* Enum definitions */ -typedef enum _ErrorReason { - ErrorReason_NONE = 0, - ErrorReason_NO_ROUTE = 1, - ErrorReason_GOT_NAK = 2, - ErrorReason_TIMEOUT = 3, - ErrorReason_NO_INTERFACE = 4, - ErrorReason_MAX_RETRANSMIT = 5 -} ErrorReason; - typedef enum _Constants { Constants_Unused = 0, Constants_DATA_PAYLOAD_LEN = 240 @@ -83,6 +74,15 @@ typedef enum _CriticalErrorCode { CriticalErrorCode_TransmitFailed = 8 } CriticalErrorCode; +typedef enum _Routing_Error { + Routing_Error_NONE = 0, + Routing_Error_NO_ROUTE = 1, + Routing_Error_GOT_NAK = 2, + Routing_Error_TIMEOUT = 3, + Routing_Error_NO_INTERFACE = 4, + Routing_Error_MAX_RETRANSMIT = 5 +} Routing_Error; + typedef enum _MeshPacket_Priority { MeshPacket_Priority_UNSET = 0, MeshPacket_Priority_MIN = 1, @@ -136,6 +136,9 @@ typedef PB_BYTES_ARRAY_T(240) Data_payload_t; typedef struct _Data { PortNum portnum; Data_payload_t payload; + bool want_response; + uint32_t dest; + uint32_t source; } Data; typedef struct _LogRecord { @@ -216,7 +219,7 @@ typedef struct _RadioConfig_UserPreferences { typedef struct _RouteDiscovery { pb_size_t route_count; - int32_t route[8]; + uint32_t route[8]; } RouteDiscovery; typedef struct _User { @@ -233,6 +236,24 @@ typedef struct _Channel { Channel_Role role; } Channel; +typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t; +typedef struct _MeshPacket { + uint32_t from; + uint32_t to; + pb_size_t which_payloadVariant; + union { + Data decoded; + MeshPacket_encrypted_t encrypted; + }; + uint32_t channel_index; + uint32_t id; + float rx_snr; + uint32_t rx_time; + uint32_t hop_limit; + bool want_ack; + MeshPacket_Priority priority; +} MeshPacket; + typedef struct _NodeInfo { uint32_t num; bool has_user; @@ -248,48 +269,22 @@ typedef struct _RadioConfig { RadioConfig_UserPreferences preferences; } RadioConfig; -typedef struct _SubPacket { - uint32_t original_id; - pb_size_t which_payloadVariant; +typedef struct _Routing { + pb_size_t which_variant; union { - Data data; RouteDiscovery route_request; RouteDiscovery route_reply; - ErrorReason error_reason; - }; - bool want_response; - uint32_t dest; - pb_size_t which_ackVariant; - union { + Routing_Error error_reason; uint32_t success_id; uint32_t fail_id; - } ackVariant; - uint32_t source; -} SubPacket; - -typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t; -typedef struct _MeshPacket { - uint32_t from; - uint32_t to; - pb_size_t which_payloadVariant; - union { - SubPacket decoded; - MeshPacket_encrypted_t encrypted; }; - uint32_t channel_index; - uint32_t id; - float rx_snr; - uint32_t rx_time; - uint32_t hop_limit; - bool want_ack; - MeshPacket_Priority priority; -} MeshPacket; + uint32_t original_id; +} Routing; typedef struct _FromRadio { uint32_t num; pb_size_t which_payloadVariant; union { - MeshPacket packet; MyNodeInfo my_info; NodeInfo node_info; RadioConfig radio; @@ -297,6 +292,7 @@ typedef struct _FromRadio { uint32_t config_complete_id; bool rebooted; Channel channel; + MeshPacket packet; }; } FromRadio; @@ -313,10 +309,6 @@ typedef struct _ToRadio { /* Helper constants for enums */ -#define _ErrorReason_MIN ErrorReason_NONE -#define _ErrorReason_MAX ErrorReason_MAX_RETRANSMIT -#define _ErrorReason_ARRAYSIZE ((ErrorReason)(ErrorReason_MAX_RETRANSMIT+1)) - #define _Constants_MIN Constants_Unused #define _Constants_MAX Constants_DATA_PAYLOAD_LEN #define _Constants_ARRAYSIZE ((Constants)(Constants_DATA_PAYLOAD_LEN+1)) @@ -341,6 +333,10 @@ typedef struct _ToRadio { #define _CriticalErrorCode_MAX CriticalErrorCode_TransmitFailed #define _CriticalErrorCode_ARRAYSIZE ((CriticalErrorCode)(CriticalErrorCode_TransmitFailed+1)) +#define _Routing_Error_MIN Routing_Error_NONE +#define _Routing_Error_MAX Routing_Error_MAX_RETRANSMIT +#define _Routing_Error_ARRAYSIZE ((Routing_Error)(Routing_Error_MAX_RETRANSMIT+1)) + #define _MeshPacket_Priority_MIN MeshPacket_Priority_UNSET #define _MeshPacket_Priority_MAX MeshPacket_Priority_MAX #define _MeshPacket_Priority_ARRAYSIZE ((MeshPacket_Priority)(MeshPacket_Priority_MAX+1)) @@ -364,11 +360,11 @@ extern "C" { /* Initializer values for message structs */ #define Position_init_default {0, 0, 0, 0, 0} -#define Data_init_default {_PortNum_MIN, {0, {0}}} #define User_init_default {"", "", "", {0}} #define RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}} -#define SubPacket_init_default {0, 0, {Data_init_default}, 0, 0, 0, {0}, 0} -#define MeshPacket_init_default {0, 0, 0, {SubPacket_init_default}, 0, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} +#define Routing_init_default {0, {RouteDiscovery_init_default}, 0} +#define Data_init_default {_PortNum_MIN, {0, {0}}, 0, 0, 0} +#define MeshPacket_init_default {0, 0, 0, {Data_init_default}, 0, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} #define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} #define Channel_init_default {0, false, ChannelSettings_init_default, _Channel_Role_MIN} #define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default} @@ -376,14 +372,14 @@ extern "C" { #define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0} #define MyNodeInfo_init_default {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0} #define LogRecord_init_default {"", 0, "", _LogRecord_Level_MIN} -#define FromRadio_init_default {0, 0, {MeshPacket_init_default}} +#define FromRadio_init_default {0, 0, {MyNodeInfo_init_default}} #define ToRadio_init_default {0, {MeshPacket_init_default}} #define Position_init_zero {0, 0, 0, 0, 0} -#define Data_init_zero {_PortNum_MIN, {0, {0}}} #define User_init_zero {"", "", "", {0}} #define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}} -#define SubPacket_init_zero {0, 0, {Data_init_zero}, 0, 0, 0, {0}, 0} -#define MeshPacket_init_zero {0, 0, 0, {SubPacket_init_zero}, 0, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} +#define Routing_init_zero {0, {RouteDiscovery_init_zero}, 0} +#define Data_init_zero {_PortNum_MIN, {0, {0}}, 0, 0, 0} +#define MeshPacket_init_zero {0, 0, 0, {Data_init_zero}, 0, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} #define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} #define Channel_init_zero {0, false, ChannelSettings_init_zero, _Channel_Role_MIN} #define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero} @@ -391,7 +387,7 @@ extern "C" { #define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0} #define MyNodeInfo_init_zero {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0} #define LogRecord_init_zero {"", 0, "", _LogRecord_Level_MIN} -#define FromRadio_init_zero {0, 0, {MeshPacket_init_zero}} +#define FromRadio_init_zero {0, 0, {MyNodeInfo_init_zero}} #define ToRadio_init_zero {0, {MeshPacket_init_zero}} /* Field tags (for use in manual encoding/decoding) */ @@ -408,6 +404,9 @@ extern "C" { #define ChannelSettings_downlink_enabled_tag 17 #define Data_portnum_tag 1 #define Data_payload_tag 2 +#define Data_want_response_tag 5 +#define Data_dest_tag 9 +#define Data_source_tag 12 #define LogRecord_message_tag 1 #define LogRecord_time_tag 2 #define LogRecord_source_tag 3 @@ -479,22 +478,6 @@ extern "C" { #define Channel_index_tag 1 #define Channel_settings_tag 2 #define Channel_role_tag 3 -#define NodeInfo_num_tag 1 -#define NodeInfo_user_tag 2 -#define NodeInfo_position_tag 3 -#define NodeInfo_next_hop_tag 5 -#define NodeInfo_snr_tag 7 -#define RadioConfig_preferences_tag 1 -#define SubPacket_original_id_tag 2 -#define SubPacket_data_tag 3 -#define SubPacket_route_request_tag 6 -#define SubPacket_route_reply_tag 7 -#define SubPacket_error_reason_tag 13 -#define SubPacket_want_response_tag 5 -#define SubPacket_dest_tag 9 -#define SubPacket_success_id_tag 10 -#define SubPacket_fail_id_tag 11 -#define SubPacket_source_tag 12 #define MeshPacket_from_tag 1 #define MeshPacket_to_tag 2 #define MeshPacket_decoded_tag 3 @@ -506,8 +489,19 @@ extern "C" { #define MeshPacket_hop_limit_tag 10 #define MeshPacket_want_ack_tag 11 #define MeshPacket_priority_tag 12 +#define NodeInfo_num_tag 1 +#define NodeInfo_user_tag 2 +#define NodeInfo_position_tag 3 +#define NodeInfo_next_hop_tag 5 +#define NodeInfo_snr_tag 7 +#define RadioConfig_preferences_tag 1 +#define Routing_route_request_tag 1 +#define Routing_route_reply_tag 2 +#define Routing_error_reason_tag 3 +#define Routing_success_id_tag 4 +#define Routing_fail_id_tag 5 +#define Routing_original_id_tag 6 #define FromRadio_num_tag 1 -#define FromRadio_packet_tag 2 #define FromRadio_my_info_tag 3 #define FromRadio_node_info_tag 4 #define FromRadio_radio_tag 6 @@ -515,7 +509,8 @@ extern "C" { #define FromRadio_config_complete_id_tag 8 #define FromRadio_rebooted_tag 9 #define FromRadio_channel_tag 10 -#define ToRadio_packet_tag 1 +#define FromRadio_packet_tag 11 +#define ToRadio_packet_tag 2 #define ToRadio_want_config_id_tag 100 #define ToRadio_set_radio_tag 101 #define ToRadio_set_owner_tag 102 @@ -531,12 +526,6 @@ X(a, STATIC, SINGULAR, FIXED32, time, 9) #define Position_CALLBACK NULL #define Position_DEFAULT NULL -#define Data_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UENUM, portnum, 1) \ -X(a, STATIC, SINGULAR, BYTES, payload, 2) -#define Data_CALLBACK NULL -#define Data_DEFAULT NULL - #define User_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, id, 1) \ X(a, STATIC, SINGULAR, STRING, long_name, 2) \ @@ -546,34 +535,38 @@ X(a, STATIC, SINGULAR, FIXED_LENGTH_BYTES, macaddr, 4) #define User_DEFAULT NULL #define RouteDiscovery_FIELDLIST(X, a) \ -X(a, STATIC, REPEATED, INT32, route, 2) +X(a, STATIC, REPEATED, FIXED32, route, 2) #define RouteDiscovery_CALLBACK NULL #define RouteDiscovery_DEFAULT NULL -#define SubPacket_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, original_id, 2) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,data,data), 3) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,route_request,route_request), 6) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,route_reply,route_reply), 7) \ -X(a, STATIC, ONEOF, UENUM, (payloadVariant,error_reason,error_reason), 13) \ +#define Routing_FIELDLIST(X, a) \ +X(a, STATIC, ONEOF, MESSAGE, (variant,route_request,route_request), 1) \ +X(a, STATIC, ONEOF, MESSAGE, (variant,route_reply,route_reply), 2) \ +X(a, STATIC, ONEOF, UENUM, (variant,error_reason,error_reason), 3) \ +X(a, STATIC, ONEOF, FIXED32, (variant,success_id,success_id), 4) \ +X(a, STATIC, ONEOF, FIXED32, (variant,fail_id,fail_id), 5) \ +X(a, STATIC, SINGULAR, FIXED32, original_id, 6) +#define Routing_CALLBACK NULL +#define Routing_DEFAULT NULL +#define Routing_variant_route_request_MSGTYPE RouteDiscovery +#define Routing_variant_route_reply_MSGTYPE RouteDiscovery + +#define Data_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, portnum, 1) \ +X(a, STATIC, SINGULAR, BYTES, payload, 2) \ X(a, STATIC, SINGULAR, BOOL, want_response, 5) \ -X(a, STATIC, SINGULAR, UINT32, dest, 9) \ -X(a, STATIC, ONEOF, UINT32, (ackVariant,success_id,ackVariant.success_id), 10) \ -X(a, STATIC, ONEOF, UINT32, (ackVariant,fail_id,ackVariant.fail_id), 11) \ -X(a, STATIC, SINGULAR, UINT32, source, 12) -#define SubPacket_CALLBACK NULL -#define SubPacket_DEFAULT NULL -#define SubPacket_payloadVariant_data_MSGTYPE Data -#define SubPacket_payloadVariant_route_request_MSGTYPE RouteDiscovery -#define SubPacket_payloadVariant_route_reply_MSGTYPE RouteDiscovery +X(a, STATIC, SINGULAR, FIXED32, dest, 9) \ +X(a, STATIC, SINGULAR, FIXED32, source, 12) +#define Data_CALLBACK NULL +#define Data_DEFAULT NULL #define MeshPacket_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, from, 1) \ -X(a, STATIC, SINGULAR, UINT32, to, 2) \ +X(a, STATIC, SINGULAR, FIXED32, from, 1) \ +X(a, STATIC, SINGULAR, FIXED32, to, 2) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,decoded,decoded), 3) \ X(a, STATIC, ONEOF, BYTES, (payloadVariant,encrypted,encrypted), 8) \ X(a, STATIC, SINGULAR, UINT32, channel_index, 4) \ -X(a, STATIC, SINGULAR, UINT32, id, 6) \ +X(a, STATIC, SINGULAR, FIXED32, id, 6) \ X(a, STATIC, SINGULAR, FLOAT, rx_snr, 7) \ X(a, STATIC, SINGULAR, FIXED32, rx_time, 9) \ X(a, STATIC, SINGULAR, UINT32, hop_limit, 10) \ @@ -581,7 +574,7 @@ X(a, STATIC, SINGULAR, BOOL, want_ack, 11) \ X(a, STATIC, SINGULAR, UENUM, priority, 12) #define MeshPacket_CALLBACK NULL #define MeshPacket_DEFAULT NULL -#define MeshPacket_payloadVariant_decoded_MSGTYPE SubPacket +#define MeshPacket_payloadVariant_decoded_MSGTYPE Data #define ChannelSettings_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, INT32, tx_power, 1) \ @@ -695,25 +688,25 @@ X(a, STATIC, SINGULAR, UENUM, level, 4) #define FromRadio_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, num, 1) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,packet,packet), 2) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,my_info,my_info), 3) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,node_info,node_info), 4) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,radio,radio), 6) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,log_record,log_record), 7) \ X(a, STATIC, ONEOF, UINT32, (payloadVariant,config_complete_id,config_complete_id), 8) \ X(a, STATIC, ONEOF, BOOL, (payloadVariant,rebooted,rebooted), 9) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,channel,channel), 10) +X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,channel,channel), 10) \ +X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,packet,packet), 11) #define FromRadio_CALLBACK NULL #define FromRadio_DEFAULT NULL -#define FromRadio_payloadVariant_packet_MSGTYPE MeshPacket #define FromRadio_payloadVariant_my_info_MSGTYPE MyNodeInfo #define FromRadio_payloadVariant_node_info_MSGTYPE NodeInfo #define FromRadio_payloadVariant_radio_MSGTYPE RadioConfig #define FromRadio_payloadVariant_log_record_MSGTYPE LogRecord #define FromRadio_payloadVariant_channel_MSGTYPE Channel +#define FromRadio_payloadVariant_packet_MSGTYPE MeshPacket #define ToRadio_FIELDLIST(X, a) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,packet,packet), 1) \ +X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,packet,packet), 2) \ X(a, STATIC, ONEOF, UINT32, (payloadVariant,want_config_id,want_config_id), 100) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,set_radio,set_radio), 101) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,set_owner,set_owner), 102) \ @@ -726,10 +719,10 @@ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,set_channel,set_channel), 104 #define ToRadio_payloadVariant_set_channel_MSGTYPE Channel extern const pb_msgdesc_t Position_msg; -extern const pb_msgdesc_t Data_msg; extern const pb_msgdesc_t User_msg; extern const pb_msgdesc_t RouteDiscovery_msg; -extern const pb_msgdesc_t SubPacket_msg; +extern const pb_msgdesc_t Routing_msg; +extern const pb_msgdesc_t Data_msg; extern const pb_msgdesc_t MeshPacket_msg; extern const pb_msgdesc_t ChannelSettings_msg; extern const pb_msgdesc_t Channel_msg; @@ -743,10 +736,10 @@ extern const pb_msgdesc_t ToRadio_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define Position_fields &Position_msg -#define Data_fields &Data_msg #define User_fields &User_msg #define RouteDiscovery_fields &RouteDiscovery_msg -#define SubPacket_fields &SubPacket_msg +#define Routing_fields &Routing_msg +#define Data_fields &Data_msg #define MeshPacket_fields &MeshPacket_msg #define ChannelSettings_fields &ChannelSettings_msg #define Channel_fields &Channel_msg @@ -760,11 +753,11 @@ extern const pb_msgdesc_t ToRadio_msg; /* Maximum encoded size of messages (where known) */ #define Position_size 37 -#define Data_size 246 #define User_size 72 -#define RouteDiscovery_size 88 -#define SubPacket_size 275 -#define MeshPacket_size 322 +#define RouteDiscovery_size 40 +#define Routing_size 47 +#define Data_size 258 +#define MeshPacket_size 302 #define ChannelSettings_size 95 #define Channel_size 105 #define RadioConfig_size 308 @@ -772,8 +765,8 @@ extern const pb_msgdesc_t ToRadio_msg; #define NodeInfo_size 130 #define MyNodeInfo_size 89 #define LogRecord_size 81 -#define FromRadio_size 331 -#define ToRadio_size 325 +#define FromRadio_size 317 +#define ToRadio_size 312 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/portnums.pb.h b/src/mesh/generated/portnums.pb.h index 2133ecaa7..72360f295 100644 --- a/src/mesh/generated/portnums.pb.h +++ b/src/mesh/generated/portnums.pb.h @@ -16,6 +16,7 @@ typedef enum _PortNum { PortNum_REMOTE_HARDWARE_APP = 2, PortNum_POSITION_APP = 3, PortNum_NODEINFO_APP = 4, + PortNum_ROUTING_APP = 5, PortNum_REPLY_APP = 32, PortNum_IP_TUNNEL_APP = 33, PortNum_SERIAL_APP = 64, diff --git a/src/mesh/mesh-pb-constants.h b/src/mesh/mesh-pb-constants.h index ed1c4f7e8..21163c496 100644 --- a/src/mesh/mesh-pb-constants.h +++ b/src/mesh/mesh-pb-constants.h @@ -17,7 +17,7 @@ #define MAX_NUM_NODES (member_size(DeviceState, node_db) / member_size(DeviceState, node_db[0])) /// Max number of channels allowed -#define MAX_CHANNELS (member_size(DeviceState, channels) / member_size(DeviceState, channels[0])) +#define MAX_NUM_CHANNELS (member_size(DeviceState, channels) / member_size(DeviceState, channels[0])) /// helper function for encoding a record as a protobuf, any failures to encode are fatal and we will panic /// returns the encoded packet size diff --git a/src/plugins/Plugins.cpp b/src/plugins/Plugins.cpp index ac8dd7336..65cfdcee4 100644 --- a/src/plugins/Plugins.cpp +++ b/src/plugins/Plugins.cpp @@ -7,12 +7,14 @@ #include "plugins/SerialPlugin.h" #include "plugins/StoreForwardPlugin.h" #include "plugins/TextMessagePlugin.h" +#include "plugins/RoutingPlugin.h" /** * Create plugin instances here. If you are adding a new plugin, you must 'new' it here (or somewhere else) */ void setupPlugins() { + routingPlugin = new RoutingPlugin(); nodeInfoPlugin = new NodeInfoPlugin(); positionPlugin = new PositionPlugin(); textMessagePlugin = new TextMessagePlugin(); diff --git a/src/plugins/RangeTestPlugin.cpp b/src/plugins/RangeTestPlugin.cpp index 58150f5bb..dc5f30048 100644 --- a/src/plugins/RangeTestPlugin.cpp +++ b/src/plugins/RangeTestPlugin.cpp @@ -108,8 +108,8 @@ void RangeTestPluginRadio::sendPayload(NodeNum dest, bool wantReplies) static char heartbeatString[20]; snprintf(heartbeatString, sizeof(heartbeatString), "seq %d", packetSequence); - p->decoded.data.payload.size = strlen(heartbeatString); // You must specify how many bytes are in the reply - memcpy(p->decoded.data.payload.bytes, heartbeatString, p->decoded.data.payload.size); + p->decoded.payload.size = strlen(heartbeatString); // You must specify how many bytes are in the reply + memcpy(p->decoded.payload.bytes, heartbeatString, p->decoded.payload.size); service.sendToMesh(p); } diff --git a/src/plugins/ReplyPlugin.cpp b/src/plugins/ReplyPlugin.cpp index a8c607436..69903aa36 100644 --- a/src/plugins/ReplyPlugin.cpp +++ b/src/plugins/ReplyPlugin.cpp @@ -9,7 +9,7 @@ MeshPacket *ReplyPlugin::allocReply() { assert(currentRequest); // should always be !NULL auto req = *currentRequest; - auto &p = req.decoded.data; + auto &p = req.decoded; // The incoming message is in p.payload DEBUG_MSG("Received message from=0x%0x, id=%d, msg=%.*s\n", req.from, req.id, p.payload.size, p.payload.bytes); @@ -17,8 +17,8 @@ MeshPacket *ReplyPlugin::allocReply() const char *replyStr = "Message Received"; auto reply = allocDataPacket(); // Allocate a packet for sending - reply->decoded.data.payload.size = strlen(replyStr); // You must specify how many bytes are in the reply - memcpy(reply->decoded.data.payload.bytes, replyStr, reply->decoded.data.payload.size); + reply->decoded.payload.size = strlen(replyStr); // You must specify how many bytes are in the reply + memcpy(reply->decoded.payload.bytes, replyStr, reply->decoded.payload.size); return reply; } diff --git a/src/plugins/RoutingPlugin.cpp b/src/plugins/RoutingPlugin.cpp new file mode 100644 index 000000000..6f4c2123b --- /dev/null +++ b/src/plugins/RoutingPlugin.cpp @@ -0,0 +1,54 @@ +#include "RoutingPlugin.h" +#include "MeshService.h" +#include "NodeDB.h" +#include "RTC.h" +#include "Router.h" +#include "configuration.h" +#include "main.h" + +RoutingPlugin *routingPlugin; + +bool RoutingPlugin::handleReceivedProtobuf(const MeshPacket &mp, const Routing &p) +{ + + return false; // Let others look at this message also if they want +} + + +MeshPacket *RoutingPlugin::allocReply() +{ + assert(0); // 1.2 refactoring fixme, Not sure if anything needs this yet? + // return allocDataProtobuf(u); + return NULL; +} + +void RoutingPlugin::sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom) +{ + Routing c = Routing_init_default; + + if (!err) { + c.success_id = idFrom; + } else { + c.fail_id = idFrom; + + // Also send back the error reason + c.error_reason = err; + } + + auto p = allocDataProtobuf(c); + p->priority = MeshPacket_Priority_ACK; + + p->hop_limit = 0; // Assume just immediate neighbors for now + p->to = to; + DEBUG_MSG("Sending an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id); + + router->sendLocal(p); // we sometimes send directly to the local node +} + +RoutingPlugin::RoutingPlugin() + : ProtobufPlugin("routing", PortNum_ROUTING_APP, User_fields) +{ + isPromiscuous = true; +} + + diff --git a/src/plugins/RoutingPlugin.h b/src/plugins/RoutingPlugin.h new file mode 100644 index 000000000..080b8fe12 --- /dev/null +++ b/src/plugins/RoutingPlugin.h @@ -0,0 +1,31 @@ +#pragma once +#include "ProtobufPlugin.h" + +/** + * Routing plugin for router control messages + */ +class RoutingPlugin : public ProtobufPlugin +{ + public: + /** Constructor + * name is for debugging output + */ + RoutingPlugin(); + + protected: + friend class Router; + + /** Called to handle a particular incoming message + + @return true if you've guaranteed you've handled this message and no other handlers should be considered for it + */ + virtual bool handleReceivedProtobuf(const MeshPacket &mp, const Routing &p); + + /** Messages can be received that have the want_response bit set. If set, this callback will be invoked + * so that subclasses can (optionally) send a response back to the original sender. */ + virtual MeshPacket *allocReply(); + + void sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom); +}; + +extern RoutingPlugin *routingPlugin; \ No newline at end of file diff --git a/src/plugins/SerialPlugin.cpp b/src/plugins/SerialPlugin.cpp index 47f279089..a3493c880 100644 --- a/src/plugins/SerialPlugin.cpp +++ b/src/plugins/SerialPlugin.cpp @@ -144,8 +144,8 @@ void SerialPluginRadio::sendPayload(NodeNum dest, bool wantReplies) p->want_ack = SERIALPLUGIN_ACK; - p->decoded.data.payload.size = strlen(serialStringChar); // You must specify how many bytes are in the reply - memcpy(p->decoded.data.payload.bytes, serialStringChar, p->decoded.data.payload.size); + p->decoded.payload.size = strlen(serialStringChar); // You must specify how many bytes are in the reply + memcpy(p->decoded.payload.bytes, serialStringChar, p->decoded.payload.size); service.sendToMesh(p); } diff --git a/src/plugins/TextMessagePlugin.cpp b/src/plugins/TextMessagePlugin.cpp index 4ad080702..8da2a10f9 100644 --- a/src/plugins/TextMessagePlugin.cpp +++ b/src/plugins/TextMessagePlugin.cpp @@ -7,7 +7,7 @@ TextMessagePlugin *textMessagePlugin; bool TextMessagePlugin::handleReceived(const MeshPacket &mp) { - auto &p = mp.decoded.data; + auto &p = mp.decoded; DEBUG_MSG("Received text msg from=0x%0x, id=%d, msg=%.*s\n", mp.from, mp.id, p.payload.size, p.payload.bytes); // We only store/display messages destined for us. From f064e56dc944114ed1a489c6ca73409a1505338a Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Wed, 17 Feb 2021 16:17:46 +0800 Subject: [PATCH 04/35] fix esp32 build for dev1.2 --- docs/software/TODO.md | 9 +++++++-- platformio.ini | 1 + proto | 2 +- src/plugins/ExternalNotificationPlugin.cpp | 2 +- src/plugins/RangeTestPlugin.cpp | 2 +- src/plugins/SerialPlugin.cpp | 2 +- src/plugins/StoreForwardPlugin.cpp | 2 +- 7 files changed, 13 insertions(+), 7 deletions(-) diff --git a/docs/software/TODO.md b/docs/software/TODO.md index c4569cbda..c15c837f3 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -4,16 +4,21 @@ You probably don't care about this section - skip to the next one. 1.2 cleanup & multichannel: +* clear priority before sending (to keep wire size small) +* generate channel hash from the name of the channel+the psk (not just one or the other) * DONE remove deprecated -* allow chaning packets in single transmission * DONE fix setchannel in phoneapi.cpp * DONE set mynodeinfo.max_channels * DONE set mynodeinfo.num_bands (formerly num_channels) * fix sniffing of non Routing packets -* move portnum up? +* DONE move portnum up? * scrub protobufs to make sure they are absoloute minimum wiresize (in particular packets, ChannelSets and positions) * send a hint that can be used to select which channel to try and hash against with each message * change syncword +* allow chaning packets in single transmission - to increase airtime efficiency and amortize packet overhead +* move #define PACKET_FLAGS_HOP_MASK PACKET_FLAGS_WANT_ACK_MASK out of wire header, instead include keyHint. shrink header len to 14 bytes. +* move most parts of meshpacket into the Data packet, so that we can chain multiple Data for sending when they all have a common destination and key. +when selecting a MeshPacket for transmit, scan the TX queue for any Data packets we can merge together. * DONE move acks into routing * DONE make all subpackets different versions of data * DONE move routing control into a data packet diff --git a/platformio.ini b/platformio.ini index 4b91317d9..c29fe0e0f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -15,6 +15,7 @@ default_envs = tbeam ;default_envs = tlora-v1 ;default_envs = tlora-v2 ;default_envs = lora-relay-v1 # nrf board +;default_envs = eink ;default_envs = linux # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here [common] diff --git a/proto b/proto index 65914b84f..527b0fdc3 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 65914b84f1ee8f25807187d60b43ad29dfbaedc3 +Subproject commit 527b0fdc343f89843158977a1c1a7c14db854565 diff --git a/src/plugins/ExternalNotificationPlugin.cpp b/src/plugins/ExternalNotificationPlugin.cpp index 505eff7d1..84822f1d9 100644 --- a/src/plugins/ExternalNotificationPlugin.cpp +++ b/src/plugins/ExternalNotificationPlugin.cpp @@ -145,7 +145,7 @@ bool ExternalNotificationPluginRadio::handleReceived(const MeshPacket &mp) if (radioConfig.preferences.ext_notification_plugin_enabled) { - auto &p = mp.decoded.data; + auto &p = mp.decoded; if (mp.from != nodeDB.getNodeNum()) { diff --git a/src/plugins/RangeTestPlugin.cpp b/src/plugins/RangeTestPlugin.cpp index dc5f30048..e277f70e9 100644 --- a/src/plugins/RangeTestPlugin.cpp +++ b/src/plugins/RangeTestPlugin.cpp @@ -120,7 +120,7 @@ bool RangeTestPluginRadio::handleReceived(const MeshPacket &mp) if (radioConfig.preferences.range_test_plugin_enabled) { - auto &p = mp.decoded.data; + auto &p = mp.decoded; // DEBUG_MSG("Received text msg self=0x%0x, from=0x%0x, to=0x%0x, id=%d, msg=%.*s\n", // nodeDB.getNodeNum(), mp.from, mp.to, mp.id, p.payload.size, p.payload.bytes); diff --git a/src/plugins/SerialPlugin.cpp b/src/plugins/SerialPlugin.cpp index a3493c880..060f05ba1 100644 --- a/src/plugins/SerialPlugin.cpp +++ b/src/plugins/SerialPlugin.cpp @@ -156,7 +156,7 @@ bool SerialPluginRadio::handleReceived(const MeshPacket &mp) if (radioConfig.preferences.serialplugin_enabled) { - auto &p = mp.decoded.data; + auto &p = mp.decoded; // DEBUG_MSG("Received text msg self=0x%0x, from=0x%0x, to=0x%0x, id=%d, msg=%.*s\n", // nodeDB.getNodeNum(), mp.from, mp.to, mp.id, p.payload.size, p.payload.bytes); diff --git a/src/plugins/StoreForwardPlugin.cpp b/src/plugins/StoreForwardPlugin.cpp index f71fb965b..73df054e8 100644 --- a/src/plugins/StoreForwardPlugin.cpp +++ b/src/plugins/StoreForwardPlugin.cpp @@ -118,7 +118,7 @@ bool StoreForwardPluginRadio::handleReceived(const MeshPacket &mp) if (STOREFORWARDPLUGIN_ENABLED) { - auto &p = mp.decoded.data; + auto &p = mp.decoded; // DEBUG_MSG("Received text msg self=0x%0x, from=0x%0x, to=0x%0x, id=%d, msg=%.*s\n", // nodeDB.getNodeNum(), mp.from, mp.to, mp.id, p.payload.size, p.payload.bytes); From 60a01567d9e7d5275bdcce2c88694efa95060e34 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Wed, 17 Feb 2021 19:01:20 +0800 Subject: [PATCH 05/35] remove region specific builds --- bin/build-all.sh | 4 +++- docs/software/TODO.md | 13 ++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/bin/build-all.sh b/bin/build-all.sh index c4d48b122..fb14156df 100755 --- a/bin/build-all.sh +++ b/bin/build-all.sh @@ -4,7 +4,9 @@ set -e VERSION=`bin/buildinfo.py` -COUNTRIES="US EU433 EU865 CN JP ANZ KR" +# We now only do regionless builds +COUNTRIES="" +#COUNTRIES="US EU433 EU865 CN JP ANZ KR" #COUNTRIES=US #COUNTRIES=CN diff --git a/docs/software/TODO.md b/docs/software/TODO.md index c15c837f3..8f1b07625 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -2,8 +2,9 @@ You probably don't care about this section - skip to the next one. -1.2 cleanup & multichannel: +1.2 cleanup & multichannel support: +* call RouterPlugin for *all* packets - not just Router packets * clear priority before sending (to keep wire size small) * generate channel hash from the name of the channel+the psk (not just one or the other) * DONE remove deprecated @@ -12,13 +13,15 @@ You probably don't care about this section - skip to the next one. * DONE set mynodeinfo.num_bands (formerly num_channels) * fix sniffing of non Routing packets * DONE move portnum up? +* DONE remove region specific builds from the firmware +* add gui in android app for setting region * scrub protobufs to make sure they are absoloute minimum wiresize (in particular packets, ChannelSets and positions) * send a hint that can be used to select which channel to try and hash against with each message * change syncword * allow chaning packets in single transmission - to increase airtime efficiency and amortize packet overhead -* move #define PACKET_FLAGS_HOP_MASK PACKET_FLAGS_WANT_ACK_MASK out of wire header, instead include keyHint. shrink header len to 14 bytes. -* move most parts of meshpacket into the Data packet, so that we can chain multiple Data for sending when they all have a common destination and key. -when selecting a MeshPacket for transmit, scan the TX queue for any Data packets we can merge together. +* DONE move most parts of meshpacket into the Data packet, so that we can chain multiple Data for sending when they all have a common destination and key. +* when selecting a MeshPacket for transmit, scan the TX queue for any Data packets we can merge together as a WirePayload. In the low level send/rx code expand that into multiple MeshPackets as needed (thus 'hiding' from MeshPacket that over the wire we send multiple datapackets +* confirm we are still calling the plugins for messages inbound from the phone (or generated locally) * DONE move acks into routing * DONE make all subpackets different versions of data * DONE move routing control into a data packet @@ -31,7 +34,7 @@ when selecting a MeshPacket for transmit, scan the TX queue for any Data packets * add channel restrictions for plugins (and restrict routing plugin to the "control" channel) * make a primaryChannel global and properly maintain it when the phone sends setChannel * move setCrypto call into packet send and packet decode code -* implement'small locations' change? +* implement 'small location diffs' change * move battery level out of position? * DOUBLE CHECK android app can still upgrade 1.1 and 1.0 loads From 69a11e7375efa1624f1a884b0a35ca80e47b9fdf Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Wed, 17 Feb 2021 19:04:41 +0800 Subject: [PATCH 06/35] WIP phone api changes for dev1.2 --- src/mesh/MeshPlugin.cpp | 25 +++++++++---- src/mesh/MeshPlugin.h | 2 +- src/mesh/MeshService.cpp | 1 - src/mesh/MeshService.h | 2 -- src/mesh/NodeDB.cpp | 9 +++-- src/mesh/ProtobufPlugin.h | 16 ++++++--- src/mesh/Router.cpp | 5 +-- src/mesh/Router.h | 4 --- src/mesh/SinglePortPlugin.h | 2 +- src/mesh/generated/mesh.pb.h | 52 ++++++++++++++-------------- src/plugins/NodeInfoPlugin.cpp | 6 ++-- src/plugins/NodeInfoPlugin.h | 2 +- src/plugins/PositionPlugin.cpp | 6 ++-- src/plugins/PositionPlugin.h | 2 +- src/plugins/RemoteHardwarePlugin.cpp | 3 +- src/plugins/RemoteHardwarePlugin.h | 2 +- src/plugins/RoutingPlugin.cpp | 4 +-- src/plugins/RoutingPlugin.h | 2 +- 18 files changed, 82 insertions(+), 63 deletions(-) diff --git a/src/mesh/MeshPlugin.cpp b/src/mesh/MeshPlugin.cpp index 7befb6623..763d4d46e 100644 --- a/src/mesh/MeshPlugin.cpp +++ b/src/mesh/MeshPlugin.cpp @@ -28,22 +28,35 @@ void MeshPlugin::callPlugins(const MeshPacket &mp) { // DEBUG_MSG("In call plugins\n"); bool pluginFound = false; + + assert(mp.which_payloadVariant == MeshPacket_decoded_tag); // I think we are guarnteed the packet is decoded by this point? + + // Was this message directed to us specifically? Will be false if we are sniffing someone elses packets + bool toUs = mp.to == NODENUM_BROADCAST || mp.to == nodeDB.getNodeNum(); for (auto i = plugins->begin(); i != plugins->end(); ++i) { auto &pi = **i; pi.currentRequest = ∓ - if (pi.wantPortnum(mp.decoded.portnum)) { + + // We only call plugins that are interested in the packet (and the message is destined to us or we are promiscious) + bool wantsPacket = (pi.isPromiscuous || toUs) && pi.wantPacket(&mp); + if (wantsPacket) { pluginFound = true; bool handled = pi.handleReceived(mp); - // Possibly send replies - if (mp.decoded.want_response) + // Possibly send replies (but only if the message was directed to us specifically, i.e. not for promiscious sniffing) + if (mp.decoded.want_response && toUs) { pi.sendResponse(mp); - - DEBUG_MSG("Plugin %s handled=%d\n", pi.name, handled); - if (handled) + DEBUG_MSG("Plugin %s sent a response\n", pi.name); + } + else { + DEBUG_MSG("Plugin %s considered\n", pi.name); + } + if (handled) { + DEBUG_MSG("Plugin %s handled and skipped other processing\n", pi.name); break; + } } pi.currentRequest = NULL; diff --git a/src/mesh/MeshPlugin.h b/src/mesh/MeshPlugin.h index 1c90f8829..11f579fa9 100644 --- a/src/mesh/MeshPlugin.h +++ b/src/mesh/MeshPlugin.h @@ -55,7 +55,7 @@ class MeshPlugin /** * @return true if you want to receive the specified portnum */ - virtual bool wantPortnum(PortNum p) = 0; + virtual bool wantPacket(const MeshPacket *p) = 0; /** Called to handle a particular incoming message diff --git a/src/mesh/MeshService.cpp b/src/mesh/MeshService.cpp index ae53e802f..753d942df 100644 --- a/src/mesh/MeshService.cpp +++ b/src/mesh/MeshService.cpp @@ -65,7 +65,6 @@ void MeshService::init() if (gps) gpsObserver.observe(&gps->newStatus); - packetReceivedObserver.observe(&router->notifyPacketReceived); } diff --git a/src/mesh/MeshService.h b/src/mesh/MeshService.h index 8cba07710..6cf52a00e 100644 --- a/src/mesh/MeshService.h +++ b/src/mesh/MeshService.h @@ -19,8 +19,6 @@ class MeshService { CallbackObserver gpsObserver = CallbackObserver(this, &MeshService::onGPSChanged); - CallbackObserver packetReceivedObserver = - CallbackObserver(this, &MeshService::handleFromRadio); /// received packets waiting for the phone to process them /// FIXME, change to a DropOldestQueue and keep a count of the number of dropped packets to ensure diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 3cc6b000b..6e81acd76 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -357,7 +357,13 @@ void NodeDB::updatePosition(uint32_t nodeId, const Position &p) DEBUG_MSG("DB update position node=0x%x time=%u, latI=%d, lonI=%d\n", nodeId, p.time, p.latitude_i, p.longitude_i); + auto oldtime = info->position.time; info->position = p; + if(p.time == 0 && oldtime != 0) { + // A lot of position reports don't have time populated. In that case, be careful to not blow away the time we + // recorded based on the packet rxTime + info->position.time = oldtime; + } info->has_position = true; updateGUIforNode = info; notifyObservers(true); // Force an update whether or not our node counts have changed @@ -405,9 +411,6 @@ void NodeDB::updateFrom(const MeshPacket &mp) } info->snr = mp.rx_snr; // keep the most recent SNR we received for this node. - - if (mp.to == NODENUM_BROADCAST || mp.to == nodeDB.getNodeNum()) - MeshPlugin::callPlugins(mp); } } diff --git a/src/mesh/ProtobufPlugin.h b/src/mesh/ProtobufPlugin.h index d931185e0..c68885df2 100644 --- a/src/mesh/ProtobufPlugin.h +++ b/src/mesh/ProtobufPlugin.h @@ -25,8 +25,11 @@ template class ProtobufPlugin : protected SinglePortPlugin /** * Handle a received message, the data field in the message is already decoded and is provided + * + * In general decoded will always be !NULL. But in some special applications (where you have handling packets + * for multiple port numbers, decoding will ONLY be attempted for packets where the portnum matches our expected ourPortNum. */ - virtual bool handleReceivedProtobuf(const MeshPacket &mp, const T &decoded) = 0; + virtual bool handleReceivedProtobuf(const MeshPacket &mp, const T *decoded) = 0; /** * Return a mesh packet which has been preinited with a particular protobuf data payload and port number. @@ -58,9 +61,14 @@ template class ProtobufPlugin : protected SinglePortPlugin DEBUG_MSG("Received %s from=0x%0x, id=0x%x, payloadlen=%d\n", name, mp.from, mp.id, p.payload.size); T scratch; - if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, fields, &scratch)) - return handleReceivedProtobuf(mp, scratch); + T *decoded = NULL; + if(mp.decoded.portnum == ourPortNum) { + if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, fields, &scratch)) + decoded = &scratch; + else + DEBUG_MSG("Error decoding protobuf plugin!\n"); + } - return false; // Let others look at this message also if they want + return handleReceivedProtobuf(mp, decoded); } }; diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index f20cf02bf..7876ddde4 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -244,12 +244,13 @@ void Router::handleReceived(MeshPacket *p) if (perhapsDecode(p)) { // parsing was successful, queue for our recipient - assert(0); // FIXME, call any promiscious plugins here, make a (non promisiocous) plugin for forwarding messages to phone api + // call any promiscious plugins here, make a (non promisiocous) plugin for forwarding messages to phone api // sniffReceived(p); + MeshPlugin::callPlugins(*p); if (p->to == NODENUM_BROADCAST || p->to == getNodeNum()) { printPacket("Delivering rx packet", p); - notifyPacketReceived.notifyObservers(p); + meshservice.handleFromRadio(p); } } } diff --git a/src/mesh/Router.h b/src/mesh/Router.h index e9a10dae1..17297ba14 100644 --- a/src/mesh/Router.h +++ b/src/mesh/Router.h @@ -21,10 +21,6 @@ class Router : protected concurrency::OSThread RadioInterface *iface = NULL; public: - /// Local services that want to see _every_ packet this node receives can observe this. - /// Observers should always return 0 and _copy_ any packets they want to keep for use later (this packet will be getting - /// freed) - Observable notifyPacketReceived; /** * Constructor diff --git a/src/mesh/SinglePortPlugin.h b/src/mesh/SinglePortPlugin.h index 5fa609dd4..305532dc5 100644 --- a/src/mesh/SinglePortPlugin.h +++ b/src/mesh/SinglePortPlugin.h @@ -21,7 +21,7 @@ class SinglePortPlugin : public MeshPlugin /** * @return true if you want to receive the specified portnum */ - virtual bool wantPortnum(PortNum p) { return p == ourPortNum; } + virtual bool wantPacket(const MeshPacket *p) { return p->decoded.portnum == ourPortNum; } /** * Return a mesh packet which has been preinited as a data packet with a particular port number. diff --git a/src/mesh/generated/mesh.pb.h b/src/mesh/generated/mesh.pb.h index ca47ffa89..106444eb3 100644 --- a/src/mesh/generated/mesh.pb.h +++ b/src/mesh/generated/mesh.pb.h @@ -240,15 +240,15 @@ typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t; typedef struct _MeshPacket { uint32_t from; uint32_t to; + uint32_t channel_index; pb_size_t which_payloadVariant; union { Data decoded; MeshPacket_encrypted_t encrypted; }; - uint32_t channel_index; uint32_t id; - float rx_snr; uint32_t rx_time; + float rx_snr; uint32_t hop_limit; bool want_ack; MeshPacket_Priority priority; @@ -364,7 +364,7 @@ extern "C" { #define RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}} #define Routing_init_default {0, {RouteDiscovery_init_default}, 0} #define Data_init_default {_PortNum_MIN, {0, {0}}, 0, 0, 0} -#define MeshPacket_init_default {0, 0, 0, {Data_init_default}, 0, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} +#define MeshPacket_init_default {0, 0, 0, 0, {Data_init_default}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} #define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} #define Channel_init_default {0, false, ChannelSettings_init_default, _Channel_Role_MIN} #define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default} @@ -379,7 +379,7 @@ extern "C" { #define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}} #define Routing_init_zero {0, {RouteDiscovery_init_zero}, 0} #define Data_init_zero {_PortNum_MIN, {0, {0}}, 0, 0, 0} -#define MeshPacket_init_zero {0, 0, 0, {Data_init_zero}, 0, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} +#define MeshPacket_init_zero {0, 0, 0, 0, {Data_init_zero}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} #define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} #define Channel_init_zero {0, false, ChannelSettings_init_zero, _Channel_Role_MIN} #define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero} @@ -404,9 +404,9 @@ extern "C" { #define ChannelSettings_downlink_enabled_tag 17 #define Data_portnum_tag 1 #define Data_payload_tag 2 -#define Data_want_response_tag 5 -#define Data_dest_tag 9 -#define Data_source_tag 12 +#define Data_want_response_tag 3 +#define Data_dest_tag 4 +#define Data_source_tag 5 #define LogRecord_message_tag 1 #define LogRecord_time_tag 2 #define LogRecord_source_tag 3 @@ -480,15 +480,15 @@ extern "C" { #define Channel_role_tag 3 #define MeshPacket_from_tag 1 #define MeshPacket_to_tag 2 -#define MeshPacket_decoded_tag 3 -#define MeshPacket_encrypted_tag 8 -#define MeshPacket_channel_index_tag 4 +#define MeshPacket_channel_index_tag 3 +#define MeshPacket_decoded_tag 4 +#define MeshPacket_encrypted_tag 5 #define MeshPacket_id_tag 6 -#define MeshPacket_rx_snr_tag 7 -#define MeshPacket_rx_time_tag 9 -#define MeshPacket_hop_limit_tag 10 -#define MeshPacket_want_ack_tag 11 -#define MeshPacket_priority_tag 12 +#define MeshPacket_rx_time_tag 7 +#define MeshPacket_rx_snr_tag 8 +#define MeshPacket_hop_limit_tag 9 +#define MeshPacket_want_ack_tag 10 +#define MeshPacket_priority_tag 11 #define NodeInfo_num_tag 1 #define NodeInfo_user_tag 2 #define NodeInfo_position_tag 3 @@ -554,24 +554,24 @@ X(a, STATIC, SINGULAR, FIXED32, original_id, 6) #define Data_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, portnum, 1) \ X(a, STATIC, SINGULAR, BYTES, payload, 2) \ -X(a, STATIC, SINGULAR, BOOL, want_response, 5) \ -X(a, STATIC, SINGULAR, FIXED32, dest, 9) \ -X(a, STATIC, SINGULAR, FIXED32, source, 12) +X(a, STATIC, SINGULAR, BOOL, want_response, 3) \ +X(a, STATIC, SINGULAR, FIXED32, dest, 4) \ +X(a, STATIC, SINGULAR, FIXED32, source, 5) #define Data_CALLBACK NULL #define Data_DEFAULT NULL #define MeshPacket_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, FIXED32, from, 1) \ X(a, STATIC, SINGULAR, FIXED32, to, 2) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,decoded,decoded), 3) \ -X(a, STATIC, ONEOF, BYTES, (payloadVariant,encrypted,encrypted), 8) \ -X(a, STATIC, SINGULAR, UINT32, channel_index, 4) \ +X(a, STATIC, SINGULAR, UINT32, channel_index, 3) \ +X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,decoded,decoded), 4) \ +X(a, STATIC, ONEOF, BYTES, (payloadVariant,encrypted,encrypted), 5) \ X(a, STATIC, SINGULAR, FIXED32, id, 6) \ -X(a, STATIC, SINGULAR, FLOAT, rx_snr, 7) \ -X(a, STATIC, SINGULAR, FIXED32, rx_time, 9) \ -X(a, STATIC, SINGULAR, UINT32, hop_limit, 10) \ -X(a, STATIC, SINGULAR, BOOL, want_ack, 11) \ -X(a, STATIC, SINGULAR, UENUM, priority, 12) +X(a, STATIC, SINGULAR, FIXED32, rx_time, 7) \ +X(a, STATIC, SINGULAR, FLOAT, rx_snr, 8) \ +X(a, STATIC, SINGULAR, UINT32, hop_limit, 9) \ +X(a, STATIC, SINGULAR, BOOL, want_ack, 10) \ +X(a, STATIC, SINGULAR, UENUM, priority, 11) #define MeshPacket_CALLBACK NULL #define MeshPacket_DEFAULT NULL #define MeshPacket_payloadVariant_decoded_MSGTYPE Data diff --git a/src/plugins/NodeInfoPlugin.cpp b/src/plugins/NodeInfoPlugin.cpp index a04ec4159..2524ffa58 100644 --- a/src/plugins/NodeInfoPlugin.cpp +++ b/src/plugins/NodeInfoPlugin.cpp @@ -8,10 +8,9 @@ NodeInfoPlugin *nodeInfoPlugin; -bool NodeInfoPlugin::handleReceivedProtobuf(const MeshPacket &mp, const User &p) +bool NodeInfoPlugin::handleReceivedProtobuf(const MeshPacket &mp, const User *pptr) { - // FIXME - we currently update NodeInfo data in the DB only if the message was a broadcast or destined to us - // it would be better to update even if the message was destined to others. + auto p = *pptr; nodeDB.updateUser(mp.from, p); @@ -52,6 +51,7 @@ MeshPacket *NodeInfoPlugin::allocReply() NodeInfoPlugin::NodeInfoPlugin() : ProtobufPlugin("nodeinfo", PortNum_NODEINFO_APP, User_fields), concurrency::OSThread("NodeInfoPlugin") { + isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others setIntervalFromNow(30 * 1000); // Send our initial owner announcement 30 seconds after we start (to give network time to setup) } diff --git a/src/plugins/NodeInfoPlugin.h b/src/plugins/NodeInfoPlugin.h index f0a7efebd..eb2a16da1 100644 --- a/src/plugins/NodeInfoPlugin.h +++ b/src/plugins/NodeInfoPlugin.h @@ -26,7 +26,7 @@ class NodeInfoPlugin : public ProtobufPlugin, private concurrency::OSThrea @return true if you've guaranteed you've handled this message and no other handlers should be considered for it */ - virtual bool handleReceivedProtobuf(const MeshPacket &mp, const User &p); + virtual bool handleReceivedProtobuf(const MeshPacket &mp, const User *p); /** Messages can be received that have the want_response bit set. If set, this callback will be invoked * so that subclasses can (optionally) send a response back to the original sender. */ diff --git a/src/plugins/PositionPlugin.cpp b/src/plugins/PositionPlugin.cpp index 153d20cfc..251605865 100644 --- a/src/plugins/PositionPlugin.cpp +++ b/src/plugins/PositionPlugin.cpp @@ -10,15 +10,15 @@ PositionPlugin *positionPlugin; PositionPlugin::PositionPlugin() : ProtobufPlugin("position", PortNum_POSITION_APP, Position_fields), concurrency::OSThread("PositionPlugin") { + isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others setIntervalFromNow(60 * 1000); // Send our initial position 60 seconds after we start (to give GPS time to setup) } -bool PositionPlugin::handleReceivedProtobuf(const MeshPacket &mp, const Position &p) +bool PositionPlugin::handleReceivedProtobuf(const MeshPacket &mp, const Position *pptr) { - // FIXME - we currently update position data in the DB only if the message was a broadcast or destined to us - // it would be better to update even if the message was destined to others. + auto p = *pptr; if (p.time) { struct timeval tv; diff --git a/src/plugins/PositionPlugin.h b/src/plugins/PositionPlugin.h index 7a45c23a0..45c4884a5 100644 --- a/src/plugins/PositionPlugin.h +++ b/src/plugins/PositionPlugin.h @@ -33,7 +33,7 @@ class PositionPlugin : public ProtobufPlugin, private concurrency::OST @return true if you've guaranteed you've handled this message and no other handlers should be considered for it */ - virtual bool handleReceivedProtobuf(const MeshPacket &mp, const Position &p); + virtual bool handleReceivedProtobuf(const MeshPacket &mp, const Position *p); /** Messages can be received that have the want_response bit set. If set, this callback will be invoked * so that subclasses can (optionally) send a response back to the original sender. */ diff --git a/src/plugins/RemoteHardwarePlugin.cpp b/src/plugins/RemoteHardwarePlugin.cpp index 26b78c800..33130663f 100644 --- a/src/plugins/RemoteHardwarePlugin.cpp +++ b/src/plugins/RemoteHardwarePlugin.cpp @@ -47,8 +47,9 @@ RemoteHardwarePlugin::RemoteHardwarePlugin() { } -bool RemoteHardwarePlugin::handleReceivedProtobuf(const MeshPacket &req, const HardwareMessage &p) +bool RemoteHardwarePlugin::handleReceivedProtobuf(const MeshPacket &req, const HardwareMessage *pptr) { + auto p = *pptr; DEBUG_MSG("Received RemoteHardware typ=%d\n", p.typ); switch (p.typ) { diff --git a/src/plugins/RemoteHardwarePlugin.h b/src/plugins/RemoteHardwarePlugin.h index 5147a18e8..fad6e8386 100644 --- a/src/plugins/RemoteHardwarePlugin.h +++ b/src/plugins/RemoteHardwarePlugin.h @@ -27,7 +27,7 @@ class RemoteHardwarePlugin : public ProtobufPlugin, private con @return true if you've guaranteed you've handled this message and no other handlers should be considered for it */ - virtual bool handleReceivedProtobuf(const MeshPacket &mp, const HardwareMessage &p); + virtual bool handleReceivedProtobuf(const MeshPacket &mp, const HardwareMessage *p); /** * Periodically read the gpios we have been asked to WATCH, if they have changed, diff --git a/src/plugins/RoutingPlugin.cpp b/src/plugins/RoutingPlugin.cpp index 6f4c2123b..d0bcaf6a9 100644 --- a/src/plugins/RoutingPlugin.cpp +++ b/src/plugins/RoutingPlugin.cpp @@ -8,9 +8,9 @@ RoutingPlugin *routingPlugin; -bool RoutingPlugin::handleReceivedProtobuf(const MeshPacket &mp, const Routing &p) +bool RoutingPlugin::handleReceivedProtobuf(const MeshPacket &mp, const Routing *p) { - + assert(0); return false; // Let others look at this message also if they want } diff --git a/src/plugins/RoutingPlugin.h b/src/plugins/RoutingPlugin.h index 080b8fe12..0d987f39e 100644 --- a/src/plugins/RoutingPlugin.h +++ b/src/plugins/RoutingPlugin.h @@ -19,7 +19,7 @@ class RoutingPlugin : public ProtobufPlugin @return true if you've guaranteed you've handled this message and no other handlers should be considered for it */ - virtual bool handleReceivedProtobuf(const MeshPacket &mp, const Routing &p); + virtual bool handleReceivedProtobuf(const MeshPacket &mp, const Routing *p); /** Messages can be received that have the want_response bit set. If set, this callback will be invoked * so that subclasses can (optionally) send a response back to the original sender. */ From 587102f6bc06796892599f75f779c30b074a70c8 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sun, 21 Feb 2021 11:36:34 +0800 Subject: [PATCH 07/35] fix android lint warning --- bin/build-all.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/build-all.sh b/bin/build-all.sh index fb14156df..d9a6393e4 100755 --- a/bin/build-all.sh +++ b/bin/build-all.sh @@ -109,7 +109,7 @@ release. It is used by the android app for forcing software updates. Do not ed Generated by bin/buildall.sh --> - $VERSION + $VERSION XML From 99467cd874253166048e95bac65ff4c80ca10ed5 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sun, 21 Feb 2021 12:59:47 +0800 Subject: [PATCH 08/35] 1.2 WIP at least doesn't crash --- docs/software/TODO.md | 10 ++-- proto | 2 +- src/mesh/DSRRouter.cpp | 95 ++++++++++++++++++----------------- src/mesh/DSRRouter.h | 2 +- src/mesh/FloodingRouter.cpp | 4 +- src/mesh/FloodingRouter.h | 2 +- src/mesh/MeshService.h | 3 +- src/mesh/ReliableRouter.cpp | 25 ++++----- src/mesh/ReliableRouter.h | 2 +- src/mesh/Router.cpp | 7 +-- src/mesh/Router.h | 2 +- src/plugins/RoutingPlugin.cpp | 11 +++- 12 files changed, 89 insertions(+), 76 deletions(-) diff --git a/docs/software/TODO.md b/docs/software/TODO.md index 8f1b07625..d2c4a7c97 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -4,14 +4,14 @@ You probably don't care about this section - skip to the next one. 1.2 cleanup & multichannel support: -* call RouterPlugin for *all* packets - not just Router packets -* clear priority before sending (to keep wire size small) +* DONE call RouterPlugin for *all* packets - not just Router packets * generate channel hash from the name of the channel+the psk (not just one or the other) * DONE remove deprecated * DONE fix setchannel in phoneapi.cpp * DONE set mynodeinfo.max_channels * DONE set mynodeinfo.num_bands (formerly num_channels) -* fix sniffing of non Routing packets +* DONE fix sniffing of non Routing packets +* enable remote setttings access by moving settings operations into a regular plugin (move settings ops out of PhoneAPI) * DONE move portnum up? * DONE remove region specific builds from the firmware * add gui in android app for setting region @@ -22,6 +22,9 @@ You probably don't care about this section - skip to the next one. * DONE move most parts of meshpacket into the Data packet, so that we can chain multiple Data for sending when they all have a common destination and key. * when selecting a MeshPacket for transmit, scan the TX queue for any Data packets we can merge together as a WirePayload. In the low level send/rx code expand that into multiple MeshPackets as needed (thus 'hiding' from MeshPacket that over the wire we send multiple datapackets * confirm we are still calling the plugins for messages inbound from the phone (or generated locally) +* confirm we are still multi hop routing flood broadcasts +* confirm we are still doing resends on unicast reliable packets +* add support for full DSR unicast delivery * DONE move acks into routing * DONE make all subpackets different versions of data * DONE move routing control into a data packet @@ -31,6 +34,7 @@ You probably don't care about this section - skip to the next one. * add multichannel support in python * add channel selection for sending * record recevied channel in meshpacket +* test remote settings operations (confirm it works 3 hops away) * add channel restrictions for plugins (and restrict routing plugin to the "control" channel) * make a primaryChannel global and properly maintain it when the phone sends setChannel * move setCrypto call into packet send and packet decode code diff --git a/proto b/proto index 527b0fdc3..f23417aa7 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 527b0fdc343f89843158977a1c1a7c14db854565 +Subproject commit f23417aa7dcb8f61bbb2c1ea07c7b988ae66ec38 diff --git a/src/mesh/DSRRouter.cpp b/src/mesh/DSRRouter.cpp index 04d4a2bef..0b28257f6 100644 --- a/src/mesh/DSRRouter.cpp +++ b/src/mesh/DSRRouter.cpp @@ -62,7 +62,7 @@ ErrorCode DSRRouter::send(MeshPacket *p) return ReliableRouter::send(p); } -void DSRRouter::sniffReceived(const MeshPacket *p, const Routing &c) +void DSRRouter::sniffReceived(const MeshPacket *p, const Routing *c) { // Learn 0 hop routes by just hearing any adjacent nodes // But treat broadcasts carefully, because when flood broadcasts go out they keep the same original "from". So we want to @@ -72,47 +72,49 @@ void DSRRouter::sniffReceived(const MeshPacket *p, const Routing &c) addRoute(p->from, p->from, 0); // We are adjacent with zero hops } - switch (c.which_variant) { - case Routing_route_request_tag: - // Handle route discovery packets (will be a broadcast message) - // FIXME - always start request with the senders nodenum - if (weAreInRoute(c.route_request)) { - DEBUG_MSG("Ignoring a route request that contains us\n"); - } else { - updateRoutes(c.route_request, - true); // Update our routing tables based on the route that came in so far on this request - - if (p->decoded.dest == getNodeNum()) { - // They were looking for us, send back a route reply (the sender address will be first in the list) - sendRouteReply(c.route_request); + if (c) + switch (c->which_variant) { + case Routing_route_request_tag: + // Handle route discovery packets (will be a broadcast message) + // FIXME - always start request with the senders nodenum + if (weAreInRoute(c->route_request)) { + DEBUG_MSG("Ignoring a route request that contains us\n"); } else { - // They were looking for someone else, forward it along (as a zero hop broadcast) - NodeNum nextHop = getNextHop(p->decoded.dest); - if (nextHop) { - // in our route cache, reply to the requester (the sender address will be first in the list) - sendRouteReply(c.route_request, nextHop); + updateRoutes(c->route_request, + true); // Update our routing tables based on the route that came in so far on this request + + if (p->decoded.dest == getNodeNum()) { + // They were looking for us, send back a route reply (the sender address will be first in the list) + sendRouteReply(c->route_request); } else { - // Not in our route cache, rebroadcast on their behalf (after adding ourselves to the request route) - resendRouteRequest(p); + // They were looking for someone else, forward it along (as a zero hop broadcast) + NodeNum nextHop = getNextHop(p->decoded.dest); + if (nextHop) { + // in our route cache, reply to the requester (the sender address will be first in the list) + sendRouteReply(c->route_request, nextHop); + } else { + // Not in our route cache, rebroadcast on their behalf (after adding ourselves to the request route) + resendRouteRequest(p); + } } } + break; + case Routing_route_reply_tag: + updateRoutes(c->route_reply, false); + + // FIXME, if any of our current pending packets were waiting for this route, send them (and leave them as regular + // pending packets until ack arrives) + // FIXME, if we don't get a route reply at all (or a route error), timeout and generate a routeerror TIMEOUT on our + // own... + break; + case Routing_error_reason_tag: + removeRoute(p->decoded.dest); + + // FIXME: if any pending packets were waiting on this route, delete them + break; + default: + break; } - break; - case Routing_route_reply_tag: - updateRoutes(c.route_reply, false); - - // FIXME, if any of our current pending packets were waiting for this route, send them (and leave them as regular pending - // packets until ack arrives) - // FIXME, if we don't get a route reply at all (or a route error), timeout and generate a routeerror TIMEOUT on our own... - break; - case Routing_error_reason_tag: - removeRoute(p->decoded.dest); - - // FIXME: if any pending packets were waiting on this route, delete them - break; - default: - break; - } // We simply ignore ACKs - because ReliableRouter will delete the pending packet for us @@ -137,15 +139,18 @@ void DSRRouter::sniffReceived(const MeshPacket *p, const Routing &c) // FIXME, stop local processing of this packet } - // handle naks - convert them to route error packets - // All naks are generated locally, because we failed resending the packet too many times - PacketId nakId = c.fail_id; - if (nakId) { - auto pending = findPendingPacket(p->to, nakId); - if (pending && pending->packet->decoded.source) { // if source not set, this was not a multihop packet, just ignore - removeRoute(pending->packet->decoded.dest); // We no longer have a route to the specified node + if (c) { + // handle naks - convert them to route error packets + // All naks are generated locally, because we failed resending the packet too many times + PacketId nakId = c->fail_id; + if (nakId) { + auto pending = findPendingPacket(p->to, nakId); + if (pending && + pending->packet->decoded.source) { // if source not set, this was not a multihop packet, just ignore + removeRoute(pending->packet->decoded.dest); // We no longer have a route to the specified node - sendRouteError(p, Routing_Error_GOT_NAK); + sendRouteError(p, Routing_Error_GOT_NAK); + } } } } diff --git a/src/mesh/DSRRouter.h b/src/mesh/DSRRouter.h index eef1a991c..796dc236c 100644 --- a/src/mesh/DSRRouter.h +++ b/src/mesh/DSRRouter.h @@ -8,7 +8,7 @@ class DSRRouter : public ReliableRouter * Every (non duplicate) packet this node receives will be passed through this method. This allows subclasses to * update routing tables etc... based on what we overhear (even for messages not destined to our node) */ - virtual void sniffReceived(const MeshPacket *p, const Routing &c); + virtual void sniffReceived(const MeshPacket *p, const Routing *c); /** * Send a packet on a suitable interface. This routine will diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index 777178c41..049d038c7 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -27,11 +27,11 @@ bool FloodingRouter::shouldFilterReceived(const MeshPacket *p) return Router::shouldFilterReceived(p); } -void FloodingRouter::sniffReceived(const MeshPacket *p, const Routing &c) +void FloodingRouter::sniffReceived(const MeshPacket *p, const Routing *c) { // If a broadcast, possibly _also_ send copies out into the mesh. // (FIXME, do something smarter than naive flooding here) - if (p->to == NODENUM_BROADCAST && p->hop_limit > 0) { + if (p->to == NODENUM_BROADCAST && p->hop_limit > 0 && p->from != getNodeNum()) { if (p->id != 0) { MeshPacket *tosend = packetPool.allocCopy(*p); // keep a copy because we will be sending it diff --git a/src/mesh/FloodingRouter.h b/src/mesh/FloodingRouter.h index 3e4f5de6e..41bc898df 100644 --- a/src/mesh/FloodingRouter.h +++ b/src/mesh/FloodingRouter.h @@ -55,5 +55,5 @@ class FloodingRouter : public Router, protected PacketHistory /** * Look for broadcasts we need to rebroadcast */ - virtual void sniffReceived(const MeshPacket *p, const Routing &c); + virtual void sniffReceived(const MeshPacket *p, const Routing *c); }; diff --git a/src/mesh/MeshService.h b/src/mesh/MeshService.h index 6cf52a00e..0f2e772b3 100644 --- a/src/mesh/MeshService.h +++ b/src/mesh/MeshService.h @@ -89,9 +89,10 @@ class MeshService /// returns 0 to allow futher processing int onGPSChanged(const meshtastic::GPSStatus *arg); - /// Handle a packet that just arrived from the radio. This method does _not_ free the provided packet. If it needs + /// Handle a packet that just arrived from the radio. This method does _ReliableRouternot_ free the provided packet. If it needs /// to keep the packet around it makes a copy int handleFromRadio(const MeshPacket *p); + friend class RoutingPlugin; }; extern MeshService service; diff --git a/src/mesh/ReliableRouter.cpp b/src/mesh/ReliableRouter.cpp index 3dc07c9c9..65e1ff9f8 100644 --- a/src/mesh/ReliableRouter.cpp +++ b/src/mesh/ReliableRouter.cpp @@ -53,7 +53,7 @@ bool ReliableRouter::shouldFilterReceived(const MeshPacket *p) * * Otherwise, let superclass handle it. */ -void ReliableRouter::sniffReceived(const MeshPacket *p, const Routing &c) +void ReliableRouter::sniffReceived(const MeshPacket *p, const Routing *c) { NodeNum ourNode = getNodeNum(); @@ -64,18 +64,19 @@ void ReliableRouter::sniffReceived(const MeshPacket *p, const Routing &c) } // If the payload is valid, look for ack/nak + if (c) { + PacketId ackId = c->success_id; + PacketId nakId = c->fail_id; - PacketId ackId = c.success_id; - PacketId nakId = c.fail_id; - - // We intentionally don't check wasSeenRecently, because it is harmless to delete non existent retransmission records - if (ackId || nakId) { - if (ackId) { - DEBUG_MSG("Received a ack=%d, stopping retransmissions\n", ackId); - stopRetransmission(p->to, ackId); - } else { - DEBUG_MSG("Received a nak=%d, stopping retransmissions\n", nakId); - stopRetransmission(p->to, nakId); + // We intentionally don't check wasSeenRecently, because it is harmless to delete non existent retransmission records + if (ackId || nakId) { + if (ackId) { + DEBUG_MSG("Received a ack=%d, stopping retransmissions\n", ackId); + stopRetransmission(p->to, ackId); + } else { + DEBUG_MSG("Received a nak=%d, stopping retransmissions\n", nakId); + stopRetransmission(p->to, nakId); + } } } } diff --git a/src/mesh/ReliableRouter.h b/src/mesh/ReliableRouter.h index bf0338f9b..e6a71f423 100644 --- a/src/mesh/ReliableRouter.h +++ b/src/mesh/ReliableRouter.h @@ -90,7 +90,7 @@ class ReliableRouter : public FloodingRouter /** * Look for acks/naks or someone retransmitting us */ - virtual void sniffReceived(const MeshPacket *p, const Routing &c); + virtual void sniffReceived(const MeshPacket *p, const Routing *c); /** * Try to find the pending packet record for this ID (or NULL if not found) diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 7876ddde4..673fafefd 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -194,7 +194,7 @@ bool Router::cancelSending(NodeNum from, PacketId id) { * Every (non duplicate) packet this node receives will be passed through this method. This allows subclasses to * update routing tables etc... based on what we overhear (even for messages not destined to our node) */ -void Router::sniffReceived(const MeshPacket *p, const Routing &c) +void Router::sniffReceived(const MeshPacket *p, const Routing *c) { DEBUG_MSG("FIXME-update-db Sniffing packet\n"); // FIXME, update nodedb here for any packet that passes through us @@ -247,11 +247,6 @@ void Router::handleReceived(MeshPacket *p) // call any promiscious plugins here, make a (non promisiocous) plugin for forwarding messages to phone api // sniffReceived(p); MeshPlugin::callPlugins(*p); - - if (p->to == NODENUM_BROADCAST || p->to == getNodeNum()) { - printPacket("Delivering rx packet", p); - meshservice.handleFromRadio(p); - } } } diff --git a/src/mesh/Router.h b/src/mesh/Router.h index 17297ba14..4b1656936 100644 --- a/src/mesh/Router.h +++ b/src/mesh/Router.h @@ -89,7 +89,7 @@ class Router : protected concurrency::OSThread * Every (non duplicate) packet this node receives will be passed through this method. This allows subclasses to * update routing tables etc... based on what we overhear (even for messages not destined to our node) */ - virtual void sniffReceived(const MeshPacket *p, const Routing &c); + virtual void sniffReceived(const MeshPacket *p, const Routing *c); /** * Remove any encryption and decode the protobufs inside this packet (if necessary). diff --git a/src/plugins/RoutingPlugin.cpp b/src/plugins/RoutingPlugin.cpp index d0bcaf6a9..c3709ea5a 100644 --- a/src/plugins/RoutingPlugin.cpp +++ b/src/plugins/RoutingPlugin.cpp @@ -8,9 +8,16 @@ RoutingPlugin *routingPlugin; -bool RoutingPlugin::handleReceivedProtobuf(const MeshPacket &mp, const Routing *p) +bool RoutingPlugin::handleReceivedProtobuf(const MeshPacket &mp, const Routing *r) { - assert(0); + router->sniffReceived(&mp, r); + + // FIXME - move this to a non promsicious PhoneAPI plugin? + if (mp.to == NODENUM_BROADCAST || mp.to == nodeDB.getNodeNum()) { + printPacket("Delivering rx packet", &mp); + service.handleFromRadio(&mp); + } + return false; // Let others look at this message also if they want } From c6091338ab5433befbbae4a0a817c96cf2906f99 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sun, 21 Feb 2021 14:03:44 +0800 Subject: [PATCH 09/35] admin ops --- docs/software/TODO.md | 2 + proto | 2 +- src/mesh/PhoneAPI.cpp | 60 --------------------- src/mesh/generated/mesh.pb.c | 3 ++ src/mesh/generated/mesh.pb.h | 43 ++++++++++----- src/mesh/generated/portnums.pb.h | 1 + src/plugins/AdminPlugin.cpp | 93 ++++++++++++++++++++++++++++++++ src/plugins/AdminPlugin.h | 32 +++++++++++ src/plugins/Plugins.cpp | 2 + src/plugins/RoutingPlugin.cpp | 3 +- 10 files changed, 164 insertions(+), 77 deletions(-) create mode 100644 src/plugins/AdminPlugin.cpp create mode 100644 src/plugins/AdminPlugin.h diff --git a/docs/software/TODO.md b/docs/software/TODO.md index d2c4a7c97..1c6714e84 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -14,7 +14,9 @@ You probably don't care about this section - skip to the next one. * enable remote setttings access by moving settings operations into a regular plugin (move settings ops out of PhoneAPI) * DONE move portnum up? * DONE remove region specific builds from the firmware +* restrict settings operations to the admin channel * add gui in android app for setting region +* "FIXME - move the radioconfig/user/channel READ operations into SettingsMessage as well" * scrub protobufs to make sure they are absoloute minimum wiresize (in particular packets, ChannelSets and positions) * send a hint that can be used to select which channel to try and hash against with each message * change syncword diff --git a/proto b/proto index f23417aa7..649c3deb7 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit f23417aa7dcb8f61bbb2c1ea07c7b988ae66ec38 +Subproject commit 649c3deb71d1780416fac5db33ad3c957c0278b6 diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index 6ec09b2ca..7f63fc18e 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -78,20 +78,6 @@ void PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength) // this will break once we have multiple instances of PhoneAPI running independently break; - case ToRadio_set_owner_tag: - DEBUG_MSG("Client is setting owner\n"); - handleSetOwner(toRadioScratch.set_owner); - break; - - case ToRadio_set_radio_tag: - DEBUG_MSG("Client is setting radio\n"); - handleSetRadio(toRadioScratch.set_radio); - break; - - case ToRadio_set_channel_tag: - DEBUG_MSG("Client is setting channel\n"); - handleSetChannel(toRadioScratch.set_channel); - break; default: DEBUG_MSG("Error: unexpected ToRadio variant\n"); break; @@ -255,52 +241,6 @@ bool PhoneAPI::available() return false; } -// -// The following routines are only public for now - until the rev1 bluetooth API is removed -// - -void PhoneAPI::handleSetOwner(const User &o) -{ - int changed = 0; - - if (*o.long_name) { - changed |= strcmp(owner.long_name, o.long_name); - strcpy(owner.long_name, o.long_name); - } - if (*o.short_name) { - changed |= strcmp(owner.short_name, o.short_name); - strcpy(owner.short_name, o.short_name); - } - if (*o.id) { - changed |= strcmp(owner.id, o.id); - strcpy(owner.id, o.id); - } - - if (changed) // If nothing really changed, don't broadcast on the network or write to flash - service.reloadOwner(); -} - -void PhoneAPI::handleSetChannel(const Channel &cc) -{ - channels.setChannel(cc); - - bool didReset = service.reloadConfig(); - if (didReset) { - state = STATE_SEND_MY_INFO; // Squirt a completely new set of configs to the client - } - -} - -void PhoneAPI::handleSetRadio(const RadioConfig &r) -{ - radioConfig = r; - - bool didReset = service.reloadConfig(); - if (didReset) { - state = STATE_SEND_MY_INFO; // Squirt a completely new set of configs to the client - } -} - /** * Handle a packet that the phone wants us to send. It is our responsibility to free the packet to the pool */ diff --git a/src/mesh/generated/mesh.pb.c b/src/mesh/generated/mesh.pb.c index c4fd0d8e5..f0b3f8c66 100644 --- a/src/mesh/generated/mesh.pb.c +++ b/src/mesh/generated/mesh.pb.c @@ -51,6 +51,9 @@ PB_BIND(FromRadio, FromRadio, 2) PB_BIND(ToRadio, ToRadio, 2) +PB_BIND(AdminMessage, AdminMessage, 2) + + diff --git a/src/mesh/generated/mesh.pb.h b/src/mesh/generated/mesh.pb.h index 106444eb3..d29f6c86b 100644 --- a/src/mesh/generated/mesh.pb.h +++ b/src/mesh/generated/mesh.pb.h @@ -281,6 +281,15 @@ typedef struct _Routing { uint32_t original_id; } Routing; +typedef struct _AdminMessage { + pb_size_t which_variant; + union { + RadioConfig set_radio; + User set_owner; + Channel set_channel; + }; +} AdminMessage; + typedef struct _FromRadio { uint32_t num; pb_size_t which_payloadVariant; @@ -301,9 +310,6 @@ typedef struct _ToRadio { union { MeshPacket packet; uint32_t want_config_id; - RadioConfig set_radio; - User set_owner; - Channel set_channel; }; } ToRadio; @@ -374,6 +380,7 @@ extern "C" { #define LogRecord_init_default {"", 0, "", _LogRecord_Level_MIN} #define FromRadio_init_default {0, 0, {MyNodeInfo_init_default}} #define ToRadio_init_default {0, {MeshPacket_init_default}} +#define AdminMessage_init_default {0, {RadioConfig_init_default}} #define Position_init_zero {0, 0, 0, 0, 0} #define User_init_zero {"", "", "", {0}} #define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}} @@ -389,6 +396,7 @@ extern "C" { #define LogRecord_init_zero {"", 0, "", _LogRecord_Level_MIN} #define FromRadio_init_zero {0, 0, {MyNodeInfo_init_zero}} #define ToRadio_init_zero {0, {MeshPacket_init_zero}} +#define AdminMessage_init_zero {0, {RadioConfig_init_zero}} /* Field tags (for use in manual encoding/decoding) */ #define ChannelSettings_tx_power_tag 1 @@ -501,6 +509,9 @@ extern "C" { #define Routing_success_id_tag 4 #define Routing_fail_id_tag 5 #define Routing_original_id_tag 6 +#define AdminMessage_set_radio_tag 1 +#define AdminMessage_set_owner_tag 2 +#define AdminMessage_set_channel_tag 3 #define FromRadio_num_tag 1 #define FromRadio_my_info_tag 3 #define FromRadio_node_info_tag 4 @@ -512,9 +523,6 @@ extern "C" { #define FromRadio_packet_tag 11 #define ToRadio_packet_tag 2 #define ToRadio_want_config_id_tag 100 -#define ToRadio_set_radio_tag 101 -#define ToRadio_set_owner_tag 102 -#define ToRadio_set_channel_tag 104 /* Struct field encoding specification for nanopb */ #define Position_FIELDLIST(X, a) \ @@ -707,16 +715,20 @@ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,packet,packet), 11) #define ToRadio_FIELDLIST(X, a) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,packet,packet), 2) \ -X(a, STATIC, ONEOF, UINT32, (payloadVariant,want_config_id,want_config_id), 100) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,set_radio,set_radio), 101) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,set_owner,set_owner), 102) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,set_channel,set_channel), 104) +X(a, STATIC, ONEOF, UINT32, (payloadVariant,want_config_id,want_config_id), 100) #define ToRadio_CALLBACK NULL #define ToRadio_DEFAULT NULL #define ToRadio_payloadVariant_packet_MSGTYPE MeshPacket -#define ToRadio_payloadVariant_set_radio_MSGTYPE RadioConfig -#define ToRadio_payloadVariant_set_owner_MSGTYPE User -#define ToRadio_payloadVariant_set_channel_MSGTYPE Channel + +#define AdminMessage_FIELDLIST(X, a) \ +X(a, STATIC, ONEOF, MESSAGE, (variant,set_radio,set_radio), 1) \ +X(a, STATIC, ONEOF, MESSAGE, (variant,set_owner,set_owner), 2) \ +X(a, STATIC, ONEOF, MESSAGE, (variant,set_channel,set_channel), 3) +#define AdminMessage_CALLBACK NULL +#define AdminMessage_DEFAULT NULL +#define AdminMessage_variant_set_radio_MSGTYPE RadioConfig +#define AdminMessage_variant_set_owner_MSGTYPE User +#define AdminMessage_variant_set_channel_MSGTYPE Channel extern const pb_msgdesc_t Position_msg; extern const pb_msgdesc_t User_msg; @@ -733,6 +745,7 @@ extern const pb_msgdesc_t MyNodeInfo_msg; extern const pb_msgdesc_t LogRecord_msg; extern const pb_msgdesc_t FromRadio_msg; extern const pb_msgdesc_t ToRadio_msg; +extern const pb_msgdesc_t AdminMessage_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define Position_fields &Position_msg @@ -750,6 +763,7 @@ extern const pb_msgdesc_t ToRadio_msg; #define LogRecord_fields &LogRecord_msg #define FromRadio_fields &FromRadio_msg #define ToRadio_fields &ToRadio_msg +#define AdminMessage_fields &AdminMessage_msg /* Maximum encoded size of messages (where known) */ #define Position_size 37 @@ -766,7 +780,8 @@ extern const pb_msgdesc_t ToRadio_msg; #define MyNodeInfo_size 89 #define LogRecord_size 81 #define FromRadio_size 317 -#define ToRadio_size 312 +#define ToRadio_size 305 +#define AdminMessage_size 311 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/portnums.pb.h b/src/mesh/generated/portnums.pb.h index 72360f295..3ddd806ea 100644 --- a/src/mesh/generated/portnums.pb.h +++ b/src/mesh/generated/portnums.pb.h @@ -17,6 +17,7 @@ typedef enum _PortNum { PortNum_POSITION_APP = 3, PortNum_NODEINFO_APP = 4, PortNum_ROUTING_APP = 5, + PortNum_ADMIN_APP = 6, PortNum_REPLY_APP = 32, PortNum_IP_TUNNEL_APP = 33, PortNum_SERIAL_APP = 64, diff --git a/src/plugins/AdminPlugin.cpp b/src/plugins/AdminPlugin.cpp new file mode 100644 index 000000000..248a4ebd3 --- /dev/null +++ b/src/plugins/AdminPlugin.cpp @@ -0,0 +1,93 @@ +#include "AdminPlugin.h" +#include "MeshService.h" +#include "NodeDB.h" +#include "Router.h" +#include "configuration.h" +#include "main.h" +#include "Channels.h" + +AdminPlugin *adminPlugin; + +bool AdminPlugin::handleReceivedProtobuf(const MeshPacket &mp, const AdminMessage *r) +{ + assert(r); + switch(r->which_variant) { + case AdminMessage_set_owner_tag: + DEBUG_MSG("Client is setting owner\n"); + handleSetOwner(r->set_owner); + break; + + case AdminMessage_set_radio_tag: + DEBUG_MSG("Client is setting radio\n"); + handleSetRadio(r->set_radio); + break; + + case AdminMessage_set_channel_tag: + DEBUG_MSG("Client is setting channel\n"); + handleSetChannel(r->set_channel); + break; + } + return false; // Let others look at this message also if they want +} + + + +void AdminPlugin::handleSetOwner(const User &o) +{ + int changed = 0; + + if (*o.long_name) { + changed |= strcmp(owner.long_name, o.long_name); + strcpy(owner.long_name, o.long_name); + } + if (*o.short_name) { + changed |= strcmp(owner.short_name, o.short_name); + strcpy(owner.short_name, o.short_name); + } + if (*o.id) { + changed |= strcmp(owner.id, o.id); + strcpy(owner.id, o.id); + } + + if (changed) // If nothing really changed, don't broadcast on the network or write to flash + service.reloadOwner(); +} + +void AdminPlugin::handleSetChannel(const Channel &cc) +{ + channels.setChannel(cc); + + bool didReset = service.reloadConfig(); + /* FIXME - do we need this still? + if (didReset) { + state = STATE_SEND_MY_INFO; // Squirt a completely new set of configs to the client + } */ + +} + +void AdminPlugin::handleSetRadio(const RadioConfig &r) +{ + radioConfig = r; + + bool didReset = service.reloadConfig(); + /* FIXME - do we need this still? if (didReset) { + state = STATE_SEND_MY_INFO; // Squirt a completely new set of configs to the client + } */ +} + + +MeshPacket *AdminPlugin::allocReply() +{ + assert(0); // 1.2 refactoring fixme, Not sure if anything needs this yet? + // return allocDataProtobuf(u); + return NULL; +} + +AdminPlugin::AdminPlugin() + : ProtobufPlugin("Admin", PortNum_ADMIN_APP, AdminMessage_fields) +{ + // FIXME, restrict to the admin channel for rx +} + + + diff --git a/src/plugins/AdminPlugin.h b/src/plugins/AdminPlugin.h new file mode 100644 index 000000000..de8ffac11 --- /dev/null +++ b/src/plugins/AdminPlugin.h @@ -0,0 +1,32 @@ +#pragma once +#include "ProtobufPlugin.h" + +/** + * Routing plugin for router control messages + */ +class AdminPlugin : public ProtobufPlugin +{ + public: + /** Constructor + * name is for debugging output + */ + AdminPlugin(); + + protected: + /** Called to handle a particular incoming message + + @return true if you've guaranteed you've handled this message and no other handlers should be considered for it + */ + virtual bool handleReceivedProtobuf(const MeshPacket &mp, const AdminMessage *p); + + /** Messages can be received that have the want_response bit set. If set, this callback will be invoked + * so that subclasses can (optionally) send a response back to the original sender. */ + virtual MeshPacket *allocReply(); + + private: + void handleSetOwner(const User &o); + void handleSetChannel(const Channel &cc); + void handleSetRadio(const RadioConfig &r); +}; + +extern AdminPlugin *adminPlugin; \ No newline at end of file diff --git a/src/plugins/Plugins.cpp b/src/plugins/Plugins.cpp index 65cfdcee4..12246f8c8 100644 --- a/src/plugins/Plugins.cpp +++ b/src/plugins/Plugins.cpp @@ -8,6 +8,7 @@ #include "plugins/StoreForwardPlugin.h" #include "plugins/TextMessagePlugin.h" #include "plugins/RoutingPlugin.h" +#include "plugins/AdminPlugin.h" /** * Create plugin instances here. If you are adding a new plugin, you must 'new' it here (or somewhere else) @@ -15,6 +16,7 @@ void setupPlugins() { routingPlugin = new RoutingPlugin(); + adminPlugin = new AdminPlugin(); nodeInfoPlugin = new NodeInfoPlugin(); positionPlugin = new PositionPlugin(); textMessagePlugin = new TextMessagePlugin(); diff --git a/src/plugins/RoutingPlugin.cpp b/src/plugins/RoutingPlugin.cpp index c3709ea5a..58b3f08ae 100644 --- a/src/plugins/RoutingPlugin.cpp +++ b/src/plugins/RoutingPlugin.cpp @@ -1,7 +1,6 @@ #include "RoutingPlugin.h" #include "MeshService.h" #include "NodeDB.h" -#include "RTC.h" #include "Router.h" #include "configuration.h" #include "main.h" @@ -53,7 +52,7 @@ void RoutingPlugin::sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom) } RoutingPlugin::RoutingPlugin() - : ProtobufPlugin("routing", PortNum_ROUTING_APP, User_fields) + : ProtobufPlugin("routing", PortNum_ROUTING_APP, Routing_fields) { isPromiscuous = true; } From 008187caa4776b84be403b09029951405c22d02b Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Mon, 22 Feb 2021 10:26:11 +0800 Subject: [PATCH 10/35] 1.2 wip - psk work --- docs/software/TODO.md | 6 +++--- proto | 2 +- src/mesh/Channels.cpp | 15 ++++++++++----- src/mesh/Channels.h | 29 +++++++++++++++++++++++++++++ src/mesh/generated/deviceonly.pb.h | 2 +- src/mesh/generated/mesh.pb.h | 26 +++++++++++++------------- src/mesh/generated/portnums.pb.h | 7 ++++--- 7 files changed, 61 insertions(+), 26 deletions(-) diff --git a/docs/software/TODO.md b/docs/software/TODO.md index 1c6714e84..c4769c2ef 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -6,19 +6,19 @@ You probably don't care about this section - skip to the next one. * DONE call RouterPlugin for *all* packets - not just Router packets * generate channel hash from the name of the channel+the psk (not just one or the other) +* send a hint that can be used to select which channel to try and hash against with each message * DONE remove deprecated * DONE fix setchannel in phoneapi.cpp * DONE set mynodeinfo.max_channels * DONE set mynodeinfo.num_bands (formerly num_channels) * DONE fix sniffing of non Routing packets -* enable remote setttings access by moving settings operations into a regular plugin (move settings ops out of PhoneAPI) +* DONE enable remote setttings access by moving settings operations into a regular plugin (move settings ops out of PhoneAPI) * DONE move portnum up? * DONE remove region specific builds from the firmware * restrict settings operations to the admin channel * add gui in android app for setting region * "FIXME - move the radioconfig/user/channel READ operations into SettingsMessage as well" -* scrub protobufs to make sure they are absoloute minimum wiresize (in particular packets, ChannelSets and positions) -* send a hint that can be used to select which channel to try and hash against with each message +* DONE scrub protobufs to make sure they are absoloute minimum wiresize (in particular Data, ChannelSets and positions) * change syncword * allow chaning packets in single transmission - to increase airtime efficiency and amortize packet overhead * DONE move most parts of meshpacket into the Data packet, so that we can chain multiple Data for sending when they all have a common destination and key. diff --git a/proto b/proto index 649c3deb7..7db1c2edb 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 649c3deb71d1780416fac5db33ad3c957c0278b6 +Subproject commit 7db1c2edb2e62e90b1f297be2f11aff0df35330a diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp index 510510ca3..dc1383bdf 100644 --- a/src/mesh/Channels.cpp +++ b/src/mesh/Channels.cpp @@ -74,18 +74,23 @@ void initDefaultChannel(size_t chIndex) /** Given a channel index, change to use the crypto key specified by that index */ -void setCrypto(size_t chIndex) +void Channels::setCrypto(size_t chIndex) { - assert(chIndex < devicestate.channels_count); Channel *ch = devicestate.channels + chIndex; ChannelSettings &channelSettings = ch->settings; + assert(ch->has_settings); memset(activePSK, 0, sizeof(activePSK)); // In case the user provided a short key, we want to pad the rest with zeros memcpy(activePSK, channelSettings.psk.bytes, channelSettings.psk.size); activePSKSize = channelSettings.psk.size; - if (activePSKSize == 0) - DEBUG_MSG("Warning: User disabled encryption\n"); + if (activePSKSize == 0) { + if(ch->role == Channel_Role_SECONDARY) { + DEBUG_MSG("Unset PSK for secondary channel %s. using primary key\n", ch->settings.name); + setCrypto(primaryIndex); + } else + DEBUG_MSG("Warning: User disabled encryption\n"); + } else if (activePSKSize == 1) { // Convert the short single byte variants of psk into variant that can be used more generally @@ -134,7 +139,7 @@ void Channels::onConfigChanged() primaryIndex = i; } - setCrypto(0); // FIXME: for the time being (still single channel - just use our only channel as the crypto key) + setCrypto(primaryIndex); // FIXME: for the time being (still single channel - just use our only channel as the crypto key) } Channel &Channels::getChannel(size_t chIndex) diff --git a/src/mesh/Channels.h b/src/mesh/Channels.h index 5654fb1f2..ec64cd49b 100644 --- a/src/mesh/Channels.h +++ b/src/mesh/Channels.h @@ -45,6 +45,35 @@ their nodes /// called when the user has just changed our radio config and we might need to change channel keys void onConfigChanged(); + + /** Given a channel hash setup crypto for decoding that channel (or the primary channel if that channel is unsecured) + * + * This method is called before decoding inbound packets + * + * @return false if no suitable channel could be found. + */ + bool setCryptoByHash(uint8_t channelHash); + + /** Given a channel index setup crypto for encoding that channel (or the primary channel if that channel is unsecured) + * + * This method is called before encoding inbound packets + * + * @eturn the (0 to 255) hash for that channel - if no suitable channel could be found, return -1 + */ + int16_t setCryptoByIndex(uint8_t channelIndex); + +private: + /** Given a channel index, change to use the crypto key specified by that index + */ + void setCrypto(size_t chIndex); + + /** Return the channel index for the specified channel hash, or -1 for not found */ + int8_t getChannelIndexByHash(uint8_t channelHash); + + /** Given a channel number, return the (0 to 255) hash for that channel + * If no suitable channel could be found, return -1 + */ + int16_t getChannelHash(size_t channelNum); }; /// Singleton channel table diff --git a/src/mesh/generated/deviceonly.pb.h b/src/mesh/generated/deviceonly.pb.h index 47ffe2ae3..b8c372664 100644 --- a/src/mesh/generated/deviceonly.pb.h +++ b/src/mesh/generated/deviceonly.pb.h @@ -80,7 +80,7 @@ extern const pb_msgdesc_t DeviceState_msg; #define DeviceState_fields &DeviceState_msg /* Maximum encoded size of messages (where known) */ -#define DeviceState_size 6225 +#define DeviceState_size 6119 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/mesh.pb.h b/src/mesh/generated/mesh.pb.h index d29f6c86b..873e0aa2f 100644 --- a/src/mesh/generated/mesh.pb.h +++ b/src/mesh/generated/mesh.pb.h @@ -119,20 +119,20 @@ typedef enum _LogRecord_Level { /* Struct definitions */ typedef PB_BYTES_ARRAY_T(32) ChannelSettings_psk_t; typedef struct _ChannelSettings { - int32_t tx_power; + int8_t tx_power; ChannelSettings_ModemConfig modem_config; ChannelSettings_psk_t psk; char name[12]; - uint32_t bandwidth; + uint16_t bandwidth; uint32_t spread_factor; - uint32_t coding_rate; - uint32_t channel_num; + uint8_t coding_rate; + uint8_t channel_num; uint32_t id; bool uplink_enabled; bool downlink_enabled; } ChannelSettings; -typedef PB_BYTES_ARRAY_T(240) Data_payload_t; +typedef PB_BYTES_ARRAY_T(237) Data_payload_t; typedef struct _Data { PortNum portnum; Data_payload_t payload; @@ -230,7 +230,7 @@ typedef struct _User { } User; typedef struct _Channel { - uint32_t index; + uint8_t index; bool has_settings; ChannelSettings settings; Channel_Role role; @@ -240,7 +240,7 @@ typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t; typedef struct _MeshPacket { uint32_t from; uint32_t to; - uint32_t channel_index; + uint8_t channel_index; pb_size_t which_payloadVariant; union { Data decoded; @@ -249,7 +249,7 @@ typedef struct _MeshPacket { uint32_t id; uint32_t rx_time; float rx_snr; - uint32_t hop_limit; + uint8_t hop_limit; bool want_ack; MeshPacket_Priority priority; } MeshPacket; @@ -770,17 +770,17 @@ extern const pb_msgdesc_t AdminMessage_msg; #define User_size 72 #define RouteDiscovery_size 40 #define Routing_size 47 -#define Data_size 258 -#define MeshPacket_size 302 -#define ChannelSettings_size 95 -#define Channel_size 105 +#define Data_size 255 +#define MeshPacket_size 294 +#define ChannelSettings_size 87 +#define Channel_size 94 #define RadioConfig_size 308 #define RadioConfig_UserPreferences_size 305 #define NodeInfo_size 130 #define MyNodeInfo_size 89 #define LogRecord_size 81 #define FromRadio_size 317 -#define ToRadio_size 305 +#define ToRadio_size 297 #define AdminMessage_size 311 #ifdef __cplusplus diff --git a/src/mesh/generated/portnums.pb.h b/src/mesh/generated/portnums.pb.h index 3ddd806ea..4e9203db1 100644 --- a/src/mesh/generated/portnums.pb.h +++ b/src/mesh/generated/portnums.pb.h @@ -24,13 +24,14 @@ typedef enum _PortNum { PortNum_STORE_FORWARD_APP = 65, PortNum_RANGE_TEST_APP = 66, PortNum_PRIVATE_APP = 256, - PortNum_ATAK_FORWARDER = 257 + PortNum_ATAK_FORWARDER = 257, + PortNum_MAX = 511 } PortNum; /* Helper constants for enums */ #define _PortNum_MIN PortNum_UNKNOWN_APP -#define _PortNum_MAX PortNum_ATAK_FORWARDER -#define _PortNum_ARRAYSIZE ((PortNum)(PortNum_ATAK_FORWARDER+1)) +#define _PortNum_MAX PortNum_MAX +#define _PortNum_ARRAYSIZE ((PortNum)(PortNum_MAX+1)) #ifdef __cplusplus From d4781280b752dfc24b017c0515559ffe422a3876 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Mon, 22 Feb 2021 10:29:27 +0800 Subject: [PATCH 11/35] update protos --- proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto b/proto index 7db1c2edb..4396b3689 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 7db1c2edb2e62e90b1f297be2f11aff0df35330a +Subproject commit 4396b3689719ac292f9628752b5b1c78288ab2e7 From d6c2e9063ada43c34c9634406c1d3e3380b063a3 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Mon, 22 Feb 2021 11:16:38 +0800 Subject: [PATCH 12/35] 1.2 channel cleanup --- docs/software/TODO.md | 1 + proto | 2 +- src/mesh/Channels.cpp | 70 +++++++++++------------- src/mesh/Channels.h | 94 ++++++++++++++++++++------------ src/mesh/generated/portnums.pb.h | 2 +- 5 files changed, 94 insertions(+), 75 deletions(-) diff --git a/docs/software/TODO.md b/docs/software/TODO.md index c4769c2ef..b30b58795 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -17,6 +17,7 @@ You probably don't care about this section - skip to the next one. * DONE remove region specific builds from the firmware * restrict settings operations to the admin channel * add gui in android app for setting region +* make an alpha channel for the python API * "FIXME - move the radioconfig/user/channel READ operations into SettingsMessage as well" * DONE scrub protobufs to make sure they are absoloute minimum wiresize (in particular Data, ChannelSets and positions) * change syncword diff --git a/proto b/proto index 4396b3689..6421b29ef 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 4396b3689719ac292f9628752b5b1c78288ab2e7 +Subproject commit 6421b29ef45dbd34d7c6c43f4be48a7906e66ad9 diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp index dc1383bdf..8b5d5cb6b 100644 --- a/src/mesh/Channels.cpp +++ b/src/mesh/Channels.cpp @@ -1,13 +1,9 @@ #include "Channels.h" -#include "NodeDB.h" #include "CryptoEngine.h" +#include "NodeDB.h" #include -/// A usable psk - which has been constructed based on the (possibly short psk) in channelSettings -static uint8_t activePSK[32]; -static uint8_t activePSKSize; - /// 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}; @@ -17,19 +13,19 @@ Channels channels; /** * Validate a channel, fixing any errors as needed */ -Channel &fixupChannel(size_t chIndex) +Channel &Channels::fixupChannel(ChannelIndex chIndex) { - assert(chIndex < devicestate.channels_count); + auto ch = getByIndex(chIndex); - Channel *ch = devicestate.channels + chIndex; + ch.index = chIndex; // Preinit the index so it be ready to share with the phone (we'll never change it later) - ch->index = chIndex; // Preinit the index so it be ready to share with the phone (we'll never change it later) - - if (!ch->has_settings) { + if (!ch.has_settings) { // No settings! Must disable and skip - ch->role = Channel_Role_DISABLED; + ch.role = Channel_Role_DISABLED; + memset(&ch.settings, 0, sizeof(ch.settings)); + ch.has_settings = true; } else { - ChannelSettings &channelSettings = ch->settings; + ChannelSettings &channelSettings = ch.settings; // Convert the old string "Default" to our new short representation if (strcmp(channelSettings.name, "Default") == 0) @@ -43,19 +39,16 @@ Channel &fixupChannel(size_t chIndex) } } - return *ch; + return ch; } - - /** * Write a default channel to the specified channel index */ -void initDefaultChannel(size_t chIndex) +void Channels::initDefaultChannel(ChannelIndex chIndex) { - assert(chIndex < devicestate.channels_count); - Channel *ch = devicestate.channels + chIndex; - ChannelSettings &channelSettings = ch->settings; + auto ch = getByIndex(chIndex); + ChannelSettings &channelSettings = ch.settings; // radioConfig.modem_config = RadioConfig_ModemConfig_Bw125Cr45Sf128; // medium range and fast // channelSettings.modem_config = ChannelSettings_ModemConfig_Bw500Cr45Sf128; // short range and fast, but wide @@ -68,30 +61,28 @@ void initDefaultChannel(size_t chIndex) channelSettings.psk.size = 1; strcpy(channelSettings.name, ""); - ch->has_settings = true; - ch->role = Channel_Role_PRIMARY; + ch.has_settings = true; + ch.role = Channel_Role_PRIMARY; } /** Given a channel index, change to use the crypto key specified by that index */ -void Channels::setCrypto(size_t chIndex) +void Channels::setCrypto(ChannelIndex chIndex) { - assert(chIndex < devicestate.channels_count); - Channel *ch = devicestate.channels + chIndex; - ChannelSettings &channelSettings = ch->settings; - assert(ch->has_settings); + auto ch = getByIndex(chIndex); + ChannelSettings &channelSettings = ch.settings; + assert(ch.has_settings); memset(activePSK, 0, sizeof(activePSK)); // In case the user provided a short key, we want to pad the rest with zeros memcpy(activePSK, channelSettings.psk.bytes, channelSettings.psk.size); activePSKSize = channelSettings.psk.size; if (activePSKSize == 0) { - if(ch->role == Channel_Role_SECONDARY) { - DEBUG_MSG("Unset PSK for secondary channel %s. using primary key\n", ch->settings.name); + if (ch.role == Channel_Role_SECONDARY) { + DEBUG_MSG("Unset PSK for secondary channel %s. using primary key\n", ch.settings.name); setCrypto(primaryIndex); } else DEBUG_MSG("Warning: User disabled encryption\n"); - } - else if (activePSKSize == 1) { + } else if (activePSKSize == 1) { // Convert the short single byte variants of psk into variant that can be used more generally uint8_t pskIndex = activePSK[0]; @@ -135,27 +126,28 @@ void Channels::onConfigChanged() for (int i = 0; i < devicestate.channels_count; i++) { auto ch = fixupChannel(i); - if(ch.role == Channel_Role_PRIMARY) + if (ch.role == Channel_Role_PRIMARY) primaryIndex = i; } setCrypto(primaryIndex); // FIXME: for the time being (still single channel - just use our only channel as the crypto key) } -Channel &Channels::getChannel(size_t chIndex) +Channel &Channels::getByIndex(ChannelIndex chIndex) { assert(chIndex < devicestate.channels_count); Channel *ch = devicestate.channels + chIndex; return *ch; } -void Channels::setChannel(const Channel &c) { - Channel &old = getChannel(c.index); +void Channels::setChannel(const Channel &c) +{ + Channel &old = getByIndex(c.index); // if this is the new primary, demote any existing roles - if(c.role == Channel_Role_PRIMARY) - for (int i = 0; i < devicestate.channels_count; i++) - if(devicestate.channels[i].role == Channel_Role_PRIMARY) + if (c.role == Channel_Role_PRIMARY) + for (int i = 0; i < devicestate.channels_count; i++) + if (devicestate.channels[i].role == Channel_Role_PRIMARY) devicestate.channels[i].role = Channel_Role_SECONDARY; old = c; // slam in the new settings/role @@ -164,7 +156,7 @@ void Channels::setChannel(const Channel &c) { const char *Channels::getName(size_t chIndex) { // Convert the short "" representation for Default into a usable string - ChannelSettings &channelSettings = getChannel(chIndex).settings; + ChannelSettings &channelSettings = getByIndex(chIndex).settings; const char *channelName = channelSettings.name; if (!*channelName) { // emptystring // Per mesh.proto spec, if bandwidth is specified we must ignore modemConfig enum, we assume that in that case diff --git a/src/mesh/Channels.h b/src/mesh/Channels.h index ec64cd49b..913c316dc 100644 --- a/src/mesh/Channels.h +++ b/src/mesh/Channels.h @@ -3,41 +3,57 @@ #include "mesh-pb-constants.h" #include +typedef uint8_t ChannelIndex; +typedef uint8_t ChannelHash; + +/** The container/on device API for working with channels */ class Channels { - size_t primaryIndex = 0; - + /// The index of the primary channel + ChannelIndex primaryIndex = 0; + + /** The channel index that was requested for sending/receving. Note: if this channel is a secondary + channel and does not have a PSK, we will use the PSK from the primary channel. If this channel is disabled + no sending or receiving will be allowed */ + ChannelIndex activeChannelIndex = 0; + + /// The in-use psk - which has been constructed based on the (possibly short psk) in channelSettings + uint8_t activePSK[32]; + uint8_t activePSKSize = 0; + public: - const ChannelSettings &getPrimary() { return getChannel(getPrimaryIndex()).settings; } + const ChannelSettings &getPrimary() { return getByIndex(getPrimaryIndex()).settings; } - Channel &getChannel(size_t chIndex); + /** Return the Channel for a specified index */ + Channel &getByIndex(ChannelIndex chIndex); - /** Using the index inside the channel, update the specified channel's settings and role. If this channel is being promoted to be - * primary, force all other channels to be secondary. + /** Using the index inside the channel, update the specified channel's settings and role. If this channel is being promoted + * to be primary, force all other channels to be secondary. */ void setChannel(const Channel &c); const char *getName(size_t chIndex); /** The index of the primary channel */ - size_t getPrimaryIndex() const { return primaryIndex; } + ChannelIndex getPrimaryIndex() const { return primaryIndex; } /** - * Generate a short suffix used to disambiguate channels that might have the same "name" entered by the human but different PSKs. - * The ideas is that the PSK changing should be visible to the user so that they see they probably messed up and that's why they -their nodes - * aren't talking to each other. - * - * This string is of the form "#name-X". - * - * Where X is either: - * (for custom PSKS) a letter from A to Z (base26), and formed by xoring all the bytes of the PSK together, - * OR (for the standard minimially secure PSKs) a number from 0 to 9. - * - * This function will also need to be implemented in GUI apps that talk to the radio. - * - * https://github.com/meshtastic/Meshtastic-device/issues/269 - */ + * Generate a short suffix used to disambiguate channels that might have the same "name" entered by the human but different + PSKs. + * The ideas is that the PSK changing should be visible to the user so that they see they probably messed up and that's why + they their nodes + * aren't talking to each other. + * + * This string is of the form "#name-X". + * + * Where X is either: + * (for custom PSKS) a letter from A to Z (base26), and formed by xoring all the bytes of the PSK together, + * OR (for the standard minimially secure PSKs) a number from 0 to 9. + * + * This function will also need to be implemented in GUI apps that talk to the radio. + * + * https://github.com/meshtastic/Meshtastic-device/issues/269 + */ const char *getPrimaryName(); /// Called by NodeDB on initial boot when the radio config settings are unset. Set a default single channel config. @@ -47,33 +63,43 @@ their nodes void onConfigChanged(); /** Given a channel hash setup crypto for decoding that channel (or the primary channel if that channel is unsecured) - * + * * This method is called before decoding inbound packets - * + * * @return false if no suitable channel could be found. */ - bool setCryptoByHash(uint8_t channelHash); + bool setActiveByHash(ChannelHash channelHash); /** Given a channel index setup crypto for encoding that channel (or the primary channel if that channel is unsecured) - * + * * This method is called before encoding inbound packets - * + * * @eturn the (0 to 255) hash for that channel - if no suitable channel could be found, return -1 */ - int16_t setCryptoByIndex(uint8_t channelIndex); + int16_t setActiveByIndex(ChannelIndex channelIndex); -private: + private: /** Given a channel index, change to use the crypto key specified by that index */ - void setCrypto(size_t chIndex); + void setCrypto(ChannelIndex chIndex); /** Return the channel index for the specified channel hash, or -1 for not found */ - int8_t getChannelIndexByHash(uint8_t channelHash); + int8_t getIndexByHash(ChannelHash channelHash); - /** Given a channel number, return the (0 to 255) hash for that channel + /** Given a channel number, return the (0 to 255) hash for that channel * If no suitable channel could be found, return -1 - */ - int16_t getChannelHash(size_t channelNum); + */ + int16_t getHash(ChannelIndex channelNum); + + /** + * Validate a channel, fixing any errors as needed + */ + Channel &fixupChannel(ChannelIndex chIndex); + + /** + * Write a default channel to the specified channel index + */ + void initDefaultChannel(ChannelIndex chIndex); }; /// Singleton channel table diff --git a/src/mesh/generated/portnums.pb.h b/src/mesh/generated/portnums.pb.h index 758db47a6..5904a548c 100644 --- a/src/mesh/generated/portnums.pb.h +++ b/src/mesh/generated/portnums.pb.h @@ -20,10 +20,10 @@ typedef enum _PortNum { PortNum_ADMIN_APP = 6, PortNum_REPLY_APP = 32, PortNum_IP_TUNNEL_APP = 33, - PortNum_ENVIRONMENTAL_MEASUREMENT_APP = 34, PortNum_SERIAL_APP = 64, PortNum_STORE_FORWARD_APP = 65, PortNum_RANGE_TEST_APP = 66, + PortNum_ENVIRONMENTAL_MEASUREMENT_APP = 67, PortNum_PRIVATE_APP = 256, PortNum_ATAK_FORWARDER = 257, PortNum_MAX = 511 From 923ecc9d8a0e4d1ba0e65f909d39f421ddd2d4dc Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Mon, 22 Feb 2021 12:57:03 +0800 Subject: [PATCH 13/35] fix printf warnings --- platformio.ini | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 2ae37ea31..09ac280f6 100644 --- a/platformio.ini +++ b/platformio.ini @@ -34,7 +34,9 @@ extra_scripts = bin/platformio-custom.py ; note: we add src to our include search path so that lmic_project_config can override ; FIXME: fix lib/BluetoothOTA dependency back on src/ so we can remove -Isrc -build_flags = -Wno-missing-field-initializers -Isrc -Isrc/mesh -Isrc/gps -Ilib/nanopb/include -Wl,-Map,.pio/build/output.map +build_flags = -Wno-missing-field-initializers + -Wno-format + -Isrc -Isrc/mesh -Isrc/gps -Ilib/nanopb/include -Wl,-Map,.pio/build/output.map -DHW_VERSION_${sysenv.COUNTRY} -DHW_VERSION=${sysenv.HW_VERSION} -DUSE_THREAD_NAMES From 94cd96cfdea1cb2387c807e0fb8a4089b0ccabb0 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Mon, 22 Feb 2021 12:57:26 +0800 Subject: [PATCH 14/35] begin multichannel hash impl --- proto | 2 +- src/mesh/Channels.cpp | 49 +++++++++++++---- src/mesh/Channels.h | 20 +++++-- src/mesh/MeshTypes.h | 2 + src/mesh/RadioInterface.cpp | 4 +- src/mesh/RadioInterface.h | 3 ++ src/mesh/RadioLibInterface.cpp | 1 + src/mesh/Router.cpp | 84 ++++++++++++++++++------------ src/mesh/Router.h | 3 ++ src/mesh/generated/deviceonly.pb.h | 2 +- src/mesh/generated/mesh.pb.h | 18 ++++--- 11 files changed, 129 insertions(+), 59 deletions(-) diff --git a/proto b/proto index 6421b29ef..f6ff4cc0c 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 6421b29ef45dbd34d7c6c43f4be48a7906e66ad9 +Subproject commit f6ff4cc0c98b201342c32776eeeb9ace83b450dd diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp index 8b5d5cb6b..696f78f4f 100644 --- a/src/mesh/Channels.cpp +++ b/src/mesh/Channels.cpp @@ -10,12 +10,20 @@ static const uint8_t defaultpsk[] = {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0 Channels channels; +uint8_t xorHash(uint8_t *p, size_t len) +{ + uint8_t code = 0; + for (int i = 0; i < len; i++) + code ^= p[i]; + return code; +} + /** * Validate a channel, fixing any errors as needed */ Channel &Channels::fixupChannel(ChannelIndex chIndex) { - auto ch = getByIndex(chIndex); + Channel &ch = getByIndex(chIndex); ch.index = chIndex; // Preinit the index so it be ready to share with the phone (we'll never change it later) @@ -31,14 +39,16 @@ Channel &Channels::fixupChannel(ChannelIndex chIndex) if (strcmp(channelSettings.name, "Default") == 0) *channelSettings.name = '\0'; - // Convert any old usage of the defaultpsk into our new short representation. + /* Convert any old usage of the defaultpsk into our new short representation. if (channelSettings.psk.size == sizeof(defaultpsk) && memcmp(channelSettings.psk.bytes, defaultpsk, sizeof(defaultpsk)) == 0) { *channelSettings.psk.bytes = 1; channelSettings.psk.size = 1; - } + } */ } + hashes[chIndex] = generateHash(chIndex); + return ch; } @@ -47,7 +57,7 @@ Channel &Channels::fixupChannel(ChannelIndex chIndex) */ void Channels::initDefaultChannel(ChannelIndex chIndex) { - auto ch = getByIndex(chIndex); + Channel &ch = getByIndex(chIndex); ChannelSettings &channelSettings = ch.settings; // radioConfig.modem_config = RadioConfig_ModemConfig_Bw125Cr45Sf128; // medium range and fast @@ -69,7 +79,7 @@ void Channels::initDefaultChannel(ChannelIndex chIndex) */ void Channels::setCrypto(ChannelIndex chIndex) { - auto ch = getByIndex(chIndex); + Channel &ch = getByIndex(chIndex); ChannelSettings &channelSettings = ch.settings; assert(ch.has_settings); @@ -124,7 +134,7 @@ void Channels::onConfigChanged() { // Make sure the phone hasn't mucked anything up for (int i = 0; i < devicestate.channels_count; i++) { - auto ch = fixupChannel(i); + Channel &ch = fixupChannel(i); if (ch.role == Channel_Role_PRIMARY) primaryIndex = i; @@ -211,9 +221,7 @@ const char *Channels::getPrimaryName() auto channelSettings = getPrimary(); if (channelSettings.psk.size != 1) { // We have a standard PSK, so generate a letter based hash. - uint8_t code = 0; - for (int i = 0; i < activePSKSize; i++) - code ^= activePSK[i]; + uint8_t code = xorHash(activePSK, activePSKSize); suffix = 'A' + (code % 26); } else { @@ -222,4 +230,25 @@ const char *Channels::getPrimaryName() snprintf(buf, sizeof(buf), "#%s-%c", channelSettings.name, suffix); return buf; -} \ No newline at end of file +} + +/** Given a channel hash setup crypto for decoding that channel (or the primary channel if that channel is unsecured) + * + * This method is called before decoding inbound packets + * + * @return -1 if no suitable channel could be found, otherwise returns the channel index + */ +int16_t Channels::setActiveByHash(ChannelHash channelHash) {} + +/** Given a channel index setup crypto for encoding that channel (or the primary channel if that channel is unsecured) + * + * This method is called before encoding outbound packets + * + * @eturn the (0 to 255) hash for that channel - if no suitable channel could be found, return -1 + */ +int16_t Channels::setActiveByIndex(ChannelIndex channelIndex) {} + +/** Given a channel number, return the (0 to 255) hash for that channel + * If no suitable channel could be found, return -1 + */ +ChannelHash Channels::generateHash(ChannelIndex channelNum) {} \ No newline at end of file diff --git a/src/mesh/Channels.h b/src/mesh/Channels.h index 913c316dc..a86b7ff68 100644 --- a/src/mesh/Channels.h +++ b/src/mesh/Channels.h @@ -3,7 +3,13 @@ #include "mesh-pb-constants.h" #include +/** A channel number (index into the channel table) + */ typedef uint8_t ChannelIndex; + +/** A low quality hash of the channel PSK and the channel name. created by generateHash(chIndex) + * Used as a hint to limit which PSKs are considered for packet decoding. +*/ typedef uint8_t ChannelHash; /** The container/on device API for working with channels */ @@ -21,6 +27,9 @@ class Channels uint8_t activePSK[32]; uint8_t activePSKSize = 0; + /// the precomputed hashes for each of our channels + ChannelHash hashes[MAX_NUM_CHANNELS]; + public: const ChannelSettings &getPrimary() { return getByIndex(getPrimaryIndex()).settings; } @@ -66,18 +75,21 @@ class Channels * * This method is called before decoding inbound packets * - * @return false if no suitable channel could be found. + * @return -1 if no suitable channel could be found, otherwise returns the channel index */ - bool setActiveByHash(ChannelHash channelHash); + int16_t setActiveByHash(ChannelHash channelHash); /** Given a channel index setup crypto for encoding that channel (or the primary channel if that channel is unsecured) * - * This method is called before encoding inbound packets + * This method is called before encoding outbound packets * * @eturn the (0 to 255) hash for that channel - if no suitable channel could be found, return -1 */ int16_t setActiveByIndex(ChannelIndex channelIndex); + /** return the channel hash we are currently using for sending */ + ChannelHash getActiveHash(); + private: /** Given a channel index, change to use the crypto key specified by that index */ @@ -89,7 +101,7 @@ class Channels /** Given a channel number, return the (0 to 255) hash for that channel * If no suitable channel could be found, return -1 */ - int16_t getHash(ChannelIndex channelNum); + ChannelHash generateHash(ChannelIndex channelNum); /** * Validate a channel, fixing any errors as needed diff --git a/src/mesh/MeshTypes.h b/src/mesh/MeshTypes.h index 69e782b12..06f2bf480 100644 --- a/src/mesh/MeshTypes.h +++ b/src/mesh/MeshTypes.h @@ -14,6 +14,8 @@ typedef uint32_t PacketId; // A packet sequence number #define ERRNO_NO_INTERFACES 33 #define ERRNO_UNKNOWN 32 // pick something that doesn't conflict with RH_ROUTER_ERROR_UNABLE_TO_DELIVER #define ERRNO_DISABLED 34 // the itnerface is disabled +#define ERRNO_TOO_LARGE 35 +#define ERRNO_NO_CHANNEL 36 /** * the max number of hops a message can pass through, used as the default max for hop_limit in MeshPacket. diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 08ac40d5d..93dd55e80 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -10,6 +10,7 @@ #include #include #include +#include "Channels.h" #define RDEF(name, freq, spacing, num_ch, power_limit) \ { \ @@ -157,7 +158,7 @@ void printPacket(const char *prefix, const MeshPacket *p) RadioInterface::RadioInterface() { - assert(sizeof(PacketHeader) == 4 || sizeof(PacketHeader) == 16); // make sure the compiler did what we expected + assert(sizeof(PacketHeader) == 16); // make sure the compiler did what we expected // Can't print strings this early - serial not setup yet // DEBUG_MSG("Set meshradio defaults name=%s\n", channelSettings.name); @@ -350,6 +351,7 @@ size_t RadioInterface::beginSending(MeshPacket *p) h->from = p->from; h->to = p->to; h->id = p->id; + h->channel = p->channel; assert(p->hop_limit <= HOP_MAX); h->flags = p->hop_limit | (p->want_ack ? PACKET_FLAGS_WANT_ACK_MASK : 0); diff --git a/src/mesh/RadioInterface.h b/src/mesh/RadioInterface.h index 5efad0ae4..9d19fa590 100644 --- a/src/mesh/RadioInterface.h +++ b/src/mesh/RadioInterface.h @@ -29,6 +29,9 @@ typedef struct { * The bottom three bits of flags are use to store hop_limit when sent over the wire. **/ uint8_t flags; + + /** The channel hash - used as a hint for the decoder to limit which channels we consider */ + uint8_t channel; } PacketHeader; /** diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index 63d7095c5..ab1728126 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -274,6 +274,7 @@ void RadioLibInterface::handleReceiveInterrupt() mp->from = h->from; mp->to = h->to; mp->id = h->id; + mp->channel = h->id; assert(HOP_MAX <= PACKET_FLAGS_HOP_MASK); // If hopmax changes, carefully check this code mp->hop_limit = h->flags & PACKET_FLAGS_HOP_MASK; mp->want_ack = !!(h->flags & PACKET_FLAGS_WANT_ACK_MASK); diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 673fafefd..434bdde5d 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -1,9 +1,10 @@ #include "Router.h" +#include "Channels.h" #include "CryptoEngine.h" +#include "NodeDB.h" #include "RTC.h" #include "configuration.h" #include "mesh-pb-constants.h" -#include #include "plugins/RoutingPlugin.h" /** @@ -107,7 +108,12 @@ void Router::sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom) routingPlugin->sendAckNak(err, to, idFrom); } - +void Router::abortSendAndNak(Routing_Error err, MeshPacket *p) +{ + DEBUG_MSG("Error=%d, returning NAK and dropping packet.\n", err); + sendAckNak(Routing_Error_NO_INTERFACE, p->from, p->id); + packetPool.release(p); +} ErrorCode Router::sendLocal(MeshPacket *p) { @@ -118,11 +124,7 @@ ErrorCode Router::sendLocal(MeshPacket *p) return ERRNO_OK; } else if (!iface) { // We must be sending to remote nodes also, fail if no interface found - - // ERROR! no radio found, report failure back to the client and drop the packet - DEBUG_MSG("Error: No interface, returning NAK and dropping packet.\n"); - sendAckNak(Routing_Error_NO_INTERFACE, p->from, p->id); - packetPool.release(p); + abortSendAndNak(Routing_Error_NO_INTERFACE, p); return ERRNO_NO_INTERFACES; } else { @@ -146,7 +148,8 @@ ErrorCode Router::send(MeshPacket *p) assert(p->to != nodeDB.getNodeNum()); // should have already been handled by sendLocal // PacketId nakId = p->decoded.which_ackVariant == SubPacket_fail_id_tag ? p->decoded.ackVariant.fail_id : 0; - // assert(!nakId); // I don't think we ever send 0hop naks over the wire (other than to the phone), test that assumption with assert + // assert(!nakId); // I don't think we ever send 0hop naks over the wire (other than to the phone), test that assumption with + // assert // Never set the want_ack flag on broadcast packets sent over the air. if (p->to == NODENUM_BROADCAST) @@ -163,7 +166,20 @@ ErrorCode Router::send(MeshPacket *p) size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), Data_fields, &p->decoded); - assert(numbytes <= MAX_RHPACKETLEN); + if (numbytes > MAX_RHPACKETLEN) { + abortSendAndNak(Routing_Error_TOO_LARGE, p); + return ERRNO_TOO_LARGE; + } + + auto hash = channels.setActiveByIndex(p->channel); + if (hash < 0) { + // No suitable channel could be found for sending + abortSendAndNak(Routing_Error_NO_CHANNEL, p); + return ERRNO_NO_CHANNEL; + } + + // Now that we are encrypting the packet channel should be the hash (no longer the index) + p->channel = hash; crypto->encrypt(p->from, p->id, numbytes, bytes); // Copy back into the packet and set the variant type @@ -173,23 +189,15 @@ ErrorCode Router::send(MeshPacket *p) } assert(iface); // This should have been detected already in sendLocal (or we just received a packet from outside) - // if (iface) { - // DEBUG_MSG("Sending packet via interface fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id); return iface->send(p); - /* } else { - DEBUG_MSG("Dropping packet - no interfaces - fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id); - packetPool.release(p); - return ERRNO_NO_INTERFACES; - } */ } /** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */ -bool Router::cancelSending(NodeNum from, PacketId id) { +bool Router::cancelSending(NodeNum from, PacketId id) +{ return iface ? iface->cancelSending(from, id) : false; } - - /** * Every (non duplicate) packet this node receives will be passed through this method. This allows subclasses to * update routing tables etc... based on what we overhear (even for messages not destined to our node) @@ -207,22 +215,30 @@ bool Router::perhapsDecode(MeshPacket *p) assert(p->which_payloadVariant == MeshPacket_encrypted_tag); - // FIXME - someday don't send routing packets encrypted. That would allow us to route for other channels without - // being able to decrypt their data. - // Try to decrypt the packet if we can - static uint8_t bytes[MAX_RHPACKETLEN]; - memcpy(bytes, p->encrypted.bytes, - p->encrypted.size); // we have to copy into a scratch buffer, because these bytes are a union with the decoded protobuf - crypto->decrypt(p->from, p->id, p->encrypted.size, bytes); - - // Take those raw bytes and convert them back into a well structured protobuf we can understand - if (!pb_decode_from_bytes(bytes, p->encrypted.size, Data_fields, &p->decoded)) { - DEBUG_MSG("Invalid protobufs in received mesh packet!\n"); + ChannelHash chHash = p->channel; + int16_t chIndex = channels.setActiveByHash(chHash); + if (chIndex < 0) { + DEBUG_MSG("No suitable channel found for decoding, hash was 0x%x!\n", chHash); return false; } else { - // parsing was successful - p->which_payloadVariant = MeshPacket_decoded_tag; - return true; + p->channel = chIndex; + + // Try to decrypt the packet if we can + static uint8_t bytes[MAX_RHPACKETLEN]; + memcpy(bytes, p->encrypted.bytes, + p->encrypted + .size); // we have to copy into a scratch buffer, because these bytes are a union with the decoded protobuf + crypto->decrypt(p->from, p->id, p->encrypted.size, bytes); + + // Take those raw bytes and convert them back into a well structured protobuf we can understand + if (!pb_decode_from_bytes(bytes, p->encrypted.size, Data_fields, &p->decoded)) { + DEBUG_MSG("Invalid protobufs in received mesh packet!\n"); + return false; + } else { + // parsing was successful + p->which_payloadVariant = MeshPacket_decoded_tag; + return true; + } } } @@ -244,7 +260,7 @@ void Router::handleReceived(MeshPacket *p) if (perhapsDecode(p)) { // parsing was successful, queue for our recipient - // call any promiscious plugins here, make a (non promisiocous) plugin for forwarding messages to phone api + // call any promiscious plugins here, make a (non promisiocous) plugin for forwarding messages to phone api // sniffReceived(p); MeshPlugin::callPlugins(*p); } diff --git a/src/mesh/Router.h b/src/mesh/Router.h index 4b1656936..6e6bf2c2a 100644 --- a/src/mesh/Router.h +++ b/src/mesh/Router.h @@ -123,6 +123,9 @@ class Router : protected concurrency::OSThread * Note: this method will free the provided packet. */ void handleReceived(MeshPacket *p); + + /** Frees the provided packet, and generates a NAK indicating the speicifed error while sending */ + void abortSendAndNak(Routing_Error err, MeshPacket *p); }; extern Router *router; diff --git a/src/mesh/generated/deviceonly.pb.h b/src/mesh/generated/deviceonly.pb.h index b8c372664..9ec3fa5a0 100644 --- a/src/mesh/generated/deviceonly.pb.h +++ b/src/mesh/generated/deviceonly.pb.h @@ -80,7 +80,7 @@ extern const pb_msgdesc_t DeviceState_msg; #define DeviceState_fields &DeviceState_msg /* Maximum encoded size of messages (where known) */ -#define DeviceState_size 6119 +#define DeviceState_size 6125 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/mesh.pb.h b/src/mesh/generated/mesh.pb.h index 873e0aa2f..6858cdcd9 100644 --- a/src/mesh/generated/mesh.pb.h +++ b/src/mesh/generated/mesh.pb.h @@ -80,7 +80,9 @@ typedef enum _Routing_Error { Routing_Error_GOT_NAK = 2, Routing_Error_TIMEOUT = 3, Routing_Error_NO_INTERFACE = 4, - Routing_Error_MAX_RETRANSMIT = 5 + Routing_Error_MAX_RETRANSMIT = 5, + Routing_Error_NO_CHANNEL = 6, + Routing_Error_TOO_LARGE = 7 } Routing_Error; typedef enum _MeshPacket_Priority { @@ -240,7 +242,7 @@ typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t; typedef struct _MeshPacket { uint32_t from; uint32_t to; - uint8_t channel_index; + uint32_t channel; pb_size_t which_payloadVariant; union { Data decoded; @@ -340,8 +342,8 @@ typedef struct _ToRadio { #define _CriticalErrorCode_ARRAYSIZE ((CriticalErrorCode)(CriticalErrorCode_TransmitFailed+1)) #define _Routing_Error_MIN Routing_Error_NONE -#define _Routing_Error_MAX Routing_Error_MAX_RETRANSMIT -#define _Routing_Error_ARRAYSIZE ((Routing_Error)(Routing_Error_MAX_RETRANSMIT+1)) +#define _Routing_Error_MAX Routing_Error_TOO_LARGE +#define _Routing_Error_ARRAYSIZE ((Routing_Error)(Routing_Error_TOO_LARGE+1)) #define _MeshPacket_Priority_MIN MeshPacket_Priority_UNSET #define _MeshPacket_Priority_MAX MeshPacket_Priority_MAX @@ -488,7 +490,7 @@ extern "C" { #define Channel_role_tag 3 #define MeshPacket_from_tag 1 #define MeshPacket_to_tag 2 -#define MeshPacket_channel_index_tag 3 +#define MeshPacket_channel_tag 3 #define MeshPacket_decoded_tag 4 #define MeshPacket_encrypted_tag 5 #define MeshPacket_id_tag 6 @@ -571,7 +573,7 @@ X(a, STATIC, SINGULAR, FIXED32, source, 5) #define MeshPacket_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, FIXED32, from, 1) \ X(a, STATIC, SINGULAR, FIXED32, to, 2) \ -X(a, STATIC, SINGULAR, UINT32, channel_index, 3) \ +X(a, STATIC, SINGULAR, UINT32, channel, 3) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,decoded,decoded), 4) \ X(a, STATIC, ONEOF, BYTES, (payloadVariant,encrypted,encrypted), 5) \ X(a, STATIC, SINGULAR, FIXED32, id, 6) \ @@ -771,7 +773,7 @@ extern const pb_msgdesc_t AdminMessage_msg; #define RouteDiscovery_size 40 #define Routing_size 47 #define Data_size 255 -#define MeshPacket_size 294 +#define MeshPacket_size 297 #define ChannelSettings_size 87 #define Channel_size 94 #define RadioConfig_size 308 @@ -780,7 +782,7 @@ extern const pb_msgdesc_t AdminMessage_msg; #define MyNodeInfo_size 89 #define LogRecord_size 81 #define FromRadio_size 317 -#define ToRadio_size 297 +#define ToRadio_size 300 #define AdminMessage_size 311 #ifdef __cplusplus From 2761c855640723f1a8f8c5c5cb27c3c6ffda3a73 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Tue, 23 Feb 2021 10:10:35 +0800 Subject: [PATCH 15/35] clean up the crypto api --- src/esp32/ESP32CryptoEngine.cpp | 15 +-- src/mesh/Channels.cpp | 142 ++++++++++++-------- src/mesh/Channels.h | 29 ++-- src/mesh/CryptoEngine.cpp | 5 +- src/mesh/CryptoEngine.h | 11 +- src/nrf52/NRF52CryptoEngine.cpp | 27 +--- src/portduino/CrossPlatformCryptoEngine.cpp | 11 +- 7 files changed, 135 insertions(+), 105 deletions(-) diff --git a/src/esp32/ESP32CryptoEngine.cpp b/src/esp32/ESP32CryptoEngine.cpp index 613d5cc17..9d86ffeb0 100644 --- a/src/esp32/ESP32CryptoEngine.cpp +++ b/src/esp32/ESP32CryptoEngine.cpp @@ -18,9 +18,6 @@ class ESP32CryptoEngine : public CryptoEngine mbedtls_aes_context aes; - /// How many bytes in our key - uint8_t keySize = 0; - public: ESP32CryptoEngine() { mbedtls_aes_init(&aes); } @@ -35,12 +32,12 @@ class ESP32CryptoEngine : public CryptoEngine * @param bytes a _static_ buffer that will remain valid for the life of this crypto instance (i.e. this class will cache the * provided pointer) */ - virtual void setKey(size_t numBytes, uint8_t *bytes) + virtual void setKey(const CryptoKey &k) { - keySize = numBytes; - DEBUG_MSG("Installing AES%d key!\n", numBytes * 8); - if (numBytes != 0) { - auto res = mbedtls_aes_setkey_enc(&aes, bytes, numBytes * 8); + CryptoEngine::setKey(k); + + if (key.length != 0) { + auto res = mbedtls_aes_setkey_enc(&aes, key.bytes, key.length * 8); assert(!res); } } @@ -52,7 +49,7 @@ class ESP32CryptoEngine : public CryptoEngine */ virtual void encrypt(uint32_t fromNode, uint64_t packetNum, size_t numBytes, uint8_t *bytes) { - if (keySize != 0) { + if (key.length > 0) { uint8_t stream_block[16]; static uint8_t scratch[MAX_BLOCKSIZE]; size_t nc_off = 0; diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp index 696f78f4f..f3238b9c5 100644 --- a/src/mesh/Channels.cpp +++ b/src/mesh/Channels.cpp @@ -10,7 +10,7 @@ static const uint8_t defaultpsk[] = {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0 Channels channels; -uint8_t xorHash(uint8_t *p, size_t len) +uint8_t xorHash(const uint8_t *p, size_t len) { uint8_t code = 0; for (int i = 0; i < len; i++) @@ -18,6 +18,26 @@ uint8_t xorHash(uint8_t *p, size_t len) return code; } +/** Given a channel number, return the (0 to 255) hash for that channel. + * The hash is just an xor of the channel name followed by the channel PSK being used for encryption + * If no suitable channel could be found, return -1 + */ +int16_t Channels::generateHash(ChannelIndex channelNum) +{ + auto k = getKey(channelNum); + if (k.length < 0) + return -1; // invalid + else { + Channel &c = getByIndex(channelNum); + + uint8_t h = xorHash((const uint8_t *)c.settings.name, strlen(c.settings.name)); + + h ^= xorHash(k.bytes, k.length); + + return h; + } +} + /** * Validate a channel, fixing any errors as needed */ @@ -75,51 +95,69 @@ void Channels::initDefaultChannel(ChannelIndex chIndex) ch.role = Channel_Role_PRIMARY; } -/** Given a channel index, change to use the crypto key specified by that index - */ -void Channels::setCrypto(ChannelIndex chIndex) +CryptoKey Channels::getKey(ChannelIndex chIndex) { Channel &ch = getByIndex(chIndex); ChannelSettings &channelSettings = ch.settings; assert(ch.has_settings); - memset(activePSK, 0, sizeof(activePSK)); // In case the user provided a short key, we want to pad the rest with zeros - memcpy(activePSK, channelSettings.psk.bytes, channelSettings.psk.size); - activePSKSize = channelSettings.psk.size; - if (activePSKSize == 0) { - if (ch.role == Channel_Role_SECONDARY) { - DEBUG_MSG("Unset PSK for secondary channel %s. using primary key\n", ch.settings.name); - setCrypto(primaryIndex); - } else - DEBUG_MSG("Warning: User disabled encryption\n"); - } else if (activePSKSize == 1) { - // Convert the short single byte variants of psk into variant that can be used more generally + CryptoKey k; + memset(k.bytes, 0, sizeof(k.bytes)); // In case the user provided a short key, we want to pad the rest with zeros - uint8_t pskIndex = activePSK[0]; - DEBUG_MSG("Expanding short PSK #%d\n", pskIndex); - if (pskIndex == 0) - activePSKSize = 0; // Turn off encryption - else { - memcpy(activePSK, defaultpsk, sizeof(defaultpsk)); - activePSKSize = sizeof(defaultpsk); - // Bump up the last byte of PSK as needed - uint8_t *last = activePSK + sizeof(defaultpsk) - 1; - *last = *last + pskIndex - 1; // index of 1 means no change vs defaultPSK + if (ch.role == Channel_Role_DISABLED) { + k.length = -1; // invalid + } else { + memcpy(k.bytes, channelSettings.psk.bytes, channelSettings.psk.size); + k.length = channelSettings.psk.size; + if (k.length == 0) { + if (ch.role == Channel_Role_SECONDARY) { + DEBUG_MSG("Unset PSK for secondary channel %s. using primary key\n", ch.settings.name); + k = getKey(primaryIndex); + } else + DEBUG_MSG("Warning: User disabled encryption\n"); + } else if (k.length == 1) { + // Convert the short single byte variants of psk into variant that can be used more generally + + uint8_t pskIndex = k.bytes[0]; + DEBUG_MSG("Expanding short PSK #%d\n", pskIndex); + if (pskIndex == 0) + k.length = 0; // Turn off encryption + else { + memcpy(k.bytes, defaultpsk, sizeof(defaultpsk)); + k.length = sizeof(defaultpsk); + // Bump up the last byte of PSK as needed + uint8_t *last = k.bytes + sizeof(defaultpsk) - 1; + *last = *last + pskIndex - 1; // index of 1 means no change vs defaultPSK + } + } else if (k.length < 16) { + // Error! The user specified only the first few bits of an AES128 key. So by convention we just pad the rest of the + // key with zeros + DEBUG_MSG("Warning: User provided a too short AES128 key - padding\n"); + k.length = 16; + } else if (k.length < 32 && k.length != 16) { + // Error! The user specified only the first few bits of an AES256 key. So by convention we just pad the rest of the + // key with zeros + DEBUG_MSG("Warning: User provided a too short AES256 key - padding\n"); + k.length = 32; } - } else if (activePSKSize < 16) { - // Error! The user specified only the first few bits of an AES128 key. So by convention we just pad the rest of the key - // with zeros - DEBUG_MSG("Warning: User provided a too short AES128 key - padding\n"); - activePSKSize = 16; - } else if (activePSKSize < 32 && activePSKSize != 16) { - // Error! The user specified only the first few bits of an AES256 key. So by convention we just pad the rest of the key - // with zeros - DEBUG_MSG("Warning: User provided a too short AES256 key - padding\n"); - activePSKSize = 32; } - // Tell our crypto engine about the psk - crypto->setKey(activePSKSize, activePSK); + return k; +} + +/** Given a channel index, change to use the crypto key specified by that index + */ +int16_t Channels::setCrypto(ChannelIndex chIndex) +{ + CryptoKey k = getKey(chIndex); + + if (k.length < 0) + return -1; + else { + // Tell our crypto engine about the psk + crypto->setKey(k); + return getHash(chIndex); + } } void Channels::initDefaults() @@ -139,8 +177,6 @@ void Channels::onConfigChanged() if (ch.role == Channel_Role_PRIMARY) primaryIndex = i; } - - setCrypto(primaryIndex); // FIXME: for the time being (still single channel - just use our only channel as the crypto key) } Channel &Channels::getByIndex(ChannelIndex chIndex) @@ -207,7 +243,6 @@ their nodes * * Where X is either: * (for custom PSKS) a letter from A to Z (base26), and formed by xoring all the bytes of the PSK together, -* OR (for the standard minimially secure PSKs) a number from 0 to 9. * * This function will also need to be implemented in GUI apps that talk to the radio. * @@ -219,14 +254,14 @@ const char *Channels::getPrimaryName() char suffix; auto channelSettings = getPrimary(); - if (channelSettings.psk.size != 1) { - // We have a standard PSK, so generate a letter based hash. - uint8_t code = xorHash(activePSK, activePSKSize); + // if (channelSettings.psk.size != 1) { + // We have a standard PSK, so generate a letter based hash. + uint8_t code = getHash(primaryIndex); - suffix = 'A' + (code % 26); - } else { + suffix = 'A' + (code % 26); + /* } else { suffix = '0' + channelSettings.psk.bytes[0]; - } + } */ snprintf(buf, sizeof(buf), "#%s-%c", channelSettings.name, suffix); return buf; @@ -238,7 +273,10 @@ const char *Channels::getPrimaryName() * * @return -1 if no suitable channel could be found, otherwise returns the channel index */ -int16_t Channels::setActiveByHash(ChannelHash channelHash) {} +int16_t Channels::setActiveByHash(ChannelHash channelHash) +{ + // fixme cant work; +} /** Given a channel index setup crypto for encoding that channel (or the primary channel if that channel is unsecured) * @@ -246,9 +284,7 @@ int16_t Channels::setActiveByHash(ChannelHash channelHash) {} * * @eturn the (0 to 255) hash for that channel - if no suitable channel could be found, return -1 */ -int16_t Channels::setActiveByIndex(ChannelIndex channelIndex) {} - -/** Given a channel number, return the (0 to 255) hash for that channel - * If no suitable channel could be found, return -1 - */ -ChannelHash Channels::generateHash(ChannelIndex channelNum) {} \ No newline at end of file +int16_t Channels::setActiveByIndex(ChannelIndex channelIndex) +{ + return setCrypto(channelIndex); +} diff --git a/src/mesh/Channels.h b/src/mesh/Channels.h index a86b7ff68..4e70e2304 100644 --- a/src/mesh/Channels.h +++ b/src/mesh/Channels.h @@ -2,6 +2,7 @@ #include "mesh-pb-constants.h" #include +#include "CryptoEngine.h" /** A channel number (index into the channel table) */ @@ -23,12 +24,8 @@ class Channels no sending or receiving will be allowed */ ChannelIndex activeChannelIndex = 0; - /// The in-use psk - which has been constructed based on the (possibly short psk) in channelSettings - uint8_t activePSK[32]; - uint8_t activePSKSize = 0; - - /// the precomputed hashes for each of our channels - ChannelHash hashes[MAX_NUM_CHANNELS]; + /// the precomputed hashes for each of our channels, or -1 for invalid + int16_t hashes[MAX_NUM_CHANNELS]; public: const ChannelSettings &getPrimary() { return getByIndex(getPrimaryIndex()).settings; } @@ -87,21 +84,24 @@ class Channels */ int16_t setActiveByIndex(ChannelIndex channelIndex); - /** return the channel hash we are currently using for sending */ - ChannelHash getActiveHash(); - private: /** Given a channel index, change to use the crypto key specified by that index + * + * @eturn the (0 to 255) hash for that channel - if no suitable channel could be found, return -1 */ - void setCrypto(ChannelIndex chIndex); + int16_t setCrypto(ChannelIndex chIndex); /** Return the channel index for the specified channel hash, or -1 for not found */ int8_t getIndexByHash(ChannelHash channelHash); /** Given a channel number, return the (0 to 255) hash for that channel * If no suitable channel could be found, return -1 + * + * called by fixupChannel when a new channel is set */ - ChannelHash generateHash(ChannelIndex channelNum); + int16_t generateHash(ChannelIndex channelNum); + + int16_t getHash(ChannelIndex i) { return hashes[i]; } /** * Validate a channel, fixing any errors as needed @@ -112,6 +112,13 @@ class Channels * Write a default channel to the specified channel index */ void initDefaultChannel(ChannelIndex chIndex); + + /** + * Return the key used for encrypting this channel (if channel is secondary and no key provided, use the primary channel's PSK) + */ + CryptoKey getKey(ChannelIndex chIndex); + + }; /// Singleton channel table diff --git a/src/mesh/CryptoEngine.cpp b/src/mesh/CryptoEngine.cpp index d72be1118..74f4b7836 100644 --- a/src/mesh/CryptoEngine.cpp +++ b/src/mesh/CryptoEngine.cpp @@ -1,9 +1,10 @@ #include "CryptoEngine.h" #include "configuration.h" -void CryptoEngine::setKey(size_t numBytes, uint8_t *bytes) +void CryptoEngine::setKey(const CryptoKey &k) { - DEBUG_MSG("WARNING: Using stub crypto - all crypto is sent in plaintext!\n"); + DEBUG_MSG("Installing AES%d key!\n", k.length * 8); + key = k; } /** diff --git a/src/mesh/CryptoEngine.h b/src/mesh/CryptoEngine.h index b97abed55..9853f564a 100644 --- a/src/mesh/CryptoEngine.h +++ b/src/mesh/CryptoEngine.h @@ -2,6 +2,13 @@ #include +struct CryptoKey { + uint8_t bytes[32]; + + /// # of bytes, or -1 to mean "invalid key - do not use" + int8_t length; +}; + /** * see docs/software/crypto.md for details. * @@ -15,6 +22,8 @@ class CryptoEngine /** Our per packet nonce */ uint8_t nonce[16]; + CryptoKey key; + public: virtual ~CryptoEngine() {} @@ -27,7 +36,7 @@ class CryptoEngine * @param bytes a _static_ buffer that will remain valid for the life of this crypto instance (i.e. this class will cache the * provided pointer) */ - virtual void setKey(size_t numBytes, uint8_t *bytes); + virtual void setKey(const CryptoKey &k); /** * Encrypt a packet diff --git a/src/nrf52/NRF52CryptoEngine.cpp b/src/nrf52/NRF52CryptoEngine.cpp index 2bf16f23f..431fa2e9c 100644 --- a/src/nrf52/NRF52CryptoEngine.cpp +++ b/src/nrf52/NRF52CryptoEngine.cpp @@ -6,30 +6,13 @@ class NRF52CryptoEngine : public CryptoEngine { - /// How many bytes in our key - uint8_t keySize = 0; - const uint8_t *keyBytes; + public: NRF52CryptoEngine() {} ~NRF52CryptoEngine() {} - /** - * Set the key used for encrypt, decrypt. - * - * As a special case: If all bytes are zero, we assume _no encryption_ and send all data in cleartext. - * - * @param numBytes must be 16 (AES128), 32 (AES256) or 0 (no crypt) - * @param bytes a _static_ buffer that will remain valid for the life of this crypto instance (i.e. this class will cache the - * provided pointer) - */ - virtual void setKey(size_t numBytes, uint8_t *bytes) - { - keySize = numBytes; - keyBytes = bytes; - } - /** * Encrypt a packet * @@ -39,11 +22,11 @@ class NRF52CryptoEngine : public CryptoEngine { // DEBUG_MSG("NRF52 encrypt!\n"); - if (keySize != 0) { + if (key.length > 0) { ocrypto_aes_ctr_ctx ctx; initNonce(fromNode, packetNum); - ocrypto_aes_ctr_init(&ctx, keyBytes, keySize, nonce); + ocrypto_aes_ctr_init(&ctx, key.bytes, key.length, nonce); ocrypto_aes_ctr_encrypt(&ctx, bytes, bytes, numBytes); } @@ -53,11 +36,11 @@ class NRF52CryptoEngine : public CryptoEngine { // DEBUG_MSG("NRF52 decrypt!\n"); - if (keySize != 0) { + if (key.length > 0) { ocrypto_aes_ctr_ctx ctx; initNonce(fromNode, packetNum); - ocrypto_aes_ctr_init(&ctx, keyBytes, keySize, nonce); + ocrypto_aes_ctr_init(&ctx, key.bytes, key.length, nonce); ocrypto_aes_ctr_decrypt(&ctx, bytes, bytes, numBytes); } diff --git a/src/portduino/CrossPlatformCryptoEngine.cpp b/src/portduino/CrossPlatformCryptoEngine.cpp index b9e818c0b..06225aa12 100644 --- a/src/portduino/CrossPlatformCryptoEngine.cpp +++ b/src/portduino/CrossPlatformCryptoEngine.cpp @@ -10,9 +10,6 @@ class CrossPlatformCryptoEngine : public CryptoEngine CTRCommon *ctr = NULL; - /// How many bytes in our key - uint8_t keySize = 0; - public: CrossPlatformCryptoEngine() {} @@ -27,9 +24,9 @@ class CrossPlatformCryptoEngine : public CryptoEngine * @param bytes a _static_ buffer that will remain valid for the life of this crypto instance (i.e. this class will cache the * provided pointer) */ - virtual void setKey(size_t numBytes, uint8_t *bytes) + virtual void setKey(const CryptoKey &k) { - keySize = numBytes; + CryptoEngine::setKey(k); DEBUG_MSG("Installing AES%d key!\n", numBytes * 8); if (ctr) { delete ctr; @@ -41,7 +38,7 @@ class CrossPlatformCryptoEngine : public CryptoEngine else ctr = new CTR(); - ctr->setKey(bytes, numBytes); + ctr->setKey(key.bytes, key.length); } } @@ -52,7 +49,7 @@ class CrossPlatformCryptoEngine : public CryptoEngine */ virtual void encrypt(uint32_t fromNode, uint64_t packetNum, size_t numBytes, uint8_t *bytes) { - if (keySize != 0) { + if (key.length > 0) { uint8_t stream_block[16]; static uint8_t scratch[MAX_BLOCKSIZE]; size_t nc_off = 0; From ae6b7e7259c5caa4da3e90342264b0e67afe5346 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Tue, 23 Feb 2021 10:45:03 +0800 Subject: [PATCH 16/35] multichannel code is done! (only basic testing completed though) --- docs/software/TODO.md | 8 +++++--- src/mesh/Channels.cpp | 15 +++++++++++---- src/mesh/Channels.h | 24 ++++++++++++----------- src/mesh/Router.cpp | 44 +++++++++++++++++++++---------------------- 4 files changed, 51 insertions(+), 40 deletions(-) diff --git a/docs/software/TODO.md b/docs/software/TODO.md index b30b58795..232ea2122 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -5,8 +5,8 @@ You probably don't care about this section - skip to the next one. 1.2 cleanup & multichannel support: * DONE call RouterPlugin for *all* packets - not just Router packets -* generate channel hash from the name of the channel+the psk (not just one or the other) -* send a hint that can be used to select which channel to try and hash against with each message +* DONE generate channel hash from the name of the channel+the psk (not just one or the other) +* DONE send a hint that can be used to select which channel to try and hash against with each message * DONE remove deprecated * DONE fix setchannel in phoneapi.cpp * DONE set mynodeinfo.max_channels @@ -15,7 +15,9 @@ You probably don't care about this section - skip to the next one. * DONE enable remote setttings access by moving settings operations into a regular plugin (move settings ops out of PhoneAPI) * DONE move portnum up? * DONE remove region specific builds from the firmware -* restrict settings operations to the admin channel +* test single channel +* test multi channel +* restrict gpio & serial & settings operations to the admin channel (unless local to the current node) * add gui in android app for setting region * make an alpha channel for the python API * "FIXME - move the radioconfig/user/channel READ operations into SettingsMessage as well" diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp index f3238b9c5..3e1ea3185 100644 --- a/src/mesh/Channels.cpp +++ b/src/mesh/Channels.cpp @@ -192,7 +192,7 @@ void Channels::setChannel(const Channel &c) // if this is the new primary, demote any existing roles if (c.role == Channel_Role_PRIMARY) - for (int i = 0; i < devicestate.channels_count; i++) + for (int i = 0; i < getNumChannels(); i++) if (devicestate.channels[i].role == Channel_Role_PRIMARY) devicestate.channels[i].role = Channel_Role_SECONDARY; @@ -271,11 +271,18 @@ const char *Channels::getPrimaryName() * * This method is called before decoding inbound packets * - * @return -1 if no suitable channel could be found, otherwise returns the channel index + * @return false if the channel hash or channel is invalid */ -int16_t Channels::setActiveByHash(ChannelHash channelHash) +bool Channels::decryptForHash(ChannelIndex chIndex, ChannelHash channelHash) { - // fixme cant work; + if(chIndex > getNumChannels() || getHash(chIndex) != channelHash) { + DEBUG_MSG("Skipping channel %d due to invalid hash/index\n", chIndex); + return false; + } + else { + setCrypto(chIndex); + return true; + } } /** Given a channel index setup crypto for encoding that channel (or the primary channel if that channel is unsecured) diff --git a/src/mesh/Channels.h b/src/mesh/Channels.h index 4e70e2304..547b0a581 100644 --- a/src/mesh/Channels.h +++ b/src/mesh/Channels.h @@ -1,16 +1,17 @@ #pragma once +#include "CryptoEngine.h" +#include "NodeDB.h" #include "mesh-pb-constants.h" #include -#include "CryptoEngine.h" /** A channel number (index into the channel table) */ typedef uint8_t ChannelIndex; -/** A low quality hash of the channel PSK and the channel name. created by generateHash(chIndex) +/** A low quality hash of the channel PSK and the channel name. created by generateHash(chIndex) * Used as a hint to limit which PSKs are considered for packet decoding. -*/ + */ typedef uint8_t ChannelHash; /** The container/on device API for working with channels */ @@ -22,7 +23,7 @@ class Channels /** The channel index that was requested for sending/receving. Note: if this channel is a secondary channel and does not have a PSK, we will use the PSK from the primary channel. If this channel is disabled no sending or receiving will be allowed */ - ChannelIndex activeChannelIndex = 0; + ChannelIndex activeChannelIndex = 0; /// the precomputed hashes for each of our channels, or -1 for invalid int16_t hashes[MAX_NUM_CHANNELS]; @@ -43,6 +44,8 @@ class Channels /** The index of the primary channel */ ChannelIndex getPrimaryIndex() const { return primaryIndex; } + ChannelIndex getNumChannels() { return devicestate.channels_count; } + /** * Generate a short suffix used to disambiguate channels that might have the same "name" entered by the human but different PSKs. @@ -72,9 +75,9 @@ class Channels * * This method is called before decoding inbound packets * - * @return -1 if no suitable channel could be found, otherwise returns the channel index + * @return false if the channel hash or channel is invalid */ - int16_t setActiveByHash(ChannelHash channelHash); + bool decryptForHash(ChannelIndex chIndex, ChannelHash channelHash); /** Given a channel index setup crypto for encoding that channel (or the primary channel if that channel is unsecured) * @@ -86,7 +89,7 @@ class Channels private: /** Given a channel index, change to use the crypto key specified by that index - * + * * @eturn the (0 to 255) hash for that channel - if no suitable channel could be found, return -1 */ int16_t setCrypto(ChannelIndex chIndex); @@ -96,7 +99,7 @@ class Channels /** Given a channel number, return the (0 to 255) hash for that channel * If no suitable channel could be found, return -1 - * + * * called by fixupChannel when a new channel is set */ int16_t generateHash(ChannelIndex channelNum); @@ -114,11 +117,10 @@ class Channels void initDefaultChannel(ChannelIndex chIndex); /** - * Return the key used for encrypting this channel (if channel is secondary and no key provided, use the primary channel's PSK) + * Return the key used for encrypting this channel (if channel is secondary and no key provided, use the primary channel's + * PSK) */ CryptoKey getKey(ChannelIndex chIndex); - - }; /// Singleton channel table diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 434bdde5d..50e4215b2 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -215,31 +215,31 @@ bool Router::perhapsDecode(MeshPacket *p) assert(p->which_payloadVariant == MeshPacket_encrypted_tag); - ChannelHash chHash = p->channel; - int16_t chIndex = channels.setActiveByHash(chHash); - if (chIndex < 0) { - DEBUG_MSG("No suitable channel found for decoding, hash was 0x%x!\n", chHash); - return false; - } else { - p->channel = chIndex; + // Try to find a channel that works with this hash + for (ChannelIndex chIndex = 0; chIndex < channels.getNumChannels(); chIndex++) { + // Try to use this hash/channel pair + if (channels.decryptForHash(chIndex, p->channel)) { + // Try to decrypt the packet if we can + static uint8_t bytes[MAX_RHPACKETLEN]; + memcpy(bytes, p->encrypted.bytes, + p->encrypted + .size); // we have to copy into a scratch buffer, because these bytes are a union with the decoded protobuf + crypto->decrypt(p->from, p->id, p->encrypted.size, bytes); - // Try to decrypt the packet if we can - static uint8_t bytes[MAX_RHPACKETLEN]; - memcpy(bytes, p->encrypted.bytes, - p->encrypted - .size); // we have to copy into a scratch buffer, because these bytes are a union with the decoded protobuf - crypto->decrypt(p->from, p->id, p->encrypted.size, bytes); - - // Take those raw bytes and convert them back into a well structured protobuf we can understand - if (!pb_decode_from_bytes(bytes, p->encrypted.size, Data_fields, &p->decoded)) { - DEBUG_MSG("Invalid protobufs in received mesh packet!\n"); - return false; - } else { - // parsing was successful - p->which_payloadVariant = MeshPacket_decoded_tag; - return true; + // Take those raw bytes and convert them back into a well structured protobuf we can understand + if (!pb_decode_from_bytes(bytes, p->encrypted.size, Data_fields, &p->decoded)) { + DEBUG_MSG("Invalid protobufs in received mesh packet (bad psk?!\n"); + } else { + // parsing was successful + p->channel = chIndex; // change to store the index instead of the hash + p->which_payloadVariant = MeshPacket_decoded_tag; + return true; + } } } + + DEBUG_MSG("No suitable channel found for decoding, hash was 0x%x!\n", p->channel); + return false; } NodeNum Router::getNodeNum() From aa8b86c6b2739af1bcf2d53c315f0d1551df883a Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Tue, 23 Feb 2021 11:43:30 +0800 Subject: [PATCH 17/35] multichannel send/rx kinda works --- docs/software/TODO.md | 17 +++++++++++------ proto | 2 +- src/mesh/MeshPlugin.cpp | 7 ++++--- src/mesh/NodeDB.cpp | 3 +-- src/mesh/PhoneAPI.h | 4 ---- src/mesh/RadioLibInterface.cpp | 2 +- version.properties | 4 ++-- 7 files changed, 20 insertions(+), 19 deletions(-) diff --git a/docs/software/TODO.md b/docs/software/TODO.md index 232ea2122..c61ce0953 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -15,11 +15,17 @@ You probably don't care about this section - skip to the next one. * DONE enable remote setttings access by moving settings operations into a regular plugin (move settings ops out of PhoneAPI) * DONE move portnum up? * DONE remove region specific builds from the firmware -* test single channel +* test single channel without python +* test single channel with python +* implement 'get channels' Admin operation +* use get-channels from python +* use set-channel from python * test multi channel +* pick default random admin key * restrict gpio & serial & settings operations to the admin channel (unless local to the current node) * add gui in android app for setting region -* make an alpha channel for the python API +* warn in python api if we are too new to talk to the device code +* make a post warning about 1.2, telling how to stay on old android & python clients. link to this from the android dialog message and python version warning. * "FIXME - move the radioconfig/user/channel READ operations into SettingsMessage as well" * DONE scrub protobufs to make sure they are absoloute minimum wiresize (in particular Data, ChannelSets and positions) * change syncword @@ -34,11 +40,10 @@ You probably don't care about this section - skip to the next one. * DONE make all subpackets different versions of data * DONE move routing control into a data packet * have phoneapi done via plugin -* figure out how to add micro_delta to position, make it so that phone apps don't need to understand it? +* DONE figure out how to add micro_delta to position, make it so that phone apps don't need to understand it? * only send battery updates a max of once a minute -* add multichannel support in python -* add channel selection for sending -* record recevied channel in meshpacket +* add python channel selection for sending +* DONE record recevied channel in meshpacket * test remote settings operations (confirm it works 3 hops away) * add channel restrictions for plugins (and restrict routing plugin to the "control" channel) * make a primaryChannel global and properly maintain it when the phone sends setChannel diff --git a/proto b/proto index f6ff4cc0c..7a5875d96 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit f6ff4cc0c98b201342c32776eeeb9ace83b450dd +Subproject commit 7a5875d9639a0682bd36d7e118bf26d7b4d733be diff --git a/src/mesh/MeshPlugin.cpp b/src/mesh/MeshPlugin.cpp index 763d4d46e..76ac99b6f 100644 --- a/src/mesh/MeshPlugin.cpp +++ b/src/mesh/MeshPlugin.cpp @@ -32,7 +32,8 @@ void MeshPlugin::callPlugins(const MeshPacket &mp) assert(mp.which_payloadVariant == MeshPacket_decoded_tag); // I think we are guarnteed the packet is decoded by this point? // Was this message directed to us specifically? Will be false if we are sniffing someone elses packets - bool toUs = mp.to == NODENUM_BROADCAST || mp.to == nodeDB.getNodeNum(); + auto ourNodeNum = nodeDB.getNodeNum(); + bool toUs = mp.to == NODENUM_BROADCAST || mp.to == ourNodeNum; for (auto i = plugins->begin(); i != plugins->end(); ++i) { auto &pi = **i; @@ -45,8 +46,8 @@ void MeshPlugin::callPlugins(const MeshPacket &mp) bool handled = pi.handleReceived(mp); - // Possibly send replies (but only if the message was directed to us specifically, i.e. not for promiscious sniffing) - if (mp.decoded.want_response && toUs) { + // Possibly send replies (but only if the message was directed to us specifically, i.e. not for promiscious sniffing), also not if we sent it + if (mp.decoded.want_response && toUs && mp.from != ourNodeNum) { pi.sendResponse(mp); DEBUG_MSG("Plugin %s sent a response\n", pi.name); } diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 6e81acd76..876a66bc5 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -148,7 +148,7 @@ void NodeDB::installDefaultDeviceState() // Restore region if possible if (oldRegionCode != RegionCode_Unset) radioConfig.preferences.region = oldRegionCode; - if (oldRegion.length()) + if (oldRegion.length()) // If the old style region was set, try to keep it up-to-date strcpy(myNodeInfo.region, oldRegion.c_str()); } @@ -400,7 +400,6 @@ void NodeDB::updateUser(uint32_t nodeId, const User &p) void NodeDB::updateFrom(const MeshPacket &mp) { if (mp.which_payloadVariant == MeshPacket_decoded_tag) { - const Data &p = mp.decoded; DEBUG_MSG("Update DB node 0x%x, rx_time=%u\n", mp.from, mp.rx_time); NodeInfo *info = getOrCreateNode(mp.from); diff --git a/src/mesh/PhoneAPI.h b/src/mesh/PhoneAPI.h index 6d4e8d626..19c5d0583 100644 --- a/src/mesh/PhoneAPI.h +++ b/src/mesh/PhoneAPI.h @@ -101,10 +101,6 @@ class PhoneAPI */ virtual void onNowHasData(uint32_t fromRadioNum) {} - void handleSetOwner(const User &o); - void handleSetChannel(const Channel &cc); - void handleSetRadio(const RadioConfig &r); - private: /** * Handle a packet that the phone wants us to send. It is our responsibility to free the packet to the pool diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index ab1728126..b3fac2ab8 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -274,7 +274,7 @@ void RadioLibInterface::handleReceiveInterrupt() mp->from = h->from; mp->to = h->to; mp->id = h->id; - mp->channel = h->id; + mp->channel = h->channel; assert(HOP_MAX <= PACKET_FLAGS_HOP_MASK); // If hopmax changes, carefully check this code mp->hop_limit = h->flags & PACKET_FLAGS_HOP_MASK; mp->want_ack = !!(h->flags & PACKET_FLAGS_WANT_ACK_MASK); diff --git a/version.properties b/version.properties index 6c1503acd..c77424e6a 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 1 -minor = 1 -build = 48 +minor = 2 +build = 0 From f8d8dc25c0aff49d0b99aa7819e46f1f0f38493a Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Tue, 23 Feb 2021 14:35:34 +0800 Subject: [PATCH 18/35] properly route messages to phone again --- docs/software/TODO.md | 9 ++++++--- src/mesh/Channels.cpp | 9 ++++----- src/mesh/MeshPlugin.cpp | 4 +++- src/mesh/RadioInterface.cpp | 4 ++-- src/mesh/Router.cpp | 6 +++++- src/plugins/RoutingPlugin.cpp | 10 ++++++++-- src/plugins/RoutingPlugin.h | 3 +++ 7 files changed, 31 insertions(+), 14 deletions(-) diff --git a/docs/software/TODO.md b/docs/software/TODO.md index c61ce0953..9dcfa3781 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -15,11 +15,14 @@ You probably don't care about this section - skip to the next one. * DONE enable remote setttings access by moving settings operations into a regular plugin (move settings ops out of PhoneAPI) * DONE move portnum up? * DONE remove region specific builds from the firmware -* test single channel without python -* test single channel with python -* implement 'get channels' Admin operation +* DONE test single channel without python +* DONE Use "default" for name if name is empty +* DONE fix python data packet receiving (nothing showing in log?) +* implement 'get channels' Admin plugin operation * use get-channels from python * use set-channel from python +* make python tests more exhaustive +* document the relationship between want_response (indicating remote node received it) and want_ack (indicating that this message should be sent reliably - and also get acks from the first rx node and naks if it is never delivered) * test multi channel * pick default random admin key * restrict gpio & serial & settings operations to the admin channel (unless local to the current node) diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp index 3e1ea3185..76ea3fb92 100644 --- a/src/mesh/Channels.cpp +++ b/src/mesh/Channels.cpp @@ -28,9 +28,8 @@ int16_t Channels::generateHash(ChannelIndex channelNum) if (k.length < 0) return -1; // invalid else { - Channel &c = getByIndex(channelNum); - - uint8_t h = xorHash((const uint8_t *)c.settings.name, strlen(c.settings.name)); + const char *name = getName(channelNum); + uint8_t h = xorHash((const uint8_t *) name, strlen(name)); h ^= xorHash(k.bytes, k.length); @@ -253,7 +252,7 @@ const char *Channels::getPrimaryName() static char buf[32]; char suffix; - auto channelSettings = getPrimary(); + // auto channelSettings = getPrimary(); // if (channelSettings.psk.size != 1) { // We have a standard PSK, so generate a letter based hash. uint8_t code = getHash(primaryIndex); @@ -263,7 +262,7 @@ const char *Channels::getPrimaryName() suffix = '0' + channelSettings.psk.bytes[0]; } */ - snprintf(buf, sizeof(buf), "#%s-%c", channelSettings.name, suffix); + snprintf(buf, sizeof(buf), "#%s-%c", getName(primaryIndex), suffix); return buf; } diff --git a/src/mesh/MeshPlugin.cpp b/src/mesh/MeshPlugin.cpp index 76ac99b6f..a1fdfd2e2 100644 --- a/src/mesh/MeshPlugin.cpp +++ b/src/mesh/MeshPlugin.cpp @@ -41,6 +41,7 @@ void MeshPlugin::callPlugins(const MeshPacket &mp) // We only call plugins that are interested in the packet (and the message is destined to us or we are promiscious) bool wantsPacket = (pi.isPromiscuous || toUs) && pi.wantPacket(&mp); + // DEBUG_MSG("Plugin %s wantsPacket=%d\n", pi.name, wantsPacket); if (wantsPacket) { pluginFound = true; @@ -79,7 +80,8 @@ void MeshPlugin::sendResponse(const MeshPacket &req) { service.sendToMesh(r); } else { - DEBUG_MSG("WARNING: Client requested response but this plugin did not provide\n"); + // Ignore - this is now expected behavior for routing plugin (because it ignores some replies) + // DEBUG_MSG("WARNING: Client requested response but this plugin did not provide\n"); } } diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 93dd55e80..7b8aec605 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -119,8 +119,8 @@ uint32_t RadioInterface::getTxDelayMsec() void printPacket(const char *prefix, const MeshPacket *p) { - DEBUG_MSG("%s (id=0x%08x Fr0x%02x To0x%02x, WantAck%d, HopLim%d", prefix, p->id, p->from & 0xff, p->to & 0xff, p->want_ack, - p->hop_limit); + DEBUG_MSG("%s (id=0x%08x Fr0x%02x To0x%02x, WantAck%d, HopLim%d Ch0x%x", prefix, p->id, p->from & 0xff, p->to & 0xff, p->want_ack, + p->hop_limit, p->channel); if (p->which_payloadVariant == MeshPacket_decoded_tag) { auto &s = p->decoded; diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 50e4215b2..a6afe952e 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -232,6 +232,7 @@ bool Router::perhapsDecode(MeshPacket *p) } else { // parsing was successful p->channel = chIndex; // change to store the index instead of the hash + // printPacket("decoded message", p); p->which_payloadVariant = MeshPacket_decoded_tag; return true; } @@ -257,7 +258,10 @@ void Router::handleReceived(MeshPacket *p) p->rx_time = getValidTime(RTCQualityFromNet); // store the arrival timestamp for the phone // Take those raw bytes and convert them back into a well structured protobuf we can understand - if (perhapsDecode(p)) { + bool decoded = perhapsDecode(p); + printPacket("handleReceived", p); + DEBUG_MSG("decoded=%d\n", decoded); + if (decoded) { // parsing was successful, queue for our recipient // call any promiscious plugins here, make a (non promisiocous) plugin for forwarding messages to phone api diff --git a/src/plugins/RoutingPlugin.cpp b/src/plugins/RoutingPlugin.cpp index 58b3f08ae..9af7d31ff 100644 --- a/src/plugins/RoutingPlugin.cpp +++ b/src/plugins/RoutingPlugin.cpp @@ -9,6 +9,7 @@ RoutingPlugin *routingPlugin; bool RoutingPlugin::handleReceivedProtobuf(const MeshPacket &mp, const Routing *r) { + DEBUG_MSG("Routing sniffing", &mp); router->sniffReceived(&mp, r); // FIXME - move this to a non promsicious PhoneAPI plugin? @@ -23,8 +24,13 @@ bool RoutingPlugin::handleReceivedProtobuf(const MeshPacket &mp, const Routing * MeshPacket *RoutingPlugin::allocReply() { - assert(0); // 1.2 refactoring fixme, Not sure if anything needs this yet? - // return allocDataProtobuf(u); + assert(currentRequest); + + // We only consider making replies if the request was a legit routing packet (not just something we were sniffing) + if(currentRequest->decoded.portnum == PortNum_ROUTING_APP) { + assert(0); // 1.2 refactoring fixme, Not sure if anything needs this yet? + // return allocDataProtobuf(u); + } return NULL; } diff --git a/src/plugins/RoutingPlugin.h b/src/plugins/RoutingPlugin.h index 0d987f39e..a848bc9c4 100644 --- a/src/plugins/RoutingPlugin.h +++ b/src/plugins/RoutingPlugin.h @@ -25,6 +25,9 @@ class RoutingPlugin : public ProtobufPlugin * so that subclasses can (optionally) send a response back to the original sender. */ virtual MeshPacket *allocReply(); + /// Override wantPacket to say we want to see all packets, not just those for our port number + virtual bool wantPacket(const MeshPacket *p) { return true; } + void sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom); }; From 4b07f9e160f90d4ad059305dcdcdabafb3e1b80e Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Tue, 23 Feb 2021 14:45:02 +0800 Subject: [PATCH 19/35] todo update --- docs/software/TODO.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/software/TODO.md b/docs/software/TODO.md index 9dcfa3781..564f11f2d 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -21,6 +21,7 @@ You probably don't care about this section - skip to the next one. * implement 'get channels' Admin plugin operation * use get-channels from python * use set-channel from python +* use portuino TCP connection to debug with python API * make python tests more exhaustive * document the relationship between want_response (indicating remote node received it) and want_ack (indicating that this message should be sent reliably - and also get acks from the first rx node and naks if it is never delivered) * test multi channel From ada05a1374c89f4db0db388e900de0c4211c3847 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Tue, 23 Feb 2021 16:56:28 +0800 Subject: [PATCH 20/35] fix linux --- src/portduino/CrossPlatformCryptoEngine.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/portduino/CrossPlatformCryptoEngine.cpp b/src/portduino/CrossPlatformCryptoEngine.cpp index 06225aa12..1f31d592b 100644 --- a/src/portduino/CrossPlatformCryptoEngine.cpp +++ b/src/portduino/CrossPlatformCryptoEngine.cpp @@ -27,13 +27,13 @@ class CrossPlatformCryptoEngine : public CryptoEngine virtual void setKey(const CryptoKey &k) { CryptoEngine::setKey(k); - DEBUG_MSG("Installing AES%d key!\n", numBytes * 8); + DEBUG_MSG("Installing AES%d key!\n", key.length * 8); if (ctr) { delete ctr; ctr = NULL; } - if (numBytes != 0) { - if (numBytes == 16) + if (key.length != 0) { + if (key.length == 16) ctr = new CTR(); else ctr = new CTR(); From 245638a1d4ad009e14a140ee966d8b5977e7b10d Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Tue, 23 Feb 2021 17:07:38 +0800 Subject: [PATCH 21/35] get more parallism in CI build --- .github/workflows/main.yml | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5f17d9176..b7dfa69fb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,8 +4,7 @@ on: - pull_request jobs: - main: - name: Main + setup: runs-on: ubuntu-latest steps: - uses: actions/checkout@master @@ -25,12 +24,26 @@ jobs: - name: Install libs needed for linux build run: | sudo apt install -y libpsocksxx-dev + + build-esp: + needs: setup + runs-on: ubuntu-latest + steps: - name: Build for tbeam run: platformio run -e tbeam - name: Build for heltec run: platformio run -e heltec + + build-nrf: + needs: setup + runs-on: ubuntu-latest + steps: - name: Build for lora-relay-v1 run: platformio run -e lora-relay-v1 + + build-portduino: + needs: setup + runs-on: ubuntu-latest + steps: - name: Build for linux - run: platformio run -e linux - + run: platformio run -e linux \ No newline at end of file From 577336d2df034796d8f9a0c4771e27d0b7e0ef9c Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Tue, 23 Feb 2021 17:16:12 +0800 Subject: [PATCH 22/35] oh well - github actions defeated me --- .github/workflows/main.yml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b7dfa69fb..9c9b2fffd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,26 +24,11 @@ jobs: - name: Install libs needed for linux build run: | sudo apt install -y libpsocksxx-dev - - build-esp: - needs: setup - runs-on: ubuntu-latest - steps: - name: Build for tbeam run: platformio run -e tbeam - name: Build for heltec run: platformio run -e heltec - - build-nrf: - needs: setup - runs-on: ubuntu-latest - steps: - name: Build for lora-relay-v1 run: platformio run -e lora-relay-v1 - - build-portduino: - needs: setup - runs-on: ubuntu-latest - steps: - name: Build for linux run: platformio run -e linux \ No newline at end of file From 8ba43e174557bc00d998cea3dd549d525dc320e0 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Thu, 25 Feb 2021 20:02:32 +0800 Subject: [PATCH 23/35] merge latest from master --- proto | 2 +- src/mesh/generated/deviceonly.pb.h | 2 +- src/mesh/generated/mesh.pb.h | 41 ++++++++++++++++++++---------- src/mesh/generated/portnums.pb.h | 2 +- 4 files changed, 31 insertions(+), 16 deletions(-) diff --git a/proto b/proto index f2d342de0..b53818d67 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit f2d342de0ca74e9202c79876afc5aec675150e49 +Subproject commit b53818d67b34bf7a221ae2292cd2cd4af9412253 diff --git a/src/mesh/generated/deviceonly.pb.h b/src/mesh/generated/deviceonly.pb.h index 9ec3fa5a0..01246c70e 100644 --- a/src/mesh/generated/deviceonly.pb.h +++ b/src/mesh/generated/deviceonly.pb.h @@ -80,7 +80,7 @@ extern const pb_msgdesc_t DeviceState_msg; #define DeviceState_fields &DeviceState_msg /* Maximum encoded size of messages (where known) */ -#define DeviceState_size 6125 +#define DeviceState_size 6152 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/mesh.pb.h b/src/mesh/generated/mesh.pb.h index 6858cdcd9..6ad5945e1 100644 --- a/src/mesh/generated/mesh.pb.h +++ b/src/mesh/generated/mesh.pb.h @@ -217,6 +217,11 @@ typedef struct _RadioConfig_UserPreferences { bool range_test_plugin_save; bool store_forward_plugin_enabled; uint32_t store_forward_plugin_records; + bool environmental_measurement_plugin_measurement_enabled; + bool environmental_measurement_plugin_screen_enabled; + uint32_t environmental_measurement_plugin_read_error_count_threshold; + uint32_t environmental_measurement_plugin_update_interval; + uint32_t environmental_measurement_plugin_recovery_interval; } RadioConfig_UserPreferences; typedef struct _RouteDiscovery { @@ -376,7 +381,7 @@ extern "C" { #define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} #define Channel_init_default {0, false, ChannelSettings_init_default, _Channel_Role_MIN} #define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default} -#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 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, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 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, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0} #define LogRecord_init_default {"", 0, "", _LogRecord_Level_MIN} @@ -392,7 +397,7 @@ extern "C" { #define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} #define Channel_init_zero {0, false, ChannelSettings_init_zero, _Channel_Role_MIN} #define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero} -#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 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, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 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, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0} #define LogRecord_init_zero {"", 0, "", _LogRecord_Level_MIN} @@ -480,6 +485,11 @@ extern "C" { #define RadioConfig_UserPreferences_range_test_plugin_save_tag 134 #define RadioConfig_UserPreferences_store_forward_plugin_enabled_tag 136 #define RadioConfig_UserPreferences_store_forward_plugin_records_tag 137 +#define RadioConfig_UserPreferences_environmental_measurement_plugin_measurement_enabled_tag 140 +#define RadioConfig_UserPreferences_environmental_measurement_plugin_screen_enabled_tag 141 +#define RadioConfig_UserPreferences_environmental_measurement_plugin_read_error_count_threshold_tag 142 +#define RadioConfig_UserPreferences_environmental_measurement_plugin_update_interval_tag 143 +#define RadioConfig_UserPreferences_environmental_measurement_plugin_recovery_interval_tag 144 #define RouteDiscovery_route_tag 2 #define User_id_tag 1 #define User_long_name_tag 2 @@ -496,9 +506,9 @@ extern "C" { #define MeshPacket_id_tag 6 #define MeshPacket_rx_time_tag 7 #define MeshPacket_rx_snr_tag 8 -#define MeshPacket_hop_limit_tag 9 -#define MeshPacket_want_ack_tag 10 -#define MeshPacket_priority_tag 11 +#define MeshPacket_hop_limit_tag 10 +#define MeshPacket_want_ack_tag 11 +#define MeshPacket_priority_tag 12 #define NodeInfo_num_tag 1 #define NodeInfo_user_tag 2 #define NodeInfo_position_tag 3 @@ -579,9 +589,9 @@ X(a, STATIC, ONEOF, BYTES, (payloadVariant,encrypted,encrypted), 5) \ X(a, STATIC, SINGULAR, FIXED32, id, 6) \ X(a, STATIC, SINGULAR, FIXED32, rx_time, 7) \ X(a, STATIC, SINGULAR, FLOAT, rx_snr, 8) \ -X(a, STATIC, SINGULAR, UINT32, hop_limit, 9) \ -X(a, STATIC, SINGULAR, BOOL, want_ack, 10) \ -X(a, STATIC, SINGULAR, UENUM, priority, 11) +X(a, STATIC, SINGULAR, UINT32, hop_limit, 10) \ +X(a, STATIC, SINGULAR, BOOL, want_ack, 11) \ +X(a, STATIC, SINGULAR, UENUM, priority, 12) #define MeshPacket_CALLBACK NULL #define MeshPacket_DEFAULT NULL #define MeshPacket_payloadVariant_decoded_MSGTYPE Data @@ -657,7 +667,12 @@ X(a, STATIC, SINGULAR, BOOL, range_test_plugin_enabled, 132) \ X(a, STATIC, SINGULAR, UINT32, range_test_plugin_sender, 133) \ X(a, STATIC, SINGULAR, BOOL, range_test_plugin_save, 134) \ X(a, STATIC, SINGULAR, BOOL, store_forward_plugin_enabled, 136) \ -X(a, STATIC, SINGULAR, UINT32, store_forward_plugin_records, 137) +X(a, STATIC, SINGULAR, UINT32, store_forward_plugin_records, 137) \ +X(a, STATIC, SINGULAR, BOOL, environmental_measurement_plugin_measurement_enabled, 140) \ +X(a, STATIC, SINGULAR, BOOL, environmental_measurement_plugin_screen_enabled, 141) \ +X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_read_error_count_threshold, 142) \ +X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_update_interval, 143) \ +X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_recovery_interval, 144) #define RadioConfig_UserPreferences_CALLBACK NULL #define RadioConfig_UserPreferences_DEFAULT NULL @@ -776,14 +791,14 @@ extern const pb_msgdesc_t AdminMessage_msg; #define MeshPacket_size 297 #define ChannelSettings_size 87 #define Channel_size 94 -#define RadioConfig_size 308 -#define RadioConfig_UserPreferences_size 305 +#define RadioConfig_size 335 +#define RadioConfig_UserPreferences_size 332 #define NodeInfo_size 130 #define MyNodeInfo_size 89 #define LogRecord_size 81 -#define FromRadio_size 317 +#define FromRadio_size 344 #define ToRadio_size 300 -#define AdminMessage_size 311 +#define AdminMessage_size 338 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/portnums.pb.h b/src/mesh/generated/portnums.pb.h index 5904a548c..758db47a6 100644 --- a/src/mesh/generated/portnums.pb.h +++ b/src/mesh/generated/portnums.pb.h @@ -20,10 +20,10 @@ typedef enum _PortNum { PortNum_ADMIN_APP = 6, PortNum_REPLY_APP = 32, PortNum_IP_TUNNEL_APP = 33, + PortNum_ENVIRONMENTAL_MEASUREMENT_APP = 34, PortNum_SERIAL_APP = 64, PortNum_STORE_FORWARD_APP = 65, PortNum_RANGE_TEST_APP = 66, - PortNum_ENVIRONMENTAL_MEASUREMENT_APP = 67, PortNum_PRIVATE_APP = 256, PortNum_ATAK_FORWARDER = 257, PortNum_MAX = 511 From 5ae4edf8fd5e36eb342d7300903cfd3d78775bc3 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Thu, 25 Feb 2021 20:36:37 +0800 Subject: [PATCH 24/35] move admin out of core proto --- proto | 2 +- src/mesh/generated/admin.pb.c | 12 ++++++ src/mesh/generated/admin.pb.h | 66 ++++++++++++++++++++++++++++++ src/mesh/generated/deviceonly.pb.h | 2 +- src/mesh/generated/mesh.pb.c | 3 -- src/mesh/generated/mesh.pb.h | 33 ++------------- src/mesh/mesh-pb-constants.h | 1 + 7 files changed, 84 insertions(+), 35 deletions(-) create mode 100644 src/mesh/generated/admin.pb.c create mode 100644 src/mesh/generated/admin.pb.h diff --git a/proto b/proto index b53818d67..75ae9929a 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit b53818d67b34bf7a221ae2292cd2cd4af9412253 +Subproject commit 75ae9929a22a0cfa65059f30b27485f2ae8f3a63 diff --git a/src/mesh/generated/admin.pb.c b/src/mesh/generated/admin.pb.c new file mode 100644 index 000000000..4b90c51ae --- /dev/null +++ b/src/mesh/generated/admin.pb.c @@ -0,0 +1,12 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.4 */ + +#include "admin.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(AdminMessage, AdminMessage, 2) + + + diff --git a/src/mesh/generated/admin.pb.h b/src/mesh/generated/admin.pb.h new file mode 100644 index 000000000..b3d29825a --- /dev/null +++ b/src/mesh/generated/admin.pb.h @@ -0,0 +1,66 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.4 */ + +#ifndef PB_ADMIN_PB_H_INCLUDED +#define PB_ADMIN_PB_H_INCLUDED +#include +#include "mesh.pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +typedef struct _AdminMessage { + pb_size_t which_variant; + union { + RadioConfig set_radio; + User set_owner; + Channel set_channel; + bool get_radio; + uint32_t get_channel; + }; +} AdminMessage; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define AdminMessage_init_default {0, {RadioConfig_init_default}} +#define AdminMessage_init_zero {0, {RadioConfig_init_zero}} + +/* Field tags (for use in manual encoding/decoding) */ +#define AdminMessage_set_radio_tag 1 +#define AdminMessage_set_owner_tag 2 +#define AdminMessage_set_channel_tag 3 +#define AdminMessage_get_radio_tag 4 +#define AdminMessage_get_channel_tag 5 + +/* Struct field encoding specification for nanopb */ +#define AdminMessage_FIELDLIST(X, a) \ +X(a, STATIC, ONEOF, MESSAGE, (variant,set_radio,set_radio), 1) \ +X(a, STATIC, ONEOF, MESSAGE, (variant,set_owner,set_owner), 2) \ +X(a, STATIC, ONEOF, MESSAGE, (variant,set_channel,set_channel), 3) \ +X(a, STATIC, ONEOF, BOOL, (variant,get_radio,get_radio), 4) \ +X(a, STATIC, ONEOF, UINT32, (variant,get_channel,get_channel), 5) +#define AdminMessage_CALLBACK NULL +#define AdminMessage_DEFAULT NULL +#define AdminMessage_variant_set_radio_MSGTYPE RadioConfig +#define AdminMessage_variant_set_owner_MSGTYPE User +#define AdminMessage_variant_set_channel_MSGTYPE Channel + +extern const pb_msgdesc_t AdminMessage_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define AdminMessage_fields &AdminMessage_msg + +/* Maximum encoded size of messages (where known) */ +#define AdminMessage_size 338 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/src/mesh/generated/deviceonly.pb.h b/src/mesh/generated/deviceonly.pb.h index 01246c70e..3b81f2240 100644 --- a/src/mesh/generated/deviceonly.pb.h +++ b/src/mesh/generated/deviceonly.pb.h @@ -80,7 +80,7 @@ extern const pb_msgdesc_t DeviceState_msg; #define DeviceState_fields &DeviceState_msg /* Maximum encoded size of messages (where known) */ -#define DeviceState_size 6152 +#define DeviceState_size 6146 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/mesh.pb.c b/src/mesh/generated/mesh.pb.c index f0b3f8c66..c4fd0d8e5 100644 --- a/src/mesh/generated/mesh.pb.c +++ b/src/mesh/generated/mesh.pb.c @@ -51,9 +51,6 @@ PB_BIND(FromRadio, FromRadio, 2) PB_BIND(ToRadio, ToRadio, 2) -PB_BIND(AdminMessage, AdminMessage, 2) - - diff --git a/src/mesh/generated/mesh.pb.h b/src/mesh/generated/mesh.pb.h index 6ad5945e1..eed90661c 100644 --- a/src/mesh/generated/mesh.pb.h +++ b/src/mesh/generated/mesh.pb.h @@ -247,7 +247,7 @@ typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t; typedef struct _MeshPacket { uint32_t from; uint32_t to; - uint32_t channel; + uint8_t channel; pb_size_t which_payloadVariant; union { Data decoded; @@ -288,15 +288,6 @@ typedef struct _Routing { uint32_t original_id; } Routing; -typedef struct _AdminMessage { - pb_size_t which_variant; - union { - RadioConfig set_radio; - User set_owner; - Channel set_channel; - }; -} AdminMessage; - typedef struct _FromRadio { uint32_t num; pb_size_t which_payloadVariant; @@ -387,7 +378,6 @@ extern "C" { #define LogRecord_init_default {"", 0, "", _LogRecord_Level_MIN} #define FromRadio_init_default {0, 0, {MyNodeInfo_init_default}} #define ToRadio_init_default {0, {MeshPacket_init_default}} -#define AdminMessage_init_default {0, {RadioConfig_init_default}} #define Position_init_zero {0, 0, 0, 0, 0} #define User_init_zero {"", "", "", {0}} #define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}} @@ -403,7 +393,6 @@ extern "C" { #define LogRecord_init_zero {"", 0, "", _LogRecord_Level_MIN} #define FromRadio_init_zero {0, 0, {MyNodeInfo_init_zero}} #define ToRadio_init_zero {0, {MeshPacket_init_zero}} -#define AdminMessage_init_zero {0, {RadioConfig_init_zero}} /* Field tags (for use in manual encoding/decoding) */ #define ChannelSettings_tx_power_tag 1 @@ -521,9 +510,6 @@ extern "C" { #define Routing_success_id_tag 4 #define Routing_fail_id_tag 5 #define Routing_original_id_tag 6 -#define AdminMessage_set_radio_tag 1 -#define AdminMessage_set_owner_tag 2 -#define AdminMessage_set_channel_tag 3 #define FromRadio_num_tag 1 #define FromRadio_my_info_tag 3 #define FromRadio_node_info_tag 4 @@ -737,16 +723,6 @@ X(a, STATIC, ONEOF, UINT32, (payloadVariant,want_config_id,want_config_id #define ToRadio_DEFAULT NULL #define ToRadio_payloadVariant_packet_MSGTYPE MeshPacket -#define AdminMessage_FIELDLIST(X, a) \ -X(a, STATIC, ONEOF, MESSAGE, (variant,set_radio,set_radio), 1) \ -X(a, STATIC, ONEOF, MESSAGE, (variant,set_owner,set_owner), 2) \ -X(a, STATIC, ONEOF, MESSAGE, (variant,set_channel,set_channel), 3) -#define AdminMessage_CALLBACK NULL -#define AdminMessage_DEFAULT NULL -#define AdminMessage_variant_set_radio_MSGTYPE RadioConfig -#define AdminMessage_variant_set_owner_MSGTYPE User -#define AdminMessage_variant_set_channel_MSGTYPE Channel - extern const pb_msgdesc_t Position_msg; extern const pb_msgdesc_t User_msg; extern const pb_msgdesc_t RouteDiscovery_msg; @@ -762,7 +738,6 @@ extern const pb_msgdesc_t MyNodeInfo_msg; extern const pb_msgdesc_t LogRecord_msg; extern const pb_msgdesc_t FromRadio_msg; extern const pb_msgdesc_t ToRadio_msg; -extern const pb_msgdesc_t AdminMessage_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define Position_fields &Position_msg @@ -780,7 +755,6 @@ extern const pb_msgdesc_t AdminMessage_msg; #define LogRecord_fields &LogRecord_msg #define FromRadio_fields &FromRadio_msg #define ToRadio_fields &ToRadio_msg -#define AdminMessage_fields &AdminMessage_msg /* Maximum encoded size of messages (where known) */ #define Position_size 37 @@ -788,7 +762,7 @@ extern const pb_msgdesc_t AdminMessage_msg; #define RouteDiscovery_size 40 #define Routing_size 47 #define Data_size 255 -#define MeshPacket_size 297 +#define MeshPacket_size 294 #define ChannelSettings_size 87 #define Channel_size 94 #define RadioConfig_size 335 @@ -797,8 +771,7 @@ extern const pb_msgdesc_t AdminMessage_msg; #define MyNodeInfo_size 89 #define LogRecord_size 81 #define FromRadio_size 344 -#define ToRadio_size 300 -#define AdminMessage_size 338 +#define ToRadio_size 297 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/mesh-pb-constants.h b/src/mesh/mesh-pb-constants.h index 21163c496..0b2a0d6cf 100644 --- a/src/mesh/mesh-pb-constants.h +++ b/src/mesh/mesh-pb-constants.h @@ -2,6 +2,7 @@ #include "mesh/generated/mesh.pb.h" #include "mesh/generated/deviceonly.pb.h" +#include "mesh/generated/admin.pb.h" // this file defines constants which come from mesh.options From c7c8b34adf593bf9e34a64a92e47386a3e6786ec Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Fri, 26 Feb 2021 15:34:00 +0800 Subject: [PATCH 25/35] impl get channels/get radio remote api --- proto | 2 +- src/mesh/generated/admin.pb.h | 20 ++++++--- src/plugins/AdminPlugin.cpp | 80 +++++++++++++++++++++++------------ src/plugins/AdminPlugin.h | 5 +++ 4 files changed, 72 insertions(+), 35 deletions(-) diff --git a/proto b/proto index 75ae9929a..6bb139c0a 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 75ae9929a22a0cfa65059f30b27485f2ae8f3a63 +Subproject commit 6bb139c0a43825d868a5e78c07c443f8e9e80b55 diff --git a/src/mesh/generated/admin.pb.h b/src/mesh/generated/admin.pb.h index b3d29825a..36696f717 100644 --- a/src/mesh/generated/admin.pb.h +++ b/src/mesh/generated/admin.pb.h @@ -17,8 +17,10 @@ typedef struct _AdminMessage { RadioConfig set_radio; User set_owner; Channel set_channel; - bool get_radio; - uint32_t get_channel; + bool get_radio_request; + RadioConfig get_radio_response; + uint32_t get_channel_request; + Channel get_channel_response; }; } AdminMessage; @@ -35,21 +37,27 @@ extern "C" { #define AdminMessage_set_radio_tag 1 #define AdminMessage_set_owner_tag 2 #define AdminMessage_set_channel_tag 3 -#define AdminMessage_get_radio_tag 4 -#define AdminMessage_get_channel_tag 5 +#define AdminMessage_get_radio_request_tag 4 +#define AdminMessage_get_radio_response_tag 5 +#define AdminMessage_get_channel_request_tag 6 +#define AdminMessage_get_channel_response_tag 7 /* Struct field encoding specification for nanopb */ #define AdminMessage_FIELDLIST(X, a) \ X(a, STATIC, ONEOF, MESSAGE, (variant,set_radio,set_radio), 1) \ X(a, STATIC, ONEOF, MESSAGE, (variant,set_owner,set_owner), 2) \ X(a, STATIC, ONEOF, MESSAGE, (variant,set_channel,set_channel), 3) \ -X(a, STATIC, ONEOF, BOOL, (variant,get_radio,get_radio), 4) \ -X(a, STATIC, ONEOF, UINT32, (variant,get_channel,get_channel), 5) +X(a, STATIC, ONEOF, BOOL, (variant,get_radio_request,get_radio_request), 4) \ +X(a, STATIC, ONEOF, MESSAGE, (variant,get_radio_response,get_radio_response), 5) \ +X(a, STATIC, ONEOF, UINT32, (variant,get_channel_request,get_channel_request), 6) \ +X(a, STATIC, ONEOF, MESSAGE, (variant,get_channel_response,get_channel_response), 7) #define AdminMessage_CALLBACK NULL #define AdminMessage_DEFAULT NULL #define AdminMessage_variant_set_radio_MSGTYPE RadioConfig #define AdminMessage_variant_set_owner_MSGTYPE User #define AdminMessage_variant_set_channel_MSGTYPE Channel +#define AdminMessage_variant_get_radio_response_MSGTYPE RadioConfig +#define AdminMessage_variant_get_channel_response_MSGTYPE Channel extern const pb_msgdesc_t AdminMessage_msg; diff --git a/src/plugins/AdminPlugin.cpp b/src/plugins/AdminPlugin.cpp index 248a4ebd3..f187fb1cc 100644 --- a/src/plugins/AdminPlugin.cpp +++ b/src/plugins/AdminPlugin.cpp @@ -1,37 +1,67 @@ #include "AdminPlugin.h" +#include "Channels.h" #include "MeshService.h" #include "NodeDB.h" #include "Router.h" #include "configuration.h" #include "main.h" -#include "Channels.h" AdminPlugin *adminPlugin; +void AdminPlugin::handleGetChannel(const MeshPacket &req, uint32_t channelIndex) { + if (req.decoded.want_response) { + // We create the reply here + AdminMessage r = AdminMessage_init_default; + r.get_channel_response = channels.getByIndex(channelIndex); + reply = allocDataProtobuf(r); + } +} + +void AdminPlugin::handleGetRadio(const MeshPacket &req) +{ + if (req.decoded.want_response) { + // We create the reply here + AdminMessage r = AdminMessage_init_default; + r.get_radio_response = devicestate.radio; + reply = allocDataProtobuf(r); + } +} + bool AdminPlugin::handleReceivedProtobuf(const MeshPacket &mp, const AdminMessage *r) { assert(r); - switch(r->which_variant) { - case AdminMessage_set_owner_tag: - DEBUG_MSG("Client is setting owner\n"); - handleSetOwner(r->set_owner); - break; + switch (r->which_variant) { + case AdminMessage_set_owner_tag: + DEBUG_MSG("Client is setting owner\n"); + handleSetOwner(r->set_owner); + break; - case AdminMessage_set_radio_tag: - DEBUG_MSG("Client is setting radio\n"); - handleSetRadio(r->set_radio); - break; + case AdminMessage_set_radio_tag: + DEBUG_MSG("Client is setting radio\n"); + handleSetRadio(r->set_radio); + break; - case AdminMessage_set_channel_tag: - DEBUG_MSG("Client is setting channel\n"); - handleSetChannel(r->set_channel); - break; + case AdminMessage_set_channel_tag: + DEBUG_MSG("Client is setting channel\n"); + handleSetChannel(r->set_channel); + break; + + case AdminMessage_get_channel_request_tag: + DEBUG_MSG("Client is getting channel %d\n", r->get_channel_request); + handleGetChannel(mp, r->get_channel_request); + break; + + case AdminMessage_get_radio_request_tag: + DEBUG_MSG("Client is getting radio\n"); + handleGetRadio(mp); + break; + + default: + break; } return false; // Let others look at this message also if they want } - - void AdminPlugin::handleSetOwner(const User &o) { int changed = 0; @@ -58,11 +88,10 @@ void AdminPlugin::handleSetChannel(const Channel &cc) channels.setChannel(cc); bool didReset = service.reloadConfig(); - /* FIXME - do we need this still? + /* FIXME - do we need this still? if (didReset) { state = STATE_SEND_MY_INFO; // Squirt a completely new set of configs to the client } */ - } void AdminPlugin::handleSetRadio(const RadioConfig &r) @@ -75,19 +104,14 @@ void AdminPlugin::handleSetRadio(const RadioConfig &r) } */ } - MeshPacket *AdminPlugin::allocReply() { - assert(0); // 1.2 refactoring fixme, Not sure if anything needs this yet? - // return allocDataProtobuf(u); - return NULL; + auto r = reply; + reply = NULL; // Only use each reply once + return r; } -AdminPlugin::AdminPlugin() - : ProtobufPlugin("Admin", PortNum_ADMIN_APP, AdminMessage_fields) -{ +AdminPlugin::AdminPlugin() : ProtobufPlugin("Admin", PortNum_ADMIN_APP, AdminMessage_fields) +{ // FIXME, restrict to the admin channel for rx } - - - diff --git a/src/plugins/AdminPlugin.h b/src/plugins/AdminPlugin.h index de8ffac11..71dd5536a 100644 --- a/src/plugins/AdminPlugin.h +++ b/src/plugins/AdminPlugin.h @@ -6,6 +6,8 @@ */ class AdminPlugin : public ProtobufPlugin { + MeshPacket *reply = NULL; + public: /** Constructor * name is for debugging output @@ -27,6 +29,9 @@ class AdminPlugin : public ProtobufPlugin void handleSetOwner(const User &o); void handleSetChannel(const Channel &cc); void handleSetRadio(const RadioConfig &r); + + void handleGetChannel(const MeshPacket &req, uint32_t channelIndex); + void handleGetRadio(const MeshPacket &req); }; extern AdminPlugin *adminPlugin; \ No newline at end of file From 0307e4161ec604b06a45279fc236b01588f66f28 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Fri, 26 Feb 2021 20:10:41 +0800 Subject: [PATCH 26/35] get settings message works --- docs/software/TODO.md | 1 + src/mesh/MeshPlugin.cpp | 8 ++++++-- src/plugins/AdminPlugin.cpp | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/software/TODO.md b/docs/software/TODO.md index 564f11f2d..2320eaafb 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -21,6 +21,7 @@ You probably don't care about this section - skip to the next one. * implement 'get channels' Admin plugin operation * use get-channels from python * use set-channel from python +* combine acks and responses in a single message if possible * use portuino TCP connection to debug with python API * make python tests more exhaustive * document the relationship between want_response (indicating remote node received it) and want_ack (indicating that this message should be sent reliably - and also get acks from the first rx node and naks if it is never delivered) diff --git a/src/mesh/MeshPlugin.cpp b/src/mesh/MeshPlugin.cpp index 2d6b907c5..c9cc89e12 100644 --- a/src/mesh/MeshPlugin.cpp +++ b/src/mesh/MeshPlugin.cpp @@ -47,8 +47,12 @@ void MeshPlugin::callPlugins(const MeshPacket &mp) bool handled = pi.handleReceived(mp); - // Possibly send replies (but only if the message was directed to us specifically, i.e. not for promiscious sniffing), also not if we sent it - if (mp.decoded.want_response && toUs && mp.from != ourNodeNum) { + // Possibly send replies (but only if the message was directed to us specifically, i.e. not for promiscious sniffing) + + // NOTE: we send a reply *even if the (non broadcast) request was from us* which is unfortunate but necessary because currently when the phone + // sends things, it sends things using the local node ID as the from address. A better solution (FIXME) would be to let phones + // have their own distinct addresses and we 'route' to them like any other node. + if (mp.decoded.want_response && toUs && (mp.from != ourNodeNum || mp.to == ourNodeNum)) { pi.sendResponse(mp); DEBUG_MSG("Plugin %s sent a response\n", pi.name); } diff --git a/src/plugins/AdminPlugin.cpp b/src/plugins/AdminPlugin.cpp index f187fb1cc..63f7a41da 100644 --- a/src/plugins/AdminPlugin.cpp +++ b/src/plugins/AdminPlugin.cpp @@ -13,6 +13,7 @@ void AdminPlugin::handleGetChannel(const MeshPacket &req, uint32_t channelIndex) // We create the reply here AdminMessage r = AdminMessage_init_default; r.get_channel_response = channels.getByIndex(channelIndex); + r.which_variant = AdminMessage_get_channel_response_tag; reply = allocDataProtobuf(r); } } @@ -23,6 +24,7 @@ void AdminPlugin::handleGetRadio(const MeshPacket &req) // We create the reply here AdminMessage r = AdminMessage_init_default; r.get_radio_response = devicestate.radio; + r.which_variant = AdminMessage_get_radio_response_tag; reply = allocDataProtobuf(r); } } From 989f52494db5e3d532d7b52076a881f030630582 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Fri, 26 Feb 2021 20:36:22 +0800 Subject: [PATCH 27/35] clean up ack packets --- proto | 2 +- src/mesh/DSRRouter.cpp | 2 +- src/mesh/MeshPlugin.cpp | 2 ++ src/mesh/ReliableRouter.cpp | 4 ++-- src/mesh/SinglePortPlugin.h | 1 + src/mesh/generated/deviceonly.pb.h | 2 +- src/mesh/generated/mesh.pb.h | 32 ++++++++++++------------------ src/plugins/RoutingPlugin.cpp | 10 ++-------- 8 files changed, 23 insertions(+), 32 deletions(-) diff --git a/proto b/proto index 6bb139c0a..fa40a9389 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 6bb139c0a43825d868a5e78c07c443f8e9e80b55 +Subproject commit fa40a9389bc910b6291fabe148260070e393600f diff --git a/src/mesh/DSRRouter.cpp b/src/mesh/DSRRouter.cpp index 0b28257f6..5fa6b1609 100644 --- a/src/mesh/DSRRouter.cpp +++ b/src/mesh/DSRRouter.cpp @@ -142,7 +142,7 @@ void DSRRouter::sniffReceived(const MeshPacket *p, const Routing *c) if (c) { // handle naks - convert them to route error packets // All naks are generated locally, because we failed resending the packet too many times - PacketId nakId = c->fail_id; + PacketId nakId = c->error_reason ? p->decoded.request_id : 0; if (nakId) { auto pending = findPendingPacket(p->to, nakId); if (pending && diff --git a/src/mesh/MeshPlugin.cpp b/src/mesh/MeshPlugin.cpp index c9cc89e12..6fd3c72b8 100644 --- a/src/mesh/MeshPlugin.cpp +++ b/src/mesh/MeshPlugin.cpp @@ -93,8 +93,10 @@ void MeshPlugin::sendResponse(const MeshPacket &req) { * This ensures that if the request packet was sent reliably, the reply is sent that way as well. */ void setReplyTo(MeshPacket *p, const MeshPacket &to) { + assert(p->which_payloadVariant == MeshPacket_decoded_tag); // Should already be set by now p->to = to.from; p->want_ack = to.want_ack; + p->decoded.request_id = to.id; } std::vector MeshPlugin::GetMeshPluginsWithUIFrames() { diff --git a/src/mesh/ReliableRouter.cpp b/src/mesh/ReliableRouter.cpp index 65e1ff9f8..da743c389 100644 --- a/src/mesh/ReliableRouter.cpp +++ b/src/mesh/ReliableRouter.cpp @@ -65,8 +65,8 @@ void ReliableRouter::sniffReceived(const MeshPacket *p, const Routing *c) // If the payload is valid, look for ack/nak if (c) { - PacketId ackId = c->success_id; - PacketId nakId = c->fail_id; + PacketId ackId = c->error_reason == Routing_Error_NONE ? p->decoded.request_id : 0; + PacketId nakId = c->error_reason != Routing_Error_NONE ? p->decoded.request_id : 0; // We intentionally don't check wasSeenRecently, because it is harmless to delete non existent retransmission records if (ackId || nakId) { diff --git a/src/mesh/SinglePortPlugin.h b/src/mesh/SinglePortPlugin.h index 305532dc5..20836246d 100644 --- a/src/mesh/SinglePortPlugin.h +++ b/src/mesh/SinglePortPlugin.h @@ -33,6 +33,7 @@ class SinglePortPlugin : public MeshPlugin // Update our local node info with our position (even if we don't decide to update anyone else) MeshPacket *p = router->allocForSending(); p->decoded.portnum = ourPortNum; + p->which_payloadVariant = MeshPacket_decoded_tag; return p; } diff --git a/src/mesh/generated/deviceonly.pb.h b/src/mesh/generated/deviceonly.pb.h index 3b81f2240..1e4443af5 100644 --- a/src/mesh/generated/deviceonly.pb.h +++ b/src/mesh/generated/deviceonly.pb.h @@ -80,7 +80,7 @@ extern const pb_msgdesc_t DeviceState_msg; #define DeviceState_fields &DeviceState_msg /* Maximum encoded size of messages (where known) */ -#define DeviceState_size 6146 +#define DeviceState_size 6156 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/mesh.pb.h b/src/mesh/generated/mesh.pb.h index eed90661c..79e14f26a 100644 --- a/src/mesh/generated/mesh.pb.h +++ b/src/mesh/generated/mesh.pb.h @@ -141,6 +141,7 @@ typedef struct _Data { bool want_response; uint32_t dest; uint32_t source; + uint32_t request_id; } Data; typedef struct _LogRecord { @@ -282,10 +283,7 @@ typedef struct _Routing { RouteDiscovery route_request; RouteDiscovery route_reply; Routing_Error error_reason; - uint32_t success_id; - uint32_t fail_id; }; - uint32_t original_id; } Routing; typedef struct _FromRadio { @@ -366,8 +364,8 @@ extern "C" { #define Position_init_default {0, 0, 0, 0, 0} #define User_init_default {"", "", "", {0}} #define RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}} -#define Routing_init_default {0, {RouteDiscovery_init_default}, 0} -#define Data_init_default {_PortNum_MIN, {0, {0}}, 0, 0, 0} +#define Routing_init_default {0, {RouteDiscovery_init_default}} +#define Data_init_default {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0} #define MeshPacket_init_default {0, 0, 0, 0, {Data_init_default}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} #define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} #define Channel_init_default {0, false, ChannelSettings_init_default, _Channel_Role_MIN} @@ -381,8 +379,8 @@ extern "C" { #define Position_init_zero {0, 0, 0, 0, 0} #define User_init_zero {"", "", "", {0}} #define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}} -#define Routing_init_zero {0, {RouteDiscovery_init_zero}, 0} -#define Data_init_zero {_PortNum_MIN, {0, {0}}, 0, 0, 0} +#define Routing_init_zero {0, {RouteDiscovery_init_zero}} +#define Data_init_zero {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0} #define MeshPacket_init_zero {0, 0, 0, 0, {Data_init_zero}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} #define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} #define Channel_init_zero {0, false, ChannelSettings_init_zero, _Channel_Role_MIN} @@ -411,6 +409,7 @@ extern "C" { #define Data_want_response_tag 3 #define Data_dest_tag 4 #define Data_source_tag 5 +#define Data_request_id_tag 6 #define LogRecord_message_tag 1 #define LogRecord_time_tag 2 #define LogRecord_source_tag 3 @@ -507,9 +506,6 @@ extern "C" { #define Routing_route_request_tag 1 #define Routing_route_reply_tag 2 #define Routing_error_reason_tag 3 -#define Routing_success_id_tag 4 -#define Routing_fail_id_tag 5 -#define Routing_original_id_tag 6 #define FromRadio_num_tag 1 #define FromRadio_my_info_tag 3 #define FromRadio_node_info_tag 4 @@ -548,10 +544,7 @@ X(a, STATIC, REPEATED, FIXED32, route, 2) #define Routing_FIELDLIST(X, a) \ X(a, STATIC, ONEOF, MESSAGE, (variant,route_request,route_request), 1) \ X(a, STATIC, ONEOF, MESSAGE, (variant,route_reply,route_reply), 2) \ -X(a, STATIC, ONEOF, UENUM, (variant,error_reason,error_reason), 3) \ -X(a, STATIC, ONEOF, FIXED32, (variant,success_id,success_id), 4) \ -X(a, STATIC, ONEOF, FIXED32, (variant,fail_id,fail_id), 5) \ -X(a, STATIC, SINGULAR, FIXED32, original_id, 6) +X(a, STATIC, ONEOF, UENUM, (variant,error_reason,error_reason), 3) #define Routing_CALLBACK NULL #define Routing_DEFAULT NULL #define Routing_variant_route_request_MSGTYPE RouteDiscovery @@ -562,7 +555,8 @@ X(a, STATIC, SINGULAR, UENUM, portnum, 1) \ X(a, STATIC, SINGULAR, BYTES, payload, 2) \ X(a, STATIC, SINGULAR, BOOL, want_response, 3) \ X(a, STATIC, SINGULAR, FIXED32, dest, 4) \ -X(a, STATIC, SINGULAR, FIXED32, source, 5) +X(a, STATIC, SINGULAR, FIXED32, source, 5) \ +X(a, STATIC, SINGULAR, FIXED32, request_id, 6) #define Data_CALLBACK NULL #define Data_DEFAULT NULL @@ -760,9 +754,9 @@ extern const pb_msgdesc_t ToRadio_msg; #define Position_size 37 #define User_size 72 #define RouteDiscovery_size 40 -#define Routing_size 47 -#define Data_size 255 -#define MeshPacket_size 294 +#define Routing_size 42 +#define Data_size 260 +#define MeshPacket_size 298 #define ChannelSettings_size 87 #define Channel_size 94 #define RadioConfig_size 335 @@ -771,7 +765,7 @@ extern const pb_msgdesc_t ToRadio_msg; #define MyNodeInfo_size 89 #define LogRecord_size 81 #define FromRadio_size 344 -#define ToRadio_size 297 +#define ToRadio_size 301 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/plugins/RoutingPlugin.cpp b/src/plugins/RoutingPlugin.cpp index 9af7d31ff..18427bdca 100644 --- a/src/plugins/RoutingPlugin.cpp +++ b/src/plugins/RoutingPlugin.cpp @@ -38,20 +38,14 @@ void RoutingPlugin::sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom) { Routing c = Routing_init_default; - if (!err) { - c.success_id = idFrom; - } else { - c.fail_id = idFrom; - - // Also send back the error reason - c.error_reason = err; - } + c.error_reason = err; auto p = allocDataProtobuf(c); p->priority = MeshPacket_Priority_ACK; p->hop_limit = 0; // Assume just immediate neighbors for now p->to = to; + p->decoded.request_id = idFrom; DEBUG_MSG("Sending an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id); router->sendLocal(p); // we sometimes send directly to the local node From 63e0b530546a914b27bc3a8453fb1a094a5f9a33 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sat, 27 Feb 2021 09:17:58 +0800 Subject: [PATCH 28/35] 1 index channel index --- docs/software/TODO.md | 2 +- proto | 2 +- src/mesh/SinglePortPlugin.h | 1 - src/plugins/AdminPlugin.cpp | 4 ++-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/software/TODO.md b/docs/software/TODO.md index 2320eaafb..481799cc1 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -21,7 +21,7 @@ You probably don't care about this section - skip to the next one. * implement 'get channels' Admin plugin operation * use get-channels from python * use set-channel from python -* combine acks and responses in a single message if possible +* combine acks and responses in a single message if possible (do routing plugin LAST and drop ACK if someone else has already replied) * use portuino TCP connection to debug with python API * make python tests more exhaustive * document the relationship between want_response (indicating remote node received it) and want_ack (indicating that this message should be sent reliably - and also get acks from the first rx node and naks if it is never delivered) diff --git a/proto b/proto index fa40a9389..83e00e564 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit fa40a9389bc910b6291fabe148260070e393600f +Subproject commit 83e00e564d3973b594a46e786b62eed2823e02ed diff --git a/src/mesh/SinglePortPlugin.h b/src/mesh/SinglePortPlugin.h index 20836246d..305532dc5 100644 --- a/src/mesh/SinglePortPlugin.h +++ b/src/mesh/SinglePortPlugin.h @@ -33,7 +33,6 @@ class SinglePortPlugin : public MeshPlugin // Update our local node info with our position (even if we don't decide to update anyone else) MeshPacket *p = router->allocForSending(); p->decoded.portnum = ourPortNum; - p->which_payloadVariant = MeshPacket_decoded_tag; return p; } diff --git a/src/plugins/AdminPlugin.cpp b/src/plugins/AdminPlugin.cpp index 63f7a41da..bba1b39a9 100644 --- a/src/plugins/AdminPlugin.cpp +++ b/src/plugins/AdminPlugin.cpp @@ -49,8 +49,8 @@ bool AdminPlugin::handleReceivedProtobuf(const MeshPacket &mp, const AdminMessag break; case AdminMessage_get_channel_request_tag: - DEBUG_MSG("Client is getting channel %d\n", r->get_channel_request); - handleGetChannel(mp, r->get_channel_request); + DEBUG_MSG("Client is getting channel %d\n", r->get_channel_request - 1); + handleGetChannel(mp, r->get_channel_request - 1); break; case AdminMessage_get_radio_request_tag: From fb47c3a03d0a490b1dd95f01eec979a72b24ddfc Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sat, 27 Feb 2021 13:17:18 +0800 Subject: [PATCH 29/35] move channel and settings protos --- proto | 2 +- src/mesh/PhoneAPI.cpp | 18 +- src/mesh/PhoneAPI.h | 2 +- src/mesh/generated/admin.pb.h | 2 + src/mesh/generated/apponly.pb.h | 1 + src/mesh/generated/channel.pb.c | 17 ++ src/mesh/generated/channel.pb.h | 125 +++++++++++ src/mesh/generated/deviceonly.pb.h | 2 + src/mesh/generated/mesh.pb.c | 18 -- src/mesh/generated/mesh.pb.h | 333 +--------------------------- src/mesh/generated/radioconfig.pb.c | 19 ++ src/mesh/generated/radioconfig.pb.h | 268 ++++++++++++++++++++++ 12 files changed, 438 insertions(+), 369 deletions(-) create mode 100644 src/mesh/generated/channel.pb.c create mode 100644 src/mesh/generated/channel.pb.h create mode 100644 src/mesh/generated/radioconfig.pb.c create mode 100644 src/mesh/generated/radioconfig.pb.h diff --git a/proto b/proto index 83e00e564..3edb02dab 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 83e00e564d3973b594a46e786b62eed2823e02ed +Subproject commit 3edb02dabb9b8b72d90bbbb7233b557c09391b87 diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index 7f63fc18e..a7797c255 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -124,24 +124,11 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) : (gps && gps->isConnected()); // Update with latest GPS connect info fromRadioScratch.which_payloadVariant = FromRadio_my_info_tag; fromRadioScratch.my_info = myNodeInfo; - state = STATE_SEND_RADIO; + state = STATE_SEND_NODEINFO; service.refreshMyNodeInfo(); // Update my NodeInfo because the client will be asking for it soon. break; - case STATE_SEND_RADIO: - fromRadioScratch.which_payloadVariant = FromRadio_radio_tag; - - fromRadioScratch.radio = radioConfig; - - // NOTE: The phone app needs to know the ls_secs value so it can properly expect sleep behavior. - // So even if we internally use 0 to represent 'use default' we still need to send the value we are - // using to the app (so that even old phone apps work with new device loads). - fromRadioScratch.radio.preferences.ls_secs = getPref_ls_secs(); - - state = STATE_SEND_NODEINFO; - break; - case STATE_SEND_NODEINFO: { const NodeInfo *info = nodeInfoForPhone; nodeInfoForPhone = NULL; // We just consumed a nodeinfo, will need a new one next time @@ -218,9 +205,6 @@ bool PhoneAPI::available() nodeInfoForPhone = nodeDB.readNextInfo(); return true; // Always say we have something, because we might need to advance our state machine - case STATE_SEND_RADIO: - return true; - case STATE_SEND_COMPLETE_ID: return true; diff --git a/src/mesh/PhoneAPI.h b/src/mesh/PhoneAPI.h index 19c5d0583..094e9830b 100644 --- a/src/mesh/PhoneAPI.h +++ b/src/mesh/PhoneAPI.h @@ -23,7 +23,7 @@ class PhoneAPI STATE_LEGACY, // (no longer used) old default state - until Android apps are all updated, uses the old BLE API STATE_SEND_NOTHING, // (Eventual) Initial state, don't send anything until the client starts asking for config STATE_SEND_MY_INFO, // send our my info record - STATE_SEND_RADIO, + // STATE_SEND_RADIO, // in 1.2 we now send this as a regular mesh packet // STATE_SEND_OWNER, no need to send Owner specially, it is just part of the nodedb STATE_SEND_NODEINFO, // states progress in this order as the device sends to to the client STATE_SEND_COMPLETE_ID, diff --git a/src/mesh/generated/admin.pb.h b/src/mesh/generated/admin.pb.h index 36696f717..f9be1cada 100644 --- a/src/mesh/generated/admin.pb.h +++ b/src/mesh/generated/admin.pb.h @@ -5,6 +5,8 @@ #define PB_ADMIN_PB_H_INCLUDED #include #include "mesh.pb.h" +#include "radioconfig.pb.h" +#include "channel.pb.h" #if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. diff --git a/src/mesh/generated/apponly.pb.h b/src/mesh/generated/apponly.pb.h index af527f0c8..89fe235da 100644 --- a/src/mesh/generated/apponly.pb.h +++ b/src/mesh/generated/apponly.pb.h @@ -5,6 +5,7 @@ #define PB_APPONLY_PB_H_INCLUDED #include #include "mesh.pb.h" +#include "channel.pb.h" #if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. diff --git a/src/mesh/generated/channel.pb.c b/src/mesh/generated/channel.pb.c new file mode 100644 index 000000000..329314dae --- /dev/null +++ b/src/mesh/generated/channel.pb.c @@ -0,0 +1,17 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.4 */ + +#include "channel.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(ChannelSettings, ChannelSettings, AUTO) + + +PB_BIND(Channel, Channel, AUTO) + + + + + diff --git a/src/mesh/generated/channel.pb.h b/src/mesh/generated/channel.pb.h new file mode 100644 index 000000000..151495be1 --- /dev/null +++ b/src/mesh/generated/channel.pb.h @@ -0,0 +1,125 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.4 */ + +#ifndef PB_CHANNEL_PB_H_INCLUDED +#define PB_CHANNEL_PB_H_INCLUDED +#include + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Enum definitions */ +typedef enum _ChannelSettings_ModemConfig { + ChannelSettings_ModemConfig_Bw125Cr45Sf128 = 0, + ChannelSettings_ModemConfig_Bw500Cr45Sf128 = 1, + ChannelSettings_ModemConfig_Bw31_25Cr48Sf512 = 2, + ChannelSettings_ModemConfig_Bw125Cr48Sf4096 = 3 +} ChannelSettings_ModemConfig; + +typedef enum _Channel_Role { + Channel_Role_DISABLED = 0, + Channel_Role_PRIMARY = 1, + Channel_Role_SECONDARY = 2 +} Channel_Role; + +/* Struct definitions */ +typedef PB_BYTES_ARRAY_T(32) ChannelSettings_psk_t; +typedef struct _ChannelSettings { + int8_t tx_power; + ChannelSettings_ModemConfig modem_config; + ChannelSettings_psk_t psk; + char name[12]; + uint16_t bandwidth; + uint32_t spread_factor; + uint8_t coding_rate; + uint8_t channel_num; + uint32_t id; + bool uplink_enabled; + bool downlink_enabled; +} ChannelSettings; + +typedef struct _Channel { + uint8_t index; + bool has_settings; + ChannelSettings settings; + Channel_Role role; +} Channel; + + +/* Helper constants for enums */ +#define _ChannelSettings_ModemConfig_MIN ChannelSettings_ModemConfig_Bw125Cr45Sf128 +#define _ChannelSettings_ModemConfig_MAX ChannelSettings_ModemConfig_Bw125Cr48Sf4096 +#define _ChannelSettings_ModemConfig_ARRAYSIZE ((ChannelSettings_ModemConfig)(ChannelSettings_ModemConfig_Bw125Cr48Sf4096+1)) + +#define _Channel_Role_MIN Channel_Role_DISABLED +#define _Channel_Role_MAX Channel_Role_SECONDARY +#define _Channel_Role_ARRAYSIZE ((Channel_Role)(Channel_Role_SECONDARY+1)) + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} +#define Channel_init_default {0, false, ChannelSettings_init_default, _Channel_Role_MIN} +#define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} +#define Channel_init_zero {0, false, ChannelSettings_init_zero, _Channel_Role_MIN} + +/* Field tags (for use in manual encoding/decoding) */ +#define ChannelSettings_tx_power_tag 1 +#define ChannelSettings_modem_config_tag 3 +#define ChannelSettings_psk_tag 4 +#define ChannelSettings_name_tag 5 +#define ChannelSettings_bandwidth_tag 6 +#define ChannelSettings_spread_factor_tag 7 +#define ChannelSettings_coding_rate_tag 8 +#define ChannelSettings_channel_num_tag 9 +#define ChannelSettings_id_tag 10 +#define ChannelSettings_uplink_enabled_tag 16 +#define ChannelSettings_downlink_enabled_tag 17 +#define Channel_index_tag 1 +#define Channel_settings_tag 2 +#define Channel_role_tag 3 + +/* Struct field encoding specification for nanopb */ +#define ChannelSettings_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, tx_power, 1) \ +X(a, STATIC, SINGULAR, UENUM, modem_config, 3) \ +X(a, STATIC, SINGULAR, BYTES, psk, 4) \ +X(a, STATIC, SINGULAR, STRING, name, 5) \ +X(a, STATIC, SINGULAR, UINT32, bandwidth, 6) \ +X(a, STATIC, SINGULAR, UINT32, spread_factor, 7) \ +X(a, STATIC, SINGULAR, UINT32, coding_rate, 8) \ +X(a, STATIC, SINGULAR, UINT32, channel_num, 9) \ +X(a, STATIC, SINGULAR, FIXED32, id, 10) \ +X(a, STATIC, SINGULAR, BOOL, uplink_enabled, 16) \ +X(a, STATIC, SINGULAR, BOOL, downlink_enabled, 17) +#define ChannelSettings_CALLBACK NULL +#define ChannelSettings_DEFAULT NULL + +#define Channel_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, index, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, settings, 2) \ +X(a, STATIC, SINGULAR, UENUM, role, 3) +#define Channel_CALLBACK NULL +#define Channel_DEFAULT NULL +#define Channel_settings_MSGTYPE ChannelSettings + +extern const pb_msgdesc_t ChannelSettings_msg; +extern const pb_msgdesc_t Channel_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define ChannelSettings_fields &ChannelSettings_msg +#define Channel_fields &Channel_msg + +/* Maximum encoded size of messages (where known) */ +#define ChannelSettings_size 87 +#define Channel_size 94 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/src/mesh/generated/deviceonly.pb.h b/src/mesh/generated/deviceonly.pb.h index 1e4443af5..52420a376 100644 --- a/src/mesh/generated/deviceonly.pb.h +++ b/src/mesh/generated/deviceonly.pb.h @@ -5,6 +5,8 @@ #define PB_DEVICEONLY_PB_H_INCLUDED #include #include "mesh.pb.h" +#include "radioconfig.pb.h" +#include "channel.pb.h" #if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. diff --git a/src/mesh/generated/mesh.pb.c b/src/mesh/generated/mesh.pb.c index c4fd0d8e5..ab27832f8 100644 --- a/src/mesh/generated/mesh.pb.c +++ b/src/mesh/generated/mesh.pb.c @@ -24,18 +24,6 @@ PB_BIND(Data, Data, 2) PB_BIND(MeshPacket, MeshPacket, 2) -PB_BIND(ChannelSettings, ChannelSettings, AUTO) - - -PB_BIND(Channel, Channel, AUTO) - - -PB_BIND(RadioConfig, RadioConfig, 2) - - -PB_BIND(RadioConfig_UserPreferences, RadioConfig_UserPreferences, 2) - - PB_BIND(NodeInfo, NodeInfo, AUTO) @@ -57,9 +45,3 @@ PB_BIND(ToRadio, ToRadio, 2) - - - - - - diff --git a/src/mesh/generated/mesh.pb.h b/src/mesh/generated/mesh.pb.h index 79e14f26a..a8f36a140 100644 --- a/src/mesh/generated/mesh.pb.h +++ b/src/mesh/generated/mesh.pb.h @@ -16,52 +16,6 @@ typedef enum _Constants { Constants_DATA_PAYLOAD_LEN = 240 } 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 _ChargeCurrent { - ChargeCurrent_MAUnset = 0, - ChargeCurrent_MA100 = 1, - ChargeCurrent_MA190 = 2, - ChargeCurrent_MA280 = 3, - ChargeCurrent_MA360 = 4, - ChargeCurrent_MA450 = 5, - ChargeCurrent_MA550 = 6, - ChargeCurrent_MA630 = 7, - ChargeCurrent_MA700 = 8, - ChargeCurrent_MA780 = 9, - ChargeCurrent_MA880 = 10, - ChargeCurrent_MA960 = 11, - ChargeCurrent_MA1000 = 12, - ChargeCurrent_MA1080 = 13, - ChargeCurrent_MA1160 = 14, - ChargeCurrent_MA1240 = 15, - ChargeCurrent_MA1320 = 16 -} ChargeCurrent; - -typedef enum _GpsOperation { - GpsOperation_GpsOpUnset = 0, - GpsOperation_GpsOpStationary = 1, - GpsOperation_GpsOpMobile = 2, - GpsOperation_GpsOpTimeOnly = 3, - GpsOperation_GpsOpDisabled = 4 -} GpsOperation; - -typedef enum _LocationSharing { - LocationSharing_LocUnset = 0, - LocationSharing_LocEnabled = 1, - LocationSharing_LocDisabled = 2 -} LocationSharing; - typedef enum _CriticalErrorCode { CriticalErrorCode_None = 0, CriticalErrorCode_TxWatchdog = 1, @@ -95,19 +49,6 @@ typedef enum _MeshPacket_Priority { MeshPacket_Priority_MAX = 127 } MeshPacket_Priority; -typedef enum _ChannelSettings_ModemConfig { - ChannelSettings_ModemConfig_Bw125Cr45Sf128 = 0, - ChannelSettings_ModemConfig_Bw500Cr45Sf128 = 1, - ChannelSettings_ModemConfig_Bw31_25Cr48Sf512 = 2, - ChannelSettings_ModemConfig_Bw125Cr48Sf4096 = 3 -} ChannelSettings_ModemConfig; - -typedef enum _Channel_Role { - Channel_Role_DISABLED = 0, - Channel_Role_PRIMARY = 1, - Channel_Role_SECONDARY = 2 -} Channel_Role; - typedef enum _LogRecord_Level { LogRecord_Level_UNSET = 0, LogRecord_Level_CRITICAL = 50, @@ -119,21 +60,6 @@ typedef enum _LogRecord_Level { } LogRecord_Level; /* Struct definitions */ -typedef PB_BYTES_ARRAY_T(32) ChannelSettings_psk_t; -typedef struct _ChannelSettings { - int8_t tx_power; - ChannelSettings_ModemConfig modem_config; - ChannelSettings_psk_t psk; - char name[12]; - uint16_t bandwidth; - uint32_t spread_factor; - uint8_t coding_rate; - uint8_t channel_num; - uint32_t id; - bool uplink_enabled; - bool downlink_enabled; -} ChannelSettings; - typedef PB_BYTES_ARRAY_T(237) Data_payload_t; typedef struct _Data { PortNum portnum; @@ -174,57 +100,6 @@ typedef struct _Position { uint32_t time; } Position; -typedef struct _RadioConfig_UserPreferences { - uint32_t position_broadcast_secs; - uint32_t send_owner_interval; - uint32_t wait_bluetooth_secs; - uint32_t screen_on_secs; - uint32_t phone_timeout_secs; - uint32_t phone_sds_timeout_sec; - uint32_t mesh_sds_timeout_secs; - uint32_t sds_secs; - uint32_t ls_secs; - uint32_t min_wake_secs; - char wifi_ssid[33]; - char wifi_password[64]; - bool wifi_ap_mode; - RegionCode region; - ChargeCurrent charge_current; - LocationSharing location_share; - GpsOperation gps_operation; - uint32_t gps_update_interval; - uint32_t gps_attempt_time; - bool is_router; - bool is_low_power; - bool fixed_position; - bool factory_reset; - bool debug_log_enabled; - pb_size_t ignore_incoming_count; - uint32_t ignore_incoming[3]; - bool serialplugin_enabled; - bool serialplugin_echo; - uint32_t serialplugin_rxd; - uint32_t serialplugin_txd; - uint32_t serialplugin_timeout; - uint32_t serialplugin_mode; - bool ext_notification_plugin_enabled; - uint32_t ext_notification_plugin_output_ms; - uint32_t ext_notification_plugin_output; - bool ext_notification_plugin_active; - bool ext_notification_plugin_alert_message; - bool ext_notification_plugin_alert_bell; - bool range_test_plugin_enabled; - uint32_t range_test_plugin_sender; - bool range_test_plugin_save; - bool store_forward_plugin_enabled; - uint32_t store_forward_plugin_records; - bool environmental_measurement_plugin_measurement_enabled; - bool environmental_measurement_plugin_screen_enabled; - uint32_t environmental_measurement_plugin_read_error_count_threshold; - uint32_t environmental_measurement_plugin_update_interval; - uint32_t environmental_measurement_plugin_recovery_interval; -} RadioConfig_UserPreferences; - typedef struct _RouteDiscovery { pb_size_t route_count; uint32_t route[8]; @@ -237,13 +112,6 @@ typedef struct _User { pb_byte_t macaddr[6]; } User; -typedef struct _Channel { - uint8_t index; - bool has_settings; - ChannelSettings settings; - Channel_Role role; -} Channel; - typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t; typedef struct _MeshPacket { uint32_t from; @@ -272,11 +140,6 @@ typedef struct _NodeInfo { float snr; } NodeInfo; -typedef struct _RadioConfig { - bool has_preferences; - RadioConfig_UserPreferences preferences; -} RadioConfig; - typedef struct _Routing { pb_size_t which_variant; union { @@ -292,11 +155,9 @@ typedef struct _FromRadio { union { MyNodeInfo my_info; NodeInfo node_info; - RadioConfig radio; LogRecord log_record; uint32_t config_complete_id; bool rebooted; - Channel channel; MeshPacket packet; }; } FromRadio; @@ -315,22 +176,6 @@ typedef struct _ToRadio { #define _Constants_MAX Constants_DATA_PAYLOAD_LEN #define _Constants_ARRAYSIZE ((Constants)(Constants_DATA_PAYLOAD_LEN+1)) -#define _RegionCode_MIN RegionCode_Unset -#define _RegionCode_MAX RegionCode_TW -#define _RegionCode_ARRAYSIZE ((RegionCode)(RegionCode_TW+1)) - -#define _ChargeCurrent_MIN ChargeCurrent_MAUnset -#define _ChargeCurrent_MAX ChargeCurrent_MA1320 -#define _ChargeCurrent_ARRAYSIZE ((ChargeCurrent)(ChargeCurrent_MA1320+1)) - -#define _GpsOperation_MIN GpsOperation_GpsOpUnset -#define _GpsOperation_MAX GpsOperation_GpsOpDisabled -#define _GpsOperation_ARRAYSIZE ((GpsOperation)(GpsOperation_GpsOpDisabled+1)) - -#define _LocationSharing_MIN LocationSharing_LocUnset -#define _LocationSharing_MAX LocationSharing_LocDisabled -#define _LocationSharing_ARRAYSIZE ((LocationSharing)(LocationSharing_LocDisabled+1)) - #define _CriticalErrorCode_MIN CriticalErrorCode_None #define _CriticalErrorCode_MAX CriticalErrorCode_TransmitFailed #define _CriticalErrorCode_ARRAYSIZE ((CriticalErrorCode)(CriticalErrorCode_TransmitFailed+1)) @@ -343,14 +188,6 @@ typedef struct _ToRadio { #define _MeshPacket_Priority_MAX MeshPacket_Priority_MAX #define _MeshPacket_Priority_ARRAYSIZE ((MeshPacket_Priority)(MeshPacket_Priority_MAX+1)) -#define _ChannelSettings_ModemConfig_MIN ChannelSettings_ModemConfig_Bw125Cr45Sf128 -#define _ChannelSettings_ModemConfig_MAX ChannelSettings_ModemConfig_Bw125Cr48Sf4096 -#define _ChannelSettings_ModemConfig_ARRAYSIZE ((ChannelSettings_ModemConfig)(ChannelSettings_ModemConfig_Bw125Cr48Sf4096+1)) - -#define _Channel_Role_MIN Channel_Role_DISABLED -#define _Channel_Role_MAX Channel_Role_SECONDARY -#define _Channel_Role_ARRAYSIZE ((Channel_Role)(Channel_Role_SECONDARY+1)) - #define _LogRecord_Level_MIN LogRecord_Level_UNSET #define _LogRecord_Level_MAX LogRecord_Level_CRITICAL #define _LogRecord_Level_ARRAYSIZE ((LogRecord_Level)(LogRecord_Level_CRITICAL+1)) @@ -367,10 +204,6 @@ extern "C" { #define Routing_init_default {0, {RouteDiscovery_init_default}} #define Data_init_default {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0} #define MeshPacket_init_default {0, 0, 0, 0, {Data_init_default}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} -#define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} -#define Channel_init_default {0, false, ChannelSettings_init_default, _Channel_Role_MIN} -#define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default} -#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 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, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0} #define LogRecord_init_default {"", 0, "", _LogRecord_Level_MIN} @@ -382,10 +215,6 @@ extern "C" { #define Routing_init_zero {0, {RouteDiscovery_init_zero}} #define Data_init_zero {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0} #define MeshPacket_init_zero {0, 0, 0, 0, {Data_init_zero}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} -#define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} -#define Channel_init_zero {0, false, ChannelSettings_init_zero, _Channel_Role_MIN} -#define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero} -#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 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, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0} #define LogRecord_init_zero {"", 0, "", _LogRecord_Level_MIN} @@ -393,17 +222,6 @@ extern "C" { #define ToRadio_init_zero {0, {MeshPacket_init_zero}} /* Field tags (for use in manual encoding/decoding) */ -#define ChannelSettings_tx_power_tag 1 -#define ChannelSettings_modem_config_tag 3 -#define ChannelSettings_psk_tag 4 -#define ChannelSettings_name_tag 5 -#define ChannelSettings_bandwidth_tag 6 -#define ChannelSettings_spread_factor_tag 7 -#define ChannelSettings_coding_rate_tag 8 -#define ChannelSettings_channel_num_tag 9 -#define ChannelSettings_id_tag 10 -#define ChannelSettings_uplink_enabled_tag 16 -#define ChannelSettings_downlink_enabled_tag 17 #define Data_portnum_tag 1 #define Data_payload_tag 2 #define Data_want_response_tag 3 @@ -431,61 +249,11 @@ extern "C" { #define Position_altitude_tag 3 #define Position_battery_level_tag 4 #define Position_time_tag 9 -#define RadioConfig_UserPreferences_position_broadcast_secs_tag 1 -#define RadioConfig_UserPreferences_send_owner_interval_tag 2 -#define RadioConfig_UserPreferences_wait_bluetooth_secs_tag 4 -#define RadioConfig_UserPreferences_screen_on_secs_tag 5 -#define RadioConfig_UserPreferences_phone_timeout_secs_tag 6 -#define RadioConfig_UserPreferences_phone_sds_timeout_sec_tag 7 -#define RadioConfig_UserPreferences_mesh_sds_timeout_secs_tag 8 -#define RadioConfig_UserPreferences_sds_secs_tag 9 -#define RadioConfig_UserPreferences_ls_secs_tag 10 -#define RadioConfig_UserPreferences_min_wake_secs_tag 11 -#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_region_tag 15 -#define RadioConfig_UserPreferences_charge_current_tag 16 -#define RadioConfig_UserPreferences_location_share_tag 32 -#define RadioConfig_UserPreferences_gps_operation_tag 33 -#define RadioConfig_UserPreferences_gps_update_interval_tag 34 -#define RadioConfig_UserPreferences_gps_attempt_time_tag 36 -#define RadioConfig_UserPreferences_is_router_tag 37 -#define RadioConfig_UserPreferences_is_low_power_tag 38 -#define RadioConfig_UserPreferences_fixed_position_tag 39 -#define RadioConfig_UserPreferences_factory_reset_tag 100 -#define RadioConfig_UserPreferences_debug_log_enabled_tag 101 -#define RadioConfig_UserPreferences_ignore_incoming_tag 103 -#define RadioConfig_UserPreferences_serialplugin_enabled_tag 120 -#define RadioConfig_UserPreferences_serialplugin_echo_tag 121 -#define RadioConfig_UserPreferences_serialplugin_rxd_tag 122 -#define RadioConfig_UserPreferences_serialplugin_txd_tag 123 -#define RadioConfig_UserPreferences_serialplugin_timeout_tag 124 -#define RadioConfig_UserPreferences_serialplugin_mode_tag 125 -#define RadioConfig_UserPreferences_ext_notification_plugin_enabled_tag 126 -#define RadioConfig_UserPreferences_ext_notification_plugin_output_ms_tag 127 -#define RadioConfig_UserPreferences_ext_notification_plugin_output_tag 128 -#define RadioConfig_UserPreferences_ext_notification_plugin_active_tag 129 -#define RadioConfig_UserPreferences_ext_notification_plugin_alert_message_tag 130 -#define RadioConfig_UserPreferences_ext_notification_plugin_alert_bell_tag 131 -#define RadioConfig_UserPreferences_range_test_plugin_enabled_tag 132 -#define RadioConfig_UserPreferences_range_test_plugin_sender_tag 133 -#define RadioConfig_UserPreferences_range_test_plugin_save_tag 134 -#define RadioConfig_UserPreferences_store_forward_plugin_enabled_tag 136 -#define RadioConfig_UserPreferences_store_forward_plugin_records_tag 137 -#define RadioConfig_UserPreferences_environmental_measurement_plugin_measurement_enabled_tag 140 -#define RadioConfig_UserPreferences_environmental_measurement_plugin_screen_enabled_tag 141 -#define RadioConfig_UserPreferences_environmental_measurement_plugin_read_error_count_threshold_tag 142 -#define RadioConfig_UserPreferences_environmental_measurement_plugin_update_interval_tag 143 -#define RadioConfig_UserPreferences_environmental_measurement_plugin_recovery_interval_tag 144 #define RouteDiscovery_route_tag 2 #define User_id_tag 1 #define User_long_name_tag 2 #define User_short_name_tag 3 #define User_macaddr_tag 4 -#define Channel_index_tag 1 -#define Channel_settings_tag 2 -#define Channel_role_tag 3 #define MeshPacket_from_tag 1 #define MeshPacket_to_tag 2 #define MeshPacket_channel_tag 3 @@ -502,18 +270,15 @@ extern "C" { #define NodeInfo_position_tag 3 #define NodeInfo_next_hop_tag 5 #define NodeInfo_snr_tag 7 -#define RadioConfig_preferences_tag 1 #define Routing_route_request_tag 1 #define Routing_route_reply_tag 2 #define Routing_error_reason_tag 3 #define FromRadio_num_tag 1 #define FromRadio_my_info_tag 3 #define FromRadio_node_info_tag 4 -#define FromRadio_radio_tag 6 #define FromRadio_log_record_tag 7 #define FromRadio_config_complete_id_tag 8 #define FromRadio_rebooted_tag 9 -#define FromRadio_channel_tag 10 #define FromRadio_packet_tag 11 #define ToRadio_packet_tag 2 #define ToRadio_want_config_id_tag 100 @@ -576,86 +341,6 @@ X(a, STATIC, SINGULAR, UENUM, priority, 12) #define MeshPacket_DEFAULT NULL #define MeshPacket_payloadVariant_decoded_MSGTYPE Data -#define ChannelSettings_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, INT32, tx_power, 1) \ -X(a, STATIC, SINGULAR, UENUM, modem_config, 3) \ -X(a, STATIC, SINGULAR, BYTES, psk, 4) \ -X(a, STATIC, SINGULAR, STRING, name, 5) \ -X(a, STATIC, SINGULAR, UINT32, bandwidth, 6) \ -X(a, STATIC, SINGULAR, UINT32, spread_factor, 7) \ -X(a, STATIC, SINGULAR, UINT32, coding_rate, 8) \ -X(a, STATIC, SINGULAR, UINT32, channel_num, 9) \ -X(a, STATIC, SINGULAR, FIXED32, id, 10) \ -X(a, STATIC, SINGULAR, BOOL, uplink_enabled, 16) \ -X(a, STATIC, SINGULAR, BOOL, downlink_enabled, 17) -#define ChannelSettings_CALLBACK NULL -#define ChannelSettings_DEFAULT NULL - -#define Channel_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, index, 1) \ -X(a, STATIC, OPTIONAL, MESSAGE, settings, 2) \ -X(a, STATIC, SINGULAR, UENUM, role, 3) -#define Channel_CALLBACK NULL -#define Channel_DEFAULT NULL -#define Channel_settings_MSGTYPE ChannelSettings - -#define RadioConfig_FIELDLIST(X, a) \ -X(a, STATIC, OPTIONAL, MESSAGE, preferences, 1) -#define RadioConfig_CALLBACK NULL -#define RadioConfig_DEFAULT NULL -#define RadioConfig_preferences_MSGTYPE RadioConfig_UserPreferences - -#define RadioConfig_UserPreferences_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, position_broadcast_secs, 1) \ -X(a, STATIC, SINGULAR, UINT32, send_owner_interval, 2) \ -X(a, STATIC, SINGULAR, UINT32, wait_bluetooth_secs, 4) \ -X(a, STATIC, SINGULAR, UINT32, screen_on_secs, 5) \ -X(a, STATIC, SINGULAR, UINT32, phone_timeout_secs, 6) \ -X(a, STATIC, SINGULAR, UINT32, phone_sds_timeout_sec, 7) \ -X(a, STATIC, SINGULAR, UINT32, mesh_sds_timeout_secs, 8) \ -X(a, STATIC, SINGULAR, UINT32, sds_secs, 9) \ -X(a, STATIC, SINGULAR, UINT32, ls_secs, 10) \ -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, UENUM, region, 15) \ -X(a, STATIC, SINGULAR, UENUM, charge_current, 16) \ -X(a, STATIC, SINGULAR, UENUM, location_share, 32) \ -X(a, STATIC, SINGULAR, UENUM, gps_operation, 33) \ -X(a, STATIC, SINGULAR, UINT32, gps_update_interval, 34) \ -X(a, STATIC, SINGULAR, UINT32, gps_attempt_time, 36) \ -X(a, STATIC, SINGULAR, BOOL, is_router, 37) \ -X(a, STATIC, SINGULAR, BOOL, is_low_power, 38) \ -X(a, STATIC, SINGULAR, BOOL, fixed_position, 39) \ -X(a, STATIC, SINGULAR, BOOL, factory_reset, 100) \ -X(a, STATIC, SINGULAR, BOOL, debug_log_enabled, 101) \ -X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103) \ -X(a, STATIC, SINGULAR, BOOL, serialplugin_enabled, 120) \ -X(a, STATIC, SINGULAR, BOOL, serialplugin_echo, 121) \ -X(a, STATIC, SINGULAR, UINT32, serialplugin_rxd, 122) \ -X(a, STATIC, SINGULAR, UINT32, serialplugin_txd, 123) \ -X(a, STATIC, SINGULAR, UINT32, serialplugin_timeout, 124) \ -X(a, STATIC, SINGULAR, UINT32, serialplugin_mode, 125) \ -X(a, STATIC, SINGULAR, BOOL, ext_notification_plugin_enabled, 126) \ -X(a, STATIC, SINGULAR, UINT32, ext_notification_plugin_output_ms, 127) \ -X(a, STATIC, SINGULAR, UINT32, ext_notification_plugin_output, 128) \ -X(a, STATIC, SINGULAR, BOOL, ext_notification_plugin_active, 129) \ -X(a, STATIC, SINGULAR, BOOL, ext_notification_plugin_alert_message, 130) \ -X(a, STATIC, SINGULAR, BOOL, ext_notification_plugin_alert_bell, 131) \ -X(a, STATIC, SINGULAR, BOOL, range_test_plugin_enabled, 132) \ -X(a, STATIC, SINGULAR, UINT32, range_test_plugin_sender, 133) \ -X(a, STATIC, SINGULAR, BOOL, range_test_plugin_save, 134) \ -X(a, STATIC, SINGULAR, BOOL, store_forward_plugin_enabled, 136) \ -X(a, STATIC, SINGULAR, UINT32, store_forward_plugin_records, 137) \ -X(a, STATIC, SINGULAR, BOOL, environmental_measurement_plugin_measurement_enabled, 140) \ -X(a, STATIC, SINGULAR, BOOL, environmental_measurement_plugin_screen_enabled, 141) \ -X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_read_error_count_threshold, 142) \ -X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_update_interval, 143) \ -X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_recovery_interval, 144) -#define RadioConfig_UserPreferences_CALLBACK NULL -#define RadioConfig_UserPreferences_DEFAULT NULL - #define NodeInfo_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, num, 1) \ X(a, STATIC, OPTIONAL, MESSAGE, user, 2) \ @@ -695,19 +380,15 @@ X(a, STATIC, SINGULAR, UENUM, level, 4) X(a, STATIC, SINGULAR, UINT32, num, 1) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,my_info,my_info), 3) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,node_info,node_info), 4) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,radio,radio), 6) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,log_record,log_record), 7) \ X(a, STATIC, ONEOF, UINT32, (payloadVariant,config_complete_id,config_complete_id), 8) \ X(a, STATIC, ONEOF, BOOL, (payloadVariant,rebooted,rebooted), 9) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,channel,channel), 10) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,packet,packet), 11) #define FromRadio_CALLBACK NULL #define FromRadio_DEFAULT NULL #define FromRadio_payloadVariant_my_info_MSGTYPE MyNodeInfo #define FromRadio_payloadVariant_node_info_MSGTYPE NodeInfo -#define FromRadio_payloadVariant_radio_MSGTYPE RadioConfig #define FromRadio_payloadVariant_log_record_MSGTYPE LogRecord -#define FromRadio_payloadVariant_channel_MSGTYPE Channel #define FromRadio_payloadVariant_packet_MSGTYPE MeshPacket #define ToRadio_FIELDLIST(X, a) \ @@ -723,10 +404,6 @@ extern const pb_msgdesc_t RouteDiscovery_msg; extern const pb_msgdesc_t Routing_msg; extern const pb_msgdesc_t Data_msg; extern const pb_msgdesc_t MeshPacket_msg; -extern const pb_msgdesc_t ChannelSettings_msg; -extern const pb_msgdesc_t Channel_msg; -extern const pb_msgdesc_t RadioConfig_msg; -extern const pb_msgdesc_t RadioConfig_UserPreferences_msg; extern const pb_msgdesc_t NodeInfo_msg; extern const pb_msgdesc_t MyNodeInfo_msg; extern const pb_msgdesc_t LogRecord_msg; @@ -740,10 +417,6 @@ extern const pb_msgdesc_t ToRadio_msg; #define Routing_fields &Routing_msg #define Data_fields &Data_msg #define MeshPacket_fields &MeshPacket_msg -#define ChannelSettings_fields &ChannelSettings_msg -#define Channel_fields &Channel_msg -#define RadioConfig_fields &RadioConfig_msg -#define RadioConfig_UserPreferences_fields &RadioConfig_UserPreferences_msg #define NodeInfo_fields &NodeInfo_msg #define MyNodeInfo_fields &MyNodeInfo_msg #define LogRecord_fields &LogRecord_msg @@ -757,14 +430,10 @@ extern const pb_msgdesc_t ToRadio_msg; #define Routing_size 42 #define Data_size 260 #define MeshPacket_size 298 -#define ChannelSettings_size 87 -#define Channel_size 94 -#define RadioConfig_size 335 -#define RadioConfig_UserPreferences_size 332 #define NodeInfo_size 130 #define MyNodeInfo_size 89 #define LogRecord_size 81 -#define FromRadio_size 344 +#define FromRadio_size 307 #define ToRadio_size 301 #ifdef __cplusplus diff --git a/src/mesh/generated/radioconfig.pb.c b/src/mesh/generated/radioconfig.pb.c new file mode 100644 index 000000000..85aa7aa18 --- /dev/null +++ b/src/mesh/generated/radioconfig.pb.c @@ -0,0 +1,19 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.4 */ + +#include "radioconfig.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(RadioConfig, RadioConfig, 2) + + +PB_BIND(RadioConfig_UserPreferences, RadioConfig_UserPreferences, 2) + + + + + + + diff --git a/src/mesh/generated/radioconfig.pb.h b/src/mesh/generated/radioconfig.pb.h new file mode 100644 index 000000000..b8a6bfd7a --- /dev/null +++ b/src/mesh/generated/radioconfig.pb.h @@ -0,0 +1,268 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.4 */ + +#ifndef PB_RADIOCONFIG_PB_H_INCLUDED +#define PB_RADIOCONFIG_PB_H_INCLUDED +#include + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Enum definitions */ +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 _ChargeCurrent { + ChargeCurrent_MAUnset = 0, + ChargeCurrent_MA100 = 1, + ChargeCurrent_MA190 = 2, + ChargeCurrent_MA280 = 3, + ChargeCurrent_MA360 = 4, + ChargeCurrent_MA450 = 5, + ChargeCurrent_MA550 = 6, + ChargeCurrent_MA630 = 7, + ChargeCurrent_MA700 = 8, + ChargeCurrent_MA780 = 9, + ChargeCurrent_MA880 = 10, + ChargeCurrent_MA960 = 11, + ChargeCurrent_MA1000 = 12, + ChargeCurrent_MA1080 = 13, + ChargeCurrent_MA1160 = 14, + ChargeCurrent_MA1240 = 15, + ChargeCurrent_MA1320 = 16 +} ChargeCurrent; + +typedef enum _GpsOperation { + GpsOperation_GpsOpUnset = 0, + GpsOperation_GpsOpStationary = 1, + GpsOperation_GpsOpMobile = 2, + GpsOperation_GpsOpTimeOnly = 3, + GpsOperation_GpsOpDisabled = 4 +} GpsOperation; + +typedef enum _LocationSharing { + LocationSharing_LocUnset = 0, + LocationSharing_LocEnabled = 1, + LocationSharing_LocDisabled = 2 +} LocationSharing; + +/* Struct definitions */ +typedef struct _RadioConfig_UserPreferences { + uint32_t position_broadcast_secs; + uint32_t send_owner_interval; + uint32_t wait_bluetooth_secs; + uint32_t screen_on_secs; + uint32_t phone_timeout_secs; + uint32_t phone_sds_timeout_sec; + uint32_t mesh_sds_timeout_secs; + uint32_t sds_secs; + uint32_t ls_secs; + uint32_t min_wake_secs; + char wifi_ssid[33]; + char wifi_password[64]; + bool wifi_ap_mode; + RegionCode region; + ChargeCurrent charge_current; + LocationSharing location_share; + GpsOperation gps_operation; + uint32_t gps_update_interval; + uint32_t gps_attempt_time; + bool is_router; + bool is_low_power; + bool fixed_position; + bool factory_reset; + bool debug_log_enabled; + pb_size_t ignore_incoming_count; + uint32_t ignore_incoming[3]; + bool serialplugin_enabled; + bool serialplugin_echo; + uint32_t serialplugin_rxd; + uint32_t serialplugin_txd; + uint32_t serialplugin_timeout; + uint32_t serialplugin_mode; + bool ext_notification_plugin_enabled; + uint32_t ext_notification_plugin_output_ms; + uint32_t ext_notification_plugin_output; + bool ext_notification_plugin_active; + bool ext_notification_plugin_alert_message; + bool ext_notification_plugin_alert_bell; + bool range_test_plugin_enabled; + uint32_t range_test_plugin_sender; + bool range_test_plugin_save; + bool store_forward_plugin_enabled; + uint32_t store_forward_plugin_records; + bool environmental_measurement_plugin_measurement_enabled; + bool environmental_measurement_plugin_screen_enabled; + uint32_t environmental_measurement_plugin_read_error_count_threshold; + uint32_t environmental_measurement_plugin_update_interval; + uint32_t environmental_measurement_plugin_recovery_interval; +} RadioConfig_UserPreferences; + +typedef struct _RadioConfig { + bool has_preferences; + RadioConfig_UserPreferences preferences; +} RadioConfig; + + +/* Helper constants for enums */ +#define _RegionCode_MIN RegionCode_Unset +#define _RegionCode_MAX RegionCode_TW +#define _RegionCode_ARRAYSIZE ((RegionCode)(RegionCode_TW+1)) + +#define _ChargeCurrent_MIN ChargeCurrent_MAUnset +#define _ChargeCurrent_MAX ChargeCurrent_MA1320 +#define _ChargeCurrent_ARRAYSIZE ((ChargeCurrent)(ChargeCurrent_MA1320+1)) + +#define _GpsOperation_MIN GpsOperation_GpsOpUnset +#define _GpsOperation_MAX GpsOperation_GpsOpDisabled +#define _GpsOperation_ARRAYSIZE ((GpsOperation)(GpsOperation_GpsOpDisabled+1)) + +#define _LocationSharing_MIN LocationSharing_LocUnset +#define _LocationSharing_MAX LocationSharing_LocDisabled +#define _LocationSharing_ARRAYSIZE ((LocationSharing)(LocationSharing_LocDisabled+1)) + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default} +#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero} +#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define RadioConfig_UserPreferences_position_broadcast_secs_tag 1 +#define RadioConfig_UserPreferences_send_owner_interval_tag 2 +#define RadioConfig_UserPreferences_wait_bluetooth_secs_tag 4 +#define RadioConfig_UserPreferences_screen_on_secs_tag 5 +#define RadioConfig_UserPreferences_phone_timeout_secs_tag 6 +#define RadioConfig_UserPreferences_phone_sds_timeout_sec_tag 7 +#define RadioConfig_UserPreferences_mesh_sds_timeout_secs_tag 8 +#define RadioConfig_UserPreferences_sds_secs_tag 9 +#define RadioConfig_UserPreferences_ls_secs_tag 10 +#define RadioConfig_UserPreferences_min_wake_secs_tag 11 +#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_region_tag 15 +#define RadioConfig_UserPreferences_charge_current_tag 16 +#define RadioConfig_UserPreferences_location_share_tag 32 +#define RadioConfig_UserPreferences_gps_operation_tag 33 +#define RadioConfig_UserPreferences_gps_update_interval_tag 34 +#define RadioConfig_UserPreferences_gps_attempt_time_tag 36 +#define RadioConfig_UserPreferences_is_router_tag 37 +#define RadioConfig_UserPreferences_is_low_power_tag 38 +#define RadioConfig_UserPreferences_fixed_position_tag 39 +#define RadioConfig_UserPreferences_factory_reset_tag 100 +#define RadioConfig_UserPreferences_debug_log_enabled_tag 101 +#define RadioConfig_UserPreferences_ignore_incoming_tag 103 +#define RadioConfig_UserPreferences_serialplugin_enabled_tag 120 +#define RadioConfig_UserPreferences_serialplugin_echo_tag 121 +#define RadioConfig_UserPreferences_serialplugin_rxd_tag 122 +#define RadioConfig_UserPreferences_serialplugin_txd_tag 123 +#define RadioConfig_UserPreferences_serialplugin_timeout_tag 124 +#define RadioConfig_UserPreferences_serialplugin_mode_tag 125 +#define RadioConfig_UserPreferences_ext_notification_plugin_enabled_tag 126 +#define RadioConfig_UserPreferences_ext_notification_plugin_output_ms_tag 127 +#define RadioConfig_UserPreferences_ext_notification_plugin_output_tag 128 +#define RadioConfig_UserPreferences_ext_notification_plugin_active_tag 129 +#define RadioConfig_UserPreferences_ext_notification_plugin_alert_message_tag 130 +#define RadioConfig_UserPreferences_ext_notification_plugin_alert_bell_tag 131 +#define RadioConfig_UserPreferences_range_test_plugin_enabled_tag 132 +#define RadioConfig_UserPreferences_range_test_plugin_sender_tag 133 +#define RadioConfig_UserPreferences_range_test_plugin_save_tag 134 +#define RadioConfig_UserPreferences_store_forward_plugin_enabled_tag 136 +#define RadioConfig_UserPreferences_store_forward_plugin_records_tag 137 +#define RadioConfig_UserPreferences_environmental_measurement_plugin_measurement_enabled_tag 140 +#define RadioConfig_UserPreferences_environmental_measurement_plugin_screen_enabled_tag 141 +#define RadioConfig_UserPreferences_environmental_measurement_plugin_read_error_count_threshold_tag 142 +#define RadioConfig_UserPreferences_environmental_measurement_plugin_update_interval_tag 143 +#define RadioConfig_UserPreferences_environmental_measurement_plugin_recovery_interval_tag 144 +#define RadioConfig_preferences_tag 1 + +/* Struct field encoding specification for nanopb */ +#define RadioConfig_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, preferences, 1) +#define RadioConfig_CALLBACK NULL +#define RadioConfig_DEFAULT NULL +#define RadioConfig_preferences_MSGTYPE RadioConfig_UserPreferences + +#define RadioConfig_UserPreferences_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, position_broadcast_secs, 1) \ +X(a, STATIC, SINGULAR, UINT32, send_owner_interval, 2) \ +X(a, STATIC, SINGULAR, UINT32, wait_bluetooth_secs, 4) \ +X(a, STATIC, SINGULAR, UINT32, screen_on_secs, 5) \ +X(a, STATIC, SINGULAR, UINT32, phone_timeout_secs, 6) \ +X(a, STATIC, SINGULAR, UINT32, phone_sds_timeout_sec, 7) \ +X(a, STATIC, SINGULAR, UINT32, mesh_sds_timeout_secs, 8) \ +X(a, STATIC, SINGULAR, UINT32, sds_secs, 9) \ +X(a, STATIC, SINGULAR, UINT32, ls_secs, 10) \ +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, UENUM, region, 15) \ +X(a, STATIC, SINGULAR, UENUM, charge_current, 16) \ +X(a, STATIC, SINGULAR, UENUM, location_share, 32) \ +X(a, STATIC, SINGULAR, UENUM, gps_operation, 33) \ +X(a, STATIC, SINGULAR, UINT32, gps_update_interval, 34) \ +X(a, STATIC, SINGULAR, UINT32, gps_attempt_time, 36) \ +X(a, STATIC, SINGULAR, BOOL, is_router, 37) \ +X(a, STATIC, SINGULAR, BOOL, is_low_power, 38) \ +X(a, STATIC, SINGULAR, BOOL, fixed_position, 39) \ +X(a, STATIC, SINGULAR, BOOL, factory_reset, 100) \ +X(a, STATIC, SINGULAR, BOOL, debug_log_enabled, 101) \ +X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103) \ +X(a, STATIC, SINGULAR, BOOL, serialplugin_enabled, 120) \ +X(a, STATIC, SINGULAR, BOOL, serialplugin_echo, 121) \ +X(a, STATIC, SINGULAR, UINT32, serialplugin_rxd, 122) \ +X(a, STATIC, SINGULAR, UINT32, serialplugin_txd, 123) \ +X(a, STATIC, SINGULAR, UINT32, serialplugin_timeout, 124) \ +X(a, STATIC, SINGULAR, UINT32, serialplugin_mode, 125) \ +X(a, STATIC, SINGULAR, BOOL, ext_notification_plugin_enabled, 126) \ +X(a, STATIC, SINGULAR, UINT32, ext_notification_plugin_output_ms, 127) \ +X(a, STATIC, SINGULAR, UINT32, ext_notification_plugin_output, 128) \ +X(a, STATIC, SINGULAR, BOOL, ext_notification_plugin_active, 129) \ +X(a, STATIC, SINGULAR, BOOL, ext_notification_plugin_alert_message, 130) \ +X(a, STATIC, SINGULAR, BOOL, ext_notification_plugin_alert_bell, 131) \ +X(a, STATIC, SINGULAR, BOOL, range_test_plugin_enabled, 132) \ +X(a, STATIC, SINGULAR, UINT32, range_test_plugin_sender, 133) \ +X(a, STATIC, SINGULAR, BOOL, range_test_plugin_save, 134) \ +X(a, STATIC, SINGULAR, BOOL, store_forward_plugin_enabled, 136) \ +X(a, STATIC, SINGULAR, UINT32, store_forward_plugin_records, 137) \ +X(a, STATIC, SINGULAR, BOOL, environmental_measurement_plugin_measurement_enabled, 140) \ +X(a, STATIC, SINGULAR, BOOL, environmental_measurement_plugin_screen_enabled, 141) \ +X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_read_error_count_threshold, 142) \ +X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_update_interval, 143) \ +X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_recovery_interval, 144) +#define RadioConfig_UserPreferences_CALLBACK NULL +#define RadioConfig_UserPreferences_DEFAULT NULL + +extern const pb_msgdesc_t RadioConfig_msg; +extern const pb_msgdesc_t RadioConfig_UserPreferences_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define RadioConfig_fields &RadioConfig_msg +#define RadioConfig_UserPreferences_fields &RadioConfig_UserPreferences_msg + +/* Maximum encoded size of messages (where known) */ +#define RadioConfig_size 335 +#define RadioConfig_UserPreferences_size 332 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif From a51c08bfb1e5cac09c2cdebf80606248e25ef460 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sat, 27 Feb 2021 14:42:07 +0800 Subject: [PATCH 30/35] todo updated --- docs/software/TODO.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/software/TODO.md b/docs/software/TODO.md index 481799cc1..a5924c199 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -18,8 +18,9 @@ You probably don't care about this section - skip to the next one. * DONE test single channel without python * DONE Use "default" for name if name is empty * DONE fix python data packet receiving (nothing showing in log?) -* implement 'get channels' Admin plugin operation -* use get-channels from python +* DONE implement 'get channels' Admin plugin operation +* DONE use get-channels from python +* use get channels & get settings from android * use set-channel from python * combine acks and responses in a single message if possible (do routing plugin LAST and drop ACK if someone else has already replied) * use portuino TCP connection to debug with python API @@ -31,7 +32,7 @@ You probably don't care about this section - skip to the next one. * add gui in android app for setting region * warn in python api if we are too new to talk to the device code * make a post warning about 1.2, telling how to stay on old android & python clients. link to this from the android dialog message and python version warning. -* "FIXME - move the radioconfig/user/channel READ operations into SettingsMessage as well" +* DONE "FIXME - move the radioconfig/user/channel READ operations into SettingsMessage as well" * DONE scrub protobufs to make sure they are absoloute minimum wiresize (in particular Data, ChannelSets and positions) * change syncword * allow chaning packets in single transmission - to increase airtime efficiency and amortize packet overhead From f6761d637f55b73454ae64ab9842909062613e58 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Tue, 2 Mar 2021 11:46:00 +0800 Subject: [PATCH 31/35] proto update --- proto | 2 +- src/mesh/generated/mesh.pb.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/proto b/proto index 3edb02dab..2def8ece6 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 3edb02dabb9b8b72d90bbbb7233b557c09391b87 +Subproject commit 2def8ece61f792a2d7c4fb9297727b0efb4bf555 diff --git a/src/mesh/generated/mesh.pb.h b/src/mesh/generated/mesh.pb.h index a8f36a140..c92a44f2b 100644 --- a/src/mesh/generated/mesh.pb.h +++ b/src/mesh/generated/mesh.pb.h @@ -275,7 +275,7 @@ extern "C" { #define Routing_error_reason_tag 3 #define FromRadio_num_tag 1 #define FromRadio_my_info_tag 3 -#define FromRadio_node_info_tag 4 +#define FromRadio_node_info_tag 5 #define FromRadio_log_record_tag 7 #define FromRadio_config_complete_id_tag 8 #define FromRadio_rebooted_tag 9 @@ -379,7 +379,7 @@ X(a, STATIC, SINGULAR, UENUM, level, 4) #define FromRadio_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, num, 1) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,my_info,my_info), 3) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,node_info,node_info), 4) \ +X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,node_info,node_info), 5) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,log_record,log_record), 7) \ X(a, STATIC, ONEOF, UINT32, (payloadVariant,config_complete_id,config_complete_id), 8) \ X(a, STATIC, ONEOF, BOOL, (payloadVariant,rebooted,rebooted), 9) \ From 082101f99f6f7c8ad7a1e36465c608bd81426dbf Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Tue, 2 Mar 2021 12:44:48 +0800 Subject: [PATCH 32/35] wire compat --- proto | 2 +- src/mesh/generated/mesh.pb.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/proto b/proto index 2def8ece6..7de496ffe 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 2def8ece61f792a2d7c4fb9297727b0efb4bf555 +Subproject commit 7de496ffe941f88e9d99c2ef2c7bc01f79efe11e diff --git a/src/mesh/generated/mesh.pb.h b/src/mesh/generated/mesh.pb.h index c92a44f2b..a8f36a140 100644 --- a/src/mesh/generated/mesh.pb.h +++ b/src/mesh/generated/mesh.pb.h @@ -275,7 +275,7 @@ extern "C" { #define Routing_error_reason_tag 3 #define FromRadio_num_tag 1 #define FromRadio_my_info_tag 3 -#define FromRadio_node_info_tag 5 +#define FromRadio_node_info_tag 4 #define FromRadio_log_record_tag 7 #define FromRadio_config_complete_id_tag 8 #define FromRadio_rebooted_tag 9 @@ -379,7 +379,7 @@ X(a, STATIC, SINGULAR, UENUM, level, 4) #define FromRadio_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, num, 1) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,my_info,my_info), 3) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,node_info,node_info), 5) \ +X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,node_info,node_info), 4) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,log_record,log_record), 7) \ X(a, STATIC, ONEOF, UINT32, (payloadVariant,config_complete_id,config_complete_id), 8) \ X(a, STATIC, ONEOF, BOOL, (payloadVariant,rebooted,rebooted), 9) \ From 2ac410600456d9e739678f7a80ef33d46aa6d9b8 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Tue, 2 Mar 2021 12:51:28 +0800 Subject: [PATCH 33/35] add play store link --- docs/software/android-too-old.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/software/android-too-old.md b/docs/software/android-too-old.md index 2e2f2c766..4f0c2403b 100644 --- a/docs/software/android-too-old.md +++ b/docs/software/android-too-old.md @@ -6,6 +6,8 @@ If you've landed here that means your android application is too old for the run Probably, what this means is that you installed the **alpha test** version of the firmware from github. We really love people helping with development by running the alpha test binaries. But if you aren't ready to sign up for that right now, please go back to [github](https://github.com/meshtastic/Meshtastic-device/releases) and install the latest **not alpha** 1.1.x firmware. -If you **do** intend to run the alpha test please opt-in to receive the alpha test version of the android application. +If you **do** intend to run the alpha test please [opt-in](https://play.google.com/apps/testing/com.geeksville.mesh) to receive the alpha test version of the android application. + +If you are willing to be an alpha tester, please keep an eye on our forum where we post frequent release notes. We also will actively help you with any bugs you might encounter (along our shared journey of new feature goodness). If you have problems/questions please post in our [forum](https://meshtastic.discourse.group) and some nice person will probably help. \ No newline at end of file From e884ace0ab941c649b9d3fa60deef5b958e0a54b Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Tue, 2 Mar 2021 15:16:22 +0800 Subject: [PATCH 34/35] show build name --- bin/program-release-tbeam.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/program-release-tbeam.sh b/bin/program-release-tbeam.sh index 037431678..7870680fd 100755 --- a/bin/program-release-tbeam.sh +++ b/bin/program-release-tbeam.sh @@ -3,4 +3,5 @@ set -e VERSION=`bin/buildinfo.py` +echo Installing release/latest/bins/firmware-tbeam-US-$VERSION.bin esptool.py --baud 921600 write_flash 0x10000 release/latest/bins/firmware-tbeam-US-$VERSION.bin From 866125f2abaf7e35c315d74fcc98a55b1a9fe23d Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Tue, 2 Mar 2021 15:37:56 +0800 Subject: [PATCH 35/35] fix release script for universal builds --- bin/build-all.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/build-all.sh b/bin/build-all.sh index d9a6393e4..fae51feee 100755 --- a/bin/build-all.sh +++ b/bin/build-all.sh @@ -94,7 +94,7 @@ pio run --environment tbeam -t buildfs cp .pio/build/tbeam/spiffs.bin $OUTDIR/bins/universal/spiffs-$VERSION.bin # keep the bins in archive also -cp $OUTDIR/bins/firmware* $OUTDIR/bins/universal/spiffs* $OUTDIR/elfs/firmware* $OUTDIR/bins/universal/firmware* $OUTDIR/elfs/universal/firmware* $ARCHIVEDIR +cp $OUTDIR/bins/universal/spiffs* $OUTDIR/bins/universal/firmware* $OUTDIR/elfs/universal/firmware* $ARCHIVEDIR echo Updating android bins $OUTDIR/forandroid rm -rf $OUTDIR/forandroid @@ -115,6 +115,6 @@ XML echo Generating $ARCHIVEDIR/firmware-$VERSION.zip rm -f $ARCHIVEDIR/firmware-$VERSION.zip -zip --junk-paths $ARCHIVEDIR/firmware-$VERSION.zip $ARCHIVEDIR/spiffs-$VERSION.bin $OUTDIR/bins/firmware-*-$VERSION.* images/system-info.bin bin/device-install.sh bin/device-update.sh +zip --junk-paths $ARCHIVEDIR/firmware-$VERSION.zip $ARCHIVEDIR/spiffs-$VERSION.bin $OUTDIR/bins/universal/firmware-*-$VERSION.* images/system-info.bin bin/device-install.sh bin/device-update.sh echo BUILT ALL