mirror of
https://github.com/meshtastic/python.git
synced 2025-12-31 11:57:57 -05:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ddc47fb8de | ||
|
|
7ee134b819 | ||
|
|
254e9f4015 | ||
|
|
cc99ea009e | ||
|
|
76407e11f8 | ||
|
|
57719ddd5e | ||
|
|
d0b8b9ff1b | ||
|
|
c5c9723208 | ||
|
|
9bceaafd9c | ||
|
|
7d3a9178ea | ||
|
|
2c76c0cafa | ||
|
|
82977e9ef2 | ||
|
|
7a9c25da8e | ||
|
|
342c48fb16 | ||
|
|
6bc955a403 |
@@ -1,6 +1,6 @@
|
|||||||
# Meshtastic Python
|
# Meshtastic Python
|
||||||
|
|
||||||
[](https://codecov.io/gh/meshtastic/python)
|
[](https://codecov.io/gh/meshtastic/Meshtastic-python)
|
||||||

|

|
||||||
[](https://github.com/meshtastic/python/actions/workflows/ci.yml)
|
[](https://github.com/meshtastic/python/actions/workflows/ci.yml)
|
||||||
[](https://cla-assistant.io/meshtastic/python)
|
[](https://cla-assistant.io/meshtastic/python)
|
||||||
|
|||||||
@@ -183,5 +183,6 @@ protocols = {
|
|||||||
portnums_pb2.PortNum.ROUTING_APP: KnownProtocol("routing", mesh_pb2.Routing),
|
portnums_pb2.PortNum.ROUTING_APP: KnownProtocol("routing", mesh_pb2.Routing),
|
||||||
portnums_pb2.PortNum.TELEMETRY_APP: KnownProtocol("telemetry", telemetry_pb2.Telemetry),
|
portnums_pb2.PortNum.TELEMETRY_APP: KnownProtocol("telemetry", telemetry_pb2.Telemetry),
|
||||||
portnums_pb2.PortNum.REMOTE_HARDWARE_APP: KnownProtocol("remotehw", remote_hardware_pb2.HardwareMessage),
|
portnums_pb2.PortNum.REMOTE_HARDWARE_APP: KnownProtocol("remotehw", remote_hardware_pb2.HardwareMessage),
|
||||||
portnums_pb2.PortNum.SIMULATOR_APP: KnownProtocol("simulator", mesh_pb2.Compressed)
|
portnums_pb2.PortNum.SIMULATOR_APP: KnownProtocol("simulator", mesh_pb2.Compressed),
|
||||||
|
portnums_pb2.PortNum.TRACEROUTE_APP: KnownProtocol("traceroute", mesh_pb2.RouteDiscovery)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -330,6 +330,13 @@ def onConnected(interface):
|
|||||||
interface.sendData(payload, args.dest, portNum=portnums_pb2.PortNum.REPLY_APP,
|
interface.sendData(payload, args.dest, portNum=portnums_pb2.PortNum.REPLY_APP,
|
||||||
wantAck=True, wantResponse=True)
|
wantAck=True, wantResponse=True)
|
||||||
|
|
||||||
|
if args.traceroute:
|
||||||
|
loraConfig = getattr(interface.localNode.localConfig, 'lora')
|
||||||
|
hopLimit = getattr(loraConfig, 'hop_limit')
|
||||||
|
dest = str(args.traceroute)
|
||||||
|
print(f"Sending traceroute request to {dest} (this could take a while)")
|
||||||
|
interface.sendTraceRoute(dest, hopLimit)
|
||||||
|
|
||||||
if args.gpio_wrb or args.gpio_rd or args.gpio_watch:
|
if args.gpio_wrb or args.gpio_rd or args.gpio_watch:
|
||||||
if args.dest == BROADCAST_ADDR:
|
if args.dest == BROADCAST_ADDR:
|
||||||
meshtastic.util.our_exit("Warning: Must use a destination node ID.")
|
meshtastic.util.our_exit("Warning: Must use a destination node ID.")
|
||||||
@@ -889,7 +896,7 @@ def initParser():
|
|||||||
"--ch-set", help=("Set a channel parameter. To see channel settings available:'--ch-set all all --ch-index 0'. "
|
"--ch-set", help=("Set a channel parameter. To see channel settings available:'--ch-set all all --ch-index 0'. "
|
||||||
"Can set the 'psk' using this command. To disable encryption on primary channel:'--ch-set psk none --ch-index 0'. "
|
"Can set the 'psk' using this command. To disable encryption on primary channel:'--ch-set psk none --ch-index 0'. "
|
||||||
"To set encryption with a new random key on second channel:'--ch-set psk random --ch-index 1'. "
|
"To set encryption with a new random key on second channel:'--ch-set psk random --ch-index 1'. "
|
||||||
"To set encryption back to the default:'--ch-set default --ch-index 0'. To set encryption with your "
|
"To set encryption back to the default:'--ch-set psk default --ch-index 0'. To set encryption with your "
|
||||||
"own key: '--ch-set psk 0x1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b --ch-index 0'."),
|
"own key: '--ch-set psk 0x1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b --ch-index 0'."),
|
||||||
nargs=2, action='append')
|
nargs=2, action='append')
|
||||||
|
|
||||||
@@ -935,6 +942,12 @@ def initParser():
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--sendping", help="Send a ping message (which requests a reply)", action="store_true")
|
"--sendping", help="Send a ping message (which requests a reply)", action="store_true")
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"--traceroute", help="Traceroute from connected node to a destination. " \
|
||||||
|
"You need pass the destination ID as argument, like " \
|
||||||
|
"this: '--traceroute !ba4bf9d0' " \
|
||||||
|
"Only nodes that have the encryption key can be traced.")
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--reboot", help="Tell the destination node to reboot", action="store_true")
|
"--reboot", help="Tell the destination node to reboot", action="store_true")
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -53,7 +53,6 @@ class MeshInterface:
|
|||||||
self.currentPacketId = random.randint(0, 0xffffffff)
|
self.currentPacketId = random.randint(0, 0xffffffff)
|
||||||
self.nodesByNum = None
|
self.nodesByNum = None
|
||||||
self.configId = None
|
self.configId = None
|
||||||
self.defaultHopLimit = 3
|
|
||||||
self.gotResponse = False # used in gpio read
|
self.gotResponse = False # used in gpio read
|
||||||
self.mask = None # used in gpio read and gpio watch
|
self.mask = None # used in gpio read and gpio watch
|
||||||
|
|
||||||
@@ -176,7 +175,6 @@ class MeshInterface:
|
|||||||
destinationId=BROADCAST_ADDR,
|
destinationId=BROADCAST_ADDR,
|
||||||
wantAck=False,
|
wantAck=False,
|
||||||
wantResponse=False,
|
wantResponse=False,
|
||||||
hopLimit=None,
|
|
||||||
onResponse=None,
|
onResponse=None,
|
||||||
channelIndex=0):
|
channelIndex=0):
|
||||||
"""Send a utf8 string to some other node, if the node has a display it
|
"""Send a utf8 string to some other node, if the node has a display it
|
||||||
@@ -198,21 +196,17 @@ class MeshInterface:
|
|||||||
Returns the sent packet. The id field will be populated in this packet
|
Returns the sent packet. The id field will be populated in this packet
|
||||||
and can be used to track future message acks/naks.
|
and can be used to track future message acks/naks.
|
||||||
"""
|
"""
|
||||||
if hopLimit is None:
|
|
||||||
hopLimit = self.defaultHopLimit
|
|
||||||
|
|
||||||
return self.sendData(text.encode("utf-8"), destinationId,
|
return self.sendData(text.encode("utf-8"), destinationId,
|
||||||
portNum=portnums_pb2.PortNum.TEXT_MESSAGE_APP,
|
portNum=portnums_pb2.PortNum.TEXT_MESSAGE_APP,
|
||||||
wantAck=wantAck,
|
wantAck=wantAck,
|
||||||
wantResponse=wantResponse,
|
wantResponse=wantResponse,
|
||||||
hopLimit=hopLimit,
|
|
||||||
onResponse=onResponse,
|
onResponse=onResponse,
|
||||||
channelIndex=channelIndex)
|
channelIndex=channelIndex)
|
||||||
|
|
||||||
def sendData(self, data, destinationId=BROADCAST_ADDR,
|
def sendData(self, data, destinationId=BROADCAST_ADDR,
|
||||||
portNum=portnums_pb2.PortNum.PRIVATE_APP, wantAck=False,
|
portNum=portnums_pb2.PortNum.PRIVATE_APP, wantAck=False,
|
||||||
wantResponse=False,
|
wantResponse=False,
|
||||||
hopLimit=None,
|
|
||||||
onResponse=None,
|
onResponse=None,
|
||||||
channelIndex=0):
|
channelIndex=0):
|
||||||
"""Send a data packet to some other node
|
"""Send a data packet to some other node
|
||||||
@@ -237,8 +231,6 @@ class MeshInterface:
|
|||||||
Returns the sent packet. The id field will be populated in this packet
|
Returns the sent packet. The id field will be populated in this packet
|
||||||
and can be used to track future message acks/naks.
|
and can be used to track future message acks/naks.
|
||||||
"""
|
"""
|
||||||
if hopLimit is None:
|
|
||||||
hopLimit = self.defaultHopLimit
|
|
||||||
|
|
||||||
if getattr(data, "SerializeToString", None):
|
if getattr(data, "SerializeToString", None):
|
||||||
logging.debug(f"Serializing protobuf as data: {stripnl(data)}")
|
logging.debug(f"Serializing protobuf as data: {stripnl(data)}")
|
||||||
@@ -261,8 +253,7 @@ class MeshInterface:
|
|||||||
|
|
||||||
if onResponse is not None:
|
if onResponse is not None:
|
||||||
self._addResponseHandler(meshPacket.id, onResponse)
|
self._addResponseHandler(meshPacket.id, onResponse)
|
||||||
p = self._sendPacket(meshPacket, destinationId,
|
p = self._sendPacket(meshPacket, destinationId, wantAck=wantAck)
|
||||||
wantAck=wantAck, hopLimit=hopLimit)
|
|
||||||
return p
|
return p
|
||||||
|
|
||||||
def sendPosition(self, latitude=0.0, longitude=0.0, altitude=0, timeSec=0,
|
def sendPosition(self, latitude=0.0, longitude=0.0, altitude=0, timeSec=0,
|
||||||
@@ -300,21 +291,42 @@ class MeshInterface:
|
|||||||
portNum=portnums_pb2.PortNum.POSITION_APP,
|
portNum=portnums_pb2.PortNum.POSITION_APP,
|
||||||
wantAck=wantAck,
|
wantAck=wantAck,
|
||||||
wantResponse=wantResponse)
|
wantResponse=wantResponse)
|
||||||
|
|
||||||
|
def sendTraceRoute(self, dest, hopLimit):
|
||||||
|
r = mesh_pb2.RouteDiscovery()
|
||||||
|
self.sendData(r, destinationId=dest, portNum=portnums_pb2.PortNum.TRACEROUTE_APP,
|
||||||
|
wantResponse=True, onResponse=self.onResponseTraceRoute)
|
||||||
|
# extend timeout based on number of nodes, limit by configured hopLimit
|
||||||
|
waitFactor = min(len(self.nodes)-1, hopLimit)
|
||||||
|
self.waitForTraceRoute(waitFactor)
|
||||||
|
|
||||||
|
def onResponseTraceRoute(self, p):
|
||||||
|
routeDiscovery = mesh_pb2.RouteDiscovery()
|
||||||
|
routeDiscovery.ParseFromString(p["decoded"]["payload"])
|
||||||
|
asDict = google.protobuf.json_format.MessageToDict(routeDiscovery)
|
||||||
|
|
||||||
|
print("Route traced:")
|
||||||
|
routeStr = self._nodeNumToId(p["to"])
|
||||||
|
if "route" in asDict:
|
||||||
|
for nodeNum in asDict["route"]:
|
||||||
|
routeStr += " --> " + self._nodeNumToId(nodeNum)
|
||||||
|
routeStr += " --> " + self._nodeNumToId(p["from"])
|
||||||
|
print(routeStr)
|
||||||
|
|
||||||
|
self._acknowledgment.receivedTraceRoute = True
|
||||||
|
|
||||||
def _addResponseHandler(self, requestId, callback):
|
def _addResponseHandler(self, requestId, callback):
|
||||||
self.responseHandlers[requestId] = ResponseHandler(callback)
|
self.responseHandlers[requestId] = ResponseHandler(callback)
|
||||||
|
|
||||||
def _sendPacket(self, meshPacket,
|
def _sendPacket(self, meshPacket,
|
||||||
destinationId=BROADCAST_ADDR,
|
destinationId=BROADCAST_ADDR,
|
||||||
wantAck=False, hopLimit=None):
|
wantAck=False):
|
||||||
"""Send a MeshPacket to the specified node (or if unspecified, broadcast).
|
"""Send a MeshPacket to the specified node (or if unspecified, broadcast).
|
||||||
You probably don't want this - use sendData instead.
|
You probably don't want this - use sendData instead.
|
||||||
|
|
||||||
Returns the sent packet. The id field will be populated in this packet and
|
Returns the sent packet. The id field will be populated in this packet and
|
||||||
can be used to track future message acks/naks.
|
can be used to track future message acks/naks.
|
||||||
"""
|
"""
|
||||||
if hopLimit is None:
|
|
||||||
hopLimit = self.defaultHopLimit
|
|
||||||
|
|
||||||
# We allow users to talk to the local node before we've completed the full connection flow...
|
# We allow users to talk to the local node before we've completed the full connection flow...
|
||||||
if(self.myInfo is not None and destinationId != self.myInfo.my_node_num):
|
if(self.myInfo is not None and destinationId != self.myInfo.my_node_num):
|
||||||
@@ -348,6 +360,8 @@ class MeshInterface:
|
|||||||
|
|
||||||
meshPacket.to = nodeNum
|
meshPacket.to = nodeNum
|
||||||
meshPacket.want_ack = wantAck
|
meshPacket.want_ack = wantAck
|
||||||
|
loraConfig = getattr(self.localNode.localConfig, 'lora')
|
||||||
|
hopLimit = getattr(loraConfig, 'hop_limit')
|
||||||
meshPacket.hop_limit = hopLimit
|
meshPacket.hop_limit = hopLimit
|
||||||
|
|
||||||
# if the user hasn't set an ID for this packet (likely and recommended),
|
# if the user hasn't set an ID for this packet (likely and recommended),
|
||||||
@@ -374,6 +388,11 @@ class MeshInterface:
|
|||||||
if not success:
|
if not success:
|
||||||
raise Exception("Timed out waiting for an acknowledgment")
|
raise Exception("Timed out waiting for an acknowledgment")
|
||||||
|
|
||||||
|
def waitForTraceRoute(self, waitFactor):
|
||||||
|
success = self._timeout.waitForTraceRoute(waitFactor, self._acknowledgment)
|
||||||
|
if not success:
|
||||||
|
raise Exception("Timed out waiting for traceroute")
|
||||||
|
|
||||||
def getMyNodeInfo(self):
|
def getMyNodeInfo(self):
|
||||||
"""Get info about my node."""
|
"""Get info about my node."""
|
||||||
if self.myInfo is None:
|
if self.myInfo is None:
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -521,8 +521,8 @@ class Node:
|
|||||||
onResponse = self.onAckNak
|
onResponse = self.onAckNak
|
||||||
return self._sendAdmin(p, onResponse=onResponse)
|
return self._sendAdmin(p, onResponse=onResponse)
|
||||||
|
|
||||||
def getMetadata(self, secs: int = 10):
|
def getMetadata(self):
|
||||||
"""Tell the node to shutdown."""
|
"""Get the node's metadata."""
|
||||||
p = admin_pb2.AdminMessage()
|
p = admin_pb2.AdminMessage()
|
||||||
p.get_device_metadata_request = True
|
p.get_device_metadata_request = True
|
||||||
logging.info(f"Requesting device metadata")
|
logging.info(f"Requesting device metadata")
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ _sym_db = _symbol_database.Default()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0eportnums.proto*\x90\x03\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\x0f\n\x0bROUTING_APP\x10\x05\x12\r\n\tADMIN_APP\x10\x06\x12\x1f\n\x1bTEXT_MESSAGE_COMPRESSED_APP\x10\x07\x12\x10\n\x0cWAYPOINT_APP\x10\x08\x12\r\n\tAUDIO_APP\x10\t\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12\x11\n\rTELEMETRY_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\x11\n\rSIMULATOR_APP\x10\x45\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42\x45\n\x13\x63om.geeksville.meshB\x08PortnumsH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
|
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0eportnums.proto*\xa4\x03\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\x0f\n\x0bROUTING_APP\x10\x05\x12\r\n\tADMIN_APP\x10\x06\x12\x1f\n\x1bTEXT_MESSAGE_COMPRESSED_APP\x10\x07\x12\x10\n\x0cWAYPOINT_APP\x10\x08\x12\r\n\tAUDIO_APP\x10\t\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12\x11\n\rTELEMETRY_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\x11\n\rSIMULATOR_APP\x10\x45\x12\x12\n\x0eTRACEROUTE_APP\x10\x46\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42\x45\n\x13\x63om.geeksville.meshB\x08PortnumsH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
|
||||||
|
|
||||||
_PORTNUM = DESCRIPTOR.enum_types_by_name['PortNum']
|
_PORTNUM = DESCRIPTOR.enum_types_by_name['PortNum']
|
||||||
PortNum = enum_type_wrapper.EnumTypeWrapper(_PORTNUM)
|
PortNum = enum_type_wrapper.EnumTypeWrapper(_PORTNUM)
|
||||||
@@ -37,6 +37,7 @@ RANGE_TEST_APP = 66
|
|||||||
TELEMETRY_APP = 67
|
TELEMETRY_APP = 67
|
||||||
ZPS_APP = 68
|
ZPS_APP = 68
|
||||||
SIMULATOR_APP = 69
|
SIMULATOR_APP = 69
|
||||||
|
TRACEROUTE_APP = 70
|
||||||
PRIVATE_APP = 256
|
PRIVATE_APP = 256
|
||||||
ATAK_FORWARDER = 257
|
ATAK_FORWARDER = 257
|
||||||
MAX = 511
|
MAX = 511
|
||||||
@@ -47,5 +48,5 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|||||||
DESCRIPTOR._options = None
|
DESCRIPTOR._options = None
|
||||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\010PortnumsH\003Z\"github.com/meshtastic/go/generated'
|
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\010PortnumsH\003Z\"github.com/meshtastic/go/generated'
|
||||||
_PORTNUM._serialized_start=19
|
_PORTNUM._serialized_start=19
|
||||||
_PORTNUM._serialized_end=419
|
_PORTNUM._serialized_end=439
|
||||||
# @@protoc_insertion_point(module_scope)
|
# @@protoc_insertion_point(module_scope)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ def onGPIOreceive(packet, interface):
|
|||||||
|
|
||||||
#print(f'mask:{interface.mask}')
|
#print(f'mask:{interface.mask}')
|
||||||
value = int(gpioValue) & int(interface.mask)
|
value = int(gpioValue) & int(interface.mask)
|
||||||
print(f'Received RemoteHardware typ={hw["typ"]}, gpio_value={gpioValue} value={value}')
|
print(f'Received RemoteHardware type={hw["type"]}, gpio_value={gpioValue} value={value}')
|
||||||
interface.gotResponse = True
|
interface.gotResponse = True
|
||||||
|
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ class RemoteHardwareClient:
|
|||||||
"""
|
"""
|
||||||
logging.debug(f'writeGPIOs nodeid:{nodeid} mask:{mask} vals:{vals}')
|
logging.debug(f'writeGPIOs nodeid:{nodeid} mask:{mask} vals:{vals}')
|
||||||
r = remote_hardware_pb2.HardwareMessage()
|
r = remote_hardware_pb2.HardwareMessage()
|
||||||
r.typ = remote_hardware_pb2.HardwareMessage.Type.WRITE_GPIOS
|
r.type = remote_hardware_pb2.HardwareMessage.Type.WRITE_GPIOS
|
||||||
r.gpio_mask = mask
|
r.gpio_mask = mask
|
||||||
r.gpio_value = vals
|
r.gpio_value = vals
|
||||||
return self._sendHardware(nodeid, r)
|
return self._sendHardware(nodeid, r)
|
||||||
@@ -75,7 +75,7 @@ class RemoteHardwareClient:
|
|||||||
"""Read the specified bits from GPIO inputs on the device"""
|
"""Read the specified bits from GPIO inputs on the device"""
|
||||||
logging.debug(f'readGPIOs nodeid:{nodeid} mask:{mask}')
|
logging.debug(f'readGPIOs nodeid:{nodeid} mask:{mask}')
|
||||||
r = remote_hardware_pb2.HardwareMessage()
|
r = remote_hardware_pb2.HardwareMessage()
|
||||||
r.typ = remote_hardware_pb2.HardwareMessage.Type.READ_GPIOS
|
r.type = remote_hardware_pb2.HardwareMessage.Type.READ_GPIOS
|
||||||
r.gpio_mask = mask
|
r.gpio_mask = mask
|
||||||
return self._sendHardware(nodeid, r, wantResponse=True, onResponse=onResponse)
|
return self._sendHardware(nodeid, r, wantResponse=True, onResponse=onResponse)
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ class RemoteHardwareClient:
|
|||||||
"""Watch the specified bits from GPIO inputs on the device for changes"""
|
"""Watch the specified bits from GPIO inputs on the device for changes"""
|
||||||
logging.debug(f'watchGPIOs nodeid:{nodeid} mask:{mask}')
|
logging.debug(f'watchGPIOs nodeid:{nodeid} mask:{mask}')
|
||||||
r = remote_hardware_pb2.HardwareMessage()
|
r = remote_hardware_pb2.HardwareMessage()
|
||||||
r.typ = remote_hardware_pb2.HardwareMessage.Type.WATCH_GPIOS
|
r.type = remote_hardware_pb2.HardwareMessage.Type.WATCH_GPIOS
|
||||||
r.gpio_mask = mask
|
r.gpio_mask = mask
|
||||||
self.iface.mask = mask
|
self.iface.mask = mask
|
||||||
return self._sendHardware(nodeid, r)
|
return self._sendHardware(nodeid, r)
|
||||||
|
|||||||
@@ -169,17 +169,30 @@ class Timeout:
|
|||||||
time.sleep(self.sleepInterval)
|
time.sleep(self.sleepInterval)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def waitForTraceRoute(self, waitFactor, acknowledgment, attr='receivedTraceRoute'):
|
||||||
|
"""Block until traceroute response is received. Returns True if traceroute response has been received."""
|
||||||
|
self.expireTimeout *= waitFactor
|
||||||
|
self.reset()
|
||||||
|
while time.time() < self.expireTime:
|
||||||
|
if getattr(acknowledgment, attr, None):
|
||||||
|
acknowledgment.reset()
|
||||||
|
return True
|
||||||
|
time.sleep(self.sleepInterval)
|
||||||
|
return False
|
||||||
|
|
||||||
class Acknowledgment:
|
class Acknowledgment:
|
||||||
"A class that records which type of acknowledgment was just received, if any."
|
"A class that records which type of acknowledgment was just received, if any."
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.receivedAck = False
|
self.receivedAck = False
|
||||||
self.receivedNak = False
|
self.receivedNak = False
|
||||||
self.receivedImplAck = False
|
self.receivedImplAck = False
|
||||||
|
self.receivedTraceRoute = False
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
self.receivedAck = False
|
self.receivedAck = False
|
||||||
self.receivedNak = False
|
self.receivedNak = False
|
||||||
self.receivedImplAck = False
|
self.receivedImplAck = False
|
||||||
|
self.receivedTraceRoute = False
|
||||||
|
|
||||||
class DeferredExecution():
|
class DeferredExecution():
|
||||||
"""A thread that accepts closures to run, and runs them as they are received"""
|
"""A thread that accepts closures to run, and runs them as they are received"""
|
||||||
|
|||||||
Submodule protobufs updated: 24874086e3...c4c484d9a3
2
setup.py
2
setup.py
@@ -12,7 +12,7 @@ with open("README.md", "r") as fh:
|
|||||||
# This call to setup() does all the work
|
# This call to setup() does all the work
|
||||||
setup(
|
setup(
|
||||||
name="meshtastic",
|
name="meshtastic",
|
||||||
version="2.0.4",
|
version="2.0.6",
|
||||||
description="Python API & client shell for talking to Meshtastic devices",
|
description="Python API & client shell for talking to Meshtastic devices",
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type="text/markdown",
|
||||||
|
|||||||
Reference in New Issue
Block a user