Skip to content

Commit

Permalink
Merge pull request #546 from ianmcorvidae/request-position
Browse files Browse the repository at this point in the history
Add a `--request-position` argument to request positions from nodes
  • Loading branch information
ianmcorvidae authored Apr 16, 2024
2 parents 948846e + e8ba558 commit bdf3a24
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 7 deletions.
17 changes: 16 additions & 1 deletion meshtastic/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.")
Expand Down Expand Up @@ -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",
)
Expand Down
50 changes: 44 additions & 6 deletions meshtastic/mesh_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,13 +381,50 @@ def sendPosition(
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"""
Expand Down Expand Up @@ -445,11 +482,6 @@ def sendTelemetry(self, destinationId=BROADCAST_ADDR, wantResponse=False):
else:
onResponse = None

if destinationId.startswith("!"):
destinationId = int(destinationId[1:], 16)
else:
destinationId = int(destinationId)

self.sendData(
r,
destinationId=destinationId,
Expand Down Expand Up @@ -573,6 +605,12 @@ def waitForTelemetry(self):
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:
Expand Down
12 changes: 12 additions & 0 deletions meshtastic/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,16 @@ def waitForTelemetry(self, acknowledgment) -> bool:
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."

Expand All @@ -216,6 +226,7 @@ def __init__(self):
self.receivedImplAck = False
self.receivedTraceRoute = False
self.receivedTelemetry = False
self.receivedPosition = False

def reset(self):
"""reset"""
Expand All @@ -224,6 +235,7 @@ def reset(self):
self.receivedImplAck = False
self.receivedTraceRoute = False
self.receivedTelemetry = False
self.receivedPosition = False


class DeferredExecution:
Expand Down

0 comments on commit bdf3a24

Please sign in to comment.