forked from iarv/meshcore-hub
feat: Add MESHCORE_DEVICE_NAME config to set node name on startup
- Add meshcore_device_name field to InterfaceSettings - Implement set_name() method in device interface (real and mock) - Update receiver to set device name during initialization if configured - Add --device-name CLI option with MESHCORE_DEVICE_NAME env var support - Device name is set after time sync and before advertisement broadcast Fixes #37 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: JingleManSweep <jinglemansweep@users.noreply.github.com>
This commit is contained in:
@@ -70,6 +70,11 @@ class InterfaceSettings(CommonSettings):
|
||||
# Mock device
|
||||
mock_device: bool = Field(default=False, description="Use mock device for testing")
|
||||
|
||||
# Device name
|
||||
meshcore_device_name: Optional[str] = Field(
|
||||
default=None, description="Device/node name (optional)"
|
||||
)
|
||||
|
||||
|
||||
class CollectorSettings(CommonSettings):
|
||||
"""Settings for the Collector component."""
|
||||
|
||||
@@ -51,6 +51,13 @@ def interface() -> None:
|
||||
envvar="NODE_ADDRESS",
|
||||
help="Override for device public key/address (hex string)",
|
||||
)
|
||||
@click.option(
|
||||
"--device-name",
|
||||
type=str,
|
||||
default=None,
|
||||
envvar="MESHCORE_DEVICE_NAME",
|
||||
help="Device/node name (optional)",
|
||||
)
|
||||
@click.option(
|
||||
"--mqtt-host",
|
||||
type=str,
|
||||
@@ -99,6 +106,7 @@ def run(
|
||||
baud: int,
|
||||
mock: bool,
|
||||
node_address: str | None,
|
||||
device_name: str | None,
|
||||
mqtt_host: str,
|
||||
mqtt_port: int,
|
||||
mqtt_username: str | None,
|
||||
@@ -139,6 +147,7 @@ def run(
|
||||
baud=baud,
|
||||
mock=mock,
|
||||
node_address=node_address,
|
||||
device_name=device_name,
|
||||
mqtt_host=mqtt_host,
|
||||
mqtt_port=mqtt_port,
|
||||
mqtt_username=mqtt_username,
|
||||
@@ -153,6 +162,7 @@ def run(
|
||||
baud=baud,
|
||||
mock=mock,
|
||||
node_address=node_address,
|
||||
device_name=device_name,
|
||||
mqtt_host=mqtt_host,
|
||||
mqtt_port=mqtt_port,
|
||||
mqtt_username=mqtt_username,
|
||||
@@ -193,6 +203,13 @@ def run(
|
||||
envvar="NODE_ADDRESS",
|
||||
help="Override for device public key/address (hex string)",
|
||||
)
|
||||
@click.option(
|
||||
"--device-name",
|
||||
type=str,
|
||||
default=None,
|
||||
envvar="MESHCORE_DEVICE_NAME",
|
||||
help="Device/node name (optional)",
|
||||
)
|
||||
@click.option(
|
||||
"--mqtt-host",
|
||||
type=str,
|
||||
@@ -233,6 +250,7 @@ def receiver(
|
||||
baud: int,
|
||||
mock: bool,
|
||||
node_address: str | None,
|
||||
device_name: str | None,
|
||||
mqtt_host: str,
|
||||
mqtt_port: int,
|
||||
mqtt_username: str | None,
|
||||
@@ -294,6 +312,13 @@ def receiver(
|
||||
envvar="NODE_ADDRESS",
|
||||
help="Override for device public key/address (hex string)",
|
||||
)
|
||||
@click.option(
|
||||
"--device-name",
|
||||
type=str,
|
||||
default=None,
|
||||
envvar="MESHCORE_DEVICE_NAME",
|
||||
help="Device/node name (optional)",
|
||||
)
|
||||
@click.option(
|
||||
"--mqtt-host",
|
||||
type=str,
|
||||
@@ -334,6 +359,7 @@ def sender(
|
||||
baud: int,
|
||||
mock: bool,
|
||||
node_address: str | None,
|
||||
device_name: str | None,
|
||||
mqtt_host: str,
|
||||
mqtt_port: int,
|
||||
mqtt_username: str | None,
|
||||
|
||||
@@ -164,6 +164,18 @@ class BaseMeshCoreDevice(ABC):
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def set_name(self, name: str) -> bool:
|
||||
"""Set the device's node name.
|
||||
|
||||
Args:
|
||||
name: Node name to set
|
||||
|
||||
Returns:
|
||||
True if name was set successfully
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def start_message_fetching(self) -> bool:
|
||||
"""Start automatic message fetching.
|
||||
@@ -518,6 +530,24 @@ class MeshCoreDevice(BaseMeshCoreDevice):
|
||||
logger.error(f"Failed to set device time: {e}")
|
||||
return False
|
||||
|
||||
def set_name(self, name: str) -> bool:
|
||||
"""Set the device's node name."""
|
||||
if not self._connected or not self._mc:
|
||||
logger.error("Cannot set name: not connected")
|
||||
return False
|
||||
|
||||
try:
|
||||
|
||||
async def _set_name() -> None:
|
||||
await self._mc.commands.set_name(name)
|
||||
|
||||
self._loop.run_until_complete(_set_name())
|
||||
logger.info(f"Set device name to '{name}'")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to set device name: {e}")
|
||||
return False
|
||||
|
||||
def start_message_fetching(self) -> bool:
|
||||
"""Start automatic message fetching."""
|
||||
if not self._connected or not self._mc:
|
||||
|
||||
@@ -271,6 +271,17 @@ class MockMeshCoreDevice(BaseMeshCoreDevice):
|
||||
logger.info(f"Mock: Set device time to {timestamp}")
|
||||
return True
|
||||
|
||||
def set_name(self, name: str) -> bool:
|
||||
"""Set the mock device's node name."""
|
||||
if not self._connected:
|
||||
logger.error("Cannot set name: not connected")
|
||||
return False
|
||||
|
||||
logger.info(f"Mock: Set device name to '{name}'")
|
||||
# Update the mock config name
|
||||
self.mock_config.name = name
|
||||
return True
|
||||
|
||||
def start_message_fetching(self) -> bool:
|
||||
"""Start automatic message fetching (mock)."""
|
||||
if not self._connected:
|
||||
|
||||
@@ -33,15 +33,18 @@ class Receiver:
|
||||
self,
|
||||
device: BaseMeshCoreDevice,
|
||||
mqtt_client: MQTTClient,
|
||||
device_name: Optional[str] = None,
|
||||
):
|
||||
"""Initialize receiver.
|
||||
|
||||
Args:
|
||||
device: MeshCore device instance
|
||||
mqtt_client: MQTT client instance
|
||||
device_name: Optional device/node name to set on startup
|
||||
"""
|
||||
self.device = device
|
||||
self.mqtt = mqtt_client
|
||||
self.device_name = device_name
|
||||
self._running = False
|
||||
self._shutdown_event = threading.Event()
|
||||
self._device_connected = False
|
||||
@@ -71,11 +74,14 @@ class Receiver:
|
||||
"device_public_key": self.device.public_key,
|
||||
}
|
||||
|
||||
def _initialize_device(self) -> None:
|
||||
def _initialize_device(self, device_name: Optional[str] = None) -> None:
|
||||
"""Initialize device after connection.
|
||||
|
||||
Sets the hardware clock, sends a local advertisement, starts message fetching,
|
||||
and syncs the contact database.
|
||||
Sets the hardware clock, optionally sets device name, sends a local advertisement,
|
||||
starts message fetching, and syncs the contact database.
|
||||
|
||||
Args:
|
||||
device_name: Optional device/node name to set
|
||||
"""
|
||||
# Set device time to current Unix timestamp
|
||||
current_time = int(time.time())
|
||||
@@ -84,6 +90,13 @@ class Receiver:
|
||||
else:
|
||||
logger.warning("Failed to synchronize device clock")
|
||||
|
||||
# Set device name if provided
|
||||
if device_name:
|
||||
if self.device.set_name(device_name):
|
||||
logger.info(f"Set device name to '{device_name}'")
|
||||
else:
|
||||
logger.warning(f"Failed to set device name to '{device_name}'")
|
||||
|
||||
# Send a flood advertisement to broadcast device name
|
||||
if self.device.send_advertisement(flood=True):
|
||||
logger.info("Sent flood advertisement")
|
||||
@@ -211,8 +224,8 @@ class Receiver:
|
||||
|
||||
self._device_connected = True
|
||||
|
||||
# Initialize device: set time and send local advertisement
|
||||
self._initialize_device()
|
||||
# Initialize device: set time, optionally set name, and send local advertisement
|
||||
self._initialize_device(device_name=self.device_name)
|
||||
|
||||
self._running = True
|
||||
|
||||
@@ -271,6 +284,7 @@ def create_receiver(
|
||||
baud: int = 115200,
|
||||
mock: bool = False,
|
||||
node_address: Optional[str] = None,
|
||||
device_name: Optional[str] = None,
|
||||
mqtt_host: str = "localhost",
|
||||
mqtt_port: int = 1883,
|
||||
mqtt_username: Optional[str] = None,
|
||||
@@ -284,6 +298,7 @@ def create_receiver(
|
||||
baud: Baud rate
|
||||
mock: Use mock device
|
||||
node_address: Optional override for device public key/address
|
||||
device_name: Optional device/node name to set on startup
|
||||
mqtt_host: MQTT broker host
|
||||
mqtt_port: MQTT broker port
|
||||
mqtt_username: MQTT username
|
||||
@@ -312,7 +327,7 @@ def create_receiver(
|
||||
)
|
||||
mqtt_client = MQTTClient(mqtt_config)
|
||||
|
||||
return Receiver(device, mqtt_client)
|
||||
return Receiver(device, mqtt_client, device_name=device_name)
|
||||
|
||||
|
||||
def run_receiver(
|
||||
@@ -320,6 +335,7 @@ def run_receiver(
|
||||
baud: int = 115200,
|
||||
mock: bool = False,
|
||||
node_address: Optional[str] = None,
|
||||
device_name: Optional[str] = None,
|
||||
mqtt_host: str = "localhost",
|
||||
mqtt_port: int = 1883,
|
||||
mqtt_username: Optional[str] = None,
|
||||
@@ -335,6 +351,7 @@ def run_receiver(
|
||||
baud: Baud rate
|
||||
mock: Use mock device
|
||||
node_address: Optional override for device public key/address
|
||||
device_name: Optional device/node name to set on startup
|
||||
mqtt_host: MQTT broker host
|
||||
mqtt_port: MQTT broker port
|
||||
mqtt_username: MQTT username
|
||||
@@ -346,6 +363,7 @@ def run_receiver(
|
||||
baud=baud,
|
||||
mock=mock,
|
||||
node_address=node_address,
|
||||
device_name=device_name,
|
||||
mqtt_host=mqtt_host,
|
||||
mqtt_port=mqtt_port,
|
||||
mqtt_username=mqtt_username,
|
||||
|
||||
@@ -287,6 +287,7 @@ def create_sender(
|
||||
baud: int = 115200,
|
||||
mock: bool = False,
|
||||
node_address: Optional[str] = None,
|
||||
device_name: Optional[str] = None,
|
||||
mqtt_host: str = "localhost",
|
||||
mqtt_port: int = 1883,
|
||||
mqtt_username: Optional[str] = None,
|
||||
@@ -300,6 +301,7 @@ def create_sender(
|
||||
baud: Baud rate
|
||||
mock: Use mock device
|
||||
node_address: Optional override for device public key/address
|
||||
device_name: Optional device/node name (not used in SENDER mode)
|
||||
mqtt_host: MQTT broker host
|
||||
mqtt_port: MQTT broker port
|
||||
mqtt_username: MQTT username
|
||||
@@ -336,6 +338,7 @@ def run_sender(
|
||||
baud: int = 115200,
|
||||
mock: bool = False,
|
||||
node_address: Optional[str] = None,
|
||||
device_name: Optional[str] = None,
|
||||
mqtt_host: str = "localhost",
|
||||
mqtt_port: int = 1883,
|
||||
mqtt_username: Optional[str] = None,
|
||||
@@ -351,6 +354,7 @@ def run_sender(
|
||||
baud: Baud rate
|
||||
mock: Use mock device
|
||||
node_address: Optional override for device public key/address
|
||||
device_name: Optional device/node name (not used in SENDER mode)
|
||||
mqtt_host: MQTT broker host
|
||||
mqtt_port: MQTT broker port
|
||||
mqtt_username: MQTT username
|
||||
@@ -362,6 +366,7 @@ def run_sender(
|
||||
baud=baud,
|
||||
mock=mock,
|
||||
node_address=node_address,
|
||||
device_name=device_name,
|
||||
mqtt_host=mqtt_host,
|
||||
mqtt_port=mqtt_port,
|
||||
mqtt_username=mqtt_username,
|
||||
|
||||
Reference in New Issue
Block a user