mirror of
https://github.com/meshtastic/python.git
synced 2025-12-26 01:17:51 -05:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3adeb925dd | ||
|
|
9de04a12e1 | ||
|
|
e01a1bb6e0 | ||
|
|
1ebea53703 | ||
|
|
ba2d6c9d93 | ||
|
|
fef0e1b77f | ||
|
|
dc1dec17b5 | ||
|
|
02ed17837b | ||
|
|
8cf996a242 | ||
|
|
02189aae07 | ||
|
|
894581ce00 | ||
|
|
fb8db01427 | ||
|
|
fa5ede93ed |
@@ -28,8 +28,7 @@ If you're interested in contributing but don't have specific things you'd like t
|
||||
This should always be considered a list in progress and flux -- inclusion doesn't guarantee implementation, and exclusion doesn't mean something's not wanted. GitHub issues are a great place to discuss ideas.
|
||||
|
||||
* Types
|
||||
* type annotations throughout the codebase
|
||||
* mypy running in CI to type-check new code
|
||||
* type annotations throughout the codebase, and upgrading mypy running in CI to `--strict`
|
||||
* async-friendliness
|
||||
* CLI completeness & consistency
|
||||
* the CLI should support all features of the firmware
|
||||
@@ -40,9 +39,9 @@ This should always be considered a list in progress and flux -- inclusion doesn'
|
||||
* pubsub events should be documented clearly
|
||||
* helpers for third-party code
|
||||
* it should be easy to write a script that supports similar options to the CLI so many tools support the same ways of connecting to nodes
|
||||
* interactive client
|
||||
* data storage & processing
|
||||
* there should be a standardized way of recording packets for later use, debugging, etc.
|
||||
* a persistence layer could also keep track of nodes beyond nodedb, as the apps do
|
||||
* a sqlite database schema and tools for writing to it may be a good starting point
|
||||
* enable maps, charts, visualizations
|
||||
|
||||
|
||||
@@ -265,7 +265,6 @@ def onConnected(interface):
|
||||
alt = 0
|
||||
lat = 0.0
|
||||
lon = 0.0
|
||||
# TODO: use getNode(args.dest) to be able to set it for a remote node
|
||||
localConfig = interface.localNode.localConfig
|
||||
if args.setalt:
|
||||
alt = int(args.setalt)
|
||||
@@ -722,6 +721,10 @@ def onConnected(interface):
|
||||
ch = interface.getNode(args.dest).channels[channelIndex]
|
||||
|
||||
if args.ch_enable or args.ch_disable:
|
||||
print(
|
||||
"Warning: --ch-enable and --ch-disable can produce noncontiguous channels, "
|
||||
"which can cause errors in some clients. Whenever possible, use --ch-add and --ch-del instead."
|
||||
)
|
||||
if channelIndex == 0:
|
||||
meshtastic.util.our_exit(
|
||||
"Warning: Cannot enable/disable PRIMARY channel."
|
||||
@@ -1351,7 +1354,7 @@ def initParser():
|
||||
|
||||
group.add_argument(
|
||||
"--request-position",
|
||||
help="Request the position from a nade. "
|
||||
help="Request the position from a node. "
|
||||
"You need to pass the destination ID as an argument with '--dest'. "
|
||||
"For repeaters, the nodeNum is required.",
|
||||
action="store_true",
|
||||
|
||||
@@ -5,6 +5,8 @@ import time
|
||||
import struct
|
||||
import asyncio
|
||||
from threading import Thread, Event
|
||||
from typing import Optional
|
||||
|
||||
from bleak import BleakScanner, BleakClient
|
||||
|
||||
from meshtastic.mesh_interface import MeshInterface
|
||||
@@ -30,7 +32,7 @@ class BLEInterface(MeshInterface):
|
||||
MESH = False
|
||||
|
||||
|
||||
def __init__(self, address, noProto = False, debugOut = None):
|
||||
def __init__(self, address: Optional[str], noProto: bool = False, debugOut = None):
|
||||
self.state = BLEInterface.BLEState()
|
||||
|
||||
if not address:
|
||||
|
||||
@@ -211,8 +211,8 @@ class MeshInterface:
|
||||
row.update(
|
||||
{
|
||||
"SNR": formatFloat(node.get("snr"), 2, " dB"),
|
||||
"Hops Away": node.get("hopsAway", "unknown"),
|
||||
"Channel": node.get("channel"),
|
||||
"Hops Away": node.get("hopsAway", "0/unknown"),
|
||||
"Channel": node.get("channel", 0),
|
||||
"LastHeard": getLH(node.get("lastHeard")),
|
||||
"Since": getTimeAgo(node.get("lastHeard")),
|
||||
}
|
||||
@@ -875,14 +875,28 @@ class MeshInterface:
|
||||
elif fromRadio.HasField("queueStatus"):
|
||||
self._handleQueueStatusFromRadio(fromRadio.queueStatus)
|
||||
|
||||
elif fromRadio.rebooted:
|
||||
elif fromRadio.HasField("mqttClientProxyMessage"):
|
||||
publishingThread.queueWork(
|
||||
lambda: pub.sendMessage(
|
||||
"meshtastic.mqttclientproxymessage", proxymessage=fromRadio.mqttClientProxyMessage, interface=self
|
||||
)
|
||||
)
|
||||
|
||||
elif fromRadio.HasField("xmodemPacket"):
|
||||
publishingThread.queueWork(
|
||||
lambda: pub.sendMessage(
|
||||
"meshtastic.xmodempacket", packet=fromRadio.xmodemPacket, interface=self
|
||||
)
|
||||
)
|
||||
|
||||
elif fromRadio.HasField("rebooted") and fromRadio.rebooted:
|
||||
# Tell clients the device went away. Careful not to call the overridden
|
||||
# subclass version that closes the serial port
|
||||
MeshInterface._disconnected(self)
|
||||
|
||||
self._startConfig() # redownload the node db etc...
|
||||
|
||||
elif fromRadio.config or fromRadio.moduleConfig:
|
||||
elif fromRadio.HasField("config") or fromRadio.HasField("moduleConfig"):
|
||||
if fromRadio.config.HasField("device"):
|
||||
self.localNode.localConfig.device.CopyFrom(fromRadio.config.device)
|
||||
elif fromRadio.config.HasField("position"):
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -112,6 +112,10 @@ class _HardwareModelEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._
|
||||
"""
|
||||
LoRAType device: https://loratype.org/
|
||||
"""
|
||||
WIPHONE: _HardwareModel.ValueType # 20
|
||||
"""
|
||||
wiphone https://www.wiphone.io/
|
||||
"""
|
||||
STATION_G1: _HardwareModel.ValueType # 25
|
||||
"""
|
||||
B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station
|
||||
@@ -276,6 +280,11 @@ class _HardwareModelEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._
|
||||
TWC_MESH_V4
|
||||
Adafruit NRF52840 feather express with SX1262, SSD1306 OLED and NEO6M GPS
|
||||
"""
|
||||
NRF52_PROMICRO_DIY: _HardwareModel.ValueType # 63
|
||||
"""
|
||||
NRF52_PROMICRO_DIY
|
||||
Promicro NRF52840 with SX1262/LLCC68, SSD1306 OLED and NEO6M GPS
|
||||
"""
|
||||
PRIVATE_HW: _HardwareModel.ValueType # 255
|
||||
"""
|
||||
------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -373,6 +382,10 @@ LORA_TYPE: HardwareModel.ValueType # 19
|
||||
"""
|
||||
LoRAType device: https://loratype.org/
|
||||
"""
|
||||
WIPHONE: HardwareModel.ValueType # 20
|
||||
"""
|
||||
wiphone https://www.wiphone.io/
|
||||
"""
|
||||
STATION_G1: HardwareModel.ValueType # 25
|
||||
"""
|
||||
B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station
|
||||
@@ -537,6 +550,11 @@ TWC_MESH_V4: HardwareModel.ValueType # 62
|
||||
TWC_MESH_V4
|
||||
Adafruit NRF52840 feather express with SX1262, SSD1306 OLED and NEO6M GPS
|
||||
"""
|
||||
NRF52_PROMICRO_DIY: HardwareModel.ValueType # 63
|
||||
"""
|
||||
NRF52_PROMICRO_DIY
|
||||
Promicro NRF52840 with SX1262/LLCC68, SSD1306 OLED and NEO6M GPS
|
||||
"""
|
||||
PRIVATE_HW: HardwareModel.ValueType # 255
|
||||
"""
|
||||
------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -4,6 +4,8 @@ import logging
|
||||
import platform
|
||||
import time
|
||||
|
||||
from typing import Optional
|
||||
|
||||
import serial # type: ignore[import-untyped]
|
||||
|
||||
import meshtastic.util
|
||||
@@ -16,7 +18,7 @@ if platform.system() != "Windows":
|
||||
class SerialInterface(StreamInterface):
|
||||
"""Interface class for meshtastic devices over a serial link"""
|
||||
|
||||
def __init__(self, devPath=None, debugOut=None, noProto=False, connectNow=True):
|
||||
def __init__(self, devPath: Optional[str]=None, debugOut=None, noProto=False, connectNow=True):
|
||||
"""Constructor, opens a connection to a specified serial port, or if unspecified try to
|
||||
find one Meshtastic device by probing
|
||||
|
||||
@@ -26,7 +28,7 @@ class SerialInterface(StreamInterface):
|
||||
"""
|
||||
self.noProto = noProto
|
||||
|
||||
self.devPath = devPath
|
||||
self.devPath: Optional[str] = devPath
|
||||
|
||||
if self.devPath is None:
|
||||
ports = meshtastic.util.findPorts(True)
|
||||
|
||||
@@ -13,7 +13,7 @@ _sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1ameshtastic/telemetry.proto\x12\nmeshtastic\"\x81\x01\n\rDeviceMetrics\x12\x15\n\rbattery_level\x18\x01 \x01(\r\x12\x0f\n\x07voltage\x18\x02 \x01(\x02\x12\x1b\n\x13\x63hannel_utilization\x18\x03 \x01(\x02\x12\x13\n\x0b\x61ir_util_tx\x18\x04 \x01(\x02\x12\x16\n\x0euptime_seconds\x18\x05 \x01(\r\"\xba\x01\n\x12\x45nvironmentMetrics\x12\x13\n\x0btemperature\x18\x01 \x01(\x02\x12\x19\n\x11relative_humidity\x18\x02 \x01(\x02\x12\x1b\n\x13\x62\x61rometric_pressure\x18\x03 \x01(\x02\x12\x16\n\x0egas_resistance\x18\x04 \x01(\x02\x12\x0f\n\x07voltage\x18\x05 \x01(\x02\x12\x0f\n\x07\x63urrent\x18\x06 \x01(\x02\x12\x0b\n\x03iaq\x18\x07 \x01(\r\x12\x10\n\x08\x64istance\x18\x08 \x01(\x02\"\x8c\x01\n\x0cPowerMetrics\x12\x13\n\x0b\x63h1_voltage\x18\x01 \x01(\x02\x12\x13\n\x0b\x63h1_current\x18\x02 \x01(\x02\x12\x13\n\x0b\x63h2_voltage\x18\x03 \x01(\x02\x12\x13\n\x0b\x63h2_current\x18\x04 \x01(\x02\x12\x13\n\x0b\x63h3_voltage\x18\x05 \x01(\x02\x12\x13\n\x0b\x63h3_current\x18\x06 \x01(\x02\"\xbf\x02\n\x11\x41irQualityMetrics\x12\x15\n\rpm10_standard\x18\x01 \x01(\r\x12\x15\n\rpm25_standard\x18\x02 \x01(\r\x12\x16\n\x0epm100_standard\x18\x03 \x01(\r\x12\x1a\n\x12pm10_environmental\x18\x04 \x01(\r\x12\x1a\n\x12pm25_environmental\x18\x05 \x01(\r\x12\x1b\n\x13pm100_environmental\x18\x06 \x01(\r\x12\x16\n\x0eparticles_03um\x18\x07 \x01(\r\x12\x16\n\x0eparticles_05um\x18\x08 \x01(\r\x12\x16\n\x0eparticles_10um\x18\t \x01(\r\x12\x16\n\x0eparticles_25um\x18\n \x01(\r\x12\x16\n\x0eparticles_50um\x18\x0b \x01(\r\x12\x17\n\x0fparticles_100um\x18\x0c \x01(\r\"\x89\x02\n\tTelemetry\x12\x0c\n\x04time\x18\x01 \x01(\x07\x12\x33\n\x0e\x64\x65vice_metrics\x18\x02 \x01(\x0b\x32\x19.meshtastic.DeviceMetricsH\x00\x12=\n\x13\x65nvironment_metrics\x18\x03 \x01(\x0b\x32\x1e.meshtastic.EnvironmentMetricsH\x00\x12<\n\x13\x61ir_quality_metrics\x18\x04 \x01(\x0b\x32\x1d.meshtastic.AirQualityMetricsH\x00\x12\x31\n\rpower_metrics\x18\x05 \x01(\x0b\x32\x18.meshtastic.PowerMetricsH\x00\x42\t\n\x07variant*\xee\x01\n\x13TelemetrySensorType\x12\x10\n\x0cSENSOR_UNSET\x10\x00\x12\n\n\x06\x42ME280\x10\x01\x12\n\n\x06\x42ME680\x10\x02\x12\x0b\n\x07MCP9808\x10\x03\x12\n\n\x06INA260\x10\x04\x12\n\n\x06INA219\x10\x05\x12\n\n\x06\x42MP280\x10\x06\x12\t\n\x05SHTC3\x10\x07\x12\t\n\x05LPS22\x10\x08\x12\x0b\n\x07QMC6310\x10\t\x12\x0b\n\x07QMI8658\x10\n\x12\x0c\n\x08QMC5883L\x10\x0b\x12\t\n\x05SHT31\x10\x0c\x12\x0c\n\x08PMSA003I\x10\r\x12\x0b\n\x07INA3221\x10\x0e\x12\n\n\x06\x42MP085\x10\x0f\x12\x0c\n\x08RCWL9620\x10\x10\x42\x64\n\x13\x63om.geeksville.meshB\x0fTelemetryProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1ameshtastic/telemetry.proto\x12\nmeshtastic\"\x81\x01\n\rDeviceMetrics\x12\x15\n\rbattery_level\x18\x01 \x01(\r\x12\x0f\n\x07voltage\x18\x02 \x01(\x02\x12\x1b\n\x13\x63hannel_utilization\x18\x03 \x01(\x02\x12\x13\n\x0b\x61ir_util_tx\x18\x04 \x01(\x02\x12\x16\n\x0euptime_seconds\x18\x05 \x01(\r\"\xba\x01\n\x12\x45nvironmentMetrics\x12\x13\n\x0btemperature\x18\x01 \x01(\x02\x12\x19\n\x11relative_humidity\x18\x02 \x01(\x02\x12\x1b\n\x13\x62\x61rometric_pressure\x18\x03 \x01(\x02\x12\x16\n\x0egas_resistance\x18\x04 \x01(\x02\x12\x0f\n\x07voltage\x18\x05 \x01(\x02\x12\x0f\n\x07\x63urrent\x18\x06 \x01(\x02\x12\x0b\n\x03iaq\x18\x07 \x01(\r\x12\x10\n\x08\x64istance\x18\x08 \x01(\x02\"\x8c\x01\n\x0cPowerMetrics\x12\x13\n\x0b\x63h1_voltage\x18\x01 \x01(\x02\x12\x13\n\x0b\x63h1_current\x18\x02 \x01(\x02\x12\x13\n\x0b\x63h2_voltage\x18\x03 \x01(\x02\x12\x13\n\x0b\x63h2_current\x18\x04 \x01(\x02\x12\x13\n\x0b\x63h3_voltage\x18\x05 \x01(\x02\x12\x13\n\x0b\x63h3_current\x18\x06 \x01(\x02\"\xbf\x02\n\x11\x41irQualityMetrics\x12\x15\n\rpm10_standard\x18\x01 \x01(\r\x12\x15\n\rpm25_standard\x18\x02 \x01(\r\x12\x16\n\x0epm100_standard\x18\x03 \x01(\r\x12\x1a\n\x12pm10_environmental\x18\x04 \x01(\r\x12\x1a\n\x12pm25_environmental\x18\x05 \x01(\r\x12\x1b\n\x13pm100_environmental\x18\x06 \x01(\r\x12\x16\n\x0eparticles_03um\x18\x07 \x01(\r\x12\x16\n\x0eparticles_05um\x18\x08 \x01(\r\x12\x16\n\x0eparticles_10um\x18\t \x01(\r\x12\x16\n\x0eparticles_25um\x18\n \x01(\r\x12\x16\n\x0eparticles_50um\x18\x0b \x01(\r\x12\x17\n\x0fparticles_100um\x18\x0c \x01(\r\"\x89\x02\n\tTelemetry\x12\x0c\n\x04time\x18\x01 \x01(\x07\x12\x33\n\x0e\x64\x65vice_metrics\x18\x02 \x01(\x0b\x32\x19.meshtastic.DeviceMetricsH\x00\x12=\n\x13\x65nvironment_metrics\x18\x03 \x01(\x0b\x32\x1e.meshtastic.EnvironmentMetricsH\x00\x12<\n\x13\x61ir_quality_metrics\x18\x04 \x01(\x0b\x32\x1d.meshtastic.AirQualityMetricsH\x00\x12\x31\n\rpower_metrics\x18\x05 \x01(\x0b\x32\x18.meshtastic.PowerMetricsH\x00\x42\t\n\x07variant*\xf9\x01\n\x13TelemetrySensorType\x12\x10\n\x0cSENSOR_UNSET\x10\x00\x12\n\n\x06\x42ME280\x10\x01\x12\n\n\x06\x42ME680\x10\x02\x12\x0b\n\x07MCP9808\x10\x03\x12\n\n\x06INA260\x10\x04\x12\n\n\x06INA219\x10\x05\x12\n\n\x06\x42MP280\x10\x06\x12\t\n\x05SHTC3\x10\x07\x12\t\n\x05LPS22\x10\x08\x12\x0b\n\x07QMC6310\x10\t\x12\x0b\n\x07QMI8658\x10\n\x12\x0c\n\x08QMC5883L\x10\x0b\x12\t\n\x05SHT31\x10\x0c\x12\x0c\n\x08PMSA003I\x10\r\x12\x0b\n\x07INA3221\x10\x0e\x12\n\n\x06\x42MP085\x10\x0f\x12\x0c\n\x08RCWL9620\x10\x10\x12\t\n\x05SHT4X\x10\x11\x42\x64\n\x13\x63om.geeksville.meshB\x0fTelemetryProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
|
||||
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
|
||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.telemetry_pb2', globals())
|
||||
@@ -22,7 +22,7 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
DESCRIPTOR._options = None
|
||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\017TelemetryProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
|
||||
_TELEMETRYSENSORTYPE._serialized_start=1097
|
||||
_TELEMETRYSENSORTYPE._serialized_end=1335
|
||||
_TELEMETRYSENSORTYPE._serialized_end=1346
|
||||
_DEVICEMETRICS._serialized_start=43
|
||||
_DEVICEMETRICS._serialized_end=172
|
||||
_ENVIRONMENTMETRICS._serialized_start=175
|
||||
|
||||
@@ -90,6 +90,10 @@ class _TelemetrySensorTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wra
|
||||
"""
|
||||
RCWL-9620 Doppler Radar Distance Sensor, used for water level detection
|
||||
"""
|
||||
SHT4X: _TelemetrySensorType.ValueType # 17
|
||||
"""
|
||||
Sensirion High accuracy temperature and humidity
|
||||
"""
|
||||
|
||||
class TelemetrySensorType(_TelemetrySensorType, metaclass=_TelemetrySensorTypeEnumTypeWrapper):
|
||||
"""
|
||||
@@ -164,6 +168,10 @@ RCWL9620: TelemetrySensorType.ValueType # 16
|
||||
"""
|
||||
RCWL-9620 Doppler Radar Distance Sensor, used for water level detection
|
||||
"""
|
||||
SHT4X: TelemetrySensorType.ValueType # 17
|
||||
"""
|
||||
Sensirion High accuracy temperature and humidity
|
||||
"""
|
||||
global___TelemetrySensorType = TelemetrySensorType
|
||||
|
||||
@typing_extensions.final
|
||||
|
||||
@@ -11,7 +11,7 @@ import threading
|
||||
import time
|
||||
import traceback
|
||||
from queue import Queue
|
||||
from typing import Union
|
||||
from typing import List, NoReturn, Union
|
||||
|
||||
from google.protobuf.json_format import MessageToJson
|
||||
|
||||
@@ -122,7 +122,7 @@ def catchAndIgnore(reason, closure):
|
||||
logging.error(f"Exception thrown in {reason}: {ex}")
|
||||
|
||||
|
||||
def findPorts(eliminate_duplicates=False):
|
||||
def findPorts(eliminate_duplicates: bool=False) -> List[str]:
|
||||
"""Find all ports that might have meshtastic devices
|
||||
eliminate_duplicates will run the eliminate_duplicate_port() on the collection
|
||||
|
||||
@@ -263,7 +263,7 @@ class DeferredExecution:
|
||||
print(traceback.format_exc())
|
||||
|
||||
|
||||
def our_exit(message, return_value=1):
|
||||
def our_exit(message, return_value=1) -> NoReturn:
|
||||
"""Print the message and return a value.
|
||||
return_value defaults to 1 (non-successful)
|
||||
"""
|
||||
|
||||
Submodule protobufs updated: e21899aa6b...1bfe0354d1
2
setup.py
2
setup.py
@@ -13,7 +13,7 @@ with open("README.md", "r") as fh:
|
||||
# This call to setup() does all the work
|
||||
setup(
|
||||
name="meshtastic",
|
||||
version="2.3.7",
|
||||
version="2.3.8",
|
||||
description="Python API & client shell for talking to Meshtastic devices",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
|
||||
Reference in New Issue
Block a user