Skip to content

Commit 9381acd

Browse files
authored
Merge pull request #681 from william-stearns/wls_add_types2
Wls add types2
2 parents 0deb1d7 + 384063d commit 9381acd

File tree

11 files changed

+183
-150
lines changed

11 files changed

+183
-150
lines changed

meshtastic/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,13 @@ def onConnection(interface, topic=pub.AUTO_TOPIC): # called when we (re)connect
111111
LOCAL_ADDR = "^local"
112112
"""A special ID that means the local node"""
113113

114-
BROADCAST_NUM = 0xFFFFFFFF
114+
BROADCAST_NUM: int = 0xFFFFFFFF
115115
"""if using 8 bit nodenums this will be shortened on the target"""
116116

117117
BROADCAST_ADDR = "^all"
118118
"""A special ID that means broadcast"""
119119

120-
OUR_APP_VERSION = 20300
120+
OUR_APP_VERSION: int = 20300
121121
"""The numeric buildnumber (shared with android apps) specifying the
122122
level of device code we are guaranteed to understand
123123

meshtastic/__main__.py

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import platform
1212
import sys
1313
import time
14-
from typing import Optional
14+
from typing import List, Optional
1515

1616
import pyqrcode # type: ignore[import-untyped]
1717
import yaml
@@ -42,7 +42,7 @@
4242
from meshtastic.protobuf import channel_pb2, config_pb2, portnums_pb2
4343
from meshtastic.version import get_active_version
4444

45-
def onReceive(packet, interface):
45+
def onReceive(packet, interface) -> None:
4646
"""Callback invoked when a packet arrives"""
4747
args = mt_config.args
4848
try:
@@ -73,7 +73,7 @@ def onReceive(packet, interface):
7373
print(f"Warning: There is no field {ex} in the packet.")
7474

7575

76-
def onConnection(interface, topic=pub.AUTO_TOPIC): # pylint: disable=W0613
76+
def onConnection(interface, topic=pub.AUTO_TOPIC) -> None: # pylint: disable=W0613
7777
"""Callback invoked when we connect/disconnect from a radio"""
7878
print(f"Connection changed: {topic.getName()}")
7979

@@ -85,7 +85,7 @@ def checkChannel(interface: MeshInterface, channelIndex: int) -> bool:
8585
return ch and ch.role != channel_pb2.Channel.Role.DISABLED
8686

8787

88-
def getPref(node, comp_name):
88+
def getPref(node, comp_name) -> bool:
8989
"""Get a channel or preferences value"""
9090
def _printSetting(config_type, uni_name, pref_value, repeated):
9191
"""Pretty print the setting"""
@@ -109,11 +109,11 @@ def _printSetting(config_type, uni_name, pref_value, repeated):
109109
# First validate the input
110110
localConfig = node.localConfig
111111
moduleConfig = node.moduleConfig
112-
found = False
112+
found: bool = False
113113
for config in [localConfig, moduleConfig]:
114114
objDesc = config.DESCRIPTOR
115115
config_type = objDesc.fields_by_name.get(name[0])
116-
pref = False
116+
pref = "" #FIXME - is this correct to leave as an empty string if not found?
117117
if config_type:
118118
pref = config_type.message_type.fields_by_name.get(snake_name)
119119
if pref or wholeField:
@@ -130,7 +130,7 @@ def _printSetting(config_type, uni_name, pref_value, repeated):
130130
return False
131131

132132
# Check if we need to request the config
133-
if len(config.ListFields()) != 0:
133+
if len(config.ListFields()) != 0 and not isinstance(pref, str): # if str, it's still the empty string, I think
134134
# read the value
135135
config_values = getattr(config, config_type.name)
136136
if not wholeField:
@@ -148,16 +148,16 @@ def _printSetting(config_type, uni_name, pref_value, repeated):
148148
return True
149149

150150

151-
def splitCompoundName(comp_name):
151+
def splitCompoundName(comp_name: str) -> List[str]:
152152
"""Split compound (dot separated) preference name into parts"""
153-
name = comp_name.split(".")
153+
name: List[str] = comp_name.split(".")
154154
if len(name) < 2:
155155
name[0] = comp_name
156156
name.append(comp_name)
157157
return name
158158

159159

160-
def traverseConfig(config_root, config, interface_config):
160+
def traverseConfig(config_root, config, interface_config) -> bool:
161161
"""Iterate through current config level preferences and either traverse deeper if preference is a dict or set preference"""
162162
snake_name = meshtastic.util.camel_to_snake(config_root)
163163
for pref in config:
@@ -958,7 +958,7 @@ def setSimpleConfig(modem_preset):
958958
sys.exit(1)
959959

960960

961-
def printConfig(config):
961+
def printConfig(config) -> None:
962962
"""print configuration"""
963963
objDesc = config.DESCRIPTOR
964964
for config_section in objDesc.fields:
@@ -975,12 +975,12 @@ def printConfig(config):
975975
print(f" {temp_name}")
976976

977977

978-
def onNode(node):
978+
def onNode(node) -> None:
979979
"""Callback invoked when the node DB changes"""
980980
print(f"Node changed: {node}")
981981

982982

983-
def subscribe():
983+
def subscribe() -> None:
984984
"""Subscribe to the topics the user probably wants to see, prints output to stdout"""
985985
pub.subscribe(onReceive, "meshtastic.receive")
986986
# pub.subscribe(onConnection, "meshtastic.connection")
@@ -991,7 +991,7 @@ def subscribe():
991991
# pub.subscribe(onNode, "meshtastic.node")
992992

993993

994-
def export_config(interface):
994+
def export_config(interface) -> str:
995995
"""used in --export-config"""
996996
configObj = {}
997997

@@ -1023,7 +1023,7 @@ def export_config(interface):
10231023
if alt:
10241024
configObj["location"]["alt"] = alt
10251025

1026-
config = MessageToDict(interface.localNode.localConfig)
1026+
config = MessageToDict(interface.localNode.localConfig) #checkme - Used as a dictionary here and a string below
10271027
if config:
10281028
# Convert inner keys to correct snake/camelCase
10291029
prefs = {}
@@ -1042,7 +1042,7 @@ def export_config(interface):
10421042
for i in range(len(prefs[pref]['adminKey'])):
10431043
prefs[pref]['adminKey'][i] = 'base64:' + prefs[pref]['adminKey'][i]
10441044
if mt_config.camel_case:
1045-
configObj["config"] = config
1045+
configObj["config"] = config #Identical command here and 2 lines below?
10461046
else:
10471047
configObj["config"] = config
10481048

@@ -1058,10 +1058,11 @@ def export_config(interface):
10581058
else:
10591059
configObj["module_config"] = prefs
10601060

1061-
config = "# start of Meshtastic configure yaml\n"
1062-
config += yaml.dump(configObj)
1063-
print(config)
1064-
return config
1061+
config_txt = "# start of Meshtastic configure yaml\n" #checkme - "config" (now changed to config_out)
1062+
#was used as a string here and a Dictionary above
1063+
config_txt += yaml.dump(configObj)
1064+
print(config_txt)
1065+
return config_txt
10651066

10661067

10671068
def create_power_meter():

meshtastic/ble_interface.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import logging
66
import struct
77
import time
8+
import io
89
from threading import Thread
910
from typing import List, Optional
1011

@@ -34,9 +35,9 @@ def __init__(
3435
self,
3536
address: Optional[str],
3637
noProto: bool = False,
37-
debugOut=None,
38+
debugOut: Optional[io.TextIOWrapper]=None,
3839
noNodes: bool = False,
39-
):
40+
) -> None:
4041
MeshInterface.__init__(
4142
self, debugOut=debugOut, noProto=noProto, noNodes=noNodes
4243
)
@@ -82,7 +83,7 @@ def __init__(
8283
# Note: the on disconnected callback will call our self.close which will make us nicely wait for threads to exit
8384
self._exit_handler = atexit.register(self.client.disconnect)
8485

85-
def from_num_handler(self, _, b): # pylint: disable=C0116
86+
def from_num_handler(self, _, b: bytes) -> None: # pylint: disable=C0116
8687
"""Handle callbacks for fromnum notify.
8788
Note: this method does not need to be async because it is just setting a bool.
8889
"""
@@ -150,9 +151,12 @@ def find_device(self, address: Optional[str]) -> BLEDevice:
150151
)
151152
return addressed_devices[0]
152153

153-
def _sanitize_address(address): # pylint: disable=E0213
154+
def _sanitize_address(self, address: Optional[str]) -> Optional[str]: # pylint: disable=E0213
154155
"Standardize BLE address by removing extraneous characters and lowercasing."
155-
return address.replace("-", "").replace("_", "").replace(":", "").lower()
156+
if address is None:
157+
return None
158+
else:
159+
return address.replace("-", "").replace("_", "").replace(":", "").lower()
156160

157161
def connect(self, address: Optional[str] = None) -> "BLEClient":
158162
"Connect to a device by address."
@@ -164,12 +168,16 @@ def connect(self, address: Optional[str] = None) -> "BLEClient":
164168
client.discover()
165169
return client
166170

167-
def _receiveFromRadioImpl(self):
171+
def _receiveFromRadioImpl(self) -> None:
168172
while self._want_receive:
169173
if self.should_read:
170174
self.should_read = False
171-
retries = 0
175+
retries: int = 0
172176
while self._want_receive:
177+
if self.client is None:
178+
logging.debug(f"BLE client is None, shutting down")
179+
self._want_receive = False
180+
continue
173181
try:
174182
b = bytes(self.client.read_gatt_char(FROMRADIO_UUID))
175183
except BleakDBusError as e:
@@ -194,8 +202,8 @@ def _receiveFromRadioImpl(self):
194202
else:
195203
time.sleep(0.01)
196204

197-
def _sendToRadioImpl(self, toRadio):
198-
b = toRadio.SerializeToString()
205+
def _sendToRadioImpl(self, toRadio) -> None:
206+
b: bytes = toRadio.SerializeToString()
199207
if b and self.client: # we silently ignore writes while we are shutting down
200208
logging.debug(f"TORADIO write: {b.hex()}")
201209
try:
@@ -211,7 +219,7 @@ def _sendToRadioImpl(self, toRadio):
211219
time.sleep(0.01)
212220
self.should_read = True
213221

214-
def close(self):
222+
def close(self) -> None:
215223
try:
216224
MeshInterface.close(self)
217225
except Exception as e:
@@ -236,7 +244,7 @@ def close(self):
236244
class BLEClient:
237245
"""Client for managing connection to a BLE device"""
238246

239-
def __init__(self, address=None, **kwargs):
247+
def __init__(self, address=None, **kwargs) -> None:
240248
self._eventLoop = asyncio.new_event_loop()
241249
self._eventThread = Thread(
242250
target=self._run_event_loop, name="BLEClient", daemon=True

meshtastic/mt_config.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
1414
"""
1515

16+
from typing import Any, Optional
17+
1618
def reset():
1719
"""
1820
Restore the namespace to pristine condition.
@@ -33,5 +35,5 @@ def reset():
3335
parser = None
3436
channel_index = None
3537
logfile = None
36-
tunnelInstance = None
38+
tunnelInstance: Optional[Any] = None
3739
camel_case = False

meshtastic/remote_hardware.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from meshtastic.util import our_exit
99

1010

11-
def onGPIOreceive(packet, interface):
11+
def onGPIOreceive(packet, interface) -> None:
1212
"""Callback for received GPIO responses"""
1313
logging.debug(f"packet:{packet} interface:{interface}")
1414
gpioValue = 0
@@ -37,7 +37,7 @@ class RemoteHardwareClient:
3737
code for how you can connect to your own custom meshtastic services
3838
"""
3939

40-
def __init__(self, iface):
40+
def __init__(self, iface) -> None:
4141
"""
4242
Constructor
4343

meshtastic/serial_interface.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import platform
66
import time
77

8-
from typing import Optional
8+
from typing import List, Optional
99

1010
import serial # type: ignore[import-untyped]
1111

@@ -19,7 +19,7 @@
1919
class SerialInterface(StreamInterface):
2020
"""Interface class for meshtastic devices over a serial link"""
2121

22-
def __init__(self, devPath: Optional[str]=None, debugOut=None, noProto=False, connectNow=True, noNodes: bool=False):
22+
def __init__(self, devPath: Optional[str]=None, debugOut=None, noProto: bool=False, connectNow: bool=True, noNodes: bool=False) -> None:
2323
"""Constructor, opens a connection to a specified serial port, or if unspecified try to
2424
find one Meshtastic device by probing
2525
@@ -32,13 +32,13 @@ def __init__(self, devPath: Optional[str]=None, debugOut=None, noProto=False, co
3232
self.devPath: Optional[str] = devPath
3333

3434
if self.devPath is None:
35-
ports = meshtastic.util.findPorts(True)
35+
ports: List[str] = meshtastic.util.findPorts(True)
3636
logging.debug(f"ports:{ports}")
3737
if len(ports) == 0:
3838
print("No Serial Meshtastic device detected, attempting TCP connection on localhost.")
3939
return
4040
elif len(ports) > 1:
41-
message = "Warning: Multiple serial ports were detected so one serial port must be specified with the '--port'.\n"
41+
message: str = "Warning: Multiple serial ports were detected so one serial port must be specified with the '--port'.\n"
4242
message += f" Ports detected:{ports}"
4343
meshtastic.util.our_exit(message)
4444
else:
@@ -59,14 +59,14 @@ def __init__(self, devPath: Optional[str]=None, debugOut=None, noProto=False, co
5959
self.stream = serial.Serial(
6060
self.devPath, 115200, exclusive=True, timeout=0.5, write_timeout=0
6161
)
62-
self.stream.flush()
62+
self.stream.flush() # type: ignore[attr-defined]
6363
time.sleep(0.1)
6464

6565
StreamInterface.__init__(
6666
self, debugOut=debugOut, noProto=noProto, connectNow=connectNow, noNodes=noNodes
6767
)
6868

69-
def close(self):
69+
def close(self) -> None:
7070
"""Close a connection to the device"""
7171
if self.stream: # Stream can be null if we were already closed
7272
self.stream.flush() # FIXME: why are there these two flushes with 100ms sleeps? This shouldn't be necessary

0 commit comments

Comments
 (0)