Skip to content
Merged
Show file tree
Hide file tree
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
32 changes: 20 additions & 12 deletions meshtastic/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from meshtastic import channel_pb2, config_pb2, portnums_pb2, remote_hardware, BROADCAST_ADDR
from meshtastic.version import get_active_version
from meshtastic.ble_interface import BLEInterface
from meshtastic.mesh_interface import MeshInterface

def onReceive(packet, interface):
"""Callback invoked when a packet arrives"""
Expand Down Expand Up @@ -56,6 +57,11 @@ def onConnection(interface, topic=pub.AUTO_TOPIC): # pylint: disable=W0613
"""Callback invoked when we connect/disconnect from a radio"""
print(f"Connection changed: {topic.getName()}")

def checkChannel(interface: MeshInterface, channelIndex: int) -> bool:
"""Given an interface and channel index, return True if that channel is non-disabled on the local node"""
ch = interface.localNode.getChannelByChannelIndex(channelIndex)
logging.debug(f"ch:{ch}")
return (ch and ch.role != channel_pb2.Channel.Role.DISABLED)

def getPref(node, comp_name):
"""Get a channel or preferences value"""
Expand Down Expand Up @@ -403,12 +409,8 @@ def onConnected(interface):

if args.sendtext:
closeNow = True
channelIndex = 0
if args.ch_index is not None:
channelIndex = int(args.ch_index)
ch = interface.localNode.getChannelByChannelIndex(channelIndex)
logging.debug(f"ch:{ch}")
if ch and ch.role != channel_pb2.Channel.Role.DISABLED:
channelIndex = mt_config.channel_index or 0
if checkChannel(interface, channelIndex):
print(
f"Sending text message {args.sendtext} to {args.dest} on channelIndex:{channelIndex}"
)
Expand All @@ -428,22 +430,28 @@ def onConnected(interface):
loraConfig = getattr(interface.localNode.localConfig, "lora")
hopLimit = getattr(loraConfig, "hop_limit")
dest = str(args.traceroute)
print(f"Sending traceroute request to {dest} (this could take a while)")
interface.sendTraceRoute(dest, hopLimit)
channelIndex = mt_config.channel_index or 0
if checkChannel(interface, channelIndex):
print(f"Sending traceroute request to {dest} on channelIndex:{channelIndex} (this could take a while)")
interface.sendTraceRoute(dest, hopLimit, channelIndex=channelIndex)

if args.request_telemetry:
if args.dest == BROADCAST_ADDR:
meshtastic.util.our_exit("Warning: Must use a destination node ID.")
else:
print(f"Sending telemetry request to {args.dest} (this could take a while)")
interface.sendTelemetry(destinationId=args.dest, wantResponse=True)
channelIndex = mt_config.channel_index or 0
if checkChannel(interface, channelIndex):
print(f"Sending telemetry request to {args.dest} on channelIndex:{channelIndex} (this could take a while)")
interface.sendTelemetry(destinationId=args.dest, wantResponse=True, channelIndex=channelIndex)

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)
channelIndex = mt_config.channel_index or 0
if checkChannel(interface, channelIndex):
print(f"Sending position request to {args.dest} on channelIndex:{channelIndex} (this could take a while)")
interface.sendPosition(destinationId=args.dest, wantResponse=True, channelIndex=channelIndex)

if args.gpio_wrb or args.gpio_rd or args.gpio_watch:
if args.dest == BROADCAST_ADDR:
Expand Down
41 changes: 23 additions & 18 deletions meshtastic/mesh_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ def sendPosition(
destinationId: Union[int, str]=BROADCAST_ADDR,
wantAck: bool=False,
wantResponse: bool=False,
channelIndex: int=0,
):
"""
Send a position packet to some other node (normally a broadcast)
Expand Down Expand Up @@ -393,6 +394,7 @@ def sendPosition(
wantAck=wantAck,
wantResponse=wantResponse,
onResponse=onResponse,
channelIndex=channelIndex,
)
if wantResponse:
self.waitForPosition()
Expand Down Expand Up @@ -426,7 +428,7 @@ def onResponsePosition(self, p):
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):
def sendTraceRoute(self, dest: Union[int, str], hopLimit: int, channelIndex: int=0):
"""Send the trace route"""
r = mesh_pb2.RouteDiscovery()
self.sendData(
Expand All @@ -435,6 +437,7 @@ def sendTraceRoute(self, dest: Union[int, str], hopLimit: int):
portNum=portnums_pb2.PortNum.TRACEROUTE_APP,
wantResponse=True,
onResponse=self.onResponseTraceRoute,
channelIndex=channelIndex,
)
# extend timeout based on number of nodes, limit by configured hopLimit
waitFactor = min(len(self.nodes) - 1 if self.nodes else 0, hopLimit)
Expand All @@ -456,26 +459,27 @@ def onResponseTraceRoute(self, p):

self._acknowledgment.receivedTraceRoute = True

def sendTelemetry(self, destinationId=BROADCAST_ADDR, wantResponse=False):
def sendTelemetry(self, destinationId: Union[int,str]=BROADCAST_ADDR, wantResponse: bool=False, channelIndex: int=0):
"""Send telemetry and optionally ask for a response"""
r = telemetry_pb2.Telemetry()

node = next(n for n in self.nodes.values() if n["num"] == self.localNode.nodeNum)
if node is not None:
metrics = node.get("deviceMetrics")
if metrics:
batteryLevel = metrics.get("batteryLevel")
if batteryLevel is not None:
r.device_metrics.battery_level = batteryLevel
voltage = metrics.get("voltage")
if voltage is not None:
r.device_metrics.voltage = voltage
channel_utilization = metrics.get("channelUtilization")
if channel_utilization is not None:
r.device_metrics.channel_utilization = channel_utilization
air_util_tx = metrics.get("airUtilTx")
if air_util_tx is not None:
r.device_metrics.air_util_tx = air_util_tx
if self.nodes is not None:
node = next(n for n in self.nodes.values() if n["num"] == self.localNode.nodeNum)
if node is not None:
metrics = node.get("deviceMetrics")
if metrics:
batteryLevel = metrics.get("batteryLevel")
if batteryLevel is not None:
r.device_metrics.battery_level = batteryLevel
voltage = metrics.get("voltage")
if voltage is not None:
r.device_metrics.voltage = voltage
channel_utilization = metrics.get("channelUtilization")
if channel_utilization is not None:
r.device_metrics.channel_utilization = channel_utilization
air_util_tx = metrics.get("airUtilTx")
if air_util_tx is not None:
r.device_metrics.air_util_tx = air_util_tx

if wantResponse:
onResponse = self.onResponseTelemetry
Expand All @@ -488,6 +492,7 @@ def sendTelemetry(self, destinationId=BROADCAST_ADDR, wantResponse=False):
portNum=portnums_pb2.PortNum.TELEMETRY_APP,
wantResponse=wantResponse,
onResponse=onResponse,
channelIndex=channelIndex,
)
if wantResponse:
self.waitForTelemetry()
Expand Down