diff --git a/docs/meshtastic/index.html b/docs/meshtastic/index.html index 8f6c1b2..362ceca 100644 --- a/docs/meshtastic/index.html +++ b/docs/meshtastic/index.html @@ -34,7 +34,7 @@ the device. Includes always up-to-date location and username information for each node in the mesh. This is a read-only datastructure. -
  • myNodeInfo - Contains read-only information about the local radio device (software version, hardware version, etc)
  • +
  • myInfo - Contains read-only information about the local radio device (software version, hardware version, etc)
  • Published PubSub topics

    We use a publish-subscribe model to communicate asynchronous events. @@ -97,7 +97,7 @@ properties of SerialInterface: the device. - nodes - The database of received nodes. Includes always up-to-date location and username information for each node in the mesh. This is a read-only datastructure. -- myNodeInfo - Contains read-only information about the local radio device (software version, hardware version, etc) +- myInfo - Contains read-only information about the local radio device (software version, hardware version, etc) # Published PubSub topics @@ -322,7 +322,7 @@ class MeshInterface: self._sendToRadio(t) logging.debug("Wrote config") - def getMyNode(self): + def getMyUser(self): if self.myInfo is None: return None myId = self.myInfo.my_node_num @@ -333,13 +333,13 @@ class MeshInterface: return None def getLongName(self): - user = self.getMyNode() + user = self.getMyUser() if user is not None: return user.get('longName', None) return None def getShortName(self): - user = self.getMyNode() + user = self.getMyUser() if user is not None: return user.get('shortName', None) return None @@ -600,7 +600,7 @@ class MeshInterface: n = self._getOrCreateByNum(asDict["from"]) n["user"] = u # We now have a node ID, make sure it is uptodate in that table - self.nodes[u["id"]] = u + self.nodes[u["id"]] = n logging.debug(f"Publishing topic {topic}") pub.sendMessage(topic, packet=asDict, interface=self) @@ -817,7 +817,9 @@ class SerialInterface(StreamInterface): # control and will always drive RTS either high or low (rather than letting the CP102 leave # it as an open-collector floating pin). Since it is going to drive it anyways we want to make # sure it is driven low, so that the TBEAM won't reset - self.stream.rts = False + # Linux does this properly, so don't apply this hack (because it makes the reset button not work) + if platform.system() != 'Linux': + self.stream.rts = False self.stream.open() StreamInterface.__init__( @@ -896,6 +898,10 @@ class TCPInterface(StreamInterface):

    +
    meshtastic.tunnel
    +
    +
    +
    meshtastic.util
    @@ -1169,7 +1175,7 @@ noProto – If True, don't try to run our protocol on the link - just be a d self._sendToRadio(t) logging.debug("Wrote config") - def getMyNode(self): + def getMyUser(self): if self.myInfo is None: return None myId = self.myInfo.my_node_num @@ -1180,13 +1186,13 @@ noProto – If True, don't try to run our protocol on the link - just be a d return None def getLongName(self): - user = self.getMyNode() + user = self.getMyUser() if user is not None: return user.get('longName', None) return None def getShortName(self): - user = self.getMyNode() + user = self.getMyUser() if user is not None: return user.get('shortName', None) return None @@ -1447,7 +1453,7 @@ noProto – If True, don't try to run our protocol on the link - just be a d n = self._getOrCreateByNum(asDict["from"]) n["user"] = u # We now have a node ID, make sure it is uptodate in that table - self.nodes[u["id"]] = u + self.nodes[u["id"]] = n logging.debug(f"Publishing topic {topic}") pub.sendMessage(topic, packet=asDict, interface=self) @@ -1488,14 +1494,14 @@ def channelURL(self): Expand source code
    def getLongName(self):
    -    user = self.getMyNode()
    +    user = self.getMyUser()
         if user is not None:
             return user.get('longName', None)
         return None
    -
    -def getMyNode(self) +
    +def getMyUser(self)
    @@ -1503,7 +1509,7 @@ def channelURL(self): Expand source code -
    def getMyNode(self):
    +
    def getMyUser(self):
         if self.myInfo is None:
             return None
         myId = self.myInfo.my_node_num
    @@ -1524,7 +1530,7 @@ def channelURL(self):
     Expand source code
     
     
    def getShortName(self):
    -    user = self.getMyNode()
    +    user = self.getMyUser()
         if user is not None:
             return user.get('shortName', None)
         return None
    @@ -1836,7 +1842,9 @@ debugOut {stream} – If a stream is provided, any debug serial output from # control and will always drive RTS either high or low (rather than letting the CP102 leave # it as an open-collector floating pin). Since it is going to drive it anyways we want to make # sure it is driven low, so that the TBEAM won't reset - self.stream.rts = False + # Linux does this properly, so don't apply this hack (because it makes the reset button not work) + if platform.system() != 'Linux': + self.stream.rts = False self.stream.open() StreamInterface.__init__( @@ -2195,6 +2203,7 @@ hostname {string} – Hostname/IP address of the device to connect to

    meshtastic.remote_hardware
  • meshtastic.remote_hardware_pb2
  • meshtastic.test
  • +
  • meshtastic.tunnel
  • meshtastic.util
  • @@ -2216,7 +2225,7 @@ hostname {string} – Hostname/IP address of the device to connect to

  • channelURL
  • getLongName
  • -
  • getMyNode
  • +
  • getMyUser
  • getShortName
  • sendData
  • sendPacket
  • diff --git a/docs/meshtastic/mesh_pb2.html b/docs/meshtastic/mesh_pb2.html index 1865877..7445e26 100644 --- a/docs/meshtastic/mesh_pb2.html +++ b/docs/meshtastic/mesh_pb2.html @@ -50,7 +50,7 @@ DESCRIPTOR = _descriptor.FileDescriptor( syntax='proto3', serialized_options=b'\n\023com.geeksville.meshB\nMeshProtosH\003', create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\nmesh.proto\x1a\x0eportnums.proto\"j\n\x08Position\x12\x12\n\nlatitude_i\x18\x07 \x01(\x11\x12\x13\n\x0blongitude_i\x18\x08 \x01(\x11\x12\x10\n\x08\x61ltitude\x18\x03 \x01(\x05\x12\x15\n\rbattery_level\x18\x04 \x01(\x05\x12\x0c\n\x04time\x18\t \x01(\x07\"2\n\x04\x44\x61ta\x12\x19\n\x07portnum\x18\x01 \x01(\x0e\x32\x08.PortNum\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\"J\n\x04User\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\tlong_name\x18\x02 \x01(\t\x12\x12\n\nshort_name\x18\x03 \x01(\t\x12\x0f\n\x07macaddr\x18\x04 \x01(\x0c\"\x1f\n\x0eRouteDiscovery\x12\r\n\x05route\x18\x02 \x03(\x05\"\xdb\x02\n\tSubPacket\x12!\n\x08position\x18\x01 \x01(\x0b\x32\t.PositionB\x02\x18\x01H\x00\x12\x15\n\x04\x64\x61ta\x18\x03 \x01(\x0b\x32\x05.DataH\x00\x12\x19\n\x04user\x18\x04 \x01(\x0b\x32\x05.UserB\x02\x18\x01H\x00\x12(\n\rroute_request\x18\x06 \x01(\x0b\x32\x0f.RouteDiscoveryH\x00\x12&\n\x0broute_reply\x18\x07 \x01(\x0b\x32\x0f.RouteDiscoveryH\x00\x12\"\n\x0broute_error\x18\r \x01(\x0e\x32\x0b.RouteErrorH\x00\x12\x15\n\rwant_response\x18\x05 \x01(\x08\x12\x14\n\nsuccess_id\x18\n \x01(\rH\x01\x12\x11\n\x07\x66\x61il_id\x18\x0b \x01(\rH\x01\x12\x0c\n\x04\x64\x65st\x18\t \x01(\r\x12\x0e\n\x06source\x18\x0c \x01(\r\x12\x13\n\x0boriginal_id\x18\x02 \x01(\rB\t\n\x07payloadB\x05\n\x03\x61\x63k\"\xb7\x01\n\nMeshPacket\x12\x0c\n\x04\x66rom\x18\x01 \x01(\r\x12\n\n\x02to\x18\x02 \x01(\r\x12\x1d\n\x07\x64\x65\x63oded\x18\x03 \x01(\x0b\x32\n.SubPacketH\x00\x12\x13\n\tencrypted\x18\x08 \x01(\x0cH\x00\x12\n\n\x02id\x18\x06 \x01(\r\x12\x0f\n\x07rx_time\x18\t \x01(\x07\x12\x0e\n\x06rx_snr\x18\x07 \x01(\x02\x12\x11\n\thop_limit\x18\n \x01(\r\x12\x10\n\x08want_ack\x18\x0b \x01(\x08\x42\t\n\x07payload\"\xa8\x02\n\x0f\x43hannelSettings\x12\x10\n\x08tx_power\x18\x01 \x01(\x05\x12\x32\n\x0cmodem_config\x18\x03 \x01(\x0e\x32\x1c.ChannelSettings.ModemConfig\x12\x11\n\tbandwidth\x18\x06 \x01(\r\x12\x15\n\rspread_factor\x18\x07 \x01(\r\x12\x13\n\x0b\x63oding_rate\x18\x08 \x01(\r\x12\x13\n\x0b\x63hannel_num\x18\t \x01(\r\x12\x0b\n\x03psk\x18\x04 \x01(\x0c\x12\x0c\n\x04name\x18\x05 \x01(\t\"`\n\x0bModemConfig\x12\x12\n\x0e\x42w125Cr45Sf128\x10\x00\x12\x12\n\x0e\x42w500Cr45Sf128\x10\x01\x12\x14\n\x10\x42w31_25Cr48Sf512\x10\x02\x12\x13\n\x0f\x42w125Cr48Sf4096\x10\x03\"\x93\x06\n\x0bRadioConfig\x12\x31\n\x0bpreferences\x18\x01 \x01(\x0b\x32\x1c.RadioConfig.UserPreferences\x12*\n\x10\x63hannel_settings\x18\x02 \x01(\x0b\x32\x10.ChannelSettings\x1a\xa4\x05\n\x0fUserPreferences\x12\x1f\n\x17position_broadcast_secs\x18\x01 \x01(\r\x12\x1b\n\x13send_owner_interval\x18\x02 \x01(\r\x12\x1a\n\x12num_missed_to_fail\x18\x03 \x01(\r\x12\x1b\n\x13wait_bluetooth_secs\x18\x04 \x01(\r\x12\x16\n\x0escreen_on_secs\x18\x05 \x01(\r\x12\x1a\n\x12phone_timeout_secs\x18\x06 \x01(\r\x12\x1d\n\x15phone_sds_timeout_sec\x18\x07 \x01(\r\x12\x1d\n\x15mesh_sds_timeout_secs\x18\x08 \x01(\r\x12\x10\n\x08sds_secs\x18\t \x01(\r\x12\x0f\n\x07ls_secs\x18\n \x01(\r\x12\x15\n\rmin_wake_secs\x18\x0b \x01(\r\x12\x11\n\twifi_ssid\x18\x0c \x01(\t\x12\x15\n\rwifi_password\x18\r \x01(\t\x12\x14\n\x0cwifi_ap_mode\x18\x0e \x01(\x08\x12\x1b\n\x06region\x18\x0f \x01(\x0e\x32\x0b.RegionCode\x12\x11\n\tis_router\x18% \x01(\x08\x12\x14\n\x0cis_low_power\x18& \x01(\x08\x12\x16\n\x0e\x66ixed_position\x18\' \x01(\x08\x12\x15\n\rfactory_reset\x18\x64 \x01(\x08\x12\x19\n\x11\x64\x65\x62ug_log_enabled\x18\x65 \x01(\x08\x12(\n\x0elocation_share\x18 \x01(\x0e\x32\x10.LocationSharing\x12$\n\rgps_operation\x18! \x01(\x0e\x32\r.GpsOperation\x12\x1b\n\x13gps_update_interval\x18\" \x01(\r\x12\x18\n\x10gps_attempt_time\x18$ \x01(\r\x12\x17\n\x0fignore_incoming\x18g \x03(\r\"h\n\x08NodeInfo\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x13\n\x04user\x18\x02 \x01(\x0b\x32\x05.User\x12\x1b\n\x08position\x18\x03 \x01(\x0b\x32\t.Position\x12\x0b\n\x03snr\x18\x07 \x01(\x02\x12\x10\n\x08next_hop\x18\x05 \x01(\r\"\xc5\x02\n\nMyNodeInfo\x12\x13\n\x0bmy_node_num\x18\x01 \x01(\r\x12\x0f\n\x07has_gps\x18\x02 \x01(\x08\x12\x14\n\x0cnum_channels\x18\x03 \x01(\x05\x12\x0e\n\x06region\x18\x04 \x01(\t\x12\x10\n\x08hw_model\x18\x05 \x01(\t\x12\x18\n\x10\x66irmware_version\x18\x06 \x01(\t\x12\x12\n\nerror_code\x18\x07 \x01(\r\x12\x15\n\rerror_address\x18\x08 \x01(\r\x12\x13\n\x0b\x65rror_count\x18\t \x01(\r\x12\x16\n\x0epacket_id_bits\x18\n \x01(\r\x12\x19\n\x11\x63urrent_packet_id\x18\x0b \x01(\r\x12\x15\n\rnode_num_bits\x18\x0c \x01(\r\x12\x1c\n\x14message_timeout_msec\x18\r \x01(\r\x12\x17\n\x0fmin_app_version\x18\x0e \x01(\r\"\xfd\x01\n\x0b\x44\x65viceState\x12\x1b\n\x05radio\x18\x01 \x01(\x0b\x32\x0c.RadioConfig\x12\x1c\n\x07my_node\x18\x02 \x01(\x0b\x32\x0b.MyNodeInfo\x12\x14\n\x05owner\x18\x03 \x01(\x0b\x32\x05.User\x12\x1a\n\x07node_db\x18\x04 \x03(\x0b\x32\t.NodeInfo\x12\"\n\rreceive_queue\x18\x05 \x03(\x0b\x32\x0b.MeshPacket\x12\x0f\n\x07version\x18\x08 \x01(\r\x12$\n\x0frx_text_message\x18\x07 \x01(\x0b\x32\x0b.MeshPacket\x12\x0f\n\x07no_save\x18\t \x01(\x08\x12\x15\n\rdid_gps_reset\x18\x0b \x01(\x08\"\x1e\n\x0b\x44\x65\x62ugString\x12\x0f\n\x07message\x18\x01 \x01(\t\"\xf9\x01\n\tFromRadio\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x1d\n\x06packet\x18\x02 \x01(\x0b\x32\x0b.MeshPacketH\x00\x12\x1e\n\x07my_info\x18\x03 \x01(\x0b\x32\x0b.MyNodeInfoH\x00\x12\x1e\n\tnode_info\x18\x04 \x01(\x0b\x32\t.NodeInfoH\x00\x12\x1d\n\x05radio\x18\x06 \x01(\x0b\x32\x0c.RadioConfigH\x00\x12$\n\x0c\x64\x65\x62ug_string\x18\x07 \x01(\x0b\x32\x0c.DebugStringH\x00\x12\x1c\n\x12\x63onfig_complete_id\x18\x08 \x01(\rH\x00\x12\x12\n\x08rebooted\x18\t \x01(\x08H\x00\x42\t\n\x07variant\"\x8c\x01\n\x07ToRadio\x12\x1d\n\x06packet\x18\x01 \x01(\x0b\x32\x0b.MeshPacketH\x00\x12\x18\n\x0ewant_config_id\x18\x64 \x01(\rH\x00\x12!\n\tset_radio\x18\x65 \x01(\x0b\x32\x0c.RadioConfigH\x00\x12\x1a\n\tset_owner\x18\x66 \x01(\x0b\x32\x05.UserH\x00\x42\t\n\x07variant*>\n\nRouteError\x12\x08\n\x04NONE\x10\x00\x12\x0c\n\x08NO_ROUTE\x10\x01\x12\x0b\n\x07GOT_NAK\x10\x02\x12\x0b\n\x07TIMEOUT\x10\x03*.\n\tConstants\x12\n\n\x06Unused\x10\x00\x12\x15\n\x10\x44\x41TA_PAYLOAD_LEN\x10\xf0\x01*^\n\nRegionCode\x12\t\n\x05Unset\x10\x00\x12\x06\n\x02US\x10\x01\x12\t\n\x05\x45U433\x10\x02\x12\t\n\x05\x45U865\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*U\n\x0cGpsOperation\x12\x0e\n\nGpsOpUnset\x10\x00\x12\x0f\n\x0bGpsOpMobile\x10\x02\x12\x11\n\rGpsOpTimeOnly\x10\x03\x12\x11\n\rGpsOpDisabled\x10\x04*@\n\x0fLocationSharing\x12\x0c\n\x08LocUnset\x10\x00\x12\x0e\n\nLocEnabled\x10\x01\x12\x0f\n\x0bLocDisabled\x10\x02\x42#\n\x13\x63om.geeksville.meshB\nMeshProtosH\x03\x62\x06proto3' + serialized_pb=b'\n\nmesh.proto\x1a\x0eportnums.proto\"j\n\x08Position\x12\x12\n\nlatitude_i\x18\x07 \x01(\x11\x12\x13\n\x0blongitude_i\x18\x08 \x01(\x11\x12\x10\n\x08\x61ltitude\x18\x03 \x01(\x05\x12\x15\n\rbattery_level\x18\x04 \x01(\x05\x12\x0c\n\x04time\x18\t \x01(\x07\"2\n\x04\x44\x61ta\x12\x19\n\x07portnum\x18\x01 \x01(\x0e\x32\x08.PortNum\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\"J\n\x04User\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\tlong_name\x18\x02 \x01(\t\x12\x12\n\nshort_name\x18\x03 \x01(\t\x12\x0f\n\x07macaddr\x18\x04 \x01(\x0c\"\x1f\n\x0eRouteDiscovery\x12\r\n\x05route\x18\x02 \x03(\x05\"\xdb\x02\n\tSubPacket\x12!\n\x08position\x18\x01 \x01(\x0b\x32\t.PositionB\x02\x18\x01H\x00\x12\x15\n\x04\x64\x61ta\x18\x03 \x01(\x0b\x32\x05.DataH\x00\x12\x19\n\x04user\x18\x04 \x01(\x0b\x32\x05.UserB\x02\x18\x01H\x00\x12(\n\rroute_request\x18\x06 \x01(\x0b\x32\x0f.RouteDiscoveryH\x00\x12&\n\x0broute_reply\x18\x07 \x01(\x0b\x32\x0f.RouteDiscoveryH\x00\x12\"\n\x0broute_error\x18\r \x01(\x0e\x32\x0b.RouteErrorH\x00\x12\x15\n\rwant_response\x18\x05 \x01(\x08\x12\x14\n\nsuccess_id\x18\n \x01(\rH\x01\x12\x11\n\x07\x66\x61il_id\x18\x0b \x01(\rH\x01\x12\x0c\n\x04\x64\x65st\x18\t \x01(\r\x12\x0e\n\x06source\x18\x0c \x01(\r\x12\x13\n\x0boriginal_id\x18\x02 \x01(\rB\t\n\x07payloadB\x05\n\x03\x61\x63k\"\xce\x01\n\nMeshPacket\x12\x0c\n\x04\x66rom\x18\x01 \x01(\r\x12\n\n\x02to\x18\x02 \x01(\r\x12\x15\n\rchannel_index\x18\x04 \x01(\r\x12\x1d\n\x07\x64\x65\x63oded\x18\x03 \x01(\x0b\x32\n.SubPacketH\x00\x12\x13\n\tencrypted\x18\x08 \x01(\x0cH\x00\x12\n\n\x02id\x18\x06 \x01(\r\x12\x0f\n\x07rx_time\x18\t \x01(\x07\x12\x0e\n\x06rx_snr\x18\x07 \x01(\x02\x12\x11\n\thop_limit\x18\n \x01(\r\x12\x10\n\x08want_ack\x18\x0b \x01(\x08\x42\t\n\x07payload\"\xa8\x02\n\x0f\x43hannelSettings\x12\x10\n\x08tx_power\x18\x01 \x01(\x05\x12\x32\n\x0cmodem_config\x18\x03 \x01(\x0e\x32\x1c.ChannelSettings.ModemConfig\x12\x11\n\tbandwidth\x18\x06 \x01(\r\x12\x15\n\rspread_factor\x18\x07 \x01(\r\x12\x13\n\x0b\x63oding_rate\x18\x08 \x01(\r\x12\x13\n\x0b\x63hannel_num\x18\t \x01(\r\x12\x0b\n\x03psk\x18\x04 \x01(\x0c\x12\x0c\n\x04name\x18\x05 \x01(\t\"`\n\x0bModemConfig\x12\x12\n\x0e\x42w125Cr45Sf128\x10\x00\x12\x12\n\x0e\x42w500Cr45Sf128\x10\x01\x12\x14\n\x10\x42w31_25Cr48Sf512\x10\x02\x12\x13\n\x0f\x42w125Cr48Sf4096\x10\x03\"\xf7\x05\n\x0bRadioConfig\x12\x31\n\x0bpreferences\x18\x01 \x01(\x0b\x32\x1c.RadioConfig.UserPreferences\x12*\n\x10\x63hannel_settings\x18\x02 \x01(\x0b\x32\x10.ChannelSettings\x1a\x88\x05\n\x0fUserPreferences\x12\x1f\n\x17position_broadcast_secs\x18\x01 \x01(\r\x12\x1b\n\x13send_owner_interval\x18\x02 \x01(\r\x12\x1b\n\x13wait_bluetooth_secs\x18\x04 \x01(\r\x12\x16\n\x0escreen_on_secs\x18\x05 \x01(\r\x12\x1a\n\x12phone_timeout_secs\x18\x06 \x01(\r\x12\x1d\n\x15phone_sds_timeout_sec\x18\x07 \x01(\r\x12\x1d\n\x15mesh_sds_timeout_secs\x18\x08 \x01(\r\x12\x10\n\x08sds_secs\x18\t \x01(\r\x12\x0f\n\x07ls_secs\x18\n \x01(\r\x12\x15\n\rmin_wake_secs\x18\x0b \x01(\r\x12\x11\n\twifi_ssid\x18\x0c \x01(\t\x12\x15\n\rwifi_password\x18\r \x01(\t\x12\x14\n\x0cwifi_ap_mode\x18\x0e \x01(\x08\x12\x1b\n\x06region\x18\x0f \x01(\x0e\x32\x0b.RegionCode\x12\x11\n\tis_router\x18% \x01(\x08\x12\x14\n\x0cis_low_power\x18& \x01(\x08\x12\x16\n\x0e\x66ixed_position\x18\' \x01(\x08\x12\x15\n\rfactory_reset\x18\x64 \x01(\x08\x12\x19\n\x11\x64\x65\x62ug_log_enabled\x18\x65 \x01(\x08\x12(\n\x0elocation_share\x18 \x01(\x0e\x32\x10.LocationSharing\x12$\n\rgps_operation\x18! \x01(\x0e\x32\r.GpsOperation\x12\x1b\n\x13gps_update_interval\x18\" \x01(\r\x12\x18\n\x10gps_attempt_time\x18$ \x01(\r\x12\x17\n\x0fignore_incoming\x18g \x03(\r\"h\n\x08NodeInfo\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x13\n\x04user\x18\x02 \x01(\x0b\x32\x05.User\x12\x1b\n\x08position\x18\x03 \x01(\x0b\x32\t.Position\x12\x0b\n\x03snr\x18\x07 \x01(\x02\x12\x10\n\x08next_hop\x18\x05 \x01(\r\"\xc5\x02\n\nMyNodeInfo\x12\x13\n\x0bmy_node_num\x18\x01 \x01(\r\x12\x0f\n\x07has_gps\x18\x02 \x01(\x08\x12\x14\n\x0cnum_channels\x18\x03 \x01(\x05\x12\x0e\n\x06region\x18\x04 \x01(\t\x12\x10\n\x08hw_model\x18\x05 \x01(\t\x12\x18\n\x10\x66irmware_version\x18\x06 \x01(\t\x12\x12\n\nerror_code\x18\x07 \x01(\r\x12\x15\n\rerror_address\x18\x08 \x01(\r\x12\x13\n\x0b\x65rror_count\x18\t \x01(\r\x12\x16\n\x0epacket_id_bits\x18\n \x01(\r\x12\x19\n\x11\x63urrent_packet_id\x18\x0b \x01(\r\x12\x15\n\rnode_num_bits\x18\x0c \x01(\r\x12\x1c\n\x14message_timeout_msec\x18\r \x01(\r\x12\x17\n\x0fmin_app_version\x18\x0e \x01(\r\"\xab\x02\n\x0b\x44\x65viceState\x12\x1b\n\x05radio\x18\x01 \x01(\x0b\x32\x0c.RadioConfig\x12\x1c\n\x07my_node\x18\x02 \x01(\x0b\x32\x0b.MyNodeInfo\x12\x14\n\x05owner\x18\x03 \x01(\x0b\x32\x05.User\x12\x1a\n\x07node_db\x18\x04 \x03(\x0b\x32\t.NodeInfo\x12\"\n\rreceive_queue\x18\x05 \x03(\x0b\x32\x0b.MeshPacket\x12\x0f\n\x07version\x18\x08 \x01(\r\x12$\n\x0frx_text_message\x18\x07 \x01(\x0b\x32\x0b.MeshPacket\x12\x0f\n\x07no_save\x18\t \x01(\x08\x12\x15\n\rdid_gps_reset\x18\x0b \x01(\x08\x12,\n\x12secondary_channels\x18\x0c \x03(\x0b\x32\x10.ChannelSettings\"\x1e\n\x0b\x44\x65\x62ugString\x12\x0f\n\x07message\x18\x01 \x01(\t\"\xa8\x02\n\tFromRadio\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x1d\n\x06packet\x18\x02 \x01(\x0b\x32\x0b.MeshPacketH\x00\x12\x1e\n\x07my_info\x18\x03 \x01(\x0b\x32\x0b.MyNodeInfoH\x00\x12\x1e\n\tnode_info\x18\x04 \x01(\x0b\x32\t.NodeInfoH\x00\x12\x1d\n\x05radio\x18\x06 \x01(\x0b\x32\x0c.RadioConfigH\x00\x12$\n\x0c\x64\x65\x62ug_string\x18\x07 \x01(\x0b\x32\x0c.DebugStringH\x00\x12\x1c\n\x12\x63onfig_complete_id\x18\x08 \x01(\rH\x00\x12\x12\n\x08rebooted\x18\t \x01(\x08H\x00\x12-\n\x11secondary_channel\x18\n \x01(\x0b\x32\x10.ChannelSettingsH\x00\x42\t\n\x07variant\"\x8c\x01\n\x07ToRadio\x12\x1d\n\x06packet\x18\x01 \x01(\x0b\x32\x0b.MeshPacketH\x00\x12\x18\n\x0ewant_config_id\x18\x64 \x01(\rH\x00\x12!\n\tset_radio\x18\x65 \x01(\x0b\x32\x0c.RadioConfigH\x00\x12\x1a\n\tset_owner\x18\x66 \x01(\x0b\x32\x05.UserH\x00\x42\t\n\x07variant*>\n\nRouteError\x12\x08\n\x04NONE\x10\x00\x12\x0c\n\x08NO_ROUTE\x10\x01\x12\x0b\n\x07GOT_NAK\x10\x02\x12\x0b\n\x07TIMEOUT\x10\x03*.\n\tConstants\x12\n\n\x06Unused\x10\x00\x12\x15\n\x10\x44\x41TA_PAYLOAD_LEN\x10\xf0\x01*^\n\nRegionCode\x12\t\n\x05Unset\x10\x00\x12\x06\n\x02US\x10\x01\x12\t\n\x05\x45U433\x10\x02\x12\t\n\x05\x45U865\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*U\n\x0cGpsOperation\x12\x0e\n\nGpsOpUnset\x10\x00\x12\x0f\n\x0bGpsOpMobile\x10\x02\x12\x11\n\rGpsOpTimeOnly\x10\x03\x12\x11\n\rGpsOpDisabled\x10\x04*@\n\x0fLocationSharing\x12\x0c\n\x08LocUnset\x10\x00\x12\x0e\n\nLocEnabled\x10\x01\x12\x0f\n\x0bLocDisabled\x10\x02\x42#\n\x13\x63om.geeksville.meshB\nMeshProtosH\x03\x62\x06proto3' , dependencies=[portnums__pb2.DESCRIPTOR,]) @@ -84,8 +84,8 @@ _ROUTEERROR = _descriptor.EnumDescriptor( ], containing_type=None, serialized_options=None, - serialized_start=3041, - serialized_end=3103, + serialized_start=3129, + serialized_end=3191, ) _sym_db.RegisterEnumDescriptor(_ROUTEERROR) @@ -110,8 +110,8 @@ _CONSTANTS = _descriptor.EnumDescriptor( ], containing_type=None, serialized_options=None, - serialized_start=3105, - serialized_end=3151, + serialized_start=3193, + serialized_end=3239, ) _sym_db.RegisterEnumDescriptor(_CONSTANTS) @@ -171,8 +171,8 @@ _REGIONCODE = _descriptor.EnumDescriptor( ], containing_type=None, serialized_options=None, - serialized_start=3153, - serialized_end=3247, + serialized_start=3241, + serialized_end=3335, ) _sym_db.RegisterEnumDescriptor(_REGIONCODE) @@ -207,8 +207,8 @@ _GPSOPERATION = _descriptor.EnumDescriptor( ], containing_type=None, serialized_options=None, - serialized_start=3249, - serialized_end=3334, + serialized_start=3337, + serialized_end=3422, ) _sym_db.RegisterEnumDescriptor(_GPSOPERATION) @@ -238,8 +238,8 @@ _LOCATIONSHARING = _descriptor.EnumDescriptor( ], containing_type=None, serialized_options=None, - serialized_start=3336, - serialized_end=3400, + serialized_start=3424, + serialized_end=3488, ) _sym_db.RegisterEnumDescriptor(_LOCATIONSHARING) @@ -298,8 +298,8 @@ _CHANNELSETTINGS_MODEMCONFIG = _descriptor.EnumDescriptor( ], containing_type=None, serialized_options=None, - serialized_start=1036, - serialized_end=1132, + serialized_start=1059, + serialized_end=1155, ) _sym_db.RegisterEnumDescriptor(_CHANNELSETTINGS_MODEMCONFIG) @@ -630,49 +630,56 @@ _MESHPACKET = _descriptor.Descriptor( is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='decoded', full_name='MeshPacket.decoded', index=2, + name='channel_index', full_name='MeshPacket.channel_index', index=2, + number=4, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='decoded', full_name='MeshPacket.decoded', index=3, number=3, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='encrypted', full_name='MeshPacket.encrypted', index=3, + name='encrypted', full_name='MeshPacket.encrypted', index=4, number=8, type=12, cpp_type=9, label=1, has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='id', full_name='MeshPacket.id', index=4, + name='id', full_name='MeshPacket.id', index=5, number=6, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='rx_time', full_name='MeshPacket.rx_time', index=5, + name='rx_time', full_name='MeshPacket.rx_time', index=6, number=9, type=7, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='rx_snr', full_name='MeshPacket.rx_snr', index=6, + name='rx_snr', full_name='MeshPacket.rx_snr', index=7, number=7, type=2, cpp_type=6, label=1, has_default_value=False, default_value=float(0), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='hop_limit', full_name='MeshPacket.hop_limit', index=7, + name='hop_limit', full_name='MeshPacket.hop_limit', index=8, number=10, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='want_ack', full_name='MeshPacket.want_ack', index=8, + name='want_ack', full_name='MeshPacket.want_ack', index=9, number=11, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, @@ -696,7 +703,7 @@ _MESHPACKET = _descriptor.Descriptor( fields=[]), ], serialized_start=650, - serialized_end=833, + serialized_end=856, ) @@ -777,8 +784,8 @@ _CHANNELSETTINGS = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=836, - serialized_end=1132, + serialized_start=859, + serialized_end=1155, ) @@ -805,161 +812,154 @@ _RADIOCONFIG_USERPREFERENCES = _descriptor.Descriptor( is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='num_missed_to_fail', full_name='RadioConfig.UserPreferences.num_missed_to_fail', index=2, - number=3, type=13, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='wait_bluetooth_secs', full_name='RadioConfig.UserPreferences.wait_bluetooth_secs', index=3, + name='wait_bluetooth_secs', full_name='RadioConfig.UserPreferences.wait_bluetooth_secs', index=2, number=4, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='screen_on_secs', full_name='RadioConfig.UserPreferences.screen_on_secs', index=4, + name='screen_on_secs', full_name='RadioConfig.UserPreferences.screen_on_secs', index=3, number=5, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='phone_timeout_secs', full_name='RadioConfig.UserPreferences.phone_timeout_secs', index=5, + name='phone_timeout_secs', full_name='RadioConfig.UserPreferences.phone_timeout_secs', index=4, number=6, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='phone_sds_timeout_sec', full_name='RadioConfig.UserPreferences.phone_sds_timeout_sec', index=6, + name='phone_sds_timeout_sec', full_name='RadioConfig.UserPreferences.phone_sds_timeout_sec', index=5, number=7, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='mesh_sds_timeout_secs', full_name='RadioConfig.UserPreferences.mesh_sds_timeout_secs', index=7, + name='mesh_sds_timeout_secs', full_name='RadioConfig.UserPreferences.mesh_sds_timeout_secs', index=6, number=8, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='sds_secs', full_name='RadioConfig.UserPreferences.sds_secs', index=8, + name='sds_secs', full_name='RadioConfig.UserPreferences.sds_secs', index=7, number=9, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='ls_secs', full_name='RadioConfig.UserPreferences.ls_secs', index=9, + name='ls_secs', full_name='RadioConfig.UserPreferences.ls_secs', index=8, number=10, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='min_wake_secs', full_name='RadioConfig.UserPreferences.min_wake_secs', index=10, + name='min_wake_secs', full_name='RadioConfig.UserPreferences.min_wake_secs', index=9, number=11, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='wifi_ssid', full_name='RadioConfig.UserPreferences.wifi_ssid', index=11, + name='wifi_ssid', full_name='RadioConfig.UserPreferences.wifi_ssid', index=10, number=12, type=9, cpp_type=9, label=1, has_default_value=False, default_value=b"".decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='wifi_password', full_name='RadioConfig.UserPreferences.wifi_password', index=12, + name='wifi_password', full_name='RadioConfig.UserPreferences.wifi_password', index=11, number=13, type=9, cpp_type=9, label=1, has_default_value=False, default_value=b"".decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='wifi_ap_mode', full_name='RadioConfig.UserPreferences.wifi_ap_mode', index=13, + name='wifi_ap_mode', full_name='RadioConfig.UserPreferences.wifi_ap_mode', index=12, number=14, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='region', full_name='RadioConfig.UserPreferences.region', index=14, + name='region', full_name='RadioConfig.UserPreferences.region', index=13, number=15, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='is_router', full_name='RadioConfig.UserPreferences.is_router', index=15, + name='is_router', full_name='RadioConfig.UserPreferences.is_router', index=14, number=37, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='is_low_power', full_name='RadioConfig.UserPreferences.is_low_power', index=16, + name='is_low_power', full_name='RadioConfig.UserPreferences.is_low_power', index=15, number=38, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='fixed_position', full_name='RadioConfig.UserPreferences.fixed_position', index=17, + name='fixed_position', full_name='RadioConfig.UserPreferences.fixed_position', index=16, number=39, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='factory_reset', full_name='RadioConfig.UserPreferences.factory_reset', index=18, + name='factory_reset', full_name='RadioConfig.UserPreferences.factory_reset', index=17, number=100, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='debug_log_enabled', full_name='RadioConfig.UserPreferences.debug_log_enabled', index=19, + name='debug_log_enabled', full_name='RadioConfig.UserPreferences.debug_log_enabled', index=18, number=101, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='location_share', full_name='RadioConfig.UserPreferences.location_share', index=20, + name='location_share', full_name='RadioConfig.UserPreferences.location_share', index=19, number=32, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='gps_operation', full_name='RadioConfig.UserPreferences.gps_operation', index=21, + name='gps_operation', full_name='RadioConfig.UserPreferences.gps_operation', index=20, number=33, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='gps_update_interval', full_name='RadioConfig.UserPreferences.gps_update_interval', index=22, + name='gps_update_interval', full_name='RadioConfig.UserPreferences.gps_update_interval', index=21, number=34, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='gps_attempt_time', full_name='RadioConfig.UserPreferences.gps_attempt_time', index=23, + name='gps_attempt_time', full_name='RadioConfig.UserPreferences.gps_attempt_time', index=22, number=36, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='ignore_incoming', full_name='RadioConfig.UserPreferences.ignore_incoming', index=24, + name='ignore_incoming', full_name='RadioConfig.UserPreferences.ignore_incoming', index=23, number=103, type=13, cpp_type=3, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, @@ -977,8 +977,8 @@ _RADIOCONFIG_USERPREFERENCES = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1246, - serialized_end=1922, + serialized_start=1269, + serialized_end=1917, ) _RADIOCONFIG = _descriptor.Descriptor( @@ -1015,8 +1015,8 @@ _RADIOCONFIG = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1135, - serialized_end=1922, + serialized_start=1158, + serialized_end=1917, ) @@ -1075,8 +1075,8 @@ _NODEINFO = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1924, - serialized_end=2028, + serialized_start=1919, + serialized_end=2023, ) @@ -1198,8 +1198,8 @@ _MYNODEINFO = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=2031, - serialized_end=2356, + serialized_start=2026, + serialized_end=2351, ) @@ -1274,6 +1274,13 @@ _DEVICESTATE = _descriptor.Descriptor( message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='secondary_channels', full_name='DeviceState.secondary_channels', index=9, + number=12, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), ], extensions=[ ], @@ -1286,8 +1293,8 @@ _DEVICESTATE = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=2359, - serialized_end=2612, + serialized_start=2354, + serialized_end=2653, ) @@ -1318,8 +1325,8 @@ _DEBUGSTRING = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=2614, - serialized_end=2644, + serialized_start=2655, + serialized_end=2685, ) @@ -1387,6 +1394,13 @@ _FROMRADIO = _descriptor.Descriptor( message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='secondary_channel', full_name='FromRadio.secondary_channel', index=8, + number=10, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), ], extensions=[ ], @@ -1404,8 +1418,8 @@ _FROMRADIO = _descriptor.Descriptor( create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=2647, - serialized_end=2896, + serialized_start=2688, + serialized_end=2984, ) @@ -1462,8 +1476,8 @@ _TORADIO = _descriptor.Descriptor( create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=2899, - serialized_end=3039, + serialized_start=2987, + serialized_end=3127, ) _DATA.fields_by_name['portnum'].enum_type = portnums__pb2._PORTNUM @@ -1520,11 +1534,13 @@ _DEVICESTATE.fields_by_name['owner'].message_type = _USER _DEVICESTATE.fields_by_name['node_db'].message_type = _NODEINFO _DEVICESTATE.fields_by_name['receive_queue'].message_type = _MESHPACKET _DEVICESTATE.fields_by_name['rx_text_message'].message_type = _MESHPACKET +_DEVICESTATE.fields_by_name['secondary_channels'].message_type = _CHANNELSETTINGS _FROMRADIO.fields_by_name['packet'].message_type = _MESHPACKET _FROMRADIO.fields_by_name['my_info'].message_type = _MYNODEINFO _FROMRADIO.fields_by_name['node_info'].message_type = _NODEINFO _FROMRADIO.fields_by_name['radio'].message_type = _RADIOCONFIG _FROMRADIO.fields_by_name['debug_string'].message_type = _DEBUGSTRING +_FROMRADIO.fields_by_name['secondary_channel'].message_type = _CHANNELSETTINGS _FROMRADIO.oneofs_by_name['variant'].fields.append( _FROMRADIO.fields_by_name['packet']) _FROMRADIO.fields_by_name['packet'].containing_oneof = _FROMRADIO.oneofs_by_name['variant'] @@ -1546,6 +1562,9 @@ _FROMRADIO.fields_by_name['config_complete_id'].containing_oneof = _FROM _FROMRADIO.oneofs_by_name['variant'].fields.append( _FROMRADIO.fields_by_name['rebooted']) _FROMRADIO.fields_by_name['rebooted'].containing_oneof = _FROMRADIO.oneofs_by_name['variant'] +_FROMRADIO.oneofs_by_name['variant'].fields.append( + _FROMRADIO.fields_by_name['secondary_channel']) +_FROMRADIO.fields_by_name['secondary_channel'].containing_oneof = _FROMRADIO.oneofs_by_name['variant'] _TORADIO.fields_by_name['packet'].message_type = _MESHPACKET _TORADIO.fields_by_name['set_radio'].message_type = _RADIOCONFIG _TORADIO.fields_by_name['set_owner'].message_type = _USER @@ -3532,6 +3551,10 @@ shown below.

    +
    var SECONDARY_CHANNELS_FIELD_NUMBER
    +
    +
    +
    var VERSION_FIELD_NUMBER
    @@ -3738,6 +3761,29 @@ shown below.

    return field_value
    +
    var secondary_channels
    +
    +

    Getter for secondary_channels.

    +
    + +Expand source code + +
    def getter(self):
    +  field_value = self._fields.get(field)
    +  if field_value is None:
    +    # Construct a new object to represent this field.
    +    field_value = field._default_constructor(self)
    +
    +    # Atomically check if another thread has preempted us and, if not, swap
    +    # in the new object we just created.  If someone has preempted us, we
    +    # take that object and discard ours.
    +    # WARNING:  We are relying on setdefault() being atomic.  This is true
    +    #   in CPython but we haven't investigated others.  This warning appears
    +    #   in several other locations in this file.
    +    field_value = self._fields.setdefault(field, field_value)
    +  return field_value
    +
    +
    var version

    Getter for version.

    @@ -4268,6 +4314,10 @@ shown below.

    +
    var SECONDARY_CHANNEL_FIELD_NUMBER
    +
    +
    +

    Static methods

    @@ -4460,6 +4510,29 @@ shown below.

    return self._fields.get(field, default_value)
    +
    var secondary_channel
    +
    +

    Getter for secondary_channel.

    +
    + +Expand source code + +
    def getter(self):
    +  field_value = self._fields.get(field)
    +  if field_value is None:
    +    # Construct a new object to represent this field.
    +    field_value = field._default_constructor(self)
    +
    +    # Atomically check if another thread has preempted us and, if not, swap
    +    # in the new object we just created.  If someone has preempted us, we
    +    # take that object and discard ours.
    +    # WARNING:  We are relying on setdefault() being atomic.  This is true
    +    #   in CPython but we haven't investigated others.  This warning appears
    +    #   in several other locations in this file.
    +    field_value = self._fields.setdefault(field, field_value)
    +  return field_value
    +
    +

    Methods

    @@ -4941,6 +5014,10 @@ shown below.

    Class variables

    +
    var CHANNEL_INDEX_FIELD_NUMBER
    +
    +
    +
    var DECODED_FIELD_NUMBER
    @@ -5019,6 +5096,19 @@ shown below.

    Instance variables

    +
    var channel_index
    +
    +

    Getter for channel_index.

    +
    + +Expand source code + +
    def getter(self):
    +  # TODO(protobuf-team): This may be broken since there may not be
    +  # default_value.  Combine with has_default_value somehow.
    +  return self._fields.get(field, default_value)
    +
    +
    var decoded

    Getter for decoded.

    @@ -10868,6 +10958,7 @@ and propagates this to our listener iff this was a state change.

  • RECEIVE_QUEUE_FIELD_NUMBER
  • RX_TEXT_MESSAGE_FIELD_NUMBER
  • RegisterExtension
  • +
  • SECONDARY_CHANNELS_FIELD_NUMBER
  • SerializePartialToString
  • SerializeToString
  • SetInParent
  • @@ -10882,6 +10973,7 @@ and propagates this to our listener iff this was a state change.

  • radio
  • receive_queue
  • rx_text_message
  • +
  • secondary_channels
  • version
  • @@ -10909,6 +11001,7 @@ and propagates this to our listener iff this was a state change.

  • RADIO_FIELD_NUMBER
  • REBOOTED_FIELD_NUMBER
  • RegisterExtension
  • +
  • SECONDARY_CHANNEL_FIELD_NUMBER
  • SerializePartialToString
  • SerializeToString
  • SetInParent
  • @@ -10922,12 +11015,14 @@ and propagates this to our listener iff this was a state change.

  • packet
  • radio
  • rebooted
  • +
  • secondary_channel
  • MeshPacket

    • ByteSize
    • +
    • CHANNEL_INDEX_FIELD_NUMBER
    • Clear
    • ClearField
    • DECODED_FIELD_NUMBER
    • @@ -10954,6 +11049,7 @@ and propagates this to our listener iff this was a state change.

    • UnknownFields
    • WANT_ACK_FIELD_NUMBER
    • WhichOneof
    • +
    • channel_index
    • decoded
    • encrypted
    • from
    • diff --git a/docs/meshtastic/portnums_pb2.html b/docs/meshtastic/portnums_pb2.html index 83474a1..5e1377f 100644 --- a/docs/meshtastic/portnums_pb2.html +++ b/docs/meshtastic/portnums_pb2.html @@ -49,7 +49,7 @@ DESCRIPTOR = _descriptor.FileDescriptor( syntax='proto3', serialized_options=b'\n\023com.geeksville.meshB\010PortnumsH\003', create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\x0eportnums.proto*\xa2\x01\n\x07PortNum\x12\x0f\n\x0bUNKNOWN_APP\x10\x00\x12\x14\n\x10TEXT_MESSAGE_APP\x10\x01\x12\x17\n\x13REMOTE_HARDWARE_APP\x10\x02\x12\x10\n\x0cPOSITION_APP\x10\x03\x12\x10\n\x0cNODEINFO_APP\x10\x04\x12\r\n\tREPLY_APP\x10 \x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x12\n\rIP_TUNNEL_APP\x10\x80\x08\x42!\n\x13\x63om.geeksville.meshB\x08PortnumsH\x03\x62\x06proto3' + serialized_pb=b'\n\x0eportnums.proto*\xa1\x01\n\x07PortNum\x12\x0f\n\x0bUNKNOWN_APP\x10\x00\x12\x14\n\x10TEXT_MESSAGE_APP\x10\x01\x12\x17\n\x13REMOTE_HARDWARE_APP\x10\x02\x12\x10\n\x0cPOSITION_APP\x10\x03\x12\x10\n\x0cNODEINFO_APP\x10\x04\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x42!\n\x13\x63om.geeksville.meshB\x08PortnumsH\x03\x62\x06proto3' ) _PORTNUM = _descriptor.EnumDescriptor( @@ -90,12 +90,12 @@ _PORTNUM = _descriptor.EnumDescriptor( type=None, create_key=_descriptor._internal_create_key), _descriptor.EnumValueDescriptor( - name='PRIVATE_APP', index=6, number=256, + name='IP_TUNNEL_APP', index=6, number=33, serialized_options=None, type=None, create_key=_descriptor._internal_create_key), _descriptor.EnumValueDescriptor( - name='IP_TUNNEL_APP', index=7, number=1024, + name='PRIVATE_APP', index=7, number=256, serialized_options=None, type=None, create_key=_descriptor._internal_create_key), @@ -103,7 +103,7 @@ _PORTNUM = _descriptor.EnumDescriptor( containing_type=None, serialized_options=None, serialized_start=19, - serialized_end=181, + serialized_end=180, ) _sym_db.RegisterEnumDescriptor(_PORTNUM) @@ -114,8 +114,8 @@ REMOTE_HARDWARE_APP = 2 POSITION_APP = 3 NODEINFO_APP = 4 REPLY_APP = 32 +IP_TUNNEL_APP = 33 PRIVATE_APP = 256 -IP_TUNNEL_APP = 1024 DESCRIPTOR.enum_types_by_name['PortNum'] = _PORTNUM diff --git a/docs/meshtastic/tunnel.html b/docs/meshtastic/tunnel.html new file mode 100644 index 0000000..115c93b --- /dev/null +++ b/docs/meshtastic/tunnel.html @@ -0,0 +1,553 @@ + + + + + + +meshtastic.tunnel API documentation + + + + + + + + + + + +
      +
      +
      +

      Module meshtastic.tunnel

      +
      +
      +
      + +Expand source code + +
      # code for IP tunnel over a mesh
      +# Note python-pytuntap was too buggy
      +# using pip3 install pytap2
      +# make sure to "sudo setcap cap_net_admin+eip /usr/bin/python3.8" so python can access tun device without being root
      +# sudo ip tuntap del mode tun tun0
      +# sudo bin/run.sh --port /dev/ttyUSB0 --setch-shortfast
      +# sudo bin/run.sh --port /dev/ttyUSB0 --tunnel --debug
      +# ssh -Y root@192.168.10.151 (or dietpi), default password p
      +# ncat -e /bin/cat -k -u -l 1235 
      +# ncat -u 10.115.64.152 1235
      +# ping -c 1 -W 20 10.115.64.152
      +
      +# FIXME: use a more optimal MTU
      +
      +from . import portnums_pb2
      +from pubsub import pub
      +from pytap2 import TapDevice
      +import logging
      +import threading
      +
      +# A new non standard log level that is lower level than DEBUG
      +LOG_TRACE = 5
      +
      +# fixme - find a way to move onTunnelReceive inside of the class
      +tunnelInstance = None
      +
      +"""A list of chatty UDP services we should never accidentally
      +forward to our slow network"""
      +udpBlacklist = {
      +    1900, # SSDP
      +    5353, # multicast DNS
      +}
      +
      +"""A list of TCP services to block"""
      +tcpBlacklist = {}
      +
      +"""A list of protocols we ignore"""
      +protocolBlacklist = {
      +    0x02, # IGMP
      +        0x80, # Service-Specific Connection-Oriented Protocol in a Multilink and Connectionless Environment
      +}
      +
      +def hexstr(barray):
      +    """Print a string of hex digits"""
      +    return ":".join('{:02x}'.format(x) for x in barray)
      +
      +def ipstr(barray):
      +    """Print a string of ip digits"""
      +    return ".".join('{}'.format(x) for x in barray)
      +
      +def readnet_u16(p, offset):
      +    """Read big endian u16 (network byte order)"""
      +    return p[offset] * 256 + p[offset + 1]
      +
      +def onTunnelReceive(packet, interface):
      +    """Callback for received tunneled messages from mesh
      +    
      +    FIXME figure out how to do closures with methods in python"""
      +    tunnelInstance.onReceive(packet)
      +
      +class Tunnel:
      +    """A TUN based IP tunnel over meshtastic"""
      +    
      +    def __init__(self, iface, subnet=None, netmask="255.255.0.0"):
      +        """
      +        Constructor
      +
      +        iface is the already open MeshInterface instance
      +        subnet is used to construct our network number (normally 10.115.x.x)
      +        """
      +
      +        if subnet is None:
      +            subnet = "10.115"
      +
      +        self.iface = iface
      +        self.subnetPrefix = subnet
      +
      +        global tunnelInstance
      +        tunnelInstance = self
      +
      +        logging.info("Starting IP to mesh tunnel (you must be root for this *pre-alpha* feature to work).  Mesh members:")
      +
      +        pub.subscribe(onTunnelReceive, "meshtastic.receive.data.IP_TUNNEL_APP")
      +        myAddr = self._nodeNumToIp(self.iface.myInfo.my_node_num)
      +
      +        for node in self.iface.nodes.values():
      +            nodeId = node["user"]["id"]
      +            ip = self._nodeNumToIp(node["num"])
      +            logging.info(f"Node { nodeId } has IP address { ip }")        
      +
      +        logging.debug("creating TUN device")
      +        # FIXME - figure out real max MTU, it should be 240 - the overhead bytes for SubPacket and Data
      +        self.tun = TapDevice(name="mesh", mtu=200)
      +        self.tun.up()
      +        self.tun.ifconfig(address=myAddr,netmask=netmask)
      +        logging.debug(f"starting TUN reader, our IP address is {myAddr}")
      +        self._rxThread = threading.Thread(target=self.__tunReader, args=(), daemon=True)
      +        self._rxThread.start()
      +
      +    def onReceive(self, packet):
      +        p = packet["decoded"]["data"]["payload"]
      +        if packet["from"] == self.iface.myInfo.my_node_num:
      +            logging.debug("Ignoring message we sent")
      +        else:
      +            logging.debug(f"Received mesh tunnel message type={type(p)} len={len(p)}")
      +            # we don't really need to check for filtering here (sender should have checked), but this provides
      +            # useful debug printing on types of packets received
      +            if not self._shouldFilterPacket(p):
      +                self.tun.write(p)
      +
      +    def _shouldFilterPacket(self, p):
      +        """Given a packet, decode it and return true if it should be ignored"""
      +        protocol = p[8 + 1]
      +        srcaddr = p[12:16]
      +        destAddr = p[16:20]
      +        subheader = 20
      +        ignore = False # Assume we will be forwarding the packet
      +        if protocol in protocolBlacklist:
      +            ignore = True
      +            logging.log(LOG_TRACE, f"Ignoring blacklisted protocol 0x{protocol:02x}")
      +        elif protocol == 0x01: # ICMP
      +            icmpType = p[20]
      +            icmpCode = p[21]
      +            checksum = p[22:24]
      +            logging.debug(f"forwarding ICMP message src={ipstr(srcaddr)}, dest={ipstr(destAddr)}, type={icmpType}, code={icmpCode}, checksum={checksum}")
      +            # reply to pings (swap src and dest but keep rest of packet unchanged)
      +            #pingback = p[:12]+p[16:20]+p[12:16]+p[20:]
      +            #tap.write(pingback)
      +        elif protocol == 0x11: # UDP
      +            srcport = readnet_u16(p, subheader)
      +            destport = readnet_u16(p, subheader + 2)
      +            if destport in udpBlacklist:
      +                ignore = True
      +                logging.log(LOG_TRACE, f"ignoring blacklisted UDP port {destport}")
      +            else:
      +                logging.debug(f"forwarding udp srcport={srcport}, destport={destport}")
      +        elif protocol == 0x06: # TCP
      +            srcport = readnet_u16(p, subheader)
      +            destport = readnet_u16(p, subheader + 2)
      +            if destport in tcpBlacklist:
      +                ignore = True
      +                logging.log(LOG_TRACE, f"ignoring blacklisted TCP port {destport}")
      +            else:
      +                logging.debug(f"forwarding tcp srcport={srcport}, destport={destport}")
      +        else:
      +            logging.warning(f"forwarding unexpected protocol 0x{protocol:02x}, src={ipstr(srcaddr)}, dest={ipstr(destAddr)}")
      +
      +        return ignore
      +
      +    def __tunReader(self):
      +        tap = self.tun
      +        logging.debug("TUN reader running")
      +        while True:
      +            p = tap.read()
      +            #logging.debug(f"IP packet received on TUN interface, type={type(p)}")
      +            destAddr = p[16:20]
      +
      +            if not self._shouldFilterPacket(p):
      +                self.sendPacket(destAddr, p)
      +
      +    def _ipToNodeId(self, ipAddr):
      +        # We only consider the last 16 bits of the nodenum for IP address matching
      +        ipBits = ipAddr[2] * 256 + ipAddr[3]
      +
      +        if ipBits == 0xffff:
      +            return "^all"
      +
      +        for node in self.iface.nodes.values():
      +            nodeNum = node["num"] & 0xffff
      +            # logging.debug(f"Considering nodenum 0x{nodeNum:x} for ipBits 0x{ipBits:x}")
      +            if (nodeNum) == ipBits:
      +                return node["user"]["id"]
      +        return None
      +
      +    def _nodeNumToIp(self, nodeNum):
      +        return f"{self.subnetPrefix}.{(nodeNum >> 8) & 0xff}.{nodeNum & 0xff}"
      +
      +    def sendPacket(self, destAddr, p):
      +        """Forward the provided IP packet into the mesh"""
      +        nodeId = self._ipToNodeId(destAddr)
      +        if nodeId is not None:
      +            logging.debug(f"Forwarding packet bytelen={len(p)} dest={ipstr(destAddr)}, destNode={nodeId}")
      +            self.iface.sendData(p, nodeId, portnums_pb2.IP_TUNNEL_APP, wantAck = False)
      +        else:
      +            logging.warning(f"Dropping packet because no node found for destIP={ipstr(destAddr)}")
      +
      +    def close(self):
      +        self.tun.close()
      +
      +
      +
      +
      +
      +

      Global variables

      +
      +
      var tcpBlacklist
      +
      +

      A list of protocols we ignore

      +
      +
      var tunnelInstance
      +
      +

      A list of chatty UDP services we should never accidentally +forward to our slow network

      +
      +
      var udpBlacklist
      +
      +

      A list of TCP services to block

      +
      +
      +
      +
      +

      Functions

      +
      +
      +def hexstr(barray) +
      +
      +

      Print a string of hex digits

      +
      + +Expand source code + +
      def hexstr(barray):
      +    """Print a string of hex digits"""
      +    return ":".join('{:02x}'.format(x) for x in barray)
      +
      +
      +
      +def ipstr(barray) +
      +
      +

      Print a string of ip digits

      +
      + +Expand source code + +
      def ipstr(barray):
      +    """Print a string of ip digits"""
      +    return ".".join('{}'.format(x) for x in barray)
      +
      +
      +
      +def onTunnelReceive(packet, interface) +
      +
      +

      Callback for received tunneled messages from mesh

      +

      FIXME figure out how to do closures with methods in python

      +
      + +Expand source code + +
      def onTunnelReceive(packet, interface):
      +    """Callback for received tunneled messages from mesh
      +    
      +    FIXME figure out how to do closures with methods in python"""
      +    tunnelInstance.onReceive(packet)
      +
      +
      +
      +def readnet_u16(p, offset) +
      +
      +

      Read big endian u16 (network byte order)

      +
      + +Expand source code + +
      def readnet_u16(p, offset):
      +    """Read big endian u16 (network byte order)"""
      +    return p[offset] * 256 + p[offset + 1]
      +
      +
      +
      +
      +
      +

      Classes

      +
      +
      +class Tunnel +(iface, subnet=None, netmask='255.255.0.0') +
      +
      +

      A TUN based IP tunnel over meshtastic

      +

      Constructor

      +

      iface is the already open MeshInterface instance +subnet is used to construct our network number (normally 10.115.x.x)

      +
      + +Expand source code + +
      class Tunnel:
      +    """A TUN based IP tunnel over meshtastic"""
      +    
      +    def __init__(self, iface, subnet=None, netmask="255.255.0.0"):
      +        """
      +        Constructor
      +
      +        iface is the already open MeshInterface instance
      +        subnet is used to construct our network number (normally 10.115.x.x)
      +        """
      +
      +        if subnet is None:
      +            subnet = "10.115"
      +
      +        self.iface = iface
      +        self.subnetPrefix = subnet
      +
      +        global tunnelInstance
      +        tunnelInstance = self
      +
      +        logging.info("Starting IP to mesh tunnel (you must be root for this *pre-alpha* feature to work).  Mesh members:")
      +
      +        pub.subscribe(onTunnelReceive, "meshtastic.receive.data.IP_TUNNEL_APP")
      +        myAddr = self._nodeNumToIp(self.iface.myInfo.my_node_num)
      +
      +        for node in self.iface.nodes.values():
      +            nodeId = node["user"]["id"]
      +            ip = self._nodeNumToIp(node["num"])
      +            logging.info(f"Node { nodeId } has IP address { ip }")        
      +
      +        logging.debug("creating TUN device")
      +        # FIXME - figure out real max MTU, it should be 240 - the overhead bytes for SubPacket and Data
      +        self.tun = TapDevice(name="mesh", mtu=200)
      +        self.tun.up()
      +        self.tun.ifconfig(address=myAddr,netmask=netmask)
      +        logging.debug(f"starting TUN reader, our IP address is {myAddr}")
      +        self._rxThread = threading.Thread(target=self.__tunReader, args=(), daemon=True)
      +        self._rxThread.start()
      +
      +    def onReceive(self, packet):
      +        p = packet["decoded"]["data"]["payload"]
      +        if packet["from"] == self.iface.myInfo.my_node_num:
      +            logging.debug("Ignoring message we sent")
      +        else:
      +            logging.debug(f"Received mesh tunnel message type={type(p)} len={len(p)}")
      +            # we don't really need to check for filtering here (sender should have checked), but this provides
      +            # useful debug printing on types of packets received
      +            if not self._shouldFilterPacket(p):
      +                self.tun.write(p)
      +
      +    def _shouldFilterPacket(self, p):
      +        """Given a packet, decode it and return true if it should be ignored"""
      +        protocol = p[8 + 1]
      +        srcaddr = p[12:16]
      +        destAddr = p[16:20]
      +        subheader = 20
      +        ignore = False # Assume we will be forwarding the packet
      +        if protocol in protocolBlacklist:
      +            ignore = True
      +            logging.log(LOG_TRACE, f"Ignoring blacklisted protocol 0x{protocol:02x}")
      +        elif protocol == 0x01: # ICMP
      +            icmpType = p[20]
      +            icmpCode = p[21]
      +            checksum = p[22:24]
      +            logging.debug(f"forwarding ICMP message src={ipstr(srcaddr)}, dest={ipstr(destAddr)}, type={icmpType}, code={icmpCode}, checksum={checksum}")
      +            # reply to pings (swap src and dest but keep rest of packet unchanged)
      +            #pingback = p[:12]+p[16:20]+p[12:16]+p[20:]
      +            #tap.write(pingback)
      +        elif protocol == 0x11: # UDP
      +            srcport = readnet_u16(p, subheader)
      +            destport = readnet_u16(p, subheader + 2)
      +            if destport in udpBlacklist:
      +                ignore = True
      +                logging.log(LOG_TRACE, f"ignoring blacklisted UDP port {destport}")
      +            else:
      +                logging.debug(f"forwarding udp srcport={srcport}, destport={destport}")
      +        elif protocol == 0x06: # TCP
      +            srcport = readnet_u16(p, subheader)
      +            destport = readnet_u16(p, subheader + 2)
      +            if destport in tcpBlacklist:
      +                ignore = True
      +                logging.log(LOG_TRACE, f"ignoring blacklisted TCP port {destport}")
      +            else:
      +                logging.debug(f"forwarding tcp srcport={srcport}, destport={destport}")
      +        else:
      +            logging.warning(f"forwarding unexpected protocol 0x{protocol:02x}, src={ipstr(srcaddr)}, dest={ipstr(destAddr)}")
      +
      +        return ignore
      +
      +    def __tunReader(self):
      +        tap = self.tun
      +        logging.debug("TUN reader running")
      +        while True:
      +            p = tap.read()
      +            #logging.debug(f"IP packet received on TUN interface, type={type(p)}")
      +            destAddr = p[16:20]
      +
      +            if not self._shouldFilterPacket(p):
      +                self.sendPacket(destAddr, p)
      +
      +    def _ipToNodeId(self, ipAddr):
      +        # We only consider the last 16 bits of the nodenum for IP address matching
      +        ipBits = ipAddr[2] * 256 + ipAddr[3]
      +
      +        if ipBits == 0xffff:
      +            return "^all"
      +
      +        for node in self.iface.nodes.values():
      +            nodeNum = node["num"] & 0xffff
      +            # logging.debug(f"Considering nodenum 0x{nodeNum:x} for ipBits 0x{ipBits:x}")
      +            if (nodeNum) == ipBits:
      +                return node["user"]["id"]
      +        return None
      +
      +    def _nodeNumToIp(self, nodeNum):
      +        return f"{self.subnetPrefix}.{(nodeNum >> 8) & 0xff}.{nodeNum & 0xff}"
      +
      +    def sendPacket(self, destAddr, p):
      +        """Forward the provided IP packet into the mesh"""
      +        nodeId = self._ipToNodeId(destAddr)
      +        if nodeId is not None:
      +            logging.debug(f"Forwarding packet bytelen={len(p)} dest={ipstr(destAddr)}, destNode={nodeId}")
      +            self.iface.sendData(p, nodeId, portnums_pb2.IP_TUNNEL_APP, wantAck = False)
      +        else:
      +            logging.warning(f"Dropping packet because no node found for destIP={ipstr(destAddr)}")
      +
      +    def close(self):
      +        self.tun.close()
      +
      +

      Methods

      +
      +
      +def close(self) +
      +
      +
      +
      + +Expand source code + +
      def close(self):
      +    self.tun.close()
      +
      +
      +
      +def onReceive(self, packet) +
      +
      +
      +
      + +Expand source code + +
      def onReceive(self, packet):
      +    p = packet["decoded"]["data"]["payload"]
      +    if packet["from"] == self.iface.myInfo.my_node_num:
      +        logging.debug("Ignoring message we sent")
      +    else:
      +        logging.debug(f"Received mesh tunnel message type={type(p)} len={len(p)}")
      +        # we don't really need to check for filtering here (sender should have checked), but this provides
      +        # useful debug printing on types of packets received
      +        if not self._shouldFilterPacket(p):
      +            self.tun.write(p)
      +
      +
      +
      +def sendPacket(self, destAddr, p) +
      +
      +

      Forward the provided IP packet into the mesh

      +
      + +Expand source code + +
      def sendPacket(self, destAddr, p):
      +    """Forward the provided IP packet into the mesh"""
      +    nodeId = self._ipToNodeId(destAddr)
      +    if nodeId is not None:
      +        logging.debug(f"Forwarding packet bytelen={len(p)} dest={ipstr(destAddr)}, destNode={nodeId}")
      +        self.iface.sendData(p, nodeId, portnums_pb2.IP_TUNNEL_APP, wantAck = False)
      +    else:
      +        logging.warning(f"Dropping packet because no node found for destIP={ipstr(destAddr)}")
      +
      +
      +
      +
      +
      +
      +
      + +
      + + + \ No newline at end of file diff --git a/setup.py b/setup.py index b832b85..c5b6d85 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ with open("README.md", "r") as fh: # This call to setup() does all the work setup( name="meshtastic", - version="1.1.25", + version="1.1.26", description="Python API & client shell for talking to Meshtastic devices", long_description=long_description, long_description_content_type="text/markdown",