diff --git a/README.md b/README.md index 8220c03..7812630 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ Filter Cycle 2 Begins | Time | ✓ | N/A Filter Cycle 2 Runs | Time | ✓ | N/A Filter Cycle 2 Status | Binary sensor | ✓ | Begins, Runs, Ends Heat Mode | Switch | ✓ | Ready, Rest, Ready in Rest +Hold Mode | Switch | ✓ | Remaining Time Last Known Fault | Sensor | ✓ | N/A Light 1 | Light | ✓ | False, True Light 2 | Light | ? | False, True @@ -75,6 +76,7 @@ Pump 4 | Switch | ? | Off, Low, High Pump 5 | Switch | ? | Off, Low, High Pump 6 | Switch | ? | Off, Low, High Spa Thermostat | Climate | ✓ | N/A +Standby Mode | Switch | ✓ | N/A Temperature Range | Switch | ✓ | Low, High Option | Tested diff --git a/custom_components/spaclient/const.py b/custom_components/spaclient/const.py index f3129c2..fbecb4d 100644 --- a/custom_components/spaclient/const.py +++ b/custom_components/spaclient/const.py @@ -45,17 +45,19 @@ "Auxiliary 1": "mdi:numeric-1-circle-outline", "Auxiliary 2": "mdi:numeric-2-circle-outline", "Blower": "mdi:weather-windy", - "Circulation Pump": "mdi:fan", + "Circulation Pump": "mdi:pump", "Fault Log": "mdi:archive-alert", "Filter Cycle": "mdi:sync", - "Heat Mode": "mdi:alpha-r", + "Heat Mode": "mdi:alpha-r-box-outline", + "Hold Mode": "mdi:car-brake-hold", "Mister": "mdi:auto-fix", - "Pump 1": "mdi:fan", - "Pump 2": "mdi:fan", - "Pump 3": "mdi:fan", - "Pump 4": "mdi:fan", - "Pump 5": "mdi:fan", - "Pump 6": "mdi:fan", + "Pump 1": "mdi:pump", + "Pump 2": "mdi:pump", + "Pump 3": "mdi:pump", + "Pump 4": "mdi:pump", + "Pump 5": "mdi:pump", + "Pump 6": "mdi:pump", "Spa Thermostat": "mdi:hot-tub", + "Standby Mode": "mdi:ungroup", "Temperature Range": "mdi:thermometer-lines", } diff --git a/custom_components/spaclient/light.py b/custom_components/spaclient/light.py index 756c539..90cdaab 100644 --- a/custom_components/spaclient/light.py +++ b/custom_components/spaclient/light.py @@ -55,17 +55,14 @@ def supported_color_modes(self): @property def is_on(self): """Return true if light is on.""" - #_LOGGER.info("Update Light %s state", self._light_num) return self._spaclient.get_light(self._light_num) async def async_turn_on(self, **kwargs): """Instruct the light to turn on.""" - #_LOGGER.info("Turning On Light %s", self._light_num) self._spaclient.set_light(self._light_num, True) async def async_turn_off(self, **kwargs): """Instruct the light to turn off.""" - #_LOGGER.info("Turning Off Light %s", self._light_num) self._spaclient.set_light(self._light_num, False) @property diff --git a/custom_components/spaclient/manifest.json b/custom_components/spaclient/manifest.json index 72567dc..9970cc3 100644 --- a/custom_components/spaclient/manifest.json +++ b/custom_components/spaclient/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://github.com/plmilord/Hass.io-custom-component-spaclient", "iot_class": "local_push", "issue_tracker": "https://github.com/plmilord/Hass.io-custom-component-spaclient/issues", - "version": "3.1" + "version": "3.2" } \ No newline at end of file diff --git a/custom_components/spaclient/spaclient.py b/custom_components/spaclient/spaclient.py index 7a333ac..a65e6d8 100644 --- a/custom_components/spaclient/spaclient.py +++ b/custom_components/spaclient/spaclient.py @@ -22,12 +22,13 @@ def __init__(self, host_ip): self.status_chunk_array = [] """ Status update variables """ - self.hold_mode = False - self.priming = False + self.hold_mode = 0 + self.priming = 0 self.current_temp = None self.hour = 0 self.minute = 0 self.heat_mode = "Rest" + self.hold_mode_remain_time = 0 self.temp_scale = "Fahrenheit" self.filter_mode = False self.time_scale = "24 Hr" @@ -47,6 +48,7 @@ def __init__(self, host_ip): self.aux1 = "Off" self.aux2 = "Off" self.set_temp = 0 + self.standby_mode = 0 """ Information variables """ self.info_model_name = "Unknown" @@ -521,9 +523,9 @@ def parse_status_update(self, byte_array): CS: Checksum (CRC-8 with 0x02 initial value, and 0x02 final XOR) ME: Message End (always 0x7e "~") - 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 - MS ML MT MT MT F0 F1 CT HH MM F2 06 TA TB F3 F4 P1 P2 F5 LF F6 16 17 18 CU ST AB 22 23 M8 25 26 CS ME - 7E 20 FF AF 13 7E + 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + MS ML MT MT MT F0 F1 CT HH MM F2 06 TA TB F3 F4 P1 P2 F5 LF F6 16 17 18 CU ST AB 22 23 M8 CS ME + 7E 20 FF AF 13 7E F0: 0x00 = Running 0x01 = Initializing @@ -572,43 +574,39 @@ def parse_status_update(self, byte_array): AB: 0x02 = Sensor A/B Temperatures (0 = No, 1 = Yes) 0x04 = Timeouts (0 = Normal, 1 = 8h) 0x08 = Settings Locked / Test Mode: Temp Limits (0 = No, 1 = Yes) - 22: ? - 23: ? + 22: Mode of operation (0x00 = Normal Mode, 0x01 = Pump Test Mode, 0x40 = Hold Mode) + 23: Saving states when switching between modes... For internal use in the BP controller M8: M8 Cycle Time (0 = OFF, 30, 60, 90, or 120 (in minutes)) - 25: ? - 26: ? """ - self.hold_mode = byte_array[0] & 0x05 == 1 - self.priming = byte_array[1] & 0x01 == 1 + self.hold_mode = 1 if byte_array[0] == 0x05 else 0 + self.priming = 1 if byte_array[1] == 0x01 else 0 self.current_temp = byte_array[2] if (byte_array[2] != 255) else None self.hour = byte_array[3] self.minute = byte_array[4] self.heat_mode = ("Ready", "Rest", "Ready in Rest")[byte_array[5]] - flag3 = byte_array[9] - self.temp_scale = "Fahrenheit" if (flag3 & 0x01 == 0) else "Celsius" - self.time_scale = "12 Hr" if (flag3 & 0x02 == 0) else "24 Hr" - self.filter_mode = (flag3 & 0x0c) >> 2 - flag4 = byte_array[10] - self.heating = (flag4 & 0x30) >> 4 - self.temp_range = "Low" if (flag4 & 0x04) >> 2 == 0 else "High" + self.hold_mode_remain_time = byte_array[7] if self.hold_mode else 0 + self.temp_scale = "Fahrenheit" if (byte_array[9] & 0x01 == 0) else "Celsius" + self.time_scale = "12 Hr" if (byte_array[9] & 0x02 == 0) else "24 Hr" + self.filter_mode = (byte_array[9] & 0x0c) >> 2 + self.heating = (byte_array[10] & 0x30) >> 4 + self.temp_range = "Low" if (byte_array[10] & 0x04) >> 2 == 0 else "High" self.pump1 = ("Off", "Low", "High")[byte_array[11] & 0x03] self.pump2 = ("Off", "Low", "High")[byte_array[11] >> 2 & 0x03] self.pump3 = ("Off", "Low", "High")[byte_array[11] >> 4 & 0x03] self.pump4 = ("Off", "Low", "High")[byte_array[11] >> 6 & 0x03] self.pump5 = ("Off", "Low", "High")[byte_array[12] & 0x03] self.pump6 = ("Off", "Low", "High")[byte_array[12] >> 6 & 0x03] - flag5 = byte_array[13] - self.circ_pump = flag5 & 0x02 - self.blower = "Off" if (flag5 & 0x0c) >> 2 == 0 else "On" + self.circ_pump = byte_array[13] & 0x02 + self.blower = "Off" if (byte_array[13] & 0x0c) >> 2 == 0 else "On" self.light1 = byte_array[14] & 0x03 == 0x03 self.light2 = byte_array[14] >> 6 & 0x03 == 0x03 - flag6 = byte_array[15] - self.mister = "Off" if (flag6 & 0x01) == 0 else "On" - self.aux1 = flag6 & 0x08 - self.aux2 = flag6 & 0x10 + self.mister = "Off" if (byte_array[15] & 0x01) == 0 else "On" + self.aux1 = byte_array[15] & 0x08 + self.aux2 = byte_array[15] & 0x10 self.set_temp = byte_array[20] + self.standby_mode = 1 if (byte_array[22] & 0x01) == 1 else 0 def get_aux(self, aux_num): @@ -720,6 +718,14 @@ def get_high_range_max(self): def get_high_range_min(self): return self.add_info_high_range_min + def get_hold_mode(self): + return self.hold_mode + + def get_hold_mode_remain_time(self): + hours = self.hold_mode_remain_time // 60 + minutes = self.hold_mode_remain_time % 60 + return "%02d:%02d" % (hours, minutes) + def get_light(self, light_num): if light_num == 1: return self.get_light1() @@ -794,6 +800,9 @@ def get_set_temp(self): def get_ssid(self): return self.info_ssid + def get_standby_mode(self): + return self.standby_mode + def get_temp_range(self): return self.temp_range @@ -892,6 +901,12 @@ def set_blower(self, value): self.send_toggle_message(0x0c) self.blower = value + def set_clear_notification(self, value): + if self.clear_notification == value: + return + self.send_toggle_message(0x03) + self.clear_notification = value + async def set_current_time(self): now = dt_util.utcnow() now = dt_util.as_local(now) @@ -954,6 +969,12 @@ def set_mister(self, value): self.send_toggle_message(0x0e) self.mister = value + def set_normal_operation(self, value): + if self.normal_operation == value: + return + self.send_toggle_message(0x01) + self.normal_operation = value + def set_pump(self, pump_num, value): pump_val = self.pump1 pump_code = 0x04 @@ -988,6 +1009,9 @@ def set_pump(self, pump_num, value): if pump_num == 6: self.pump6 = value + def set_standby_mode(self): + self.send_toggle_message(0x1d) + def set_temp_range(self, value): if self.temp_range == value: return @@ -1007,65 +1031,67 @@ def print_variables(self): _LOGGER.info("<< socket variables >>") _LOGGER.info("======================") _LOGGER.info("self.socket_is_connected = %s", self.socket_is_connected) - _LOGGER.info("self.socket_l = %s", self.socket_l) - _LOGGER.info("self.socket_s = %s", self.socket_s) + _LOGGER.info("self.socket_l = %s", self.socket_l) + _LOGGER.info("self.socket_s = %s", self.socket_s) _LOGGER.info("self.socket_host_ip = %s", self.socket_host_ip) _LOGGER.info("") _LOGGER.info("=============================") _LOGGER.info("<< Status update variables >>") _LOGGER.info("=============================") - _LOGGER.info("self.hold_mode = %s", self.hold_mode) - _LOGGER.info("self.priming = %s", self.priming) + _LOGGER.info("self.hold_mode= %s", self.hold_mode) + _LOGGER.info("self.priming = %s", self.priming) _LOGGER.info("self.current_temp = %s", self.current_temp) - _LOGGER.info("self.hour = %s", self.hour) - _LOGGER.info("self.minute = %s", self.minute) - _LOGGER.info("self.heat_mode = %s", self.heat_mode) - _LOGGER.info("self.temp_scale = %s", self.temp_scale) - _LOGGER.info("self.filter_mode = %s", self.filter_mode) - _LOGGER.info("self.time_scale = %s", self.time_scale) - _LOGGER.info("self.heating = %s", self.heating) - _LOGGER.info("self.temp_range = %s", self.temp_range) - _LOGGER.info("self.pump1 = %s", self.pump1) - _LOGGER.info("self.pump2 = %s", self.pump2) - _LOGGER.info("self.pump3 = %s", self.pump3) - _LOGGER.info("self.pump4 = %s", self.pump4) - _LOGGER.info("self.pump5 = %s", self.pump5) - _LOGGER.info("self.pump6 = %s", self.pump6) - _LOGGER.info("self.circ_pump = %s", self.circ_pump) - _LOGGER.info("self.blower = %s", self.blower) - _LOGGER.info("self.light1 = %s", self.light1) - _LOGGER.info("self.light2 = %s", self.light2) - _LOGGER.info("self.mister = %s", self.mister) - _LOGGER.info("self.aux1 = %s", self.aux1) - _LOGGER.info("self.aux2 = %s", self.aux2) - _LOGGER.info("self.set_temp = %s", self.set_temp) + _LOGGER.info("self.hour = %s", self.hour) + _LOGGER.info("self.minute = %s", self.minute) + _LOGGER.info("self.heat_mode = %s", self.heat_mode) + _LOGGER.info("self.hold_mode_remain_time = %s", self.hold_mode_remain_time) + _LOGGER.info("self.temp_scale = %s", self.temp_scale) + _LOGGER.info("self.filter_mode = %s", self.filter_mode) + _LOGGER.info("self.time_scale = %s", self.time_scale) + _LOGGER.info("self.heating = %s", self.heating) + _LOGGER.info("self.temp_range = %s", self.temp_range) + _LOGGER.info("self.pump1 = %s", self.pump1) + _LOGGER.info("self.pump2 = %s", self.pump2) + _LOGGER.info("self.pump3 = %s", self.pump3) + _LOGGER.info("self.pump4 = %s", self.pump4) + _LOGGER.info("self.pump5 = %s", self.pump5) + _LOGGER.info("self.pump6 = %s", self.pump6) + _LOGGER.info("self.circ_pump = %s", self.circ_pump) + _LOGGER.info("self.blower = %s", self.blower) + _LOGGER.info("self.light1 = %s", self.light1) + _LOGGER.info("self.light2 = %s", self.light2) + _LOGGER.info("self.mister = %s", self.mister) + _LOGGER.info("self.aux1 = %s", self.aux1) + _LOGGER.info("self.aux2 = %s", self.aux2) + _LOGGER.info("self.set_temp = %s", self.set_temp) + _LOGGER.info("self.standby_mode = %s", self.standby_mode) _LOGGER.info("") _LOGGER.info("===========================") _LOGGER.info("<< Information variables >>") _LOGGER.info("===========================") _LOGGER.info("self.information_loaded = %s", self.information_loaded) - _LOGGER.info("self.info_model_name = %s", self.info_model_name) - _LOGGER.info("self.info_cfg_sig = %s", self.info_cfg_sig) - _LOGGER.info("self.info_sw_vers = %s", self.info_sw_vers) - _LOGGER.info("self.info_setup = %s", self.info_setup) - _LOGGER.info("self.info_ssid = %s", self.info_ssid) + _LOGGER.info("self.info_model_name = %s", self.info_model_name) + _LOGGER.info("self.info_cfg_sig = %s", self.info_cfg_sig) + _LOGGER.info("self.info_sw_vers = %s", self.info_sw_vers) + _LOGGER.info("self.info_setup = %s", self.info_setup) + _LOGGER.info("self.info_ssid = %s", self.info_ssid) _LOGGER.info("self.info_heater_voltage = %s", self.info_heater_voltage) - _LOGGER.info("self.info_heater_type = %s", self.info_heater_type) - _LOGGER.info("self.info_dip_switch = %s", self.info_dip_switch) + _LOGGER.info("self.info_heater_type = %s", self.info_heater_type) + _LOGGER.info("self.info_dip_switch = %s", self.info_dip_switch) _LOGGER.info("") _LOGGER.info("=============================") _LOGGER.info("<< Configuration variables >>") _LOGGER.info("=============================") _LOGGER.info("self.configuration_loaded = %s", self.configuration_loaded) - _LOGGER.info("self.cfg_pump_array = %s", self.cfg_pump_array) - _LOGGER.info("self.cfg_light_array = %s", self.cfg_light_array) + _LOGGER.info("self.cfg_pump_array = %s", self.cfg_pump_array) + _LOGGER.info("self.cfg_light_array = %s", self.cfg_light_array) _LOGGER.info("self.cfg_circ_pump_array = %s", self.cfg_circ_pump_array) - _LOGGER.info("self.cfg_blower_array = %s", self.cfg_blower_array) - _LOGGER.info("self.cfg_mister_array = %s", self.cfg_mister_array) - _LOGGER.info("self.cfg_aux_array = %s", self.cfg_aux_array) + _LOGGER.info("self.cfg_blower_array = %s", self.cfg_blower_array) + _LOGGER.info("self.cfg_mister_array = %s", self.cfg_mister_array) + _LOGGER.info("self.cfg_aux_array = %s", self.cfg_aux_array) _LOGGER.info("") _LOGGER.info("=====================================") @@ -1081,38 +1107,38 @@ def print_variables(self): _LOGGER.info("<< Filter cycles variables >>") _LOGGER.info("=============================") _LOGGER.info("self.filter_cycles_loaded = %s", self.filter_cycles_loaded) - _LOGGER.info("self.filter_1_begins_hour = %s", self.filter_1_begins_hour) + _LOGGER.info("self.filter_1_begins_hour = %s", self.filter_1_begins_hour) _LOGGER.info("self.filter_1_begins_minute = %s", self.filter_1_begins_minute) - _LOGGER.info("self.filter_1_runs_hour = %s", self.filter_1_runs_hour) - _LOGGER.info("self.filter_1_runs_minute = %s", self.filter_1_runs_minute) - _LOGGER.info("self.filter_2_enabled = %s", self.filter_2_enabled) - _LOGGER.info("self.filter_2_begins_hour = %s", self.filter_2_begins_hour) + _LOGGER.info("self.filter_1_runs_hour = %s", self.filter_1_runs_hour) + _LOGGER.info("self.filter_1_runs_minute = %s", self.filter_1_runs_minute) + _LOGGER.info("self.filter_2_enabled = %s", self.filter_2_enabled) + _LOGGER.info("self.filter_2_begins_hour = %s", self.filter_2_begins_hour) _LOGGER.info("self.filter_2_begins_minute = %s", self.filter_2_begins_minute) - _LOGGER.info("self.filter_2_runs_hour = %s", self.filter_2_runs_hour) - _LOGGER.info("self.filter_2_runs_minute = %s", self.filter_2_runs_minute) + _LOGGER.info("self.filter_2_runs_hour = %s", self.filter_2_runs_hour) + _LOGGER.info("self.filter_2_runs_minute = %s", self.filter_2_runs_minute) _LOGGER.info("") _LOGGER.info("======================================") _LOGGER.info("<< Additional information variables >>") _LOGGER.info("======================================") _LOGGER.info("self.additional_information_loaded = %s", self.additional_information_loaded) - _LOGGER.info("self.add_info_low_range_min = %s", self.add_info_low_range_min) - _LOGGER.info("self.add_info_low_range_max = %s", self.add_info_low_range_max) + _LOGGER.info("self.add_info_low_range_min = %s", self.add_info_low_range_min) + _LOGGER.info("self.add_info_low_range_max = %s", self.add_info_low_range_max) _LOGGER.info("self.add_info_high_range_min = %s", self.add_info_high_range_min) _LOGGER.info("self.add_info_high_range_max = %s", self.add_info_high_range_max) - _LOGGER.info("self.add_info_nb_of_pumps = %s", self.add_info_nb_of_pumps) + _LOGGER.info("self.add_info_nb_of_pumps = %s", self.add_info_nb_of_pumps) _LOGGER.info("") _LOGGER.info("===========================") _LOGGER.info("<< Preferences variables >>") _LOGGER.info("===========================") _LOGGER.info("self.preferences_loaded = %s", self.preferences_loaded) - _LOGGER.info("self.pref_reminder = %s", self.pref_reminder) - _LOGGER.info("self.pref_temp_scale = %s", self.pref_temp_scale) - _LOGGER.info("self.pref_clock_mode = %s", self.pref_clock_mode) - _LOGGER.info("self.pref_clean_up_cycle = %s", self.pref_clean_up_cycle) + _LOGGER.info("self.pref_reminder = %s", self.pref_reminder) + _LOGGER.info("self.pref_temp_scale = %s", self.pref_temp_scale) + _LOGGER.info("self.pref_clock_mode = %s", self.pref_clock_mode) + _LOGGER.info("self.pref_clean_up_cycle = %s", self.pref_clean_up_cycle) _LOGGER.info("self.pref_dolphin_address = %s", self.pref_dolphin_address) - _LOGGER.info("self.pref_m8_ai = %s", self.pref_m8_ai) + _LOGGER.info("self.pref_m8_ai = %s", self.pref_m8_ai) _LOGGER.info("") _LOGGER.info("=========================") @@ -1120,13 +1146,13 @@ def print_variables(self): _LOGGER.info("=========================") _LOGGER.info("self.fault_log_loaded = %s", self.fault_log_loaded) _LOGGER.info("self.fault_log_total_entries = %s", self.fault_log_total_entries) - _LOGGER.info("self.fault_log_entry_nb = %s", self.fault_log_entry_nb) - _LOGGER.info("self.fault_log_msg_code = %s", self.fault_log_msg_code) - _LOGGER.info("self.fault_log_days_ago = %s", self.fault_log_days_ago) - _LOGGER.info("self.fault_log_msg_hour = %s", self.fault_log_msg_hour) - _LOGGER.info("self.fault_log_msg_minute = %s", self.fault_log_msg_minute) - _LOGGER.info("self.fault_log_todo = %s", self.fault_log_todo) - _LOGGER.info("self.fault_log_set_temp = %s", self.fault_log_set_temp) + _LOGGER.info("self.fault_log_entry_nb = %s", self.fault_log_entry_nb) + _LOGGER.info("self.fault_log_msg_code = %s", self.fault_log_msg_code) + _LOGGER.info("self.fault_log_days_ago = %s", self.fault_log_days_ago) + _LOGGER.info("self.fault_log_msg_hour = %s", self.fault_log_msg_hour) + _LOGGER.info("self.fault_log_msg_minute = %s", self.fault_log_msg_minute) + _LOGGER.info("self.fault_log_todo = %s", self.fault_log_todo) + _LOGGER.info("self.fault_log_set_temp = %s", self.fault_log_set_temp) _LOGGER.info("self.fault_log_sensor_a_temp = %s", self.fault_log_sensor_a_temp) _LOGGER.info("self.fault_log_sensor_b_temp = %s", self.fault_log_sensor_b_temp) diff --git a/custom_components/spaclient/switch.py b/custom_components/spaclient/switch.py index cd76d43..f91956e 100644 --- a/custom_components/spaclient/switch.py +++ b/custom_components/spaclient/switch.py @@ -14,10 +14,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities): spaclient = hass.data[DOMAIN][config_entry.entry_id][SPA] entities = [] - pump_array = spaclient.get_pump_list() + aux_array = spaclient.get_aux_list() blower_array = spaclient.get_blower_list() mister_array = spaclient.get_mister_list() - aux_array = spaclient.get_aux_list() + pump_array = spaclient.get_pump_list() for i in range(0, 6): if pump_array[i] != 0: @@ -30,70 +30,52 @@ async def async_setup_entry(hass, config_entry, async_add_entities): if aux_array[i] != 0: entities.append(SpaAux(i + 1, spaclient, config_entry)) + entities.append(EnableFilterCycle2(spaclient, config_entry)) entities.append(HeatMode(spaclient, config_entry)) + entities.append(HoldMode(spaclient, config_entry)) + entities.append(StandbyMode(spaclient, config_entry)) entities.append(TempRange(spaclient, config_entry)) - entities.append(EnableFilterCycle2(spaclient, config_entry)) async_add_entities(entities, True) -class SpaPump(SpaClientDevice, SwitchEntity): - """Representation of a Pump switch.""" +class SpaAux(SpaClientDevice, SwitchEntity): + """Representation of an Auxiliary switch.""" - def __init__(self, pump_num, spaclient, config_entry): + def __init__(self, aux_num, spaclient, config_entry): """Initialise the device.""" super().__init__(spaclient, config_entry) self._spaclient = spaclient - self._pump_num = pump_num - self._icon = ICONS.get('Pump ' + str(self._pump_num)) + self._aux_num = aux_num + self._icon = ICONS.get('Auxiliary ' + str(self._aux_num)) @property def unique_id(self) -> str: """Return a unique ID.""" - return f"{self._spaclient.get_macaddr().replace(':', '')}#pump_{str(self._pump_num)}" + return f"{self._spaclient.get_macaddr().replace(':', '')}#auxiliary_{str(self._aux_num)}" @property def name(self): """Return the name of the device.""" - return 'Pump ' + str(self._pump_num) + return 'Auxiliary ' + str(self._aux_num) @property def icon(self): """Return the icon of the device.""" return self._icon - @property - def extra_state_attributes(self): - """Return the state attributes of the device.""" - attrs = {} - attrs['Pump ' + str(self._pump_num)] = self._spaclient.get_pump(self._pump_num) - return attrs - @property def is_on(self): """Get whether the switch is in on state.""" - return self._spaclient.get_pump(self._pump_num) != "Off" + return self._spaclient.get_aux(self._aux_num) != "Off" async def async_turn_on(self, **kwargs): """Send the on command.""" - #_LOGGER.info("Pump %s status %s", self._pump_num, self._spaclient.get_pump(self._pump_num)) - #_LOGGER.info("Turning On Pump %s", self._pump_num) - if self._spaclient.cfg_pump_array[self._pump_num - 1] == 1: - return self._spaclient.set_pump(self._pump_num, "High") - - self._spaclient.set_pump(self._pump_num, "Low") + self._spaclient.set_aux(self._aux_num, "On") async def async_turn_off(self, **kwargs): """Send the off command.""" - #_LOGGER.info("Pump %s status %s", self._pump_num, self._spaclient.get_pump(self._pump_num)) - #if self._spaclient.get_pump(self._pump_num) == "Low": - #_LOGGER.info("Set to High Pump %s", self._pump_num) - #if self._spaclient.get_pump(self._pump_num) == "High": - #_LOGGER.info("Turning Off Pump %s", self._pump_num) - if self._spaclient.get_pump(self._pump_num) == "Low": - return self._spaclient.set_pump(self._pump_num, "High") - - self._spaclient.set_pump(self._pump_num, "Off") + self._spaclient.set_aux(self._aux_num, "Off") @property def available(self) -> bool: @@ -140,12 +122,10 @@ def is_on(self): async def async_turn_on(self, **kwargs): """Send the on command.""" self._spaclient.set_blower("On") - #_LOGGER.info("Blower changed to %s", self._spaclient.get_blower()) async def async_turn_off(self, **kwargs): """Send the off command.""" self._spaclient.set_blower("Off") - #_LOGGER.info("Blower changed to %s", self._spaclient.get_blower()) @property def available(self) -> bool: @@ -184,12 +164,10 @@ def is_on(self): async def async_turn_on(self, **kwargs): """Send the on command.""" - #_LOGGER.info("Turning On Mister") self._spaclient.set_mister("On") async def async_turn_off(self, **kwargs): """Send the off command.""" - #_LOGGER.info("Turning Off Mister") self._spaclient.set_mister("Off") @property @@ -198,45 +176,99 @@ def available(self) -> bool: return self._spaclient.get_gateway_status() -class SpaAux(SpaClientDevice, SwitchEntity): - """Representation of an Auxiliary switch.""" +class SpaPump(SpaClientDevice, SwitchEntity): + """Representation of a Pump switch.""" - def __init__(self, aux_num, spaclient, config_entry): + def __init__(self, pump_num, spaclient, config_entry): """Initialise the device.""" super().__init__(spaclient, config_entry) self._spaclient = spaclient - self._aux_num = aux_num - self._icon = ICONS.get('Auxiliary ' + str(self._aux_num)) + self._pump_num = pump_num + self._icon = ICONS.get('Pump ' + str(self._pump_num)) @property def unique_id(self) -> str: """Return a unique ID.""" - return f"{self._spaclient.get_macaddr().replace(':', '')}#auxiliary_{str(self._aux_num)}" + return f"{self._spaclient.get_macaddr().replace(':', '')}#pump_{str(self._pump_num)}" @property def name(self): """Return the name of the device.""" - return 'Auxiliary ' + str(self._aux_num) + return 'Pump ' + str(self._pump_num) @property def icon(self): """Return the icon of the device.""" return self._icon + @property + def extra_state_attributes(self): + """Return the state attributes of the device.""" + attrs = {} + attrs['Pump ' + str(self._pump_num)] = self._spaclient.get_pump(self._pump_num) + return attrs + @property def is_on(self): """Get whether the switch is in on state.""" - return self._spaclient.get_aux(self._aux_num) != "Off" + return self._spaclient.get_pump(self._pump_num) != "Off" async def async_turn_on(self, **kwargs): """Send the on command.""" - #_LOGGER.info("Turning On Auxiliary %s", self._aux_num) - self._spaclient.set_aux(self._aux_num, "On") + if self._spaclient.cfg_pump_array[self._pump_num - 1] == 1: + return self._spaclient.set_pump(self._pump_num, "High") + + self._spaclient.set_pump(self._pump_num, "Low") async def async_turn_off(self, **kwargs): """Send the off command.""" - #_LOGGER.info("Turning Off Auxiliary %s", self._aux_num) - self._spaclient.set_aux(self._aux_num, "Off") + if self._spaclient.get_pump(self._pump_num) == "Low": + return self._spaclient.set_pump(self._pump_num, "High") + + self._spaclient.set_pump(self._pump_num, "Off") + + @property + def available(self) -> bool: + """Return True if entity is available.""" + return self._spaclient.get_gateway_status() + + +class EnableFilterCycle2(SpaClientDevice, SwitchEntity): + """Representation of a Temperature Range switch.""" + + def __init__(self, spaclient, config_entry): + """Initialise the switch.""" + super().__init__(spaclient, config_entry) + self._spaclient = spaclient + self._icon = ICONS.get('Filter Cycle') + + @property + def unique_id(self) -> str: + """Return a unique ID.""" + return f"{self._spaclient.get_macaddr().replace(':', '')}#enable_filter_cycle_2" + + @property + def name(self): + """Return the name of the device.""" + return 'Filter Cycle 2' + + @property + def icon(self): + """Return the icon of the device.""" + return self._icon + + @property + def is_on(self): + """Get whether the switch is in on state.""" + return self._spaclient.get_filter2_enabled() + + async def async_turn_on(self, **kwargs): + """Send the on command.""" + self._spaclient.set_filter2_enabled(1) + + async def async_turn_off(self, **kwargs): + """Send the off command.""" + self._spaclient.set_filter2_enabled(0) @property def available(self) -> bool: @@ -283,12 +315,10 @@ def is_on(self): async def async_turn_on(self, **kwargs): """Send the on command.""" self._spaclient.set_heat_mode("Ready") - #_LOGGER.info("Heat Mode changed to %s", self._spaclient.get_heat_mode()) async def async_turn_off(self, **kwargs): """Send the off command.""" self._spaclient.set_heat_mode("Rest") - #_LOGGER.info("Heat Mode changed to %s", self._spaclient.get_heat_mode()) @property def available(self) -> bool: @@ -296,24 +326,24 @@ def available(self) -> bool: return self._spaclient.get_gateway_status() -class TempRange(SpaClientDevice, SwitchEntity): - """Representation of a Temperature Range switch.""" +class HoldMode(SpaClientDevice, SwitchEntity): + """Representation of a Hold Mode switch.""" def __init__(self, spaclient, config_entry): """Initialise the switch.""" super().__init__(spaclient, config_entry) self._spaclient = spaclient - self._icon = ICONS.get('Temperature Range') + self._icon = ICONS.get('Hold Mode') @property def unique_id(self) -> str: """Return a unique ID.""" - return f"{self._spaclient.get_macaddr().replace(':', '')}#temperature_range" + return f"{self._spaclient.get_macaddr().replace(':', '')}#hold_mode" @property def name(self): """Return the name of the device.""" - return 'Temperature Range' + return 'Hold Mode' @property def icon(self): @@ -324,23 +354,21 @@ def icon(self): def extra_state_attributes(self): """Return the state attributes of the device.""" attrs = {} - attrs["Temperature Range"] = self._spaclient.get_temp_range() + attrs["Remaining Time"] = self._spaclient.get_hold_mode_remain_time() return attrs @property def is_on(self): """Get whether the switch is in on state.""" - return self._spaclient.get_temp_range() != "Low" + return self._spaclient.get_hold_mode() async def async_turn_on(self, **kwargs): """Send the on command.""" - self._spaclient.set_temp_range("High") - #_LOGGER.info("Temperature Range changed to %s", self._spaclient.get_temp_range()) + self._spaclient.set_hold_mode(1) async def async_turn_off(self, **kwargs): """Send the off command.""" - self._spaclient.set_temp_range("Low") - #_LOGGER.info("Temperature Range changed to %s", self._spaclient.get_temp_range()) + self._spaclient.set_hold_mode(0) @property def available(self) -> bool: @@ -348,44 +376,92 @@ def available(self) -> bool: return self._spaclient.get_gateway_status() -class EnableFilterCycle2(SpaClientDevice, SwitchEntity): +class StandbyMode(SpaClientDevice, SwitchEntity): + """Representation of a Standby Mode switch.""" + + def __init__(self, spaclient, config_entry): + """Initialise the switch.""" + super().__init__(spaclient, config_entry) + self._spaclient = spaclient + self._icon = ICONS.get('Standby Mode') + + @property + def unique_id(self) -> str: + """Return a unique ID.""" + return f"{self._spaclient.get_macaddr().replace(':', '')}#standby_mode" + + @property + def name(self): + """Return the name of the device.""" + return 'Standby Mode' + + @property + def icon(self): + """Return the icon of the device.""" + return self._icon + + @property + def is_on(self): + """Get whether the switch is in on state.""" + return self._spaclient.get_standby_mode() + + async def async_turn_on(self, **kwargs): + """Send the on command.""" + self._spaclient.set_standby_mode() + + async def async_turn_off(self, **kwargs): + """Send the off command.""" + self._spaclient.set_standby_mode() + + @property + def available(self) -> bool: + """Return True if entity is available.""" + return self._spaclient.get_gateway_status() + + +class TempRange(SpaClientDevice, SwitchEntity): """Representation of a Temperature Range switch.""" def __init__(self, spaclient, config_entry): """Initialise the switch.""" super().__init__(spaclient, config_entry) self._spaclient = spaclient - self._icon = ICONS.get('Filter Cycle') + self._icon = ICONS.get('Temperature Range') @property def unique_id(self) -> str: """Return a unique ID.""" - return f"{self._spaclient.get_macaddr().replace(':', '')}#enable_filter_cycle_2" + return f"{self._spaclient.get_macaddr().replace(':', '')}#temperature_range" @property def name(self): """Return the name of the device.""" - return 'Filter Cycle 2' + return 'Temperature Range' @property def icon(self): """Return the icon of the device.""" return self._icon + @property + def extra_state_attributes(self): + """Return the state attributes of the device.""" + attrs = {} + attrs["Temperature Range"] = self._spaclient.get_temp_range() + return attrs + @property def is_on(self): """Get whether the switch is in on state.""" - return self._spaclient.get_filter2_enabled() + return self._spaclient.get_temp_range() != "Low" async def async_turn_on(self, **kwargs): """Send the on command.""" - #_LOGGER.info("Turning On Filter Cycle 2") - self._spaclient.set_filter2_enabled(1) + self._spaclient.set_temp_range("High") async def async_turn_off(self, **kwargs): """Send the off command.""" - #_LOGGER.info("Turning Off Filter Cycle 2") - self._spaclient.set_filter2_enabled(0) + self._spaclient.set_temp_range("Low") @property def available(self) -> bool: diff --git a/images/preview.png b/images/preview.png index b562c44..8c74454 100644 Binary files a/images/preview.png and b/images/preview.png differ