From c6efccdbd2a1f27766904c7247b4ff414712f7b3 Mon Sep 17 00:00:00 2001 From: pdxlocations Date: Fri, 29 Aug 2025 23:11:26 -0700 Subject: [PATCH 1/2] init --- meshtastic/__main__.py | 20 +++++++++++++------- meshtastic/node.py | 27 +++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/meshtastic/__main__.py b/meshtastic/__main__.py index b58cc66b..8114fec6 100644 --- a/meshtastic/__main__.py +++ b/meshtastic/__main__.py @@ -59,7 +59,7 @@ have_powermon = False powermon_exception = e meter = None -from meshtastic.protobuf import channel_pb2, config_pb2, portnums_pb2 +from meshtastic.protobuf import channel_pb2, config_pb2, portnums_pb2, mesh_pb2 from meshtastic.version import get_active_version def onReceive(packet, interface) -> None: @@ -377,16 +377,22 @@ def onConnected(interface): if args.set_canned_message: closeNow = True waitForAckNak = True - print(f"Setting canned plugin message to {args.set_canned_message}") - interface.getNode(args.dest, False, **getNode_kwargs).set_canned_message( - args.set_canned_message - ) + node = interface.getNode(args.dest, False, **getNode_kwargs) + if node.module_available(mesh_pb2.CANNEDMSG_CONFIG): + print(f"Setting canned plugin message to {args.set_canned_message}") + node.set_canned_message(args.set_canned_message) + else: + print("Canned Message module is excluded by firmware; skipping set.") if args.set_ringtone: closeNow = True waitForAckNak = True - print(f"Setting ringtone to {args.set_ringtone}") - interface.getNode(args.dest, False, **getNode_kwargs).set_ringtone(args.set_ringtone) + node = interface.getNode(args.dest, False, **getNode_kwargs) + if node.module_available(mesh_pb2.EXTNOTIF_CONFIG): + print(f"Setting ringtone to {args.set_ringtone}") + node.set_ringtone(args.set_ringtone) + else: + print("External Notification is excluded by firmware; skipping ringtone set.") if args.pos_fields: # If --pos-fields invoked with args, set position fields diff --git a/meshtastic/node.py b/meshtastic/node.py index e6bd3ca6..b8144303 100644 --- a/meshtastic/node.py +++ b/meshtastic/node.py @@ -51,6 +51,16 @@ def __repr__(self): r += ")" return r + def module_available(self, excluded_bit: int) -> bool: + """Check DeviceMetadata.excluded_modules to see if a module is available.""" + meta = getattr(self.iface, "metadata", None) + if meta is None: + return True + try: + return (meta.excluded_modules & excluded_bit) == 0 + except Exception: + return True + def showChannels(self): """Show human readable description of our channels.""" print("Channels:") @@ -441,6 +451,10 @@ def onResponseRequestRingtone(self, p): def get_ringtone(self): """Get the ringtone. Concatenate all pieces together and return a single string.""" logging.debug(f"in get_ringtone()") + if not self.module_available(mesh_pb2.EXTNOTIF_CONFIG): + logging.warning("External Notification module not present (excluded by firmware)") + return None + if not self.ringtone: p1 = admin_pb2.AdminMessage() p1.get_ringtone_request = True @@ -462,7 +476,10 @@ def get_ringtone(self): def set_ringtone(self, ringtone): """Set the ringtone. The ringtone length must be less than 230 character.""" - + if not self.module_available(mesh_pb2.EXTNOTIF_CONFIG): + logging.warning("External Notification module not present (excluded by firmware)") + return None + if len(ringtone) > 230: our_exit("Warning: The ringtone must be less than 230 characters.") self.ensureSessionKey() @@ -512,6 +529,9 @@ def onResponseRequestCannedMessagePluginMessageMessages(self, p): def get_canned_message(self): """Get the canned message string. Concatenate all pieces together and return a single string.""" logging.debug(f"in get_canned_message()") + if not self.module_available(mesh_pb2.CANNEDMSG_CONFIG): + logging.warning("Canned Message module not present (excluded by firmware)") + return None if not self.cannedPluginMessage: p1 = admin_pb2.AdminMessage() p1.get_canned_message_module_messages_request = True @@ -537,7 +557,10 @@ def get_canned_message(self): def set_canned_message(self, message): """Set the canned message. The canned messages length must be less than 200 character.""" - + if not self.module_available(mesh_pb2.CANNEDMSG_CONFIG): + logging.warning("Canned Message module not present (excluded by firmware)") + return None + if len(message) > 200: our_exit("Warning: The canned message must be less than 200 characters.") self.ensureSessionKey() From 7e3d347b63644297691d3f02be48a325ac28ed62 Mon Sep 17 00:00:00 2001 From: pdxlocations Date: Fri, 29 Aug 2025 23:19:22 -0700 Subject: [PATCH 2/2] remove trailing whitespaces --- meshtastic/node.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/meshtastic/node.py b/meshtastic/node.py index b8144303..8c4a6951 100644 --- a/meshtastic/node.py +++ b/meshtastic/node.py @@ -454,7 +454,7 @@ def get_ringtone(self): if not self.module_available(mesh_pb2.EXTNOTIF_CONFIG): logging.warning("External Notification module not present (excluded by firmware)") return None - + if not self.ringtone: p1 = admin_pb2.AdminMessage() p1.get_ringtone_request = True @@ -479,7 +479,7 @@ def set_ringtone(self, ringtone): if not self.module_available(mesh_pb2.EXTNOTIF_CONFIG): logging.warning("External Notification module not present (excluded by firmware)") return None - + if len(ringtone) > 230: our_exit("Warning: The ringtone must be less than 230 characters.") self.ensureSessionKey() @@ -560,7 +560,7 @@ def set_canned_message(self, message): if not self.module_available(mesh_pb2.CANNEDMSG_CONFIG): logging.warning("Canned Message module not present (excluded by firmware)") return None - + if len(message) > 200: our_exit("Warning: The canned message must be less than 200 characters.") self.ensureSessionKey()