From b038c942f1cca0755c9924875caf0bc2e4c8dffd Mon Sep 17 00:00:00 2001 From: Damien Tournoud Date: Wed, 17 Jan 2024 16:29:58 -0800 Subject: [PATCH] sensors: Add scd30.force_calibration remote command --- modules/main.py | 13 ++++++++++++- modules/ribbit/golioth/__init__.py | 14 +++++++++----- modules/ribbit/sensors/base.py | 17 +++++++++++++++++ modules/ribbit/sensors/scd30.py | 17 +++++++++++++++++ 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/modules/main.py b/modules/main.py index a61d2cf..954d549 100644 --- a/modules/main.py +++ b/modules/main.py @@ -98,6 +98,16 @@ class Registry: "memory": _board.Memory, } + commands = {} + + for sensor_cls in sensor_types.values(): + commands_factory = getattr(sensor_cls, "commands", None) + if commands_factory is None: + continue + + for command_name, command in commands_factory().items(): + commands[command_name] = command + default_sensors = [ { "type": "board", @@ -151,9 +161,10 @@ class Registry: registry.ota_manager = _ota.OTAManager(in_simulator=in_simulator) registry.golioth = _golioth.Golioth( - registry.config, + registry, ota_manager=registry.ota_manager, in_simulator=in_simulator, + commands=commands, ) registry.sensors = {} diff --git a/modules/ribbit/golioth/__init__.py b/modules/ribbit/golioth/__init__.py index 950a65e..faa10a9 100644 --- a/modules/ribbit/golioth/__init__.py +++ b/modules/ribbit/golioth/__init__.py @@ -59,9 +59,9 @@ class Golioth: - def __init__(self, config, ota_manager, commands=None, in_simulator=False): + def __init__(self, registry, ota_manager, commands=None, in_simulator=False): self._logger = logging.getLogger(__name__) - self._config = config + self._registry = registry self._commands = commands or {} self._coap = None self._ota_manager = ota_manager @@ -73,7 +73,7 @@ def __init__(self, config, ota_manager, commands=None, in_simulator=False): asyncio.create_task(self._loop()) async def _loop(self): - with self._config.watch(*_CONFIG_KEYS) as cfg_watcher: + with self._registry.config.watch(*_CONFIG_KEYS) as cfg_watcher: while True: enabled, host, port, user, password, self._ota_enabled = cfg_watcher.get() @@ -128,7 +128,7 @@ async def _on_golioth_config(self, client, packet): k = k.replace("_", ".").lower() config[k] = v - self._config.set_remote(config) + self._registry.config.set_remote(config) await client.post( ".c/status", @@ -172,7 +172,11 @@ async def _on_golioth_rpc(self, client, packet): command = self._commands.get(req["method"], None) if command is not None: try: - details = await command(*req["params"]) + details = await command( + registry=self._registry, + method=req["method"], + params=req["params"], + ) if details is not None: details = str(details) except Exception as exc: diff --git a/modules/ribbit/sensors/base.py b/modules/ribbit/sensors/base.py index dec3b85..af35fb8 100644 --- a/modules/ribbit/sensors/base.py +++ b/modules/ribbit/sensors/base.py @@ -10,6 +10,23 @@ def __init__(self, registry, id): self._logger = logging.getLogger("sensor." + self.config.name) +def find_sensor_by_id(registry, id, cls=None): + for sensor in registry.sensors.values(): + if sensor._sensor_id == id and (cls is None or sensor.__class__ is cls): + return sensor + + raise ValueError(f"Unknown sensor id ({id})") + + +def sensor_command(cls, command_method_name): + def _command(registry, method, params): + id = params.pop(0) + sensor = find_sensor_by_id(registry, id, cls=cls) + return getattr(sensor, command_method_name)(params) + + return _command + + class PollingSensor(BaseSensor): def __init__(self, registry, id, interval): super().__init__(registry, id) diff --git a/modules/ribbit/sensors/scd30.py b/modules/ribbit/sensors/scd30.py index 895cdb4..874f378 100644 --- a/modules/ribbit/sensors/scd30.py +++ b/modules/ribbit/sensors/scd30.py @@ -207,6 +207,23 @@ async def read_once(self): self.temperature = temperature self.humidity = humidity + @classmethod + def commands(cls): + return { + "scd30.force_calibration": _base.sensor_command(cls, "_force_calibration"), + } + + async def _force_calibration(self, params): + if len(params) != 1: + raise ValueError() + + value = int(params[0]) + + await self._send_command( + _CMD_SET_FORCED_RECALIBRATION_FACTOR, + value, + ) + def export(self): t = isotime(self.last_update) sensor_id = self._sensor_id