Fix device public key retrieval and add node-address config option

- Use meshcore library's self_info property directly after connection
  instead of waiting for SELF_INFO event (which was already processed)
- Add --node-address CLI option to override device public key/address
- Support NODE_ADDRESS environment variable
- Add node_address parameter to DeviceConfig and all related functions
This commit is contained in:
Claude
2025-12-03 00:26:21 +00:00
parent 32fff7749a
commit 5a1b4fb855
4 changed files with 76 additions and 21 deletions
+34
View File
@@ -45,6 +45,13 @@ def interface() -> None:
envvar="MOCK_DEVICE",
help="Use mock device for testing",
)
@click.option(
"--node-address",
type=str,
default=None,
envvar="NODE_ADDRESS",
help="Override for device public key/address (hex string)",
)
@click.option(
"--mqtt-host",
type=str,
@@ -92,6 +99,7 @@ def run(
port: str,
baud: int,
mock: bool,
node_address: str | None,
mqtt_host: str,
mqtt_port: int,
mqtt_username: str | None,
@@ -119,6 +127,8 @@ def run(
click.echo(f"Serial: {port} @ {baud} baud")
click.echo(f"MQTT: {mqtt_host}:{mqtt_port} (prefix: {prefix})")
click.echo(f"Mock device: {mock}")
if node_address:
click.echo(f"Node address: {node_address}")
mode_upper = mode.upper()
@@ -129,6 +139,7 @@ def run(
port=port,
baud=baud,
mock=mock,
node_address=node_address,
mqtt_host=mqtt_host,
mqtt_port=mqtt_port,
mqtt_username=mqtt_username,
@@ -142,6 +153,7 @@ def run(
port=port,
baud=baud,
mock=mock,
node_address=node_address,
mqtt_host=mqtt_host,
mqtt_port=mqtt_port,
mqtt_username=mqtt_username,
@@ -175,6 +187,13 @@ def run(
envvar="MOCK_DEVICE",
help="Use mock device for testing",
)
@click.option(
"--node-address",
type=str,
default=None,
envvar="NODE_ADDRESS",
help="Override for device public key/address (hex string)",
)
@click.option(
"--mqtt-host",
type=str,
@@ -214,6 +233,7 @@ def receiver(
port: str,
baud: int,
mock: bool,
node_address: str | None,
mqtt_host: str,
mqtt_port: int,
mqtt_username: str | None,
@@ -230,11 +250,14 @@ def receiver(
click.echo(f"Serial: {port} @ {baud} baud")
click.echo(f"MQTT: {mqtt_host}:{mqtt_port} (prefix: {prefix})")
click.echo(f"Mock device: {mock}")
if node_address:
click.echo(f"Node address: {node_address}")
run_receiver(
port=port,
baud=baud,
mock=mock,
node_address=node_address,
mqtt_host=mqtt_host,
mqtt_port=mqtt_port,
mqtt_username=mqtt_username,
@@ -265,6 +288,13 @@ def receiver(
envvar="MOCK_DEVICE",
help="Use mock device for testing",
)
@click.option(
"--node-address",
type=str,
default=None,
envvar="NODE_ADDRESS",
help="Override for device public key/address (hex string)",
)
@click.option(
"--mqtt-host",
type=str,
@@ -304,6 +334,7 @@ def sender(
port: str,
baud: int,
mock: bool,
node_address: str | None,
mqtt_host: str,
mqtt_port: int,
mqtt_username: str | None,
@@ -320,11 +351,14 @@ def sender(
click.echo(f"Serial: {port} @ {baud} baud")
click.echo(f"MQTT: {mqtt_host}:{mqtt_port} (prefix: {prefix})")
click.echo(f"Mock device: {mock}")
if node_address:
click.echo(f"Node address: {node_address}")
run_sender(
port=port,
baud=baud,
mock=mock,
node_address=node_address,
mqtt_host=mqtt_host,
mqtt_port=mqtt_port,
mqtt_username=mqtt_username,
+30 -19
View File
@@ -38,6 +38,7 @@ class DeviceConfig:
timeout: float = 1.0
reconnect_delay: float = 5.0
max_reconnect_attempts: int = 10
node_address: Optional[str] = None # Override for device public key/address
class BaseMeshCoreDevice(ABC):
@@ -244,8 +245,8 @@ class MeshCoreDevice(BaseMeshCoreDevice):
def connect(self) -> bool:
"""Connect to the MeshCore device."""
try:
from meshcore import MeshCore, SerialConnection
from meshcore import EventType as MCEventType
from meshcore import MeshCore
from meshcore.serial_cx import SerialConnection
except ImportError:
logger.error(
"meshcore library not installed. "
@@ -273,22 +274,30 @@ class MeshCoreDevice(BaseMeshCoreDevice):
# Connect asynchronously
self._loop.run_until_complete(self._mc.connect())
# Get device info to retrieve public key
async def get_self_info():
from meshcore import EventType as MCEventType
# Wait for SELF_INFO event
event = await self._mc.wait_for_event(
MCEventType.SELF_INFO,
timeout=5.0
)
if event:
return event.attributes.get("public_key")
return None
self._public_key = self._loop.run_until_complete(get_self_info())
if not self._public_key:
logger.warning("Could not retrieve device public key")
# Get device public key from self_info property
# After connect(), the library internally processes SELF_INFO
# and stores it in the self_info property
if self.config.node_address:
# Use configured override
self._public_key = self.config.node_address
logger.info(f"Using configured node address: {self._public_key}")
else:
# Get from device self_info
self_info = self._mc.self_info
if self_info:
self._public_key = self_info.get("public_key")
if self._public_key:
logger.info(f"Retrieved device public key from self_info")
else:
logger.warning(
"Device self_info missing public_key field. "
"Use --node-address to configure manually."
)
else:
logger.warning(
"Could not retrieve device self_info. "
"Use --node-address to configure manually."
)
self._connected = True
logger.info(f"Connected to MeshCore device, public_key: {self._public_key}")
@@ -480,6 +489,7 @@ def create_device(
port: str = "/dev/ttyUSB0",
baud: int = 115200,
mock: bool = False,
node_address: Optional[str] = None,
) -> BaseMeshCoreDevice:
"""Create a MeshCore device instance.
@@ -487,11 +497,12 @@ def create_device(
port: Serial port path
baud: Baud rate
mock: Use mock device for testing
node_address: Optional override for device public key/address
Returns:
Device instance
"""
config = DeviceConfig(port=port, baud=baud)
config = DeviceConfig(port=port, baud=baud, node_address=node_address)
if mock:
from meshcore_hub.interface.mock_device import MockMeshCoreDevice
+6 -1
View File
@@ -139,6 +139,7 @@ def create_receiver(
port: str = "/dev/ttyUSB0",
baud: int = 115200,
mock: bool = False,
node_address: Optional[str] = None,
mqtt_host: str = "localhost",
mqtt_port: int = 1883,
mqtt_username: Optional[str] = None,
@@ -151,6 +152,7 @@ def create_receiver(
port: Serial port path
baud: Baud rate
mock: Use mock device
node_address: Optional override for device public key/address
mqtt_host: MQTT broker host
mqtt_port: MQTT broker port
mqtt_username: MQTT username
@@ -161,7 +163,7 @@ def create_receiver(
Configured Receiver instance
"""
# Create device
device = create_device(port=port, baud=baud, mock=mock)
device = create_device(port=port, baud=baud, mock=mock, node_address=node_address)
# Create MQTT client
mqtt_config = MQTTConfig(
@@ -181,6 +183,7 @@ def run_receiver(
port: str = "/dev/ttyUSB0",
baud: int = 115200,
mock: bool = False,
node_address: Optional[str] = None,
mqtt_host: str = "localhost",
mqtt_port: int = 1883,
mqtt_username: Optional[str] = None,
@@ -195,6 +198,7 @@ def run_receiver(
port: Serial port path
baud: Baud rate
mock: Use mock device
node_address: Optional override for device public key/address
mqtt_host: MQTT broker host
mqtt_port: MQTT broker port
mqtt_username: MQTT username
@@ -205,6 +209,7 @@ def run_receiver(
port=port,
baud=baud,
mock=mock,
node_address=node_address,
mqtt_host=mqtt_host,
mqtt_port=mqtt_port,
mqtt_username=mqtt_username,
+6 -1
View File
@@ -239,6 +239,7 @@ def create_sender(
port: str = "/dev/ttyUSB0",
baud: int = 115200,
mock: bool = False,
node_address: Optional[str] = None,
mqtt_host: str = "localhost",
mqtt_port: int = 1883,
mqtt_username: Optional[str] = None,
@@ -251,6 +252,7 @@ def create_sender(
port: Serial port path
baud: Baud rate
mock: Use mock device
node_address: Optional override for device public key/address
mqtt_host: MQTT broker host
mqtt_port: MQTT broker port
mqtt_username: MQTT username
@@ -261,7 +263,7 @@ def create_sender(
Configured Sender instance
"""
# Create device
device = create_device(port=port, baud=baud, mock=mock)
device = create_device(port=port, baud=baud, mock=mock, node_address=node_address)
# Create MQTT client
mqtt_config = MQTTConfig(
@@ -281,6 +283,7 @@ def run_sender(
port: str = "/dev/ttyUSB0",
baud: int = 115200,
mock: bool = False,
node_address: Optional[str] = None,
mqtt_host: str = "localhost",
mqtt_port: int = 1883,
mqtt_username: Optional[str] = None,
@@ -295,6 +298,7 @@ def run_sender(
port: Serial port path
baud: Baud rate
mock: Use mock device
node_address: Optional override for device public key/address
mqtt_host: MQTT broker host
mqtt_port: MQTT broker port
mqtt_username: MQTT username
@@ -305,6 +309,7 @@ def run_sender(
port=port,
baud=baud,
mock=mock,
node_address=node_address,
mqtt_host=mqtt_host,
mqtt_port=mqtt_port,
mqtt_username=mqtt_username,