diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml index 09c0635a4..145a75c2d 100644 --- a/.github/workflows/main_matrix.yml +++ b/.github/workflows/main_matrix.yml @@ -95,6 +95,7 @@ jobs: - board: tlora-t3s3-v1 - board: t-watch-s3 - board: t-deck + - board: picomputer-s3 uses: ./.github/workflows/build_esp32_s3.yml with: board: ${{ matrix.board }} diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index cdf662e1f..8ab9166fb 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -1,6 +1,6 @@ version: 0.1 cli: - version: 1.9.1 + version: 1.10.0 plugins: sources: - id: trunk @@ -10,7 +10,7 @@ lint: enabled: - taplo@0.7.0 - ruff@0.0.265 - - yamllint@1.31.0 + - yamllint@1.32.0 - isort@5.12.0 - markdownlint@0.34.0 - oxipng@8.0.0 diff --git a/boards/bpi_picow_esp32_s3.json b/boards/bpi_picow_esp32_s3.json index 75983d845..9a20dd57f 100644 --- a/boards/bpi_picow_esp32_s3.json +++ b/boards/bpi_picow_esp32_s3.json @@ -28,8 +28,6 @@ "flash_size": "8MB", "maximum_ram_size": 327680, "maximum_size": 8388608, - "use_1200bps_touch": true, - "wait_for_upload_port": true, "require_upload_port": true, "speed": 921600 }, diff --git a/protobufs b/protobufs index c5fa71fbb..d47300965 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit c5fa71fbb68b8d4044cb6a6d72f06257ac29dd9c +Subproject commit d47300965904a8d55d109327568e19a2eb9a12c0 diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index 08ed66337..a9611d888 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -108,10 +108,12 @@ class LGFX : public lgfx::LGFX_Device lgfx::Panel_ST7789 _panel_instance; lgfx::Bus_SPI _bus_instance; lgfx::Light_PWM _light_instance; +#if HAS_TOUCHSCREEN #ifdef T_WATCH_S3 lgfx::Touch_FT5x06 _touch_instance; #else lgfx::Touch_GT911 _touch_instance; +#endif #endif public: @@ -126,13 +128,14 @@ class LGFX : public lgfx::LGFX_Device cfg.freq_write = SPI_FREQUENCY; // SPI clock for transmission (up to 80MHz, rounded to the value obtained by dividing // 80MHz by an integer) cfg.freq_read = SPI_READ_FREQUENCY; // SPI clock when receiving - cfg.spi_3wire = false; // Set to true if reception is done on the MOSI pin - cfg.use_lock = true; // Set to true to use transaction locking - cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch / - cfg.pin_sclk = ST7789_SCK; // Set SPI SCLK pin number - cfg.pin_mosi = ST7789_SDA; // Set SPI MOSI pin number - cfg.pin_miso = ST7789_MISO; // Set SPI MISO pin number (-1 = disable) - cfg.pin_dc = ST7789_RS; // Set SPI DC pin number (-1 = disable) + cfg.spi_3wire = false; + cfg.use_lock = true; // Set to true to use transaction locking + cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch / + // SPI_DMA_CH_AUTO=auto setting) + cfg.pin_sclk = ST7789_SCK; // Set SPI SCLK pin number + cfg.pin_mosi = ST7789_SDA; // Set SPI MOSI pin number + cfg.pin_miso = ST7789_MISO; // Set SPI MISO pin number (-1 = disable) + cfg.pin_dc = ST7789_RS; // Set SPI DC pin number (-1 = disable) _bus_instance.config(cfg); // applies the set value to the bus. _panel_instance.setBus(&_bus_instance); // set the bus on the panel. @@ -181,6 +184,7 @@ class LGFX : public lgfx::LGFX_Device _panel_instance.setLight(&_light_instance); // Set the backlight on the panel. } +#if HAS_TOUCHSCREEN // Configure settings for touch screen control. { auto cfg = _touch_instance.config(); @@ -210,6 +214,7 @@ class LGFX : public lgfx::LGFX_Device _touch_instance.config(cfg); _panel_instance.setTouch(&_touch_instance); } +#endif setPanel(&_panel_instance); // Sets the panel to use. } @@ -434,7 +439,7 @@ bool TFTDisplay::connect() tft.init(); #if defined(M5STACK) tft.setRotation(0); -#elif defined(T_DECK) +#elif defined(T_DECK) || defined(PICOMPUTER_S3) tft.setRotation(1); // T-Deck has the TFT in landscape #elif defined(T_WATCH_S3) tft.setRotation(2); // T-Watch S3 left-handed orientation diff --git a/src/input/kbI2cBase.cpp b/src/input/kbI2cBase.cpp index cdffbaf7e..f7fd62645 100644 --- a/src/input/kbI2cBase.cpp +++ b/src/input/kbI2cBase.cpp @@ -28,17 +28,6 @@ uint8_t read_from_14004(TwoWire *i2cBus, uint8_t reg, uint8_t *data, uint8_t len return readflag; } -// Unused for now - flagging it off -#if 0 -void write_to_14004(const TwoWire * i2cBus, uint8_t reg, uint8_t data) -{ - i2cBus->beginTransmission(CARDKB_ADDR); - i2cBus->write(reg); - i2cBus->write(data); - i2cBus->endTransmission(); // stop transmitting -} -#endif - int32_t KbI2cBase::runOnce() { if (cardkb_found.address != CARDKB_ADDR && cardkb_found.address != TDECK_KB_ADDR) { diff --git a/src/input/kbMatrixBase.cpp b/src/input/kbMatrixBase.cpp new file mode 100644 index 000000000..823bfb629 --- /dev/null +++ b/src/input/kbMatrixBase.cpp @@ -0,0 +1,131 @@ +#include "kbMatrixBase.h" +#include "configuration.h" + +#ifdef INPUTBROKER_MATRIX_TYPE + +const byte keys_cols[] = KEYS_COLS; +const byte keys_rows[] = KEYS_ROWS; + +#if INPUTBROKER_MATRIX_TYPE == 1 + +unsigned char KeyMap[3][sizeof(keys_rows)][sizeof(keys_cols)] = {{{' ', '.', 'm', 'n', 'b', 0xb6}, + {0x0d, 'l', 'k', 'j', 'h', 0xb4}, + {'p', 'o', 'i', 'u', 'y', 0xb5}, + {0x08, 'z', 'x', 'c', 'v', 0xb7}, + {'a', 's', 'd', 'f', 'g', 0x09}, + {'q', 'w', 'e', 'r', 't', 0x1a}}, + {// SHIFT + {':', ';', 'M', 'N', 'B', 0xb6}, + {0x0d, 'L', 'K', 'J', 'H', 0xb4}, + {'P', 'O', 'I', 'U', 'Y', 0xb5}, + {0x08, 'Z', 'X', 'C', 'V', 0xb7}, + {'A', 'S', 'D', 'F', 'G', 0x09}, + {'Q', 'W', 'E', 'R', 'T', 0x1a}}, + {// SHIFT-SHIFT + {'_', ',', '>', '<', '"', '{'}, + {'~', '-', '*', '&', '+', '['}, + {'0', '9', '8', '7', '6', '}'}, + {'=', '(', ')', '?', '/', ']'}, + {'!', '@', '#', '$', '%', '\\'}, + {'1', '2', '3', '4', '5', 0x1a}}}; +#endif + +KbMatrixBase::KbMatrixBase(const char *name) : concurrency::OSThread(name) +{ + this->_originName = name; +} + +int32_t KbMatrixBase::runOnce() +{ + if (!INPUTBROKER_MATRIX_TYPE) { + // Input device is not requested. + return disable(); + } + + if (firstTime) { + // This is the first time the OSThread library has called this function, so do port setup + firstTime = 0; + for (byte i = 0; i < sizeof(keys_rows); i++) { + pinMode(keys_rows[i], OUTPUT); + digitalWrite(keys_rows[i], HIGH); + } + for (byte i = 0; i < sizeof(keys_cols); i++) { + pinMode(keys_cols[i], INPUT_PULLUP); + } + } + + key = 0; + + if (INPUTBROKER_MATRIX_TYPE == 1) { + // scan for keypresses + for (byte i = 0; i < sizeof(keys_rows); i++) { + digitalWrite(keys_rows[i], LOW); + for (byte j = 0; j < sizeof(keys_cols); j++) { + if (digitalRead(keys_cols[j]) == LOW) { + key = KeyMap[shift][i][j]; + } + } + digitalWrite(keys_rows[i], HIGH); + } + // debounce + if (key != prevkey) { + if (key != 0) { + LOG_DEBUG("Key 0x%x pressed\n", key); + // reset shift now that we have a keypress + InputEvent e; + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE; + e.source = this->_originName; + switch (key) { + case 0x1b: // ESC + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL; + break; + case 0x08: // Back + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK; + e.kbchar = key; + break; + case 0xb5: // Up + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP; + break; + case 0xb6: // Down + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN; + break; + case 0xb4: // Left + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT; + e.kbchar = key; + break; + case 0xb7: // Right + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT; + e.kbchar = key; + break; + case 0x0d: // Enter + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT; + break; + case 0x00: // nopress + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE; + break; + case 0x1a: // Shift + shift++; + if (shift > 2) { + shift = 0; + } + break; + default: // all other keys + e.inputEvent = ANYKEY; + e.kbchar = key; + break; + } + if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) { + this->notifyObservers(&e); + } + } + prevkey = key; + } + + } else { + LOG_WARN("Unknown kb_model 0x%02x\n", INPUTBROKER_MATRIX_TYPE); + return disable(); + } + return 50; // Keyscan every 50msec to avoid key bounce +} + +#endif // INPUTBROKER_MATRIX_TYPE \ No newline at end of file diff --git a/src/input/kbMatrixBase.h b/src/input/kbMatrixBase.h new file mode 100644 index 000000000..8259fc07c --- /dev/null +++ b/src/input/kbMatrixBase.h @@ -0,0 +1,20 @@ +#pragma once + +#include "InputBroker.h" +#include "concurrency/OSThread.h" + +class KbMatrixBase : public Observable, public concurrency::OSThread +{ + public: + explicit KbMatrixBase(const char *name); + + protected: + virtual int32_t runOnce() override; + + private: + const char *_originName; + bool firstTime = 1; + int shift = 0; + char key = 0; + char prevkey = 0; +}; \ No newline at end of file diff --git a/src/input/kbMatrixImpl.cpp b/src/input/kbMatrixImpl.cpp new file mode 100644 index 000000000..0561b16fe --- /dev/null +++ b/src/input/kbMatrixImpl.cpp @@ -0,0 +1,20 @@ +#include "kbMatrixImpl.h" +#include "InputBroker.h" + +#ifdef INPUTBROKER_MATRIX_TYPE + +KbMatrixImpl *kbMatrixImpl; + +KbMatrixImpl::KbMatrixImpl() : KbMatrixBase("matrixKB") {} + +void KbMatrixImpl::init() +{ + if (!INPUTBROKER_MATRIX_TYPE) { + disable(); + return; + } + + inputBroker->registerSource(this); +} + +#endif // INPUTBROKER_MATRIX_TYPE \ No newline at end of file diff --git a/src/input/kbMatrixImpl.h b/src/input/kbMatrixImpl.h new file mode 100644 index 000000000..ead4a2d57 --- /dev/null +++ b/src/input/kbMatrixImpl.h @@ -0,0 +1,19 @@ +#pragma once +#include "kbMatrixBase.h" +#include "main.h" + +/** + * @brief The idea behind this class to have static methods for the event handlers. + * Check attachInterrupt() at RotaryEncoderInteruptBase.cpp + * Technically you can have as many rotary encoders hardver attached + * to your device as you wish, but you always need to have separate event + * handlers, thus you need to have a RotaryEncoderInterrupt implementation. + */ +class KbMatrixImpl : public KbMatrixBase +{ + public: + KbMatrixImpl(); + void init(); +}; + +extern KbMatrixImpl *kbMatrixImpl; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 12ee157a5..5f0eaca30 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -480,7 +480,7 @@ void setup() #endif // We do this as early as possible because this loads preferences from flash - // but we need to do this after main cpu iniot (esp32setup), because we need the random seed set + // but we need to do this after main cpu init (esp32setup), because we need the random seed set nodeDB.init(); // If we're taking on the repeater role, use flood router @@ -545,6 +545,7 @@ void setup() #else // ESP32 SPI.begin(RF95_SCK, RF95_MISO, RF95_MOSI, RF95_NSS); + LOG_WARN("SPI.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)\n", RF95_SCK, RF95_MISO, RF95_MOSI, RF95_NSS); SPI.setFrequency(4000000); #endif diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index 83bd0e325..d27d47e87 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -21,7 +21,7 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p) { if (wasSeenRecently(p)) { // Note: this will also add a recent packet record printPacket("Ignoring incoming msg, because we've already seen it", p); - if (config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER && + if (!moduleConfig.mqtt.enabled && config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER && config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT && config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) { // cancel rebroadcast of this message *if* there was already one, unless we're a router/repeater! @@ -49,10 +49,13 @@ void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas tosend->hop_limit--; // bump down the hop count - // If it is a traceRoute request, update the route that it went via me - if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag && traceRouteModule && - traceRouteModule->wantPacket(p)) { - traceRouteModule->updateRoute(tosend); + if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) { + // If it is a traceRoute request, update the route that it went via me + if (traceRouteModule && traceRouteModule->wantPacket(p)) + traceRouteModule->updateRoute(tosend); + // If it is a neighborInfo packet, update last_sent_by_id + if (neighborInfoModule && neighborInfoModule->wantPacket(p)) + neighborInfoModule->updateLastSentById(tosend); } LOG_INFO("Rebroadcasting received floodmsg to neighbors\n"); diff --git a/src/mesh/FloodingRouter.h b/src/mesh/FloodingRouter.h index 563b850a5..309035cb3 100644 --- a/src/mesh/FloodingRouter.h +++ b/src/mesh/FloodingRouter.h @@ -2,6 +2,7 @@ #include "PacketHistory.h" #include "Router.h" +#include "modules/NeighborInfoModule.h" #include "modules/TraceRouteModule.h" /** @@ -57,4 +58,4 @@ class FloodingRouter : public Router, protected PacketHistory * Look for broadcasts we need to rebroadcast */ virtual void sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c) override; -}; +}; \ No newline at end of file diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 38f4960b6..e7526505a 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -15,6 +15,7 @@ #include "error.h" #include "main.h" #include "mesh-pb-constants.h" +#include "modules/NeighborInfoModule.h" #include #include #include @@ -63,11 +64,7 @@ uint32_t error_address = 0; static uint8_t ourMacAddr[6]; -NodeDB::NodeDB() - : nodes(devicestate.node_db), numNodes(&devicestate.node_db_count), meshNodes(devicestate.node_db_lite), - numMeshNodes(&devicestate.node_db_lite_count) -{ -} +NodeDB::NodeDB() : meshNodes(devicestate.node_db_lite), numMeshNodes(&devicestate.node_db_lite_count) {} /** * Most (but not always) of the time we want to treat packets 'from' the local phone (where from == 0), as if they originated on @@ -248,6 +245,9 @@ void NodeDB::installDefaultModuleConfig() strncpy(moduleConfig.mqtt.username, default_mqtt_username, sizeof(moduleConfig.mqtt.username)); strncpy(moduleConfig.mqtt.password, default_mqtt_password, sizeof(moduleConfig.mqtt.password)); + moduleConfig.has_neighbor_info = true; + moduleConfig.neighbor_info.enabled = false; + initModuleConfigIntervals(); } @@ -271,6 +271,7 @@ void NodeDB::initModuleConfigIntervals() moduleConfig.telemetry.device_update_interval = default_broadcast_interval_secs; moduleConfig.telemetry.environment_update_interval = default_broadcast_interval_secs; moduleConfig.telemetry.air_quality_interval = default_broadcast_interval_secs; + moduleConfig.neighbor_info.update_interval = default_broadcast_interval_secs; } void NodeDB::installDefaultChannels() @@ -282,12 +283,11 @@ void NodeDB::installDefaultChannels() void NodeDB::resetNodes() { - devicestate.node_db_count = 0; - memset(devicestate.node_db, 0, sizeof(devicestate.node_db)); - devicestate.node_db_lite_count = 0; memset(devicestate.node_db_lite, 0, sizeof(devicestate.node_db_lite)); saveDeviceStateToDisk(); + if (neighborInfoModule && moduleConfig.neighbor_info.enabled) + neighborInfoModule->resetNeighbors(); } void NodeDB::installDefaultDeviceState() @@ -295,12 +295,11 @@ void NodeDB::installDefaultDeviceState() LOG_INFO("Installing default DeviceState\n"); memset(&devicestate, 0, sizeof(meshtastic_DeviceState)); - *numNodes = 0; + *numMeshNodes = 0; // init our devicestate with valid flags so protobuf writing/reading will work devicestate.has_my_node = true; devicestate.has_owner = true; - devicestate.node_db_count = 0; devicestate.node_db_lite_count = 0; devicestate.version = DEVICESTATE_CUR_VER; devicestate.receive_queue_count = 0; // Not yet implemented FIXME @@ -328,11 +327,9 @@ void NodeDB::init() int saveWhat = 0; // likewise - we always want the app requirements to come from the running appload - myNodeInfo.min_app_version = 20300; // format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20 - myNodeInfo.max_channels = MAX_NUM_CHANNELS; // tell others the max # of channels we can understand + myNodeInfo.min_app_version = 30200; // format is Mmmss (where M is 1+the numeric major number. i.e. 30200 means 2.2.00 // 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) - strncpy(myNodeInfo.firmware_version, optstr(APP_VERSION), sizeof(myNodeInfo.firmware_version)); pickNewNodeNum(); // Set our board type so we can share it with others @@ -343,19 +340,6 @@ void NodeDB::init() info->user = owner; info->has_user = true; - if (*numNodes > 0) { - LOG_DEBUG("Legacy NodeDB detected... Migrating to NodeDBLite\n"); - uint32_t readIndex = 0; - const meshtastic_NodeInfo *oldNodeInfo = nodeDB.readNextNodeInfo(readIndex); - while (oldNodeInfo != NULL) { - migrateToNodeInfoLite(oldNodeInfo); - oldNodeInfo = nodeDB.readNextNodeInfo(readIndex); - } - LOG_DEBUG("Migration complete! Clearing out legacy NodeDB...\n"); - devicestate.node_db_count = 0; - memset(devicestate.node_db, 0, sizeof(devicestate.node_db)); - } - #ifdef ARCH_ESP32 Preferences preferences; preferences.begin("meshtastic", false); @@ -365,7 +349,7 @@ void NodeDB::init() #endif resetRadioConfig(); // If bogus settings got saved, then fix them - LOG_DEBUG("region=%d, NODENUM=0x%x, dbsize=%d\n", config.lora.region, myNodeInfo.my_node_num, *numNodes); + LOG_DEBUG("region=%d, NODENUM=0x%x, dbsize=%d\n", config.lora.region, myNodeInfo.my_node_num, *numMeshNodes); if (devicestateCRC != crc32Buffer(&devicestate, sizeof(devicestate))) saveWhat |= SEGMENT_DEVICESTATE; @@ -611,14 +595,6 @@ void NodeDB::saveToDisk(int saveWhat) } } -const meshtastic_NodeInfo *NodeDB::readNextNodeInfo(uint32_t &readIndex) -{ - if (readIndex < *numNodes) - return &nodes[readIndex++]; - else - return NULL; -} - const meshtastic_NodeInfoLite *NodeDB::readNextMeshNode(uint32_t &readIndex) { if (readIndex < *numMeshNodes) @@ -796,17 +772,6 @@ uint8_t NodeDB::getMeshNodeChannel(NodeNum n) return info->channel; } -/// Find a node in our DB, return null for missing -/// NOTE: This function might be called from an ISR -meshtastic_NodeInfo *NodeDB::getNodeInfo(NodeNum n) -{ - for (int i = 0; i < *numNodes; i++) - if (nodes[i].num == n) - return &nodes[i]; - - return NULL; -} - /// Find a node in our DB, return null for missing /// NOTE: This function might be called from an ISR meshtastic_NodeInfoLite *NodeDB::getMeshNode(NodeNum n) @@ -852,57 +817,6 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n) return lite; } -void NodeDB::migrateToNodeInfoLite(const meshtastic_NodeInfo *node) -{ - meshtastic_NodeInfoLite *lite = getMeshNode(node->num); - - if (!lite) { - if ((*numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfoLite_size * 3)) { - screen->print("warning: node_db_lite full! erasing oldest entry\n"); - // look for oldest node and erase it - uint32_t oldest = UINT32_MAX; - int oldestIndex = -1; - for (int i = 0; i < *numMeshNodes; i++) { - if (meshNodes[i].last_heard < oldest) { - oldest = meshNodes[i].last_heard; - oldestIndex = i; - } - } - // Shove the remaining nodes down the chain - for (int i = oldestIndex; i < *numMeshNodes - 1; i++) { - meshNodes[i] = meshNodes[i + 1]; - } - (*numMeshNodes)--; - } - // add the node at the end - lite = &meshNodes[(*numMeshNodes)++]; - - // everything is missing except the nodenum - memset(lite, 0, sizeof(*lite)); - lite->num = node->num; - lite->snr = node->snr; - lite->last_heard = node->last_heard; - lite->channel = node->channel; - - if (node->has_position) { - lite->has_position = true; - lite->position.latitude_i = node->position.latitude_i; - lite->position.longitude_i = node->position.longitude_i; - lite->position.altitude = node->position.altitude; - lite->position.location_source = node->position.location_source; - lite->position.time = node->position.time; - } - if (node->has_user) { - lite->has_user = true; - lite->user = node->user; - } - if (node->has_device_metrics) { - lite->has_device_metrics = true; - lite->device_metrics = node->device_metrics; - } - } -} - /// Record an error that should be reported via analytics void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, const char *filename) { diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index 0816af817..ab0ec8288 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -19,7 +19,7 @@ DeviceState versions used to be defined in the .proto file but really only this #define SEGMENT_DEVICESTATE 4 #define SEGMENT_CHANNELS 8 -#define DEVICESTATE_CUR_VER 20 +#define DEVICESTATE_CUR_VER 22 #define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER extern meshtastic_DeviceState devicestate; @@ -45,9 +45,6 @@ class NodeDB // Eventually use a smarter datastructure // HashMap nodes; // Note: these two references just point into our static array we serialize to/from disk - meshtastic_NodeInfo *nodes; - pb_size_t *numNodes; - meshtastic_NodeInfoLite *meshNodes; pb_size_t *numMeshNodes; @@ -137,18 +134,6 @@ class NodeDB private: /// Find a node in our DB, create an empty NodeInfoLite if missing meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n); - void migrateToNodeInfoLite(const meshtastic_NodeInfo *node); - /// Find a node in our DB, return null for missing - meshtastic_NodeInfo *getNodeInfo(NodeNum n); - /// Allow the bluetooth layer to read our next nodeinfo record, or NULL if done reading - const meshtastic_NodeInfo *readNextNodeInfo(uint32_t &readIndex); - size_t getNumNodes() { return *numNodes; } - - meshtastic_NodeInfo *getNodeByIndex(size_t x) - { - assert(x < *numNodes); - return &nodes[x]; - } /// Notify observers of changes to the DB void notifyObservers(bool forceUpdate = false) @@ -226,10 +211,6 @@ inline uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t d /// Sometimes we will have Position objects that only have a time, so check for /// valid lat/lon -static inline bool hasValidPosition(const meshtastic_NodeInfo *n) -{ - return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0); -} static inline bool hasValidPosition(const meshtastic_NodeInfoLite *n) { return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0); diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index 6c6c70165..cd230cb1c 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -279,6 +279,10 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_remote_hardware_tag; fromRadioScratch.moduleConfig.payload_variant.remote_hardware = moduleConfig.remote_hardware; break; + case meshtastic_ModuleConfig_neighbor_info_tag: + fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_neighbor_info_tag; + fromRadioScratch.moduleConfig.payload_variant.neighbor_info = moduleConfig.neighbor_info; + break; default: LOG_ERROR("Unknown module config type %d\n", config_state); } diff --git a/src/mesh/generated/meshtastic/admin.pb.h b/src/mesh/generated/meshtastic/admin.pb.h index aa39244ff..89e1fde0c 100644 --- a/src/mesh/generated/meshtastic/admin.pb.h +++ b/src/mesh/generated/meshtastic/admin.pb.h @@ -55,6 +55,8 @@ typedef enum _meshtastic_AdminMessage_ModuleConfigType { /* TODO: REPLACE */ meshtastic_AdminMessage_ModuleConfigType_REMOTEHARDWARE_CONFIG = 8, /* TODO: REPLACE */ + meshtastic_AdminMessage_ModuleConfigType_NEIGHBORINFO_CONFIG = 9, + /* TODO: REPLACE */ meshtastic_AdminMessage_ModuleConfigType_AMBIENTLIGHTING_CONFIG = 10 } meshtastic_AdminMessage_ModuleConfigType; diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index a093c9fe2..0c4b94c86 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -124,10 +124,6 @@ typedef struct _meshtastic_DeviceState { /* My owner info */ bool has_owner; meshtastic_User owner; - /* Deprecated in 2.1.x - Old node_db. See NodeInfoLite node_db_lite */ - pb_size_t node_db_count; - meshtastic_NodeInfo node_db[80]; /* Received packets saved for delivery to the phone */ pb_size_t receive_queue_count; meshtastic_MeshPacket receive_queue[1]; @@ -178,13 +174,13 @@ extern "C" { /* Initializer values for message structs */ -#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default}, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_init_default, 0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}, 0, {meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default}} +#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_init_default, 0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}, 0, {meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default}} #define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_User_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0} #define meshtastic_PositionLite_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN} #define meshtastic_ChannelFile_init_default {0, {meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default}, 0} #define meshtastic_OEMStore_init_default {0, 0, {0, {0}}, _meshtastic_ScreenFonts_MIN, "", {0, {0}}, false, meshtastic_LocalConfig_init_default, false, meshtastic_LocalModuleConfig_init_default} #define meshtastic_NodeRemoteHardwarePin_init_default {0, false, meshtastic_RemoteHardwarePin_init_default} -#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero}, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_init_zero, 0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}, 0, {meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero}} +#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_init_zero, 0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}, 0, {meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero}} #define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0} #define meshtastic_PositionLite_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN} #define meshtastic_ChannelFile_init_zero {0, {meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero}, 0} @@ -218,7 +214,6 @@ extern "C" { #define meshtastic_NodeRemoteHardwarePin_pin_tag 2 #define meshtastic_DeviceState_my_node_tag 2 #define meshtastic_DeviceState_owner_tag 3 -#define meshtastic_DeviceState_node_db_tag 4 #define meshtastic_DeviceState_receive_queue_tag 5 #define meshtastic_DeviceState_rx_text_message_tag 7 #define meshtastic_DeviceState_version_tag 8 @@ -232,7 +227,6 @@ extern "C" { #define meshtastic_DeviceState_FIELDLIST(X, a) \ X(a, STATIC, OPTIONAL, MESSAGE, my_node, 2) \ X(a, STATIC, OPTIONAL, MESSAGE, owner, 3) \ -X(a, STATIC, REPEATED, MESSAGE, node_db, 4) \ X(a, STATIC, REPEATED, MESSAGE, receive_queue, 5) \ X(a, STATIC, OPTIONAL, MESSAGE, rx_text_message, 7) \ X(a, STATIC, SINGULAR, UINT32, version, 8) \ @@ -245,7 +239,6 @@ X(a, STATIC, REPEATED, MESSAGE, node_db_lite, 14) #define meshtastic_DeviceState_DEFAULT NULL #define meshtastic_DeviceState_my_node_MSGTYPE meshtastic_MyNodeInfo #define meshtastic_DeviceState_owner_MSGTYPE meshtastic_User -#define meshtastic_DeviceState_node_db_MSGTYPE meshtastic_NodeInfo #define meshtastic_DeviceState_receive_queue_MSGTYPE meshtastic_MeshPacket #define meshtastic_DeviceState_rx_text_message_MSGTYPE meshtastic_MeshPacket #define meshtastic_DeviceState_rx_waypoint_MSGTYPE meshtastic_MeshPacket @@ -320,7 +313,7 @@ extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg; /* Maximum encoded size of messages (where known) */ #define meshtastic_ChannelFile_size 638 -#define meshtastic_DeviceState_size 35056 +#define meshtastic_DeviceState_size 13774 #define meshtastic_NodeInfoLite_size 151 #define meshtastic_NodeRemoteHardwarePin_size 29 #define meshtastic_OEMStore_size 3154 diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 7fffe9ea7..79800f3c8 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -103,10 +103,12 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_HELTEC_WIRELESS_TRACKER = 48, /* Heltec Wireless Paper with ESP32-S3 CPU and E-Ink display */ meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER = 49, - /* LilyGo T-Deck with ESP32-S3 CPU, Keyboard, and IPS display */ + /* LilyGo T-Deck with ESP32-S3 CPU, Keyboard and IPS display */ meshtastic_HardwareModel_T_DECK = 50, /* LilyGo T-Watch S3 with ESP32-S3 CPU and IPS display */ meshtastic_HardwareModel_T_WATCH_S3 = 51, + /* Bobricius Picomputer with ESP32-S3 CPU, Keyboard and IPS display */ + meshtastic_HardwareModel_PICOMPUTER_S3 = 52, /* ------------------------------------------------------------------------------------------------------------------------------------------ Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. ------------------------------------------------------------------------------------------------------------------------------------------ */ @@ -605,60 +607,12 @@ typedef struct _meshtastic_MyNodeInfo { /* Tells the phone what our node number is, default starting value is lowbyte of macaddr, but it will be fixed if that is already in use */ uint32_t my_node_num; - /* Deprecated in 2.1.x (Source from device_metadata) - Note: This flag merely means we detected a hardware GPS in our node. - Not the same as UserPreferences.location_sharing */ - bool has_gps; - /* Deprecated in 2.1.x - The maximum number of 'software' channels that can be set on this node. */ - uint32_t max_channels; - /* Deprecated in 2.1.x (Source from device_metadata) - 0.0.5 etc... */ - char firmware_version[18]; - /* An error message we'd like to report back to the mothership through analytics. - It indicates a serious bug occurred on the device, the device coped with it, - but we still want to tell the devs about the bug. - This field will be cleared after the phone reads MyNodeInfo - (i.e. it will only be reported once) - a numeric error code to go with error message, zero means no error */ - meshtastic_CriticalErrorCode error_code; - /* A numeric error address (nonzero if available) */ - uint32_t error_address; - /* The total number of errors this node has ever encountered - (well - since the last time we discarded preferences) */ - uint32_t error_count; /* The total number of reboots this node has ever encountered (well - since the last time we discarded preferences) */ uint32_t reboot_count; - /* Deprecated in 2.1.x - Calculated bitrate of the current channel (in Bytes Per Second) */ - float bitrate; - /* Deprecated in 2.1.x - How long before we consider a message abandoned and we can clear our - caches of any messages in flight Normally quite large to handle the worst case - message delivery time, 5 minutes. - Formerly called FLOOD_EXPIRE_TIME in the device code */ - uint32_t message_timeout_msec; /* The minimum app version that can talk to this device. Phone/PC apps should compare this to their build number and if too low tell the user they must update their app */ uint32_t min_app_version; - /* Deprecated in 2.1.x (Only used on device to keep track of utilization) - 24 time windows of 1hr each with the airtime transmitted out of the device per hour. */ - pb_size_t air_period_tx_count; - uint32_t air_period_tx[8]; - /* Deprecated in 2.1.x (Only used on device to keep track of utilization) - 24 time windows of 1hr each with the airtime of valid packets for your mesh. */ - pb_size_t air_period_rx_count; - uint32_t air_period_rx[8]; - /* Deprecated in 2.1.x (Source from DeviceMetadata instead) - Is the device wifi capable? */ - bool has_wifi; - /* Deprecated in 2.1.x (Source from DeviceMetrics telemetry payloads) - Utilization for the current channel, including well formed TX, RX and malformed RX (aka noise). */ - float channel_utilization; - /* Deprecated in 2.1.x (Source from DeviceMetrics telemetry payloads) - Percent of airtime for transmission used within the last hour. */ - float air_util_tx; } meshtastic_MyNodeInfo; /* Debug output from the device. @@ -729,6 +683,12 @@ typedef struct _meshtastic_Neighbor { uint32_t node_id; /* SNR of last heard message */ float snr; + /* Reception time (in secs since 1970) of last message that was last sent by this ID. + Note: this is for local storage only and will not be sent out over the mesh. */ + uint32_t last_rx_time; + /* Broadcast interval of this neighbor (in seconds). + Note: this is for local storage only and will not be sent out over the mesh. */ + uint32_t node_broadcast_interval_secs; } meshtastic_Neighbor; /* Full info on edges for a single node */ @@ -737,6 +697,8 @@ typedef struct _meshtastic_NeighborInfo { uint32_t node_id; /* Field to pass neighbor info for the next sending cycle */ uint32_t last_sent_by_id; + /* Broadcast interval of the represented node (in seconds) */ + uint32_t node_broadcast_interval_secs; /* The list of out edges from this node */ pb_size_t neighbors_count; meshtastic_Neighbor neighbors[10]; @@ -871,7 +833,6 @@ extern "C" { #define meshtastic_MeshPacket_delayed_ENUMTYPE meshtastic_MeshPacket_Delayed -#define meshtastic_MyNodeInfo_error_code_ENUMTYPE meshtastic_CriticalErrorCode #define meshtastic_LogRecord_level_ENUMTYPE meshtastic_LogRecord_Level @@ -896,14 +857,14 @@ extern "C" { #define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN} #define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0} -#define meshtastic_MyNodeInfo_init_default {0, 0, 0, "", _meshtastic_CriticalErrorCode_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} +#define meshtastic_MyNodeInfo_init_default {0, 0, 0} #define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN} #define meshtastic_QueueStatus_init_default {0, 0, 0, 0} #define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}} #define meshtastic_ToRadio_init_default {0, {meshtastic_MeshPacket_init_default}} #define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}} -#define meshtastic_NeighborInfo_init_default {0, 0, 0, {meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default}} -#define meshtastic_Neighbor_init_default {0, 0} +#define meshtastic_NeighborInfo_init_default {0, 0, 0, 0, {meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default}} +#define meshtastic_Neighbor_init_default {0, 0, 0, 0} #define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0} #define meshtastic_Position_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0} @@ -914,14 +875,14 @@ extern "C" { #define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN} #define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0} -#define meshtastic_MyNodeInfo_init_zero {0, 0, 0, "", _meshtastic_CriticalErrorCode_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} +#define meshtastic_MyNodeInfo_init_zero {0, 0, 0} #define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN} #define meshtastic_QueueStatus_init_zero {0, 0, 0, 0} #define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}} #define meshtastic_ToRadio_init_zero {0, {meshtastic_MeshPacket_init_zero}} #define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}} -#define meshtastic_NeighborInfo_init_zero {0, 0, 0, {meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero}} -#define meshtastic_Neighbor_init_zero {0, 0} +#define meshtastic_NeighborInfo_init_zero {0, 0, 0, 0, {meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero}} +#define meshtastic_Neighbor_init_zero {0, 0, 0, 0} #define meshtastic_DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0} /* Field tags (for use in manual encoding/decoding) */ @@ -998,21 +959,8 @@ extern "C" { #define meshtastic_NodeInfo_device_metrics_tag 6 #define meshtastic_NodeInfo_channel_tag 7 #define meshtastic_MyNodeInfo_my_node_num_tag 1 -#define meshtastic_MyNodeInfo_has_gps_tag 2 -#define meshtastic_MyNodeInfo_max_channels_tag 3 -#define meshtastic_MyNodeInfo_firmware_version_tag 4 -#define meshtastic_MyNodeInfo_error_code_tag 5 -#define meshtastic_MyNodeInfo_error_address_tag 6 -#define meshtastic_MyNodeInfo_error_count_tag 7 #define meshtastic_MyNodeInfo_reboot_count_tag 8 -#define meshtastic_MyNodeInfo_bitrate_tag 9 -#define meshtastic_MyNodeInfo_message_timeout_msec_tag 10 #define meshtastic_MyNodeInfo_min_app_version_tag 11 -#define meshtastic_MyNodeInfo_air_period_tx_tag 12 -#define meshtastic_MyNodeInfo_air_period_rx_tag 13 -#define meshtastic_MyNodeInfo_has_wifi_tag 14 -#define meshtastic_MyNodeInfo_channel_utilization_tag 15 -#define meshtastic_MyNodeInfo_air_util_tx_tag 16 #define meshtastic_LogRecord_message_tag 1 #define meshtastic_LogRecord_time_tag 2 #define meshtastic_LogRecord_source_tag 3 @@ -1030,9 +978,12 @@ extern "C" { #define meshtastic_Compressed_data_tag 2 #define meshtastic_Neighbor_node_id_tag 1 #define meshtastic_Neighbor_snr_tag 2 +#define meshtastic_Neighbor_last_rx_time_tag 3 +#define meshtastic_Neighbor_node_broadcast_interval_secs_tag 4 #define meshtastic_NeighborInfo_node_id_tag 1 #define meshtastic_NeighborInfo_last_sent_by_id_tag 2 -#define meshtastic_NeighborInfo_neighbors_tag 3 +#define meshtastic_NeighborInfo_node_broadcast_interval_secs_tag 3 +#define meshtastic_NeighborInfo_neighbors_tag 4 #define meshtastic_DeviceMetadata_firmware_version_tag 1 #define meshtastic_DeviceMetadata_device_state_version_tag 2 #define meshtastic_DeviceMetadata_canShutdown_tag 3 @@ -1175,21 +1126,8 @@ X(a, STATIC, SINGULAR, UINT32, channel, 7) #define meshtastic_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, UINT32, max_channels, 3) \ -X(a, STATIC, SINGULAR, STRING, firmware_version, 4) \ -X(a, STATIC, SINGULAR, UENUM, error_code, 5) \ -X(a, STATIC, SINGULAR, UINT32, error_address, 6) \ -X(a, STATIC, SINGULAR, UINT32, error_count, 7) \ X(a, STATIC, SINGULAR, UINT32, reboot_count, 8) \ -X(a, STATIC, SINGULAR, FLOAT, bitrate, 9) \ -X(a, STATIC, SINGULAR, UINT32, message_timeout_msec, 10) \ -X(a, STATIC, SINGULAR, UINT32, min_app_version, 11) \ -X(a, STATIC, REPEATED, UINT32, air_period_tx, 12) \ -X(a, STATIC, REPEATED, UINT32, air_period_rx, 13) \ -X(a, STATIC, SINGULAR, BOOL, has_wifi, 14) \ -X(a, STATIC, SINGULAR, FLOAT, channel_utilization, 15) \ -X(a, STATIC, SINGULAR, FLOAT, air_util_tx, 16) +X(a, STATIC, SINGULAR, UINT32, min_app_version, 11) #define meshtastic_MyNodeInfo_CALLBACK NULL #define meshtastic_MyNodeInfo_DEFAULT NULL @@ -1259,14 +1197,17 @@ X(a, STATIC, SINGULAR, BYTES, data, 2) #define meshtastic_NeighborInfo_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, node_id, 1) \ X(a, STATIC, SINGULAR, UINT32, last_sent_by_id, 2) \ -X(a, STATIC, REPEATED, MESSAGE, neighbors, 3) +X(a, STATIC, SINGULAR, UINT32, node_broadcast_interval_secs, 3) \ +X(a, STATIC, REPEATED, MESSAGE, neighbors, 4) #define meshtastic_NeighborInfo_CALLBACK NULL #define meshtastic_NeighborInfo_DEFAULT NULL #define meshtastic_NeighborInfo_neighbors_MSGTYPE meshtastic_Neighbor #define meshtastic_Neighbor_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, node_id, 1) \ -X(a, STATIC, SINGULAR, FLOAT, snr, 2) +X(a, STATIC, SINGULAR, FLOAT, snr, 2) \ +X(a, STATIC, SINGULAR, FIXED32, last_rx_time, 3) \ +X(a, STATIC, SINGULAR, UINT32, node_broadcast_interval_secs, 4) #define meshtastic_Neighbor_CALLBACK NULL #define meshtastic_Neighbor_DEFAULT NULL @@ -1331,9 +1272,9 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg; #define meshtastic_LogRecord_size 81 #define meshtastic_MeshPacket_size 321 #define meshtastic_MqttClientProxyMessage_size 501 -#define meshtastic_MyNodeInfo_size 179 -#define meshtastic_NeighborInfo_size 142 -#define meshtastic_Neighbor_size 11 +#define meshtastic_MyNodeInfo_size 18 +#define meshtastic_NeighborInfo_size 258 +#define meshtastic_Neighbor_size 22 #define meshtastic_NodeInfo_size 261 #define meshtastic_Position_size 137 #define meshtastic_QueueStatus_size 23 diff --git a/src/mesh/generated/meshtastic/portnums.pb.h b/src/mesh/generated/meshtastic/portnums.pb.h index 089d7b59f..44e9df70d 100644 --- a/src/mesh/generated/meshtastic/portnums.pb.h +++ b/src/mesh/generated/meshtastic/portnums.pb.h @@ -25,73 +25,99 @@ typedef enum _meshtastic_PortNum { /* Deprecated: do not use in new code (formerly called OPAQUE) A message sent from a device outside of the mesh, in a form the mesh does not understand - NOTE: This must be 0, because it is documented in IMeshService.aidl to be so */ + NOTE: This must be 0, because it is documented in IMeshService.aidl to be so + ENCODING: binary undefined */ meshtastic_PortNum_UNKNOWN_APP = 0, /* A simple UTF-8 text message, which even the little micros in the mesh can understand and show on their screen eventually in some circumstances - even signal might send messages in this form (see below) */ + even signal might send messages in this form (see below) + ENCODING: UTF-8 Plaintext (?) */ meshtastic_PortNum_TEXT_MESSAGE_APP = 1, /* Reserved for built-in GPIO/example app. - See remote_hardware.proto/HardwareMessage for details on the message sent/received to this port number */ + See remote_hardware.proto/HardwareMessage for details on the message sent/received to this port number + ENCODING: Protobuf */ meshtastic_PortNum_REMOTE_HARDWARE_APP = 2, /* The built-in position messaging app. - Payload is a [Position](/docs/developers/protobufs/api#position) message */ + Payload is a [Position](/docs/developers/protobufs/api#position) message + ENCODING: Protobuf */ meshtastic_PortNum_POSITION_APP = 3, /* The built-in user info app. - Payload is a [User](/docs/developers/protobufs/api#user) message */ + Payload is a [User](/docs/developers/protobufs/api#user) message + ENCODING: Protobuf */ meshtastic_PortNum_NODEINFO_APP = 4, /* Protocol control packets for mesh protocol use. - Payload is a [Routing](/docs/developers/protobufs/api#routing) message */ + Payload is a [Routing](/docs/developers/protobufs/api#routing) message + ENCODING: Protobuf */ meshtastic_PortNum_ROUTING_APP = 5, /* Admin control packets. - Payload is a [AdminMessage](/docs/developers/protobufs/api#adminmessage) message */ + Payload is a [AdminMessage](/docs/developers/protobufs/api#adminmessage) message + ENCODING: Protobuf */ meshtastic_PortNum_ADMIN_APP = 6, - /* Compressed TEXT_MESSAGE payloads. */ + /* Compressed TEXT_MESSAGE payloads. + ENCODING: UTF-8 Plaintext (?) with Unishox2 Compression + NOTE: The Device Firmware converts a TEXT_MESSAGE_APP to TEXT_MESSAGE_COMPRESSED_APP if the compressed + payload is shorter. There's no need for app developers to do this themselves. Also the firmware will decompress + any incoming TEXT_MESSAGE_COMPRESSED_APP payload and convert to TEXT_MESSAGE_APP. */ meshtastic_PortNum_TEXT_MESSAGE_COMPRESSED_APP = 7, /* Waypoint payloads. - Payload is a [Waypoint](/docs/developers/protobufs/api#waypoint) message */ + Payload is a [Waypoint](/docs/developers/protobufs/api#waypoint) message + ENCODING: Protobuf */ meshtastic_PortNum_WAYPOINT_APP = 8, /* Audio Payloads. - Encapsulated codec2 packets. On 2.4 GHZ Bandwidths only for now */ + Encapsulated codec2 packets. On 2.4 GHZ Bandwidths only for now + ENCODING: codec2 audio frames + NOTE: audio frames contain a 3 byte header (0xc0 0xde 0xc2) and a one byte marker for the decompressed bitrate. + This marker comes from the 'moduleConfig.audio.bitrate' enum minus one. */ meshtastic_PortNum_AUDIO_APP = 9, /* Provides a 'ping' service that replies to any packet it receives. - Also serves as a small example module. */ + Also serves as a small example module. + ENCODING: ASCII Plaintext */ meshtastic_PortNum_REPLY_APP = 32, - /* Used for the python IP tunnel feature */ + /* Used for the python IP tunnel feature + ENCODING: IP Packet. Handled by the python API, firmware ignores this one and pases on. */ meshtastic_PortNum_IP_TUNNEL_APP = 33, /* Provides a hardware serial interface to send and receive from the Meshtastic network. Connect to the RX/TX pins of a device with 38400 8N1. Packets received from the Meshtastic network is forwarded to the RX pin while sending a packet to TX will go out to the Mesh network. Maximum packet size of 240 bytes. - Module is disabled by default can be turned on by setting SERIAL_MODULE_ENABLED = 1 in SerialPlugh.cpp. */ + Module is disabled by default can be turned on by setting SERIAL_MODULE_ENABLED = 1 in SerialPlugh.cpp. + ENCODING: binary undefined */ meshtastic_PortNum_SERIAL_APP = 64, /* STORE_FORWARD_APP (Work in Progress) - Maintained by Jm Casler (MC Hamster) : jm@casler.org */ + Maintained by Jm Casler (MC Hamster) : jm@casler.org + ENCODING: Protobuf */ meshtastic_PortNum_STORE_FORWARD_APP = 65, - /* Optional port for messages for the range test module. */ + /* Optional port for messages for the range test module. + ENCODING: ASCII Plaintext */ meshtastic_PortNum_RANGE_TEST_APP = 66, /* Provides a format to send and receive telemetry data from the Meshtastic network. - Maintained by Charles Crossan (crossan007) : crossan007@gmail.com */ + Maintained by Charles Crossan (crossan007) : crossan007@gmail.com + ENCODING: Protobuf */ meshtastic_PortNum_TELEMETRY_APP = 67, /* Experimental tools for estimating node position without a GPS Maintained by Github user a-f-G-U-C (a Meshtastic contributor) - Project files at https://github.com/a-f-G-U-C/Meshtastic-ZPS */ + Project files at https://github.com/a-f-G-U-C/Meshtastic-ZPS + ENCODING: arrays of int64 fields */ meshtastic_PortNum_ZPS_APP = 68, /* Used to let multiple instances of Linux native applications communicate as if they did using their LoRa chip. Maintained by GitHub user GUVWAF. - Project files at https://github.com/GUVWAF/Meshtasticator */ + Project files at https://github.com/GUVWAF/Meshtasticator + ENCODING: Protobuf (?) */ meshtastic_PortNum_SIMULATOR_APP = 69, /* Provides a traceroute functionality to show the route a packet towards - a certain destination would take on the mesh. */ + a certain destination would take on the mesh. + ENCODING: Protobuf */ meshtastic_PortNum_TRACEROUTE_APP = 70, - /* Aggregates edge info for the network by sending out a list of each node's neighbors */ + /* Aggregates edge info for the network by sending out a list of each node's neighbors + ENCODING: Protobuf */ meshtastic_PortNum_NEIGHBORINFO_APP = 71, /* Private applications should use portnums >= 256. To simplify initial development and testing you can use "PRIVATE_APP" in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/firmware/blob/master/bin/regen-protos.sh)) */ meshtastic_PortNum_PRIVATE_APP = 256, - /* ATAK Forwarder Module https://github.com/paulmandal/atak-forwarder */ + /* ATAK Forwarder Module https://github.com/paulmandal/atak-forwarder + ENCODING: libcotshrink */ meshtastic_PortNum_ATAK_FORWARDER = 257, /* Currently we limit port nums to no higher than this value */ meshtastic_PortNum_MAX = 511 diff --git a/src/mesh/mesh-pb-constants.h b/src/mesh/mesh-pb-constants.h index 8e22aa82b..22a80c8e3 100644 --- a/src/mesh/mesh-pb-constants.h +++ b/src/mesh/mesh-pb-constants.h @@ -16,7 +16,7 @@ #define MAX_RX_TOPHONE 32 /// max number of nodes allowed in the mesh -#define MAX_NUM_NODES (member_size(meshtastic_DeviceState, node_db) / member_size(meshtastic_DeviceState, node_db[0])) +#define MAX_NUM_NODES (member_size(meshtastic_DeviceState, node_db_lite) / member_size(meshtastic_DeviceState, node_db_lite[0])) /// Max number of channels allowed #define MAX_NUM_CHANNELS (member_size(meshtastic_ChannelFile, channels) / member_size(meshtastic_ChannelFile, channels[0])) diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index be76f62a5..283375b23 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -368,6 +368,11 @@ void AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c) moduleConfig.has_remote_hardware = true; moduleConfig.remote_hardware = c.payload_variant.remote_hardware; break; + case meshtastic_ModuleConfig_neighbor_info_tag: + LOG_INFO("Setting module config: Neighbor Info\n"); + moduleConfig.has_neighbor_info = true; + moduleConfig.neighbor_info = c.payload_variant.neighbor_info; + break; } saveChanges(SEGMENT_MODULECONFIG); @@ -503,6 +508,11 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_remote_hardware_tag; res.get_module_config_response.payload_variant.remote_hardware = moduleConfig.remote_hardware; break; + case meshtastic_AdminMessage_ModuleConfigType_NEIGHBORINFO_CONFIG: + LOG_INFO("Getting module config: Neighbor Info\n"); + res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_neighbor_info_tag; + res.get_module_config_response.payload_variant.neighbor_info = moduleConfig.neighbor_info; + break; } // NOTE: The phone app needs to know the ls_secsvalue so it can properly expect sleep behavior. @@ -663,4 +673,4 @@ AdminModule::AdminModule() : ProtobufModule("Admin", meshtastic_PortNum_ADMIN_AP { // restrict to the admin channel for rx boundChannel = Channels::adminChannel; -} +} \ No newline at end of file diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index 952e9065a..5f6a374a1 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -10,6 +10,10 @@ #include "main.h" // for cardkb_found +#ifndef INPUTBROKER_MATRIX_TYPE +#define INPUTBROKER_MATRIX_TYPE 0 +#endif + #ifdef OLED_RU #include "graphics/fonts/OLEDDisplayFontsRU.h" #endif @@ -62,7 +66,7 @@ CannedMessageModule::CannedMessageModule() if (moduleConfig.canned_message.enabled) { this->loadProtoForModule(); if ((this->splitConfiguredMessages() <= 0) && (cardkb_found.address != CARDKB_ADDR) && - (cardkb_found.address != TDECK_KB_ADDR)) { + (cardkb_found.address != TDECK_KB_ADDR) && !INPUTBROKER_MATRIX_TYPE) { LOG_INFO("CannedMessageModule: No messages are configured. Module is disabled\n"); this->runState = CANNED_MESSAGE_RUN_STATE_DISABLED; disable(); diff --git a/src/modules/Modules.cpp b/src/modules/Modules.cpp index 38fb7a4ae..9c216ff72 100644 --- a/src/modules/Modules.cpp +++ b/src/modules/Modules.cpp @@ -4,8 +4,10 @@ #include "input/TrackballInterruptImpl1.h" #include "input/UpDownInterruptImpl1.h" #include "input/cardKbI2cImpl.h" +#include "input/kbMatrixImpl.h" #include "modules/AdminModule.h" #include "modules/CannedMessageModule.h" +#include "modules/NeighborInfoModule.h" #include "modules/NodeInfoModule.h" #include "modules/PositionModule.h" #include "modules/RemoteHardwareModule.h" @@ -47,6 +49,7 @@ void setupModules() waypointModule = new WaypointModule(); textMessageModule = new TextMessageModule(); traceRouteModule = new TraceRouteModule(); + neighborInfoModule = new NeighborInfoModule(); // Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance // to a global variable. @@ -60,7 +63,11 @@ void setupModules() upDownInterruptImpl1->init(); cardKbI2cImpl = new CardKbI2cImpl(); cardKbI2cImpl->init(); -#endif +#ifdef INPUTBROKER_MATRIX_TYPE + kbMatrixImpl = new KbMatrixImpl(); + kbMatrixImpl->init(); +#endif // INPUTBROKER_MATRIX_TYPE +#endif // HAS_BUTTON #if HAS_TRACKBALL trackballInterruptImpl1 = new TrackballInterruptImpl1(); trackballInterruptImpl1->init(); diff --git a/src/modules/NeighborInfoModule.cpp b/src/modules/NeighborInfoModule.cpp new file mode 100644 index 000000000..578b41b29 --- /dev/null +++ b/src/modules/NeighborInfoModule.cpp @@ -0,0 +1,319 @@ +#include "NeighborInfoModule.h" +#include "MeshService.h" +#include "NodeDB.h" +#include "RTC.h" + +#define MAX_NUM_NEIGHBORS 10 // also defined in NeighborInfo protobuf options +NeighborInfoModule *neighborInfoModule; + +static const char *neighborInfoConfigFile = "/prefs/neighbors.proto"; + +/* +Prints a single neighbor info packet and associated neighbors +Uses LOG_DEBUG, which equates to Console.log +NOTE: For debugging only +*/ +void NeighborInfoModule::printNeighborInfo(const char *header, const meshtastic_NeighborInfo *np) +{ + LOG_DEBUG("%s NEIGHBORINFO PACKET from Node %d to Node %d (last sent by %d)\n", header, np->node_id, nodeDB.getNodeNum(), + np->last_sent_by_id); + LOG_DEBUG("----------------\n"); + LOG_DEBUG("Packet contains %d neighbors\n", np->neighbors_count); + for (int i = 0; i < np->neighbors_count; i++) { + LOG_DEBUG("Neighbor %d: node_id=%d, snr=%.2f\n", i, np->neighbors[i].node_id, np->neighbors[i].snr); + } + LOG_DEBUG("----------------\n"); +} +/* +Prints the nodeDB nodes so we can see whose nodeInfo we have +NOTE: for debugging only +*/ +void NeighborInfoModule::printNodeDBNodes(const char *header) +{ + int num_nodes = nodeDB.getNumMeshNodes(); + LOG_DEBUG("%s NODEDB SELECTION from Node %d:\n", header, nodeDB.getNodeNum()); + LOG_DEBUG("----------------\n"); + LOG_DEBUG("DB contains %d nodes\n", num_nodes); + for (int i = 0; i < num_nodes; i++) { + meshtastic_NodeInfoLite *dbEntry = nodeDB.getMeshNodeByIndex(i); + LOG_DEBUG(" Node %d: node_id=%d, snr=%.2f\n", i, dbEntry->num, dbEntry->snr); + } + LOG_DEBUG("----------------\n"); +} + +/* +Prints the nodeDB neighbors +NOTE: for debugging only +*/ +void NeighborInfoModule::printNodeDBNeighbors(const char *header) +{ + int num_neighbors = getNumNeighbors(); + LOG_DEBUG("%s NODEDB SELECTION from Node %d:\n", header, nodeDB.getNodeNum()); + LOG_DEBUG("----------------\n"); + LOG_DEBUG("DB contains %d neighbors\n", num_neighbors); + for (int i = 0; i < num_neighbors; i++) { + meshtastic_Neighbor *dbEntry = getNeighborByIndex(i); + LOG_DEBUG(" Node %d: node_id=%d, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr); + } + LOG_DEBUG("----------------\n"); +} + +/* +Prints the nodeDB with selectors for the neighbors we've chosen to send (inefficiently) +Uses LOG_DEBUG, which equates to Console.log +NOTE: For debugging only +*/ +void NeighborInfoModule::printNodeDBSelection(const char *header, const meshtastic_NeighborInfo *np) +{ + int num_neighbors = getNumNeighbors(); + LOG_DEBUG("%s NODEDB SELECTION from Node %d:\n", header, nodeDB.getNodeNum()); + LOG_DEBUG("----------------\n"); + LOG_DEBUG("Selected %d neighbors of %d DB neighbors\n", np->neighbors_count, num_neighbors); + for (int i = 0; i < num_neighbors; i++) { + meshtastic_Neighbor *dbEntry = getNeighborByIndex(i); + bool chosen = false; + for (int j = 0; j < np->neighbors_count; j++) { + if (np->neighbors[j].node_id == dbEntry->node_id) { + chosen = true; + } + } + if (!chosen) { + LOG_DEBUG(" Node %d: neighbor=%d, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr); + } else { + LOG_DEBUG("---> Node %d: neighbor=%d, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr); + } + } + LOG_DEBUG("----------------\n"); +} + +/* Send our initial owner announcement 35 seconds after we start (to give network time to setup) */ +NeighborInfoModule::NeighborInfoModule() + : neighbors(neighborState.neighbors), numNeighbors(&neighborState.neighbors_count), + ProtobufModule("neighborinfo", meshtastic_PortNum_NEIGHBORINFO_APP, &meshtastic_NeighborInfo_msg), concurrency::OSThread( + "NeighborInfoModule") +{ + ourPortNum = meshtastic_PortNum_NEIGHBORINFO_APP; + + if (moduleConfig.neighbor_info.enabled) { + this->loadProtoForModule(); + setIntervalFromNow(35 * 1000); + } else { + LOG_DEBUG("NeighborInfoModule is disabled\n"); + disable(); + } +} + +/* +Allocate a zeroed neighbor info packet +*/ +meshtastic_NeighborInfo *NeighborInfoModule::allocateNeighborInfoPacket() +{ + meshtastic_NeighborInfo *neighborInfo = (meshtastic_NeighborInfo *)malloc(sizeof(meshtastic_NeighborInfo)); + memset(neighborInfo, 0, sizeof(meshtastic_NeighborInfo)); + return neighborInfo; +} + +/* +Collect neighbor info from the nodeDB's history, capping at a maximum number of entries and max time +Assumes that the neighborInfo packet has been allocated +@returns the number of entries collected +*/ +uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo) +{ + int my_node_id = nodeDB.getNodeNum(); + neighborInfo->node_id = my_node_id; + neighborInfo->last_sent_by_id = my_node_id; + neighborInfo->node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval; + + int num_neighbors = cleanUpNeighbors(); + + for (int i = 0; i < num_neighbors; i++) { + meshtastic_Neighbor *dbEntry = getNeighborByIndex(i); + if ((neighborInfo->neighbors_count < MAX_NUM_NEIGHBORS) && (dbEntry->node_id != my_node_id)) { + neighborInfo->neighbors[neighborInfo->neighbors_count].node_id = dbEntry->node_id; + neighborInfo->neighbors[neighborInfo->neighbors_count].snr = dbEntry->snr; + // Note: we don't set the last_rx_time and node_broadcast_intervals_secs here, because we don't want to send this over + // the mesh + neighborInfo->neighbors_count++; + } + } + printNodeDBNodes("DBSTATE"); + printNodeDBNeighbors("NEIGHBORS"); + printNodeDBSelection("COLLECTED", neighborInfo); + return neighborInfo->neighbors_count; +} + +/* +Remove neighbors from the database that we haven't heard from in a while +@returns new number of neighbors +*/ +size_t NeighborInfoModule::cleanUpNeighbors() +{ + uint32_t now = getTime(); + int num_neighbors = getNumNeighbors(); + NodeNum my_node_id = nodeDB.getNodeNum(); + + // Find neighbors to remove + std::vector indices_to_remove; + for (int i = 0; i < num_neighbors; i++) { + meshtastic_Neighbor *dbEntry = getNeighborByIndex(i); + // We will remove a neighbor if we haven't heard from them in twice the broadcast interval + if ((now - dbEntry->last_rx_time > dbEntry->node_broadcast_interval_secs * 2) && (dbEntry->node_id != my_node_id)) { + indices_to_remove.push_back(i); + } + } + + // Update the neighbor list + for (int i = 0; i < indices_to_remove.size(); i++) { + int index = indices_to_remove[i]; + LOG_DEBUG("Removing neighbor with node ID 0x%x\n", neighbors[index].node_id); + for (int j = index; j < num_neighbors - 1; j++) { + neighbors[j] = neighbors[j + 1]; + } + (*numNeighbors)--; + } + + // Save the neighbor list if we removed any neighbors + if (indices_to_remove.size() > 0) { + saveProtoForModule(); + } + + return *numNeighbors; +} + +/* Send neighbor info to the mesh */ +void NeighborInfoModule::sendNeighborInfo(NodeNum dest, bool wantReplies) +{ + meshtastic_NeighborInfo *neighborInfo = allocateNeighborInfoPacket(); + collectNeighborInfo(neighborInfo); + meshtastic_MeshPacket *p = allocDataProtobuf(*neighborInfo); + // send regardless of whether or not we have neighbors in our DB, + // because we want to get neighbors for the next cycle + p->to = dest; + p->decoded.want_response = wantReplies; + printNeighborInfo("SENDING", neighborInfo); + service.sendToMesh(p, RX_SRC_LOCAL, true); +} + +/* +Encompasses the full construction and sending packet to mesh +Will be used for broadcast. +*/ +int32_t NeighborInfoModule::runOnce() +{ + bool requestReplies = false; + sendNeighborInfo(NODENUM_BROADCAST, requestReplies); + return getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_broadcast_interval_secs); +} + +/* +Collect a recieved neighbor info packet from another node +Pass it to an upper client; do not persist this data on the mesh +*/ +bool NeighborInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *np) +{ + printNeighborInfo("RECEIVED", np); + updateNeighbors(mp, np); + // Allow others to handle this packet + return false; +} + +/* +Copy the content of a current NeighborInfo packet into a new one and update the last_sent_by_id to our NodeNum +*/ +void NeighborInfoModule::updateLastSentById(meshtastic_MeshPacket *p) +{ + auto &incoming = p->decoded; + meshtastic_NeighborInfo scratch; + meshtastic_NeighborInfo *updated = NULL; + memset(&scratch, 0, sizeof(scratch)); + pb_decode_from_bytes(incoming.payload.bytes, incoming.payload.size, &meshtastic_NeighborInfo_msg, &scratch); + updated = &scratch; + + updated->last_sent_by_id = nodeDB.getNodeNum(); + + // Set updated last_sent_by_id to the payload of the to be flooded packet + p->decoded.payload.size = + pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), &meshtastic_NeighborInfo_msg, updated); +} + +void NeighborInfoModule::resetNeighbors() +{ + *numNeighbors = 0; + neighborState.neighbors_count = 0; + memset(neighborState.neighbors, 0, sizeof(neighborState.neighbors)); + saveProtoForModule(); +} + +void NeighborInfoModule::updateNeighbors(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *np) +{ + // The last sent ID will be 0 if the packet is from the phone, which we don't count as + // an edge. So we assume that if it's zero, then this packet is from our node. + if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp.from) { + getOrCreateNeighbor(mp.from, np->last_sent_by_id, np->node_broadcast_interval_secs, mp.rx_snr); + } +} + +meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSender, NodeNum n, + uint32_t node_broadcast_interval_secs, int snr) +{ + // our node and the phone are the same node (not neighbors) + if (n == 0) { + n = nodeDB.getNodeNum(); + } + // look for one in the existing list + for (int i = 0; i < (*numNeighbors); i++) { + meshtastic_Neighbor *nbr = &neighbors[i]; + if (nbr->node_id == n) { + // if found, update it + nbr->snr = snr; + nbr->last_rx_time = getTime(); + // Only if this is the original sender, the broadcast interval corresponds to it + if (originalSender == n) + nbr->node_broadcast_interval_secs = node_broadcast_interval_secs; + saveProtoForModule(); // Save the updated neighbor + return nbr; + } + } + // otherwise, allocate one and assign data to it + // TODO: max memory for the database should take neighbors into account, but currently doesn't + if (*numNeighbors < MAX_NUM_NODES) { + (*numNeighbors)++; + } + meshtastic_Neighbor *new_nbr = &neighbors[((*numNeighbors) - 1)]; + new_nbr->node_id = n; + new_nbr->snr = snr; + new_nbr->last_rx_time = getTime(); + // Only if this is the original sender, the broadcast interval corresponds to it + if (originalSender == n) + new_nbr->node_broadcast_interval_secs = node_broadcast_interval_secs; + saveProtoForModule(); // Save the new neighbor + return new_nbr; +} + +void NeighborInfoModule::loadProtoForModule() +{ + if (!nodeDB.loadProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, sizeof(meshtastic_NeighborInfo), + &meshtastic_NeighborInfo_msg, &neighborState)) { + neighborState = meshtastic_NeighborInfo_init_zero; + } +} + +/** + * @brief Save the module config to file. + * + * @return true On success. + * @return false On error. + */ +bool NeighborInfoModule::saveProtoForModule() +{ + bool okay = true; + +#ifdef FS + FS.mkdir("/prefs"); +#endif + + okay &= nodeDB.saveProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, &meshtastic_NeighborInfo_msg, &neighborState); + + return okay; +} \ No newline at end of file diff --git a/src/modules/NeighborInfoModule.h b/src/modules/NeighborInfoModule.h new file mode 100644 index 000000000..a2729f16e --- /dev/null +++ b/src/modules/NeighborInfoModule.h @@ -0,0 +1,84 @@ +#pragma once +#include "ProtobufModule.h" + +/* + * Neighborinfo module for sending info on each node's 0-hop neighbors to the mesh + */ +class NeighborInfoModule : public ProtobufModule, private concurrency::OSThread +{ + meshtastic_Neighbor *neighbors; + pb_size_t *numNeighbors; + + public: + /* + * Expose the constructor + */ + NeighborInfoModule(); + + /* Reset neighbor info after clearing nodeDB*/ + void resetNeighbors(); + + bool saveProtoForModule(); + + // Let FloodingRouter call updateLastSentById upon rebroadcasting a NeighborInfo packet + friend class FloodingRouter; + + protected: + // Note: this holds our local info. + meshtastic_NeighborInfo neighborState; + + /* + * 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 meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *nb) override; + + /* + * Collect neighbor info from the nodeDB's history, capping at a maximum number of entries and max time + * @return the number of entries collected + */ + uint32_t collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo); + + /* + Remove neighbors from the database that we haven't heard from in a while + @returns new number of neighbors + */ + size_t cleanUpNeighbors(); + + /* Allocate a new NeighborInfo packet */ + meshtastic_NeighborInfo *allocateNeighborInfoPacket(); + + // Find a neighbor in our DB, create an empty neighbor if missing + meshtastic_Neighbor *getOrCreateNeighbor(NodeNum originalSender, NodeNum n, uint32_t node_broadcast_interval_secs, int snr); + + /* + * Send info on our node's neighbors into the mesh + */ + void sendNeighborInfo(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false); + + size_t getNumNeighbors() { return *numNeighbors; } + + meshtastic_Neighbor *getNeighborByIndex(size_t x) + { + assert(x < *numNeighbors); + return &neighbors[x]; + } + + /* update neighbors with subpacket sniffed from network */ + void updateNeighbors(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *np); + + /* update a NeighborInfo packet with our NodeNum as last_sent_by_id */ + void updateLastSentById(meshtastic_MeshPacket *p); + + void loadProtoForModule(); + + /* Does our periodic broadcast */ + int32_t runOnce() override; + + /* These are for debugging only */ + void printNeighborInfo(const char *header, const meshtastic_NeighborInfo *np); + void printNodeDBNodes(const char *header); + void printNodeDBNeighbors(const char *header); + void printNodeDBSelection(const char *header, const meshtastic_NeighborInfo *np); +}; +extern NeighborInfoModule *neighborInfoModule; \ No newline at end of file diff --git a/src/mqtt/JSONValue.cpp b/src/mqtt/JSONValue.cpp index 1990a13b6..a229666a9 100644 --- a/src/mqtt/JSONValue.cpp +++ b/src/mqtt/JSONValue.cpp @@ -363,6 +363,19 @@ JSONValue::JSONValue(int m_integer_value) number_value = (double)m_integer_value; } +/** + * Basic constructor for creating a JSON Value of type Number + * + * @access public + * + * @param uint m_integer_value The number to use as the value + */ +JSONValue::JSONValue(uint m_integer_value) +{ + type = JSONType_Number; + number_value = (double)m_integer_value; +} + /** * Basic constructor for creating a JSON Value of type Array * @@ -874,4 +887,4 @@ std::string JSONValue::Indent(size_t depth) depth ? --depth : 0; std::string indentStr(depth * indent_step, ' '); return indentStr; -} +} \ No newline at end of file diff --git a/src/mqtt/JSONValue.h b/src/mqtt/JSONValue.h index 9b231e93f..3a50a831a 100644 --- a/src/mqtt/JSONValue.h +++ b/src/mqtt/JSONValue.h @@ -45,6 +45,7 @@ class JSONValue JSONValue(bool m_bool_value); JSONValue(double m_number_value); JSONValue(int m_integer_value); + JSONValue(uint m_integer_value); JSONValue(const JSONArray &m_array_value); JSONValue(const JSONObject &m_object_value); JSONValue(const JSONValue &m_source); @@ -91,4 +92,4 @@ class JSONValue }; }; -#endif +#endif \ No newline at end of file diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index a7a6b662b..4e5a84477 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -541,7 +541,7 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp) if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Telemetry_msg, &scratch)) { decoded = &scratch; if (decoded->which_variant == meshtastic_Telemetry_device_metrics_tag) { - msgPayload["battery_level"] = new JSONValue((int)decoded->variant.device_metrics.battery_level); + msgPayload["battery_level"] = new JSONValue((uint)decoded->variant.device_metrics.battery_level); msgPayload["voltage"] = new JSONValue(decoded->variant.device_metrics.voltage); msgPayload["channel_utilization"] = new JSONValue(decoded->variant.device_metrics.channel_utilization); msgPayload["air_util_tx"] = new JSONValue(decoded->variant.device_metrics.air_util_tx); @@ -588,10 +588,10 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp) if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Position_msg, &scratch)) { decoded = &scratch; if ((int)decoded->time) { - msgPayload["time"] = new JSONValue((int)decoded->time); + msgPayload["time"] = new JSONValue((uint)decoded->time); } if ((int)decoded->timestamp) { - msgPayload["timestamp"] = new JSONValue((int)decoded->timestamp); + msgPayload["timestamp"] = new JSONValue((uint)decoded->timestamp); } msgPayload["latitude_i"] = new JSONValue((int)decoded->latitude_i); msgPayload["longitude_i"] = new JSONValue((int)decoded->longitude_i); @@ -599,13 +599,13 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp) msgPayload["altitude"] = new JSONValue((int)decoded->altitude); } if ((int)decoded->ground_speed) { - msgPayload["ground_speed"] = new JSONValue((int)decoded->ground_speed); + msgPayload["ground_speed"] = new JSONValue((uint)decoded->ground_speed); } if (int(decoded->ground_track)) { - msgPayload["ground_track"] = new JSONValue((int)decoded->ground_track); + msgPayload["ground_track"] = new JSONValue((uint)decoded->ground_track); } if (int(decoded->sats_in_view)) { - msgPayload["sats_in_view"] = new JSONValue((int)decoded->sats_in_view); + msgPayload["sats_in_view"] = new JSONValue((uint)decoded->sats_in_view); } if ((int)decoded->PDOP) { msgPayload["PDOP"] = new JSONValue((int)decoded->PDOP); @@ -632,11 +632,11 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp) memset(&scratch, 0, sizeof(scratch)); if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Waypoint_msg, &scratch)) { decoded = &scratch; - msgPayload["id"] = new JSONValue((int)decoded->id); + msgPayload["id"] = new JSONValue((uint)decoded->id); msgPayload["name"] = new JSONValue(decoded->name); msgPayload["description"] = new JSONValue(decoded->description); - msgPayload["expire"] = new JSONValue((int)decoded->expire); - msgPayload["locked_to"] = new JSONValue((int)decoded->locked_to); + msgPayload["expire"] = new JSONValue((uint)decoded->expire); + msgPayload["locked_to"] = new JSONValue((uint)decoded->locked_to); msgPayload["latitude_i"] = new JSONValue((int)decoded->latitude_i); msgPayload["longitude_i"] = new JSONValue((int)decoded->longitude_i); jsonObj["payload"] = new JSONValue(msgPayload); @@ -646,16 +646,34 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp) }; break; } + case meshtastic_PortNum_NEIGHBORINFO_APP: { + msgType = "neighborinfo"; + meshtastic_NeighborInfo scratch; + meshtastic_NeighborInfo *decoded = NULL; + if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag) { + memset(&scratch, 0, sizeof(scratch)); + if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_NeighborInfo_msg, + &scratch)) { + decoded = &scratch; + msgPayload["node_id"] = new JSONValue((uint)decoded->node_id); + msgPayload["neighbors_count"] = new JSONValue(decoded->neighbors_count); + msgPayload["neighbors"] = new JSONValue(decoded->neighbors); + } else { + LOG_ERROR("Error decoding protobuf for neighborinfo message!\n"); + } + }; + break; + } // add more packet types here if needed default: break; } - jsonObj["id"] = new JSONValue((int)mp->id); - jsonObj["timestamp"] = new JSONValue((int)mp->rx_time); - jsonObj["to"] = new JSONValue((int)mp->to); - jsonObj["from"] = new JSONValue((int)mp->from); - jsonObj["channel"] = new JSONValue((int)mp->channel); + jsonObj["id"] = new JSONValue((uint)mp->id); + jsonObj["timestamp"] = new JSONValue((uint)mp->rx_time); + jsonObj["to"] = new JSONValue((uint)mp->to); + jsonObj["from"] = new JSONValue((uint)mp->from); + jsonObj["channel"] = new JSONValue((uint)mp->channel); jsonObj["type"] = new JSONValue(msgType.c_str()); jsonObj["sender"] = new JSONValue(owner.id); diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h index 6e80b50e6..8f71bace6 100644 --- a/src/platform/esp32/architecture.h +++ b/src/platform/esp32/architecture.h @@ -117,6 +117,8 @@ #define HW_VENDOR meshtastic_HardwareModel_NANO_G1_EXPLORER #elif defined(BETAFPV_900_TX_NANO) #define HW_VENDOR meshtastic_HardwareModel_BETAFPV_900_NANO_TX +#elif defined(PICOMPUTER_S3) +#define HW_VENDOR meshtastic_HardwareModel_PICOMPUTER_S3 #endif // diff --git a/src/shutdown.h b/src/shutdown.h index d9077151c..90fb19d0c 100644 --- a/src/shutdown.h +++ b/src/shutdown.h @@ -16,7 +16,7 @@ void powerCommandsCheck() rp2040.reboot(); #else rebootAtMsec = -1; - LOG_WARN("FIXME implement reboot for this platform. Skipping for now.\n"); + LOG_WARN("FIXME implement reboot for this platform. Note that some settings require a restart to be applied.\n"); #endif } diff --git a/variants/heltec_v3/variant.h b/variants/heltec_v3/variant.h index aedfbe677..cb26ba0a3 100644 --- a/variants/heltec_v3/variant.h +++ b/variants/heltec_v3/variant.h @@ -4,6 +4,10 @@ #define I2C_SDA SDA_OLED // I2C pins for this board #define I2C_SCL SCL_OLED +// Enable secondary bus for external periherals +#define I2C_SDA1 SDA +#define I2C_SCL1 SCL + #define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost #define BUTTON_PIN 0 diff --git a/variants/heltec_wireless_paper/variant.h b/variants/heltec_wireless_paper/variant.h index 84c16c884..eb67ea816 100644 --- a/variants/heltec_wireless_paper/variant.h +++ b/variants/heltec_wireless_paper/variant.h @@ -1,5 +1,9 @@ #define LED_PIN 18 +// Enable bus for external periherals +#define I2C_SDA SDA +#define I2C_SCL SCL + #define USE_EINK /* * eink display pins diff --git a/variants/heltec_wsl_v3/variant.h b/variants/heltec_wsl_v3/variant.h index ec5796313..40671e4fb 100644 --- a/variants/heltec_wsl_v3/variant.h +++ b/variants/heltec_wsl_v3/variant.h @@ -1,5 +1,5 @@ -#define I2C_SCL 47 -#define I2C_SDA 48 +#define I2C_SCL SCL +#define I2C_SDA SDA #define LED_PIN LED diff --git a/variants/picomputer-s3/pins_arduino.h b/variants/picomputer-s3/pins_arduino.h new file mode 100644 index 000000000..c84601b1e --- /dev/null +++ b/variants/picomputer-s3/pins_arduino.h @@ -0,0 +1,30 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +#define EXTERNAL_NUM_INTERRUPTS 46 +#define NUM_DIGITAL_PINS 48 +#define NUM_ANALOG_INPUTS 20 + +#define analogInputToDigitalPin(p) (((p) < 20) ? (analogChannelToDigitalPin(p)) : -1) +#define digitalPinToInterrupt(p) (((p) < 48) ? (p) : -1) +#define digitalPinHasPWM(p) (p < 46) + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// The default Wire will be mapped to PMU and RTC +static const uint8_t SDA = 8; +static const uint8_t SCL = 9; + +// Default SPI +static const uint8_t MISO = 39; +static const uint8_t SCK = 21; +static const uint8_t MOSI = 38; +static const uint8_t SS = 40; + +#endif /* Pins_Arduino_h */ \ No newline at end of file diff --git a/variants/picomputer-s3/platformio.ini b/variants/picomputer-s3/platformio.ini new file mode 100644 index 000000000..e7093697a --- /dev/null +++ b/variants/picomputer-s3/platformio.ini @@ -0,0 +1,17 @@ +[env:picomputer-s3] +extends = esp32s3_base +board = bpi_picow_esp32_s3 +board_level = extra +;OpenOCD flash method +;upload_protocol = esp-builtin +;Normal method +upload_protocol = esptool + +build_flags = + ${esp32s3_base.build_flags} + -DPICOMPUTER_S3 + -I variants/picomputer-s3 + +lib_deps = + ${esp32s3_base.lib_deps} + lovyan03/LovyanGFX@^1.1.8 diff --git a/variants/picomputer-s3/variant.h b/variants/picomputer-s3/variant.h new file mode 100644 index 000000000..0f416efe0 --- /dev/null +++ b/variants/picomputer-s3/variant.h @@ -0,0 +1,54 @@ +#undef GPS_RX_PIN +#undef GPS_TX_PIN + +#define BUTTON_PIN 0 + +#define PIN_BUZZER 43 + +#define HAS_GPS 0 +#define HAS_WIRE 0 + +#define USE_RF95 // RFM95/SX127x + +#define RF95_SCK SCK // 21 +#define RF95_MISO MISO // 39 +#define RF95_MOSI MOSI // 38 +#define RF95_NSS SS // 40 +#define LORA_RESET RADIOLIB_NC + +// per SX1276_Receive_Interrupt/utilities.h +#define LORA_DIO0 10 +#define LORA_DIO1 RADIOLIB_NC +#define LORA_DIO2 RADIOLIB_NC + +// Default SPI1 will be mapped to the display +#define ST7789_SDA 4 +#define ST7789_SCK 3 +#define ST7789_CS 6 +#define ST7789_RS 1 +#define ST7789_BL 5 + +#define ST7789_RESET -1 +#define ST7789_MISO -1 +#define ST7789_BUSY -1 +#define ST7789_SPI_HOST SPI3_HOST +#define ST7789_BACKLIGHT_EN 5 +#define SPI_FREQUENCY 40000000 +#define SPI_READ_FREQUENCY 16000000 +#define TFT_HEIGHT 320 +#define TFT_WIDTH 240 +#define TFT_OFFSET_X 0 +#define TFT_OFFSET_Y 0 +#define SCREEN_ROTATE +#define SCREEN_TRANSITION_FRAMERATE 5 + +#define INPUTBROKER_MATRIX_TYPE 1 + +#define KEYS_COLS \ + { \ + 44, 47, 17, 15, 13, 41 \ + } +#define KEYS_ROWS \ + { \ + 12, 16, 42, 18, 14, 7 \ + } diff --git a/version.properties b/version.properties index 1c45cbf4b..3909d8d04 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 -minor = 1 -build = 23 +minor = 2 +build = 0