diff --git a/README.md b/README.md
@@ -29,6 +29,8 @@ The goal here is to create simple & clean modules to interface with the hardware
- Documentation on MQTT bridging for high availability
- Bridge for IRC to allow channel messages to relay over Meshtastic & all Meshtastic events to relay into IRC. *(IRC to Meshtastic will require a command like `!mesh <message here>` to avoid overloading the traffic over LoRa)*
+## Notes
+- [Meshtastic PortNum List](https://buf.build/meshtastic/protobufs/docs/main:meshtastic#meshtastic.PortNum)
___
###### Mirrors for this repository: [acid.vegas](https://git.acid.vegas/meshtastic) • [SuperNETs](https://git.supernets.org/acidvegas/meshtastic) • [GitHub](https://github.com/acidvegas/meshtastic) • [GitLab](https://gitlab.com/acidvegas/meshtastic) • [Codeberg](https://codeberg.org/acidvegas/meshtastic)
\ No newline at end of file
diff --git a/docs/FIRMWARE.md b/docs/FIRMWARE.md
@@ -32,6 +32,35 @@ You can use the provided [icon.xbm](../assets/icon.xbm) for a rad GTA:SA fist to
As far as I know, at the time of writing this, the only way to change the Ringtone is from the App. While this is not a "firmware" related thing, I included it in this file because it was difficult to find this setting...
+###### Display RAM/PSRAM Usage
+Look for these lines:
+```cpp
+ display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName));
+ display->drawString(x, y + FONT_HEIGHT_SMALL * 3, "http://meshtastic.local");
+```
+
+And place the follow code AFTER the above lines:
+
+```cpp
+// Display memory usage using the MemGet class
+uint32_t freeHeap = memGet.getFreeHeap();
+uint32_t totalHeap = memGet.getHeapSize();
+uint32_t usedHeap = totalHeap - freeHeap;
+display->drawString(x, y + FONT_HEIGHT_SMALL * 4, "Heap: " + String(usedHeap / 1024) + "/" + String(totalHeap / 1024) + " KB");
+
+// Display PSRAM usage using the MemGet class
+uint32_t freePsram = memGet.getFreePsram();
+uint32_t totalPsram = memGet.getPsramSize();
+uint32_t usedPsram = totalPsram - freePsram;
+display->drawString(x, y + FONT_HEIGHT_SMALL * 5, "PSRAM: " + String(usedPsram / 1024) + "/" + String(totalPsram / 1024) + " KB");
+```
+
+###### Heartbeat for redraw
+- Uncomment the line that says: `#define SHOW_REDRAWS`
+
+This will show a little 1x1 pixel on the top left corner anytime the screen is redraw.
+
+
## Compile & flash firmware
- Select `PlatformIO: Pick Project Environment` & select your board.
- Run `PLatformIO: Build` to compile the firmware.
diff --git a/meshmqtt.py b/meshmqtt.py
@@ -26,11 +26,21 @@ except ImportError:
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %I:%M:%S')
+def clean_dict(dictionary: dict) -> dict:
+ '''
+ Remove empty fields from a dictionary.
+
+ :param dictionary: The dictionary to remove empty fields from
+ '''
+
+ return {key: value for key, value in dictionary.items() if value}
+
+
class MeshtasticMQTT(object):
def __init__(self):
'''Initialize the Meshtastic MQTT client'''
- self.broadcast_id = 4294967295
+ self.broadcast_id = 4294967295 # Our channel ID
self.key = None
@@ -148,6 +158,18 @@ class MeshtasticMQTT(object):
if message_packet.HasField('encrypted') and not message_packet.HasField('decoded'):
message_packet = self.decrypt_message_packet(message_packet)
+ text = {
+ 'from' : getattr(message_packet, 'from'),
+ 'to' : getattr(message_packet, 'to'),
+ 'channel' : getattr(message_packet, 'channel'),
+ 'id' : getattr(message_packet, 'id'),
+ 'rx_time' : getattr(message_packet, 'rx_time'),
+ 'hop_limit' : getattr(message_packet, 'hop_limit'),
+ 'priority' : getattr(message_packet, 'priority'),
+ 'hop_start' : getattr(message_packet, 'hop_start')
+ }
+ logging.info(text)
+
if message_packet.decoded.portnum == portnums_pb2.UNKNOWN_APP:
logging.warning('Received an unknown app message:')
logging.info(message_packet)
@@ -172,14 +194,40 @@ class MeshtasticMQTT(object):
elif message_packet.decoded.portnum == portnums_pb2.POSITION_APP:
data = mesh_pb2.Position()
data.ParseFromString(message_packet.decoded.payload)
+
+ data_dict = {key: value for key, value in data}
+ print(data_dict)
+
logging.info('Received position:')
- logging.info(data)
+ loc = {
+ 'lattitude' : getattr(data, 'latitude_i') / 1e7,
+ 'longitude' : getattr(data, 'longitude_i') / 1e7,
+ 'altitude' : getattr(data, 'altitude') / 1000,
+ 'location_source' : getattr(data, 'location_source'),
+ 'altitude_source' : getattr(data, 'altitude_source'),
+ 'pdop' : getattr(data, 'PDOP'),
+ 'hdop' : getattr(data, 'HDOP'),
+ 'vdop' : getattr(data, 'VDOP'),
+ 'gps_accuracy' : getattr(data, 'gps_accuracy'),
+ 'ground_speed' : getattr(data, 'ground_speed'),
+ 'ground_track' : getattr(data, 'ground_track'),
+ 'fix_quality' : getattr(data, 'fix_quality'),
+ 'fix_type' : getattr(data, 'fix_type'),
+ 'sats_in_view' : getattr(data, 'sats_in_view'),
+ 'sensor_id' : getattr(data, 'sensor_id'),
+ 'next_update' : getattr(data, 'next_update'),
+ 'seq_number' : getattr(data, 'seq_number'),
+ 'precision_bits' : getattr(data, 'precision_bits')
+ }
+
+ if (loc := clean_dict(loc)):
+ logging.info(loc)
elif message_packet.decoded.portnum == portnums_pb2.NODEINFO_APP:
data = mesh_pb2.NodeInfo()
- data.ParseFromString(message_packet.decoded.payload)
+ #data.ParseFromString(message_packet.decoded.payload)
logging.info('Received node info:')
- logging.info(data)
+ logging.info(message_packet)
elif message_packet.decoded.portnum == portnums_pb2.ROUTING_APP:
data = mesh_pb2.Routing()
@@ -242,10 +290,9 @@ class MeshtasticMQTT(object):
logging.info(data)
elif message_packet.decoded.portnum == portnums_pb2.STORE_FORWARD_APP:
- data = mesh_pb2.StoreForward()
- data.ParseFromString(message_packet.decoded.payload)
logging.info('Received store and forward:')
- logging.info(data)
+ logging.info(message_packet)
+ logging.info(message_packet.decoded.payload)
elif message_packet.decoded.portnum == portnums_pb2.RANGE_TEST_APP:
data = mesh_pb2.RangeTest()
@@ -257,7 +304,34 @@ class MeshtasticMQTT(object):
data = telemetry_pb2.Telemetry()
data.ParseFromString(message_packet.decoded.payload)
logging.info('Received telemetry:')
- logging.info(data)
+
+ data_dict = {key: value for key, value in data}
+ print(data_dict)
+
+ if getattr(data, 'device_metrics'):
+ text = {
+ 'battery_level' : getattr(data.device_metrics, 'battery_level'),
+ 'voltage' : getattr(data.device_metrics, 'voltage'),
+ 'channel_utilization' : getattr(data.device_metrics, 'channel_utilization'),
+ 'air_util_tx' : getattr(data.device_metrics, 'air_util_tx'),
+ 'uptime_seconds' : getattr(data.device_metrics, 'uptime_seconds')
+ }
+ if (text := clean_dict(text)):
+ logging.info(text)
+
+ if getattr(data, 'environment_metrics'):
+ env_metrics = {
+ 'barometric_pressure' : getattr(data.environment_metrics, 'barometric_pressure'),
+ 'current' : getattr(data.environment_metrics, 'current'),
+ 'distance' : getattr(data.environment_metrics, 'distance'),
+ 'gas_resistance' : getattr(data.environment_metrics, 'gas_resistance'),
+ 'iaq' : getattr(data.environment_metrics, 'iaq'),
+ 'relative_humidity' : getattr(data.environment_metrics, 'relative_humidity'),
+ 'temperature' : getattr(data.environment_metrics, 'temperature'),
+ 'voltage' : getattr(data.environment_metrics, 'voltage')
+ }
+ if (env_metrics := clean_dict(env_metrics)):
+ logging.info(env_metrics)
elif message_packet.decoded.portnum == portnums_pb2.ZPS_APP:
data = mesh_pb2.Zps()
@@ -281,7 +355,13 @@ class MeshtasticMQTT(object):
neighborInfo = mesh_pb2.NeighborInfo()
neighborInfo.ParseFromString(message_packet.decoded.payload)
logging.info('Received neighbor info:')
- logging.info(neighborInfo)
+ info = {
+ 'node_id' : getattr(neighborInfo, 'node_id'),
+ 'last_sent_by_id' : getattr(neighborInfo, 'last_sent_by_id'),
+ 'node_broadcast_interval_secs' : getattr(neighborInfo, 'node_broadcast_interval_secs'),
+ 'neighbors' : getattr(neighborInfo, 'neighbors')
+ }
+ logging.info(info)
elif message_packet.decoded.portnum == portnums_pb2.ATAK_PLUGIN:
data = mesh_pb2.AtakPlugin()
@@ -312,6 +392,7 @@ class MeshtasticMQTT(object):
pos.ParseFromString(message_packet.decoded.payload)
logging.info('Received map report:')
logging.info(pos)
+
else:
logging.warning('Received an unencrypted message')
logging.info(f'Payload: {message_packet}')
| | |