from components.aheater import AHeater from components.actor.hendiCtrl import HendiCtrl class HeaterHendi(AHeater): def __init__(self, params): AHeater.__init__(self, simulated=False) self.hendi = HendiCtrl(params['port'], params['speed']) self.power_set = 0 self.power_eff = 0 def get_power_min(self): return 0 def get_power_max(self): caps = self.hendi.getCapabilties() return caps['pwr_watts_max'] def get_powers(self): caps = self.hendi.getCapabilties() return [0] + caps['pwr_list'] def connect(self): ok = self.hendi.connect() self.connected = ok return ok def disconnect(self): self.hendi.disconnect() self.connected = False def activate(self, enable): if not self.connected: return try: if enable: self.hendi.remoteEnable(1) else: self.hendi.setSwitch(0) except Exception as e: # A device that was connected can still fail a live command (the # hendi's own idle-timeout auto-suspend, a cable pulled mid-run, # ...) - treat that the same as a disconnect rather than letting # it escape uncaught, since this is called both from HeaterTask's # tick loop (with self.device.open(): activate(True)/(False)) and # from a client's Connect/Disconnect command, neither of which # expect activate() itself to ever raise. self.log.error(f"comm error in activate({enable}): {e}") self.disconnect() def is_activated(self): if not self.connected: return False try: s = self.hendi.isRemoteEnable() return '1' in s except Exception as e: self.log.error(f"comm error in is_activated: {e}") self.disconnect() return False def process(self): if not self.connected: self.power_eff = 0 return try: power = self.power_set if power == 0: self.hendi.setSwitch(0) else: self.hendi.setSwitch(1) self.hendi.setPowerWatts(power) self.power_eff = self.hendi.getPowerWatts() if power > 0 else 0 except Exception as e: self.log.error(f"comm error in process: {e}") self.disconnect() self.power_eff = 0 def set_power(self, power): self.power_set = min(self.get_power_max(), power) def get_power(self): return self.power_eff def close(self): self.disconnect()