mirror of
https://github.com/meshtastic/python.git
synced 2025-12-26 01:17:51 -05:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec4e521001 | ||
|
|
19d7e914bc | ||
|
|
64bb668251 | ||
|
|
1511d4ea99 | ||
|
|
b59aee91f2 | ||
|
|
2c8fd8b606 | ||
|
|
15b03b704c | ||
|
|
775108b47b | ||
|
|
ae904f6dbe | ||
|
|
a14cc4f573 | ||
|
|
dc5f59260f | ||
|
|
91c42d598e |
@@ -811,6 +811,9 @@ def onConnected(interface):
|
||||
f"*** A newer version v{pypi_version} is available!"
|
||||
' Consider running "pip install --upgrade meshtastic" ***\n'
|
||||
)
|
||||
if sys.version_info[0] == 3 and sys.version_info[1] < 9:
|
||||
print(" *** this version of the CLI is the last that supports python 3.8 ***")
|
||||
print(" *** please update your python installation ***")
|
||||
else:
|
||||
print("Showing info of remote node is not supported.")
|
||||
print(
|
||||
|
||||
@@ -325,6 +325,7 @@ class MeshInterface: # pylint: disable=R0902
|
||||
onResponse: Optional[Callable[[dict], Any]]=None,
|
||||
onResponseAckPermitted: bool=False,
|
||||
channelIndex: int=0,
|
||||
hopLimit: Optional[int]=None,
|
||||
):
|
||||
"""Send a data packet to some other node
|
||||
|
||||
@@ -347,7 +348,8 @@ class MeshInterface: # pylint: disable=R0902
|
||||
for regular ACKs (True) or just data responses & NAKs (False)
|
||||
Note that if the onResponse callback is called 'onAckNak' this
|
||||
will implicitly be true.
|
||||
channelIndex - channel number to use
|
||||
channelIndex -- channel number to use
|
||||
hopLimit -- hop limit to use
|
||||
|
||||
Returns the sent packet. The id field will be populated in this packet
|
||||
and can be used to track future message acks/naks.
|
||||
@@ -379,7 +381,7 @@ class MeshInterface: # pylint: disable=R0902
|
||||
if onResponse is not None:
|
||||
logging.debug(f"Setting a response handler for requestId {meshPacket.id}")
|
||||
self._addResponseHandler(meshPacket.id, onResponse, ackPermitted=onResponseAckPermitted)
|
||||
p = self._sendPacket(meshPacket, destinationId, wantAck=wantAck)
|
||||
p = self._sendPacket(meshPacket, destinationId, wantAck=wantAck, hopLimit=hopLimit)
|
||||
return p
|
||||
|
||||
def sendPosition(
|
||||
@@ -478,6 +480,7 @@ class MeshInterface: # pylint: disable=R0902
|
||||
wantResponse=True,
|
||||
onResponse=self.onResponseTraceRoute,
|
||||
channelIndex=channelIndex,
|
||||
hopLimit=hopLimit,
|
||||
)
|
||||
# extend timeout based on number of nodes, limit by configured hopLimit
|
||||
waitFactor = min(len(self.nodes) - 1 if self.nodes else 0, hopLimit)
|
||||
@@ -563,7 +566,13 @@ class MeshInterface: # pylint: disable=R0902
|
||||
def _addResponseHandler(self, requestId: int, callback: Callable[[dict], Any], ackPermitted: bool=False):
|
||||
self.responseHandlers[requestId] = ResponseHandler(callback=callback, ackPermitted=ackPermitted)
|
||||
|
||||
def _sendPacket(self, meshPacket: mesh_pb2.MeshPacket, destinationId: Union[int,str]=BROADCAST_ADDR, wantAck: bool=False):
|
||||
def _sendPacket(
|
||||
self,
|
||||
meshPacket: mesh_pb2.MeshPacket,
|
||||
destinationId: Union[int,str]=BROADCAST_ADDR,
|
||||
wantAck: bool=False,
|
||||
hopLimit: Optional[int]=None
|
||||
):
|
||||
"""Send a MeshPacket to the specified node (or if unspecified, broadcast).
|
||||
You probably don't want this - use sendData instead.
|
||||
|
||||
@@ -604,9 +613,12 @@ class MeshInterface: # pylint: disable=R0902
|
||||
|
||||
meshPacket.to = nodeNum
|
||||
meshPacket.want_ack = wantAck
|
||||
loraConfig = getattr(self.localNode.localConfig, "lora")
|
||||
hopLimit = getattr(loraConfig, "hop_limit")
|
||||
meshPacket.hop_limit = hopLimit
|
||||
|
||||
if hopLimit is not None:
|
||||
meshPacket.hop_limit = hopLimit
|
||||
else:
|
||||
loraConfig = getattr(self.localNode.localConfig, "lora")
|
||||
meshPacket.hop_limit = getattr(loraConfig, "hop_limit")
|
||||
|
||||
# if the user hasn't set an ID for this packet (likely and recommended),
|
||||
# we should pick a new unique ID so the message can be tracked.
|
||||
@@ -715,9 +727,8 @@ class MeshInterface: # pylint: disable=R0902
|
||||
|
||||
def callback():
|
||||
self.heartbeatTimer = None
|
||||
prefs = self.localNode.localConfig
|
||||
i = prefs.power.ls_secs / 2
|
||||
logging.debug(f"Sending heartbeat, interval {i}")
|
||||
i = 300
|
||||
logging.debug(f"Sending heartbeat, interval {i} seconds")
|
||||
if i != 0:
|
||||
self.heartbeatTimer = threading.Timer(i, callback)
|
||||
self.heartbeatTimer.start()
|
||||
|
||||
@@ -128,7 +128,7 @@ class Node:
|
||||
print("Requesting current config from remote node (this can take a while).")
|
||||
|
||||
msgIndex = configType.index
|
||||
if configType.containing_type.full_name in ("meshtastic.LocalConfig", "LocalConfig"):
|
||||
if configType.containing_type.name == "LocalConfig":
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.get_config_request = msgIndex
|
||||
self._sendAdmin(p, wantResponse=True, onResponse=onResponse)
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -580,6 +580,7 @@ class Config(google.protobuf.message.Message):
|
||||
LS_SECS_FIELD_NUMBER: builtins.int
|
||||
MIN_WAKE_SECS_FIELD_NUMBER: builtins.int
|
||||
DEVICE_BATTERY_INA_ADDRESS_FIELD_NUMBER: builtins.int
|
||||
POWERMON_ENABLES_FIELD_NUMBER: builtins.int
|
||||
is_power_saving: builtins.bool
|
||||
"""
|
||||
Description: Will sleep everything as much as possible, for the tracker and sensor role this will also include the lora radio.
|
||||
@@ -623,6 +624,11 @@ class Config(google.protobuf.message.Message):
|
||||
"""
|
||||
I2C address of INA_2XX to use for reading device battery voltage
|
||||
"""
|
||||
powermon_enables: builtins.int
|
||||
"""
|
||||
If non-zero, we want powermon log outputs. With the particular (bitfield) sources enabled.
|
||||
Note: we picked an ID of 32 so that lower more efficient IDs can be used for more frequently used options.
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
@@ -634,8 +640,9 @@ class Config(google.protobuf.message.Message):
|
||||
ls_secs: builtins.int = ...,
|
||||
min_wake_secs: builtins.int = ...,
|
||||
device_battery_ina_address: builtins.int = ...,
|
||||
powermon_enables: builtins.int = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["adc_multiplier_override", b"adc_multiplier_override", "device_battery_ina_address", b"device_battery_ina_address", "is_power_saving", b"is_power_saving", "ls_secs", b"ls_secs", "min_wake_secs", b"min_wake_secs", "on_battery_shutdown_after_secs", b"on_battery_shutdown_after_secs", "sds_secs", b"sds_secs", "wait_bluetooth_secs", b"wait_bluetooth_secs"]) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["adc_multiplier_override", b"adc_multiplier_override", "device_battery_ina_address", b"device_battery_ina_address", "is_power_saving", b"is_power_saving", "ls_secs", b"ls_secs", "min_wake_secs", b"min_wake_secs", "on_battery_shutdown_after_secs", b"on_battery_shutdown_after_secs", "powermon_enables", b"powermon_enables", "sds_secs", b"sds_secs", "wait_bluetooth_secs", b"wait_bluetooth_secs"]) -> None: ...
|
||||
|
||||
@typing.final
|
||||
class NetworkConfig(google.protobuf.message.Message):
|
||||
@@ -1530,6 +1537,7 @@ class Config(google.protobuf.message.Message):
|
||||
ENABLED_FIELD_NUMBER: builtins.int
|
||||
MODE_FIELD_NUMBER: builtins.int
|
||||
FIXED_PIN_FIELD_NUMBER: builtins.int
|
||||
DEVICE_LOGGING_ENABLED_FIELD_NUMBER: builtins.int
|
||||
enabled: builtins.bool
|
||||
"""
|
||||
Enable Bluetooth on the device
|
||||
@@ -1542,14 +1550,19 @@ class Config(google.protobuf.message.Message):
|
||||
"""
|
||||
Specified PIN for PairingMode.FixedPin
|
||||
"""
|
||||
device_logging_enabled: builtins.bool
|
||||
"""
|
||||
Enables device (serial style logs) over Bluetooth
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
enabled: builtins.bool = ...,
|
||||
mode: global___Config.BluetoothConfig.PairingMode.ValueType = ...,
|
||||
fixed_pin: builtins.int = ...,
|
||||
device_logging_enabled: builtins.bool = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["enabled", b"enabled", "fixed_pin", b"fixed_pin", "mode", b"mode"]) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["device_logging_enabled", b"device_logging_enabled", "enabled", b"enabled", "fixed_pin", b"fixed_pin", "mode", b"mode"]) -> None: ...
|
||||
|
||||
DEVICE_FIELD_NUMBER: builtins.int
|
||||
POSITION_FIELD_NUMBER: builtins.int
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -125,6 +125,10 @@ class _HardwareModelEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._
|
||||
"""
|
||||
RAK2560 Solar base station based on RAK4630
|
||||
"""
|
||||
HELTEC_HRU_3601: _HardwareModel.ValueType # 23
|
||||
"""
|
||||
Heltec HRU-3601: https://heltec.org/project/hru-3601/
|
||||
"""
|
||||
STATION_G1: _HardwareModel.ValueType # 25
|
||||
"""
|
||||
B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station
|
||||
@@ -412,6 +416,10 @@ RAK2560: HardwareModel.ValueType # 22
|
||||
"""
|
||||
RAK2560 Solar base station based on RAK4630
|
||||
"""
|
||||
HELTEC_HRU_3601: HardwareModel.ValueType # 23
|
||||
"""
|
||||
Heltec HRU-3601: https://heltec.org/project/hru-3601/
|
||||
"""
|
||||
STATION_G1: HardwareModel.ValueType # 25
|
||||
"""
|
||||
B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station
|
||||
|
||||
28
meshtastic/protobuf/powermon_pb2.py
Normal file
28
meshtastic/protobuf/powermon_pb2.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: meshtastic/protobuf/powermon.proto
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import descriptor_pool as _descriptor_pool
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
from google.protobuf.internal import builder as _builder
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"meshtastic/protobuf/powermon.proto\x12\x13meshtastic.protobuf\"\xe0\x01\n\x08PowerMon\"\xd3\x01\n\x05State\x12\x08\n\x04None\x10\x00\x12\x11\n\rCPU_DeepSleep\x10\x01\x12\x12\n\x0e\x43PU_LightSleep\x10\x02\x12\x0c\n\x08Vext1_On\x10\x04\x12\r\n\tLora_RXOn\x10\x08\x12\r\n\tLora_TXOn\x10\x10\x12\x11\n\rLora_RXActive\x10 \x12\t\n\x05\x42T_On\x10@\x12\x0b\n\x06LED_On\x10\x80\x01\x12\x0e\n\tScreen_On\x10\x80\x02\x12\x13\n\x0eScreen_Drawing\x10\x80\x04\x12\x0c\n\x07Wifi_On\x10\x80\x08\x12\x0f\n\nGPS_Active\x10\x80\x10\x42\x63\n\x13\x63om.geeksville.meshB\x0ePowerMonProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
|
||||
|
||||
_globals = globals()
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.powermon_pb2', _globals)
|
||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
DESCRIPTOR._options = None
|
||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\016PowerMonProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
|
||||
_globals['_POWERMON']._serialized_start=60
|
||||
_globals['_POWERMON']._serialized_end=284
|
||||
_globals['_POWERMON_STATE']._serialized_start=73
|
||||
_globals['_POWERMON_STATE']._serialized_end=284
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
97
meshtastic/protobuf/powermon_pb2.pyi
Normal file
97
meshtastic/protobuf/powermon_pb2.pyi
Normal file
@@ -0,0 +1,97 @@
|
||||
"""
|
||||
@generated by mypy-protobuf. Do not edit manually!
|
||||
isort:skip_file
|
||||
"""
|
||||
|
||||
import builtins
|
||||
import google.protobuf.descriptor
|
||||
import google.protobuf.internal.enum_type_wrapper
|
||||
import google.protobuf.message
|
||||
import sys
|
||||
import typing
|
||||
|
||||
if sys.version_info >= (3, 10):
|
||||
import typing as typing_extensions
|
||||
else:
|
||||
import typing_extensions
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
|
||||
|
||||
@typing.final
|
||||
class PowerMon(google.protobuf.message.Message):
|
||||
"""Note: There are no 'PowerMon' messages normally in use (PowerMons are sent only as structured logs - slogs).
|
||||
But we wrap our State enum in this message to effectively nest a namespace (without our linter yelling at us)
|
||||
"""
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
class _State:
|
||||
ValueType = typing.NewType("ValueType", builtins.int)
|
||||
V: typing_extensions.TypeAlias = ValueType
|
||||
|
||||
class _StateEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[PowerMon._State.ValueType], builtins.type):
|
||||
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
|
||||
CPU_DeepSleep: PowerMon._State.ValueType # 1
|
||||
CPU_LightSleep: PowerMon._State.ValueType # 2
|
||||
Vext1_On: PowerMon._State.ValueType # 4
|
||||
"""
|
||||
The external Vext1 power is on. Many boards have auxillary power rails that the CPU turns on only
|
||||
occasionally. In cases where that rail has multiple devices on it we usually want to have logging on
|
||||
the state of that rail as an independent record.
|
||||
For instance on the Heltec Tracker 1.1 board, this rail is the power source for the GPS and screen.
|
||||
|
||||
The log messages will be short and complete (see PowerMon.Event in the protobufs for details).
|
||||
something like "S:PM:C,0x00001234,REASON" where the hex number is the bitmask of all current states.
|
||||
(We use a bitmask for states so that if a log message gets lost it won't be fatal)
|
||||
"""
|
||||
Lora_RXOn: PowerMon._State.ValueType # 8
|
||||
Lora_TXOn: PowerMon._State.ValueType # 16
|
||||
Lora_RXActive: PowerMon._State.ValueType # 32
|
||||
BT_On: PowerMon._State.ValueType # 64
|
||||
LED_On: PowerMon._State.ValueType # 128
|
||||
Screen_On: PowerMon._State.ValueType # 256
|
||||
Screen_Drawing: PowerMon._State.ValueType # 512
|
||||
Wifi_On: PowerMon._State.ValueType # 1024
|
||||
GPS_Active: PowerMon._State.ValueType # 2048
|
||||
"""
|
||||
GPS is actively trying to find our location
|
||||
See GPSPowerState for more details
|
||||
"""
|
||||
|
||||
class State(_State, metaclass=_StateEnumTypeWrapper):
|
||||
"""Any significant power changing event in meshtastic should be tagged with a powermon state transition.
|
||||
If you are making new meshtastic features feel free to add new entries at the end of this definition.
|
||||
"""
|
||||
|
||||
CPU_DeepSleep: PowerMon.State.ValueType # 1
|
||||
CPU_LightSleep: PowerMon.State.ValueType # 2
|
||||
Vext1_On: PowerMon.State.ValueType # 4
|
||||
"""
|
||||
The external Vext1 power is on. Many boards have auxillary power rails that the CPU turns on only
|
||||
occasionally. In cases where that rail has multiple devices on it we usually want to have logging on
|
||||
the state of that rail as an independent record.
|
||||
For instance on the Heltec Tracker 1.1 board, this rail is the power source for the GPS and screen.
|
||||
|
||||
The log messages will be short and complete (see PowerMon.Event in the protobufs for details).
|
||||
something like "S:PM:C,0x00001234,REASON" where the hex number is the bitmask of all current states.
|
||||
(We use a bitmask for states so that if a log message gets lost it won't be fatal)
|
||||
"""
|
||||
Lora_RXOn: PowerMon.State.ValueType # 8
|
||||
Lora_TXOn: PowerMon.State.ValueType # 16
|
||||
Lora_RXActive: PowerMon.State.ValueType # 32
|
||||
BT_On: PowerMon.State.ValueType # 64
|
||||
LED_On: PowerMon.State.ValueType # 128
|
||||
Screen_On: PowerMon.State.ValueType # 256
|
||||
Screen_Drawing: PowerMon.State.ValueType # 512
|
||||
Wifi_On: PowerMon.State.ValueType # 1024
|
||||
GPS_Active: PowerMon.State.ValueType # 2048
|
||||
"""
|
||||
GPS is actively trying to find our location
|
||||
See GPSPowerState for more details
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
) -> None: ...
|
||||
|
||||
global___PowerMon = PowerMon
|
||||
@@ -317,6 +317,9 @@ def support_info():
|
||||
)
|
||||
else:
|
||||
print(f" meshtastic: v{the_version}")
|
||||
if sys.version_info[0] == 3 and sys.version_info[1] < 9:
|
||||
print(" *** this version of the CLI is the last that supports python 3.8 ***")
|
||||
print(" *** please update your python installation ***")
|
||||
print(f" Executable: {sys.argv[0]}")
|
||||
print(
|
||||
f" Python: {platform.python_version()} {platform.python_implementation()} {platform.python_compiler()}"
|
||||
|
||||
7
poetry.lock
generated
7
poetry.lock
generated
@@ -119,13 +119,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2024.6.2"
|
||||
version = "2024.7.4"
|
||||
description = "Python package for providing Mozilla's CA Bundle."
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"},
|
||||
{file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"},
|
||||
{file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"},
|
||||
{file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1103,6 +1103,7 @@ files = [
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
|
||||
|
||||
Submodule protobufs updated: 0c90a6814f...4da558d0f7
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "meshtastic"
|
||||
version = "2.3.12"
|
||||
version = "2.3.13"
|
||||
description = "Python API & client shell for talking to Meshtastic devices"
|
||||
authors = ["Meshtastic Developers <contact@meshtastic.org>"]
|
||||
license = "GPL-3.0-only"
|
||||
|
||||
Reference in New Issue
Block a user