From 5f986ab77061945c27d674107db3944009482076 Mon Sep 17 00:00:00 2001 From: Arksine Date: Wed, 6 Jan 2021 14:39:33 -0500 Subject: [PATCH] power: refactor initialization The entire configuration should be validated prior to device initialization. In the event of an error, the GPIO Chip factory must be closed. Signed-off-by: Eric Callahan --- moonraker/plugins/power.py | 52 ++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/moonraker/plugins/power.py b/moonraker/plugins/power.py index af9707a..5f97c78 100644 --- a/moonraker/plugins/power.py +++ b/moonraker/plugins/power.py @@ -20,6 +20,27 @@ from tornado.escape import json_decode class PrinterPower: def __init__(self, config): self.server = config.get_server() + self.chip_factory = GpioChipFactory() + self.devices = {} + prefix_sections = config.get_prefix_sections("power") + logging.info(f"Power plugin loading devices: {prefix_sections}") + try: + for section in prefix_sections: + cfg = config[section] + dev_type = cfg.get("type") + if dev_type == "gpio": + dev = GpioDevice(cfg, self.chip_factory) + elif dev_type == "tplink_smartplug": + dev = TPLinkSmartPlug(cfg) + elif dev_type == "tasmota": + dev = Tasmota(cfg) + else: + raise config.error(f"Unsupported Device Type: {dev_type}") + self.devices[dev.get_name()] = dev + except Exception: + self.chip_factory.close() + raise + self.server.register_endpoint( "/machine/device_power/devices", ['GET'], self._handle_list_devices) @@ -36,24 +57,14 @@ class PrinterPower: "set_device_power", self.set_device_power) self.server.register_event_handler( "server:klippy_shutdown", self._handle_klippy_shutdown) + IOLoop.current().spawn_callback( + self._initalize_devices, list(self.devices.values())) - self.chip_factory = GpioChipFactory() - self.current_dev = None - self.devices = {} - prefix_sections = config.get_prefix_sections("power") - logging.info(f"Power plugin loading devices: {prefix_sections}") - for section in prefix_sections: - cfg = config[section] - dev_type = cfg.get("type") - if dev_type == "gpio": - dev = GpioDevice(cfg, self.chip_factory) - elif dev_type == "tplink_smartplug": - dev = TPLinkSmartPlug(cfg) - elif dev_type == "tasmota": - dev = Tasmota(cfg) - else: - raise config.error(f"Unsupported Device Type: {dev_type}") - self.devices[dev.get_name()] = dev + async def _initalize_devices(self, inital_devs): + for dev in inital_devs: + ret = dev.initialize() + if asyncio.iscoroutine(ret): + await ret async def _handle_klippy_shutdown(self): for name, dev in self.devices.items(): @@ -176,8 +187,7 @@ class GpioDevice: "use by another program or exported by sysfs.") raise config.error("Power GPIO Config Error") self.off_when_shutdown = config.getboolean('off_when_shutdown', False) - initial_state = config.getboolean('initial_state', False) - self.set_power("on" if initial_state else "off") + self.initial_state = config.getboolean('initial_state', False) def _parse_pin(self, config): pin = cfg_pin = config.get("pin") @@ -202,7 +212,7 @@ class GpioDevice: return pin, chip_id, invert def initialize(self): - pass + self.set_power("on" if self.initial_state else "off") def get_name(self): return self.name @@ -256,7 +266,6 @@ class TPLinkSmartPlug: raise config.error(f"Invalid Section Name: {config.get_name()}") self.name = name_parts[1] self.state = "init" - IOLoop.current().spawn_callback(self.initialize) async def _send_tplink_command(self, command): out_cmd = {} @@ -360,7 +369,6 @@ class Tasmota: raise config.error(f"Invalid Section Name: {config.get_name()}") self.name = name_parts[1] self.state = "init" - IOLoop.current().spawn_callback(self.initialize) async def _send_tasmota_command(self, command, password=None): if command in ["on", "off"]: