⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

# Add files or directories matching the regex patterns to the blacklist. The
# regex matches against base names, not paths.
ignore-patterns=mqtt_pb2.py,channel_pb2.py,telemetry_pb2.py,admin_pb2.py,config_pb2.py,deviceonly_pb2.py,apponly_pb2.py,remote_hardware_pb2.py,portnums_pb2.py,mesh_pb2.py,storeforward_pb2.py,cannedmessages_pb2.py,module_config_pb2.py,localonly_pb2.py,node.py,device_metadata_pb2.py,nanopb_pb2.py
ignore-patterns=xmodem_pb2.py,rtttl_pb2.py,powermon_pb2.py,paxcount_pb2.py,interdevice_pb2.py,atak_pb2,clientonly_pb2.py,connection_status_pb2.py,device_ui_pb2.py,mqtt_pb2.py,channel_pb2.py,telemetry_pb2.py,admin_pb2.py,config_pb2.py,deviceonly_pb2.py,apponly_pb2.py,remote_hardware_pb2.py,portnums_pb2.py,mesh_pb2.py,storeforward_pb2.py,cannedmessages_pb2.py,module_config_pb2.py,localonly_pb2.py,node.py,device_metadata_pb2.py,nanopb_pb2.py



Expand Down
44 changes: 37 additions & 7 deletions exampleConfig.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,46 @@
# example config using camelCase keys
owner: Bob TBeam
ownerShort: BOB
isUnmessagable: true

channelUrl: https://www.meshtastic.org/d/#CgUYAyIBAQ
channelUrl: https://www.meshtastic.org/e/#CgQ6AggNEg8IATgBQANIAVAeaAHABgE

cannedMessages: Hi|Bye|Yes|No|Ok
ringtone: 24:d=32,o=5,b=565:f6,p,f6,4p,p,f6,p,f6,2p,p,b6,p,b6,p,b6,p,b6,p,b,p,b,p,b,p,b,p,b,p,b,p,b,p,b,1p.,2p.,p

location:
lat: 35.88888
lon: -93.88888
alt: 304

userPrefs:
region: 1
isAlwaysPowered: "true"
screenOnSecs: 31536000
waitBluetoothSecs: 31536000
config:
bluetooth:
enabled: true
fixedPin: 123456
device:
serialEnabled: true
display:
screenOnSecs: 781
lora:
region: US
hopLimit: 3
txEnabled: true
txPower: 30
network:
ntpServer: 0.pool.ntp.org
position:
gpsAttemptTime: 900
gpsEnabled: true
gpsUpdateInterval: 120
positionBroadcastSecs: 900
positionBroadcastSmartEnabled: true
positionFlags: 3
power:
lsSecs: 300
meshSdsTimeoutSecs: 7200
minWakeSecs: 10
sdsSecs: 4294967295
waitBluetoothSecs: 344
moduleConfig:
telemetry:
deviceUpdateInterval: 900
environmentUpdateInterval: 900
7 changes: 4 additions & 3 deletions example_config.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# example configuration file with snake_case keys
owner: Bob TBeam
owner_short: BOB
is_unmessagable: true

channel_url: https://www.meshtastic.org/e/#CgMSAQESCDgBQANIAVAe
channel_url: https://www.meshtastic.org/e/#CgQ6AggNEg8IATgBQANIAVAeaAHABgE

canned_messages: Hi|Bye|Yes|No|Ok
ringtone: 24:d=32,o=5,b=565:f6,p,f6,4p,p,f6,p,f6,2p,p,b6,p,b6,p,b6,p,b6,p,b,p,b,p,b,p,b,p,b,p,b,p,b,p,b,1p.,2p.,p
Expand All @@ -19,7 +20,7 @@ config:
device:
serialEnabled: true
display:
screenOnSecs: 600
screenOnSecs: 781
lora:
region: US
hopLimit: 3
Expand All @@ -39,7 +40,7 @@ config:
meshSdsTimeoutSecs: 7200
minWakeSecs: 10
sdsSecs: 4294967295

waitBluetoothSecs: 344
module_config:
telemetry:
deviceUpdateInterval: 900
Expand Down
332 changes: 177 additions & 155 deletions meshtastic/__main__.py

Large diffs are not rendered by default.

34 changes: 25 additions & 9 deletions meshtastic/mesh_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,13 +225,14 @@ def showInfo(self, file=sys.stdout) -> str: # pylint: disable=W0613
return infos

def showNodes(
self, includeSelf: bool = True, showFields: Optional[List[str]] = None
self, includeSelf: bool = True, showFields: Optional[List[str]] = None, printFmt: Optional[str] = None
) -> str: # pylint: disable=W0613
"""Show table summary of nodes in mesh

Args:
includeSelf (bool): Include ourself in the output?
showFields (List[str]): List of fields to show in output
printFmt (str): name of format to use
"""

def get_human_readable(name):
Expand Down Expand Up @@ -261,7 +262,6 @@ def get_human_readable(name):
else:
return name


def formatFloat(value, precision=2, unit="") -> Optional[str]:
"""Format a float value with precision."""
return f"{value:.{precision}f}{unit}" if value else None
Expand Down Expand Up @@ -296,7 +296,7 @@ def getNestedValue(node_dict: Dict[str, Any], key_path: str) -> Any:
return value

if showFields is None or len(showFields) == 0:
# The default set of fields to show (e.g., the status quo)
# The default set of fields to show (e.g., the status quo)
showFields = ["N", "user.longName", "user.id", "user.shortName", "user.hwModel", "user.publicKey",
"user.role", "position.latitude", "position.longitude", "position.altitude",
"deviceMetrics.batteryLevel", "deviceMetrics.channelUtilization",
Expand Down Expand Up @@ -372,7 +372,16 @@ def getNestedValue(node_dict: Dict[str, Any], key_path: str) -> Any:
for i, row in enumerate(rows):
row["N"] = i + 1

table = tabulate(rows, headers="keys", missingval="N/A", tablefmt="fancy_grid")
if not printFmt or len(printFmt) == 0:
printFmt = "fancy_grid"
if printFmt.lower() == 'json':
headers = []
if len(rows) > 0:
headers = list(rows[0].keys())
outDict = {'headers': headers, 'nodes': rows}
table = json.dumps(outDict)
else:
table = tabulate(rows, headers="keys", missingval="N/A", tablefmt=printFmt)
print(table)
return table

Expand Down Expand Up @@ -1061,42 +1070,49 @@ def getMyNodeInfo(self) -> Optional[Dict]:
logger.debug(f"self.nodesByNum:{self.nodesByNum}")
return self.nodesByNum.get(self.myInfo.my_node_num)

def getMyUser(self):
def getMyUser(self) -> dict | None:
"""Get user"""
nodeInfo = self.getMyNodeInfo()
if nodeInfo is not None:
return nodeInfo.get("user")
return None

def getLongName(self):
def getLongName(self) -> str | None:
"""Get long name"""
user = self.getMyUser()
if user is not None:
return user.get("longName", None)
return None

def getShortName(self):
def getShortName(self) -> str | None:
"""Get short name"""
user = self.getMyUser()
if user is not None:
return user.get("shortName", None)
return None

def getIsUnmessagable(self) -> bool | None:
"""Get getIsUnmessagable property"""
user = self.getMyUser()
if user is not None:
return user.get("isUnmessagable", None)
return None

def getPublicKey(self):
"""Get Public Key"""
user = self.getMyUser()
if user is not None:
return user.get("publicKey", None)
return None

def getCannedMessage(self):
def getCannedMessage(self) -> str | None:
"""Get canned message"""
node = self.localNode
if node is not None:
return node.get_canned_message()
return None

def getRingtone(self):
def getRingtone(self) -> str | None:
"""Get ringtone"""
node = self.localNode
if node is not None:
Expand Down
Loading