Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-meshtastic for openSUSE:Factory checked in at 2025-03-07 16:44:51 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-meshtastic (Old) and /work/SRC/openSUSE:Factory/.python-meshtastic.new.19136 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-meshtastic" Fri Mar 7 16:44:51 2025 rev:2 rq:1251149 version:2.5.12 Changes: -------- --- /work/SRC/openSUSE:Factory/python-meshtastic/python-meshtastic.changes 2025-02-21 21:36:15.395961139 +0100 +++ /work/SRC/openSUSE:Factory/.python-meshtastic.new.19136/python-meshtastic.changes 2025-03-07 16:48:50.554192496 +0100 @@ -1,0 +2,11 @@ +Thu Mar 6 11:28:09 UTC 2025 - Adrian Schröter <adr...@suse.de> + +- update to version 2.5.12 + * Added descriptive FileNotFoundError handler for serial device connection + * catch unhandled OSError when serial port in use + * Add optional CLI parameter to specify node info fields to show with --nodes parameter. + * 464: allow for 0x node prefix values + * Add text message port cli option + * Add new channels from an add URL with the new --ch-add-url option + +------------------------------------------------------------------- Old: ---- meshtastic-2.5.11.tar.gz New: ---- meshtastic-2.5.12.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-meshtastic.spec ++++++ --- /var/tmp/diff_new_pack.ZrofLi/_old 2025-03-07 16:48:51.066214105 +0100 +++ /var/tmp/diff_new_pack.ZrofLi/_new 2025-03-07 16:48:51.066214105 +0100 @@ -17,7 +17,7 @@ Name: python-meshtastic -Version: 2.5.11 +Version: 2.5.12 Release: 0 Summary: A Python client for use with Meshtastic devices License: GPL-3.0-only ++++++ meshtastic-2.5.11.tar.gz -> meshtastic-2.5.12.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/meshtastic-2.5.11/PKG-INFO new/meshtastic-2.5.12/PKG-INFO --- old/meshtastic-2.5.11/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 +++ new/meshtastic-2.5.12/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.3 Name: meshtastic -Version: 2.5.11 +Version: 2.5.12 Summary: Python API & client shell for talking to Meshtastic devices License: GPL-3.0-only Author: Meshtastic Developers diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/meshtastic-2.5.11/meshtastic/__main__.py new/meshtastic-2.5.12/meshtastic/__main__.py --- old/meshtastic-2.5.11/meshtastic/__main__.py 1970-01-01 01:00:00.000000000 +0100 +++ new/meshtastic-2.5.12/meshtastic/__main__.py 1970-01-01 01:00:00.000000000 +0100 @@ -11,7 +11,7 @@ import argparse argcomplete: Union[None, ModuleType] = None try: - import argcomplete + import argcomplete # type: ignore except ImportError as e: pass # already set to None by default above @@ -226,7 +226,7 @@ logging.debug(f"valStr:{raw_val} val:{val}") if snake_name == "wifi_psk" and len(str(raw_val)) < 8: - print(f"Warning: network.wifi_psk must be 8 or more characters.") + print("Warning: network.wifi_psk must be 8 or more characters.") return False enumType = pref.enum_type @@ -483,6 +483,7 @@ if checkChannel(interface, channelIndex): print( f"Sending text message {args.sendtext} to {args.dest} on channelIndex:{channelIndex}" + f" {'using PRIVATE_APP port' if args.private else ''}" ) interface.sendText( args.sendtext, @@ -490,6 +491,7 @@ wantAck=True, channelIndex=channelIndex, onResponse=interface.getNode(args.dest, False, **getNode_kwargs).onAckNak, + portNum=portnums_pb2.PortNum.PRIVATE_APP if args.private else portnums_pb2.PortNum.TEXT_MESSAGE_APP ) else: meshtastic.util.our_exit( @@ -714,12 +716,16 @@ closeNow = True export_config(interface) - if args.seturl: + if args.ch_set_url: closeNow = True - interface.getNode(args.dest, **getNode_kwargs).setURL(args.seturl) + interface.getNode(args.dest, **getNode_kwargs).setURL(args.ch_set_url, addOnly=False) # handle changing channels + if args.ch_add_url: + closeNow = True + interface.getNode(args.dest, **getNode_kwargs).setURL(args.ch_add_url, addOnly=True) + if args.ch_add: channelIndex = mt_config.channel_index if channelIndex is not None: @@ -921,7 +927,11 @@ if args.dest != BROADCAST_ADDR: print("Showing node list of a remote node is not supported.") return - interface.showNodes() + interface.showNodes(True, args.show_fields) + + if args.show_fields and not args.nodes: + print("--show-fields can only be used with --nodes") + return if args.qr or args.qr_all: closeNow = True @@ -1245,6 +1255,19 @@ noProto=args.noproto, noNodes=args.no_nodes, ) + except FileNotFoundError: + # Handle the case where the serial device is not found + message = ( + f"File Not Found Error:\n" + ) + message += f" The serial device at '{args.port}' was not found.\n" + message += " Please check the following:\n" + message += " 1. Is the device connected properly?\n" + message += " 2. Is the correct serial port specified?\n" + message += " 3. Are the necessary drivers installed?\n" + message += " 4. Are you using a **power-only USB cable**? A power-only cable cannot transmit data.\n" + message += " Ensure you are using a **data-capable USB cable**.\n" + meshtastic.util.our_exit(message, 1) except PermissionError as ex: username = os.getlogin() message = "Permission Error:\n" @@ -1255,6 +1278,12 @@ message += " After running that command, log out and re-login for it to take effect.\n" message += f"Error was:{ex}" meshtastic.util.our_exit(message) + except OSError as ex: + message = f"OS Error:\n" + message += " The serial device couldn't be opened, it might be in use by another process.\n" + message += " Please close any applications or webpages that may be using the device and try again.\n" + message += f"\nOriginal error: {ex}" + meshtastic.util.our_exit(message) if client.devPath is None: try: client = meshtastic.tcp_interface.TCPInterface( @@ -1342,7 +1371,8 @@ group.add_argument( "--dest", - help="The destination node id for any sent commands, if not set '^all' or '^local' is assumed as appropriate", + help="The destination node id for any sent commands. If not set '^all' or '^local' is assumed." + "Use the node ID with a '!' or '0x' prefix or the node number.", default=None, metavar="!xxxxxxxx", ) @@ -1489,7 +1519,20 @@ "--set-ham", help="Set licensed Ham ID and turn off encryption", action="store" ) - group.add_argument("--seturl", help="Set a channel URL", action="store") + group.add_argument( + "--ch-set-url", "--seturl", + help="Set all channels and set LoRa config from a supplied URL", + metavar="URL", + action="store" + ) + + group.add_argument( + "--ch-add-url", + help="Add secondary channels and set LoRa config from a supplied URL", + metavar="URL", + default=None, + ) + return parser @@ -1627,6 +1670,13 @@ action="store_true", ) + group.add_argument( + "--show-fields", + help="Specify fields to show (comma-separated) when using --nodes", + type=lambda s: s.split(','), + default=None + ) + return parser def addRemoteActionArgs(parser: argparse.ArgumentParser) -> argparse.ArgumentParser: @@ -1638,15 +1688,21 @@ group.add_argument( "--sendtext", - help="Send a text message. Can specify a destination '--dest' and/or channel index '--ch-index'.", + help="Send a text message. Can specify a destination '--dest', use of PRIVATE_APP port '--private', and/or channel index '--ch-index'.", metavar="TEXT", ) group.add_argument( + "--private", + help="Optional argument for sending text messages to the PRIVATE_APP port. Use in combination with --sendtext.", + action="store_true" + ) + + group.add_argument( "--traceroute", help="Traceroute from connected node to a destination. " "You need pass the destination ID as argument, like " - "this: '--traceroute !ba4bf9d0' " + "this: '--traceroute !ba4bf9d0' | '--traceroute 0xba4bf9d0'" "Only nodes with a shared channel can be traced.", metavar="!xxxxxxxx", ) @@ -1727,27 +1783,32 @@ group.add_argument( "--remove-node", - help="Tell the destination node to remove a specific node from its DB, by node number or ID", + help="Tell the destination node to remove a specific node from its NodeDB. " + "Use the node ID with a '!' or '0x' prefix or the node number.", metavar="!xxxxxxxx" ) group.add_argument( "--set-favorite-node", - help="Tell the destination node to set the specified node to be favorited on the NodeDB on the devicein its DB, by number or ID", + help="Tell the destination node to set the specified node to be favorited on the NodeDB. " + "Use the node ID with a '!' or '0x' prefix or the node number.", metavar="!xxxxxxxx" ) group.add_argument( "--remove-favorite-node", - help="Tell the destination node to set the specified node to be un-favorited on the NodeDB on the device, by number or ID", + help="Tell the destination node to set the specified node to be un-favorited on the NodeDB. " + "Use the node ID with a '!' or '0x' prefix or the node number.", metavar="!xxxxxxxx" ) group.add_argument( "--set-ignored-node", - help="Tell the destination node to set the specified node to be ignored on the NodeDB on the devicein its DB, by number or ID", + help="Tell the destination node to set the specified node to be ignored on the NodeDB. " + "Use the node ID with a '!' or '0x' prefix or the node number.", metavar="!xxxxxxxx" ) group.add_argument( "--remove-ignored-node", - help="Tell the destination node to set the specified node to be un-ignored on the NodeDB on the device, by number or ID", + help="Tell the destination node to set the specified node to be un-ignored on the NodeDB. " + "Use the node ID with a '!' or '0x' prefix or the node number.", metavar="!xxxxxxxx" ) group.add_argument( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/meshtastic-2.5.11/meshtastic/mesh_interface.py new/meshtastic-2.5.12/meshtastic/mesh_interface.py --- old/meshtastic-2.5.11/meshtastic/mesh_interface.py 1970-01-01 01:00:00.000000000 +0100 +++ new/meshtastic-2.5.12/meshtastic/mesh_interface.py 1970-01-01 01:00:00.000000000 +0100 @@ -222,9 +222,42 @@ return infos def showNodes( - self, includeSelf: bool = True + self, includeSelf: bool = True, showFields: Optional[List[str]] = None ) -> str: # pylint: disable=W0613 - """Show table summary of nodes in mesh""" + """Show table summary of nodes in mesh + + Args: + includeSelf (bool): Include ourself in the output? + showFields (List[str]): List of fields to show in output + """ + + def get_human_readable(name): + name_map = { + "user.longName": "User", + "user.id": "ID", + "user.shortName": "AKA", + "user.hwModel": "Hardware", + "user.publicKey": "Pubkey", + "user.role": "Role", + "position.latitude": "Latitude", + "position.longitude": "Longitude", + "position.altitude": "Altitude", + "deviceMetrics.batteryLevel": "Battery", + "deviceMetrics.channelUtilization": "Channel util.", + "deviceMetrics.airUtilTx": "Tx air util.", + "snr": "SNR", + "hopsAway": "Hops", + "channel": "Channel", + "lastHeard": "LastHeard", + "since": "Since", + + } + + if name in name_map: + return name_map.get(name) # Default to a formatted guess + else: + return name + def formatFloat(value, precision=2, unit="") -> Optional[str]: """Format a float value with precision.""" @@ -246,6 +279,29 @@ return None # not handling a timestamp from the future return _timeago(delta_secs) + def getNestedValue(node_dict: Dict[str, Any], key_path: str) -> Any: + if key_path.index(".") < 0: + logging.debug("getNestedValue was called without a nested path.") + return None + keys = key_path.split(".") + value: Optional[Union[str, dict]] = node_dict + for key in keys: + if isinstance(value, dict): + value = value.get(key) + else: + return None + return value + + if showFields is None or len(showFields) == 0: + # The default set of fields to show (e.g., the status quo) + showFields = ["N", "user.longName", "user.id", "user.shortName", "user.hwModel", "user.publicKey", + "user.role", "position.latitude", "position.longitude", "position.altitude", + "deviceMetrics.batteryLevel", "deviceMetrics.channelUtilization", + "deviceMetrics.airUtilTx", "snr", "hopsAway", "channel", "lastHeard", "since"] + else: + # Always at least include the row number. + showFields.insert(0, "N") + rows: List[Dict[str, Any]] = [] if self.nodesByNum: logging.debug(f"self.nodes:{self.nodes}") @@ -254,66 +310,60 @@ continue presumptive_id = f"!{node['num']:08x}" - row = { - "N": 0, - "User": f"Meshtastic {presumptive_id[-4:]}", - "ID": presumptive_id, - } - - user = node.get("user") - if user: - row.update( - { - "User": user.get("longName", "N/A"), - "AKA": user.get("shortName", "N/A"), - "ID": user["id"], - "Hardware": user.get("hwModel", "UNSET"), - "Pubkey": user.get("publicKey", "UNSET"), - "Role": user.get("role", "N/A"), - } - ) - pos = node.get("position") - if pos: - row.update( - { - "Latitude": formatFloat(pos.get("latitude"), 4, "°"), - "Longitude": formatFloat(pos.get("longitude"), 4, "°"), - "Altitude": formatFloat(pos.get("altitude"), 0, " m"), - } - ) + # This allows the user to specify fields that wouldn't otherwise be included. + fields = {} + for field in showFields: + if "." in field: + raw_value = getNestedValue(node, field) + else: + # The "since" column is synthesized, it's not retrieved from the device. Get the + # lastHeard value here, and then we'll format it properly below. + if field == "since": + raw_value = node.get("lastHeard") + else: + raw_value = node.get(field) + + formatted_value: Optional[str] = "" - metrics = node.get("deviceMetrics") - if metrics: - batteryLevel = metrics.get("batteryLevel") - if batteryLevel is not None: - if batteryLevel == 0: - batteryString = "Powered" + # Some of these need special formatting or processing. + if field == "channel": + if raw_value is None: + formatted_value = "0" + elif field == "deviceMetrics.channelUtilization": + formatted_value = formatFloat(raw_value, 2, "%") + elif field == "deviceMetrics.airUtilTx": + formatted_value = formatFloat(raw_value, 2, "%") + elif field == "deviceMetrics.batteryLevel": + if raw_value in (0, 101): + formatted_value = "Powered" else: - batteryString = str(batteryLevel) + "%" - row.update({"Battery": batteryString}) - row.update( - { - "Channel util.": formatFloat( - metrics.get("channelUtilization"), 2, "%" - ), - "Tx air util.": formatFloat( - metrics.get("airUtilTx"), 2, "%" - ), - } - ) + formatted_value = formatFloat(raw_value, 0, "%") + elif field == "lastHeard": + formatted_value = getLH(raw_value) + elif field == "position.latitude": + formatted_value = formatFloat(raw_value, 4, "°") + elif field == "position.longitude": + formatted_value = formatFloat(raw_value, 4, "°") + elif field == "position.altitude": + formatted_value = formatFloat(raw_value, 0, "m") + elif field == "since": + formatted_value = getTimeAgo(raw_value) or "N/A" + elif field == "snr": + formatted_value = formatFloat(raw_value, 0, " dB") + elif field == "user.shortName": + formatted_value = raw_value if raw_value is not None else f'Meshtastic {presumptive_id[-4:]}' + elif field == "user.id": + formatted_value = raw_value if raw_value is not None else presumptive_id + else: + formatted_value = raw_value # No special formatting - row.update( - { - "SNR": formatFloat(node.get("snr"), 2, " dB"), - "Hops": node.get("hopsAway", "?"), - "Channel": node.get("channel", 0), - "LastHeard": getLH(node.get("lastHeard")), - "Since": getTimeAgo(node.get("lastHeard")), - } - ) + fields[field] = formatted_value - rows.append(row) + # Filter out any field in the data set that was not specified. + filteredData = {get_human_readable(k): v for k, v in fields.items() if k in showFields} + filteredData.update({get_human_readable(k): v for k, v in fields.items()}) + rows.append(filteredData) rows.sort(key=lambda r: r.get("LastHeard") or "0000", reverse=True) for i, row in enumerate(rows): @@ -345,7 +395,7 @@ if new_index != last_index: retries_left = requestChannelAttempts - 1 if retries_left <= 0: - our_exit(f"Error: Timed out waiting for channels, giving up") + our_exit("Error: Timed out waiting for channels, giving up") print("Timed out trying to retrieve channel info, retrying") n.requestChannels(startingIndex=new_index) last_index = new_index @@ -361,6 +411,7 @@ wantResponse: bool = False, onResponse: Optional[Callable[[dict], Any]] = None, channelIndex: int = 0, + portNum: portnums_pb2.PortNum.ValueType = portnums_pb2.PortNum.TEXT_MESSAGE_APP ): """Send a utf8 string to some other node, if the node has a display it will also be shown on the device. @@ -371,12 +422,12 @@ Keyword Arguments: destinationId {nodeId or nodeNum} -- where to send this message (default: {BROADCAST_ADDR}) - portNum -- the application portnum (similar to IP port numbers) - of the destination, see portnums.proto for a list wantAck -- True if you want the message sent in a reliable manner (with retries and ack/nak provided for delivery) wantResponse -- True if you want the service on the other side to send an application layer response + portNum -- the application portnum (similar to IP port numbers) + of the destination, see portnums.proto for a list Returns the sent packet. The id field will be populated in this packet and can be used to track future message acks/naks. @@ -385,7 +436,7 @@ return self.sendData( text.encode("utf-8"), destinationId, - portNum=portnums_pb2.PortNum.TEXT_MESSAGE_APP, + portNum=portNum, wantAck=wantAck, wantResponse=wantResponse, onResponse=onResponse, @@ -892,8 +943,10 @@ else: our_exit("Warning: No myInfo found.") # A simple hex style nodeid - we can parse this without needing the DB - elif destinationId.startswith("!"): - nodeNum = int(destinationId[1:], 16) + elif isinstance(destinationId, str) and len(destinationId) >= 8: + # assuming some form of node id string such as !1234578 or 0x12345678 + # always grab the last 8 items of the hexadecimal id str and parse to integer + nodeNum = int(destinationId[-8:], 16) else: if self.nodes: node = self.nodes.get(destinationId) @@ -927,7 +980,7 @@ toRadio.packet.CopyFrom(meshPacket) if self.noProto: logging.warning( - f"Not sending packet because protocol use is disabled by noProto" + "Not sending packet because protocol use is disabled by noProto" ) else: logging.debug(f"Sending packet: {stripnl(meshPacket)}") @@ -1116,7 +1169,7 @@ """Send a ToRadio protobuf to the device""" if self.noProto: logging.warning( - f"Not sending packet because protocol use is disabled by noProto" + "Not sending packet because protocol use is disabled by noProto" ) else: # logging.debug(f"Sending toRadio: {stripnl(toRadio)}") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/meshtastic-2.5.11/meshtastic/node.py new/meshtastic-2.5.12/meshtastic/node.py --- old/meshtastic-2.5.11/meshtastic/node.py 1970-01-01 01:00:00.000000000 +0100 +++ new/meshtastic-2.5.12/meshtastic/node.py 1970-01-01 01:00:00.000000000 +0100 @@ -337,14 +337,19 @@ s = s.replace("=", "").replace("+", "-").replace("/", "_") return f"https://meshtastic.org/e/#{s}" - def setURL(self, url): + def setURL(self, url: str, addOnly: bool = False): """Set mesh network URL""" - if self.localConfig is None: - our_exit("Warning: No Config has been read") + if self.localConfig is None or self.channels is None: + our_exit("Warning: config or channels not loaded") # URLs are of the form https://meshtastic.org/d/#{base64_channel_set} # Split on '/#' to find the base64 encoded channel settings - splitURL = url.split("/#") + if addOnly: + splitURL = url.split("/?add=true#") + else: + splitURL = url.split("/#") + if len(splitURL) == 1: + our_exit(f"Warning: Invalid URL '{url}'") b64 = splitURL[-1] # We normally strip padding to make for a shorter URL, but the python parser doesn't like @@ -361,20 +366,36 @@ if len(channelSet.settings) == 0: our_exit("Warning: There were no settings.") - i = 0 - for chs in channelSet.settings: - ch = channel_pb2.Channel() - ch.role = ( - channel_pb2.Channel.Role.PRIMARY - if i == 0 - else channel_pb2.Channel.Role.SECONDARY - ) - ch.index = i - ch.settings.CopyFrom(chs) - self.channels[ch.index] = ch - logging.debug(f"Channel i:{i} ch:{ch}") - self.writeChannel(ch.index) - i = i + 1 + if addOnly: + # Add new channels with names not already present + # Don't change existing channels + for chs in channelSet.settings: + channelExists = self.getChannelByName(chs.name) + if channelExists or chs.name == "": + print(f"Ignoring existing or empty channel \"{chs.name}\" from add URL") + continue + ch = self.getDisabledChannel() + if not ch: + our_exit("Warning: No free channels were found") + ch.settings.CopyFrom(chs) + ch.role = channel_pb2.Channel.Role.SECONDARY + print(f"Adding new channel '{chs.name}' to device") + self.writeChannel(ch.index) + else: + i = 0 + for chs in channelSet.settings: + ch = channel_pb2.Channel() + ch.role = ( + channel_pb2.Channel.Role.PRIMARY + if i == 0 + else channel_pb2.Channel.Role.SECONDARY + ) + ch.index = i + ch.settings.CopyFrom(chs) + self.channels[ch.index] = ch + logging.debug(f"Channel i:{i} ch:{ch}") + self.writeChannel(ch.index) + i = i + 1 p = admin_pb2.AdminMessage() p.set_config.lora.CopyFrom(channelSet.lora_config) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/meshtastic-2.5.11/meshtastic/protobuf/config_pb2.py new/meshtastic-2.5.12/meshtastic/protobuf/config_pb2.py --- old/meshtastic-2.5.11/meshtastic/protobuf/config_pb2.py 1970-01-01 01:00:00.000000000 +0100 +++ new/meshtastic-2.5.12/meshtastic/protobuf/config_pb2.py 1970-01-01 01:00:00.000000000 +0100 @@ -14,7 +14,7 @@ from meshtastic.protobuf import device_ui_pb2 as meshtastic_dot_protobuf_dot_device__ui__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n meshtastic/protobuf/config.proto\x12\x13meshtastic.protobuf\x1a#meshtastic/protobuf/device_ui.proto\"\x8c(\n\x06\x43onfig\x12:\n\x06\x64\x65vice\x18\x01 \x01(\x0b\x32(.meshtastic.protobuf.Config.DeviceConfigH\x00\x12>\n\x08position\x18\x02 \x01(\x0b\x32*.meshtastic.protobuf.Config.PositionConfigH\x00\x12\x38\n\x05power\x18\x03 \x01(\x0b\x32\'.meshtastic.protobuf.Config.PowerConfigH\x00\x12<\n\x07network\x18\x04 \x01(\x0b\x32).meshtastic.protobuf.Config.NetworkConfigH\x00\x12<\n\x07\x64isplay\x18\x05 \x01(\x0b\x32).meshtastic.protobuf.Config.DisplayConfigH\x00\x12\x36\n\x04lora\x18\x06 \x01(\x0b\x32&.meshtastic.protobuf.Config.LoRaConfigH\x00\x12@\n\tbluetooth\x18\x07 \x01(\x0b\x32+.meshtastic.protobuf.Config.BluetoothConfigH\x00\x12>\n\x08security\x18\x08 \x01(\x0b\x32*.meshtastic.protobuf.Config.SecurityConfigH\x00\x12\x42\n\nsessionkey\x18\t \x01(\x0b\x32,.meshtastic.protobuf.Config.SessionkeyConfigH\x00\x12\x38\n\tdev ice_ui\x18\n \x01(\x0b\x32#.meshtastic.protobuf.DeviceUIConfigH\x00\x1a\xc7\x05\n\x0c\x44\x65viceConfig\x12;\n\x04role\x18\x01 \x01(\x0e\x32-.meshtastic.protobuf.Config.DeviceConfig.Role\x12\x1a\n\x0eserial_enabled\x18\x02 \x01(\x08\x42\x02\x18\x01\x12\x13\n\x0b\x62utton_gpio\x18\x04 \x01(\r\x12\x13\n\x0b\x62uzzer_gpio\x18\x05 \x01(\r\x12R\n\x10rebroadcast_mode\x18\x06 \x01(\x0e\x32\x38.meshtastic.protobuf.Config.DeviceConfig.RebroadcastMode\x12 \n\x18node_info_broadcast_secs\x18\x07 \x01(\r\x12\"\n\x1a\x64ouble_tap_as_button_press\x18\x08 \x01(\x08\x12\x16\n\nis_managed\x18\t \x01(\x08\x42\x02\x18\x01\x12\x1c\n\x14\x64isable_triple_click\x18\n \x01(\x08\x12\r\n\x05tzdef\x18\x0b \x01(\t\x12\x1e\n\x16led_heartbeat_disabled\x18\x0c \x01(\x08\"\xbf\x01\n\x04Role\x12\n\n\x06\x43LIENT\x10\x00\x12\x0f\n\x0b\x43LIENT_MUTE\x10\x01\x12\n\n\x06ROUTER\x10\x02\x12\x15\n\rROUTER_CLIENT\x10\x03\x1a\x02\x08\x01\x12\x0c\n\x08REPEATER\x10\x04\x12\x0b\n\x07TRACKER\x10\x05\x12\n\n\x06SENSOR\x10\x06\x1 2\x07\n\x03TAK\x10\x07\x12\x11\n\rCLIENT_HIDDEN\x10\x08\x12\x12\n\x0eLOST_AND_FOUND\x10\t\x12\x0f\n\x0bTAK_TRACKER\x10\n\x12\x0f\n\x0bROUTER_LATE\x10\x0b\"s\n\x0fRebroadcastMode\x12\x07\n\x03\x41LL\x10\x00\x12\x15\n\x11\x41LL_SKIP_DECODING\x10\x01\x12\x0e\n\nLOCAL_ONLY\x10\x02\x12\x0e\n\nKNOWN_ONLY\x10\x03\x12\x08\n\x04NONE\x10\x04\x12\x16\n\x12\x43ORE_PORTNUMS_ONLY\x10\x05\x1a\x9a\x05\n\x0ePositionConfig\x12\x1f\n\x17position_broadcast_secs\x18\x01 \x01(\r\x12(\n position_broadcast_smart_enabled\x18\x02 \x01(\x08\x12\x16\n\x0e\x66ixed_position\x18\x03 \x01(\x08\x12\x17\n\x0bgps_enabled\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x1b\n\x13gps_update_interval\x18\x05 \x01(\r\x12\x1c\n\x10gps_attempt_time\x18\x06 \x01(\rB\x02\x18\x01\x12\x16\n\x0eposition_flags\x18\x07 \x01(\r\x12\x0f\n\x07rx_gpio\x18\x08 \x01(\r\x12\x0f\n\x07tx_gpio\x18\t \x01(\r\x12(\n broadcast_smart_minimum_distance\x18\n \x01(\r\x12-\n%broadcast_smart_minimum_interval_secs\x18\x0b \x01(\r\x12\x13\n\x0bgps_en_gpio\x18\x 0c \x01(\r\x12\x44\n\x08gps_mode\x18\r \x01(\x0e\x32\x32.meshtastic.protobuf.Config.PositionConfig.GpsMode\"\xab\x01\n\rPositionFlags\x12\t\n\x05UNSET\x10\x00\x12\x0c\n\x08\x41LTITUDE\x10\x01\x12\x10\n\x0c\x41LTITUDE_MSL\x10\x02\x12\x16\n\x12GEOIDAL_SEPARATION\x10\x04\x12\x07\n\x03\x44OP\x10\x08\x12\t\n\x05HVDOP\x10\x10\x12\r\n\tSATINVIEW\x10 \x12\n\n\x06SEQ_NO\x10@\x12\x0e\n\tTIMESTAMP\x10\x80\x01\x12\x0c\n\x07HEADING\x10\x80\x02\x12\n\n\x05SPEED\x10\x80\x04\"5\n\x07GpsMode\x12\x0c\n\x08\x44ISABLED\x10\x00\x12\x0b\n\x07\x45NABLED\x10\x01\x12\x0f\n\x0bNOT_PRESENT\x10\x02\x1a\x84\x02\n\x0bPowerConfig\x12\x17\n\x0fis_power_saving\x18\x01 \x01(\x08\x12&\n\x1eon_battery_shutdown_after_secs\x18\x02 \x01(\r\x12\x1f\n\x17\x61\x64\x63_multiplier_override\x18\x03 \x01(\x02\x12\x1b\n\x13wait_bluetooth_secs\x18\x04 \x01(\r\x12\x10\n\x08sds_secs\x18\x06 \x01(\r\x12\x0f\n\x07ls_secs\x18\x07 \x01(\r\x12\x15\n\rmin_wake_secs\x18\x08 \x01(\r\x12\"\n\x1a\x64\x65vice_battery_ina_address\x18\t \x01(\r \x12\x18\n\x10powermon_enables\x18 \x01(\x04\x1a\xe1\x03\n\rNetworkConfig\x12\x14\n\x0cwifi_enabled\x18\x01 \x01(\x08\x12\x11\n\twifi_ssid\x18\x03 \x01(\t\x12\x10\n\x08wifi_psk\x18\x04 \x01(\t\x12\x12\n\nntp_server\x18\x05 \x01(\t\x12\x13\n\x0b\x65th_enabled\x18\x06 \x01(\x08\x12K\n\x0c\x61\x64\x64ress_mode\x18\x07 \x01(\x0e\x32\x35.meshtastic.protobuf.Config.NetworkConfig.AddressMode\x12I\n\x0bipv4_config\x18\x08 \x01(\x0b\x32\x34.meshtastic.protobuf.Config.NetworkConfig.IpV4Config\x12\x16\n\x0ersyslog_server\x18\t \x01(\t\x12\x19\n\x11\x65nabled_protocols\x18\n \x01(\r\x1a\x46\n\nIpV4Config\x12\n\n\x02ip\x18\x01 \x01(\x07\x12\x0f\n\x07gateway\x18\x02 \x01(\x07\x12\x0e\n\x06subnet\x18\x03 \x01(\x07\x12\x0b\n\x03\x64ns\x18\x04 \x01(\x07\"#\n\x0b\x41\x64\x64ressMode\x12\x08\n\x04\x44HCP\x10\x00\x12\n\n\x06STATIC\x10\x01\"4\n\rProtocolFlags\x12\x10\n\x0cNO_BROADCAST\x10\x00\x12\x11\n\rUDP_BROADCAST\x10\x01\x1a\xfa\x07\n\rDisplayConfig\x12\x16\n\x0escreen_on_secs\x18\x01 \x01(\r\x12Q\ n\ngps_format\x18\x02 \x01(\x0e\x32=.meshtastic.protobuf.Config.DisplayConfig.GpsCoordinateFormat\x12!\n\x19\x61uto_screen_carousel_secs\x18\x03 \x01(\r\x12\x19\n\x11\x63ompass_north_top\x18\x04 \x01(\x08\x12\x13\n\x0b\x66lip_screen\x18\x05 \x01(\x08\x12\x45\n\x05units\x18\x06 \x01(\x0e\x32\x36.meshtastic.protobuf.Config.DisplayConfig.DisplayUnits\x12@\n\x04oled\x18\x07 \x01(\x0e\x32\x32.meshtastic.protobuf.Config.DisplayConfig.OledType\x12J\n\x0b\x64isplaymode\x18\x08 \x01(\x0e\x32\x35.meshtastic.protobuf.Config.DisplayConfig.DisplayMode\x12\x14\n\x0cheading_bold\x18\t \x01(\x08\x12\x1d\n\x15wake_on_tap_or_motion\x18\n \x01(\x08\x12Y\n\x13\x63ompass_orientation\x18\x0b \x01(\x0e\x32<.meshtastic.protobuf.Config.DisplayConfig.CompassOrientation\"M\n\x13GpsCoordinateFormat\x12\x07\n\x03\x44\x45\x43\x10\x00\x12\x07\n\x03\x44MS\x10\x01\x12\x07\n\x03UTM\x10\x02\x12\x08\n\x04MGRS\x10\x03\x12\x07\n\x03OLC\x10\x04\x12\x08\n\x04OSGR\x10\x05\"(\n\x0c\x44isplayUnits\x12\n\n\x06METRIC\x10\x00\x 12\x0c\n\x08IMPERIAL\x10\x01\"M\n\x08OledType\x12\r\n\tOLED_AUTO\x10\x00\x12\x10\n\x0cOLED_SSD1306\x10\x01\x12\x0f\n\x0bOLED_SH1106\x10\x02\x12\x0f\n\x0bOLED_SH1107\x10\x03\"A\n\x0b\x44isplayMode\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x00\x12\x0c\n\x08TWOCOLOR\x10\x01\x12\x0c\n\x08INVERTED\x10\x02\x12\t\n\x05\x43OLOR\x10\x03\"\xba\x01\n\x12\x43ompassOrientation\x12\r\n\tDEGREES_0\x10\x00\x12\x0e\n\nDEGREES_90\x10\x01\x12\x0f\n\x0b\x44\x45GREES_180\x10\x02\x12\x0f\n\x0b\x44\x45GREES_270\x10\x03\x12\x16\n\x12\x44\x45GREES_0_INVERTED\x10\x04\x12\x17\n\x13\x44\x45GREES_90_INVERTED\x10\x05\x12\x18\n\x14\x44\x45GREES_180_INVERTED\x10\x06\x12\x18\n\x14\x44\x45GREES_270_INVERTED\x10\x07\x1a\xaf\x07\n\nLoRaConfig\x12\x12\n\nuse_preset\x18\x01 \x01(\x08\x12H\n\x0cmodem_preset\x18\x02 \x01(\x0e\x32\x32.meshtastic.protobuf.Config.LoRaConfig.ModemPreset\x12\x11\n\tbandwidth\x18\x03 \x01(\r\x12\x15\n\rspread_factor\x18\x04 \x01(\r\x12\x13\n\x0b\x63oding_rate\x18\x05 \x01(\r\x12\x18\n\x10\x66requenc y_offset\x18\x06 \x01(\x02\x12\x41\n\x06region\x18\x07 \x01(\x0e\x32\x31.meshtastic.protobuf.Config.LoRaConfig.RegionCode\x12\x11\n\thop_limit\x18\x08 \x01(\r\x12\x12\n\ntx_enabled\x18\t \x01(\x08\x12\x10\n\x08tx_power\x18\n \x01(\x05\x12\x13\n\x0b\x63hannel_num\x18\x0b \x01(\r\x12\x1b\n\x13override_duty_cycle\x18\x0c \x01(\x08\x12\x1e\n\x16sx126x_rx_boosted_gain\x18\r \x01(\x08\x12\x1a\n\x12override_frequency\x18\x0e \x01(\x02\x12\x17\n\x0fpa_fan_disabled\x18\x0f \x01(\x08\x12\x17\n\x0fignore_incoming\x18g \x03(\r\x12\x13\n\x0bignore_mqtt\x18h \x01(\x08\x12\x19\n\x11\x63onfig_ok_to_mqtt\x18i \x01(\x08\"\xf1\x01\n\nRegionCode\x12\t\n\x05UNSET\x10\x00\x12\x06\n\x02US\x10\x01\x12\n\n\x06\x45U_433\x10\x02\x12\n\n\x06\x45U_868\x10\x03\x12\x06\n\x02\x43N\x10\x04\x12\x06\n\x02JP\x10\x05\x12\x07\n\x03\x41NZ\x10\x06\x12\x06\n\x02KR\x10\x07\x12\x06\n\x02TW\x10\x08\x12\x06\n\x02RU\x10\t\x12\x06\n\x02IN\x10\n\x12\n\n\x06NZ_865\x10\x0b\x12\x06\n\x02TH\x10\x0c\x12\x0b\n\x07LORA_24\x10\r\x12\n\n\ x06UA_433\x10\x0e\x12\n\n\x06UA_868\x10\x0f\x12\n\n\x06MY_433\x10\x10\x12\n\n\x06MY_919\x10\x11\x12\n\n\x06SG_923\x10\x12\x12\n\n\x06PH_433\x10\x13\x12\n\n\x06PH_868\x10\x14\x12\n\n\x06PH_915\x10\x15\"\xa9\x01\n\x0bModemPreset\x12\r\n\tLONG_FAST\x10\x00\x12\r\n\tLONG_SLOW\x10\x01\x12\x16\n\x0eVERY_LONG_SLOW\x10\x02\x1a\x02\x08\x01\x12\x0f\n\x0bMEDIUM_SLOW\x10\x03\x12\x0f\n\x0bMEDIUM_FAST\x10\x04\x12\x0e\n\nSHORT_SLOW\x10\x05\x12\x0e\n\nSHORT_FAST\x10\x06\x12\x11\n\rLONG_MODERATE\x10\x07\x12\x0f\n\x0bSHORT_TURBO\x10\x08\x1a\xb6\x01\n\x0f\x42luetoothConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x45\n\x04mode\x18\x02 \x01(\x0e\x32\x37.meshtastic.protobuf.Config.BluetoothConfig.PairingMode\x12\x11\n\tfixed_pin\x18\x03 \x01(\r\"8\n\x0bPairingMode\x12\x0e\n\nRANDOM_PIN\x10\x00\x12\r\n\tFIXED_PIN\x10\x01\x12\n\n\x06NO_PIN\x10\x02\x1a\xb6\x01\n\x0eSecurityConfig\x12\x12\n\npublic_key\x18\x01 \x01(\x0c\x12\x13\n\x0bprivate_key\x18\x02 \x01(\x0c\x12\x11\n\tadmin_key\x18\x03 \x03(\x0c\x 12\x12\n\nis_managed\x18\x04 \x01(\x08\x12\x16\n\x0eserial_enabled\x18\x05 \x01(\x08\x12\x1d\n\x15\x64\x65\x62ug_log_api_enabled\x18\x06 \x01(\x08\x12\x1d\n\x15\x61\x64min_channel_enabled\x18\x08 \x01(\x08\x1a\x12\n\x10SessionkeyConfigB\x11\n\x0fpayload_variantBa\n\x13\x63om.geeksville.meshB\x0c\x43onfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n meshtastic/protobuf/config.proto\x12\x13meshtastic.protobuf\x1a#meshtastic/protobuf/device_ui.proto\"\xa3(\n\x06\x43onfig\x12:\n\x06\x64\x65vice\x18\x01 \x01(\x0b\x32(.meshtastic.protobuf.Config.DeviceConfigH\x00\x12>\n\x08position\x18\x02 \x01(\x0b\x32*.meshtastic.protobuf.Config.PositionConfigH\x00\x12\x38\n\x05power\x18\x03 \x01(\x0b\x32\'.meshtastic.protobuf.Config.PowerConfigH\x00\x12<\n\x07network\x18\x04 \x01(\x0b\x32).meshtastic.protobuf.Config.NetworkConfigH\x00\x12<\n\x07\x64isplay\x18\x05 \x01(\x0b\x32).meshtastic.protobuf.Config.DisplayConfigH\x00\x12\x36\n\x04lora\x18\x06 \x01(\x0b\x32&.meshtastic.protobuf.Config.LoRaConfigH\x00\x12@\n\tbluetooth\x18\x07 \x01(\x0b\x32+.meshtastic.protobuf.Config.BluetoothConfigH\x00\x12>\n\x08security\x18\x08 \x01(\x0b\x32*.meshtastic.protobuf.Config.SecurityConfigH\x00\x12\x42\n\nsessionkey\x18\t \x01(\x0b\x32,.meshtastic.protobuf.Config.SessionkeyConfigH\x00\x12\x38\n\tdev ice_ui\x18\n \x01(\x0b\x32#.meshtastic.protobuf.DeviceUIConfigH\x00\x1a\xc7\x05\n\x0c\x44\x65viceConfig\x12;\n\x04role\x18\x01 \x01(\x0e\x32-.meshtastic.protobuf.Config.DeviceConfig.Role\x12\x1a\n\x0eserial_enabled\x18\x02 \x01(\x08\x42\x02\x18\x01\x12\x13\n\x0b\x62utton_gpio\x18\x04 \x01(\r\x12\x13\n\x0b\x62uzzer_gpio\x18\x05 \x01(\r\x12R\n\x10rebroadcast_mode\x18\x06 \x01(\x0e\x32\x38.meshtastic.protobuf.Config.DeviceConfig.RebroadcastMode\x12 \n\x18node_info_broadcast_secs\x18\x07 \x01(\r\x12\"\n\x1a\x64ouble_tap_as_button_press\x18\x08 \x01(\x08\x12\x16\n\nis_managed\x18\t \x01(\x08\x42\x02\x18\x01\x12\x1c\n\x14\x64isable_triple_click\x18\n \x01(\x08\x12\r\n\x05tzdef\x18\x0b \x01(\t\x12\x1e\n\x16led_heartbeat_disabled\x18\x0c \x01(\x08\"\xbf\x01\n\x04Role\x12\n\n\x06\x43LIENT\x10\x00\x12\x0f\n\x0b\x43LIENT_MUTE\x10\x01\x12\n\n\x06ROUTER\x10\x02\x12\x15\n\rROUTER_CLIENT\x10\x03\x1a\x02\x08\x01\x12\x0c\n\x08REPEATER\x10\x04\x12\x0b\n\x07TRACKER\x10\x05\x12\n\n\x06SENSOR\x10\x06\x1 2\x07\n\x03TAK\x10\x07\x12\x11\n\rCLIENT_HIDDEN\x10\x08\x12\x12\n\x0eLOST_AND_FOUND\x10\t\x12\x0f\n\x0bTAK_TRACKER\x10\n\x12\x0f\n\x0bROUTER_LATE\x10\x0b\"s\n\x0fRebroadcastMode\x12\x07\n\x03\x41LL\x10\x00\x12\x15\n\x11\x41LL_SKIP_DECODING\x10\x01\x12\x0e\n\nLOCAL_ONLY\x10\x02\x12\x0e\n\nKNOWN_ONLY\x10\x03\x12\x08\n\x04NONE\x10\x04\x12\x16\n\x12\x43ORE_PORTNUMS_ONLY\x10\x05\x1a\x9a\x05\n\x0ePositionConfig\x12\x1f\n\x17position_broadcast_secs\x18\x01 \x01(\r\x12(\n position_broadcast_smart_enabled\x18\x02 \x01(\x08\x12\x16\n\x0e\x66ixed_position\x18\x03 \x01(\x08\x12\x17\n\x0bgps_enabled\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x1b\n\x13gps_update_interval\x18\x05 \x01(\r\x12\x1c\n\x10gps_attempt_time\x18\x06 \x01(\rB\x02\x18\x01\x12\x16\n\x0eposition_flags\x18\x07 \x01(\r\x12\x0f\n\x07rx_gpio\x18\x08 \x01(\r\x12\x0f\n\x07tx_gpio\x18\t \x01(\r\x12(\n broadcast_smart_minimum_distance\x18\n \x01(\r\x12-\n%broadcast_smart_minimum_interval_secs\x18\x0b \x01(\r\x12\x13\n\x0bgps_en_gpio\x18\x 0c \x01(\r\x12\x44\n\x08gps_mode\x18\r \x01(\x0e\x32\x32.meshtastic.protobuf.Config.PositionConfig.GpsMode\"\xab\x01\n\rPositionFlags\x12\t\n\x05UNSET\x10\x00\x12\x0c\n\x08\x41LTITUDE\x10\x01\x12\x10\n\x0c\x41LTITUDE_MSL\x10\x02\x12\x16\n\x12GEOIDAL_SEPARATION\x10\x04\x12\x07\n\x03\x44OP\x10\x08\x12\t\n\x05HVDOP\x10\x10\x12\r\n\tSATINVIEW\x10 \x12\n\n\x06SEQ_NO\x10@\x12\x0e\n\tTIMESTAMP\x10\x80\x01\x12\x0c\n\x07HEADING\x10\x80\x02\x12\n\n\x05SPEED\x10\x80\x04\"5\n\x07GpsMode\x12\x0c\n\x08\x44ISABLED\x10\x00\x12\x0b\n\x07\x45NABLED\x10\x01\x12\x0f\n\x0bNOT_PRESENT\x10\x02\x1a\x84\x02\n\x0bPowerConfig\x12\x17\n\x0fis_power_saving\x18\x01 \x01(\x08\x12&\n\x1eon_battery_shutdown_after_secs\x18\x02 \x01(\r\x12\x1f\n\x17\x61\x64\x63_multiplier_override\x18\x03 \x01(\x02\x12\x1b\n\x13wait_bluetooth_secs\x18\x04 \x01(\r\x12\x10\n\x08sds_secs\x18\x06 \x01(\r\x12\x0f\n\x07ls_secs\x18\x07 \x01(\r\x12\x15\n\rmin_wake_secs\x18\x08 \x01(\r\x12\"\n\x1a\x64\x65vice_battery_ina_address\x18\t \x01(\r \x12\x18\n\x10powermon_enables\x18 \x01(\x04\x1a\xe1\x03\n\rNetworkConfig\x12\x14\n\x0cwifi_enabled\x18\x01 \x01(\x08\x12\x11\n\twifi_ssid\x18\x03 \x01(\t\x12\x10\n\x08wifi_psk\x18\x04 \x01(\t\x12\x12\n\nntp_server\x18\x05 \x01(\t\x12\x13\n\x0b\x65th_enabled\x18\x06 \x01(\x08\x12K\n\x0c\x61\x64\x64ress_mode\x18\x07 \x01(\x0e\x32\x35.meshtastic.protobuf.Config.NetworkConfig.AddressMode\x12I\n\x0bipv4_config\x18\x08 \x01(\x0b\x32\x34.meshtastic.protobuf.Config.NetworkConfig.IpV4Config\x12\x16\n\x0ersyslog_server\x18\t \x01(\t\x12\x19\n\x11\x65nabled_protocols\x18\n \x01(\r\x1a\x46\n\nIpV4Config\x12\n\n\x02ip\x18\x01 \x01(\x07\x12\x0f\n\x07gateway\x18\x02 \x01(\x07\x12\x0e\n\x06subnet\x18\x03 \x01(\x07\x12\x0b\n\x03\x64ns\x18\x04 \x01(\x07\"#\n\x0b\x41\x64\x64ressMode\x12\x08\n\x04\x44HCP\x10\x00\x12\n\n\x06STATIC\x10\x01\"4\n\rProtocolFlags\x12\x10\n\x0cNO_BROADCAST\x10\x00\x12\x11\n\rUDP_BROADCAST\x10\x01\x1a\x91\x08\n\rDisplayConfig\x12\x16\n\x0escreen_on_secs\x18\x01 \x01(\r\x12Q\ n\ngps_format\x18\x02 \x01(\x0e\x32=.meshtastic.protobuf.Config.DisplayConfig.GpsCoordinateFormat\x12!\n\x19\x61uto_screen_carousel_secs\x18\x03 \x01(\r\x12\x19\n\x11\x63ompass_north_top\x18\x04 \x01(\x08\x12\x13\n\x0b\x66lip_screen\x18\x05 \x01(\x08\x12\x45\n\x05units\x18\x06 \x01(\x0e\x32\x36.meshtastic.protobuf.Config.DisplayConfig.DisplayUnits\x12@\n\x04oled\x18\x07 \x01(\x0e\x32\x32.meshtastic.protobuf.Config.DisplayConfig.OledType\x12J\n\x0b\x64isplaymode\x18\x08 \x01(\x0e\x32\x35.meshtastic.protobuf.Config.DisplayConfig.DisplayMode\x12\x14\n\x0cheading_bold\x18\t \x01(\x08\x12\x1d\n\x15wake_on_tap_or_motion\x18\n \x01(\x08\x12Y\n\x13\x63ompass_orientation\x18\x0b \x01(\x0e\x32<.meshtastic.protobuf.Config.DisplayConfig.CompassOrientation\x12\x15\n\ruse_12h_clock\x18\x0c \x01(\x08\"M\n\x13GpsCoordinateFormat\x12\x07\n\x03\x44\x45\x43\x10\x00\x12\x07\n\x03\x44MS\x10\x01\x12\x07\n\x03UTM\x10\x02\x12\x08\n\x04MGRS\x10\x03\x12\x07\n\x03OLC\x10\x04\x12\x08\n\x04OSGR\x10\x05\"(\n\x0c \x44isplayUnits\x12\n\n\x06METRIC\x10\x00\x12\x0c\n\x08IMPERIAL\x10\x01\"M\n\x08OledType\x12\r\n\tOLED_AUTO\x10\x00\x12\x10\n\x0cOLED_SSD1306\x10\x01\x12\x0f\n\x0bOLED_SH1106\x10\x02\x12\x0f\n\x0bOLED_SH1107\x10\x03\"A\n\x0b\x44isplayMode\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x00\x12\x0c\n\x08TWOCOLOR\x10\x01\x12\x0c\n\x08INVERTED\x10\x02\x12\t\n\x05\x43OLOR\x10\x03\"\xba\x01\n\x12\x43ompassOrientation\x12\r\n\tDEGREES_0\x10\x00\x12\x0e\n\nDEGREES_90\x10\x01\x12\x0f\n\x0b\x44\x45GREES_180\x10\x02\x12\x0f\n\x0b\x44\x45GREES_270\x10\x03\x12\x16\n\x12\x44\x45GREES_0_INVERTED\x10\x04\x12\x17\n\x13\x44\x45GREES_90_INVERTED\x10\x05\x12\x18\n\x14\x44\x45GREES_180_INVERTED\x10\x06\x12\x18\n\x14\x44\x45GREES_270_INVERTED\x10\x07\x1a\xaf\x07\n\nLoRaConfig\x12\x12\n\nuse_preset\x18\x01 \x01(\x08\x12H\n\x0cmodem_preset\x18\x02 \x01(\x0e\x32\x32.meshtastic.protobuf.Config.LoRaConfig.ModemPreset\x12\x11\n\tbandwidth\x18\x03 \x01(\r\x12\x15\n\rspread_factor\x18\x04 \x01(\r\x12\x13\n\x0b\x63oding_ra te\x18\x05 \x01(\r\x12\x18\n\x10\x66requency_offset\x18\x06 \x01(\x02\x12\x41\n\x06region\x18\x07 \x01(\x0e\x32\x31.meshtastic.protobuf.Config.LoRaConfig.RegionCode\x12\x11\n\thop_limit\x18\x08 \x01(\r\x12\x12\n\ntx_enabled\x18\t \x01(\x08\x12\x10\n\x08tx_power\x18\n \x01(\x05\x12\x13\n\x0b\x63hannel_num\x18\x0b \x01(\r\x12\x1b\n\x13override_duty_cycle\x18\x0c \x01(\x08\x12\x1e\n\x16sx126x_rx_boosted_gain\x18\r \x01(\x08\x12\x1a\n\x12override_frequency\x18\x0e \x01(\x02\x12\x17\n\x0fpa_fan_disabled\x18\x0f \x01(\x08\x12\x17\n\x0fignore_incoming\x18g \x03(\r\x12\x13\n\x0bignore_mqtt\x18h \x01(\x08\x12\x19\n\x11\x63onfig_ok_to_mqtt\x18i \x01(\x08\"\xf1\x01\n\nRegionCode\x12\t\n\x05UNSET\x10\x00\x12\x06\n\x02US\x10\x01\x12\n\n\x06\x45U_433\x10\x02\x12\n\n\x06\x45U_868\x10\x03\x12\x06\n\x02\x43N\x10\x04\x12\x06\n\x02JP\x10\x05\x12\x07\n\x03\x41NZ\x10\x06\x12\x06\n\x02KR\x10\x07\x12\x06\n\x02TW\x10\x08\x12\x06\n\x02RU\x10\t\x12\x06\n\x02IN\x10\n\x12\n\n\x06NZ_865\x10\x0b\x12\x06\n\x02TH\ x10\x0c\x12\x0b\n\x07LORA_24\x10\r\x12\n\n\x06UA_433\x10\x0e\x12\n\n\x06UA_868\x10\x0f\x12\n\n\x06MY_433\x10\x10\x12\n\n\x06MY_919\x10\x11\x12\n\n\x06SG_923\x10\x12\x12\n\n\x06PH_433\x10\x13\x12\n\n\x06PH_868\x10\x14\x12\n\n\x06PH_915\x10\x15\"\xa9\x01\n\x0bModemPreset\x12\r\n\tLONG_FAST\x10\x00\x12\r\n\tLONG_SLOW\x10\x01\x12\x16\n\x0eVERY_LONG_SLOW\x10\x02\x1a\x02\x08\x01\x12\x0f\n\x0bMEDIUM_SLOW\x10\x03\x12\x0f\n\x0bMEDIUM_FAST\x10\x04\x12\x0e\n\nSHORT_SLOW\x10\x05\x12\x0e\n\nSHORT_FAST\x10\x06\x12\x11\n\rLONG_MODERATE\x10\x07\x12\x0f\n\x0bSHORT_TURBO\x10\x08\x1a\xb6\x01\n\x0f\x42luetoothConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x45\n\x04mode\x18\x02 \x01(\x0e\x32\x37.meshtastic.protobuf.Config.BluetoothConfig.PairingMode\x12\x11\n\tfixed_pin\x18\x03 \x01(\r\"8\n\x0bPairingMode\x12\x0e\n\nRANDOM_PIN\x10\x00\x12\r\n\tFIXED_PIN\x10\x01\x12\n\n\x06NO_PIN\x10\x02\x1a\xb6\x01\n\x0eSecurityConfig\x12\x12\n\npublic_key\x18\x01 \x01(\x0c\x12\x13\n\x0bprivate_key\x18\x02 \x01(\x 0c\x12\x11\n\tadmin_key\x18\x03 \x03(\x0c\x12\x12\n\nis_managed\x18\x04 \x01(\x08\x12\x16\n\x0eserial_enabled\x18\x05 \x01(\x08\x12\x1d\n\x15\x64\x65\x62ug_log_api_enabled\x18\x06 \x01(\x08\x12\x1d\n\x15\x61\x64min_channel_enabled\x18\x08 \x01(\x08\x1a\x12\n\x10SessionkeyConfigB\x11\n\x0fpayload_variantBa\n\x13\x63om.geeksville.meshB\x0c\x43onfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -35,7 +35,7 @@ _CONFIG_LORACONFIG_MODEMPRESET.values_by_name["VERY_LONG_SLOW"]._options = None _CONFIG_LORACONFIG_MODEMPRESET.values_by_name["VERY_LONG_SLOW"]._serialized_options = b'\010\001' _globals['_CONFIG']._serialized_start=95 - _globals['_CONFIG']._serialized_end=5227 + _globals['_CONFIG']._serialized_end=5250 _globals['_CONFIG_DEVICECONFIG']._serialized_start=724 _globals['_CONFIG_DEVICECONFIG']._serialized_end=1435 _globals['_CONFIG_DEVICECONFIG_ROLE']._serialized_start=1127 @@ -59,29 +59,29 @@ _globals['_CONFIG_NETWORKCONFIG_PROTOCOLFLAGS']._serialized_start=2799 _globals['_CONFIG_NETWORKCONFIG_PROTOCOLFLAGS']._serialized_end=2851 _globals['_CONFIG_DISPLAYCONFIG']._serialized_start=2854 - _globals['_CONFIG_DISPLAYCONFIG']._serialized_end=3872 - _globals['_CONFIG_DISPLAYCONFIG_GPSCOORDINATEFORMAT']._serialized_start=3418 - _globals['_CONFIG_DISPLAYCONFIG_GPSCOORDINATEFORMAT']._serialized_end=3495 - _globals['_CONFIG_DISPLAYCONFIG_DISPLAYUNITS']._serialized_start=3497 - _globals['_CONFIG_DISPLAYCONFIG_DISPLAYUNITS']._serialized_end=3537 - _globals['_CONFIG_DISPLAYCONFIG_OLEDTYPE']._serialized_start=3539 - _globals['_CONFIG_DISPLAYCONFIG_OLEDTYPE']._serialized_end=3616 - _globals['_CONFIG_DISPLAYCONFIG_DISPLAYMODE']._serialized_start=3618 - _globals['_CONFIG_DISPLAYCONFIG_DISPLAYMODE']._serialized_end=3683 - _globals['_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION']._serialized_start=3686 - _globals['_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION']._serialized_end=3872 - _globals['_CONFIG_LORACONFIG']._serialized_start=3875 - _globals['_CONFIG_LORACONFIG']._serialized_end=4818 - _globals['_CONFIG_LORACONFIG_REGIONCODE']._serialized_start=4405 - _globals['_CONFIG_LORACONFIG_REGIONCODE']._serialized_end=4646 - _globals['_CONFIG_LORACONFIG_MODEMPRESET']._serialized_start=4649 - _globals['_CONFIG_LORACONFIG_MODEMPRESET']._serialized_end=4818 - _globals['_CONFIG_BLUETOOTHCONFIG']._serialized_start=4821 - _globals['_CONFIG_BLUETOOTHCONFIG']._serialized_end=5003 - _globals['_CONFIG_BLUETOOTHCONFIG_PAIRINGMODE']._serialized_start=4947 - _globals['_CONFIG_BLUETOOTHCONFIG_PAIRINGMODE']._serialized_end=5003 - _globals['_CONFIG_SECURITYCONFIG']._serialized_start=5006 - _globals['_CONFIG_SECURITYCONFIG']._serialized_end=5188 - _globals['_CONFIG_SESSIONKEYCONFIG']._serialized_start=5190 - _globals['_CONFIG_SESSIONKEYCONFIG']._serialized_end=5208 + _globals['_CONFIG_DISPLAYCONFIG']._serialized_end=3895 + _globals['_CONFIG_DISPLAYCONFIG_GPSCOORDINATEFORMAT']._serialized_start=3441 + _globals['_CONFIG_DISPLAYCONFIG_GPSCOORDINATEFORMAT']._serialized_end=3518 + _globals['_CONFIG_DISPLAYCONFIG_DISPLAYUNITS']._serialized_start=3520 + _globals['_CONFIG_DISPLAYCONFIG_DISPLAYUNITS']._serialized_end=3560 + _globals['_CONFIG_DISPLAYCONFIG_OLEDTYPE']._serialized_start=3562 + _globals['_CONFIG_DISPLAYCONFIG_OLEDTYPE']._serialized_end=3639 + _globals['_CONFIG_DISPLAYCONFIG_DISPLAYMODE']._serialized_start=3641 + _globals['_CONFIG_DISPLAYCONFIG_DISPLAYMODE']._serialized_end=3706 + _globals['_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION']._serialized_start=3709 + _globals['_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION']._serialized_end=3895 + _globals['_CONFIG_LORACONFIG']._serialized_start=3898 + _globals['_CONFIG_LORACONFIG']._serialized_end=4841 + _globals['_CONFIG_LORACONFIG_REGIONCODE']._serialized_start=4428 + _globals['_CONFIG_LORACONFIG_REGIONCODE']._serialized_end=4669 + _globals['_CONFIG_LORACONFIG_MODEMPRESET']._serialized_start=4672 + _globals['_CONFIG_LORACONFIG_MODEMPRESET']._serialized_end=4841 + _globals['_CONFIG_BLUETOOTHCONFIG']._serialized_start=4844 + _globals['_CONFIG_BLUETOOTHCONFIG']._serialized_end=5026 + _globals['_CONFIG_BLUETOOTHCONFIG_PAIRINGMODE']._serialized_start=4970 + _globals['_CONFIG_BLUETOOTHCONFIG_PAIRINGMODE']._serialized_end=5026 + _globals['_CONFIG_SECURITYCONFIG']._serialized_start=5029 + _globals['_CONFIG_SECURITYCONFIG']._serialized_end=5211 + _globals['_CONFIG_SESSIONKEYCONFIG']._serialized_start=5213 + _globals['_CONFIG_SESSIONKEYCONFIG']._serialized_end=5231 # @@protoc_insertion_point(module_scope) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/meshtastic-2.5.11/meshtastic/protobuf/config_pb2.pyi new/meshtastic-2.5.12/meshtastic/protobuf/config_pb2.pyi --- old/meshtastic-2.5.11/meshtastic/protobuf/config_pb2.pyi 1970-01-01 01:00:00.000000000 +0100 +++ new/meshtastic-2.5.12/meshtastic/protobuf/config_pb2.pyi 1970-01-01 01:00:00.000000000 +0100 @@ -1118,6 +1118,7 @@ HEADING_BOLD_FIELD_NUMBER: builtins.int WAKE_ON_TAP_OR_MOTION_FIELD_NUMBER: builtins.int COMPASS_ORIENTATION_FIELD_NUMBER: builtins.int + USE_12H_CLOCK_FIELD_NUMBER: builtins.int screen_on_secs: builtins.int """ Number of seconds the screen stays on after pressing the user button or receiving a message @@ -1165,6 +1166,11 @@ """ Indicates how to rotate or invert the compass output to accurate display on the display. """ + use_12h_clock: builtins.bool + """ + If false (default), the device will display the time in 24-hour format on screen. + If true, the device will display the time in 12-hour format on screen. + """ def __init__( self, *, @@ -1179,8 +1185,9 @@ heading_bold: builtins.bool = ..., wake_on_tap_or_motion: builtins.bool = ..., compass_orientation: global___Config.DisplayConfig.CompassOrientation.ValueType = ..., + use_12h_clock: builtins.bool = ..., ) -> None: ... - def ClearField(self, field_name: typing.Literal["auto_screen_carousel_secs", b"auto_screen_carousel_secs", "compass_north_top", b"compass_north_top", "compass_orientation", b"compass_orientation", "displaymode", b"displaymode", "flip_screen", b"flip_screen", "gps_format", b"gps_format", "heading_bold", b"heading_bold", "oled", b"oled", "screen_on_secs", b"screen_on_secs", "units", b"units", "wake_on_tap_or_motion", b"wake_on_tap_or_motion"]) -> None: ... + def ClearField(self, field_name: typing.Literal["auto_screen_carousel_secs", b"auto_screen_carousel_secs", "compass_north_top", b"compass_north_top", "compass_orientation", b"compass_orientation", "displaymode", b"displaymode", "flip_screen", b"flip_screen", "gps_format", b"gps_format", "heading_bold", b"heading_bold", "oled", b"oled", "screen_on_secs", b"screen_on_secs", "units", b"units", "use_12h_clock", b"use_12h_clock", "wake_on_tap_or_motion", b"wake_on_tap_or_motion"]) -> None: ... @typing.final class LoRaConfig(google.protobuf.message.Message): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/meshtastic-2.5.11/meshtastic/protobuf/module_config_pb2.pyi new/meshtastic-2.5.12/meshtastic/protobuf/module_config_pb2.pyi --- old/meshtastic-2.5.11/meshtastic/protobuf/module_config_pb2.pyi 1970-01-01 01:00:00.000000000 +0100 +++ new/meshtastic-2.5.12/meshtastic/protobuf/module_config_pb2.pyi 1970-01-01 01:00:00.000000000 +0100 @@ -927,7 +927,7 @@ @typing.final class CannedMessageConfig(google.protobuf.message.Message): """ - TODO: REPLACE + Canned Messages Module Config """ DESCRIPTOR: google.protobuf.descriptor.Descriptor diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/meshtastic-2.5.11/meshtastic/tests/test_main.py new/meshtastic-2.5.12/meshtastic/tests/test_main.py --- old/meshtastic-2.5.11/meshtastic/tests/test_main.py 1970-01-01 01:00:00.000000000 +0100 +++ new/meshtastic-2.5.12/meshtastic/tests/test_main.py 1970-01-01 01:00:00.000000000 +0100 @@ -408,8 +408,8 @@ iface = MagicMock(autospec=SerialInterface) - def mock_showNodes(): - print("inside mocked showNodes") + def mock_showNodes(includeSelf, showFields): + print(f"inside mocked showNodes: {includeSelf} {showFields}") iface.showNodes.side_effect = mock_showNodes with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo: @@ -593,10 +593,10 @@ iface = MagicMock(autospec=SerialInterface) def mock_sendText( - text, dest, wantAck=False, wantResponse=False, onResponse=None, channelIndex=0 + text, dest, wantAck=False, wantResponse=False, onResponse=None, channelIndex=0, portNum=0 ): print("inside mocked sendText") - print(f"{text} {dest} {wantAck} {wantResponse} {channelIndex}") + print(f"{text} {dest} {wantAck} {wantResponse} {channelIndex} {portNum}") iface.sendText.side_effect = mock_sendText @@ -620,10 +620,10 @@ iface = MagicMock(autospec=SerialInterface) def mock_sendText( - text, dest, wantAck=False, wantResponse=False, onResponse=None, channelIndex=0 + text, dest, wantAck=False, wantResponse=False, onResponse=None, channelIndex=0, portNum=0 ): print("inside mocked sendText") - print(f"{text} {dest} {wantAck} {wantResponse} {channelIndex}") + print(f"{text} {dest} {wantAck} {wantResponse} {channelIndex} {portNum}") iface.sendText.side_effect = mock_sendText diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/meshtastic-2.5.11/meshtastic/tests/test_node.py new/meshtastic-2.5.12/meshtastic/tests/test_node.py --- old/meshtastic-2.5.11/meshtastic/tests/test_node.py 1970-01-01 01:00:00.000000000 +0100 +++ new/meshtastic-2.5.12/meshtastic/tests/test_node.py 1970-01-01 01:00:00.000000000 +0100 @@ -270,7 +270,7 @@ assert pytest_wrapped_e.type == SystemExit assert pytest_wrapped_e.value.code == 1 out, err = capsys.readouterr() - assert re.search(r"Warning: There were no settings.", out, re.MULTILINE) + assert re.search(r"Warning: config or channels not loaded", out, re.MULTILINE) assert err == "" @@ -304,7 +304,7 @@ assert pytest_wrapped_e.type == SystemExit assert pytest_wrapped_e.value.code == 1 out, err = capsys.readouterr() - assert re.search(r"Warning: There were no settings", out, re.MULTILINE) + assert re.search(r"Warning: config or channels not loaded", out, re.MULTILINE) assert err == "" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/meshtastic-2.5.11/pyproject.toml new/meshtastic-2.5.12/pyproject.toml --- old/meshtastic-2.5.11/pyproject.toml 1970-01-01 01:00:00.000000000 +0100 +++ new/meshtastic-2.5.12/pyproject.toml 1970-01-01 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ [tool.poetry] name = "meshtastic" -version = "2.5.11" +version = "2.5.12" description = "Python API & client shell for talking to Meshtastic devices" authors = ["Meshtastic Developers <cont...@meshtastic.org>"] license = "GPL-3.0-only"