Compare commits

...

25 Commits
2.4.0 ... 2.4.2

Author SHA1 Message Date
github-actions
0aac077ce7 bump version to 2.4.2 2024-09-11 16:05:25 +00:00
Ian McEwen
aa6f09635a Merge pull request #661 from meshtastic/dependabot/pip/jupyterlab-4.2.5
Bump jupyterlab from 4.2.3 to 4.2.5
2024-09-06 11:30:17 -07:00
Ian McEwen
83b0dcad56 Merge pull request #667 from ianmcorvidae/telemetry-updating
Update telemetry in interface.nodes on receiving device metrics packets
2024-09-06 11:10:17 -07:00
Ian McEwen
78d8403bbd Update telemetry in interface.nodes on receiving device metrics packets 2024-09-06 00:08:20 -07:00
Ian McEwen
0813e8dba6 protobufs: v2.4.2; bump to alpha version 2024-09-05 14:27:38 -07:00
github-actions
23bb2e26f9 bump version to 2.4.1 2024-09-05 21:22:03 +00:00
Ian McEwen
b59ecff272 Merge pull request #666 from ianmcorvidae/fix-set-owner
Ensure set-owner combined with set-owner-short sets both values
2024-09-05 13:58:36 -07:00
Ian McEwen
17f3605736 Ensure set-owner combined with set-owner-short sets both values 2024-09-05 13:58:02 -07:00
Ian McEwen
a689fd73a2 Deprecate --no-time and remove behavior, followup to #663 2024-09-05 13:49:28 -07:00
Ian McEwen
da30e1141a Merge pull request #663 from meshtastic/outtatime
Don't automatically set the time from Python
2024-09-05 13:47:36 -07:00
Ian McEwen
b4bd9568e4 Merge pull request #664 from lysol/master
Reuse node to prevent overwriting channel settings
2024-09-03 16:12:13 -07:00
Derek Arnold
aed4f25cf5 Reuse node to prevent overwriting channel settings to be sent out over the admin channel 2024-09-03 17:41:05 -05:00
Jonathan Bennett
5c312bedc1 Remove assert from test, due to removed position time 2024-08-30 01:15:40 -05:00
Jonathan Bennett
428e9a228c Remove unused time variable 2024-08-29 23:09:04 -05:00
Jonathan Bennett
4500850063 Don't automatically set the time from Python
The Python MO is to do as little as possible beyond what the user has intentionally instructed. So don't try to set the time automatically.
2024-08-29 22:29:20 -05:00
dependabot[bot]
aedaa3748d Bump jupyterlab from 4.2.3 to 4.2.5
Bumps [jupyterlab](https://github.com/jupyterlab/jupyterlab) from 4.2.3 to 4.2.5.
- [Release notes](https://github.com/jupyterlab/jupyterlab/releases)
- [Changelog](https://github.com/jupyterlab/jupyterlab/blob/@jupyterlab/lsp@4.2.5/CHANGELOG.md)
- [Commits](https://github.com/jupyterlab/jupyterlab/compare/@jupyterlab/lsp@4.2.3...@jupyterlab/lsp@4.2.5)

---
updated-dependencies:
- dependency-name: jupyterlab
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-29 18:23:54 +00:00
Ian McEwen
bcce5687c5 Merge pull request #659 from wnagele/unreachable_code
Code block unreachable
2024-08-25 13:18:06 -07:00
Ian McEwen
b9d805057f Merge pull request #658 from wnagele/master
Add method to be able to send heartbeat
2024-08-25 13:17:51 -07:00
Wolfgang Nagele
d77335caa7 Add sendHeartbeat doc-string 2024-08-25 22:13:08 +02:00
Wolfgang Nagele
b692ef4cfb Add method to be able to send heartbeat 2024-08-25 14:47:41 +02:00
Wolfgang Nagele
e725292ee0 Code block unreachable 2024-08-25 14:39:37 +02:00
Ian McEwen
abf9e96d3d Set release tag to the version update commit sha, not the pre-update one 2024-08-21 20:07:12 -07:00
Ian McEwen
740f0f0961 set prerelease version to match protobufs 2024-08-21 19:53:23 -07:00
Ian McEwen
abb00251c0 protobufs: v2.4.1 2024-08-21 19:52:56 -07:00
github-actions
3335b3d651 bump version to 2.4.0 2024-08-22 02:23:53 +00:00
11 changed files with 95 additions and 75 deletions

View File

@@ -52,6 +52,7 @@ jobs:
prerelease: true
release_name: Meshtastic Python ${{ steps.get_version.outputs.version }}
tag_name: ${{ steps.get_version.outputs.version }}
commitish: ${{ steps.commit_updated.outputs.sha }}
body: |
Autogenerated by github action, developer should edit as required before publishing...
env:

View File

@@ -191,6 +191,16 @@ def _onNodeInfoReceive(iface, asDict):
iface.nodes[p["id"]] = n
_receiveInfoUpdate(iface, asDict)
def _onTelemetryReceive(iface, asDict):
"""Automatically update device metrics on received packets"""
logging.debug(f"in _onTelemetryReceive() asDict:{asDict}")
deviceMetrics = asDict.get("decoded", {}).get("telemetry", {}).get("deviceMetrics")
if "from" in asDict and deviceMetrics is not None:
node = iface._getOrCreateByNum(asDict["from"])
newMetrics = node.get("deviceMetrics", {})
newMetrics.update(deviceMetrics)
logging.debug(f"updating metrics for {asDict['from']} to {newMetrics}")
node["deviceMetrics"] = newMetrics
def _receiveInfoUpdate(iface, asDict):
if "from" in asDict:
@@ -221,7 +231,7 @@ protocols = {
portnums_pb2.PortNum.ADMIN_APP: KnownProtocol("admin", admin_pb2.AdminMessage),
portnums_pb2.PortNum.ROUTING_APP: KnownProtocol("routing", mesh_pb2.Routing),
portnums_pb2.PortNum.TELEMETRY_APP: KnownProtocol(
"telemetry", telemetry_pb2.Telemetry
"telemetry", telemetry_pb2.Telemetry, _onTelemetryReceive
),
portnums_pb2.PortNum.REMOTE_HARDWARE_APP: KnownProtocol(
"remotehw", remote_hardware_pb2.HardwareMessage

View File

@@ -314,35 +314,17 @@ def onConnected(interface):
print("Setting device position and enabling fixed position setting")
# can include lat/long/alt etc: latitude = 37.5, longitude = -122.1
interface.localNode.setFixedPosition(lat, lon, alt)
elif not args.no_time:
# We normally provide a current time to the mesh when we connect
if (
interface.localNode.nodeNum in interface.nodesByNum
and "position" in interface.nodesByNum[interface.localNode.nodeNum]
):
# send the same position the node already knows, just to update time
position = interface.nodesByNum[interface.localNode.nodeNum]["position"]
interface.sendPosition(
position.get("latitude", 0.0),
position.get("longitude", 0.0),
position.get("altitude", 0.0),
)
else:
interface.sendPosition()
if args.set_owner:
if args.set_owner or args.set_owner_short:
closeNow = True
waitForAckNak = True
print(f"Setting device owner to {args.set_owner}")
interface.getNode(args.dest, False).setOwner(args.set_owner)
if args.set_owner_short:
closeNow = True
waitForAckNak = True
print(f"Setting device owner short to {args.set_owner_short}")
interface.getNode(args.dest, False).setOwner(
long_name=None, short_name=args.set_owner_short
)
if args.set_owner and args.set_owner_short:
print(f"Setting device owner to {args.set_owner} and short name to {args.set_owner_short}")
elif args.set_owner:
print(f"Setting device owner to {args.set_owner}")
else: # short name only
print(f"Setting device owner short to {args.set_owner_short}")
interface.getNode(args.dest, False).setOwner(long_name=args.set_owner, short_name=args.set_owner_short)
# TODO: add to export-config and configure
if args.set_canned_message:
@@ -778,7 +760,8 @@ def onConnected(interface):
channelIndex = mt_config.channel_index
if channelIndex is None:
meshtastic.util.our_exit("Warning: Need to specify '--ch-index'.", 1)
ch = interface.getNode(args.dest).channels[channelIndex]
node = interface.getNode(args.dest)
ch = node.channels[channelIndex]
if args.ch_enable or args.ch_disable:
print(
@@ -836,7 +819,7 @@ def onConnected(interface):
ch.role = channel_pb2.Channel.Role.DISABLED
print(f"Writing modified channels to device")
interface.getNode(args.dest).writeChannel(channelIndex)
node.writeChannel(channelIndex)
if args.get_canned_message:
closeNow = True
@@ -1466,6 +1449,10 @@ def initParser():
group.add_argument("--set-owner", help="Set device owner name", action="store")
group.add_argument(
"--set-owner-short", help="Set device owner short name", action="store"
)
group.add_argument(
"--set-canned-message",
help="Set the canned messages plugin message (up to 200 characters).",
@@ -1478,10 +1465,6 @@ def initParser():
action="store",
)
group.add_argument(
"--set-owner-short", help="Set device owner short name", action="store"
)
group.add_argument(
"--set-ham", help="Set licensed Ham ID and turn off encryption", action="store"
)
@@ -1587,7 +1570,7 @@ def initParser():
group.add_argument(
"--no-time",
help="Suppress sending the current time to the mesh",
help="Deprecated. Retained for backwards compatibility in scripts, but is a no-op.",
action="store_true",
)

View File

@@ -442,7 +442,6 @@ class MeshInterface: # pylint: disable=R0902
latitude: float = 0.0,
longitude: float = 0.0,
altitude: int = 0,
timeSec: int = 0,
destinationId: Union[int, str] = BROADCAST_ADDR,
wantAck: bool = False,
wantResponse: bool = False,
@@ -454,8 +453,6 @@ class MeshInterface: # pylint: disable=R0902
Also, the device software will notice this packet and use it to automatically
set its notion of the local position.
If timeSec is not specified (recommended), we will use the local machine time.
Returns the sent packet. The id field will be populated in this packet and
can be used to track future message acks/naks.
"""
@@ -472,11 +469,6 @@ class MeshInterface: # pylint: disable=R0902
p.altitude = int(altitude)
logging.debug(f"p.altitude:{p.altitude}")
if timeSec == 0:
timeSec = int(time.time()) # returns unix timestamp in seconds
p.time = timeSec
logging.debug(f"p.time:{p.time}")
if wantResponse:
onResponse = self.onResponsePosition
else:
@@ -812,19 +804,22 @@ class MeshInterface: # pylint: disable=R0902
lambda: pub.sendMessage("meshtastic.connection.lost", interface=self)
)
def sendHeartbeat(self):
"""Sends a heartbeat to the radio. Can be used to verify the connection is healthy."""
p = mesh_pb2.ToRadio()
p.heartbeat.CopyFrom(mesh_pb2.Heartbeat())
self._sendToRadio(p)
def _startHeartbeat(self):
"""We need to send a heartbeat message to the device every X seconds"""
def callback():
self.heartbeatTimer = None
i = 300
logging.debug(f"Sending heartbeat, interval {i} seconds")
if i != 0:
self.heartbeatTimer = threading.Timer(i, callback)
self.heartbeatTimer.start()
p = mesh_pb2.ToRadio()
p.heartbeat.CopyFrom(mesh_pb2.Heartbeat())
self._sendToRadio(p)
interval = 300
logging.debug(f"Sending heartbeat, interval {interval} seconds")
self.heartbeatTimer = threading.Timer(interval, callback)
self.heartbeatTimer.start()
self.sendHeartbeat()
callback() # run our periodic callback now, it will make another timer if necessary
@@ -975,13 +970,6 @@ class MeshInterface: # pylint: disable=R0902
self.localNode.nodeNum = self.myInfo.my_node_num
logging.debug(f"Received myinfo: {stripnl(fromRadio.my_info)}")
failmsg = None
if failmsg:
self.failure = MeshInterface.MeshInterfaceError(failmsg)
self.isConnected.set() # let waitConnected return this exception
self.close()
elif fromRadio.HasField("metadata"):
self.metadata = fromRadio.metadata
logging.debug(f"Received device metadata: {stripnl(fromRadio.metadata)}")

View File

@@ -5,7 +5,7 @@ import base64
import logging
import time
from typing import Union
from typing import Optional, Union
from meshtastic.protobuf import admin_pb2, apponly_pb2, channel_pb2, localonly_pb2, mesh_pb2, portnums_pb2
from meshtastic.util import (
@@ -279,7 +279,7 @@ class Node:
return c.index
return 0
def setOwner(self, long_name=None, short_name=None, is_licensed=False):
def setOwner(self, long_name: Optional[str]=None, short_name: Optional[str]=None, is_licensed: bool=False):
"""Set device owner name"""
logging.debug(f"in setOwner nodeNum:{self.nodeNum}")
p = admin_pb2.AdminMessage()

View File

File diff suppressed because one or more lines are too long

View File

@@ -324,6 +324,14 @@ class _HardwareModelEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._
Heltec Mesh Node T114 board with nRF52840 CPU, and a 1.14 inch TFT display, Ultimate low-power design,
specifically adapted for the Meshtatic project
"""
SENSECAP_INDICATOR: _HardwareModel.ValueType # 70
"""
Sensecap Indicator from Seeed Studio. ESP32-S3 device with TFT and RP2040 coprocessor
"""
TRACKER_T1000_E: _HardwareModel.ValueType # 71
"""
Seeed studio T1000-E tracker card. NRF52840 w/ LR1110 radio, GPS, button, buzzer, and sensors.
"""
PRIVATE_HW: _HardwareModel.ValueType # 255
"""
------------------------------------------------------------------------------------------------------------------------------------------
@@ -632,6 +640,14 @@ HELTEC_MESH_NODE_T114: HardwareModel.ValueType # 69
Heltec Mesh Node T114 board with nRF52840 CPU, and a 1.14 inch TFT display, Ultimate low-power design,
specifically adapted for the Meshtatic project
"""
SENSECAP_INDICATOR: HardwareModel.ValueType # 70
"""
Sensecap Indicator from Seeed Studio. ESP32-S3 device with TFT and RP2040 coprocessor
"""
TRACKER_T1000_E: HardwareModel.ValueType # 71
"""
Seeed studio T1000-E tracker card. NRF52840 w/ LR1110 radio, GPS, button, buzzer, and sensors.
"""
PRIVATE_HW: HardwareModel.ValueType # 255
"""
------------------------------------------------------------------------------------------------------------------------------------------
@@ -731,6 +747,17 @@ class _CriticalErrorCodeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapp
A (likely software but possibly hardware) failure was detected while trying to send packets.
If this occurs on your board, please post in the forum so that we can ask you to collect some information to allow fixing this bug
"""
FLASH_CORRUPTION_RECOVERABLE: _CriticalErrorCode.ValueType # 12
"""
Corruption was detected on the flash filesystem but we were able to repair things.
If you see this failure in the field please post in the forum because we are interested in seeing if this is occurring in the field.
"""
FLASH_CORRUPTION_UNRECOVERABLE: _CriticalErrorCode.ValueType # 13
"""
Corruption was detected on the flash filesystem but we were unable to repair things.
NOTE: Your node will probably need to be reconfigured the next time it reboots (it will lose the region code etc...)
If you see this failure in the field please post in the forum because we are interested in seeing if this is occurring in the field.
"""
class CriticalErrorCode(_CriticalErrorCode, metaclass=_CriticalErrorCodeEnumTypeWrapper):
"""
@@ -789,6 +816,17 @@ RADIO_SPI_BUG: CriticalErrorCode.ValueType # 11
A (likely software but possibly hardware) failure was detected while trying to send packets.
If this occurs on your board, please post in the forum so that we can ask you to collect some information to allow fixing this bug
"""
FLASH_CORRUPTION_RECOVERABLE: CriticalErrorCode.ValueType # 12
"""
Corruption was detected on the flash filesystem but we were able to repair things.
If you see this failure in the field please post in the forum because we are interested in seeing if this is occurring in the field.
"""
FLASH_CORRUPTION_UNRECOVERABLE: CriticalErrorCode.ValueType # 13
"""
Corruption was detected on the flash filesystem but we were unable to repair things.
NOTE: Your node will probably need to be reconfigured the next time it reboots (it will lose the region code etc...)
If you see this failure in the field please post in the forum because we are interested in seeing if this is occurring in the field.
"""
global___CriticalErrorCode = CriticalErrorCode
@typing.final

View File

@@ -185,7 +185,7 @@ def test_sendPosition(caplog):
with caplog.at_level(logging.DEBUG):
iface.sendPosition()
iface.close()
assert re.search(r"p.time:", caplog.text, re.MULTILINE)
# assert re.search(r"p.time:", caplog.text, re.MULTILINE)
# TODO

14
poetry.lock generated
View File

@@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
[[package]]
name = "altgraph"
@@ -1576,13 +1576,13 @@ test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (>
[[package]]
name = "jupyterlab"
version = "4.2.3"
version = "4.2.5"
description = "JupyterLab computational environment"
optional = false
python-versions = ">=3.8"
files = [
{file = "jupyterlab-4.2.3-py3-none-any.whl", hash = "sha256:0b59d11808e84bb84105c73364edfa867dd475492429ab34ea388a52f2e2e596"},
{file = "jupyterlab-4.2.3.tar.gz", hash = "sha256:df6e46969ea51d66815167f23d92f105423b7f1f06fa604d4f44aeb018c82c7b"},
{file = "jupyterlab-4.2.5-py3-none-any.whl", hash = "sha256:73b6e0775d41a9fee7ee756c80f58a6bed4040869ccc21411dc559818874d321"},
{file = "jupyterlab-4.2.5.tar.gz", hash = "sha256:ae7f3a1b8cb88b4f55009ce79fa7c06f99d70cd63601ee4aa91815d054f46f75"},
]
[package.dependencies]
@@ -1607,7 +1607,7 @@ dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov",
docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-jupyter", "sphinx (>=1.8,<7.3.0)", "sphinx-copybutton"]
docs-screenshots = ["altair (==5.3.0)", "ipython (==8.16.1)", "ipywidgets (==8.1.2)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.1.post2)", "matplotlib (==3.8.3)", "nbconvert (>=7.0.0)", "pandas (==2.2.1)", "scipy (==1.12.0)", "vega-datasets (==0.9.0)"]
test = ["coverage", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter (>=0.5.3)", "pytest-timeout", "pytest-tornasync", "requests", "requests-cache", "virtualenv"]
upgrade-extension = ["copier (>=8,<10)", "jinja2-time (<0.3)", "pydantic (<2.0)", "pyyaml-include (<2.0)", "tomli-w (<2.0)"]
upgrade-extension = ["copier (>=9,<10)", "jinja2-time (<0.3)", "pydantic (<3.0)", "pyyaml-include (<3.0)", "tomli-w (<2.0)"]
[[package]]
name = "jupyterlab-pygments"
@@ -2287,8 +2287,8 @@ files = [
[package.dependencies]
numpy = [
{version = ">=1.22.4", markers = "python_version < \"3.11\""},
{version = ">=1.23.2", markers = "python_version == \"3.11\""},
{version = ">=1.26.0", markers = "python_version >= \"3.12\""},
{version = ">=1.23.2", markers = "python_version == \"3.11\""},
]
python-dateutil = ">=2.8.2"
pytz = ">=2020.1"
@@ -2845,8 +2845,8 @@ astroid = ">=3.2.2,<=3.3.0-dev0"
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
dill = [
{version = ">=0.2", markers = "python_version < \"3.11\""},
{version = ">=0.3.6", markers = "python_version >= \"3.11\" and python_version < \"3.12\""},
{version = ">=0.3.7", markers = "python_version >= \"3.12\""},
{version = ">=0.3.6", markers = "python_version >= \"3.11\" and python_version < \"3.12\""},
]
isort = ">=4.2.5,<5.13.0 || >5.13.0,<6"
mccabe = ">=0.6,<0.8"

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "meshtastic"
version = "2.4.0a0"
version = "2.4.2"
description = "Python API & client shell for talking to Meshtastic devices"
authors = ["Meshtastic Developers <contact@meshtastic.org>"]
license = "GPL-3.0-only"