Add a --request-position argument to request positions from nodes

This commit is contained in:
Ian McEwen
2024-04-16 15:43:24 -07:00
parent 948846e0f1
commit e8ba5581f6
3 changed files with 72 additions and 7 deletions

View File

@@ -435,6 +435,13 @@ def onConnected(interface):
print(f"Sending telemetry request to {args.dest} (this could take a while)")
interface.sendTelemetry(destinationId=args.dest, wantResponse=True)
if args.request_position:
if args.dest == BROADCAST_ADDR:
meshtastic.util.our_exit("Warning: Must use a destination node ID.")
else:
print(f"Sending position request to {args.dest} (this could take a while)")
interface.sendPosition(destinationId=args.dest, wantResponse=True)
if args.gpio_wrb or args.gpio_rd or args.gpio_watch:
if args.dest == BROADCAST_ADDR:
meshtastic.util.our_exit("Warning: Must use a destination node ID.")
@@ -1299,7 +1306,15 @@ def initParser():
group.add_argument(
"--request-telemetry",
help="Request telemetry from a node. "
"You need pass the destination ID as argument with '--dest'. "
"You need to pass the destination ID as argument with '--dest'. "
"For repeaters, the nodeNum is required.",
action="store_true",
)
group.add_argument(
"--request-position",
help="Request the position from a nade. "
"You need to pass the destination ID as an argument with '--dest'. "
"For repeaters, the nodeNum is required.",
action="store_true",
)

View File

@@ -381,13 +381,50 @@ class MeshInterface:
p.time = timeSec
logging.debug(f"p.time:{p.time}")
return self.sendData(
if wantResponse:
onResponse = self.onResponsePosition
else:
onResponse = None
d = self.sendData(
p,
destinationId,
portNum=portnums_pb2.PortNum.POSITION_APP,
wantAck=wantAck,
wantResponse=wantResponse,
onResponse=onResponse,
)
if wantResponse:
self.waitForPosition()
return d
def onResponsePosition(self, p):
"""on response for position"""
if p["decoded"]["portnum"] == 'POSITION_APP':
self._acknowledgment.receivedPosition = True
position = mesh_pb2.Position()
position.ParseFromString(p["decoded"]["payload"])
ret = "Position received: "
if position.latitude_i != 0 and position.longitude_i != 0:
ret += f"({position.latitude_i * 10**-7}, {position.longitude_i * 10**-7})"
else:
ret += "(unknown)"
if position.altitude != 0:
ret += f" {position.altitude}m"
if position.precision_bits not in [0,32]:
ret += f" precision:{position.precision_bits}"
elif position.precision_bits == 32:
ret += " full precision"
elif position.precision_bits == 0:
ret += " position disabled"
print(ret)
elif p["decoded"]["portnum"] == 'ROUTING_APP':
if p["decoded"]["routing"]["errorReason"] == 'NO_RESPONSE':
our_exit("No response from node. At least firmware 2.1.22 is required on the destination node.")
def sendTraceRoute(self, dest: Union[int, str], hopLimit: int):
"""Send the trace route"""
@@ -445,11 +482,6 @@ class MeshInterface:
else:
onResponse = None
if destinationId.startswith("!"):
destinationId = int(destinationId[1:], 16)
else:
destinationId = int(destinationId)
self.sendData(
r,
destinationId=destinationId,
@@ -573,6 +605,12 @@ class MeshInterface:
if not success:
raise MeshInterface.MeshInterfaceError("Timed out waiting for telemetry")
def waitForPosition(self):
"""Wait for position"""
success = self._timeout.waitForPosition(self._acknowledgment)
if not success:
raise MeshInterface.MeshInterfaceError("Timed out waiting for position")
def getMyNodeInfo(self) -> Optional[Dict]:
"""Get info about my node."""
if self.myInfo is None or self.nodesByNum is None:

View File

@@ -206,6 +206,16 @@ class Timeout:
time.sleep(self.sleepInterval)
return False
def waitForPosition(self, acknowledgment) -> bool:
"""Block until position response is received. Returns True if position response has been received."""
self.reset()
while time.time() < self.expireTime:
if getattr(acknowledgment, "receivedPosition", None):
acknowledgment.reset()
return True
time.sleep(self.sleepInterval)
return False
class Acknowledgment:
"A class that records which type of acknowledgment was just received, if any."
@@ -216,6 +226,7 @@ class Acknowledgment:
self.receivedImplAck = False
self.receivedTraceRoute = False
self.receivedTelemetry = False
self.receivedPosition = False
def reset(self):
"""reset"""
@@ -224,6 +235,7 @@ class Acknowledgment:
self.receivedImplAck = False
self.receivedTraceRoute = False
self.receivedTelemetry = False
self.receivedPosition = False
class DeferredExecution: