From 7cc18e9df627a8730fdd1777789230c239bf5e0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Fejoz?= Date: Sat, 21 Dec 2024 10:36:36 +0100 Subject: [PATCH] fix(waypoint): Missing methods Add missing methods callbacks regarding waypoints. --- examples/waypoint.py | 2 +- meshtastic/mesh_interface.py | 21 +++++++++++++++++++++ meshtastic/util.py | 12 ++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/examples/waypoint.py b/examples/waypoint.py index 57d2e901..1ce862df 100644 --- a/examples/waypoint.py +++ b/examples/waypoint.py @@ -1,7 +1,7 @@ """Program to create and delete waypoint To run: python3 examples/waypoint.py --port /dev/ttyUSB0 create 45 test the_desc_2 '2024-12-18T23:05:23' 48.74 7.35 - python examples/waypoint.py delete 45 + python3 examples/waypoint.py delete 45 """ import argparse diff --git a/meshtastic/mesh_interface.py b/meshtastic/mesh_interface.py index 3f5a1b19..5f7ba251 100644 --- a/meshtastic/mesh_interface.py +++ b/meshtastic/mesh_interface.py @@ -702,6 +702,19 @@ def onResponseTelemetry(self, p: dict): "No response from node. At least firmware 2.1.22 is required on the destination node." ) + def onResponseWaypoint(self, p: dict): + """on response for waypoint""" + if p["decoded"]["portnum"] == "WAYPOINT_APP": + self._acknowledgment.receivedWaypoint = True + w = mesh_pb2.Waypoint() + w.ParseFromString(p["decoded"]["payload"]) + print(f"Waypoint received: {w}") + 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 sendWaypoint( self, name, @@ -726,6 +739,8 @@ def sendWaypoint( w.description = description w.expire = expire if id is None: + # Generate a waypoint's id, NOT a packet ID. + # same algorithm as https://github.com/meshtastic/js/blob/715e35d2374276a43ffa93c628e3710875d43907/src/meshDevice.ts#L791 seed = secrets.randbits(32) w.id = math.floor(seed * math.pow(2, -32) * 1e9) logging.debug(f"w.id:{w.id}") @@ -918,6 +933,12 @@ def waitForPosition(self): if not success: raise MeshInterface.MeshInterfaceError("Timed out waiting for position") + def waitForWaypoint(self): + """Wait for waypoint""" + success = self._timeout.waitForWaypoint(self._acknowledgment) + if not success: + raise MeshInterface.MeshInterfaceError("Timed out waiting for waypoint") + def getMyNodeInfo(self) -> Optional[Dict]: """Get info about my node.""" if self.myInfo is None or self.nodesByNum is None: diff --git a/meshtastic/util.py b/meshtastic/util.py index f36655e6..e7b07a08 100644 --- a/meshtastic/util.py +++ b/meshtastic/util.py @@ -254,6 +254,16 @@ def waitForPosition(self, acknowledgment) -> bool: time.sleep(self.sleepInterval) return False + def waitForWaypoint(self, acknowledgment) -> bool: + """Block until waypoint response is received. Returns True if waypoint response has been received.""" + self.reset() + while time.time() < self.expireTime: + if getattr(acknowledgment, "receivedWaypoint", 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." @@ -265,6 +275,7 @@ def __init__(self) -> None: self.receivedTraceRoute = False self.receivedTelemetry = False self.receivedPosition = False + self.receivedWaypoint = False def reset(self) -> None: """reset""" @@ -274,6 +285,7 @@ def reset(self) -> None: self.receivedTraceRoute = False self.receivedTelemetry = False self.receivedPosition = False + self.receivedWaypoint = False class DeferredExecution: