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 01/10] 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 02/10] 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 03/10] 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 04/10] 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 05/10] [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 06/10] 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 07/10] 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 08/10] 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 09/10] 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 10/10] 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;
 };