mirror of
https://github.com/meshcore-dev/meshcore_py.git
synced 2026-06-11 11:56:18 +00:00
control codes support: node_discover_req
This commit is contained in:
@@ -7,10 +7,15 @@ from .binary import BinaryCommandHandler
|
|||||||
from .contact import ContactCommands
|
from .contact import ContactCommands
|
||||||
from .device import DeviceCommands
|
from .device import DeviceCommands
|
||||||
from .messaging import MessagingCommands
|
from .messaging import MessagingCommands
|
||||||
|
from .control_data import ControlDataCommandHandler
|
||||||
|
|
||||||
|
|
||||||
class CommandHandler(
|
class CommandHandler(
|
||||||
DeviceCommands, ContactCommands, MessagingCommands, BinaryCommandHandler
|
DeviceCommands,
|
||||||
|
ContactCommands,
|
||||||
|
MessagingCommands,
|
||||||
|
BinaryCommandHandler,
|
||||||
|
ControlDataCommandHandler
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
45
src/meshcore/commands/control_data.py
Normal file
45
src/meshcore/commands/control_data.py
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import logging
|
||||||
|
import random
|
||||||
|
|
||||||
|
from .base import CommandHandlerBase
|
||||||
|
from ..events import EventType, Event
|
||||||
|
from ..packets import ControlType, PacketType
|
||||||
|
|
||||||
|
logger = logging.getLogger("meshcore")
|
||||||
|
|
||||||
|
class ControlDataCommandHandler(CommandHandlerBase):
|
||||||
|
"""Helper functions to handle binary requests through binary commands"""
|
||||||
|
|
||||||
|
async def send_control_data (self, control_type: ControlType, payload: bytes) -> Event:
|
||||||
|
data = bytearray([PacketType.SEND_CONTROL_DATA.value])
|
||||||
|
data.extend(control_type.value.to_bytes(1, "little", signed = False))
|
||||||
|
data.extend(payload)
|
||||||
|
|
||||||
|
result = await self.send(data, [EventType.OK, EventType.ERROR])
|
||||||
|
return result
|
||||||
|
|
||||||
|
async def send_node_discover_req (
|
||||||
|
self,
|
||||||
|
filter: int,
|
||||||
|
tag: int=None,
|
||||||
|
since: int=None
|
||||||
|
) -> Event:
|
||||||
|
|
||||||
|
if tag is None:
|
||||||
|
tag = random.randint(1, 0xFFFFFFFF)
|
||||||
|
|
||||||
|
data = bytearray()
|
||||||
|
data.extend(filter.to_bytes(1, "little", signed=False))
|
||||||
|
data.extend(tag.to_bytes(4, "little"))
|
||||||
|
if not since is None:
|
||||||
|
data.extend(since.to_bytes(4, "little", signed=False))
|
||||||
|
|
||||||
|
logger.debug(f"sending node discover req {data.hex()}")
|
||||||
|
|
||||||
|
res = await self.send_control_data(ControlType.NODE_DISCOVER_REQ, data)
|
||||||
|
|
||||||
|
if res is None:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
res.payload["tag"] = tag
|
||||||
|
return res
|
||||||
@@ -44,6 +44,8 @@ class EventType(Enum):
|
|||||||
PATH_RESPONSE = "path_response"
|
PATH_RESPONSE = "path_response"
|
||||||
PRIVATE_KEY = "private_key"
|
PRIVATE_KEY = "private_key"
|
||||||
DISABLED = "disabled"
|
DISABLED = "disabled"
|
||||||
|
CONTROL_DATA = "control_data"
|
||||||
|
DISCOVER_RESPONSE = "discover_response"
|
||||||
|
|
||||||
# Command response types
|
# Command response types
|
||||||
OK = "command_ok"
|
OK = "command_ok"
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ class BinaryReqType(Enum):
|
|||||||
MMA = 0x04
|
MMA = 0x04
|
||||||
ACL = 0x05
|
ACL = 0x05
|
||||||
|
|
||||||
|
class ControlType(Enum):
|
||||||
|
NODE_DISCOVER_REQ = 0x80
|
||||||
|
NODE_DISCOVER_RESP = 0x90
|
||||||
|
|
||||||
# Packet prefixes for the protocol
|
# Packet prefixes for the protocol
|
||||||
class PacketType(Enum):
|
class PacketType(Enum):
|
||||||
OK = 0
|
OK = 0
|
||||||
@@ -35,6 +39,7 @@ class PacketType(Enum):
|
|||||||
FACTORY_RESET = 51
|
FACTORY_RESET = 51
|
||||||
PATH_DISCOVERY = 52
|
PATH_DISCOVERY = 52
|
||||||
SET_FLOOD_SCOPE = 54
|
SET_FLOOD_SCOPE = 54
|
||||||
|
SEND_CONTROL_DATA = 55
|
||||||
|
|
||||||
# Push notifications
|
# Push notifications
|
||||||
ADVERTISEMENT = 0x80
|
ADVERTISEMENT = 0x80
|
||||||
@@ -51,3 +56,4 @@ class PacketType(Enum):
|
|||||||
TELEMETRY_RESPONSE = 0x8B
|
TELEMETRY_RESPONSE = 0x8B
|
||||||
BINARY_RESPONSE = 0x8C
|
BINARY_RESPONSE = 0x8C
|
||||||
PATH_DISCOVERY_RESPONSE = 0x8D
|
PATH_DISCOVERY_RESPONSE = 0x8D
|
||||||
|
CONTROL_DATA = 0x8E
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import time
|
|||||||
import io
|
import io
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
from .events import Event, EventType, EventDispatcher
|
from .events import Event, EventType, EventDispatcher
|
||||||
from .packets import BinaryReqType, PacketType
|
from .packets import BinaryReqType, PacketType, ControlType
|
||||||
from .parsing import lpp_parse, lpp_parse_mma, parse_acl, parse_status
|
from .parsing import lpp_parse, lpp_parse_mma, parse_acl, parse_status
|
||||||
from cayennelpp import LppFrame, LppData
|
from cayennelpp import LppFrame, LppData
|
||||||
from meshcore.lpp_json_encoder import lpp_json_encoder
|
from meshcore.lpp_json_encoder import lpp_json_encoder
|
||||||
@@ -331,8 +331,8 @@ class MessageReader:
|
|||||||
|
|
||||||
elif packet_type_value == PacketType.RAW_DATA.value:
|
elif packet_type_value == PacketType.RAW_DATA.value:
|
||||||
res = {}
|
res = {}
|
||||||
res["SNR"] = dbuf.read(1)[0] / 4
|
res["SNR"] = int.from_bytes(dbuf.read(1), byteorder="little", signed=True) / 4
|
||||||
res["RSSI"] = dbuf.read(1)[0]
|
res["RSSI"] = int.from_bytes(dbuf.read(1), byteorder="little", signed=True)
|
||||||
res["payload"] = dbuf.read(4).hex()
|
res["payload"] = dbuf.read(4).hex()
|
||||||
logger.debug("Received raw data")
|
logger.debug("Received raw data")
|
||||||
print(res)
|
print(res)
|
||||||
@@ -593,6 +593,43 @@ class MessageReader:
|
|||||||
res = {"reason": "private_key_export_disabled"}
|
res = {"reason": "private_key_export_disabled"}
|
||||||
await self.dispatcher.dispatch(Event(EventType.DISABLED, res))
|
await self.dispatcher.dispatch(Event(EventType.DISABLED, res))
|
||||||
|
|
||||||
|
elif packet_type_value == PacketType.CONTROL_DATA.value:
|
||||||
|
logger.debug("Received control data packet")
|
||||||
|
res={}
|
||||||
|
res["SNR"] = int.from_bytes(dbuf.read(1), byteorder="little", signed=True) / 4
|
||||||
|
res["RSSI"] = int.from_bytes(dbuf.read(1), byteorder="little", signed=True)
|
||||||
|
res["path_len"] = dbuf.read(1)[0]
|
||||||
|
payload = dbuf.read()
|
||||||
|
payload_type = payload[0]
|
||||||
|
res["payload_type"] = payload_type
|
||||||
|
res["payload"] = payload
|
||||||
|
|
||||||
|
attributes = {"payload_type": payload_type}
|
||||||
|
await self.dispatcher.dispatch(
|
||||||
|
Event(EventType.CONTROL_DATA, res, attributes)
|
||||||
|
)
|
||||||
|
|
||||||
|
# decode NODE_DISCOVER_RESP
|
||||||
|
if payload_type & 0xF0 == ControlType.NODE_DISCOVER_RESP.value:
|
||||||
|
pbuf = io.BytesIO(payload[1:])
|
||||||
|
ndr = dict(res)
|
||||||
|
del ndr["payload_type"]
|
||||||
|
del ndr["payload"]
|
||||||
|
ndr["node_type"] = payload_type & 0x0F
|
||||||
|
ndr["SNR_in"] = int.from_bytes(pbuf.read(1), byteorder="little", signed=True)/4
|
||||||
|
ndr["tag"] = pbuf.read(4).hex()
|
||||||
|
ndr["pubkey"] = pbuf.read(32).hex()
|
||||||
|
|
||||||
|
attributes = {
|
||||||
|
"node_type" : ndr["node_type"],
|
||||||
|
"tag" : ndr["tag"],
|
||||||
|
"pubkey" : ndr["pubkey"],
|
||||||
|
}
|
||||||
|
|
||||||
|
await self.dispatcher.dispatch(
|
||||||
|
Event(EventType.DISCOVER_RESPONSE, ndr, attributes)
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.debug(f"Unhandled data received {data}")
|
logger.debug(f"Unhandled data received {data}")
|
||||||
logger.debug(f"Unhandled packet type: {packet_type_value}")
|
logger.debug(f"Unhandled packet type: {packet_type_value}")
|
||||||
|
|||||||
Reference in New Issue
Block a user