|
18 | 18 | from tabulate import tabulate |
19 | 19 |
|
20 | 20 | import meshtastic.node |
21 | | -from meshtastic import mesh_pb2, portnums_pb2 |
| 21 | +from meshtastic import mesh_pb2, portnums_pb2, telemetry_pb2 |
22 | 22 | from meshtastic.__init__ import ( |
23 | 23 | BROADCAST_ADDR, |
24 | 24 | BROADCAST_NUM, |
@@ -409,6 +409,70 @@ def onResponseTraceRoute(self, p): |
409 | 409 |
|
410 | 410 | self._acknowledgment.receivedTraceRoute = True |
411 | 411 |
|
| 412 | + def sendTelemetry(self, destinationId=BROADCAST_ADDR, wantResponse=False): |
| 413 | + """Send telemetry and optionally ask for a response""" |
| 414 | + r = telemetry_pb2.Telemetry() |
| 415 | + |
| 416 | + node = next(n for n in self.nodes.values() if n["num"] == self.localNode.nodeNum) |
| 417 | + if node is not None: |
| 418 | + metrics = node.get("deviceMetrics") |
| 419 | + if metrics: |
| 420 | + batteryLevel = metrics.get("batteryLevel") |
| 421 | + if batteryLevel is not None: |
| 422 | + r.device_metrics.battery_level = batteryLevel |
| 423 | + voltage = metrics.get("voltage") |
| 424 | + if voltage is not None: |
| 425 | + r.device_metrics.voltage = voltage |
| 426 | + channel_utilization = metrics.get("channelUtilization") |
| 427 | + if channel_utilization is not None: |
| 428 | + r.device_metrics.channel_utilization = channel_utilization |
| 429 | + air_util_tx = metrics.get("airUtilTx") |
| 430 | + if air_util_tx is not None: |
| 431 | + r.device_metrics.air_util_tx = air_util_tx |
| 432 | + |
| 433 | + if wantResponse: |
| 434 | + onResponse = self.onResponseTelemetry |
| 435 | + else: |
| 436 | + onResponse = None |
| 437 | + |
| 438 | + if destinationId.startswith("!"): |
| 439 | + destinationId = int(destinationId[1:], 16) |
| 440 | + else: |
| 441 | + destinationId = int(destinationId) |
| 442 | + |
| 443 | + self.sendData( |
| 444 | + r, |
| 445 | + destinationId=destinationId, |
| 446 | + portNum=portnums_pb2.PortNum.TELEMETRY_APP, |
| 447 | + wantResponse=wantResponse, |
| 448 | + onResponse=onResponse, |
| 449 | + ) |
| 450 | + if wantResponse: |
| 451 | + self.waitForTelemetry() |
| 452 | + |
| 453 | + def onResponseTelemetry(self, p): |
| 454 | + """on response for telemetry""" |
| 455 | + if p["decoded"]["portnum"] == 'TELEMETRY_APP': |
| 456 | + self._acknowledgment.receivedTelemetry = True |
| 457 | + telemetry = telemetry_pb2.Telemetry() |
| 458 | + telemetry.ParseFromString(p["decoded"]["payload"]) |
| 459 | + |
| 460 | + print("Telemetry received:") |
| 461 | + if telemetry.device_metrics.battery_level is not None: |
| 462 | + print(f"Battery level: {telemetry.device_metrics.battery_level:.2f}%") |
| 463 | + if telemetry.device_metrics.voltage is not None: |
| 464 | + print(f"Voltage: {telemetry.device_metrics.voltage:.2f} V") |
| 465 | + if telemetry.device_metrics.channel_utilization is not None: |
| 466 | + print( |
| 467 | + f"Total channel utilization: {telemetry.device_metrics.channel_utilization:.2f}%" |
| 468 | + ) |
| 469 | + if telemetry.device_metrics.air_util_tx is not None: |
| 470 | + print(f"Transmit air utilization: {telemetry.device_metrics.air_util_tx:.2f}%") |
| 471 | + |
| 472 | + elif p["decoded"]["portnum"] == 'ROUTING_APP': |
| 473 | + if p["decoded"]["routing"]["errorReason"] == 'NO_RESPONSE': |
| 474 | + our_exit("No response from node. At least firmware 2.1.22 is required on the destination node.") |
| 475 | + |
412 | 476 | def _addResponseHandler(self, requestId, callback): |
413 | 477 | self.responseHandlers[requestId] = ResponseHandler(callback) |
414 | 478 |
|
@@ -491,6 +555,12 @@ def waitForTraceRoute(self, waitFactor): |
491 | 555 | success = self._timeout.waitForTraceRoute(waitFactor, self._acknowledgment) |
492 | 556 | if not success: |
493 | 557 | raise Exception("Timed out waiting for traceroute") |
| 558 | + |
| 559 | + def waitForTelemetry(self): |
| 560 | + """Wait for telemetry""" |
| 561 | + success = self._timeout.waitForTelemetry(self._acknowledgment) |
| 562 | + if not success: |
| 563 | + raise Exception("Timed out waiting for telemetry") |
494 | 564 |
|
495 | 565 | def getMyNodeInfo(self): |
496 | 566 | """Get info about my node.""" |
|
0 commit comments