virtual bool init() override;
};
-/* https://wiki.seeedstudio.com/LoRa-E5_STM32WLE5JC_Module/
- * Wio-E5 module ONLY transmits through RFO_HP
- * Receive: PA4=1, PA5=0
- * Transmit(high output power, SMPS mode): PA4=0, PA5=1 */
-static const RADIOLIB_PIN_TYPE rfswitch_pins[5] = {PA4, PA5, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
-
-static const Module::RfSwitchMode_t rfswitch_table[4] = {
- {STM32WLx::MODE_IDLE, {LOW, LOW}}, {STM32WLx::MODE_RX, {HIGH, LOW}}, {STM32WLx::MODE_TX_HP, {LOW, HIGH}}, END_OF_MODE_TABLE};
-
#endif // ARCH_STM32WL
\ No newline at end of file
diff --git a/src/mesh/StreamAPI.cpp b/src/mesh/StreamAPI.cpp
index 4a42e5197..20026767e 100644
--- a/src/mesh/StreamAPI.cpp
+++ b/src/mesh/StreamAPI.cpp
@@ -16,6 +16,95 @@ int32_t StreamAPI::runOncePart()
return result;
}
+int32_t StreamAPI::runOncePart(char *buf, uint16_t bufLen)
+{
+ auto result = readStream(buf, bufLen);
+ writeStream();
+ checkConnectionTimeout();
+ return result;
+}
+
+/**
+ * Read any rx chars from the link and call handleRecStream
+ */
+int32_t StreamAPI::readStream(char *buf, uint16_t bufLen)
+{
+ if (bufLen < 1) {
+ // Nothing available this time, if the computer has talked to us recently, poll often, otherwise let CPU sleep a long time
+ bool recentRx = Throttle::isWithinTimespanMs(lastRxMsec, 2000);
+ return recentRx ? 5 : 250;
+ } else {
+ handleRecStream(buf, bufLen);
+ // we had bytes available this time, so assume we might have them next time also
+ lastRxMsec = millis();
+ return 0;
+ }
+}
+
+/**
+ * call getFromRadio() and deliver encapsulated packets to the Stream
+ */
+void StreamAPI::writeStream()
+{
+ if (canWrite) {
+ uint32_t len;
+ do {
+ // Send every packet we can
+ len = getFromRadio(txBuf + HEADER_LEN);
+ emitTxBuffer(len);
+ } while (len);
+ }
+}
+
+int32_t StreamAPI::handleRecStream(char *buf, uint16_t bufLen)
+{
+ uint16_t index = 0;
+ while (bufLen > index) { // Currently we never want to block
+ int cInt = buf[index++];
+ if (cInt < 0)
+ break; // We ran out of characters (even though available said otherwise) - this can happen on rf52 adafruit
+ // arduino
+
+ uint8_t c = (uint8_t)cInt;
+
+ // Use the read pointer for a little state machine, first look for framing, then length bytes, then payload
+ size_t ptr = rxPtr;
+
+ rxPtr++; // assume we will probably advance the rxPtr
+ rxBuf[ptr] = c; // store all bytes (including framing)
+
+ // console->printf("rxPtr %d ptr=%d c=0x%x\n", rxPtr, ptr, c);
+
+ if (ptr == 0) { // looking for START1
+ if (c != START1)
+ rxPtr = 0; // failed to find framing
+ } else if (ptr == 1) { // looking for START2
+ if (c != START2)
+ rxPtr = 0; // failed to find framing
+ } else if (ptr >= HEADER_LEN - 1) { // we have at least read our 4 byte framing
+ uint32_t len = (rxBuf[2] << 8) + rxBuf[3]; // big endian 16 bit length follows framing
+
+ // console->printf("len %d\n", len);
+
+ if (ptr == HEADER_LEN - 1) {
+ // we _just_ finished our 4 byte header, validate length now (note: a length of zero is a valid
+ // protobuf also)
+ if (len > MAX_TO_FROM_RADIO_SIZE)
+ rxPtr = 0; // length is bogus, restart search for framing
+ }
+
+ if (rxPtr != 0) // Is packet still considered 'good'?
+ if (ptr + 1 >= len + HEADER_LEN) { // have we received all of the payload?
+ rxPtr = 0; // start over again on the next packet
+
+ // If we didn't just fail the packet and we now have the right # of bytes, parse it
+ handleToRadio(rxBuf + HEADER_LEN, len);
+ }
+ }
+ }
+ return 0;
+}
+
/**
* Read any rx chars from the link and call handleToRadio
*/
@@ -76,21 +165,6 @@ int32_t StreamAPI::readStream()
}
}
-/**
- * call getFromRadio() and deliver encapsulated packets to the Stream
- */
-void StreamAPI::writeStream()
-{
- if (canWrite) {
- uint32_t len;
- do {
- // Send every packet we can
- len = getFromRadio(txBuf + HEADER_LEN);
- emitTxBuffer(len);
- } while (len);
- }
-}
-
/**
* Send the current txBuffer over our stream
*/
diff --git a/src/mesh/StreamAPI.h b/src/mesh/StreamAPI.h
index 6e0364bc1..547dd0175 100644
--- a/src/mesh/StreamAPI.h
+++ b/src/mesh/StreamAPI.h
@@ -50,12 +50,15 @@ class StreamAPI : public PhoneAPI
* phone.
*/
virtual int32_t runOncePart();
+ virtual int32_t runOncePart(char *buf,uint16_t bufLen);
private:
/**
* Read any rx chars from the link and call handleToRadio
*/
int32_t readStream();
+ int32_t readStream(char *buf,uint16_t bufLen);
+ int32_t handleRecStream(char *buf,uint16_t bufLen);
/**
* call getFromRadio() and deliver encapsulated packets to the Stream
diff --git a/src/mesh/api/PacketAPI.cpp b/src/mesh/api/PacketAPI.cpp
index 1d6df855f..ab380d696 100644
--- a/src/mesh/api/PacketAPI.cpp
+++ b/src/mesh/api/PacketAPI.cpp
@@ -59,6 +59,7 @@ bool PacketAPI::receivePacket(void)
switch (mr->which_payload_variant) {
case meshtastic_ToRadio_packet_tag: {
meshtastic_MeshPacket *mp = &mr->packet;
+ mp->transport_mechanism = meshtastic_MeshPacket_TransportMechanism_TRANSPORT_API;
printPacket("PACKET FROM QUEUE", mp);
service->handleToRadio(*mp);
break;
diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h
index 8a68197f0..59e55db3f 100644
--- a/src/mesh/generated/meshtastic/config.pb.h
+++ b/src/mesh/generated/meshtastic/config.pb.h
@@ -64,7 +64,12 @@ typedef enum _meshtastic_Config_DeviceConfig_Role {
in areas not already covered by other routers, or to bridge around problematic terrain,
but should not be given priority over other routers in order to avoid unnecessaraily
consuming hops. */
- meshtastic_Config_DeviceConfig_Role_ROUTER_LATE = 11
+ meshtastic_Config_DeviceConfig_Role_ROUTER_LATE = 11,
+ /* Description: Treats packets from or to favorited nodes as ROUTER, and all other packets as CLIENT.
+ Technical Details: Used for stronger attic/roof nodes to distribute messages more widely
+ from weaker, indoor, or less-well-positioned nodes. Recommended for users with multiple nodes
+ where one CLIENT_BASE acts as a more powerful base station, such as an attic/roof node. */
+ meshtastic_Config_DeviceConfig_Role_CLIENT_BASE = 12
} meshtastic_Config_DeviceConfig_Role;
/* Defines the device's behavior for how messages are rebroadcast */
@@ -207,10 +212,10 @@ typedef enum _meshtastic_Config_DisplayConfig_OledType {
meshtastic_Config_DisplayConfig_OledType_OLED_SSD1306 = 1,
/* Default / Autodetect */
meshtastic_Config_DisplayConfig_OledType_OLED_SH1106 = 2,
- /* Can not be auto detected but set by proto. Used for 128x128 screens */
- meshtastic_Config_DisplayConfig_OledType_OLED_SH1107 = 3,
/* Can not be auto detected but set by proto. Used for 128x64 screens */
- meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_64 = 4
+ meshtastic_Config_DisplayConfig_OledType_OLED_SH1107 = 3,
+ /* Can not be auto detected but set by proto. Used for 128x128 screens */
+ meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_128 = 4
} meshtastic_Config_DisplayConfig_OledType;
typedef enum _meshtastic_Config_DisplayConfig_DisplayMode {
@@ -646,8 +651,8 @@ extern "C" {
/* Helper constants for enums */
#define _meshtastic_Config_DeviceConfig_Role_MIN meshtastic_Config_DeviceConfig_Role_CLIENT
-#define _meshtastic_Config_DeviceConfig_Role_MAX meshtastic_Config_DeviceConfig_Role_ROUTER_LATE
-#define _meshtastic_Config_DeviceConfig_Role_ARRAYSIZE ((meshtastic_Config_DeviceConfig_Role)(meshtastic_Config_DeviceConfig_Role_ROUTER_LATE+1))
+#define _meshtastic_Config_DeviceConfig_Role_MAX meshtastic_Config_DeviceConfig_Role_CLIENT_BASE
+#define _meshtastic_Config_DeviceConfig_Role_ARRAYSIZE ((meshtastic_Config_DeviceConfig_Role)(meshtastic_Config_DeviceConfig_Role_CLIENT_BASE+1))
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN meshtastic_Config_DeviceConfig_RebroadcastMode_ALL
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MAX meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY
@@ -682,8 +687,8 @@ extern "C" {
#define _meshtastic_Config_DisplayConfig_DisplayUnits_ARRAYSIZE ((meshtastic_Config_DisplayConfig_DisplayUnits)(meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL+1))
#define _meshtastic_Config_DisplayConfig_OledType_MIN meshtastic_Config_DisplayConfig_OledType_OLED_AUTO
-#define _meshtastic_Config_DisplayConfig_OledType_MAX meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_64
-#define _meshtastic_Config_DisplayConfig_OledType_ARRAYSIZE ((meshtastic_Config_DisplayConfig_OledType)(meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_64+1))
+#define _meshtastic_Config_DisplayConfig_OledType_MAX meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_128
+#define _meshtastic_Config_DisplayConfig_OledType_ARRAYSIZE ((meshtastic_Config_DisplayConfig_OledType)(meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_128+1))
#define _meshtastic_Config_DisplayConfig_DisplayMode_MIN meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT
#define _meshtastic_Config_DisplayConfig_DisplayMode_MAX meshtastic_Config_DisplayConfig_DisplayMode_COLOR
diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h
index f47091384..9b6330596 100644
--- a/src/mesh/generated/meshtastic/deviceonly.pb.h
+++ b/src/mesh/generated/meshtastic/deviceonly.pb.h
@@ -360,7 +360,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg;
/* Maximum encoded size of messages (where known) */
/* meshtastic_NodeDatabase_size depends on runtime parameters */
#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size
-#define meshtastic_BackupPreferences_size 2271
+#define meshtastic_BackupPreferences_size 2273
#define meshtastic_ChannelFile_size 718
#define meshtastic_DeviceState_size 1737
#define meshtastic_NodeInfoLite_size 196
diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h
index ca8dcd5fb..da224fb94 100644
--- a/src/mesh/generated/meshtastic/localonly.pb.h
+++ b/src/mesh/generated/meshtastic/localonly.pb.h
@@ -188,7 +188,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
/* Maximum encoded size of messages (where known) */
#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalConfig_size
#define meshtastic_LocalConfig_size 747
-#define meshtastic_LocalModuleConfig_size 669
+#define meshtastic_LocalModuleConfig_size 671
#ifdef __cplusplus
} /* extern "C" */
diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h
index 1d1ff47e0..2a4e77870 100644
--- a/src/mesh/generated/meshtastic/mesh.pb.h
+++ b/src/mesh/generated/meshtastic/mesh.pb.h
@@ -270,6 +270,10 @@ typedef enum _meshtastic_HardwareModel {
/* MeshSolar is an integrated power management and communication solution designed for outdoor low-power devices.
https://heltec.org/project/meshsolar/ */
meshtastic_HardwareModel_HELTEC_MESH_SOLAR = 108,
+ /* Lilygo T-Echo Lite */
+ meshtastic_HardwareModel_T_ECHO_LITE = 109,
+ /* New Heltec LoRA32 with ESP32-S3 CPU */
+ meshtastic_HardwareModel_HELTEC_V4 = 110,
/* ------------------------------------------------------------------------------------------------------------------------------------------
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.
------------------------------------------------------------------------------------------------------------------------------------------ */
diff --git a/src/mesh/generated/meshtastic/module_config.pb.h b/src/mesh/generated/meshtastic/module_config.pb.h
index b27f5f515..16c4c230c 100644
--- a/src/mesh/generated/meshtastic/module_config.pb.h
+++ b/src/mesh/generated/meshtastic/module_config.pb.h
@@ -317,6 +317,9 @@ typedef struct _meshtastic_ModuleConfig_RangeTestConfig {
/* Bool value indicating that this node should save a RangeTest.csv file.
ESP32 Only */
bool save;
+ /* Bool indicating that the node should cleanup / destroy it's RangeTest.csv file.
+ ESP32 Only */
+ bool clear_on_reboot;
} meshtastic_ModuleConfig_RangeTestConfig;
/* Configuration for both device and environment metrics */
@@ -519,7 +522,7 @@ extern "C" {
#define meshtastic_ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN, 0}
#define meshtastic_ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0, 0}
-#define meshtastic_ModuleConfig_RangeTestConfig_init_default {0, 0, 0}
+#define meshtastic_ModuleConfig_RangeTestConfig_init_default {0, 0, 0, 0}
#define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
#define meshtastic_ModuleConfig_AmbientLightingConfig_init_default {0, 0, 0, 0, 0}
@@ -535,7 +538,7 @@ extern "C" {
#define meshtastic_ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN, 0}
#define meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0, 0}
-#define meshtastic_ModuleConfig_RangeTestConfig_init_zero {0, 0, 0}
+#define meshtastic_ModuleConfig_RangeTestConfig_init_zero {0, 0, 0, 0}
#define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
#define meshtastic_ModuleConfig_AmbientLightingConfig_init_zero {0, 0, 0, 0, 0}
@@ -610,6 +613,7 @@ extern "C" {
#define meshtastic_ModuleConfig_RangeTestConfig_enabled_tag 1
#define meshtastic_ModuleConfig_RangeTestConfig_sender_tag 2
#define meshtastic_ModuleConfig_RangeTestConfig_save_tag 3
+#define meshtastic_ModuleConfig_RangeTestConfig_clear_on_reboot_tag 4
#define meshtastic_ModuleConfig_TelemetryConfig_device_update_interval_tag 1
#define meshtastic_ModuleConfig_TelemetryConfig_environment_update_interval_tag 2
#define meshtastic_ModuleConfig_TelemetryConfig_environment_measurement_enabled_tag 3
@@ -803,7 +807,8 @@ X(a, STATIC, SINGULAR, BOOL, is_server, 6)
#define meshtastic_ModuleConfig_RangeTestConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
X(a, STATIC, SINGULAR, UINT32, sender, 2) \
-X(a, STATIC, SINGULAR, BOOL, save, 3)
+X(a, STATIC, SINGULAR, BOOL, save, 3) \
+X(a, STATIC, SINGULAR, BOOL, clear_on_reboot, 4)
#define meshtastic_ModuleConfig_RangeTestConfig_CALLBACK NULL
#define meshtastic_ModuleConfig_RangeTestConfig_DEFAULT NULL
@@ -901,7 +906,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
#define meshtastic_ModuleConfig_MapReportSettings_size 14
#define meshtastic_ModuleConfig_NeighborInfoConfig_size 10
#define meshtastic_ModuleConfig_PaxcounterConfig_size 30
-#define meshtastic_ModuleConfig_RangeTestConfig_size 10
+#define meshtastic_ModuleConfig_RangeTestConfig_size 12
#define meshtastic_ModuleConfig_RemoteHardwareConfig_size 96
#define meshtastic_ModuleConfig_SerialConfig_size 28
#define meshtastic_ModuleConfig_StoreForwardConfig_size 24
diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h
index f758995c2..9af095e78 100644
--- a/src/mesh/generated/meshtastic/telemetry.pb.h
+++ b/src/mesh/generated/meshtastic/telemetry.pb.h
@@ -99,7 +99,9 @@ typedef enum _meshtastic_TelemetrySensorType {
/* Sensirion SFA30 Formaldehyde sensor */
meshtastic_TelemetrySensorType_SFA30 = 42,
/* SEN5X PM SENSORS */
- meshtastic_TelemetrySensorType_SEN5X = 43
+ meshtastic_TelemetrySensorType_SEN5X = 43,
+ /* TSL2561 light sensor */
+ meshtastic_TelemetrySensorType_TSL2561 = 44
} meshtastic_TelemetrySensorType;
/* Struct definitions */
@@ -434,8 +436,8 @@ extern "C" {
/* Helper constants for enums */
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
-#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_SEN5X
-#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_SEN5X+1))
+#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_TSL2561
+#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_TSL2561+1))
diff --git a/src/mesh/http/ContentHandler.cpp b/src/mesh/http/ContentHandler.cpp
index 42ebb8417..74953d8fc 100644
--- a/src/mesh/http/ContentHandler.cpp
+++ b/src/mesh/http/ContentHandler.cpp
@@ -342,6 +342,11 @@ void handleFsBrowseStatic(HTTPRequest *req, HTTPResponse *res)
res->print(value->Stringify().c_str());
delete value;
+
+ // Clean up the fileList to prevent memory leak
+ for (auto *val : fileList) {
+ delete val;
+ }
}
void handleFsDeleteStatic(HTTPRequest *req, HTTPResponse *res)
@@ -610,33 +615,38 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
res->println("");
}
+ // Helper lambda to create JSON array and clean up memory properly
+ auto createJSONArrayFromLog = [](uint32_t *logArray, int count) -> JSONValue * {
+ JSONArray tempArray;
+ for (int i = 0; i < count; i++) {
+ tempArray.push_back(new JSONValue((int)logArray[i]));
+ }
+ JSONValue *result = new JSONValue(tempArray);
+ // Clean up original array to prevent memory leak
+ for (auto *val : tempArray) {
+ delete val;
+ }
+ return result;
+ };
+
// data->airtime->tx_log
- JSONArray txLogValues;
uint32_t *logArray;
logArray = airTime->airtimeReport(TX_LOG);
- for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
- txLogValues.push_back(new JSONValue((int)logArray[i]));
- }
+ JSONValue *txLogJsonValue = createJSONArrayFromLog(logArray, airTime->getPeriodsToLog());
// data->airtime->rx_log
- JSONArray rxLogValues;
logArray = airTime->airtimeReport(RX_LOG);
- for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
- rxLogValues.push_back(new JSONValue((int)logArray[i]));
- }
+ JSONValue *rxLogJsonValue = createJSONArrayFromLog(logArray, airTime->getPeriodsToLog());
// data->airtime->rx_all_log
- JSONArray rxAllLogValues;
logArray = airTime->airtimeReport(RX_ALL_LOG);
- for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
- rxAllLogValues.push_back(new JSONValue((int)logArray[i]));
- }
+ JSONValue *rxAllLogJsonValue = createJSONArrayFromLog(logArray, airTime->getPeriodsToLog());
// data->airtime
JSONObject jsonObjAirtime;
- jsonObjAirtime["tx_log"] = new JSONValue(txLogValues);
- jsonObjAirtime["rx_log"] = new JSONValue(rxLogValues);
- jsonObjAirtime["rx_all_log"] = new JSONValue(rxAllLogValues);
+ jsonObjAirtime["tx_log"] = txLogJsonValue;
+ jsonObjAirtime["rx_log"] = rxLogJsonValue;
+ jsonObjAirtime["rx_all_log"] = rxAllLogJsonValue;
jsonObjAirtime["channel_utilization"] = new JSONValue(airTime->channelUtilizationPercent());
jsonObjAirtime["utilization_tx"] = new JSONValue(airTime->utilizationTXPercent());
jsonObjAirtime["seconds_since_boot"] = new JSONValue(int(airTime->getSecondsSinceBoot()));
@@ -765,6 +775,11 @@ void handleNodes(HTTPRequest *req, HTTPResponse *res)
JSONValue *value = new JSONValue(jsonObjOuter);
res->print(value->Stringify().c_str());
delete value;
+
+ // Clean up the nodesArray to prevent memory leak
+ for (auto *val : nodesArray) {
+ delete val;
+ }
}
/*
@@ -955,5 +970,10 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
JSONValue *value = new JSONValue(jsonObjOuter);
res->print(value->Stringify().c_str());
delete value;
+
+ // Clean up the networkObjs to prevent memory leak
+ for (auto *val : networkObjs) {
+ delete val;
+ }
}
#endif
\ No newline at end of file
diff --git a/src/mesh/udp/UdpMulticastHandler.h b/src/mesh/udp/UdpMulticastHandler.h
index d4e0eaa8c..9650668a8 100644
--- a/src/mesh/udp/UdpMulticastHandler.h
+++ b/src/mesh/udp/UdpMulticastHandler.h
@@ -50,6 +50,7 @@ class UdpMulticastHandler final
LOG_DEBUG("UDP broadcast from: %s, len=%u", packet.remoteIP().toString().c_str(), packetLength);
#endif
meshtastic_MeshPacket mp;
+ mp.transport_mechanism = meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MULTICAST_UDP;
LOG_DEBUG("Decoding MeshPacket from UDP len=%u", packetLength);
bool isPacketDecoded = pb_decode_from_bytes(packet.data(), packetLength, &meshtastic_MeshPacket_msg, &mp);
if (isPacketDecoded && router && mp.which_payload_variant == meshtastic_MeshPacket_encrypted_tag) {
@@ -78,6 +79,9 @@ class UdpMulticastHandler final
return false;
}
#endif
+ if (mp->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MULTICAST_UDP) {
+ LOG_ERROR("Attempt to send UDP sourced packet over UDP");
+ }
LOG_DEBUG("Broadcasting packet over UDP (id=%u)", mp->id);
uint8_t buffer[meshtastic_MeshPacket_size];
size_t encodedLength = pb_encode_to_bytes(buffer, sizeof(buffer), &meshtastic_MeshPacket_msg, mp);
diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp
index 4014e1c36..407003f7e 100644
--- a/src/modules/AdminModule.cpp
+++ b/src/modules/AdminModule.cpp
@@ -505,7 +505,9 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
if (mp.decoded.want_response && !myReply) {
myReply = allocErrorResponse(meshtastic_Routing_Error_NONE, &mp);
}
-
+ if (mp.pki_encrypted && myReply) {
+ myReply->pki_encrypted = true;
+ }
return handled;
}
@@ -718,6 +720,13 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
requiresReboot = false;
}
+#if defined(ARCH_PORTDUINO)
+ // If running on portduino and using SimRadio, do not require reboot
+ if (SimRadio::instance) {
+ requiresReboot = false;
+ }
+#endif
+
#ifdef RF95_FAN_EN
// Turn PA off if disabled by config
if (c.payload_variant.lora.pa_fan_disabled) {
@@ -934,6 +943,9 @@ void AdminModule::handleGetOwner(const meshtastic_MeshPacket &req)
res.which_payload_variant = meshtastic_AdminMessage_get_owner_response_tag;
setPassKey(&res);
myReply = allocDataProtobuf(res);
+ if (req.pki_encrypted) {
+ myReply->pki_encrypted = true;
+ }
}
}
@@ -1005,6 +1017,9 @@ void AdminModule::handleGetConfig(const meshtastic_MeshPacket &req, const uint32
res.which_payload_variant = meshtastic_AdminMessage_get_config_response_tag;
setPassKey(&res);
myReply = allocDataProtobuf(res);
+ if (req.pki_encrypted) {
+ myReply->pki_encrypted = true;
+ }
}
}
@@ -1092,6 +1107,9 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
res.which_payload_variant = meshtastic_AdminMessage_get_module_config_response_tag;
setPassKey(&res);
myReply = allocDataProtobuf(res);
+ if (req.pki_encrypted) {
+ myReply->pki_encrypted = true;
+ }
}
}
@@ -1116,6 +1134,9 @@ void AdminModule::handleGetNodeRemoteHardwarePins(const meshtastic_MeshPacket &r
}
setPassKey(&r);
myReply = allocDataProtobuf(r);
+ if (req.pki_encrypted) {
+ myReply->pki_encrypted = true;
+ }
}
void AdminModule::handleGetDeviceMetadata(const meshtastic_MeshPacket &req)
@@ -1125,6 +1146,9 @@ void AdminModule::handleGetDeviceMetadata(const meshtastic_MeshPacket &req)
r.which_payload_variant = meshtastic_AdminMessage_get_device_metadata_response_tag;
setPassKey(&r);
myReply = allocDataProtobuf(r);
+ if (req.pki_encrypted) {
+ myReply->pki_encrypted = true;
+ }
}
void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &req)
@@ -1193,6 +1217,9 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r
r.which_payload_variant = meshtastic_AdminMessage_get_device_connection_status_response_tag;
setPassKey(&r);
myReply = allocDataProtobuf(r);
+ if (req.pki_encrypted) {
+ myReply->pki_encrypted = true;
+ }
}
void AdminModule::handleGetChannel(const meshtastic_MeshPacket &req, uint32_t channelIndex)
@@ -1204,6 +1231,9 @@ void AdminModule::handleGetChannel(const meshtastic_MeshPacket &req, uint32_t ch
r.which_payload_variant = meshtastic_AdminMessage_get_channel_response_tag;
setPassKey(&r);
myReply = allocDataProtobuf(r);
+ if (req.pki_encrypted) {
+ myReply->pki_encrypted = true;
+ }
}
}
@@ -1213,6 +1243,9 @@ void AdminModule::handleGetDeviceUIConfig(const meshtastic_MeshPacket &req)
r.which_payload_variant = meshtastic_AdminMessage_get_ui_config_response_tag;
r.get_ui_config_response = uiconfig;
myReply = allocDataProtobuf(r);
+ if (req.pki_encrypted) {
+ myReply->pki_encrypted = true;
+ }
}
void AdminModule::reboot(int32_t seconds)
diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp
index b6cb1b0e3..e9165e57c 100644
--- a/src/modules/CannedMessageModule.cpp
+++ b/src/modules/CannedMessageModule.cpp
@@ -78,16 +78,15 @@ void CannedMessageModule::LaunchWithDestination(NodeNum newDest, uint8_t newChan
lastDestSet = true;
// Rest of function unchanged...
- // Always select the first real canned message on activation
- int firstRealMsgIdx = 0;
+ // Upon activation, highlight "[Select Destination]"
+ int selectDestination = 0;
for (int i = 0; i < messagesCount; ++i) {
- if (strcmp(messages[i], "[Select Destination]") != 0 && strcmp(messages[i], "[Exit]") != 0 &&
- strcmp(messages[i], "[---- Free Text ----]") != 0) {
- firstRealMsgIdx = i;
+ if (strcmp(messages[i], "[Select Destination]") == 0) {
+ selectDestination = i;
break;
}
}
- currentMessageIndex = firstRealMsgIdx;
+ currentMessageIndex = selectDestination;
// This triggers the canned message list
runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
@@ -633,10 +632,10 @@ bool CannedMessageModule::handleMessageSelectorInput(const InputEvent *event, bo
// Normal canned message selection
if (runState == CANNED_MESSAGE_RUN_STATE_INACTIVE || runState == CANNED_MESSAGE_RUN_STATE_DISABLED) {
} else {
+#if CANNED_MESSAGE_ADD_CONFIRMATION
// Show confirmation dialog before sending canned message
NodeNum destNode = dest;
ChannelIndex chan = channel;
-#if CANNED_MESSAGE_ADD_CONFIRMATION
graphics::menuHandler::showConfirmationBanner("Send message?", [this, destNode, chan, current]() {
this->sendText(destNode, chan, current, false);
payload = runState;
@@ -992,24 +991,22 @@ int32_t CannedMessageModule::runOnce()
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
}
}
- e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
this->currentMessageIndex = -1;
this->freetext = "";
this->cursor = 0;
this->notifyObservers(&e);
return 2000;
}
- // Always highlight the first real canned message when entering the message list
+ // Highlight [Select Destination] initially when entering the message list
else if ((this->runState != CANNED_MESSAGE_RUN_STATE_FREETEXT) && (this->currentMessageIndex == -1)) {
- int firstRealMsgIdx = 0;
+ int selectDestination = 0;
for (int i = 0; i < this->messagesCount; ++i) {
- if (strcmp(this->messages[i], "[Select Destination]") != 0 && strcmp(this->messages[i], "[Exit]") != 0 &&
- strcmp(this->messages[i], "[---- Free Text ----]") != 0) {
- firstRealMsgIdx = i;
+ if (strcmp(this->messages[i], "[Select Destination]") == 0) {
+ selectDestination = i;
break;
}
}
- this->currentMessageIndex = firstRealMsgIdx;
+ this->currentMessageIndex = selectDestination;
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_UP) {
diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp
index 1f871f87e..2f2934984 100644
--- a/src/modules/ExternalNotificationModule.cpp
+++ b/src/modules/ExternalNotificationModule.cpp
@@ -364,9 +364,10 @@ ExternalNotificationModule::ExternalNotificationModule()
// moduleConfig.external_notification.alert_message_buzzer = true;
if (moduleConfig.external_notification.enabled) {
+#if !defined(MESHTASTIC_EXCLUDE_INPUTBROKER)
if (inputBroker) // put our callback in the inputObserver list
inputObserver.observe(inputBroker);
-
+#endif
if (nodeDB->loadProto(rtttlConfigFile, meshtastic_RTTTLConfig_size, sizeof(meshtastic_RTTTLConfig),
&meshtastic_RTTTLConfig_msg, &rtttlConfig) != LoadFileResult::LOAD_SUCCESS) {
memset(rtttlConfig.ringtone, 0, sizeof(rtttlConfig.ringtone));
diff --git a/src/modules/Modules.cpp b/src/modules/Modules.cpp
index 2f3da0fdd..f2c34a7c8 100644
--- a/src/modules/Modules.cpp
+++ b/src/modules/Modules.cpp
@@ -3,6 +3,7 @@
#include "buzz/BuzzerFeedbackThread.h"
#include "input/ExpressLRSFiveWay.h"
#include "input/InputBroker.h"
+#include "input/RotaryEncoderImpl.h"
#include "input/RotaryEncoderInterruptImpl1.h"
#include "input/SerialKeyboardImpl.h"
#include "input/TrackballInterruptImpl1.h"
@@ -87,7 +88,7 @@
#include "modules/StoreForwardModule.h"
#endif
#endif
-#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO)
+
#if !MESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION
#include "modules/ExternalNotificationModule.h"
#endif
@@ -97,7 +98,6 @@
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !MESHTASTIC_EXCLUDE_SERIAL
#include "modules/SerialModule.h"
#endif
-#endif
#if !MESHTASTIC_EXCLUDE_DROPZONE
#include "modules/DropzoneModule.h"
@@ -170,11 +170,20 @@ void setupModules()
delete rotaryEncoderInterruptImpl1;
rotaryEncoderInterruptImpl1 = nullptr;
}
+#ifdef T_LORA_PAGER
+ // use a special FSM based rotary encoder version for T-LoRa Pager
+ rotaryEncoderImpl = new RotaryEncoderImpl();
+ if (!rotaryEncoderImpl->init()) {
+ delete rotaryEncoderImpl;
+ rotaryEncoderImpl = nullptr;
+ }
+#else
upDownInterruptImpl1 = new UpDownInterruptImpl1();
if (!upDownInterruptImpl1->init()) {
delete upDownInterruptImpl1;
upDownInterruptImpl1 = nullptr;
}
+#endif
cardKbI2cImpl = new CardKbI2cImpl();
cardKbI2cImpl->init();
#ifdef INPUTBROKER_MATRIX_TYPE
@@ -236,8 +245,8 @@ void setupModules()
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_POWER_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
new PowerTelemetryModule();
#endif
-#if (defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040)) && !defined(CONFIG_IDF_TARGET_ESP32S2) && \
- !defined(CONFIG_IDF_TARGET_ESP32C3)
+#if (defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040) || defined(ARCH_STM32WL)) && \
+ !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
#if !MESHTASTIC_EXCLUDE_SERIAL
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
new SerialModule();
@@ -258,13 +267,11 @@ void setupModules()
storeForwardModule = new StoreForwardModule();
#endif
#endif
-#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO)
#if !MESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION
externalNotificationModule = new ExternalNotificationModule();
#endif
#if !MESHTASTIC_EXCLUDE_RANGETEST && !MESHTASTIC_EXCLUDE_GPS
new RangeTestModule();
-#endif
#endif
} else {
#if !MESHTASTIC_EXCLUDE_ADMIN
diff --git a/src/modules/NeighborInfoModule.cpp b/src/modules/NeighborInfoModule.cpp
index eebf428a4..97dc17001 100644
--- a/src/modules/NeighborInfoModule.cpp
+++ b/src/modules/NeighborInfoModule.cpp
@@ -105,14 +105,15 @@ void NeighborInfoModule::sendNeighborInfo(NodeNum dest, bool wantReplies)
{
meshtastic_NeighborInfo neighborInfo = meshtastic_NeighborInfo_init_zero;
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;
- p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
- printNeighborInfo("SENDING", &neighborInfo);
- service->sendToMesh(p, RX_SRC_LOCAL, true);
+ // only send neighbours if we have some to send
+ if (neighborInfo.neighbors_count > 0) {
+ meshtastic_MeshPacket *p = allocDataProtobuf(neighborInfo);
+ p->to = dest;
+ p->decoded.want_response = wantReplies;
+ p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
+ printNeighborInfo("SENDING", &neighborInfo);
+ service->sendToMesh(p, RX_SRC_LOCAL, true);
+ }
}
/*
@@ -214,4 +215,4 @@ meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSen
neighbors.push_back(new_nbr);
}
return &neighbors.back();
-}
\ No newline at end of file
+}
diff --git a/src/modules/NodeInfoModule.cpp b/src/modules/NodeInfoModule.cpp
index b6fee7703..0060e99fa 100644
--- a/src/modules/NodeInfoModule.cpp
+++ b/src/modules/NodeInfoModule.cpp
@@ -14,6 +14,10 @@ bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
{
auto p = *pptr;
+ if (mp.from == nodeDB->getNodeNum()) {
+ LOG_WARN("Ignoring packet supposed to be from our own node: %08x", mp.from);
+ return false;
+ }
if (p.is_licensed != owner.is_licensed) {
LOG_WARN("Invalid nodeInfo detected, is_licensed mismatch!");
return true;
diff --git a/src/modules/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp
index 6f3d69acf..d1d2d9ead 100644
--- a/src/modules/RangeTestModule.cpp
+++ b/src/modules/RangeTestModule.cpp
@@ -31,7 +31,7 @@ uint32_t packetSequence = 0;
int32_t RangeTestModule::runOnce()
{
-#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_PORTDUINO)
+#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_STM32WL) || defined(ARCH_PORTDUINO)
/*
Uncomment the preferences below if you want to use the module
@@ -130,7 +130,7 @@ void RangeTestModuleRadio::sendPayload(NodeNum dest, bool wantReplies)
ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket &mp)
{
-#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_PORTDUINO)
+#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_STM32WL) || defined(ARCH_PORTDUINO)
if (moduleConfig.range_test.enabled) {
diff --git a/src/modules/SerialModule.cpp b/src/modules/SerialModule.cpp
index 39b297965..7485f1c2d 100644
--- a/src/modules/SerialModule.cpp
+++ b/src/modules/SerialModule.cpp
@@ -45,9 +45,12 @@
*/
+#ifdef HELTEC_MESH_SOLAR
+#include "meshSolarApp.h"
+#endif
-#if (defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040)) && !defined(CONFIG_IDF_TARGET_ESP32S2) && \
- !defined(CONFIG_IDF_TARGET_ESP32C3)
+#if (defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040) || defined(ARCH_STM32WL)) && \
+ !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
#define RX_BUFFER 256
#define TIMEOUT 250
@@ -61,10 +64,10 @@ SerialModule *serialModule;
SerialModuleRadio *serialModuleRadio;
#if defined(TTGO_T_ECHO) || defined(CANARYONE) || defined(MESHLINK) || defined(ELECROW_ThinkNode_M1) || \
- defined(ELECROW_ThinkNode_M5)
+ defined(ELECROW_ThinkNode_M5) || defined(HELTEC_MESH_SOLAR) || defined(T_ECHO_LITE)
SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial") {}
static Print *serialPrint = &Serial;
-#elif defined(CONFIG_IDF_TARGET_ESP32C6)
+#elif defined(CONFIG_IDF_TARGET_ESP32C6) || defined(RAK3172)
SerialModule::SerialModule() : StreamAPI(&Serial1), concurrency::OSThread("Serial") {}
static Print *serialPrint = &Serial1;
#else
@@ -78,7 +81,8 @@ size_t serialPayloadSize;
bool SerialModule::isValidConfig(const meshtastic_ModuleConfig_SerialConfig &config)
{
if (config.override_console_serial_port && !IS_ONE_OF(config.mode, meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA,
- meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO)) {
+ meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO,
+ meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MS_CONFIG)) {
const char *warning =
"Invalid Serial config: override console serial port is only supported in NMEA and CalTopo output-only modes.";
LOG_ERROR(warning);
@@ -169,7 +173,18 @@ int32_t SerialModule::runOnce()
Serial.begin(baud);
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
}
-
+#elif defined(ARCH_STM32WL)
+#ifndef RAK3172
+ HardwareSerial *serialInstance = &Serial2;
+#else
+ HardwareSerial *serialInstance = &Serial1;
+#endif
+ if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
+ serialInstance->setTx(moduleConfig.serial.txd);
+ serialInstance->setRx(moduleConfig.serial.rxd);
+ }
+ serialInstance->begin(baud);
+ serialInstance->setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
#elif defined(ARCH_ESP32)
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
@@ -179,8 +194,8 @@ int32_t SerialModule::runOnce()
Serial.begin(baud);
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
}
-#elif !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && \
- !defined(ELECROW_ThinkNode_M5)
+#elif !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \
+ !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
#ifdef ARCH_RP2040
Serial2.setFIFOSize(RX_BUFFER);
@@ -236,18 +251,33 @@ int32_t SerialModule::runOnce()
}
}
-#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && \
- !defined(ELECROW_ThinkNode_M5)
+#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \
+ !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85)) {
processWXSerial();
- } else {
+ }
+#if defined(HELTEC_MESH_SOLAR)
+ else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MS_CONFIG)) {
+ serialPayloadSize = Serial.readBytes(serialBytes, sizeof(serialBytes) - 1);
+ // If the parsing fails, the following parsing will be performed.
+ if ((serialPayloadSize > 0) && (meshSolarCmdHandle(serialBytes) != 0)) {
+ return runOncePart(serialBytes, serialPayloadSize);
+ }
+ }
+#endif
+ else {
#if defined(CONFIG_IDF_TARGET_ESP32C6)
while (Serial1.available()) {
serialPayloadSize = Serial1.readBytes(serialBytes, meshtastic_Constants_DATA_PAYLOAD_LEN);
#else
- while (Serial2.available()) {
- serialPayloadSize = Serial2.readBytes(serialBytes, meshtastic_Constants_DATA_PAYLOAD_LEN);
+#ifndef RAK3172
+ HardwareSerial *serialInstance = &Serial2;
+#else
+ HardwareSerial *serialInstance = &Serial1;
+#endif
+ while (serialInstance->available()) {
+ serialPayloadSize = serialInstance->readBytes(serialBytes, meshtastic_Constants_DATA_PAYLOAD_LEN);
#endif
serialModuleRadio->sendPayload();
}
@@ -496,8 +526,8 @@ ParsedLine parseLine(const char *line)
*/
void SerialModule::processWXSerial()
{
-#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(MESHLINK) && \
- !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
+#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && \
+ !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5) && !defined(ARCH_STM32WL)
static unsigned int lastAveraged = 0;
static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded.
static double dir_sum_sin = 0;
diff --git a/src/modules/SerialModule.h b/src/modules/SerialModule.h
index 1c74c927c..dbe4f75db 100644
--- a/src/modules/SerialModule.h
+++ b/src/modules/SerialModule.h
@@ -8,8 +8,8 @@
#include
#include
-#if (defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040)) && !defined(CONFIG_IDF_TARGET_ESP32S2) && \
- !defined(CONFIG_IDF_TARGET_ESP32C3)
+#if (defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040) || defined(ARCH_STM32WL)) && \
+ !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
class SerialModule : public StreamAPI, private concurrency::OSThread
{
diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp
index 8926b171c..c90d9250f 100644
--- a/src/modules/Telemetry/EnvironmentTelemetry.cpp
+++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp
@@ -198,6 +198,13 @@ T1000xSensor t1000xSensor;
IndicatorSensor indicatorSensor;
#endif
+#if __has_include()
+#include "Sensor/TSL2561Sensor.h"
+TSL2561Sensor tsl2561Sensor;
+#else
+NullSensor tsl2561Sensor;
+#endif
+
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
@@ -296,6 +303,8 @@ int32_t EnvironmentTelemetryModule::runOnce()
result = max17048Sensor.runOnce();
if (cgRadSens.hasSensor())
result = cgRadSens.runOnce();
+ if (tsl2561Sensor.hasSensor())
+ result = tsl2561Sensor.runOnce();
if (pct2075Sensor.hasSensor())
result = pct2075Sensor.runOnce();
// this only works on the wismesh hub with the solar option. This is not an I2C sensor, so we don't need the
@@ -642,6 +651,10 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m
valid = valid && nau7802Sensor.getMetrics(m);
hasSensor = true;
}
+ if (tsl2561Sensor.hasSensor()) {
+ valid = valid && tsl2561Sensor.getMetrics(m);
+ hasSensor = true;
+ }
if (aht10Sensor.hasSensor()) {
if (!bmp280Sensor.hasSensor() && !bmp3xxSensor.hasSensor()) {
valid = valid && aht10Sensor.getMetrics(m);
diff --git a/src/modules/Telemetry/Sensor/TSL2561Sensor.cpp b/src/modules/Telemetry/Sensor/TSL2561Sensor.cpp
new file mode 100644
index 000000000..9f3b7e460
--- /dev/null
+++ b/src/modules/Telemetry/Sensor/TSL2561Sensor.cpp
@@ -0,0 +1,41 @@
+#include "configuration.h"
+
+#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include()
+
+#include "../mesh/generated/meshtastic/telemetry.pb.h"
+#include "TSL2561Sensor.h"
+#include "TelemetrySensor.h"
+#include
+
+TSL2561Sensor::TSL2561Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_TSL2561, "TSL2561") {}
+
+int32_t TSL2561Sensor::runOnce()
+{
+ LOG_INFO("Init sensor: %s", sensorName);
+ if (!hasSensor()) {
+ return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
+ }
+
+ status = tsl.begin(nodeTelemetrySensorsMap[sensorType].second);
+
+ return initI2CSensor();
+}
+
+void TSL2561Sensor::setup()
+{
+ tsl.setGain(TSL2561_GAIN_1X);
+ tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_101MS);
+}
+
+bool TSL2561Sensor::getMetrics(meshtastic_Telemetry *measurement)
+{
+ measurement->variant.environment_metrics.has_lux = true;
+ sensors_event_t event;
+ tsl.getEvent(&event);
+ measurement->variant.environment_metrics.lux = event.light;
+ LOG_INFO("Lux: %f", measurement->variant.environment_metrics.lux);
+
+ return true;
+}
+
+#endif
diff --git a/src/modules/Telemetry/Sensor/TSL2561Sensor.h b/src/modules/Telemetry/Sensor/TSL2561Sensor.h
new file mode 100644
index 000000000..0329becd8
--- /dev/null
+++ b/src/modules/Telemetry/Sensor/TSL2561Sensor.h
@@ -0,0 +1,23 @@
+#include "configuration.h"
+
+#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include()
+
+#include "../mesh/generated/meshtastic/telemetry.pb.h"
+#include "TelemetrySensor.h"
+#include
+
+class TSL2561Sensor : public TelemetrySensor
+{
+ private:
+ // The magic number is a sensor id, the actual value doesn't matter
+ Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_LOW, 12345);
+
+ protected:
+ virtual void setup() override;
+
+ public:
+ TSL2561Sensor();
+ virtual int32_t runOnce() override;
+ virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
+};
+#endif
diff --git a/src/modules/TraceRouteModule.cpp b/src/modules/TraceRouteModule.cpp
index f4eccd667..d7df90bb5 100644
--- a/src/modules/TraceRouteModule.cpp
+++ b/src/modules/TraceRouteModule.cpp
@@ -602,7 +602,7 @@ void TraceRouteModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state
int start = 0;
int newlinePos = resultText.indexOf('\n', start);
- while (newlinePos != -1 || start < resultText.length()) {
+ while (newlinePos != -1 || start < static_cast(resultText.length())) {
String segment;
if (newlinePos != -1) {
segment = resultText.substring(start, newlinePos);
@@ -624,7 +624,7 @@ void TraceRouteModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state
int lastGoodBreak = -1;
bool lineComplete = false;
- for (int i = 0; i < remaining.length(); i++) {
+ for (int i = 0; i < static_cast(remaining.length()); i++) {
char ch = remaining.charAt(i);
String testLine = tempLine + ch;
diff --git a/src/motion/BMX160Sensor.h b/src/motion/BMX160Sensor.h
index d0efa5ae6..ddca5767c 100755
--- a/src/motion/BMX160Sensor.h
+++ b/src/motion/BMX160Sensor.h
@@ -7,7 +7,7 @@
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
-#if defined(RAK_4631) && !defined(RAK2560) && __has_include()
+#if !defined(RAK2560) && __has_include()
#include "Fusion/Fusion.h"
#include
diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp
index 21d4a8fa0..7f7a9d511 100644
--- a/src/mqtt/MQTT.cpp
+++ b/src/mqtt/MQTT.cpp
@@ -95,6 +95,7 @@ inline void onReceiveProto(char *topic, byte *payload, size_t length)
p->hop_start = e.packet->hop_start;
p->want_ack = e.packet->want_ack;
p->via_mqtt = true; // Mark that the packet was received via MQTT
+ p->transport_mechanism = meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MQTT;
p->which_payload_variant = e.packet->which_payload_variant;
memcpy(&p->decoded, &e.packet->decoded, std::max(sizeof(p->decoded), sizeof(p->encrypted)));
@@ -278,6 +279,8 @@ struct PubSubConfig {
// Defaults
static constexpr uint16_t defaultPort = 1883;
+ static constexpr uint16_t defaultPortTls = 8883;
+
uint16_t serverPort = defaultPort;
String serverAddr = default_mqtt_address;
const char *mqttUsername = default_mqtt_username;
@@ -640,7 +643,7 @@ bool MQTT::isValidConfig(const meshtastic_ModuleConfig_MQTTConfig &config, MQTTC
}
const bool defaultServer = isDefaultServer(parsed.serverAddr);
- if (defaultServer && parsed.serverPort != PubSubConfig::defaultPort) {
+ if (defaultServer && !IS_ONE_OF(parsed.serverPort, PubSubConfig::defaultPort, PubSubConfig::defaultPortTls)) {
const char *warning = "Invalid MQTT config: default server address must not have a port specified";
LOG_ERROR(warning);
#if !IS_RUNNING_TESTS
diff --git a/src/nimble/NimbleBluetooth.cpp b/src/nimble/NimbleBluetooth.cpp
index 834184292..95e191c8e 100644
--- a/src/nimble/NimbleBluetooth.cpp
+++ b/src/nimble/NimbleBluetooth.cpp
@@ -223,9 +223,12 @@ void NimbleBluetooth::deinit()
LOG_INFO("Disable bluetooth until reboot");
#ifdef BLE_LED
+#ifdef BLE_LED_INVERTED
+ digitalWrite(BLE_LED, HIGH);
+#else
digitalWrite(BLE_LED, LOW);
#endif
-
+#endif
NimBLEDevice::deinit();
#endif
}
diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h
index 522e862ac..cb0f0dab3 100644
--- a/src/platform/esp32/architecture.h
+++ b/src/platform/esp32/architecture.h
@@ -192,6 +192,8 @@
#define HW_VENDOR meshtastic_HardwareModel_LINK_32
#elif defined(T_DECK_PRO)
#define HW_VENDOR meshtastic_HardwareModel_T_DECK_PRO
+#elif defined(T_LORA_PAGER)
+#define HW_VENDOR meshtastic_HardwareModel_T_LORA_PAGER
#endif
// -----------------------------------------------------------------------------
diff --git a/src/platform/extra_variants/t_lora_pager/variant.cpp b/src/platform/extra_variants/t_lora_pager/variant.cpp
new file mode 100644
index 000000000..ea5773d30
--- /dev/null
+++ b/src/platform/extra_variants/t_lora_pager/variant.cpp
@@ -0,0 +1,27 @@
+#include "configuration.h"
+
+#ifdef T_LORA_PAGER
+
+#include "AudioBoard.h"
+
+DriverPins PinsAudioBoardES8311;
+AudioBoard board(AudioDriverES8311, PinsAudioBoardES8311);
+
+// TLora Pager specific init
+void lateInitVariant()
+{
+ // AudioDriverLogger.begin(Serial, AudioDriverLogLevel::Debug);
+ // I2C: function, scl, sda
+ PinsAudioBoardES8311.addI2C(PinFunction::CODEC, Wire);
+ // I2S: function, mclk, bck, ws, data_out, data_in
+ PinsAudioBoardES8311.addI2S(PinFunction::CODEC, DAC_I2S_MCLK, DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT, DAC_I2S_DIN);
+
+ // configure codec
+ CodecConfig cfg;
+ cfg.input_device = ADC_INPUT_LINE1;
+ cfg.output_device = DAC_OUTPUT_ALL;
+ cfg.i2s.bits = BIT_LENGTH_16BITS;
+ cfg.i2s.rate = RATE_44K;
+ board.begin(cfg);
+}
+#endif
\ No newline at end of file
diff --git a/src/platform/nrf52/architecture.h b/src/platform/nrf52/architecture.h
index 1bbdd77e0..c9938062e 100644
--- a/src/platform/nrf52/architecture.h
+++ b/src/platform/nrf52/architecture.h
@@ -53,10 +53,15 @@
#define HW_VENDOR meshtastic_HardwareModel_WISMESH_TAG
#elif defined(GAT562_MESH_TRIAL_TRACKER)
#define HW_VENDOR meshtastic_HardwareModel_GAT562_MESH_TRIAL_TRACKER
+#elif defined(NOMADSTAR_METEOR_PRO)
+#define HW_VENDOR meshtastic_HardwareModel_NOMADSTAR_METEOR_PRO
+// MAke sure all custom RAK4630 boards are defined before the generic RAK4630
#elif defined(RAK4630)
#define HW_VENDOR meshtastic_HardwareModel_RAK4631
#elif defined(TTGO_T_ECHO)
#define HW_VENDOR meshtastic_HardwareModel_T_ECHO
+#elif defined(T_ECHO_LITE)
+#define HW_VENDOR meshtastic_HardwareModel_T_ECHO_LITE
#elif defined(ELECROW_ThinkNode_M1)
#define HW_VENDOR meshtastic_HardwareModel_THINKNODE_M1
#elif defined(NANO_G2_ULTRA)
@@ -89,12 +94,12 @@
#define HW_VENDOR meshtastic_HardwareModel_SEEED_SOLAR_NODE
#elif defined(HELTEC_MESH_POCKET)
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_POCKET
-#elif defined(NOMADSTAR_METEOR_PRO)
-#define HW_VENDOR meshtastic_HardwareModel_NOMADSTAR_METEOR_PRO
#elif defined(SEEED_WIO_TRACKER_L1_EINK)
#define HW_VENDOR meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1_EINK
#elif defined(SEEED_WIO_TRACKER_L1)
#define HW_VENDOR meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1
+#elif defined(HELTEC_MESH_SOLAR)
+#define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_SOLAR
#else
#define HW_VENDOR meshtastic_HardwareModel_NRF52_UNKNOWN
#endif
diff --git a/src/platform/nrf52/main-nrf52.cpp b/src/platform/nrf52/main-nrf52.cpp
index 1bf9a39fd..8ce74d5f7 100644
--- a/src/platform/nrf52/main-nrf52.cpp
+++ b/src/platform/nrf52/main-nrf52.cpp
@@ -282,10 +282,14 @@ void cpuDeepSleep(uint32_t msecToWake)
#if SPI_INTERFACES_COUNT > 1
SPI1.end();
#endif
- // This may cause crashes as debug messages continue to flow.
- Serial.end();
+ if (Serial) // Another check in case of disabled default serial, does nothing bad
+ Serial.end(); // This may cause crashes as debug messages continue to flow.
+
+ // This causes troubles with waking up on nrf52 (on pro-micro in particular):
+ // we have no Serial1 in use on nrf52, check Serial and GPS modules.
#ifdef PIN_SERIAL1_RX
- Serial1.end();
+ if (Serial1) // A straightforward solution to the wake from deepsleep problem
+ Serial1.end();
#endif
setBluetoothEnable(false);
@@ -319,7 +323,7 @@ void cpuDeepSleep(uint32_t msecToWake)
#endif
#endif
-#ifdef HELTEC_MESH_NODE_T114
+#if defined(HELTEC_MESH_NODE_T114) || defined(HELTEC_MESH_SOLAR)
nrf_gpio_cfg_default(PIN_GPS_PPS);
detachInterrupt(PIN_GPS_PPS);
detachInterrupt(PIN_BUTTON1);
@@ -362,6 +366,7 @@ void cpuDeepSleep(uint32_t msecToWake)
// Resume on user button press
// https://github.com/lyusupov/SoftRF/blob/81c519ca75693b696752235d559e881f2e0511ee/software/firmware/source/SoftRF/src/platform/nRF52.cpp#L1738
constexpr uint32_t DFU_MAGIC_SKIP = 0x6d;
+ sd_power_gpregret_clr(0, 0xFF); // Clear the register before setting a new values in it for stability reasons
sd_power_gpregret_set(0, DFU_MAGIC_SKIP); // Equivalent NRF_POWER->GPREGRET = DFU_MAGIC_SKIP
// FIXME, use system off mode with ram retention for key state?
@@ -378,6 +383,12 @@ void cpuDeepSleep(uint32_t msecToWake)
nrf_gpio_cfg_sense_set(PIN_BUTTON2, sense1);
#endif
+#ifdef PROMICRO_DIY_TCXO
+ nrf_gpio_cfg_input(BUTTON_PIN, NRF_GPIO_PIN_PULLUP); // Enable internal pull-up on the button pin
+ nrf_gpio_pin_sense_t sense = NRF_GPIO_PIN_SENSE_LOW; // Configure SENSE signal on low edge
+ nrf_gpio_cfg_sense_set(BUTTON_PIN, sense); // Apply SENSE to wake up the device from the deep sleep
+#endif
+
auto ok = sd_power_system_off();
if (ok != NRF_SUCCESS) {
LOG_ERROR("FIXME: Ignoring soft device (EasyDMA pending?) and forcing system-off!");
diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp
index 5f99ec2c3..929a45d09 100644
--- a/src/platform/portduino/PortduinoGlue.cpp
+++ b/src/platform/portduino/PortduinoGlue.cpp
@@ -10,6 +10,7 @@
#include "linux/gpio/LinuxGPIOPin.h"
#include "meshUtils.h"
#include "yaml-cpp/yaml.h"
+#include
#include
#include
#include
@@ -29,11 +30,11 @@
std::map settingsMap;
std::map settingsStrings;
+portduino_config_struct portduino_config;
std::ofstream traceFile;
Ch341Hal *ch341Hal = nullptr;
char *configPath = nullptr;
char *optionMac = nullptr;
-bool forceSimulated = false;
bool verboseEnabled = false;
const char *argp_program_version = optstr(APP_VERSION);
@@ -66,7 +67,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
configPath = arg;
break;
case 's':
- forceSimulated = true;
+ portduino_config.force_simradio = true;
break;
case 'h':
optionMac = arg;
@@ -189,7 +190,7 @@ void portduinoSetup()
YAML::Node yamlConfig;
- if (forceSimulated == true) {
+ if (portduino_config.force_simradio == true) {
settingsMap[use_simradio] = true;
} else if (configPath != nullptr) {
if (loadConfig(configPath)) {
@@ -253,16 +254,95 @@ void portduinoSetup()
std::cout << "autoconf: Could not locate CH341 device" << std::endl;
}
// Try Pi HAT+
- std::cout << "autoconf: Looking for Pi HAT+..." << std::endl;
- if (access("/proc/device-tree/hat/product", R_OK) == 0) {
- std::ifstream hatProductFile("/proc/device-tree/hat/product");
- if (hatProductFile.is_open()) {
- hatProductFile.read(autoconf_product, 95);
- hatProductFile.close();
+ if (strlen(autoconf_product) < 6) {
+ std::cout << "autoconf: Looking for Pi HAT+..." << std::endl;
+ if (access("/proc/device-tree/hat/product", R_OK) == 0) {
+ std::ifstream hatProductFile("/proc/device-tree/hat/product");
+ if (hatProductFile.is_open()) {
+ hatProductFile.read(autoconf_product, 95);
+ hatProductFile.close();
+ }
+ std::cout << "autoconf: Found Pi HAT+ " << autoconf_product << " at /proc/device-tree/hat/product" << std::endl;
+ } else {
+ std::cout << "autoconf: Could not locate Pi HAT+ at /proc/device-tree/hat/product" << std::endl;
+ }
+ }
+ // attempt to load autoconf data from an EEPROM on 0x50
+ // RAK6421-13300-S1:aabbcc123456:5ba85807d92138b7519cfb60460573af:3061e8d8
+ // :mac address :<16 random unique bytes in hexidecimal> : crc32
+ // crc32 is calculated on the eeprom string up to but not including the final colon
+ if (strlen(autoconf_product) < 6) {
+ try {
+ char *mac_start = nullptr;
+ char *devID_start = nullptr;
+ char *crc32_start = nullptr;
+ Wire.begin();
+ Wire.beginTransmission(0x50);
+ Wire.write(0x0);
+ Wire.write(0x0);
+ Wire.endTransmission();
+ Wire.requestFrom((uint8_t)0x50, (uint8_t)75);
+ uint8_t i = 0;
+ delay(100);
+ std::string autoconf_raw;
+ while (Wire.available() && i < sizeof(autoconf_product)) {
+ autoconf_product[i] = Wire.read();
+ if (autoconf_product[i] == 0xff) {
+ autoconf_product[i] = 0x0;
+ break;
+ }
+ autoconf_raw += autoconf_product[i];
+ if (autoconf_product[i] == ':') {
+ autoconf_product[i] = 0x0;
+ if (mac_start == nullptr) {
+ mac_start = autoconf_product + i + 1;
+ } else if (devID_start == nullptr) {
+ devID_start = autoconf_product + i + 1;
+ } else if (crc32_start == nullptr) {
+ crc32_start = autoconf_product + i + 1;
+ }
+ }
+ i++;
+ }
+ if (crc32_start != nullptr && strlen(crc32_start) == 8) {
+ std::string crc32_str(crc32_start);
+ uint32_t crc32_value = 0;
+
+ // convert crc32 ascii to raw uint32
+ for (int j = 0; j < 4; j++) {
+ crc32_value += std::stoi(crc32_str.substr(j * 2, 2), nullptr, 16) << (3 - j) * 8;
+ }
+ std::cout << "autoconf: Found eeprom crc " << crc32_start << std::endl;
+
+ // set the autoconf string to blank and short circuit
+ if (crc32_value != crc32Buffer(autoconf_raw.c_str(), i - 9)) {
+ std::cout << "autoconf: crc32 mismatch, dropping " << std::endl;
+ autoconf_product[0] = 0x0;
+ } else {
+ std::cout << "autoconf: Found eeprom data " << autoconf_raw << std::endl;
+ if (mac_start != nullptr) {
+ std::cout << "autoconf: Found mac data " << mac_start << std::endl;
+ if (strlen(mac_start) == 12)
+ settingsStrings[mac_address] = std::string(mac_start);
+ }
+ if (devID_start != nullptr) {
+ std::cout << "autoconf: Found deviceid data " << devID_start << std::endl;
+ if (strlen(devID_start) == 32) {
+ std::string devID_str(devID_start);
+ for (int j = 0; j < 16; j++) {
+ portduino_config.device_id[j] = std::stoi(devID_str.substr(j * 2, 2), nullptr, 16);
+ }
+ portduino_config.has_device_id = true;
+ }
+ }
+ }
+ } else {
+ std::cout << "autoconf: crc32 missing " << std::endl;
+ autoconf_product[0] = 0x0;
+ }
+ } catch (...) {
+ std::cout << "autoconf: Could not locate EEPROM" << std::endl;
}
- std::cout << "autoconf: Found Pi HAT+ " << autoconf_product << " at /proc/device-tree/hat/product" << std::endl;
- } else {
- std::cout << "autoconf: Could not locate Pi HAT+ at /proc/device-tree/hat/product" << std::endl;
}
// Load the config file based on the product string
if (strlen(autoconf_product) > 0) {
@@ -553,6 +633,48 @@ bool loadConfig(const char *configPath)
}
}
}
+ if (yamlConfig["Lora"]["rfswitch_table"]) {
+ portduino_config.has_rfswitch_table = true;
+ portduino_config.rfswitch_table[0].mode = LR11x0::MODE_STBY;
+ portduino_config.rfswitch_table[1].mode = LR11x0::MODE_RX;
+ portduino_config.rfswitch_table[2].mode = LR11x0::MODE_TX;
+ portduino_config.rfswitch_table[3].mode = LR11x0::MODE_TX_HP;
+ portduino_config.rfswitch_table[4].mode = LR11x0::MODE_TX_HF;
+ portduino_config.rfswitch_table[5].mode = LR11x0::MODE_GNSS;
+ portduino_config.rfswitch_table[6].mode = LR11x0::MODE_WIFI;
+ portduino_config.rfswitch_table[7] = END_OF_MODE_TABLE;
+
+ for (int i = 0; i < 5; i++) {
+
+ // set up the pin array first
+ if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as("") == "DIO5")
+ portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO5;
+ if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as("") == "DIO6")
+ portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO6;
+ if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as("") == "DIO7")
+ portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO7;
+ if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as("") == "DIO8")
+ portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO8;
+ if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as("") == "DIO10")
+ portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO10;
+
+ // now fill in the table
+ if (yamlConfig["Lora"]["rfswitch_table"]["MODE_STBY"][i].as("") == "HIGH")
+ portduino_config.rfswitch_table[0].values[i] = HIGH;
+ if (yamlConfig["Lora"]["rfswitch_table"]["MODE_RX"][i].as("") == "HIGH")
+ portduino_config.rfswitch_table[1].values[i] = HIGH;
+ if (yamlConfig["Lora"]["rfswitch_table"]["MODE_TX"][i].as("") == "HIGH")
+ portduino_config.rfswitch_table[2].values[i] = HIGH;
+ if (yamlConfig["Lora"]["rfswitch_table"]["MODE_TX_HP"][i].as("") == "HIGH")
+ portduino_config.rfswitch_table[3].values[i] = HIGH;
+ if (yamlConfig["Lora"]["rfswitch_table"]["MODE_TX_HF"][i].as("") == "HIGH")
+ portduino_config.rfswitch_table[4].values[i] = HIGH;
+ if (yamlConfig["Lora"]["rfswitch_table"]["MODE_GNSS"][i].as("") == "HIGH")
+ portduino_config.rfswitch_table[5].values[i] = HIGH;
+ if (yamlConfig["Lora"]["rfswitch_table"]["MODE_WIFI"][i].as("") == "HIGH")
+ portduino_config.rfswitch_table[6].values[i] = HIGH;
+ }
+ }
}
if (yamlConfig["GPIO"]) {
settingsMap[userButtonPin] = yamlConfig["GPIO"]["User"].as(RADIOLIB_NC);
diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h
index 288870eef..8c36a1180 100644
--- a/src/platform/portduino/PortduinoGlue.h
+++ b/src/platform/portduino/PortduinoGlue.h
@@ -3,16 +3,21 @@
#include