Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 43 additions & 10 deletions meshtastic/mesh_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,17 +548,46 @@ def sendTraceRoute(

def onResponseTraceRoute(self, p: dict):
"""on response for trace route"""
UNK_SNR = -128 # Value representing unknown SNR

routeDiscovery = mesh_pb2.RouteDiscovery()
routeDiscovery.ParseFromString(p["decoded"]["payload"])
asDict = google.protobuf.json_format.MessageToDict(routeDiscovery)

print("Route traced:")
routeStr = self._nodeNumToId(p["to"]) or f"{p['to']:08x}"
if "route" in asDict:
for nodeNum in asDict["route"]:
routeStr += " --> " + (self._nodeNumToId(nodeNum) or f"{nodeNum:08x}")
routeStr += " --> " + (self._nodeNumToId(p["from"]) or f"{p['from']:08x}")
print(routeStr)
print("Route traced towards destination:")
routeStr = self._nodeNumToId(p["to"], False) or f"{p['to']:08x}" # Start with destination of response

# SNR list should have one more entry than the route, as the final destination adds its SNR also
lenTowards = 0 if "route" not in asDict else len(asDict["route"])
snrTowardsValid = "snrTowards" in asDict and len(asDict["snrTowards"]) == lenTowards + 1
if lenTowards > 0: # Loop through hops in route and add SNR if available
for idx, nodeNum in enumerate(asDict["route"]):
routeStr += " --> " + (self._nodeNumToId(nodeNum, False) or f"{nodeNum:08x}") \
+ " (" + (str(asDict["snrTowards"][idx] / 4) if snrTowardsValid and asDict["snrTowards"][idx] != UNK_SNR else "?") + "dB)"

# End with origin of response
routeStr += " --> " + (self._nodeNumToId(p["from"], False) or f"{p['from']:08x}") \
+ " (" + (str(asDict["snrTowards"][-1] / 4) if snrTowardsValid and asDict["snrTowards"][-1] != UNK_SNR else "?") + "dB)"

print(routeStr) # Print the route towards destination

# Only if there is an SNR entry (for the origin) it's valid, even though route might be empty (direct connection)
lenBack = 0 if "routeBack" not in asDict else len(asDict["routeBack"])
backValid = "snrBack" in asDict and len(asDict["snrBack"]) == lenBack + 1
if backValid:
print("Route traced back to us:")
routeStr = self._nodeNumToId(p["from"], False) or f"{p['from']:08x}" # Start with origin of response

if lenBack > 0: # Loop through hops in routeBack and add SNR if available
for idx, nodeNum in enumerate(asDict["routeBack"]):
routeStr += " --> " + (self._nodeNumToId(nodeNum, False) or f"{nodeNum:08x}") \
+ " (" + (str(asDict["snrBack"][idx] / 4) if asDict["snrBack"][idx] != UNK_SNR else "?") + "dB)"

# End with destination of response (us)
routeStr += " --> " + (self._nodeNumToId(p["to"], False) or f"{p['to']:08x}") \
+ " (" + (str(asDict["snrBack"][-1] / 4) if asDict["snrBack"][-1] != UNK_SNR else "?") + "dB)"

print(routeStr) # Print the route back to us

self._acknowledgment.receivedTraceRoute = True

Expand Down Expand Up @@ -1143,17 +1172,21 @@ def _fixupPosition(self, position: Dict) -> Dict:
position["longitude"] = float(position["longitudeI"] * Decimal("1e-7"))
return position

def _nodeNumToId(self, num: int) -> Optional[str]:
def _nodeNumToId(self, num: int, isDest = True) -> Optional[str]:
"""Map a node node number to a node ID

Arguments:
num {int} -- Node number
isDest {bool} -- True if the node number is a destination (to show broadcast address or unknown node)

Returns:
string -- Node ID
"""
if num == BROADCAST_NUM:
return BROADCAST_ADDR
if isDest:
return BROADCAST_ADDR
else:
return "Unknown"

try:
return self.nodesByNum[num]["user"]["id"] # type: ignore[index]
Expand Down Expand Up @@ -1226,7 +1259,7 @@ def _handlePacketFromRadio(self, meshPacket, hack=False):

# /add fromId and toId fields based on the node ID
try:
asDict["fromId"] = self._nodeNumToId(asDict["from"])
asDict["fromId"] = self._nodeNumToId(asDict["from"], False)
except Exception as ex:
logging.warning(f"Not populating fromId {ex}")
try:
Expand Down