From 92225eb6c3ac60a12995432a4bfac0ee3641f093 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Fri, 13 Dec 2024 11:48:27 -0600 Subject: [PATCH 01/14] DIO3_TCXO_VOLTAGE in config.yaml can now take an exact voltage (#5558) --- src/mesh/LR11x0Interface.cpp | 4 +++- src/mesh/SX126xInterface.cpp | 4 +--- src/platform/portduino/PortduinoGlue.cpp | 5 ++++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/mesh/LR11x0Interface.cpp b/src/mesh/LR11x0Interface.cpp index 30ef8f9af..ce4f912ba 100644 --- a/src/mesh/LR11x0Interface.cpp +++ b/src/mesh/LR11x0Interface.cpp @@ -48,8 +48,10 @@ template bool LR11x0Interface::init() digitalWrite(LR11X0_POWER_EN, HIGH); #endif +#if ARCH_PORTDUINO + float tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000; // FIXME: correct logic to default to not using TCXO if no voltage is specified for LR11x0_DIO3_TCXO_VOLTAGE -#if !defined(LR11X0_DIO3_TCXO_VOLTAGE) +#elif !defined(LR11X0_DIO3_TCXO_VOLTAGE) float tcxoVoltage = 0; // "TCXO reference voltage to be set on DIO3. Defaults to 1.6 V, set to 0 to skip." per // https://github.com/jgromes/RadioLib/blob/690a050ebb46e6097c5d00c371e961c1caa3b52e/src/modules/LR11x0/LR11x0.h#L471C26-L471C104 diff --git a/src/mesh/SX126xInterface.cpp b/src/mesh/SX126xInterface.cpp index 002fb41ca..ed0267c5b 100644 --- a/src/mesh/SX126xInterface.cpp +++ b/src/mesh/SX126xInterface.cpp @@ -50,9 +50,7 @@ template bool SX126xInterface::init() #endif #if ARCH_PORTDUINO - float tcxoVoltage = 0; - if (settingsMap[dio3_tcxo_voltage]) - tcxoVoltage = 1.8; + float tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000; if (settingsMap[sx126x_ant_sw] != RADIOLIB_NC) { digitalWrite(settingsMap[sx126x_ant_sw], HIGH); pinMode(settingsMap[sx126x_ant_sw], OUTPUT); diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index 50b5c5b7b..fa0c8c502 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -365,7 +365,10 @@ bool loadConfig(const char *configPath) settingsMap[use_sx1268] = true; } settingsMap[dio2_as_rf_switch] = yamlConfig["Lora"]["DIO2_AS_RF_SWITCH"].as(false); - settingsMap[dio3_tcxo_voltage] = yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as(false); + settingsMap[dio3_tcxo_voltage] = yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as(0) * 1000; + if (settingsMap[dio3_tcxo_voltage] == 0 && yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as(false)) { + settingsMap[dio3_tcxo_voltage] = 1800; // default millivolts for "true" + } settingsMap[cs] = yamlConfig["Lora"]["CS"].as(RADIOLIB_NC); settingsMap[irq] = yamlConfig["Lora"]["IRQ"].as(RADIOLIB_NC); settingsMap[busy] = yamlConfig["Lora"]["Busy"].as(RADIOLIB_NC); From 332dbaf57376cf93befaf8cf35e244e4ef9bf982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Sat, 14 Dec 2024 10:59:15 +0100 Subject: [PATCH 02/14] Support TLORA_V3.0 (#5563) - Support TLORA_V3.0. Update of the legendary 2.1_1.6.1 with solar charger, TCXO and IPEX connector. - 'extra' some short-lived EOL intermediate boards in that range. If possible use T3S3 instead of all of these! - update trunk to latest version --- .trunk/trunk.yaml | 25 +++++++++++----------- platformio.ini | 1 + variants/tlora_v2_1_16_tcxo/platformio.ini | 1 + variants/tlora_v2_1_18/platformio.ini | 1 + variants/tlora_v3_3_0_tcxo/platformio.ini | 11 ++++++++++ 5 files changed, 27 insertions(+), 12 deletions(-) create mode 100644 variants/tlora_v3_3_0_tcxo/platformio.ini diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 743f4214d..f2393592c 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -4,31 +4,32 @@ cli: plugins: sources: - id: trunk - ref: v1.6.4 + ref: v1.6.6 uri: https://github.com/trunk-io/plugins lint: enabled: - - trufflehog@3.83.6 + - prettier@3.4.2 + - trufflehog@3.86.1 - yamllint@1.35.1 - - bandit@1.7.10 - - checkov@3.2.287 + - bandit@1.8.0 + - checkov@3.2.334 - terrascan@1.19.9 - - trivy@0.56.2 + - trivy@0.58.0 #- trufflehog@3.63.2-rc0 - taplo@0.9.3 - - ruff@0.7.3 + - ruff@0.8.3 - isort@5.13.2 - - markdownlint@0.42.0 - - oxipng@9.1.2 + - markdownlint@0.43.0 + - oxipng@9.1.3 - svgo@3.3.2 - actionlint@1.7.4 - flake8@7.1.1 - - hadolint@2.12.0 + - hadolint@2.12.1-beta - shfmt@3.6.0 - shellcheck@0.10.0 - black@24.10.0 - git-diff-check - - gitleaks@8.21.1 + - gitleaks@8.21.2 - clang-format@16.0.3 #- prettier@3.3.3 ignore: @@ -39,11 +40,11 @@ runtimes: enabled: - python@3.10.8 - go@1.21.0 - - node@18.12.1 + - node@18.20.5 actions: disabled: - trunk-announce enabled: - trunk-fmt-pre-commit - trunk-check-pre-push - - trunk-upgrade-available \ No newline at end of file + - trunk-upgrade-available diff --git a/platformio.ini b/platformio.ini index cc08b33a0..08d21665f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,6 +16,7 @@ default_envs = tbeam ;default_envs = tlora-v2 ;default_envs = tlora-v2-1-1_6 ;default_envs = tlora-v2-1-1_6-tcxo +;default_envs = tlora-v3-3-0-tcxo ;default_envs = tlora-t3s3-v1 ;default_envs = t-echo ;default_envs = canaryone diff --git a/variants/tlora_v2_1_16_tcxo/platformio.ini b/variants/tlora_v2_1_16_tcxo/platformio.ini index e54c1a920..538fd81b0 100644 --- a/variants/tlora_v2_1_16_tcxo/platformio.ini +++ b/variants/tlora_v2_1_16_tcxo/platformio.ini @@ -1,5 +1,6 @@ [env:tlora-v2-1-1_6-tcxo] extends = esp32_base +board_level = extra board = ttgo-lora32-v21 build_flags = ${esp32_base.build_flags} diff --git a/variants/tlora_v2_1_18/platformio.ini b/variants/tlora_v2_1_18/platformio.ini index 36d6a3157..48a001ced 100644 --- a/variants/tlora_v2_1_18/platformio.ini +++ b/variants/tlora_v2_1_18/platformio.ini @@ -1,5 +1,6 @@ [env:tlora-v2-1-1_8] extends = esp32_base +board_level = extra board = ttgo-lora32-v21 build_flags = diff --git a/variants/tlora_v3_3_0_tcxo/platformio.ini b/variants/tlora_v3_3_0_tcxo/platformio.ini new file mode 100644 index 000000000..4066d64b0 --- /dev/null +++ b/variants/tlora_v3_3_0_tcxo/platformio.ini @@ -0,0 +1,11 @@ +[env:tlora-v3-3-0-tcxo] +extends = esp32_base +board = ttgo-lora32-v21 +board_level = extra +build_flags = + ${esp32_base.build_flags} + -D TLORA_V2_1_16 + -I variants/tlora_v2_1_16 + -D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. + -D LORA_TCXO_GPIO=12 + -D BUTTON_PIN=0 \ No newline at end of file From c3f89a6db8feeb304b0969841db2c4ffba53a9c9 Mon Sep 17 00:00:00 2001 From: Mark Trevor Birss Date: Sat, 14 Dec 2024 12:46:35 +0200 Subject: [PATCH 03/14] Create OpenWRT-One-mikroBUS-LR-IOT-CLICK.yaml (#5564) --- bin/config.d/OpenWRT-One-mikroBUS-LR-IOT-CLICK.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 bin/config.d/OpenWRT-One-mikroBUS-LR-IOT-CLICK.yaml diff --git a/bin/config.d/OpenWRT-One-mikroBUS-LR-IOT-CLICK.yaml b/bin/config.d/OpenWRT-One-mikroBUS-LR-IOT-CLICK.yaml new file mode 100644 index 000000000..ca5b27ebc --- /dev/null +++ b/bin/config.d/OpenWRT-One-mikroBUS-LR-IOT-CLICK.yaml @@ -0,0 +1,9 @@ +## https://www.mikroe.com/lr-iot-click +Lora: + Module: lr1110 # OpenWRT ONE mikroBUS with LR-IOT-CLICK +# CS: 25 + IRQ: 10 + Busy: 12 +# Reset: 2 + spidev: spidev2.0 + DIO3_TCXO_VOLTAGE: 1.6 From 44cf6d388ebd9d284e490c150cc568f3199fba0f Mon Sep 17 00:00:00 2001 From: GUVWAF <78759985+GUVWAF@users.noreply.github.com> Date: Sat, 14 Dec 2024 11:55:32 +0100 Subject: [PATCH 04/14] Portduino: fix setting hwId via argument (#5565) --- src/platform/portduino/PortduinoGlue.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index fa0c8c502..750cc1630 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -87,7 +87,8 @@ void getMacAddr(uint8_t *dmac) if (strlen(optionMac) >= 12) { MAC_from_string(optionMac, dmac); } else { - uint32_t hwId = sscanf(optionMac, "%u", &hwId); + uint32_t hwId; + sscanf(optionMac, "%u", &hwId); dmac[0] = 0x80; dmac[1] = 0; dmac[2] = hwId >> 24; @@ -532,4 +533,4 @@ bool MAC_from_string(std::string mac_str, uint8_t *dmac) } else { return false; } -} +} \ No newline at end of file From 4a1239f811a803b2103cf99d27c9db7dd2f2efc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Perdig=C3=A3o=20Gon=C3=A7alves?= Date: Sun, 15 Dec 2024 00:43:41 +0000 Subject: [PATCH 05/14] Add new endpoint to retrieve node info (#5557) --- src/mesh/http/ContentHandler.cpp | 74 ++++++++++++++++++++++++++++++++ src/mesh/http/ContentHandler.h | 1 + 2 files changed, 75 insertions(+) diff --git a/src/mesh/http/ContentHandler.cpp b/src/mesh/http/ContentHandler.cpp index 64f7164c9..2b88702ed 100644 --- a/src/mesh/http/ContentHandler.cpp +++ b/src/mesh/http/ContentHandler.cpp @@ -93,6 +93,7 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer) ResourceNode *nodeJsonScanNetworks = new ResourceNode("/json/scanNetworks", "GET", &handleScanNetworks); ResourceNode *nodeJsonBlinkLED = new ResourceNode("/json/blink", "POST", &handleBlinkLED); ResourceNode *nodeJsonReport = new ResourceNode("/json/report", "GET", &handleReport); + ResourceNode *nodeJsonNodes = new ResourceNode("/json/nodes", "GET", &handleNodes); ResourceNode *nodeJsonFsBrowseStatic = new ResourceNode("/json/fs/browse/static", "GET", &handleFsBrowseStatic); ResourceNode *nodeJsonDelete = new ResourceNode("/json/fs/delete/static", "DELETE", &handleFsDeleteStatic); @@ -112,6 +113,7 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer) secureServer->registerNode(nodeJsonFsBrowseStatic); secureServer->registerNode(nodeJsonDelete); secureServer->registerNode(nodeJsonReport); + secureServer->registerNode(nodeJsonNodes); // secureServer->registerNode(nodeUpdateFs); // secureServer->registerNode(nodeDeleteFs); secureServer->registerNode(nodeAdmin); @@ -680,6 +682,78 @@ void handleReport(HTTPRequest *req, HTTPResponse *res) delete value; } +void handleNodes(HTTPRequest *req, HTTPResponse *res) +{ + ResourceParameters *params = req->getParams(); + std::string content; + + if (!params->getQueryParameter("content", content)) { + content = "json"; + } + + if (content == "json") { + res->setHeader("Content-Type", "application/json"); + res->setHeader("Access-Control-Allow-Origin", "*"); + res->setHeader("Access-Control-Allow-Methods", "GET"); + } else { + res->setHeader("Content-Type", "text/html"); + res->println("
");
+    }
+
+    JSONArray nodesArray;
+
+    uint32_t readIndex = 0;
+    const meshtastic_NodeInfoLite *tempNodeInfo = nodeDB->readNextMeshNode(readIndex);
+    while (tempNodeInfo != NULL) {
+        if (tempNodeInfo->has_user) {
+            JSONObject node;
+
+            char id[16];
+            snprintf(id, sizeof(id), "!%08x", tempNodeInfo->num);
+
+            node["id"] = new JSONValue(id);
+            node["snr"] = new JSONValue(tempNodeInfo->snr);
+            node["via_mqtt"] = new JSONValue(BoolToString(tempNodeInfo->via_mqtt));
+            node["last_heard"] = new JSONValue((int)tempNodeInfo->last_heard);
+            node["position"] = new JSONValue();
+
+            if (nodeDB->hasValidPosition(tempNodeInfo)) {
+                JSONObject position;
+                position["latitude"] = new JSONValue((float)tempNodeInfo->position.latitude_i * 1e-7);
+                position["longitude"] = new JSONValue((float)tempNodeInfo->position.longitude_i * 1e-7);
+                position["altitude"] = new JSONValue((int)tempNodeInfo->position.altitude);
+                node["position"] = new JSONValue(position);
+            }
+
+            JSONObject user;
+            node["long_name"] = new JSONValue(tempNodeInfo->user.long_name);
+            node["short_name"] = new JSONValue(tempNodeInfo->user.short_name);
+            char macStr[18];
+            snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X", tempNodeInfo->user.macaddr[0],
+                     tempNodeInfo->user.macaddr[1], tempNodeInfo->user.macaddr[2], tempNodeInfo->user.macaddr[3],
+                     tempNodeInfo->user.macaddr[4], tempNodeInfo->user.macaddr[5]);
+            node["mac_address"] = new JSONValue(macStr);
+            node["hw_model"] = new JSONValue(tempNodeInfo->user.hw_model);
+
+            nodesArray.push_back(new JSONValue(node));
+        }
+        tempNodeInfo = nodeDB->readNextMeshNode(readIndex);
+    }
+
+    // collect data to inner data object
+    JSONObject jsonObjInner;
+    jsonObjInner["nodes"] = new JSONValue(nodesArray);
+
+    // create json output structure
+    JSONObject jsonObjOuter;
+    jsonObjOuter["data"] = new JSONValue(jsonObjInner);
+    jsonObjOuter["status"] = new JSONValue("ok");
+    // serialize and write it to the stream
+    JSONValue *value = new JSONValue(jsonObjOuter);
+    res->print(value->Stringify().c_str());
+    delete value;
+}
+
 /*
     This supports the Apple Captive Network Assistant (CNA) Portal
 */
diff --git a/src/mesh/http/ContentHandler.h b/src/mesh/http/ContentHandler.h
index 987e3ffef..2066a6d57 100644
--- a/src/mesh/http/ContentHandler.h
+++ b/src/mesh/http/ContentHandler.h
@@ -13,6 +13,7 @@ void handleFsBrowseStatic(HTTPRequest *req, HTTPResponse *res);
 void handleFsDeleteStatic(HTTPRequest *req, HTTPResponse *res);
 void handleBlinkLED(HTTPRequest *req, HTTPResponse *res);
 void handleReport(HTTPRequest *req, HTTPResponse *res);
+void handleNodes(HTTPRequest *req, HTTPResponse *res);
 void handleUpdateFs(HTTPRequest *req, HTTPResponse *res);
 void handleDeleteFsContent(HTTPRequest *req, HTTPResponse *res);
 void handleFs(HTTPRequest *req, HTTPResponse *res);

From 6d8be13266c9e07caa42dc7a3420a9424c1aca89 Mon Sep 17 00:00:00 2001
From: Austin 
Date: Sat, 14 Dec 2024 20:19:19 -0500
Subject: [PATCH 06/14] Portduino-buildroot: Remove pkg-config optional libs
 (#5573)

---
 variants/portduino-buildroot/platformio.ini | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/variants/portduino-buildroot/platformio.ini b/variants/portduino-buildroot/platformio.ini
index 3c8f21537..683a3cecc 100644
--- a/variants/portduino-buildroot/platformio.ini
+++ b/variants/portduino-buildroot/platformio.ini
@@ -1,11 +1,9 @@
 [env:buildroot]
 extends = portduino_base
-; The pkg-config commands below optionally add link flags.
-; the || : is just a "or run the null command" to avoid returning an error code
+; Optional libraries should be appended to `PLATFORMIO_BUILD_FLAGS`
+; environment variable in the buildroot environment.
 build_flags = ${portduino_base.build_flags} -O0 -I variants/portduino-buildroot
   -std=c++17
-  !pkg-config --libs libulfius --silence-errors || :
-  !pkg-config --libs openssl --silence-errors || :
 board = buildroot
 lib_deps = ${portduino_base.lib_deps}
 build_src_filter = ${portduino_base.build_src_filter}

From 4024bfdeeb57f8c213577d576a08ff63bd835e83 Mon Sep 17 00:00:00 2001
From: "Aaron.Lee" <32860565+Heltec-Aaron-Lee@users.noreply.github.com>
Date: Sun, 15 Dec 2024 10:20:29 +0800
Subject: [PATCH 07/14] Add screen detection function (#5533)

---
 src/mesh/NodeDB.cpp | 77 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp
index 6ad1a953d..201304395 100644
--- a/src/mesh/NodeDB.cpp
+++ b/src/mesh/NodeDB.cpp
@@ -70,6 +70,76 @@ static unsigned char userprefs_admin_key_1[] = USERPREFS_USE_ADMIN_KEY_1;
 static unsigned char userprefs_admin_key_2[] = USERPREFS_USE_ADMIN_KEY_2;
 #endif
 
+#ifdef HELTEC_MESH_NODE_T114
+
+uint32_t read8(uint8_t bits, uint8_t dummy,uint8_t cs,uint8_t sck,uint8_t mosi,uint8_t dc,uint8_t rst)
+{
+    uint32_t ret = 0;
+    uint8_t SDAPIN = mosi;
+    pinMode(SDAPIN, INPUT_PULLUP);
+    digitalWrite(dc, HIGH);
+    for (int i = 0; i < dummy; i++) {  //any dummy clocks
+        digitalWrite(sck, HIGH);
+        delay(1);
+        digitalWrite(sck, LOW);
+        delay(1);
+    }
+    for (int i = 0; i < bits; i++) {  // read results
+        ret <<= 1;
+        delay(1);
+        if (digitalRead(SDAPIN)) ret |= 1;;
+        digitalWrite(sck, HIGH);
+        delay(1);
+        digitalWrite(sck, LOW);
+    }
+    return ret;
+}
+
+void write9(uint8_t val, uint8_t dc_val,uint8_t cs,uint8_t sck,uint8_t mosi,uint8_t dc,uint8_t rst)
+{
+    pinMode(mosi, OUTPUT);
+    digitalWrite(dc, dc_val);
+    for (int i = 0; i < 8; i++) {   //send command
+        digitalWrite(mosi, (val & 0x80) != 0);
+        delay(1);
+        digitalWrite(sck, HIGH);
+        delay(1);
+        digitalWrite(sck, LOW);
+        val <<= 1;
+    }
+}
+
+uint32_t readwrite8(uint8_t cmd, uint8_t bits, uint8_t dummy,uint8_t cs,uint8_t sck,uint8_t mosi,uint8_t dc,uint8_t rst)
+{
+    digitalWrite(cs, LOW);
+    write9(cmd, 0,cs,sck,mosi,dc,rst);
+    uint32_t ret = read8(bits, dummy,cs,sck,mosi,dc,rst);
+    digitalWrite(cs, HIGH);
+    return ret;
+}
+
+uint32_t get_st7789_id(uint8_t cs,uint8_t sck,uint8_t mosi,uint8_t dc,uint8_t rst)
+{
+    pinMode(cs, OUTPUT);
+    digitalWrite(cs, HIGH);
+    pinMode(cs, OUTPUT);
+    pinMode(sck, OUTPUT);
+    pinMode(mosi, OUTPUT);
+    pinMode(dc, OUTPUT);
+    pinMode(rst, OUTPUT);
+    digitalWrite(rst, LOW);   //Hardware Reset
+    delay(10);
+    digitalWrite(rst, HIGH);
+    delay(10);
+
+    uint32_t ID = 0;
+    ID = readwrite8(0x04, 24, 1,cs,sck,mosi,dc,rst);
+    ID = readwrite8(0x04, 24, 1,cs,sck,mosi,dc,rst);  //ST7789 needs twice
+    return ID;
+}
+
+#endif
+
 bool meshtastic_DeviceState_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field)
 {
     if (ostream) {
@@ -489,6 +559,13 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
 #if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7789_CS) ||       \
     defined(HX8357_CS) || defined(USE_ST7789)
     bool hasScreen = true;
+#ifdef HELTEC_MESH_NODE_T114
+    uint32_t st7789_id=get_st7789_id(ST7789_NSS,ST7789_SCK,ST7789_SDA,ST7789_RS,ST7789_RESET);
+    if(st7789_id==0xFFFFFF)
+    {
+        hasScreen = false;
+    }
+#endif
 #elif ARCH_PORTDUINO
     bool hasScreen = false;
     if (settingsMap[displayPanel])

From ea72abff22e416b4c813d7ba6810c38d0c2755a4 Mon Sep 17 00:00:00 2001
From: Ben Meadors 
Date: Sat, 14 Dec 2024 20:21:19 -0600
Subject: [PATCH 08/14] Posthumous tronk

---
 src/mesh/NodeDB.cpp | 33 +++++++++++++++++----------------
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp
index 201304395..7fe5bd656 100644
--- a/src/mesh/NodeDB.cpp
+++ b/src/mesh/NodeDB.cpp
@@ -72,22 +72,24 @@ static unsigned char userprefs_admin_key_2[] = USERPREFS_USE_ADMIN_KEY_2;
 
 #ifdef HELTEC_MESH_NODE_T114
 
-uint32_t read8(uint8_t bits, uint8_t dummy,uint8_t cs,uint8_t sck,uint8_t mosi,uint8_t dc,uint8_t rst)
+uint32_t read8(uint8_t bits, uint8_t dummy, uint8_t cs, uint8_t sck, uint8_t mosi, uint8_t dc, uint8_t rst)
 {
     uint32_t ret = 0;
     uint8_t SDAPIN = mosi;
     pinMode(SDAPIN, INPUT_PULLUP);
     digitalWrite(dc, HIGH);
-    for (int i = 0; i < dummy; i++) {  //any dummy clocks
+    for (int i = 0; i < dummy; i++) { // any dummy clocks
         digitalWrite(sck, HIGH);
         delay(1);
         digitalWrite(sck, LOW);
         delay(1);
     }
-    for (int i = 0; i < bits; i++) {  // read results
+    for (int i = 0; i < bits; i++) { // read results
         ret <<= 1;
         delay(1);
-        if (digitalRead(SDAPIN)) ret |= 1;;
+        if (digitalRead(SDAPIN))
+            ret |= 1;
+        ;
         digitalWrite(sck, HIGH);
         delay(1);
         digitalWrite(sck, LOW);
@@ -95,11 +97,11 @@ uint32_t read8(uint8_t bits, uint8_t dummy,uint8_t cs,uint8_t sck,uint8_t mosi,u
     return ret;
 }
 
-void write9(uint8_t val, uint8_t dc_val,uint8_t cs,uint8_t sck,uint8_t mosi,uint8_t dc,uint8_t rst)
+void write9(uint8_t val, uint8_t dc_val, uint8_t cs, uint8_t sck, uint8_t mosi, uint8_t dc, uint8_t rst)
 {
     pinMode(mosi, OUTPUT);
     digitalWrite(dc, dc_val);
-    for (int i = 0; i < 8; i++) {   //send command
+    for (int i = 0; i < 8; i++) { // send command
         digitalWrite(mosi, (val & 0x80) != 0);
         delay(1);
         digitalWrite(sck, HIGH);
@@ -109,16 +111,16 @@ void write9(uint8_t val, uint8_t dc_val,uint8_t cs,uint8_t sck,uint8_t mosi,uint
     }
 }
 
-uint32_t readwrite8(uint8_t cmd, uint8_t bits, uint8_t dummy,uint8_t cs,uint8_t sck,uint8_t mosi,uint8_t dc,uint8_t rst)
+uint32_t readwrite8(uint8_t cmd, uint8_t bits, uint8_t dummy, uint8_t cs, uint8_t sck, uint8_t mosi, uint8_t dc, uint8_t rst)
 {
     digitalWrite(cs, LOW);
-    write9(cmd, 0,cs,sck,mosi,dc,rst);
-    uint32_t ret = read8(bits, dummy,cs,sck,mosi,dc,rst);
+    write9(cmd, 0, cs, sck, mosi, dc, rst);
+    uint32_t ret = read8(bits, dummy, cs, sck, mosi, dc, rst);
     digitalWrite(cs, HIGH);
     return ret;
 }
 
-uint32_t get_st7789_id(uint8_t cs,uint8_t sck,uint8_t mosi,uint8_t dc,uint8_t rst)
+uint32_t get_st7789_id(uint8_t cs, uint8_t sck, uint8_t mosi, uint8_t dc, uint8_t rst)
 {
     pinMode(cs, OUTPUT);
     digitalWrite(cs, HIGH);
@@ -127,14 +129,14 @@ uint32_t get_st7789_id(uint8_t cs,uint8_t sck,uint8_t mosi,uint8_t dc,uint8_t rs
     pinMode(mosi, OUTPUT);
     pinMode(dc, OUTPUT);
     pinMode(rst, OUTPUT);
-    digitalWrite(rst, LOW);   //Hardware Reset
+    digitalWrite(rst, LOW); // Hardware Reset
     delay(10);
     digitalWrite(rst, HIGH);
     delay(10);
 
     uint32_t ID = 0;
-    ID = readwrite8(0x04, 24, 1,cs,sck,mosi,dc,rst);
-    ID = readwrite8(0x04, 24, 1,cs,sck,mosi,dc,rst);  //ST7789 needs twice
+    ID = readwrite8(0x04, 24, 1, cs, sck, mosi, dc, rst);
+    ID = readwrite8(0x04, 24, 1, cs, sck, mosi, dc, rst); // ST7789 needs twice
     return ID;
 }
 
@@ -560,9 +562,8 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
     defined(HX8357_CS) || defined(USE_ST7789)
     bool hasScreen = true;
 #ifdef HELTEC_MESH_NODE_T114
-    uint32_t st7789_id=get_st7789_id(ST7789_NSS,ST7789_SCK,ST7789_SDA,ST7789_RS,ST7789_RESET);
-    if(st7789_id==0xFFFFFF)
-    {
+    uint32_t st7789_id = get_st7789_id(ST7789_NSS, ST7789_SCK, ST7789_SDA, ST7789_RS, ST7789_RESET);
+    if (st7789_id == 0xFFFFFF) {
         hasScreen = false;
     }
 #endif

From 547a57256d7be033a598c713eaf4b41615a67daa Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Sun, 15 Dec 2024 05:23:15 -0600
Subject: [PATCH 09/14] [create-pull-request] automated change (#5577)

Co-authored-by: fifieldt <1287116+fifieldt@users.noreply.github.com>
---
 protobufs                                    | 2 +-
 src/mesh/generated/meshtastic/mesh.pb.h      | 5 +++++
 src/mesh/generated/meshtastic/telemetry.pb.h | 8 +++++---
 3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/protobufs b/protobufs
index 00c9c9932..4a4e81951 160000
--- a/protobufs
+++ b/protobufs
@@ -1 +1 @@
-Subproject commit 00c9c9932ea50c14cdc44d497d2672a0031641ce
+Subproject commit 4a4e81951d64821a96a5131e50d2b44e5356372e
diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h
index da439c375..2c5213cff 100644
--- a/src/mesh/generated/meshtastic/mesh.pb.h
+++ b/src/mesh/generated/meshtastic/mesh.pb.h
@@ -220,6 +220,9 @@ typedef enum _meshtastic_HardwareModel {
  the same frame format.
  Runs on linux, see https://github.com/Jorropo/routastic */
     meshtastic_HardwareModel_ROUTASTIC = 85,
+    /* Mesh-Tab, esp32 based
+ https://github.com/valzzu/Mesh-Tab */
+    meshtastic_HardwareModel_MESH_TAB = 86,
     /* ------------------------------------------------------------------------------------------------------------------------------------------
  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.
  ------------------------------------------------------------------------------------------------------------------------------------------ */
@@ -414,6 +417,8 @@ typedef enum _meshtastic_MeshPacket_Priority {
     meshtastic_MeshPacket_Priority_RESPONSE = 80,
     /* Higher priority for specific message types (portnums) to distinguish between other reliable packets. */
     meshtastic_MeshPacket_Priority_HIGH = 100,
+    /* Higher priority alert message used for critical alerts which take priority over other reliable packets. */
+    meshtastic_MeshPacket_Priority_ALERT = 110,
     /* Ack/naks are sent with very high priority to ensure that retransmission
  stops as soon as possible */
     meshtastic_MeshPacket_Priority_ACK = 120,
diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h
index 874eef60f..a6102e07d 100644
--- a/src/mesh/generated/meshtastic/telemetry.pb.h
+++ b/src/mesh/generated/meshtastic/telemetry.pb.h
@@ -79,7 +79,9 @@ typedef enum _meshtastic_TelemetrySensorType {
     /* SCD40/SCD41 CO2, humidity, temperature sensor */
     meshtastic_TelemetrySensorType_SCD4X = 32,
     /* ClimateGuard RadSens, radiation, Geiger-Muller Tube */
-    meshtastic_TelemetrySensorType_RADSENS = 33
+    meshtastic_TelemetrySensorType_RADSENS = 33,
+    /* High accuracy current and voltage */
+    meshtastic_TelemetrySensorType_INA226 = 34
 } meshtastic_TelemetrySensorType;
 
 /* Struct definitions */
@@ -304,8 +306,8 @@ extern "C" {
 
 /* Helper constants for enums */
 #define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
-#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_RADSENS
-#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_RADSENS+1))
+#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_INA226
+#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_INA226+1))
 
 
 

From 56002155c68c90121692b6e327c44aeb96fd2904 Mon Sep 17 00:00:00 2001
From: Tom Fifield 
Date: Sun, 15 Dec 2024 23:23:27 +1100
Subject: [PATCH 10/14] Based default Node Names on NodeNum, rather than MAC
 address (#5576)

Presently we base the default long name (Meshtastic XXXX) and short
names (XXXX) on a node's MAC address. This works fine, unless you
have a node with no bluetooth, like Portduino.

Our logic for node numbers is also based on MAC address. However,
it has the added feature that it will create a random node number
if the Mac address is no good. The name is always "Meshtastic 0001".

This change switches node names (long and short) to instead rely
on the node number for defaults. For nodes with mac addresses,
there should be no user-visible change. For nodes without, they'll
now have a name other than "Meshtastic 0001".

Fixes https://github.com/meshtastic/firmware/issues/5370

Co-authored-by: Ben Meadors 
---
 src/mesh/NodeDB.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp
index 7fe5bd656..2af85e4f5 100644
--- a/src/mesh/NodeDB.cpp
+++ b/src/mesh/NodeDB.cpp
@@ -852,12 +852,12 @@ void NodeDB::installDefaultDeviceState()
 #ifdef USERPREFS_CONFIG_OWNER_LONG_NAME
     snprintf(owner.long_name, sizeof(owner.long_name), USERPREFS_CONFIG_OWNER_LONG_NAME);
 #else
-    snprintf(owner.long_name, sizeof(owner.long_name), "Meshtastic %02x%02x", ourMacAddr[4], ourMacAddr[5]);
+    snprintf(owner.long_name, sizeof(owner.long_name), "Meshtastic %04x", getNodeNum() & 0x0ffff);
 #endif
 #ifdef USERPREFS_CONFIG_OWNER_SHORT_NAME
     snprintf(owner.short_name, sizeof(owner.short_name), USERPREFS_CONFIG_OWNER_SHORT_NAME);
 #else
-    snprintf(owner.short_name, sizeof(owner.short_name), "%02x%02x", ourMacAddr[4], ourMacAddr[5]);
+    snprintf(owner.short_name, sizeof(owner.short_name), "%04x", getNodeNum() & 0x0ffff);
 #endif
     snprintf(owner.id, sizeof(owner.id), "!%08x", getNodeNum()); // Default node ID now based on nodenum
     memcpy(owner.macaddr, ourMacAddr, sizeof(owner.macaddr));

From 2d45afafe56091b757b7e23839564770ae1dfc1a Mon Sep 17 00:00:00 2001
From: Ben Meadors 
Date: Sun, 15 Dec 2024 06:52:45 -0600
Subject: [PATCH 11/14] Try docker authentication with command-line instead

---
 .github/workflows/build_native.yml | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/.github/workflows/build_native.yml b/.github/workflows/build_native.yml
index d4b0c8d58..d9591e72c 100644
--- a/.github/workflows/build_native.yml
+++ b/.github/workflows/build_native.yml
@@ -53,20 +53,18 @@ jobs:
 
       - name: Docker login
         if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
-        uses: docker/login-action@v3
-        continue-on-error: true # FIXME: Failing docker login auth
-        with:
-          username: meshtastic
-          password: ${{ secrets.DOCKER_FIRMWARE_TOKEN }}
+        run: |
+          echo ${{ secrets.DOCKER_FIRMWARE_TOKEN }} | docker login -u meshtastic --password-stdin
+        continue-on-error: true
 
       - name: Docker setup
         if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
-        continue-on-error: true # FIXME: Failing docker login auth
+        continue-on-error: true
         uses: docker/setup-buildx-action@v3
 
       - name: Docker build and push tagged versions
         if: ${{ github.event_name == 'workflow_dispatch' }}
-        continue-on-error: true # FIXME: Failing docker login auth
+        continue-on-error: true
         uses: docker/build-push-action@v6
         with:
           context: .
@@ -76,7 +74,7 @@ jobs:
 
       - name: Docker build and push
         if: ${{ github.ref == 'refs/heads/master' && github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
-        continue-on-error: true # FIXME: Failing docker login auth
+        continue-on-error: true
         uses: docker/build-push-action@v6
         with:
           context: .

From 020e9102a8277a40cbbbb260cbca9582be14fa87 Mon Sep 17 00:00:00 2001
From: Tom Fifield 
Date: Mon, 16 Dec 2024 00:14:48 +1100
Subject: [PATCH 12/14] Define BUTTON_PIN as -1 for RP2040-lora (#5574)

The previous approach of undef'ing meant that it was impossible
for users to change the button pin in the apps.

Fixes https://github.com/meshtastic/firmware/issues/5566
---
 variants/rp2040-lora/variant.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/variants/rp2040-lora/variant.h b/variants/rp2040-lora/variant.h
index f1826605f..92b067457 100644
--- a/variants/rp2040-lora/variant.h
+++ b/variants/rp2040-lora/variant.h
@@ -15,7 +15,7 @@
 // rxd = 9
 
 #define EXT_NOTIFY_OUT 22
-#undef BUTTON_PIN // Pin 17 used for antenna switching via DIO4
+#define BUTTON_PIN -1 // Pin 17 used for antenna switching via DIO4
 
 #define LED_PIN PIN_LED
 
@@ -57,4 +57,4 @@
 #define SX126X_DIO2_AS_RF_SWITCH // Antenna switch CTRL
 #define SX126X_RXEN LORA_DIO4    // Antenna switch !CTRL via GPIO17
 // #define SX126X_DIO3_TCXO_VOLTAGE 1.8
-#endif
\ No newline at end of file
+#endif

From 09c082fd004423374f1decd880ee7a448d6e3999 Mon Sep 17 00:00:00 2001
From: Ben Meadors 
Date: Sun, 15 Dec 2024 09:59:14 -0600
Subject: [PATCH 13/14] Fix omission of AQ metrics (#5584)

---
 src/modules/Telemetry/AirQualityTelemetry.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/modules/Telemetry/AirQualityTelemetry.cpp b/src/modules/Telemetry/AirQualityTelemetry.cpp
index 362d60252..6a8077f03 100644
--- a/src/modules/Telemetry/AirQualityTelemetry.cpp
+++ b/src/modules/Telemetry/AirQualityTelemetry.cpp
@@ -113,12 +113,18 @@ bool AirQualityTelemetryModule::getAirQualityTelemetry(meshtastic_Telemetry *m)
 
     m->time = getTime();
     m->which_variant = meshtastic_Telemetry_air_quality_metrics_tag;
+    m->variant.air_quality_metrics.has_pm10_standard = true;
     m->variant.air_quality_metrics.pm10_standard = data.pm10_standard;
+    m->variant.air_quality_metrics.has_pm25_standard = true;
     m->variant.air_quality_metrics.pm25_standard = data.pm25_standard;
+    m->variant.air_quality_metrics.has_pm100_standard = true;
     m->variant.air_quality_metrics.pm100_standard = data.pm100_standard;
 
+    m->variant.air_quality_metrics.has_pm10_environmental = true;
     m->variant.air_quality_metrics.pm10_environmental = data.pm10_env;
+    m->variant.air_quality_metrics.has_pm25_environmental = true;
     m->variant.air_quality_metrics.pm25_environmental = data.pm25_env;
+    m->variant.air_quality_metrics.has_pm100_environmental = true;
     m->variant.air_quality_metrics.pm100_environmental = data.pm100_env;
 
     LOG_INFO("Send: PM1.0(Standard)=%i, PM2.5(Standard)=%i, PM10.0(Standard)=%i", m->variant.air_quality_metrics.pm10_standard,

From 69d01a8088d89753cea18502e44777764774d765 Mon Sep 17 00:00:00 2001
From: GUVWAF <78759985+GUVWAF@users.noreply.github.com>
Date: Sun, 15 Dec 2024 20:11:13 +0100
Subject: [PATCH 14/14] StoreForward: (tapback) reply support (#5585)

---
 src/modules/StoreForwardModule.cpp | 12 +++++++++---
 src/modules/StoreForwardModule.h   |  3 +++
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/src/modules/StoreForwardModule.cpp b/src/modules/StoreForwardModule.cpp
index 4cf06f5d2..0a6e1b4c4 100644
--- a/src/modules/StoreForwardModule.cpp
+++ b/src/modules/StoreForwardModule.cpp
@@ -73,11 +73,11 @@ void StoreForwardModule::populatePSRAM()
     LOG_DEBUG("Before PSRAM init: heap %d/%d PSRAM %d/%d", memGet.getFreeHeap(), memGet.getHeapSize(), memGet.getFreePsram(),
               memGet.getPsramSize());
 
-    /* Use a maximum of 2/3 the available PSRAM unless otherwise specified.
+    /* Use a maximum of 3/4 the available PSRAM unless otherwise specified.
         Note: This needs to be done after every thing that would use PSRAM
     */
     uint32_t numberOfPackets =
-        (this->records ? this->records : (((memGet.getFreePsram() / 3) * 2) / sizeof(PacketHistoryStruct)));
+        (this->records ? this->records : (((memGet.getFreePsram() / 4) * 3) / sizeof(PacketHistoryStruct)));
     this->records = numberOfPackets;
 #if defined(ARCH_ESP32)
     this->packetHistory = static_cast(ps_calloc(numberOfPackets, sizeof(PacketHistoryStruct)));
@@ -198,6 +198,9 @@ void StoreForwardModule::historyAdd(const meshtastic_MeshPacket &mp)
     this->packetHistory[this->packetHistoryTotalCount].to = mp.to;
     this->packetHistory[this->packetHistoryTotalCount].channel = mp.channel;
     this->packetHistory[this->packetHistoryTotalCount].from = getFrom(&mp);
+    this->packetHistory[this->packetHistoryTotalCount].id = mp.id;
+    this->packetHistory[this->packetHistoryTotalCount].reply_id = p.reply_id;
+    this->packetHistory[this->packetHistoryTotalCount].emoji = (bool)p.emoji;
     this->packetHistory[this->packetHistoryTotalCount].payload_size = p.payload.size;
     memcpy(this->packetHistory[this->packetHistoryTotalCount].payload, p.payload.bytes, meshtastic_Constants_DATA_PAYLOAD_LEN);
 
@@ -244,8 +247,11 @@ meshtastic_MeshPacket *StoreForwardModule::preparePayload(NodeNum dest, uint32_t
 
                 p->to = local ? this->packetHistory[i].to : dest; // PhoneAPI can handle original `to`
                 p->from = this->packetHistory[i].from;
+                p->id = this->packetHistory[i].id;
                 p->channel = this->packetHistory[i].channel;
+                p->decoded.reply_id = this->packetHistory[i].reply_id;
                 p->rx_time = this->packetHistory[i].time;
+                p->decoded.emoji = (uint32_t)this->packetHistory[i].emoji;
 
                 // Let's assume that if the server received the S&F request that the client is in range.
                 //   TODO: Make this configurable.
@@ -617,4 +623,4 @@ StoreForwardModule::StoreForwardModule()
         disable();
     }
 #endif
-}
+}
\ No newline at end of file
diff --git a/src/modules/StoreForwardModule.h b/src/modules/StoreForwardModule.h
index e3273470b..30db1625c 100644
--- a/src/modules/StoreForwardModule.h
+++ b/src/modules/StoreForwardModule.h
@@ -13,7 +13,10 @@ struct PacketHistoryStruct {
     uint32_t time;
     uint32_t to;
     uint32_t from;
+    uint32_t id;
     uint8_t channel;
+    uint32_t reply_id;
+    bool emoji;
     uint8_t payload[meshtastic_Constants_DATA_PAYLOAD_LEN];
     pb_size_t payload_size;
 };