power: add support for bound services
A bound service is stopped when a device powers off and started when a device is powered on. Signed-off-by: Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
parent
12e035b6eb
commit
47999e24c4
|
@ -48,6 +48,7 @@ for pkg_path in PKG_PATHS:
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from confighelper import ConfigHelper
|
from confighelper import ConfigHelper
|
||||||
from websockets import WebRequest
|
from websockets import WebRequest
|
||||||
|
from .machine import Machine
|
||||||
from . import klippy_apis
|
from . import klippy_apis
|
||||||
APIComp = klippy_apis.KlippyAPI
|
APIComp = klippy_apis.KlippyAPI
|
||||||
|
|
||||||
|
@ -125,6 +126,9 @@ class PrinterPower:
|
||||||
inital_devs: List[PowerDevice]
|
inital_devs: List[PowerDevice]
|
||||||
) -> None:
|
) -> None:
|
||||||
event_loop = self.server.get_event_loop()
|
event_loop = self.server.get_event_loop()
|
||||||
|
# Wait up to 5 seconds for the machine component to init
|
||||||
|
machine_cmp: Machine = self.server.lookup_component("machine")
|
||||||
|
await machine_cmp.wait_for_init(5.)
|
||||||
cur_time = event_loop.get_loop_time()
|
cur_time = event_loop.get_loop_time()
|
||||||
endtime = cur_time + 120.
|
endtime = cur_time + 120.
|
||||||
query_devs = inital_devs
|
query_devs = inital_devs
|
||||||
|
@ -224,7 +228,7 @@ class PrinterPower:
|
||||||
await ret
|
await ret
|
||||||
dev_info = device.get_device_info()
|
dev_info = device.get_device_info()
|
||||||
self.server.send_event("power:power_changed", dev_info)
|
self.server.send_event("power:power_changed", dev_info)
|
||||||
device.run_power_changed_action()
|
await device.run_power_changed_action()
|
||||||
elif req != "status":
|
elif req != "status":
|
||||||
raise self.server.error(f"Unsupported power request: {req}")
|
raise self.server.error(f"Unsupported power request: {req}")
|
||||||
return dev_info['status']
|
return dev_info['status']
|
||||||
|
@ -283,6 +287,25 @@ class PowerDevice:
|
||||||
self.restart_delay = config.getfloat('restart_delay', 1.)
|
self.restart_delay = config.getfloat('restart_delay', 1.)
|
||||||
if self.restart_delay < .000001:
|
if self.restart_delay < .000001:
|
||||||
raise config.error("Option 'restart_delay' must be above 0.0")
|
raise config.error("Option 'restart_delay' must be above 0.0")
|
||||||
|
self.bound_service: Optional[str] = config.get('bound_service', None)
|
||||||
|
self.need_scheduled_restart = False
|
||||||
|
|
||||||
|
def _is_bound_to_klipper(self):
|
||||||
|
return (
|
||||||
|
self.bound_service is not None and
|
||||||
|
self.bound_service.startswith("klipper") and
|
||||||
|
not self.bound_service.startswith("klipper_mcu")
|
||||||
|
)
|
||||||
|
|
||||||
|
def _schedule_firmware_restart(self, state: str = "") -> None:
|
||||||
|
if not self.need_scheduled_restart:
|
||||||
|
return
|
||||||
|
self.need_scheduled_restart = False
|
||||||
|
event_loop = self.server.get_event_loop()
|
||||||
|
kapis: APIComp = self.server.lookup_component("klippy_apis")
|
||||||
|
event_loop.delay_callback(
|
||||||
|
self.restart_delay, kapis.do_restart,
|
||||||
|
"FIRMWARE_RESTART")
|
||||||
|
|
||||||
def get_name(self) -> str:
|
def get_name(self) -> str:
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -301,19 +324,42 @@ class PowerDevice:
|
||||||
def get_locked_while_printing(self) -> bool:
|
def get_locked_while_printing(self) -> bool:
|
||||||
return self.locked_while_printing
|
return self.locked_while_printing
|
||||||
|
|
||||||
def run_power_changed_action(self) -> None:
|
async def run_power_changed_action(self) -> None:
|
||||||
|
if self.bound_service is not None:
|
||||||
|
machine_cmp: Machine = self.server.lookup_component("machine")
|
||||||
|
action = "start" if self.state == "on" else "stop"
|
||||||
|
await machine_cmp.do_service_action(action, self.bound_service)
|
||||||
if self.state == "on" and self.klipper_restart:
|
if self.state == "on" and self.klipper_restart:
|
||||||
event_loop = self.server.get_event_loop()
|
self.need_scheduled_restart = True
|
||||||
kapis: APIComp = self.server.lookup_component("klippy_apis")
|
if self._is_bound_to_klipper():
|
||||||
event_loop.delay_callback(
|
return
|
||||||
self.restart_delay, kapis.do_restart,
|
self._schedule_firmware_restart()
|
||||||
"FIRMWARE_RESTART")
|
|
||||||
|
|
||||||
def has_off_when_shutdown(self) -> bool:
|
def has_off_when_shutdown(self) -> bool:
|
||||||
return self.off_when_shutdown
|
return self.off_when_shutdown
|
||||||
|
|
||||||
def initialize(self) -> Optional[Coroutine]:
|
def initialize(self) -> Optional[Coroutine]:
|
||||||
raise NotImplementedError
|
if self.bound_service is None:
|
||||||
|
return None
|
||||||
|
if self.bound_service.startswith("moonraker"):
|
||||||
|
raise self.server.error(
|
||||||
|
f"Cannot bind to '{self.bound_service}' "
|
||||||
|
"service")
|
||||||
|
machine_cmp: Machine = self.server.lookup_component("machine")
|
||||||
|
sys_info = machine_cmp.get_system_info()
|
||||||
|
avail_svcs: List[str] = sys_info.get('available_services', [])
|
||||||
|
if self.bound_service not in avail_svcs:
|
||||||
|
raise self.server.error(
|
||||||
|
f"Bound Service {self.bound_service} is not available")
|
||||||
|
if self._is_bound_to_klipper() and self.klipper_restart:
|
||||||
|
# Schedule the Firmware Restart after Klipper reconnects
|
||||||
|
logging.info(f"Power Device '{self.name}' bound to "
|
||||||
|
f"klipper service '{self.bound_service}'")
|
||||||
|
self.server.register_event_handler(
|
||||||
|
"server:klippy_started",
|
||||||
|
self._schedule_firmware_restart
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
def refresh_status(self) -> Optional[Coroutine]:
|
def refresh_status(self) -> Optional[Coroutine]:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -342,6 +388,7 @@ class HTTPDevice(PowerDevice):
|
||||||
self.protocol = config.get("protocol", default_protocol)
|
self.protocol = config.get("protocol", default_protocol)
|
||||||
|
|
||||||
async def initialize(self) -> None:
|
async def initialize(self) -> None:
|
||||||
|
super().initialize()
|
||||||
await self.refresh_status()
|
await self.refresh_status()
|
||||||
|
|
||||||
async def _send_http_command(self,
|
async def _send_http_command(self,
|
||||||
|
@ -460,6 +507,7 @@ class GpioDevice(PowerDevice):
|
||||||
return pin_id, chip_id, invert
|
return pin_id, chip_id, invert
|
||||||
|
|
||||||
def initialize(self) -> None:
|
def initialize(self) -> None:
|
||||||
|
super().initialize()
|
||||||
self.set_power("on" if self.initial_state else "off")
|
self.set_power("on" if self.initial_state else "off")
|
||||||
|
|
||||||
def refresh_status(self) -> None:
|
def refresh_status(self) -> None:
|
||||||
|
@ -505,6 +553,7 @@ class RFDevice(GpioDevice):
|
||||||
self.off = config.get("off_code").zfill(24)
|
self.off = config.get("off_code").zfill(24)
|
||||||
|
|
||||||
def initialize(self) -> None:
|
def initialize(self) -> None:
|
||||||
|
super().initialize()
|
||||||
self.set_power("on" if self.initial_state else "off")
|
self.set_power("on" if self.initial_state else "off")
|
||||||
|
|
||||||
def _transmit_digit(self, waveform) -> None:
|
def _transmit_digit(self, waveform) -> None:
|
||||||
|
@ -623,6 +672,7 @@ class TPLinkSmartPlug(PowerDevice):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
async def initialize(self) -> None:
|
async def initialize(self) -> None:
|
||||||
|
super().initialize()
|
||||||
await self.refresh_status()
|
await self.refresh_status()
|
||||||
|
|
||||||
async def refresh_status(self) -> None:
|
async def refresh_status(self) -> None:
|
||||||
|
|
Loading…
Reference in New Issue