diff --git a/pychonet/CeilingFan.py b/pychonet/CeilingFan.py index 0de7edd..9c5cd11 100644 --- a/pychonet/CeilingFan.py +++ b/pychonet/CeilingFan.py @@ -1,4 +1,7 @@ +from deprecated import deprecated from pychonet.EchonetInstance import EchonetInstance +from pychonet.lib.epc_functions import DICT_30_TRUE_FALSE +from pychonet.lib.epc_functions import _int, _swap_dict ENL_FANSPEED_PERCENT = 0xF0 ENL_FAN_DIRECTION = 0xF1 @@ -6,15 +9,12 @@ ENL_BUZZER = 0xFC ENL_FAN_POWER = 0x80 -FAN_DIRECTION = { - "forward": 0x41, - "reverse": 0x42 -} +DICT_FAN_DIRECTION = {0x41: "forward", 0x42: "reverse"} + +FAN_DIRECTION = _swap_dict(DICT_FAN_DIRECTION) + +FAN_OSCILLATION = _swap_dict(DICT_30_TRUE_FALSE) -FAN_OSCILLATION = { - True: 0x30, - False: 0x31 -} # ----- Ceiling Fan Class ------- # Fan speed in percentage @@ -23,32 +23,34 @@ def _013AF0(edt): fan_speed_percentage = int((op_mode - 0x30) * 0x0A) return fan_speed_percentage + # Fan Direction +@deprecated(reason="Scheduled for removal.") def _013AF1(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "forward", 0x42: "reverse"} - return values.get(op_mode, "invalid_setting") + return _int(edt, DICT_FAN_DIRECTION) + # Fan Fluctuation +@deprecated(reason="Scheduled for removal.") def _013AF2(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x30: True, 0x31: False} - return values.get(op_mode, "invalid_setting") + return _int(edt, DICT_30_TRUE_FALSE) + # Fan Buzzer +@deprecated(reason="Scheduled for removal.") def _013AFC(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x30: True, 0x31: False} - return values.get(op_mode, "invalid_setting") + return _int(edt, DICT_30_TRUE_FALSE) + """Class for Celing Fan Objects""" -class CeilingFan(EchonetInstance): + +class CeilingFan(EchonetInstance): EPC_FUNCTIONS = { 0xF0: _013AF0, - 0xF1: _013AF1, - 0xF2: _013AF2, - 0xFC: _013AFC + 0xF1: [_int, DICT_FAN_DIRECTION], + 0xF2: [_int, DICT_30_TRUE_FALSE], + 0xFC: [_int, DICT_30_TRUE_FALSE], } def __init__(self, host, api_connector=None, instance=0x1): @@ -64,12 +66,16 @@ def __init__(self, host, api_connector=None, instance=0x1): param fans_speed: An int representing the fan speed. """ - def setFanSpeedPercent(self, fan_speed_percent): - return self.setMessages( + async def setFanSpeedPercent(self, fan_speed_percent): + return await self.setMessages( [ - {"EPC":ENL_FAN_POWER, "PDC": 0x01, "EDT": 0x30}, - {"EPC":ENL_BUZZER, "PDC": 0x01, "EDT": 0x30}, - {"EPC":ENL_FANSPEED_PERCENT, "PDC": 0x01, "EDT": round(fan_speed_percent/10) + 0x30} + {"EPC": ENL_FAN_POWER, "PDC": 0x01, "EDT": 0x30}, + {"EPC": ENL_BUZZER, "PDC": 0x01, "EDT": 0x30}, + { + "EPC": ENL_FANSPEED_PERCENT, + "PDC": 0x01, + "EDT": round(fan_speed_percent / 10) + 0x30, + }, ] ) @@ -80,8 +86,8 @@ def setFanSpeedPercent(self, fan_speed_percent): return: A string representing the fan speed """ - def getFanSpeedPercent(self): # 0xF0 - return self.getMessage(ENL_FANSPEED_PERCENT) + async def getFanSpeedPercent(self): # 0xF0 + return await self.getMessage(ENL_FANSPEED_PERCENT) """ setFanDirection set the fan direction @@ -90,12 +96,16 @@ def getFanSpeedPercent(self): # 0xF0 e.g: 'forward', 'reverse'. """ - def setFanDirection(self, fan_direction): - return self.setMessages( + async def setFanDirection(self, fan_direction): + return await self.setMessages( [ - {"EPC":ENL_FAN_POWER, "PDC": 0x01, "EDT": 0x30}, - {"EPC":ENL_BUZZER, "PDC": 0x01, "EDT": 0x30}, - {"EPC":ENL_FAN_DIRECTION, "PDC": 0x01, "EDT": FAN_DIRECTION[fan_direction]} + {"EPC": ENL_FAN_POWER, "PDC": 0x01, "EDT": 0x30}, + {"EPC": ENL_BUZZER, "PDC": 0x01, "EDT": 0x30}, + { + "EPC": ENL_FAN_DIRECTION, + "PDC": 0x01, + "EDT": FAN_DIRECTION[fan_direction], + }, ] ) @@ -106,8 +116,8 @@ def setFanDirection(self, fan_direction): return: A string representing the fan direction """ - def getFanDirection(self): # 0xF1 - return self.getMessage(ENL_FAN_DIRECTION) + async def getFanDirection(self): # 0xF1 + return await self.getMessage(ENL_FAN_DIRECTION) """ setFanOscillation set the fan oscillation @@ -116,12 +126,16 @@ def getFanDirection(self): # 0xF1 e.g: 'True', 'False'. """ - def setFanOscillation(self, fan_oscillation): - return self.setMessages( + async def setFanOscillation(self, fan_oscillation): + return await self.setMessages( [ - {"EPC":ENL_FAN_POWER, "PDC": 0x01, "EDT": 0x30}, - {"EPC":ENL_BUZZER, "PDC": 0x01, "EDT": 0x30}, - {"EPC":ENL_FAN_OSCILLATION, "PDC": 0x01, "EDT": FAN_OSCILLATION[fan_oscillation]} + {"EPC": ENL_FAN_POWER, "PDC": 0x01, "EDT": 0x30}, + {"EPC": ENL_BUZZER, "PDC": 0x01, "EDT": 0x30}, + { + "EPC": ENL_FAN_OSCILLATION, + "PDC": 0x01, + "EDT": FAN_OSCILLATION[fan_oscillation], + }, ] ) @@ -132,5 +146,5 @@ def setFanOscillation(self, fan_oscillation): return: A boolean representing the fan oscillation status """ - def getFanOscillation(self): # 0xF2 - return self.getMessage(ENL_FAN_OSCILLATION) \ No newline at end of file + async def getFanOscillation(self): # 0xF2 + return await self.getMessage(ENL_FAN_OSCILLATION) diff --git a/pychonet/EchonetInstance.py b/pychonet/EchonetInstance.py index 6fe18db..4dbcddf 100644 --- a/pychonet/EchonetInstance.py +++ b/pychonet/EchonetInstance.py @@ -167,15 +167,32 @@ async def update(self, attributes=None, no_request=False): elif epc in list( self.EPC_FUNCTIONS.keys() ): # check the class-specific EPC function table. - returned_json_data.update( - { - epc: self.EPC_FUNCTIONS[epc]( - self._api._state[self._host]["instances"][self._eojgc][ - self._eojcc - ][self._eojci][epc] + raw_data = self._api._state[self._host]["instances"][self._eojgc][ + self._eojcc + ][self._eojci][epc] + if type(self.EPC_FUNCTIONS[epc]) == list: + if list(self.EPC_FUNCTIONS[epc]) == 3: + data = self.EPC_FUNCTIONS[epc][0]( + raw_data, + self.EPC_FUNCTIONS[epc][1], + self.EPC_FUNCTIONS[epc][2], ) - } - ) + else: + data = self.EPC_FUNCTIONS[epc][0]( + raw_data, self.EPC_FUNCTIONS[epc][1] + ) + else: + data = self.EPC_FUNCTIONS[epc](raw_data) + returned_json_data.update({epc: data}) + # returned_json_data.update( + # { + # epc: self.EPC_FUNCTIONS[epc]( + # self._api._state[self._host]["instances"][self._eojgc][ + # self._eojcc + # ][self._eojci][epc] + # ) + # } + # ) continue elif epc in list( EPC_CODE[self._eojgc][self._eojcc].keys() diff --git a/pychonet/ElectricBlind.py b/pychonet/ElectricBlind.py index 3a86849..7adacb6 100644 --- a/pychonet/ElectricBlind.py +++ b/pychonet/ElectricBlind.py @@ -1,47 +1,61 @@ +from deprecated import deprecated from pychonet.EchonetInstance import EchonetInstance +from pychonet.lib.epc_functions import ( + DATA_STATE_CLOSE, + DATA_STATE_OPEN, + DATA_STATE_STOP, + _int, +) ENL_OPENSTATE = 0xE0 +DICT_41_OPEN_CLOSE_STOP = { + 0x41: DATA_STATE_OPEN, + 0x42: DATA_STATE_CLOSE, + 0x43: DATA_STATE_STOP, +} + +@deprecated(reason="Scheduled for removal.") def _0260EO(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "open", 0x42: "close", 0x43: "stop"} - return values.get(op_mode, "invalid_setting") + return _int(edt, DICT_41_OPEN_CLOSE_STOP) # TODO - complete class definitions -# 0x80: 'Operation status', -# 0x89: 'Fault description (Recoverable faults)', -# 0x90: 'Timer operation setting', -# 0xC2: 'Wind detection status', -# 0xC3: 'Sunlight detection status', -# 0xD0: 'Opening (extension) speed setting', -# 0xD1: 'Closing (retraction) speed setting', -# 0xD2: 'Operation time', -# 0xD4: 'Automatic operation setting', -# 0xE1: 'Degree-of-opening level', -# 0xE2: 'Shade angle setting ', -# 0xE3: 'Open/close (extension/retraction) speed', -# 0xE5: 'Electric lock setting', -# 0xE8: 'Remote operation setting status', -# 0xE9: 'Selective opening (extension) operation setting', -# 0xEA: 'Open/closed (extended/retracted) status', -# 0xEE: 'One-time opening (extension) speed setting', -# 0xEF: 'One-time closing (retraction) speed setting' +# 0x80: 'Operation status', +# 0x89: 'Fault description (Recoverable faults)', +# 0x90: 'Timer operation setting', +# 0xC2: 'Wind detection status', +# 0xC3: 'Sunlight detection status', +# 0xD0: 'Opening (extension) speed setting', +# 0xD1: 'Closing (retraction) speed setting', +# 0xD2: 'Operation time', +# 0xD4: 'Automatic operation setting', +# 0xE1: 'Degree-of-opening level', +# 0xE2: 'Shade angle setting ', +# 0xE3: 'Open/close (extension/retraction) speed', +# 0xE5: 'Electric lock setting', +# 0xE8: 'Remote operation setting status', +# 0xE9: 'Selective opening (extension) operation setting', +# 0xEA: 'Open/closed (extended/retracted) status', +# 0xEE: 'One-time opening (extension) speed setting', +# 0xEF: 'One-time closing (retraction) speed setting' """Class for Electric Blind/Shade Objects""" class ElectricBlind(EchonetInstance): + EOJGC = 0x02 # Housing/facility-related device group + EOJCC = 0x60 # Electrically operated blind/shade - EPC_FUNCTIONS = {0xE0: _0260EO} + EPC_FUNCTIONS = { + 0xE0: [_int, DICT_41_OPEN_CLOSE_STOP], + } def __init__(self, host, api_connector=None, instance=0x1): - self._eojgc = 0x02 # Housing/facility-related device group - self._eojcc = 0x60 # Electrically operated blind/shade EchonetInstance.__init__( - self, host, self._eojgc, self._eojcc, instance, api_connector + self, host, self.EOJGC, self.EOJCC, instance, api_connector ) """ diff --git a/pychonet/ElectricEnergyMeter.py b/pychonet/ElectricEnergyMeter.py index 3940d94..1d345ad 100644 --- a/pychonet/ElectricEnergyMeter.py +++ b/pychonet/ElectricEnergyMeter.py @@ -1,17 +1,16 @@ from pychonet.EchonetInstance import EchonetInstance from pychonet.lib.epc_functions import _int, _signed_int + def _0280E2(edt): - # return array x 48 unsigned long big-endian - op_mode = int.from_bytes(edt, "big") - values = {0x01: 0.1, 0x02: 0.01} - return values.get(op_mode, "invalid_setting") + # return array x 48 unsigned long big-endian + return _int(edt, {0x01: 0.1, 0x02: 0.01}) class ElectricEnergyMeter(EchonetInstance): EPC_FUNCTIONS = { 0xE0: _int, # 0xE0: "Cumulative amounts of electric energy measurement value", - 0xE2: _0280E2 # 0xE2: "Cumulative amounts of electric energy unit", + 0xE2: _0280E2, # 0xE2: "Cumulative amounts of electric energy unit", } def __init__(self, host, api_connector=None, instance=0x1): diff --git a/pychonet/ElectricHeater.py b/pychonet/ElectricHeater.py index e9f5c12..1d2613e 100644 --- a/pychonet/ElectricHeater.py +++ b/pychonet/ElectricHeater.py @@ -1,41 +1,40 @@ +import asyncio +from types import _ReturnT_co +from deprecated import deprecated from pychonet.EchonetInstance import EchonetInstance -from pychonet.lib.epc_functions import _int, _hh_mm, _signed_int +from pychonet.lib.epc_functions import ( + DATA_STATE_OFF, + DATA_STATE_ON, + DICT_41_AUTO_8_SPEEDS, + DICT_41_AUTO_NONAUTO, + DICT_41_ON_OFF, + _int, + _hh_mm, + _signed_int, +) + def _014290(data): # Logic to interpret data for EPC 0x90 - if data == 0x41: - return 'Automatic' - elif data == 0x42: - return 'Manual' - else: - return 'Unknown' + return _int(data, DICT_41_AUTO_NONAUTO) + def _0142A0(data): # Logic to interpret data for EPC 0xA0 - if data == 0x41: - return 'Automatic air flow rate control used' - elif 0x31 <= data <= 0x38: - return f'Air flow rate: {data.decode()}' - else: - return 'Unknown' + return _int(data, DICT_41_AUTO_8_SPEEDS) + +@deprecated(reason="Scheduled for removal.") def _0142B1(data): # Logic to interpret data for EPC 0xB1 - if data == 0x41: - return 'On' - elif data == 0x42: - return 'Off' - else: - return 'Unknown' + return _int(data, DICT_41_ON_OFF) + +@deprecated(reason="Scheduled for removal.") def _014294(data): # Logic to interpret data for EPC 0xB1 - if data == 0x41: - return 'On' - elif data == 0x42: - return 'Off' - else: - return 'Unknown' + return _int(data, DICT_41_ON_OFF) + class ElectricHeater(EchonetInstance): EOJGC = 0x01 @@ -43,15 +42,15 @@ class ElectricHeater(EchonetInstance): EPC_FUNCTIONS = { 0x80: _int, - 0xB1: _0142B1, + 0xB1: [_int, DICT_41_AUTO_NONAUTO], 0xB3: _int, 0xBB: _signed_int, 0xBC: _int, - 0xA0: _0142A0, - 0x90: _014290, + 0xA0: [_int, DICT_41_AUTO_8_SPEEDS], + 0x90: [_int, DICT_41_ON_OFF], 0x91: _hh_mm, 0x92: _hh_mm, - 0x94: _014294, + 0x94: [_int, DICT_41_ON_OFF], 0x95: _hh_mm, 0x96: _hh_mm, } @@ -62,49 +61,49 @@ def __init__(self, host, api_connector=None, instance=0x1): super().__init__(host, self._eojgc, self._eojcc, instance, api_connector) @property - def operation_status(self): - return self.getMessage(0x80) + async def operation_status(self): + return await self.getMessage(0x80) @operation_status.setter - def operation_status(self, value): - self.setMessage(0x80, value) + async def operation_status(self, value): + await self.setMessage(0x80, value) @property - def automatic_temperature_control_setting(self): - return self.getMessage(0xB1) + async def automatic_temperature_control_setting(self): + return await self.getMessage(0xB1) @automatic_temperature_control_setting.setter - def automatic_temperature_control_setting(self, value): - self.setMessage(0xB1, value) + async def automatic_temperature_control_setting(self, value): + await self.setMessage(0xB1, value) @property - def temperature_setting(self): - return self.getMessage(0xB3) + async def temperature_setting(self): + return await self.getMessage(0xB3) @temperature_setting.setter - def temperature_setting(self, value): - self.setMessage(0xB3, value) + async def temperature_setting(self, value): + await self.setMessage(0xB3, value) @property - def measured_room_temperature(self): - return self.getMessage(0xBB) + async def measured_room_temperature(self): + return await self.getMessage(0xBB) @measured_room_temperature.setter - def measured_room_temperature(self, value): - self.setMessage(0xBB, value) + async def measured_room_temperature(self, value): + await self.setMessage(0xBB, value) @property - def remotely_set_temperature(self): - return self.getMessage(0xBC) + async def remotely_set_temperature(self): + return await self.getMessage(0xBC) @remotely_set_temperature.setter - def remotely_set_temperature(self, value): - self.setMessage(0xBC, value) + async def remotely_set_temperature(self, value): + await self.setMessage(0xBC, value) @property - def air_flow_rate_setting(self): - return self.getMessage(0xA0) + async def air_flow_rate_setting(self): + return await self.getMessage(0xA0) @air_flow_rate_setting.setter - def air_flow_rate_setting(self, value): - self.setMessage(0xA0, value) + async def air_flow_rate_setting(self, value): + await self.setMessage(0xA0, value) diff --git a/pychonet/ElectricLock.py b/pychonet/ElectricLock.py index 793c94e..0007c3b 100644 --- a/pychonet/ElectricLock.py +++ b/pychonet/ElectricLock.py @@ -1,63 +1,78 @@ +import asyncio +from deprecated import deprecated from pychonet.EchonetInstance import EchonetInstance +from pychonet.lib.epc_functions import ( + DATA_STATE_OFF, + DATA_STATE_ON, + DICT_41_ON_OFF, + DICT_41_OPEN_CLOSED, + DICT_41_UNLOCK_LOCK, + _int, +) # ----- Electric Lock Class ------- +@deprecated(reason="Scheduled for removal.") def _026FEX(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "lock", 0x42: "unlock"} - return values.get(op_mode, "invalid_setting") + return _int(edt, DICT_41_UNLOCK_LOCK) +@deprecated(reason="Scheduled for removal.") def _026FE3(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "open", 0x42: "closed"} - return values.get(op_mode, "invalid_setting") + return _int(edt, DICT_41_OPEN_CLOSED) +@deprecated(reason="Scheduled for removal.") def _026FE4(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "occupant", 0x42: "non-occupant"} - return values.get(op_mode, "invalid_setting") + return _int(edt, {0x41: "occupant", 0x42: "non-occupant"}) +@deprecated(reason="Scheduled for removal.") def _026FE5(edt): - op_mode = int.from_bytes(edt, "big") - values = { - 0x40: "normal", - 0x41: "break_open", - 0x42: "door_open", - 0x43: "maunal_unlocked", - 0x44: "tampered", - } - return values.get(op_mode, "invalid_setting") - - + return _int( + edt, + { + 0x40: "normal", + 0x41: "break_open", + 0x42: "door_open", + 0x43: "maunal_unlocked", + 0x44: "tampered", + }, + ) + + +@deprecated(reason="Scheduled for removal.") def _026FE6(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "on", 0x42: "off"} - return values.get(op_mode, "invalid_setting") + return _int(edt, DICT_41_ON_OFF) +@deprecated(reason="Scheduled for removal.") def _026FE7(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "normal", 0x42: "battery_replacement_notification"} - return values.get(op_mode, "invalid_setting") + return _int(edt, {0x41: "normal", 0x42: "battery_replacement_notification"}) """Class for Electric Lock Objects""" class ElectricLock(EchonetInstance): - EPC_FUNCTIONS = { - 0xE0: _026FEX, - 0xE1: _026FEX, - 0xE2: _026FEX, - 0xE3: _026FE3, - 0xE4: _026FE4, - 0xE5: _026FE5, - 0xE6: _026FE6, - 0xE7: _026FE7, + 0xE0: [_int, DICT_41_UNLOCK_LOCK], + 0xE1: [_int, DICT_41_UNLOCK_LOCK], + 0xE2: [_int, DICT_41_UNLOCK_LOCK], + 0xE3: [_int, DICT_41_OPEN_CLOSED], + 0xE4: [_int, {0x41: "occupant", 0x42: "non-occupant"}], + 0xE5: [ + _int, + { + 0x40: "normal", + 0x41: "break_open", + 0x42: "door_open", + 0x43: "maunal_unlocked", + 0x44: "tampered", + }, + ], + 0xE6: [_int, DICT_41_ON_OFF], + 0xE7: [_int, {0x41: "normal", 0x42: "battery_replacement_notification"}], } def __init__(self, host, api_connector=None, instance=0x1): @@ -73,5 +88,5 @@ def __init__(self, host, api_connector=None, instance=0x1): return: A string representing the lock status """ - def getLockOneStatus(self): - return self.getMessage(0xE1) + async def getLockOneStatus(self): + return await self.getMessage(0xE1) diff --git a/pychonet/ElectricStorageHeater.py b/pychonet/ElectricStorageHeater.py index 84c251a..8bff80e 100644 --- a/pychonet/ElectricStorageHeater.py +++ b/pychonet/ElectricStorageHeater.py @@ -1,234 +1,262 @@ -#TODO fix this ChatGPT created code. +from deprecated import deprecated + +# TODO fix this ChatGPT created code. from pychonet.EchonetInstance import EchonetInstance -from pychonet.lib.epc_functions import _hh_mm, _int +from pychonet.lib.epc_functions import ( + DICT_30_ON_OFF, + DICT_41_AVAILABLE_NOT_AVAILABLE, + DICT_41_ENABLED_DISABLED, + DICT_41_ON_OFF, + _hh_mm, + _int, +) + # Static methods for ElectricStorageHeater +@deprecated(reason="Scheduled for removal.") def _0155B3(payload): return _int(payload) + +@deprecated(reason="Scheduled for removal.") def _0155B8(payload): return _int(payload) + +@deprecated(reason="Scheduled for removal.") def _0155BB(payload): return _int(payload) + +@deprecated(reason="Scheduled for removal.") def _0155BE(payload): return _int(payload) + def _0155A0(payload): return _int(payload) + +@deprecated(reason="Scheduled for removal.") def _0155A1(payload): - if payload == 0x30: - return 'Fan operation ON' - elif payload == 0x31: - return 'Fan operation OFF' - else: - return 'Unknown fan operation status' + return _int(payload, DICT_30_ON_OFF) + +@deprecated(reason="Scheduled for removal.") def _0155C0(payload): - if payload == 0x41: - return 'Heat storage ON' - elif payload == 0x42: - return 'Heat storage OFF' - else: - return 'Unknown heat storage operation status' + return _int(payload, DICT_41_ON_OFF) + +@deprecated(reason="Scheduled for removal.") def _0155C1(payload): return _int(payload) + +@deprecated(reason="Scheduled for removal.") def _0155C2(payload): return _int(payload) + +@deprecated(reason="Scheduled for removal.") def _0155C3(payload): - if payload == 0x41: - return 'Daytime heat storage enabled' - elif payload == 0x42: - return 'Daytime heat storage disabled' - else: - return 'Unknown daytime heat storage setting' + return _int(payload, DICT_41_ENABLED_DISABLED) + +@deprecated(reason="Scheduled for removal.") def _0155C4(payload): - if payload == 0x41: - return 'Daytime heat storage available' - elif payload == 0x42: - return 'Daytime heat storage not available' - else: - return 'Unknown daytime heat storage ability' + return _int(payload, DICT_41_AVAILABLE_NOT_AVAILABLE) + +@deprecated(reason="Scheduled for removal.") def _0155C5(payload): return _int(payload) + +@deprecated(reason="Scheduled for removal.") def _0155C6(payload): return _hh_mm(payload) + +@deprecated(reason="Scheduled for removal.") def _0155C7(payload): - if payload == 0x41: - return 'Radiant heat method' - elif payload == 0x42: - return 'Air heat method' - elif payload == 0x43: - return 'Radiant and air heat method' - else: - return 'Unknown radiation method' + return _int( + payload, + { + 0x41: "Radiant heat method", + 0x42: "Air heat method", + 0x43: "Radiant and air heat method", + }, + ) + +@deprecated(reason="Scheduled for removal.") def _0155C8(payload): - if payload == 0x41: - return 'Child lock enabled' - elif payload == 0x42: - return 'Child lock disabled' - else: - return 'Unknown child lock setting' + return _int(payload, DICT_41_ENABLED_DISABLED) + +@deprecated(reason="Scheduled for removal.") def _0155D0(payload): return _int(payload) + +@deprecated(reason="Scheduled for removal.") def _0155D1(payload): return _hh_mm(payload) + +@deprecated(reason="Scheduled for removal.") def _0155D2(payload): return _hh_mm(payload) + +@deprecated(reason="Scheduled for removal.") def _0155D3(payload): return _int(payload) + class ElectricStorageHeater(EchonetInstance): - class_codes = { - 'class_group_code': 0x01, - 'class_code': 0x55 - } + class_codes = {"class_group_code": 0x01, "class_code": 0x55} EPC_FUNCTIONS = { - 0xB3: _0155B3, - 0xB8: _0155B8, - 0xBB: _0155BB, - 0xBE: _0155BE, - 0xA0: _0155A0, - 0xA1: _0155A1, - 0xC0: _0155C0, - 0xC1: _0155C1, - 0xC2: _0155C2, - 0xC3: _0155C3, - 0xC4: _0155C4, - 0xC5: _0155C5, - 0xC6: _0155C6, - 0xC7: _0155C7, - 0xC8: _0155C8, - 0xD0: _0155D0, + 0xB3: _int, + 0xB8: _int, + 0xBB: _int, + 0xBE: _int, + 0xA0: _int, + 0xA1: [_int, DICT_30_ON_OFF], + 0xC0: [_int, DICT_41_ON_OFF], + 0xC1: _int, + 0xC2: _int, + 0xC3: [_int, DICT_41_ENABLED_DISABLED], + 0xC4: [_int, DICT_41_AVAILABLE_NOT_AVAILABLE], + 0xC5: _int, + 0xC6: _hh_mm, + 0xC7: [ + _int, + { + 0x41: "Radiant heat method", + 0x42: "Air heat method", + 0x43: "Radiant and air heat method", + }, + ], + 0xC8: [_int, DICT_41_ENABLED_DISABLED], + 0xD0: _int, 0xD1: _hh_mm, 0xD2: _hh_mm, - 0xD3: _0155D3, + 0xD3: _int, 0xD4: _hh_mm, 0xD5: _hh_mm, } - def __init__(self, host, device): - super().__init__(host, device) + def __init__(self, host, api_connector=None, instance=0x1): + self._eojgc = self.class_codes["class_group_code"] + self._eojcc = self.class_codes["class_code"] + super().__init__(host, self._eojgc, self._eojcc, instance, api_connector) - def getTemperatureSetting(self): - return self.getMessage(0xB3) + async def getTemperatureSetting(self): + return await self.getMessage(0xB3) - def getRatedPowerConsumption(self): - return self.getMessage(0xB8) + async def getRatedPowerConsumption(self): + return await self.getMessage(0xB8) - def getMeasuredIndoorTemperature(self): - return self.getMessage(0xBB) + async def getMeasuredIndoorTemperature(self): + return await self.getMessage(0xBB) - def getMeasuredOutdoorTemperature(self): - return self.getMessage(0xBE) + async def getMeasuredOutdoorTemperature(self): + return await self.getMessage(0xBE) - def getAirFlowRateSetting(self): - return self.getMessage(0xA0) + async def getAirFlowRateSetting(self): + return await self.getMessage(0xA0) - def setAirFlowRateSetting(self, setting): - self.setMessage(0xA0, setting) + async def setAirFlowRateSetting(self, setting): + await self.setMessage(0xA0, setting) - def getFanOperationStatus(self): - return self.getMessage(0xA1) + async def getFanOperationStatus(self): + return await self.getMessage(0xA1) - def setFanOperationStatus(self, status): - self.setMessage(0xA1, status) + async def setFanOperationStatus(self, status): + await self.setMessage(0xA1, status) - def getHeatStorageOperationStatus(self): - return self.getMessage(0xC0) + async def getHeatStorageOperationStatus(self): + return await self.getMessage(0xC0) - def setHeatStorageOperationStatus(self, status): - self.setMessage(0xC0, status) + async def setHeatStorageOperationStatus(self, status): + await self.setMessage(0xC0, status) - def getHeatStorageTemperatureSetting(self): - return self.getMessage(0xC1) + async def getHeatStorageTemperatureSetting(self): + return await self.getMessage(0xC1) - def setHeatStorageTemperatureSetting(self, temperature): - self.setMessage(0xC1, temperature) + async def setHeatStorageTemperatureSetting(self, temperature): + await self.setMessage(0xC1, temperature) - def getMeasuredStoredHeatTemperature(self): - return self.getMessage(0xC2) + async def getMeasuredStoredHeatTemperature(self): + return await self.getMessage(0xC2) - def getDaytimeHeatStorageSetting(self): - return self.getMessage(0xC3) + async def getDaytimeHeatStorageSetting(self): + return await self.getMessage(0xC3) - def setDaytimeHeatStorageSetting(self, setting): - self.setMessage(0xC3, setting) + async def setDaytimeHeatStorageSetting(self, setting): + await self.setMessage(0xC3, setting) - def getDaytimeHeatStorageAbility(self): - return self.getMessage(0xC4) + async def getDaytimeHeatStorageAbility(self): + return await self.getMessage(0xC4) - def getMidnightPowerDurationSetting(self): - return self.getMessage(0xC5) + async def getMidnightPowerDurationSetting(self): + return await self.getMessage(0xC5) - def setMidnightPowerDurationSetting(self, duration): - self.setMessage(0xC5, duration) + async def setMidnightPowerDurationSetting(self, duration): + await self.setMessage(0xC5, duration) - def getMidnightPowerStartTimeSetting(self): - return self.getMessage(0xC6) + async def getMidnightPowerStartTimeSetting(self): + return await self.getMessage(0xC6) - def setMidnightPowerStartTimeSetting(self, time): - self.setMessage(0xC6, time) + async def setMidnightPowerStartTimeSetting(self, time): + await self.setMessage(0xC6, time) - def getRadiationMethod(self): - return self.getMessage(0xC7) + async def getRadiationMethod(self): + return await self.getMessage(0xC7) - def setRadiationMethod(self, method): - self.setMessage(0xC7, method) + async def setRadiationMethod(self, method): + await self.setMessage(0xC7, method) - def getChildLockSetting(self): - return self.getMessage(0xC8) + async def getChildLockSetting(self): + return await self.getMessage(0xC8) - def setChildLockSetting(self, setting): - self.setMessage(0xC8, setting) + async def setChildLockSetting(self, setting): + await self.setMessage(0xC8, setting) - def getFanTimer1Setting(self): - return self.getMessage(0xD0) + async def getFanTimer1Setting(self): + return await self.getMessage(0xD0) - def setFanTimer1Setting(self, setting): - self.setMessage(0xD0, setting) + async def setFanTimer1Setting(self, setting): + await self.setMessage(0xD0, setting) - def getFanTimer1ONTimeSetting(self): - return self.getMessage(0xD1) + async def getFanTimer1ONTimeSetting(self): + return await self.getMessage(0xD1) - def setFanTimer1ONTimeSetting(self, time): - self.setMessage(0xD1, time) + async def setFanTimer1ONTimeSetting(self, time): + await self.setMessage(0xD1, time) - def getFanTimer1OFFTimeSetting(self): - return self.getMessage(0xD2) + async def getFanTimer1OFFTimeSetting(self): + return await self.getMessage(0xD2) - def setFanTimer1OFFTimeSetting(self, time): - self.setMessage(0xD2, time) + async def setFanTimer1OFFTimeSetting(self, time): + await self.setMessage(0xD2, time) - def getFanTimer2Setting(self): - return self.getMessage(0xD3) + async def getFanTimer2Setting(self): + return await self.getMessage(0xD3) - def setFanTimer2Setting(self, setting): - self.setMessage(0xD3, setting) + async def setFanTimer2Setting(self, setting): + await self.setMessage(0xD3, setting) - def getFanTimer2ONTimeSetting(self): - return self.getMessage(0xD4) + async def getFanTimer2ONTimeSetting(self): + return await self.getMessage(0xD4) - def setFanTimer2ONTimeSetting(self, time): - self.setMessage(0xD4, time) + async def setFanTimer2ONTimeSetting(self, time): + await self.setMessage(0xD4, time) - def getFanTimer2OFFTimeSetting(self): - return self.getMessage(0xD5) + async def getFanTimer2OFFTimeSetting(self): + return await self.getMessage(0xD5) - def setFanTimer2OFFTimeSetting(self, time): - self.setMessage(0xD5, time) + async def setFanTimer2OFFTimeSetting(self, time): + await self.setMessage(0xD5, time) diff --git a/pychonet/ElectricWaterHeater.py b/pychonet/ElectricWaterHeater.py index f47147f..a845d7f 100644 --- a/pychonet/ElectricWaterHeater.py +++ b/pychonet/ElectricWaterHeater.py @@ -1,60 +1,60 @@ +from deprecated import deprecated from pychonet.EchonetInstance import EchonetInstance -from pychonet.lib.epc_functions import _int, _signed_int +from pychonet.lib.epc_functions import ( + DICT_41_HEATING_NOT_HEATING, + DICT_41_ON_OFF, + _int, + _hh_mm, +) # 0xB0 - Automatic water heating setting +@deprecated(reason="Scheduled for removal.") def _026BB0(edt): - op_mode = int.from_bytes(edt, "big") - AUTOMATIC_WATER_HEATING_STATES = { - 0x41: "Automatic", - 0x42: "Manual", - 0x43: "Stop", - } - return AUTOMATIC_WATER_HEATING_STATES.get(op_mode, "Invalid setting") + return _int( + edt, + { + 0x41: "Automatic", + 0x42: "Manual", + 0x43: "Stop", + }, + ) # 0xB1 - Automatic water temperature control setting +@deprecated(reason="Scheduled for removal.") def _026BB1(edt): - op_mode = int.from_bytes(edt, "big") - AUTOMATIC_WATER_TEMP_CONTROL = { - 0x41: "On", - 0x42: "Off", - } - return AUTOMATIC_WATER_TEMP_CONTROL.get(op_mode, "Invalid setting") + return _int(edt, DICT_41_ON_OFF) # 0xB2 - Water heating status +@deprecated(reason="Scheduled for removal.") def _026BB2(edt): - op_mode = int.from_bytes(edt, "big") - WATER_HEATING_STATUS = { - 0x41: "Heating", - 0x42: "Not Heating", - } - return WATER_HEATING_STATUS.get(op_mode, "Invalid setting") + return _int(edt, DICT_41_HEATING_NOT_HEATING) # 0xB5 Relative time setting value for manual water heating OFF +@deprecated(reason="Scheduled for removal.") def _026BB5(edt): - hh = int.from_bytes(edt[0:1], "big") - mm = str(int.from_bytes(edt[1:2], "big")).zfill(2) - return f"{hh}:{mm}" + return _hh_mm(edt) # 0xB6 - Tank Operation mode setting +@deprecated(reason="Scheduled for removal.") def _026BB6(edt): - op_mode = int.from_bytes(edt, "big") - WATER_HEATING_STATUS = {0x41: "Standard", 0x42: "Saving", 0x43: "Extra"} - return WATER_HEATING_STATUS.get(op_mode, "Invalid setting") + return _int(edt, {0x41: "Standard", 0x42: "Saving", 0x43: "Extra"}) # 0xC0 - Daytime reheating permission setting +@deprecated(reason="Scheduled for removal.") def _026BC0(edt): - op_mode = int.from_bytes(edt, "big") - AUX_SETTING_STATE = { - 0x41: "Permitted", - 0x42: "Not permitted", - } - return AUX_SETTING_STATE.get(op_mode, "Invalid setting") + return _int( + edt, + { + 0x41: "Permitted", + 0x42: "Not permitted", + }, + ) # 0xC2 - Alarm Status @@ -84,20 +84,21 @@ def _026BB9(edt): # 0xC3 - Hot water supply status +@deprecated(reason="Scheduled for removal.") def _026BC3(edt): - op_mode = int.from_bytes(edt, "big") - HOT_WATER_SUPPLY_STATUS = { - 0x41: "Supplying hot water", - 0x42: "Not supplying hot water", - } - return HOT_WATER_SUPPLY_STATUS.get(op_mode, "Invalid setting") + return _int( + edt, + { + 0x41: "Supplying hot water", + 0x42: "Stopped", + }, + ) # 0xC4 Relative time setting for keeping bath temperature +@deprecated(reason="Scheduled for removal.") def _026BC4(edt): - hh = int.from_bytes(edt[0:1], "big") - mm = str(int.from_bytes(edt[1:2], "big")).zfill(2) - return f"{hh}:{mm}" + return _hh_mm(edt) # 0xE1 - Measured amount of hot water remaining in tank @@ -106,83 +107,67 @@ def _026BC4(edt): # 0xE3 - Automatic bath water heater mode setting +@deprecated(reason="Scheduled for removal.") def _026BE3(edt): - op_mode = int.from_bytes(edt, "big") - AUTOMATIC_SETTING = { - 0x41: "On", - 0x42: "Off", - } - return AUTOMATIC_SETTING.get(op_mode, "Invalid setting") + return _int(edt, DICT_41_ON_OFF) # 0xE9 - Bathroom Priority setting +@deprecated(reason="Scheduled for removal.") def _026BE9(edt): - op_mode = int.from_bytes(edt, "big") - PRIORITY_SETTING = { - 0x41: "On", - 0x42: "Off", - } - return PRIORITY_SETTING.get(op_mode, "Invalid setting") + return _int(edt, DICT_41_ON_OFF) # 0xEA - Bath operation status monitor +@deprecated(reason="Scheduled for removal.") def _026BEA(edt): - op_mode = int.from_bytes(edt, "big") - OPERATION_STATUS_MONITOR = { - 0x41: "Filling hot water", - 0x42: "Stopped", - 0x43: "Keeping Temperature", - } - return OPERATION_STATUS_MONITOR.get(op_mode, "Invalid setting") + return _int( + edt, + { + 0x41: "Filling hot water", + 0x42: "Stopped", + 0x43: "Keeping Temperature", + }, + ) # 0xE4 - Manual bath reheating function setting +@deprecated(reason="Scheduled for removal.") def _026BE4(edt): - op_mode = int.from_bytes(edt, "big") - REHEAT_FUNCTON = { - 0x41: "On", - 0x42: "Off", - } - return REHEAT_FUNCTON.get(op_mode, "Invalid setting") + return _int(edt, DICT_41_ON_OFF) # 0xE5 - Manual bath hot water addition function setting +@deprecated(reason="Scheduled for removal.") def _026BE5(edt): - op_mode = int.from_bytes(edt, "big") - ADDITION_FUNCTION = { - 0x41: "On", - 0x42: "Off", - } - return ADDITION_FUNCTION.get(op_mode, "Invalid setting") + return _int(edt, DICT_41_ON_OFF) # 0xE6 - Manual lukewarm water temperature lowering function setting +@deprecated(reason="Scheduled for removal.") def _026BE6(edt): - op_mode = int.from_bytes(edt, "big") - LUKEWARM = { - 0x41: "On", - 0x42: "Off", - } - return LUKEWARM.get(op_mode, "Invalid setting") + return _int(edt, DICT_41_ON_OFF) # 0xE7 - Bath Volume water setting one # 0xE8 - Bath Volume water setting two +@deprecated(reason="Scheduled for removal.") def _026BE8(edt): - op_mode = int.from_bytes(edt, "big") - VOLUME = { - 0x31: "Level 1", - 0x32: "Level 2", - 0x33: "Level 3", - 0x34: "Level 4", - 0x35: "Level 5", - 0x36: "Level 6", - 0x37: "Level 7", - 0x38: "Level 8", - } - return VOLUME.get(op_mode, "Invalid setting") + return _int( + edt, + { + 0x31: "Level 1", + 0x32: "Level 2", + 0x33: "Level 3", + 0x34: "Level 4", + 0x35: "Level 5", + 0x36: "Level 6", + 0x37: "Level 7", + 0x38: "Level 8", + }, + ) # 0xEE - Bath Volume water setting three @@ -193,34 +178,29 @@ def _026BE8(edt): # 0x90 - ON timer reservation setting +@deprecated(reason="Scheduled for removal.") def _026B90(edt): - op_mode = int.from_bytes(edt, "big") - RESERVATION_SETTING = { - 0x41: "On", - 0x42: "Off", - } - return RESERVATION_SETTING.get(op_mode, "Invalid setting") + return _int(edt, DICT_41_ON_OFF) # 0x91 - ON timer setting +@deprecated(reason="Scheduled for removal.") def _026B91(edt): - hh = int.from_bytes(edt[0:1], "big") - mm = str(int.from_bytes(edt[1:2], "big")).zfill(2) - return {"time": f"{hh}:{mm}"} + return _hh_mm(edt) + # 0xD6 - Sound Volume Setting + # 0xD7 - Mute Setting +@deprecated(reason="Scheduled for removal.") def _026BD7(edt): - op_mode = int.from_bytes(edt, "big") - MUTE_SETTING = { - 0x41: "On", - 0x42: "Off", - } - return MUTE_SETTING.get(op_mode, "Invalid setting") + return _int(edt, DICT_41_ON_OFF) + # 0xD8 - Remaining Hot Water volume + # 0xD9 - Surplus electric energy prediction value def _026BD9(edt): starting_MM = str(int.from_bytes(edt[0:1], "big")).zfill(2) @@ -245,6 +225,7 @@ def _026BD9(edt): "predicted_values": predicted_values, } + # 0xDB - Rated power consumptions of H/P unit in winter time # 0xDC - Rated power consumptions of H/P unit in between seasons # 0xDD - Rated power consumptions of H/P unit in summer time @@ -252,71 +233,118 @@ def _026BD9(edt): # 0xCB - Expected electric energy at daytime heating shift time 1 def _026BCB(edt): - return("not implemented") + return "not implemented" + # 0xCC - Consumption of electric energy per hour 1 def _026BCC(edt): - return("not implemented") + return "not implemented" + # 0xCE - Expected electric energy at daytime heating shift time 2 def _026BCE(edt): - return("not implemented") + return "not implemented" + # 0xCF - Consumption of electric energy per hour 2 def _026BCF(edt): - return("not implemented") + return "not implemented" class ElectricWaterHeater(EchonetInstance): EPC_FUNCTIONS = { - 0xB0: _026BB0, - 0xB1: _026BB1, - 0xB2: _026BB2, + 0xB0: [ + _int, + { + 0x41: "Automatic", + 0x42: "Manual", + 0x43: "Stop", + }, + ], + 0xB1: [_int, DICT_41_ON_OFF], + 0xB2: [_int, DICT_41_HEATING_NOT_HEATING], 0xB3: _int, 0xB4: _int, - 0xB5: _026BB5, - 0xB6: _026BB6, - 0xC0: _026BC0, + 0xB5: _hh_mm, + 0xB6: [ + _int, + { + 0x41: "Standard", + 0x42: "Saving", + 0x43: "Extra", + }, + ], + 0xC0: [ + _int, + { + 0x41: "Permitted", + 0x42: "Not permitted", + }, + ], 0xC1: _int, 0xC2: _026BC2, - 0xC3: _026BC3, - 0xC4: _026BC4, + 0xC3: [ + _int, + { + 0x41: "Supplying hot water", + 0x42: "Stopped", + }, + ], + 0xC4: _hh_mm, 0xD1: _int, 0xD3: _int, 0xE0: _int, 0xE1: _int, 0xE2: _int, - 0xE3: _026BE3, - 0xE9: _026BE9, - 0xEA: _026BEA, - 0xE4: _026BE4, - 0xE5: _026BE5, - 0xE6: _026BE6, + 0xE3: [_int, DICT_41_ON_OFF], + 0xE9: [_int, DICT_41_ON_OFF], + 0xEA: [ + _int, + { + 0x41: "Filling hot water", + 0x42: "Stopped", + 0x43: "Keeping Temperature", + }, + ], + 0xE4: [_int, DICT_41_ON_OFF], + 0xE5: [_int, DICT_41_ON_OFF], + 0xE6: [_int, DICT_41_ON_OFF], 0xE7: _int, - 0xE8: _026BE8, + 0xE8: [ + _int, + { + 0x31: "Level 1", + 0x32: "Level 2", + 0x33: "Level 3", + 0x34: "Level 4", + 0x35: "Level 5", + 0x36: "Level 6", + 0x37: "Level 7", + 0x38: "Level 8", + }, + ], 0xE9: _int, 0xEE: _int, 0xD4: _int, 0xD5: _int, - 0x90: _026B90, - 0x91: _026B91, + 0x90: [_int, DICT_41_ON_OFF], + 0x91: _hh_mm, 0xD6: _int, - 0xD7: _026BD7, + 0xD7: [_int, DICT_41_ON_OFF], 0xD8: _int, 0xD9: _026BD9, 0xDB: _int, 0xDC: _int, 0xDD: _int, 0xC7: _int, - 0xC8: _int, # could change + 0xC8: _int, # could change 0xC9: _int, 0xCA: _int, - 0xCB: _026BCB, #todo - 0xCC: _026BCC, #todo + 0xCB: _026BCB, # todo + 0xCC: _026BCC, # todo 0xCD: _int, - 0xCE: _026BCB, #todo - 0xCF: _026BCF #todo - + 0xCE: _026BCB, # todo + 0xCF: _026BCF, # todo } def __init__(self, host, api_connector=None, instance=0x1): diff --git a/pychonet/FanHeater.py b/pychonet/FanHeater.py index ee54982..4a1808b 100644 --- a/pychonet/FanHeater.py +++ b/pychonet/FanHeater.py @@ -1,148 +1,139 @@ from pychonet import EchonetInstance -from pychonet.lib.epc_functions import _hh_mm, _int - -@staticmethod -def _0143BB(payload): - return str(payload) - -@staticmethod -def _0143B1(payload): - return str(payload) - -@staticmethod -def _014390(payload): - return str(payload) - -@staticmethod -def _014394(payload): - return str(payload) - -@staticmethod -def _0143C0(payload): - if payload == 0x41: - return 'Extension ON' - elif payload == 0x42: - return 'Extension OFF' - else: - return 'Unknown' - -@staticmethod -def _0143C2(payload): - if payload == 0x41: - return 'Ion emission ON' - elif payload == 0x42: - return 'Ion emission OFF' - else: - return 'Unknown' - -@staticmethod -def _0143C3(payload): - return str(payload) - -@staticmethod -def _0143C4(payload): - return str(payload) +from pychonet.lib.epc_functions import ( + DATA_STATE_OFF, + DATA_STATE_ON, + DICT_41_AUTO_NONAUTO, + DICT_41_ON_OFF, + _hh_mm, + _int, + _signed_int, +) + class FanHeater(EchonetInstance): - class_codes = { - 'class_group_code': 0x01, - 'class_code': 0x43 - } + class_codes = {"class_group_code": 0x01, "class_code": 0x43} EPC_FUNCTIONS = { 0xB3: _int, - 0xBB: _0143BB, - 0xB1: _0143B1, - 0x90: _014390, + 0xBB: _signed_int, + 0xB1: [_int, DICT_41_AUTO_NONAUTO], + 0x90: [ + _int, + { + 0x41: DATA_STATE_ON, + 0x42: DATA_STATE_OFF, + 0x43: "Timer-based ON", + 0x44: "Relative time ON", + }, + ], 0x91: _hh_mm, 0x92: _hh_mm, - 0x94: _014394, + 0x94: [ + _int, + { + 0x41: DATA_STATE_ON, + 0x42: DATA_STATE_OFF, + 0x43: "Timer-based ON", + 0x44: "Relative time ON", + }, + ], 0x95: _hh_mm, 0x96: _hh_mm, - 0xC0: _0143C0, + 0xC0: [_int, DICT_41_ON_OFF], 0xC1: _hh_mm, - 0xC2: _0143C2, - 0xC3: _0143C3, - 0xC4: _0143C4, + 0xC2: [_int, DICT_41_ON_OFF], + # 0xC3: #Specifies ion emission method implemented in humidifier by bit map, + # Bit 0: negative ion method mounting + # Bit 1: cluster ion method mounting + 0xC4: [ + _int, + { + 0x40: "Empty", + 0x41: "Minimum", + 0x42: "Low", + 0x43: "Middium", + 0x44: "High", + 0x45: "Maximum", + }, + ], } def __init__(self, host, api_connector=None, instance=0x1): - self._eojgc = self.class_codes['class_group_code'] - self._eojcc = self.class_codes['class_code'] + self._eojgc = self.class_codes["class_group_code"] + self._eojcc = self.class_codes["class_code"] super().__init__(host, self._eojgc, self._eojcc, instance, api_connector) - def getTemperatureSettingValue(self): + async def getTemperatureSettingValue(self): return self.getMessage(0xB3) - def setTemperatureSettingValue(self, value): + async def setTemperatureSettingValue(self, value): self.setMessage(0xB3, value) - def getMeasuredTemperature(self): + async def getMeasuredTemperature(self): return self.getMessage(0xBB) - def getAutomaticTemperatureControlSetting(self): + async def getAutomaticTemperatureControlSetting(self): return self.getMessage(0xB1) - def setAutomaticTemperatureControlSetting(self, setting): + async def setAutomaticTemperatureControlSetting(self, setting): self.setMessage(0xB1, setting) - def getOnTimerReservationSetting(self): + async def getOnTimerReservationSetting(self): return self.getMessage(0x90) - def setOnTimerReservationSetting(self, setting): + async def setOnTimerReservationSetting(self, setting): self.setMessage(0x90, setting) - def getOnTimerSettingValue(self): + async def getOnTimerSettingValue(self): return self.getMessage(0x91) - def setOnTimerSettingValue(self, value): + async def setOnTimerSettingValue(self, value): self.setMessage(0x91, value) - def getOnTimerSettingRelativeTime(self): + async def getOnTimerSettingRelativeTime(self): return self.getMessage(0x92) - def setOnTimerSettingRelativeTime(self, value): + async def setOnTimerSettingRelativeTime(self, value): self.setMessage(0x92, value) - def getOffTimerReservationSetting(self): + async def getOffTimerReservationSetting(self): return self.getMessage(0x94) - def setOffTimerReservationSetting(self, setting): + async def setOffTimerReservationSetting(self, setting): self.setMessage(0x94, setting) - def getOffTimerSettingValue(self): + async def getOffTimerSettingValue(self): return self.getMessage(0x95) - def setOffTimerSettingValue(self, value): + async def setOffTimerSettingValue(self, value): self.setMessage(0x95, value) - def getOffTimerSettingRelativeTime(self): + async def getOffTimerSettingRelativeTime(self): return self.getMessage(0x96) - def setOffTimerSettingRelativeTime(self, value): + async def setOffTimerSettingRelativeTime(self, value): self.setMessage(0x96, value) - def getExtensionalOperationSetting(self): + async def getExtensionalOperationSetting(self): return self.getMessage(0xC0) - def setExtensionalOperationSetting(self, setting): + async def setExtensionalOperationSetting(self, setting): self.setMessage(0xC0, setting) - def getExtensionalOperationTimerTimeSettingValue(self): + async def getExtensionalOperationTimerTimeSettingValue(self): return self.getMessage(0xC1) - def setExtensionalOperationTimerTimeSettingValue(self, value): + async def setExtensionalOperationTimerTimeSettingValue(self, value): self.setMessage(0xC1, value) - def getIonEmissionSetting(self): + async def getIonEmissionSetting(self): return self.getMessage(0xC2) - def setIonEmissionSetting(self, setting): + async def setIonEmissionSetting(self, setting): self.setMessage(0xC2, setting) - def getImplementedIonEmissionMethod(self): + async def getImplementedIonEmissionMethod(self): return self.getMessage(0xC3) - def getOilAmountLevel(self): + async def getOilAmountLevel(self): return self.getMessage(0xC4) - diff --git a/pychonet/FloorHeater.py b/pychonet/FloorHeater.py index 81c8182..1d778da 100644 --- a/pychonet/FloorHeater.py +++ b/pychonet/FloorHeater.py @@ -1,5 +1,5 @@ from pychonet.EchonetInstance import EchonetInstance -from pychonet.lib.epc_functions import _int, _hh_mm, _signed_int, _on_off +from pychonet.lib.epc_functions import DICT_41_ON_OFF, _int, _hh_mm, _signed_int class FloorHeater(EchonetInstance): @@ -9,20 +9,45 @@ class FloorHeater(EchonetInstance): EPC_FUNCTIONS = { 0xE0: _int, # "Temperature setting 1", 0xE1: _int, # "Temperature setting 2", - 0xD1: _int, # "The maximum settable level is the top step of temperature setting 2" + 0xD1: _int, # "Temperature setting 2 – Maximum settable level" 0xE2: _signed_int, # "Measured room temperature", 0xE3: _signed_int, # "Measured floor temperature", - 0xE4: _int, # "Zone change setting", - 0xE5: _int, # "Special operation setting", - 0xE6: _int, # "Daily timer setting", - # 0xE7: , # "Daily timer setting 1", - # 0xE8: , # "Daily timer setting 2", - 0x90: _on_off, # "ON timer reservation setting", + # 0xE4: _int, # "Zone change setting", Sets the target zone for control and gets the number of controllable zones b0–b7 is allocated to 0 to 7 Each bit 1: with control, 0: without control + 0xE5: [ + _int, + { + 0x41: "Normal", + 0x42: "Modest", + 0x43: "High power", + }, + ], # "Special operation setting", + 0xE6: [ + _int, + { + 0x40: "Timer OFF", + 0x41: "Timer 1", + 0x42: "Timer 2", + }, + ], # "Daily timer setting", + # 0xE7: , # "Daily timer setting 1", Set the time in the unit of 30 minutes, dividing 24 hours by 30 minutes and allocated to 6 bytes. Each bit 1: worked 0: stopped + # 0xE8: , # "Daily timer setting 2", Set the time in the unit of 30 minutes, dividing 24 hours by 30 minutes and allocated to 6 bytes. Each bit 1: worked 0: stopped + 0x90: [_int, DICT_41_ON_OFF], # "ON timer reservation setting", 0x91: _hh_mm, # "Time set by ON timer", 0x92: _hh_mm, # "Relative ON timer setting", - 0x94: _on_off, # "OFF timer reservation setting", + 0x94: [_int, DICT_41_ON_OFF], # "OFF timer reservation setting", 0x95: _hh_mm, # "Time set by OFF timer", 0x96: _hh_mm, # "Relative OFF timer setting", + 0x84: _signed_int, # "Measured instantaneous power consumption", + 0x85: _signed_int, # "Measured cumulative electric energy consumption", + 0xE9: _signed_int, # "Rated power consumption", + 0xEA: [ + _int, + { + 0x41: "Node unit", + 0x42: "Class unit", + 0x43: "Instance unit", + }, + ], # "Power consumption measurement method", } def __init__(self, host, api_connector=None, instance=0x1): diff --git a/pychonet/FuelCell.py b/pychonet/FuelCell.py index 245a6bd..f9f66ea 100644 --- a/pychonet/FuelCell.py +++ b/pychonet/FuelCell.py @@ -1,49 +1,76 @@ +from deprecated import deprecated from pychonet.EchonetInstance import EchonetInstance -from pychonet.lib.epc_functions import _int, _signed_int, _hh_mm +from pychonet.lib.epc_functions import DICT_41_ON_OFF, _int # ----- Fuel Cell ------- + +@deprecated(reason="Scheduled for removal.") def _027CCA(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "On", - 0x42: "Off"} - return values.get(op_mode, "Invalid setting") + return _int(edt, DICT_41_ON_OFF) + +@deprecated(reason="Scheduled for removal.") def _027CCB(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "Generating", - 0x42: "Stopped", - 0x43: "Starting", - 0x44: "Stopping", - 0x45: "Idling"} - return values.get(op_mode, "Invalid setting") + return _int( + edt, + { + 0x41: "Generating", + 0x42: "Stopped", + 0x43: "Starting", + 0x44: "Stopping", + 0x45: "Idling", + }, + ) + +@deprecated(reason="Scheduled for removal.") def _027CD0(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x01: "System interconnected (reverse power flow acceptable)", - 0x02: "Independent", - 0x03: " System interconnected (reverse power flow not acceptable)"} - return values.get(op_mode, "Invalid setting") + return _int( + edt, + { + 0x01: "System interconnected (reverse power flow acceptable)", + 0x02: "Independent", + 0x03: " System interconnected (reverse power flow not acceptable)", + }, + ) + class FuelCell(EchonetInstance): EPC_FUNCTIONS = { - 0xC1: _int, # Measured temperature of water in water heater - 0xC2: _int, # Rated power generation output - 0xC3: _int, # Heating value of hot water storage tank - 0xC4: _int, # Measured instantaneous power generation output - 0xC5: _int, # Measured cumulative power generation output - # set only 0xC6: # Cumulative power generation output reset setting - 0xC7: _int, # Measured instantaneous gas consumption - 0xC8: _int, # Measured cumulative gas consumption - # set only 0xC9: # Cumulative gas consumption reset setting - 0xCA: _027CCA, # Power generation setting - 0xCB: _027CCB, # Power generation status - 0xCC: _int, # Measured in-house instantaneous power consumption - 0xCD: _int, # Measured in-house cumulative power consumption - # set only 0xCE: # In-house cumulative power consumption reset - 0xD0: _027CD0, # System interconnected type - 0xE1: _int, # Measured remaining hot water amount - 0xE2: _int, # Tank capacity + 0xC1: _int, # Measured temperature of water in water heater + 0xC2: _int, # Rated power generation output + 0xC3: _int, # Heating value of hot water storage tank + 0xC4: _int, # Measured instantaneous power generation output + 0xC5: _int, # Measured cumulative power generation output + # set only 0xC6: # Cumulative power generation output reset setting + 0xC7: _int, # Measured instantaneous gas consumption + 0xC8: _int, # Measured cumulative gas consumption + # set only 0xC9: # Cumulative gas consumption reset setting + 0xCA: [_int, DICT_41_ON_OFF], # Power generation setting + 0xCB: [ + _int, + { + 0x41: "Generating", + 0x42: "Stopped", + 0x43: "Starting", + 0x44: "Stopping", + 0x45: "Idling", + }, + ], # Power generation status + 0xCC: _int, # Measured in-house instantaneous power consumption + 0xCD: _int, # Measured in-house cumulative power consumption + # set only 0xCE: # In-house cumulative power consumption reset + 0xD0: [ + _int, + { + 0x01: "System interconnected (reverse power flow acceptable)", + 0x02: "Independent", + 0x03: " System interconnected (reverse power flow not acceptable)", + }, + ], # System interconnected type + 0xE1: _int, # Measured remaining hot water amount + 0xE2: _int, # Tank capacity } def __init__(self, host, api_connector=None, instance=0x1): diff --git a/pychonet/GeneralLighting.py b/pychonet/GeneralLighting.py index 427fd7b..b8d2b59 100644 --- a/pychonet/GeneralLighting.py +++ b/pychonet/GeneralLighting.py @@ -1,4 +1,6 @@ +from deprecated import deprecated from pychonet.EchonetInstance import EchonetInstance +from pychonet.lib.epc_functions import _int ENL_STATUS = 0x80 ENL_BRIGHTNESS = 0xB0 @@ -7,47 +9,59 @@ # ----- General lighting class ------- +@deprecated(reason="Scheduled for removal.") def _0290B1(edt): - op_mode = int.from_bytes(edt, "big") - values = { - 0x40: "other", - 0x41: "incandescent_lamp_color", - 0x42: "white", - 0x43: "daylight_white", - 0x44: "daylight_color", - } - return values.get(op_mode, "invalid_setting") + return _int( + edt, + { + 0x40: "other", + 0x41: "incandescent_lamp_color", + 0x42: "white", + 0x43: "daylight_white", + 0x44: "daylight_color", + }, + ) # TODO - implemenet FUNCTIONS -# 0xB0: 'Illuminance level', -# 0xB2: 'Illuminance level step setting', -# 0xB3: 'Light color step setting', -# 0xB4: 'Maximum specifiable values', -# 0xB5: 'Maximum value of settable level for night lighting', -# 0xB6: 'Lighting mode setting', -# 0xB7: 'Illuminance level setting for main lighting', -# 0xB8: 'Illuminance level step setting for main lighting', -# 0xB9: 'Illuminance level setting for night lighting', -# 0xBA: 'Illuminance level step setting for night lighting', -# 0xBB: 'Light color setting for main lighting', -# 0xBC: 'Light color level step setting for main lighting', -# 0xBD: 'Light color setting for night lighting', -# 0xBE: 'Light color level step setting for night lighting', -# 0xBF: 'Lighting mode status in auto mode', -# 0xC0: 'RGB setting for color lighting', -# 0x90: 'ON timer reservation setting', -# 0x91: 'ON timer setting', -# 0x94: 'OFF timer reservation setting', -# 0x95: 'OFF timer setting' +# 0xB0: 'Illuminance level', +# 0xB2: 'Illuminance level step setting', +# 0xB3: 'Light color step setting', +# 0xB4: 'Maximum specifiable values', +# 0xB5: 'Maximum value of settable level for night lighting', +# 0xB6: 'Lighting mode setting', +# 0xB7: 'Illuminance level setting for main lighting', +# 0xB8: 'Illuminance level step setting for main lighting', +# 0xB9: 'Illuminance level setting for night lighting', +# 0xBA: 'Illuminance level step setting for night lighting', +# 0xBB: 'Light color setting for main lighting', +# 0xBC: 'Light color level step setting for main lighting', +# 0xBD: 'Light color setting for night lighting', +# 0xBE: 'Light color level step setting for night lighting', +# 0xBF: 'Lighting mode status in auto mode', +# 0xC0: 'RGB setting for color lighting', +# 0x90: 'ON timer reservation setting', +# 0x91: 'ON timer setting', +# 0x94: 'OFF timer reservation setting', +# 0x95: 'OFF timer setting' """Class for General Lighting Objects""" class GeneralLighting(EchonetInstance): - - EPC_FUNCTIONS = {0xB1: _0290B1} + EPC_FUNCTIONS = { + 0xB1: [ + _int, + { + 0x40: "other", + 0x41: "incandescent_lamp_color", + 0x42: "white", + 0x43: "daylight_white", + 0x44: "daylight_color", + }, + ], + } def __init__(self, host, api_connector=None, instance=0x1): self._eojgc = 0x02 # Housing/facility-related device group diff --git a/pychonet/HomeAirCleaner.py b/pychonet/HomeAirCleaner.py index c60ac44..2cc30fb 100644 --- a/pychonet/HomeAirCleaner.py +++ b/pychonet/HomeAirCleaner.py @@ -1,80 +1,65 @@ +from deprecated import deprecated from pychonet.EchonetInstance import EchonetInstance +from pychonet.lib.epc_functions import ( + DICT_41_AUTO_8_SPEEDS, + DICT_41_ON_OFF, + DICT_41_YES_NO, + _int, + _swap_dict, +) -FAN_SPEED = { - "auto": 0x41, - "minimum": 0x31, - "low": 0x32, - "medium-low": 0x33, - "medium": 0x34, - "medium-high": 0x35, - "high": 0x36, - "very-high": 0x37, - "max": 0x38, -} +FAN_SPEED = _swap_dict(DICT_41_AUTO_8_SPEEDS) -PHOTOCATALYST_STATUS = {"yes": 0x41, "no": 0x42} +PHOTOCATALYST_STATUS = _swap_dict(DICT_41_YES_NO) # ----- Air Cleaner Class ------- # filter change status notify +@deprecated(reason="Scheduled for removal.") def _0135E1(edt): - op_mode = int.from_bytes(edt, "big") - values = { - 0x41: "yes", - 0x42: "no", - } - return values.get(op_mode, "invalid_setting") + return _int(edt, DICT_41_YES_NO) # air volume 0x41 for auto +@deprecated(reason="Scheduled for removal.") def _0135A0(edt): - op_mode = int.from_bytes(edt, "big") - values = { - 0x41: "auto", - 0x31: "minimum", - 0x32: "low", - 0x33: "medium-low", - 0x34: "medium", - 0x35: "medium-high", - 0x36: "high", - 0x37: "very-high", - 0x38: "max", - } - return values.get(op_mode, "invalid_setting") + return _int(edt, DICT_41_AUTO_8_SPEEDS) # cigarette sensor status +@deprecated(reason="Scheduled for removal.") def _0135C1(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "yes", 0x42: "no"} - return values.get(op_mode, "invalid_setting") + return _int(edt, DICT_41_ON_OFF) # Photocatalyst setting +@deprecated(reason="Scheduled for removal.") def _0135C2(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "on", 0x42: "off"} - return values.get(op_mode, "invalid_setting") + return _int(edt, DICT_41_ON_OFF) # air pollution status +@deprecated(reason="Scheduled for removal.") def _0135C0(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "pollution", 0x42: "fresh"} - return values.get(op_mode, "invalid_setting") + return _int(edt, {0x41: "pollution", 0x42: "fresh"}) """Class for Air Cleaner Objects""" class HomeAirCleaner(EchonetInstance): - EPC_FUNCTIONS = { - 0xE1: _0135E1, - 0xA0: _0135A0, - 0xC0: _0135C0, - 0xC1: _0135C1, - 0xC2: _0135C1, + 0xE1: [_int, DICT_41_YES_NO], + 0xA0: [_int, DICT_41_AUTO_8_SPEEDS], + 0xC0: [ + _int, + { + 0x41: "pollution", + 0x42: "fresh", + }, + ], + 0xC1: [_int, DICT_41_YES_NO], + 0xC2: [_int, DICT_41_ON_OFF], } def __init__(self, host, api_connector=None, instance=0x1): diff --git a/pychonet/HomeAirConditioner.py b/pychonet/HomeAirConditioner.py index 14776a2..4c0ad27 100644 --- a/pychonet/HomeAirConditioner.py +++ b/pychonet/HomeAirConditioner.py @@ -1,5 +1,11 @@ +from deprecated import deprecated from pychonet.EchonetInstance import EchonetInstance -from pychonet.lib.epc_functions import _int, _signed_int +from pychonet.lib.epc_functions import ( + DICT_41_AUTO_8_SPEEDS, + _int, + _signed_int, + _swap_dict, +) MODES = { "auto": 0x41, @@ -10,24 +16,11 @@ "other": 0x40, "off": 0xFF, } +DICT_41_MODES = _swap_dict(MODES) -FAN_SPEED = { - "auto": 0x41, - "minimum": 0x31, - "low": 0x32, - "medium-low": 0x33, - "medium": 0x34, - "medium-high": 0x35, - "high": 0x36, - "very-high": 0x37, - "max": 0x38, -} +FAN_SPEED = _swap_dict(DICT_41_AUTO_8_SPEEDS) -SILENT_MODE = { - "normal": 0x41, - "high-speed": 0x42, - "silent": 0x43 -} +SILENT_MODE = {"normal": 0x41, "high-speed": 0x42, "silent": 0x43} AIRFLOW_HORIZ = { "rc-right": 0x41, @@ -88,126 +81,175 @@ # ----- Home Air conditioner functions ------- +@deprecated(reason="Scheduled for removal.") def _0130A0(edt): - op_mode = int.from_bytes(edt, "big") - values = { - 0x41: "auto", - 0x31: "minimum", - 0x32: "low", - 0x33: "medium-low", - 0x34: "medium", - 0x35: "medium-high", - 0x36: "high", - 0x37: "very-high", - 0x38: "max", - } - return values.get(op_mode, "Invalid setting") + return _int(edt, DICT_41_AUTO_8_SPEEDS) # Automatic control of air flow direction setting +@deprecated(reason="Scheduled for removal.") def _0130A1(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "auto", 0x42: "non-auto", 0x43: "auto-vert", 0x44: "auto-horiz"} - return values.get(op_mode, "Invalid setting") + return _int( + edt, {0x41: "auto", 0x42: "non-auto", 0x43: "auto-vert", 0x44: "auto-horiz"} + ) +@deprecated(reason="Scheduled for removal.") def _0130AA(edt): - op_mode = int.from_bytes(edt, "big") - values = { - 0x40: "Normal operation", - 0x41: "Defrosting", - 0x42: "Preheating", - 0x43: "Heat removal", - } - return values.get(op_mode, "invalid_setting") + return _int( + edt, + { + 0x40: "Normal operation", + 0x41: "Defrosting", + 0x42: "Preheating", + 0x43: "Heat removal", + }, + ) # Automatic swing of air flow direction setting +@deprecated(reason="Scheduled for removal.") def _0130A3(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x31: "not-used", 0x41: "vert", 0x42: "horiz", 0x43: "vert-horiz"} - return values.get(op_mode, "invalid_setting") + return _int( + edt, {0x31: "not-used", 0x41: "vert", 0x42: "horiz", 0x43: "vert-horiz"} + ) # Air flow direction (vertical) setting +@deprecated(reason="Scheduled for removal.") def _0130A4(edt): - op_mode = int.from_bytes(edt, "big") - values = { - 0x41: "upper", - 0x44: "upper-central", - 0x43: "central", - 0x45: "lower-central", - 0x42: "lower", - } - return values.get(op_mode, "invalid_setting") + return _int( + edt, + { + 0x41: "upper", + 0x44: "upper-central", + 0x43: "central", + 0x45: "lower-central", + 0x42: "lower", + }, + ) # Air flow direction (horiziontal) setting +@deprecated(reason="Scheduled for removal.") def _0130A5(edt): # complies with version 2.01 Release a (page 3-88) - op_mode = int.from_bytes(edt, "big") - values = { - 0x41: "rc-right", - 0x42: "left-lc", - 0x43: "lc-center-rc", - 0x44: "left-lc-rc-right", - 0x51: "right", - 0x52: "rc", - 0x54: "center", - 0x55: "center-right", - 0x56: "center-rc", - 0x57: "center-rc-right", - 0x58: "lc", - 0x59: "lc-right", - 0x5A: "lc-rc", - 0x60: "left", - 0x61: "left-right", - 0x62: "left-rc", - 0x63: "left-rc-right", - 0x64: "left-center", - 0x65: "left-center-right", - 0x66: "left-center-rc", - 0x67: "left-center-rc-right", - 0x69: "left-lc-right", - 0x6A: "left-lc-rc", - } - return values.get(op_mode, "invalid_setting") + return _int( + edt, + { + 0x41: "rc-right", + 0x42: "left-lc", + 0x43: "lc-center-rc", + 0x44: "left-lc-rc-right", + 0x51: "right", + 0x52: "rc", + 0x54: "center", + 0x55: "center-right", + 0x56: "center-rc", + 0x57: "center-rc-right", + 0x58: "lc", + 0x59: "lc-right", + 0x5A: "lc-rc", + 0x60: "left", + 0x61: "left-right", + 0x62: "left-rc", + 0x63: "left-rc-right", + 0x64: "left-center", + 0x65: "left-center-right", + 0x66: "left-center-rc", + 0x67: "left-center-rc-right", + 0x69: "left-lc-right", + 0x6A: "left-lc-rc", + }, + ) # Operation mode +@deprecated(reason="Scheduled for removal.") def _0130B0(edt): - op_mode = int.from_bytes(edt, "big") - values = { - 0x41: "auto", - 0x42: "cool", - 0x43: "heat", - 0x44: "dry", - 0x45: "fan_only", - 0x40: "other", - } - return values.get(op_mode, "invalid_setting") + return _int(edt, DICT_41_MODES) + # Silent mode +@deprecated(reason="Scheduled for removal.") def _0130B2(edt): - op_mode = int.from_bytes(edt, "big") - values = { - 0x41: "normal", - 0x42: "high-speed", - 0x43: "silent", - } - return values.get(op_mode, "invalid_setting") + return _int( + edt, + { + 0x41: "normal", + 0x42: "high-speed", + 0x43: "silent", + }, + ) -class HomeAirConditioner(EchonetInstance): +class HomeAirConditioner(EchonetInstance): EPC_FUNCTIONS = { - 0xA0: _0130A0, - 0xA1: _0130A1, - 0xA3: _0130A3, - 0xA4: _0130A4, - 0xA5: _0130A5, - 0xAA: _0130AA, - 0xB0: _0130B0, - 0xB2: _0130B2, + 0xA0: [_int, DICT_41_AUTO_8_SPEEDS], + 0xA1: [ + _int, + {0x41: "auto", 0x42: "non-auto", 0x43: "auto-vert", 0x44: "auto-horiz"}, + ], + 0xA3: [ + _int, + {0x31: "not-used", 0x41: "vert", 0x42: "horiz", 0x43: "vert-horiz"}, + ], + 0xA4: [ + _int, + { + 0x41: "upper", + 0x44: "upper-central", + 0x43: "central", + 0x45: "lower-central", + 0x42: "lower", + }, + ], + 0xA5: [ + _int, + { + 0x41: "rc-right", + 0x42: "left-lc", + 0x43: "lc-center-rc", + 0x44: "left-lc-rc-right", + 0x51: "right", + 0x52: "rc", + 0x54: "center", + 0x55: "center-right", + 0x56: "center-rc", + 0x57: "center-rc-right", + 0x58: "lc", + 0x59: "lc-right", + 0x5A: "lc-rc", + 0x60: "left", + 0x61: "left-right", + 0x62: "left-rc", + 0x63: "left-rc-right", + 0x64: "left-center", + 0x65: "left-center-right", + 0x66: "left-center-rc", + 0x67: "left-center-rc-right", + 0x69: "left-lc-right", + 0x6A: "left-lc-rc", + }, + ], + 0xAA: [ + _int, + { + 0x40: "Normal operation", + 0x41: "Defrosting", + 0x42: "Preheating", + 0x43: "Heat removal", + }, + ], + 0xB0: [_int, DICT_41_MODES], + 0xB2: [ + _int, + { + 0x41: "normal", + 0x42: "high-speed", + 0x43: "silent", + }, + ], 0xBA: _int, 0xB3: _signed_int, 0xB4: _signed_int, @@ -236,8 +278,8 @@ def __init__(self, host, api_connector=None, instance=0x1): return: A integer representing the configured temperature. """ - def getOperationalTemperature(self): - return self.getMessage(ENL_HVAC_SET_TEMP) + async def getOperationalTemperature(self): + return await self.getMessage(ENL_HVAC_SET_TEMP) """ getOperationalHumidity get the humidity that has been set in the HVAC @@ -245,8 +287,8 @@ def getOperationalTemperature(self): return: A integer representing the configured humidity. """ - def getOperationalHumidity(self): - return self.getMessage(ENL_HVAC_SET_HUMIDITY) + async def getOperationalHumidity(self): + return await self.getMessage(ENL_HVAC_SET_HUMIDITY) """ getRoomHumidity get the HVAC's room humidity. @@ -254,8 +296,8 @@ def getOperationalHumidity(self): return: A integer representing the room humidity. """ - def getRoomHumidity(self): - return self.getMessage(ENL_HVAC_ROOM_HUMIDITY) + async def getRoomHumidity(self): + return await self.getMessage(ENL_HVAC_ROOM_HUMIDITY) """ getRoomTemperature get the HVAC's room temperature. @@ -263,8 +305,8 @@ def getRoomHumidity(self): return: A integer representing the room temperature. """ - def getRoomTemperature(self): - return self.getMessage(ENL_HVAC_ROOM_TEMP) + async def getRoomTemperature(self): + return await self.getMessage(ENL_HVAC_ROOM_TEMP) """ getOutdoorTemperature get the outdoor temperature that has been set in the HVAC @@ -272,8 +314,8 @@ def getRoomTemperature(self): return: An integer representing the configured outdoor temperature. """ - def getOutdoorTemperature(self): - return self.getMessage(ENL_HVAC_OUT_TEMP) + async def getOutdoorTemperature(self): + return await self.getMessage(ENL_HVAC_OUT_TEMP) """ setOperationalTemperature get the temperature that has been set in the HVAC @@ -281,8 +323,8 @@ def getOutdoorTemperature(self): param temperature: A integer representing the desired temperature. """ - def setOperationalTemperature(self, temperature): - return self.setMessage(ENL_HVAC_SET_TEMP, int(temperature)) + async def setOperationalTemperature(self, temperature): + return await self.setMessage(ENL_HVAC_SET_TEMP, int(temperature)) """ setOperationalHumidity get the temperature that has been set in the HVAC @@ -290,13 +332,13 @@ def setOperationalTemperature(self, temperature): param humidity: A integer representing the desired humidity. """ - def setOperationalHumidity(self, humidity): - return self.setMessage(ENL_HVAC_SET_HUMIDITY, int(humidity)) + async def setOperationalHumidity(self, humidity): + return await self.setMessage(ENL_HVAC_SET_HUMIDITY, int(humidity)) - def setHeaterHumidifier(self, state, humidity): + async def setHeaterHumidifier(self, state, humidity): if not state: - return self.setMessage(ENL_HVAC_HUMIDIFIER_STATE, 0x42) - return self.setMessages( + return await self.setMessage(ENL_HVAC_HUMIDIFIER_STATE, 0x42) + return await self.setMessages( [ {"EPC": ENL_HVAC_HUMIDIFIER_STATE, "PDC": 0x01, "EDT": 0x41}, {"EPC": ENL_HVAC_HUMIDIFIER_VALUE, "PDC": 0x01, "EDT": humidity}, @@ -309,8 +351,8 @@ def setHeaterHumidifier(self, state, humidity): return: A string representing the configured mode. """ - def getMode(self): - return self.getMessage(ENL_HVAC_MODE) + async def getMode(self): + return await self.getMessage(ENL_HVAC_MODE) """ setMode set the desired mode (e.g Heating, Cooling, Fan etc) @@ -320,10 +362,10 @@ def getMode(self): param mode: A string representing the desired mode. """ - def setMode(self, mode): + async def setMode(self, mode): if mode == "off": - return self.setMessage(ENL_STATUS, 0x31) - return self.setMessages( + return await self.setMessage(ENL_STATUS, 0x31) + return await self.setMessages( [ {"EPC": ENL_STATUS, "PDC": 0x01, "EDT": 0x30}, {"EPC": ENL_HVAC_MODE, "PDC": 0x01, "EDT": MODES[mode]}, @@ -337,8 +379,8 @@ def setMode(self, mode): return: A string representing the fan speed """ - def getFanSpeed(self): # 0xA0 - return self.getMessage(ENL_FANSPEED) + async def getFanSpeed(self): # 0xA0 + return await self.getMessage(ENL_FANSPEED) """ setFanSpeed set the desired fan speed (e.g Low, Medium, High etc) @@ -346,8 +388,8 @@ def getFanSpeed(self): # 0xA0 param fans_speed: A string representing the fan speed """ - def setFanSpeed(self, fan_speed): - return self.setMessage(ENL_FANSPEED, FAN_SPEED[fan_speed]) + async def setFanSpeed(self, fan_speed): + return await self.setMessage(ENL_FANSPEED, FAN_SPEED[fan_speed]) """ setSwingMode sets the automatic swing mode function @@ -356,8 +398,8 @@ def setFanSpeed(self, fan_speed): e.g: 'not-used', 'vert', 'horiz', 'vert-horiz' """ - def setSwingMode(self, swing_mode): - return self.setMessage(ENL_SWING_MODE, SWING_MODE[swing_mode]) + async def setSwingMode(self, swing_mode): + return await self.setMessage(ENL_SWING_MODE, SWING_MODE[swing_mode]) """ getSwingMode gets the swing mode that has been set in the HVAC @@ -365,8 +407,8 @@ def setSwingMode(self, swing_mode): return: A string representing the configured swing mode. """ - def getSwingMode(self): # 0xA3 - return self.getMessage(ENL_SWING_MODE) + async def getSwingMode(self): # 0xA3 + return await self.getMessage(ENL_SWING_MODE) """ setAutoDirection sets the automatic direction mode function @@ -375,8 +417,8 @@ def getSwingMode(self): # 0xA3 e.g: 'auto', 'non-auto', 'auto-horiz', 'auto-vert' """ - def setAutoDirection(self, auto_direction): - return self.setMessage(ENL_AUTO_DIRECTION, AUTO_DIRECTION[auto_direction]) + async def setAutoDirection(self, auto_direction): + return await self.setMessage(ENL_AUTO_DIRECTION, AUTO_DIRECTION[auto_direction]) """ getAutoDirection get the direction mode that has been set in the HVAC @@ -384,8 +426,8 @@ def setAutoDirection(self, auto_direction): return: A string representing the configured temperature. """ - def getAutoDirection(self): # 0xA1 - return self.getMessage(ENL_AUTO_DIRECTION) + async def getAutoDirection(self): # 0xA1 + return await self.getMessage(ENL_AUTO_DIRECTION) """ setAirflowVert sets the vertical vane setting @@ -395,8 +437,8 @@ def getAutoDirection(self): # 0xA1 'lower-central', 'lower' """ - def setAirflowVert(self, airflow_vert): - return self.setMessage(ENL_AIR_VERT, AIRFLOW_VERT[airflow_vert]) + async def setAirflowVert(self, airflow_vert): + return await self.setMessage(ENL_AIR_VERT, AIRFLOW_VERT[airflow_vert]) """ getAirflowVert get the vertical vane setting that has been set in the HVAC @@ -404,8 +446,8 @@ def setAirflowVert(self, airflow_vert): return: A string representing vertical airflow setting """ - def getAirflowVert(self): # 0xA4 - return self.getMessage(ENL_AIR_VERT) + async def getAirflowVert(self): # 0xA4 + return await self.getMessage(ENL_AIR_VERT) """ setAirflowHoriz sets the horizontal vane setting @@ -414,8 +456,8 @@ def getAirflowVert(self): # 0xA4 e.g: 'left', 'lc', 'center', 'rc', 'right' """ - def setAirflowHoriz(self, airflow_horiz): - return self.setMessage(ENL_AIR_HORZ, AIRFLOW_HORIZ[airflow_horiz]) + async def setAirflowHoriz(self, airflow_horiz): + return await self.setMessage(ENL_AIR_HORZ, AIRFLOW_HORIZ[airflow_horiz]) """ getAirflowHoriz get the horizontal vane setting that has been set in the HVAC @@ -423,8 +465,8 @@ def setAirflowHoriz(self, airflow_horiz): return: A string representing vertical airflow setting e.g: 'left', 'lc', 'center', 'rc', 'right' """ - def getAirflowHoriz(self): # 0xA5 - return self.getMessage(ENL_AIR_HORZ) + async def getAirflowHoriz(self): # 0xA5 + return await self.getMessage(ENL_AIR_HORZ) """ setFanMode sets the Fan normal/high-speed/silent operation @@ -433,8 +475,8 @@ def getAirflowHoriz(self): # 0xA5 e.g: 'normal', 'high-speed', 'silent' """ - def setSilentMode(self, mode): # 0xB2 - return self.setMessage(ENL_HVAC_SILENT_MODE, SILENT_MODE[mode]) + async def setSilentMode(self, mode): # 0xB2 + return await self.setMessage(ENL_HVAC_SILENT_MODE, SILENT_MODE[mode]) """ getFanMode get the Fan normal/high-speed/silent operation @@ -442,5 +484,5 @@ def setSilentMode(self, mode): # 0xB2 return: A string representing airflow mode setting e.g: 'normal', 'high-speed', 'silent' """ - def getSilentMode(self): # 0xB2 - return self.getMessage(ENL_HVAC_SILENT_MODE) + async def getSilentMode(self): # 0xB2 + return await self.getMessage(ENL_HVAC_SILENT_MODE) diff --git a/pychonet/HomeSolarPower.py b/pychonet/HomeSolarPower.py index 26be9aa..2e443d0 100644 --- a/pychonet/HomeSolarPower.py +++ b/pychonet/HomeSolarPower.py @@ -1,29 +1,58 @@ +from deprecated import deprecated from pychonet.EchonetInstance import EchonetInstance from pychonet.lib.epc_functions import _int, _signed_int + # 0xD0 System-interconnected type +@deprecated(reason="Scheduled for removal.") def _0279D0(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x00: "System interconnected (reverse power flow acceptable)", - 0x01: "Independent", - 0x02: "System interconnected (reverse power flow not acceptable)", - 0x03: "Unknown"} - return values.get(op_mode, "Invalid setting") + return _int( + edt, + { + 0x00: "System interconnected (reverse power flow acceptable)", + 0x01: "Independent", + 0x02: "System interconnected (reverse power flow not acceptable)", + 0x03: "Unknown", + }, + ) + # 0xD1 Output power restraint status +@deprecated(reason="Scheduled for removal.") def _0279D1(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "Ongoing restraint (output power control)", - 0x42: "Ongoing restraint (except output power control)", - 0x43: "Ongoing restraint (reason for restraint unknown)", - 0x44: "Not restraining", - 0x45: "Unknown"} - return values.get(op_mode, "Invalid setting") + return _int( + edt, + { + 0x41: "Ongoing restraint (output power control)", + 0x42: "Ongoing restraint (except output power control)", + 0x43: "Ongoing restraint (reason for restraint unknown)", + 0x44: "Not restraining", + 0x45: "Unknown", + }, + ) + class HomeSolarPower(EchonetInstance): EPC_FUNCTIONS = { - 0xD0: _0279D0, - 0xD1: _0279D1, + 0xD0: [ + _int, + { + 0x00: "System interconnected (reverse power flow acceptable)", + 0x01: "Independent", + 0x02: "System interconnected (reverse power flow not acceptable)", + 0x03: "Unknown", + }, + ], + 0xD1: [ + _int, + { + 0x41: "Ongoing restraint (output power control)", + 0x42: "Ongoing restraint (except output power control)", + 0x43: "Ongoing restraint (reason for restraint unknown)", + 0x44: "Not restraining", + 0x45: "Unknown", + }, + ], 0xE0: _int, 0xE1: _int, 0xE2: _int, @@ -33,7 +62,7 @@ class HomeSolarPower(EchonetInstance): 0xE6: _int, 0xE7: _int, 0xE8: _int, - 0xE9: _int + 0xE9: _int, } def __init__(self, host, api_connector, instance=0x1): diff --git a/pychonet/HotWaterGenerator.py b/pychonet/HotWaterGenerator.py index bc21c08..488933a 100644 --- a/pychonet/HotWaterGenerator.py +++ b/pychonet/HotWaterGenerator.py @@ -1,94 +1,153 @@ +from deprecated import deprecated from pychonet.EchonetInstance import EchonetInstance -from pychonet.lib.epc_functions import _int, _signed_int, _hh_mm +from pychonet.lib.epc_functions import ( + DICT_30_ON_OFF, + DICT_41_HEATING_NOT_HEATING, + DICT_41_ON_OFF, + _int, + _hh_mm, +) # ----- Hot Water Generator ------- + +@deprecated(reason="Scheduled for removal.") def _0272D0E2(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "Heating", - 0x42: "Not Heating"} - return values.get(op_mode, "Invalid setting") + return _int(edt, DICT_41_HEATING_NOT_HEATING) + +@deprecated(reason="Scheduled for removal.") def _0272D2(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "Hot water warmer operation", - 0x42: "Hot water warmer operation resetting"} - return values.get(op_mode, "Invalid setting") + return _int( + edt, + { + 0x41: "Hot water warmer operation", + 0x42: "Hot water warmer operation resetting", + }, + ) + +@deprecated(reason="Scheduled for removal.") def _0272EX(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "On", - 0x42: "Off"} - return values.get(op_mode, "Invalid setting") + return _int(edt, DICT_41_ON_OFF) + +@deprecated(reason="Scheduled for removal.") def _0272D7(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x30: "On", - 0x31: "Off"} - return values.get(op_mode, "Invalid setting") + return _int(edt, DICT_30_ON_OFF) + +@deprecated(reason="Scheduled for removal.") def _0272E8(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x31: "Level 1", - 0x32: "Level 2", - 0x33: "Level 3", - 0x34: "Level 4", - 0x35: "Level 5", - 0x36: "Level 6", - 0x37: "Level 7", - 0x38: "Level 8"} - return values.get(op_mode, "Invalid setting") - -def _0272DA(edt): # Duration of automatic operation setting - if edt == 0xffff: + return _int( + edt, + { + 0x31: "Level 1", + 0x32: "Level 2", + 0x33: "Level 3", + 0x34: "Level 4", + 0x35: "Level 5", + 0x36: "Level 6", + 0x37: "Level 7", + 0x38: "Level 8", + }, + ) + + +def _0272DA(edt): # Duration of automatic operation setting + if edt == 0xFFFF: return "Limitless" hh = int.from_bytes(edt[0:1], "big") mm = str(int.from_bytes(edt[1:2], "big")).zfill(2) return f"{hh}:{mm}" -def _0272DB(edt): # Remaining automatic operation time - if edt == 0xffff: + +def _0272DB(edt): # Remaining automatic operation time + if edt == 0xFFFF: return "Infinite" hh = int.from_bytes(edt[0:1], "big") mm = str(int.from_bytes(edt[1:2], "big")).zfill(2) return f"{hh}:{mm}" -def _0272EF(edt): # "Bath operation status monitor", - op_mode = int.from_bytes(edt, "big") - values = {0x41: "Supplying Hot Water", - 0x43: "Keeping Bath Temperature", - 0x42: "Stopped"} - return values.get(op_mode, "Invalid setting") + +@deprecated(reason="Scheduled for removal.") +def _0272EF(edt): # "Bath operation status monitor", + return _int( + edt, + { + 0x41: "Supplying Hot Water", + 0x43: "Keeping Bath Temperature", + 0x42: "Stopped", + }, + ) + class HotWaterGenerator(EchonetInstance): EPC_FUNCTIONS = { - 0xD0: _0272D0E2, # Hot water heating status - 0xD1: _int, # Set value of hot water temperature - 0xD2: _0272D2, # Hot water warmer setting - 0xDA: _0272DA, # Duration of automatic operation setting - 0xDB: _0272DB, # Remaining automatic operation time - 0xE1: _int, # Set value of bath of the bath temperature in degrees C - 0xE2: _0272D0E2, # Bath water heater status - 0xE3: _0272EX, # Bath automatic mode setting - 0xE4: _0272EX, # Bath additional boil-up operation setting - 0xE5: _0272EX, # Bath adding hot water operation setting - 0xE6: _0272EX, # Bath water temperature lowering operation setting - 0xE7: _int, # Bath hot water volume setting 1 - 0xE8: _0272E8, # Bath hot water volume setting 2 - 0xEE: _int, # Bath hot water volume setting 3 - 0xD4: _int, # Bath hot water volume setting 4 - 0xD5: _int, # Bath hot water volume setting 4 - Maximum settable level - 0xE9: _0272EX, # "Bathroom priority setting", - 0xEA: _0272EX, # "Shower hot water supply status", - 0xEB: _0272EX, # "Kitchen hot water supply status", - 0xEC: _0272EX, # "Hot water warmer ON timer reservation setting", - 0xED: _hh_mm, # "Set value of hot water warmer ON timer time", - 0xEF: _0272EF, # "Bath operation status monitor", - 0x90: _0272EX, # "ON timer reservation setting", - 0x91: _hh_mm, # "Set value of ON timer time", - 0x92: _hh_mm, # "Set value of ON timer relative time", - 0xD6: _int, # "Volume setting", - 0xD7: _0272D7 # "Mute setting", + 0xD0: [ + _int, + DICT_41_HEATING_NOT_HEATING, + ], # Hot water heating status + 0xD1: _int, # Set value of hot water temperature + 0xD2: [ + _int, + { + 0x41: "Hot water warmer operation", + 0x42: "Hot water warmer operation resetting", + }, + ], # Hot water warmer setting + 0xDA: _0272DA, # Duration of automatic operation setting + 0xDB: _0272DB, # Remaining automatic operation time + 0xE1: _int, # Set value of bath of the bath temperature in degrees C + 0xE2: [ + _int, + DICT_41_HEATING_NOT_HEATING, + ], # Bath water heater status + 0xE3: [_int, DICT_41_ON_OFF], # Bath automatic mode setting + 0xE4: [_int, DICT_41_ON_OFF], # Bath additional boil-up operation setting + 0xE5: [_int, DICT_41_ON_OFF], # Bath adding hot water operation setting + 0xE6: [ + _int, + DICT_41_ON_OFF, + ], # Bath water temperature lowering operation setting + 0xE7: _int, # Bath hot water volume setting 1 + 0xE8: [ + _int, + { + 0x31: "Level 1", + 0x32: "Level 2", + 0x33: "Level 3", + 0x34: "Level 4", + 0x35: "Level 5", + 0x36: "Level 6", + 0x37: "Level 7", + 0x38: "Level 8", + }, + ], # Bath hot water volume setting 2 + 0xEE: _int, # Bath hot water volume setting 3 + 0xD4: _int, # Bath hot water volume setting 4 + 0xD5: _int, # Bath hot water volume setting 4 - Maximum settable level + 0xE9: [_int, DICT_41_ON_OFF], # "Bathroom priority setting", + 0xEA: [_int, DICT_41_ON_OFF], # "Shower hot water supply status", + 0xEB: [_int, DICT_41_ON_OFF], # "Kitchen hot water supply status", + 0xEC: [ + _int, + DICT_41_ON_OFF, + ], # "Hot water warmer ON timer reservation setting", + 0xED: _hh_mm, # "Set value of hot water warmer ON timer time", + 0xEF: [ + _int, + { + 0x41: "Supplying Hot Water", + 0x43: "Keeping Bath Temperature", + 0x42: "Stopped", + }, + ], # "Bath operation status monitor", + 0x90: [_int, DICT_41_ON_OFF], # "ON timer reservation setting", + 0x91: _hh_mm, # "Set value of ON timer time", + 0x92: _hh_mm, # "Set value of ON timer relative time", + 0xD6: _int, # "Volume setting", + 0xD7: [_int, DICT_30_ON_OFF], # "Mute setting", } def __init__(self, host, api_connector=None, instance=0x1): diff --git a/pychonet/HybridWaterHeater.py b/pychonet/HybridWaterHeater.py index dc73b5c..f72e1ce 100644 --- a/pychonet/HybridWaterHeater.py +++ b/pychonet/HybridWaterHeater.py @@ -1,49 +1,54 @@ +from deprecated import deprecated from pychonet.EchonetInstance import EchonetInstance -from pychonet.lib.epc_functions import _int, _signed_int - +from pychonet.lib.epc_functions import DICT_41_HEATING_NOT_HEATING, _int, _signed_int # 0xB0 - Automatic water heating setting +@deprecated(reason="Scheduled for removal.") def _02A6B0(edt): - op_mode = int.from_bytes(edt, "big") - AUTOMATIC_WATER_HEATING_STATES = { - 0x41: "Automatic water heating", - 0x42: "Manual water heating", - 0x43: "Water heating manual stop", - } - return AUTOMATIC_WATER_HEATING_STATES.get(op_mode, "Invalid setting") + return _int( + edt, + { + 0x41: "Automatic water heating", + 0x42: "Manual water heating", + 0x43: "Water heating manual stop", + }, + ) + # 0xB2 - Water heating status # 0xB3 - Heater status +@deprecated(reason="Scheduled for removal.") def _02A6B2B3(edt): - op_mode = int.from_bytes(edt, "big") - WATER_HEATING_STATUS = { - 0x41: "Water is heating", - 0x42: "Water is not heating", - } - return WATER_HEATING_STATUS.get(op_mode, "Invalid setting") + return _int(edt, DICT_41_HEATING_NOT_HEATING) # 0xB6 - Hot water supply mode setting for auxiliary heat source machine # 0xB7 - Heater mode setting for auxiliary heat source machine +@deprecated(reason="Scheduled for removal.") def _02A6B6B7(edt): - op_mode = int.from_bytes(edt, "big") - AUX_SETTING_STATE = { - 0x41: "Set", - 0x42: "No setting", - } - return AUX_SETTING_STATE.get(op_mode, "Invalid setting") + return _int( + edt, + { + 0x41: "Set", + 0x42: "No setting", + }, + ) + # 0xB8 - Linkage mode setting for solar power generation +@deprecated(reason="Scheduled for removal.") def _02A6B8(edt): - op_mode = int.from_bytes(edt, "big") - SOLAR_POWER_LINKAGE = { - 0x41: "Mode off", - 0x42: "Household consumption", - 0x43: "Prioritizing electricity sales", - 0x44: "Economic efficiency" - } - return SOLAR_POWER_LINKAGE.get(op_mode, "Invalid setting") + return _int( + edt, + { + 0x41: "Mode off", + 0x42: "Household consumption", + 0x43: "Prioritizing electricity sales", + 0x44: "Economic efficiency", + }, + ) + # 0xB9 - Solar power generations utilization time def _02A6B9(edt): @@ -51,33 +56,70 @@ def _02A6B9(edt): start_mm = str(int.from_bytes(edt[1:2], "big")).zfill(2) end_hh = int.from_bytes(edt[2:3], "big") end_mm = str(int.from_bytes(edt[3:4], "big")).zfill(2) - return { "start_time": f"{start_hh}:{start_mm}", "end_time": f"{end_hh}:{end_mm}" } + return {"start_time": f"{start_hh}:{start_mm}", "end_time": f"{end_hh}:{end_mm}"} + # 0xC3 - Hot water supply status +@deprecated(reason="Scheduled for removal.") def _02A6C3(edt): - op_mode = int.from_bytes(edt, "big") - HOT_WATER_SUPPLY_STATUS = { - 0x41: "Supplying hot water", - 0x42: "Not supplying hot water", - } - return HOT_WATER_SUPPLY_STATUS.get(op_mode, "Invalid setting") + return _int( + edt, + { + 0x41: "Supplying Hot Water", + 0x42: "Stopped", + }, + ) + # 0xE1 - Measured amount of hot water remaining in tank # 0xE2 - Tank Capacity -class HybridWaterHeater(EchonetInstance): +class HybridWaterHeater(EchonetInstance): EPC_FUNCTIONS = { - 0xB0: _02A6B0, - 0xB2: _02A6B2B3, - 0xB3: _02A6B2B3, - 0xB6: _02A6B6B7, - 0xB7: _02A6B6B7, - 0xB8: _02A6B8, + 0xB0: [ + _int, + { + 0x41: "Automatic water heating", + 0x42: "Manual water heating", + 0x43: "Water heating manual stop", + }, + ], + 0xB2: [_int, DICT_41_HEATING_NOT_HEATING], + 0xB3: [_int, DICT_41_HEATING_NOT_HEATING], + 0xB6: [ + _int, + { + 0x41: "Set", + 0x42: "No setting", + }, + ], + 0xB7: [ + _int, + { + 0x41: "Set", + 0x42: "No setting", + }, + ], + 0xB8: [ + _int, + { + 0x41: "Mode off", + 0x42: "Household consumption", + 0x43: "Prioritizing electricity sales", + 0x44: "Economic efficiency", + }, + ], 0xB9: _02A6B9, - 0xC3: _02A6C3, + 0xC3: [ + _int, + { + 0x41: "Supplying Hot Water", + 0x42: "Stopped", + }, + ], 0xE1: _int, - 0xE2: _int + 0xE2: _int, } def __init__(self, host, api_connector=None, instance=0x1): diff --git a/pychonet/LowVoltageSmartElectricEnergyMeter.py b/pychonet/LowVoltageSmartElectricEnergyMeter.py index 06828d6..6a7ac8c 100644 --- a/pychonet/LowVoltageSmartElectricEnergyMeter.py +++ b/pychonet/LowVoltageSmartElectricEnergyMeter.py @@ -1,3 +1,4 @@ +from datetime import datetime from pychonet.EchonetInstance import EchonetInstance from pychonet.lib.epc_functions import _int, _signed_int @@ -9,29 +10,34 @@ ENL_LVSEEM_INSTANT_ENG = 0xE7 ENL_LVSEEM_INSTANT_CUR = 0xE8 + def _0288E0(edt): if len(edt) < 1: return None power_val = _int(edt) - return None if power_val == 4294967294 else power_val # no measurement + return None if power_val == 4294967294 else power_val # no measurement + def _0288E1(edt): - if len(edt) < 1: - return None - op_mode = _int(edt) - values = {0x00: 1, - 0x01: 0.1, - 0x02: 0.01, - 0x03: 0.001, - 0x04: 0.0001, - 0x0A: 10, - 0x0B: 100, - 0x0C: 1000, - 0x0D: 10000} - return values.get(op_mode, None) + return _int( + edt, + { + 0x00: 1, + 0x01: 0.1, + 0x02: 0.01, + 0x03: 0.001, + 0x04: 0.0001, + 0x0A: 10, + 0x0B: 100, + 0x0C: 1000, + 0x0D: 10000, + }, + None, + ) + def _0288E2(edt): - ''' + """ 1-2 bytes: day for which the historical data of measured cumulative amounts of electric @@ -43,30 +49,37 @@ def _0288E2(edt): (0–99,999,999) unsigned short + unsigned long × 48 - ''' + """ return "Not implemented" + def _0288E7(edt): if len(edt) < 1: return None power_val = _signed_int(edt) - as_None = power_val in [-2147483648, 2147483647, 2147483646] # underflow, overflow, no measurement + as_None = power_val in [ + -2147483648, + 2147483647, + 2147483646, + ] # underflow, overflow, no measurement return None if as_None else power_val + def _0288E8(edt): if len(edt) < 1: return {"r_phase_amperes": None, "t_phase_amperes": None} r_phase = float(_signed_int(edt[0:2])) / 10 # R Phase t_phase = float(_signed_int(edt[2:4])) / 10 # T Phase - asNone = [-3276.8, 3276.7, 3276.6] # underflow, overflow, no measurement + asNone = [-3276.8, 3276.7, 3276.6] # underflow, overflow, no measurement if r_phase in asNone: r_phase = None if t_phase in asNone: t_phase = None return {"r_phase_amperes": r_phase, "t_phase_amperes": t_phase} + def _0288EA(edt): - ''' + """ 1–4 bytes: date of measurement YYYY: 0x0001–0x270F (1–9999) @@ -86,8 +99,19 @@ def _0288EA(edt): unsigned char × 3 + unsigned long - ''' - return "Not implemented" + """ + year = int.from_bytes(edt[0:2], "big") + month = int.from_bytes(edt[2:3], "big") + day = int.from_bytes(edt[3:4], "big") + hour = int.from_bytes(edt[4:5], "big") + minute = int.from_bytes(edt[5:6], "big") + second = int.from_bytes(edt[6:7], "big") + culmative = int.from_bytes(edt[7:], "big") + return { + "time": datetime(year, month, day, hour, minute, second).isoformat(), + "culmative_value": culmative, + } + def _0288EC(edt): """ @@ -117,8 +141,9 @@ def _0288EC(edt): """ return "Not implemented" + def _0288ED(edt): - ''' + """ 1–6 bytes: date and time for which the historical data is to be retrieved YYYY: 0x0001–0x270F (1–9999) @@ -131,23 +156,38 @@ def _0288ED(edt): 0x01–0x0C (1–12) unsigned short + unsigned char × 4 + unsigned char - ''' + """ return "Not implemented" + class LowVoltageSmartElectricEnergyMeter(EchonetInstance): EPC_FUNCTIONS = { - 0xD3: _int, #"Coefficient" - 0xD7: _int, #"Number of effective digits for cumulative amounts of electric energy" - 0xE0: _0288E0, #"Measured cumulative amount of electric energy (normal direction)" - 0xE1: _0288E1, #"Unit for cumulative amounts of electric energy (normal and reverse directions)" + 0xD3: _int, # "Coefficient" + 0xD7: _int, # "Number of effective digits for cumulative amounts of electric energy" + 0xE0: _0288E0, # "Measured cumulative amount of electric energy (normal direction)" + 0xE1: [ + _int, + { + 0x00: 1, + 0x01: 0.1, + 0x02: 0.01, + 0x03: 0.001, + 0x04: 0.0001, + 0x0A: 10, + 0x0B: 100, + 0x0C: 1000, + 0x0D: 10000, + }, + None, + ], # "Unit for cumulative amounts of electric energy (normal and reverse directions)" # 0xE2: _0288E2, #"Historical data of measured cumulative amounts of electric energy 1 (normal direction)" - 0xE3: _0288E0, #"Measured cumulative amounts of electric energy (reverse direction)" + 0xE3: _0288E0, # "Measured cumulative amounts of electric energy (reverse direction)" # 0xE4: _0288E2, #"Historical data of measured cumulative amounts of electric energy 1 (reverse direction)" # 0xE5: _int, #"Day for which the historical data of measured cumulative amounts of electric energy is to be retrieved 1" - 0xE7: _0288E7, #"Measured instantaneous electric energy" - 0xE8: _0288E8, #"Measured instantaneous currents" - # 0xEA: _0288EA, #"Cumulative amounts of electric energy measured at fixed time (normal direction)" - # 0xEB: _0288EA, #"Cumulative amounts of electric energy measured at fixed time (reverse direction)" + 0xE7: _0288E7, # "Measured instantaneous electric energy" + 0xE8: _0288E8, # "Measured instantaneous currents" + # 0xEA: _0288EA, # "Cumulative amounts of electric energy measured at fixed time (normal direction)" + # 0xEB: _0288EA, # "Cumulative amounts of electric energy measured at fixed time (reverse direction)" # 0xEC: _0288EC, #"Historical data of measured cumulative amounts of electric energy 2 (normal and reverse directions)" # 0xED: _0288ED, #"Day for which the historical data of measured cumulative amounts of electric energy is to be retrieved 2" } diff --git a/pychonet/RiceCooker.py b/pychonet/RiceCooker.py index 3d4c4fe..528aaff 100644 --- a/pychonet/RiceCooker.py +++ b/pychonet/RiceCooker.py @@ -1,131 +1,86 @@ from pychonet.EchonetInstance import EchonetInstance -from pychonet.lib.epc_functions import _hh_mm - -@staticmethod -def _03BB80(payload): - return 'On' if payload == 0x30 else 'Off' - -@staticmethod -def _03BBB0(payload): - return 'Open' if payload == 0x30 else 'Closed' - -@staticmethod -def _03BBB1(payload): - if payload == 0x41: - return 'Rice cooking completed' - elif payload == 0x42: - return 'Rice cooking in progress' - elif payload == 0x43: - return 'Rice cooking paused' - elif payload == 0x44: - return 'Rice cooking aborted' - else: - return 'Unknown' - -@staticmethod -def _03BBB2(payload): - return payload - -@staticmethod -def _03BBE1(payload): - if payload == 0x41: - return 'Warmer on' - elif payload == 0x42: - return 'Warmer off' - else: - return 'Unknown warmer setting' - -@staticmethod -def _03BBE5(payload): - if payload == 0x41: - return 'Inner pot installed' - elif payload == 0x42: - return 'Inner pot removed' - else: - return 'Unknown inner pot removal status' - -@staticmethod -def _03BBE6(payload): - if payload == 0x41: - return 'Cover installed' - elif payload == 0x42: - return 'Cover removed' - else: - return 'Unknown cover removal status' - -@staticmethod -def _03BB90(payload): - return payload +from pychonet.lib.epc_functions import ( + DICT_30_ON_OFF, + DICT_30_OPEN_CLOSED, + DICT_41_ON_OFF, + _hh_mm, + _int, +) + class RiceCooker(EchonetInstance): - class_codes = { - 'class_group_code': 0x03, - 'class_code': 0xBB - } + class_codes = {"class_group_code": 0x03, "class_code": 0xBB} EPC_FUNCTIONS = { - 0x80: _03BB80, - 0xB0: _03BBB0, - 0xB1: _03BBB1, - 0xB2: _03BBB2, - 0xE1: _03BBE1, - 0xE5: _03BBE5, - 0xE6: _03BBE6, - 0x90: _03BB90, + 0x80: [_int, DICT_30_ON_OFF], + 0xB0: [_int, DICT_30_OPEN_CLOSED], + 0xB1: [ + _int, + { + 0x41: "Rice cooking completed", + 0x42: "Rice cooking in progress", + 0x43: "Rice cooking paused", + 0x44: "Rice cooking aborted", + }, + ], + 0xB2: [_int, {0x41: "Start/Restart", 0x42: "Pause"}], + 0xE1: [_int, DICT_41_ON_OFF], + 0xE5: [_int, {0x41: "Installed", 0x42: "Removed"}], + 0xE6: [_int, {0x41: "Installed", 0x42: "Removed"}], + 0x90: [_int, DICT_41_ON_OFF], 0x91: _hh_mm, 0x92: _hh_mm, } def __init__(self, host, api_connector=None, instance=0x1): - self._eojgc = self.class_codes['class_group_code'] - self._eojcc = self.class_codes['class_code'] + self._eojgc = self.class_codes["class_group_code"] + self._eojcc = self.class_codes["class_code"] super().__init__(host, self._eojgc, self._eojcc, instance, api_connector) - def getOperationStatus(self): - return self.getMessage(0x80) - - def setOperationStatus(self, status): - self.setMessage(0x80, status) + async def getOperationStatus(self): + return await self.getMessage(0x80) - def getCoverStatus(self): - return self.getMessage(0xB0) + async def setOperationStatus(self, status): + return await self.setMessage(0x80, status) - def getRiceCookingStatus(self): - return self.getMessage(0xB1) + async def getCoverStatus(self): + return await self.getMessage(0xB0) - def getRiceCookingControlSetting(self): - return self.getMessage(0xB2) + async def getRiceCookingStatus(self): + return await self.getMessage(0xB1) - def setRiceCookingControlSetting(self, setting): - self.setMessage(0xB2, setting) + async def getRiceCookingControlSetting(self): + return await self.getMessage(0xB2) - def getWarmerSetting(self): - return self.getMessage(0xE1) + async def setRiceCookingControlSetting(self, setting): + return await self.setMessage(0xB2, setting) - def setWarmerSetting(self, setting): - self.setMessage(0xE1, setting) + async def getWarmerSetting(self): + return await self.getMessage(0xE1) - def getInnerPotRemovalStatus(self): - return self.getMessage(0xE5) + async def setWarmerSetting(self, setting): + return await self.setMessage(0xE1, setting) - def getCoverRemovalStatus(self): - return self.getMessage(0xE6) + async def getInnerPotRemovalStatus(self): + return await self.getMessage(0xE5) - def getRiceCookingReservationSetting(self): - return self.getMessage(0x90) + async def getCoverRemovalStatus(self): + return await self.getMessage(0xE6) - def setRiceCookingReservationSetting(self, setting): - self.setMessage(0x90, setting) + async def getRiceCookingReservationSetting(self): + return await self.getMessage(0x90) - def getRiceCookingReservationSettingTime(self): - return self.getMessage(0x91) + async def setRiceCookingReservationSetting(self, setting): + return await self.setMessage(0x90, setting) - def setRiceCookingReservationSettingTime(self, time): - self.setMessage(0x91, time) + async def getRiceCookingReservationSettingTime(self): + return await self.getMessage(0x91) - def getRiceCookingReservationSettingRelativeTime(self): - return self.getMessage(0x92) + async def setRiceCookingReservationSettingTime(self, time): + return await self.setMessage(0x91, time) - def setRiceCookingReservationSettingRelativeTime(self, time): - self.setMessage(0x92, time) + async def getRiceCookingReservationSettingRelativeTime(self): + return await self.getMessage(0x92) + async def setRiceCookingReservationSettingRelativeTime(self, time): + return await self.setMessage(0x92, time) diff --git a/pychonet/StorageBattery.py b/pychonet/StorageBattery.py index 12cd661..7f69e67 100644 --- a/pychonet/StorageBattery.py +++ b/pychonet/StorageBattery.py @@ -1,5 +1,7 @@ +from deprecated import deprecated from pychonet.EchonetInstance import EchonetInstance from pychonet.lib.epc_functions import ( + DICT_41_PERMITTED_PROHIBITED, _int, _signed_int, _hh_mm, @@ -8,37 +10,43 @@ ) +@deprecated(reason="Scheduled for removal.") def _permission_setting(edt): - op_mode = int.from_bytes(edt, "big") - values = { - 0x41: "permitted", - 0x42: "Prohibited", - } - return values.get(op_mode, "Invalid setting") + return _int( + edt, + { + 0x41: "permitted", + 0x42: "Prohibited", + }, + ) +@deprecated(reason="Scheduled for removal.") def _027DC1(edt): - op_mode = int.from_bytes(edt, "big") - values = { - 0x00: "other", - 0x01: "maximum", - 0x02: "surplus", - 0x03: "designatedPower", - 0x04: "designatedCurrent", - } - return values.get(op_mode, "Invalid setting") - - + return _int( + edt, + { + 0x00: "other", + 0x01: "maximum", + 0x02: "surplus", + 0x03: "designatedPower", + 0x04: "designatedCurrent", + }, + ) + + +@deprecated(reason="Scheduled for removal.") def _027DC2(edt): - op_mode = int.from_bytes(edt, "big") - values = { - 0x00: "other", - 0x01: "maximum", - 0x02: "loadFollowing", - 0x03: "designatedPower", - 0x04: "designatedCurrent", - } - return values.get(op_mode, "Invalid setting") + return _int( + edt, + { + 0x00: "other", + 0x01: "maximum", + 0x02: "loadFollowing", + 0x03: "designatedPower", + 0x04: "designatedCurrent", + }, + ) def _max_min_int(edt): @@ -53,9 +61,54 @@ def _max_min_short_int(edt): return max + "/" + min +@deprecated(reason="Scheduled for removal.") def _027DCF(edt): - op_mode = int.from_bytes(edt, "big") - values = { + return _int( + edt, + { + 0x41: "rapidCharging", + 0x42: "charging", + 0x43: "discharging", + 0x44: "standby", + 0x45: "test", + 0x46: "auto", + 0x48: "restart", + 0x49: "capacityRecalculation", + 0x40: "Other", + }, + ) + + +@deprecated(reason="Scheduled for removal.") +def _027DDB(edt): + return _int( + edt, + { + 0x00: "reversePowerFlowAcceptable", + 0x01: "independent", + 0x02: "reversePowerFlowNotAcceptable", + }, + ) + + +@deprecated(reason="Scheduled for removal.") +def _027DE6(edt): + return _int( + edt, + { + 0x00: "unknown", + 0x01: "lead", + 0x02: "ni_mh", + 0x03: "ni_cd", + 0x04: "Lithium", + 0x05: "zinc", + 0x06: "alkaline", + }, + ) + + +class StorageBattery(EchonetInstance): + DICT_OPERATION_MODE = { 0x41: "rapidCharging", 0x42: "charging", 0x43: "discharging", @@ -66,122 +119,135 @@ def _027DCF(edt): 0x49: "capacityRecalculation", 0x40: "Other", } - return values.get(op_mode, "Invalid setting") - - -def _027DDB(edt): - op_mode = int.from_bytes(edt, "big") - values = { - 0x00: "reversePowerFlowAcceptable", - 0x01: "independent", - 0x02: "reversePowerFlowNotAcceptable", - } - return values.get(op_mode, "Invalid setting") - - -def _027DE6(edt): - op_mode = int.from_bytes(edt, "big") - values = { - 0x00: "unknown", - 0x01: "lead", - 0x02: "ni_mh", - 0x03: "ni_cd", - 0x04: "Lithium", - 0x05: "zinc", - 0x06: "alkaline", - } - return values.get(op_mode, "Invalid setting") - - -class StorageBattery(EchonetInstance): EPC_FUNCTIONS = { - 0x83: _to_string, #Identification number + 0x83: _to_string, # Identification number 0x97: _hh_mm, # Current time setting 0x98: _yyyy_mm_dd, # Current date setting - 0xA0: _int, #AC effective capacity (charging) - 0xA1: _int, #AC effective capacity (discharging) - 0xA2: _int, #AC chargeable capacity - 0xA3: _int, #AC dischargeable capacity - 0xA4: _int, #AC chargeable electric energy - 0xA5: _int, #AC dischargeable electric energy - 0xA6: _int, #AC charge upper limit setting - 0xA7: _int, #AC discharge lower limit setting - 0xA8: _int, #AC measured cumulative charging electric energy - 0xA9: _int, #AC measured cumulative discharging electric energy" - 0xAA: _int, #AC charge amount setting value - 0xAB: _int, #AC discharge amount setting value - 0xC1: _027DC1, #Charging method - 0xC2: _027DC2, #Discharging method - 0xC7: _int, #AC rated electric energy - 0xC8: _max_min_int, #Minimum/maximum charging electric power - 0xC9: _max_min_int, #Minimum/maximum discharging electric power - 0xCA: _max_min_short_int, #Minimum/maximum charging currentt - 0xCB: _max_min_short_int, #Minimum/maximum discharging current - 0xCC: _permission_setting, #Re-interconnection permission setting - 0xCD: _permission_setting, #"Operation permission setting - 0xCE: _permission_setting, #"Independent operation permission setting - 0xCF: _027DCF, #Working operation status - 0xD0: _int, #Rated electric energy - 0xD1: _int, #Rated capacity - 0xD2: _int, #Rated voltage - 0xD3: - _signed_int, #Measured instantaneous charging/discharging electric energy - 0xD4: - _signed_int, #Measured instantaneous charging/discharging current - 0xD5: - _signed_int, #Measured instantaneous charging/discharging voltage - 0xD6: _int, #Measured cumulative discharging electric energy + 0xA0: _int, # AC effective capacity (charging) + 0xA1: _int, # AC effective capacity (discharging) + 0xA2: _int, # AC chargeable capacity + 0xA3: _int, # AC dischargeable capacity + 0xA4: _int, # AC chargeable electric energy + 0xA5: _int, # AC dischargeable electric energy + 0xA6: _int, # AC charge upper limit setting + 0xA7: _int, # AC discharge lower limit setting + 0xA8: _int, # AC measured cumulative charging electric energy + 0xA9: _int, # AC measured cumulative discharging electric energy" + 0xAA: _int, # AC charge amount setting value + 0xAB: _int, # AC discharge amount setting value + 0xC1: [ + _int, + { + 0x00: "other", + 0x01: "maximum", + 0x02: "surplus", + 0x03: "designatedPower", + 0x04: "designatedCurrent", + }, + ], # Charging method + 0xC2: [ + _int, + { + 0x00: "other", + 0x01: "maximum", + 0x02: "loadFollowing", + 0x03: "designatedPower", + 0x04: "designatedCurrent", + }, + ], # Discharging method + 0xC7: _int, # AC rated electric energy + 0xC8: _max_min_int, # Minimum/maximum charging electric power + 0xC9: _max_min_int, # Minimum/maximum discharging electric power + 0xCA: _max_min_short_int, # Minimum/maximum charging currentt + 0xCB: _max_min_short_int, # Minimum/maximum discharging current + 0xCC: [ + _int, + DICT_41_PERMITTED_PROHIBITED, + ], # Re-interconnection permission setting + 0xCD: [ + _int, + DICT_41_PERMITTED_PROHIBITED, + ], # "Operation permission setting + 0xCE: [ + _int, + DICT_41_PERMITTED_PROHIBITED, + ], # "Independent operation permission setting + 0xCF: [_int, DICT_OPERATION_MODE], # Working operation status + 0xD0: _int, # Rated electric energy + 0xD1: _int, # Rated capacity + 0xD2: _int, # Rated voltage + 0xD3: _signed_int, # Measured instantaneous charging/discharging electric energy + 0xD4: _signed_int, # Measured instantaneous charging/discharging current + 0xD5: _signed_int, # Measured instantaneous charging/discharging voltage + 0xD6: _int, # Measured cumulative discharging electric energy # set only 0xD7: "Measured cumulative discharging electric energy” reset setting", - 0xD8: _int, #Measured cumulative charging electric energy + 0xD8: _int, # Measured cumulative charging electric energy # set only 0xD9: "Measured cumulative charging electric energy” reset setting", - 0xDA: _027DCF, #Operation mode setting - 0xDB: _027DDB, #System-interconnected type - 0xDC: _max_min_int, #Minimum/maxim um charging power (Independent) - 0xDD: _max_min_int, #Minimum/maxim um discharging power (Independent) - 0xDE: - _max_min_short_int, #Minimum/maxim um charging current (Independent) - 0xDF: - _max_min_short_int, #Minimum/maxim um discharging current (Independent) - 0xE0: _signed_int, #Charging/discharging amount setting 1 - 0xE1: _signed_int, #Charging/discharging amount setting 2 - 0xE2: _int, #Remaining stored electricity 1 - 0xE3: _int, #Remaining stored electricity 2 - 0xE4: _int, #Remaining stored electricity 3 - 0xE5: _int, #Battery state of health - 0xE6: _027DE6, #Battery type - 0xE7: _int, #Charging amount setting 1 - 0xE8: _int, #Discharging amount setting 1 - 0xE9: _int, #Charging amount setting 2 - 0xEA: _int, #Discharging amount setting 2 - 0xEB: _int, #Charging electric energy setting - 0xEC: _int, #Discharging electric energy setting - 0xED: _int, #Charging current setting - 0xEE: _int, #Discharging current setting - 0xEF: _int, #Rated voltage (Independent) + 0xDA: [_int, DICT_OPERATION_MODE], # Operation mode setting + 0xDB: [ + _int, + { + 0x00: "reversePowerFlowAcceptable", + 0x01: "independent", + 0x02: "reversePowerFlowNotAcceptable", + }, + ], # System-interconnected type + 0xDC: _max_min_int, # Minimum/maxim um charging power (Independent) + 0xDD: _max_min_int, # Minimum/maxim um discharging power (Independent) + 0xDE: _max_min_short_int, # Minimum/maxim um charging current (Independent) + 0xDF: _max_min_short_int, # Minimum/maxim um discharging current (Independent) + 0xE0: _signed_int, # Charging/discharging amount setting 1 + 0xE1: _signed_int, # Charging/discharging amount setting 2 + 0xE2: _int, # Remaining stored electricity 1 + 0xE3: _int, # Remaining stored electricity 2 + 0xE4: _int, # Remaining stored electricity 3 + 0xE5: _int, # Battery state of health + 0xE6: [ + _int, + { + 0x00: "unknown", + 0x01: "lead", + 0x02: "ni_mh", + 0x03: "ni_cd", + 0x04: "Lithium", + 0x05: "zinc", + 0x06: "alkaline", + }, + ], # Battery type + 0xE7: _int, # Charging amount setting 1 + 0xE8: _int, # Discharging amount setting 1 + 0xE9: _int, # Charging amount setting 2 + 0xEA: _int, # Discharging amount setting 2 + 0xEB: _int, # Charging electric energy setting + 0xEC: _int, # Discharging electric energy setting + 0xED: _int, # Charging current setting + 0xEE: _int, # Discharging current setting + 0xEF: _int, # Rated voltage (Independent) } - WORKING_OPERATION_STATES = { - 0x40: "Other", - 0x41: "Rapid charging", - 0x42: "Charging", - 0x43: "Discharging", - 0x44: "Standby", - 0x45: "Test", - 0x46: "Automatic", - 0x48: "Restart", - 0x49: "Effective capacity recalculation processing", - } - - def _permission_setting(edt): - op_mode = int.from_bytes(edt, "big") - values = { - 0x41: "permitted", - 0x42: "Prohibited", - } - return values.get(op_mode, "Invalid setting") + # WORKING_OPERATION_STATES = { + # 0x40: "Other", + # 0x41: "Rapid charging", + # 0x42: "Charging", + # 0x43: "Discharging", + # 0x44: "Standby", + # 0x45: "Test", + # 0x46: "Automatic", + # 0x48: "Restart", + # 0x49: "Effective capacity recalculation processing", + # } + + # def _permission_setting(edt): + # op_mode = int.from_bytes(edt, "big") + # values = { + # 0x41: "permitted", + # 0x42: "Prohibited", + # } + # return values.get(op_mode, "Invalid setting") def __init__(self, host, api_connector=None, instance=0x1): self._eojgc = 0x02 self._eojcc = 0x7D - EchonetInstance.__init__(self, host, self._eojgc, self._eojcc, - instance, api_connector) + EchonetInstance.__init__( + self, host, self._eojgc, self._eojcc, instance, api_connector + ) diff --git a/pychonet/WaterFlowMeter.py b/pychonet/WaterFlowMeter.py index 30eb93b..2c041fc 100644 --- a/pychonet/WaterFlowMeter.py +++ b/pychonet/WaterFlowMeter.py @@ -1,51 +1,98 @@ +from deprecated import deprecated from pychonet.EchonetInstance import EchonetInstance from pychonet.lib.epc_functions import _int, _signed_int, _to_string import struct + +@deprecated(reason="Scheduled for removal.") def _0281D0(edt): # Water flow meter classification - op_mode = int.from_bytes(edt, "big") - values = {0x30: "Running Water", - 0x31: "Recycled Water", - 0x32: "Sewage Water", - 0x33: "Other Water"} - return values.get(op_mode, "invalid_setting") + return _int( + edt, + { + 0x30: "Running Water", + 0x31: "Recycled Water", + 0x32: "Sewage Water", + 0x33: "Other Water", + }, + ) + +@deprecated(reason="Scheduled for removal.") def _0281D1(edt): # Owner classification - op_mode = int.from_bytes(edt, "big") - values = {0x30: "Not specified", - 0x31: "Public waterworks company", - 0x32: "Private sector company", - 0x33: "Individual"} - return values.get(op_mode, "invalid_setting") + return _int( + edt, + { + 0x30: "Not specified", + 0x31: "Public waterworks company", + 0x32: "Private sector company", + 0x33: "Individual", + }, + ) + +@deprecated(reason="Scheduled for removal.") def _0281E1(edt): - # Unit for measured cumulative amounts of flowing water - op_mode = int.from_bytes(edt, "big") - values = {0x00: 1, - 0x01: 0.1, - 0x02: 0.01, - 0x03: 0.001, - 0x04: 0.0001, - 0x05: 0.00001, - 0x06: 0.000001} - return values.get(op_mode, "invalid_setting") + # Unit for measured cumulative amounts of flowing water + return _int( + edt, + { + 0x00: 1, + 0x01: 0.1, + 0x02: 0.01, + 0x03: 0.001, + 0x04: 0.0001, + 0x05: 0.00001, + 0x06: 0.000001, + }, + None, + ) + # 0xE2: "Historical data of measured cumulative amounts of flowing water" def _0281E2(edt): - # return array x 48 unsigned long big-endian - return [x[0] for x in struct.iter_unpack('>L',edt)] + # return array x 48 unsigned long big-endian + return [x[0] for x in struct.iter_unpack(">L", edt)] + class WaterFlowMeter(EchonetInstance): EPC_FUNCTIONS = { - 0xD0: _0281D0, # "Water flow meter classification" - 0xD1: _0281D1, # "Owner classification" - 0xE0: _int, # "Measured cumulative amount of flowing water" - 0xE1: _0281E1, # "Unit for measured cumulative amounts of flowing water" - 0xE2: _0281E2, # "Historical data of measured cumulative amounts of flowing water" - 0xE5: _to_string, # "ID number setting" - 0xE6: _to_string # "Verification expiration information" + 0xD0: [ + _int, + { + 0x30: "Running Water", + 0x31: "Recycled Water", + 0x32: "Sewage Water", + 0x33: "Other Water", + }, + ], # "Water flow meter classification" + 0xD1: [ + _int, + { + 0x30: "Not specified", + 0x31: "Public waterworks company", + 0x32: "Private sector company", + 0x33: "Individual", + }, + ], # "Owner classification" + 0xE0: _int, # "Measured cumulative amount of flowing water" + 0xE1: [ + _int, + { + 0x00: 1, + 0x01: 0.1, + 0x02: 0.01, + 0x03: 0.001, + 0x04: 0.0001, + 0x05: 0.00001, + 0x06: 0.000001, + }, + None, + ], # "Unit for measured cumulative amounts of flowing water" + 0xE2: _0281E2, # "Historical data of measured cumulative amounts of flowing water" + 0xE5: _to_string, # "ID number setting" + 0xE6: _to_string, # "Verification expiration information" } def __init__(self, host, api_connector=None, instance=0x1): diff --git a/pychonet/__init__.py b/pychonet/__init__.py index 80af03f..35d846c 100644 --- a/pychonet/__init__.py +++ b/pychonet/__init__.py @@ -4,6 +4,12 @@ from .version import __version__ from .EchonetInstance import EchonetInstance from .ElectricBlind import ElectricBlind +from .ElectricShutter import ElectricShutter +from .ElectricCurtain import ElectricCurtain +from .ElectricRainSlidingDoor import ElectricRainSlidingDoor +from .ElectricGate import ElectricGate +from .ElectricWindow import ElectricWindow +from .AutomaticEntranceDoor import AutomaticEntranceDoor from .ElectricLock import ElectricLock from .ElectricVehicleCharger import ElectricVehicleCharger from .GeneralLighting import GeneralLighting @@ -40,6 +46,12 @@ def Factory(host, server, eojgc, eojcc, eojci=0x01): f"{0x01}-{0x35}": HomeAirCleaner, f"{0x01}-{0x3A}": CeilingFan, f"{0x02}-{0x60}": ElectricBlind, + f"{0x02}-{0x61}": ElectricShutter, + f"{0x02}-{0x62}": ElectricCurtain, + f"{0x02}-{0x63}": ElectricRainSlidingDoor, + f"{0x02}-{0x64}": ElectricGate, + f"{0x02}-{0x65}": ElectricWindow, + f"{0x02}-{0x66}": AutomaticEntranceDoor, f"{0x02}-{0x6B}": ElectricWaterHeater, f"{0x02}-{0x6F}": ElectricLock, f"{0x02}-{0x72}": HotWaterGenerator, diff --git a/pychonet/echonetapiclient.py b/pychonet/echonetapiclient.py index e559d19..3f9f70a 100644 --- a/pychonet/echonetapiclient.py +++ b/pychonet/echonetapiclient.py @@ -131,9 +131,14 @@ async def echonetMessageReceived(self, raw_data, addr): epc ] = EPC_SUPER_FUNCTIONS[epc](opc["EDT"]) except KeyError as e: - raise Exception( - f"ECHONET Packet contains the following data: {processed_data}" - ) + if self._debug_flag: + self._logger( + f"ECHONET _state _key error {e} of {host} this packet contains the following data: {processed_data}" + ) + continue + # raise Exception( + # f"ECHONET Packet contains the following data: {processed_data}" + # ) else: if esv_set: if opc["PDC"] > 0 or isPush: diff --git a/pychonet/lib/epc.py b/pychonet/lib/epc.py index 691889b..d43a474 100644 --- a/pychonet/lib/epc.py +++ b/pychonet/lib/epc.py @@ -725,7 +725,7 @@ 0x80: "Operation status", 0xE0: "Temperature setting 1", 0xE1: "Temperature setting 2", - 0xD1: "The maximum settable level is the top step of temperature setting 2", + 0xD1: "Temperature setting 2 – Maximum settable level", 0xE2: "Measured room temperature", 0xE3: "Measured floor temperature", 0xE4: "Zone change setting", @@ -739,6 +739,10 @@ 0x94: "OFF timer reservation setting", 0x95: "Time set by OFF timer", 0x96: "Relative OFF timer setting", + 0x84: "Measured instantaneous power consumption", + 0x85: "Measured cumulative electric energy consumption", + 0xE9: "Rated power consumption", + 0xEA: "Power consumption measurement method", }, 0x7C: { # Fuel cell class 0x80: "Operation status", diff --git a/pychonet/lib/epc_functions.py b/pychonet/lib/epc_functions.py index 4fb51ca..4e181d2 100644 --- a/pychonet/lib/epc_functions.py +++ b/pychonet/lib/epc_functions.py @@ -1,11 +1,66 @@ -from datetime import datetime, timezone - +from typing import Any, ByteString from pychonet.lib.const import MANUFACTURERS +# Data States +DATA_STATE_ON = "on" +DATA_STATE_OFF = "off" +DATA_STATE_LOCK = "locked" +DATA_STATE_UNLOCK = "unlocked" +DATA_STATE_OPEN = "open" +DATA_STATE_CLOSE = "closed" +DATA_STATE_STOP = "stop" + +# Like switch type +DICT_41_ON_OFF = {0x41: DATA_STATE_ON, 0x42: DATA_STATE_OFF} +DICT_41_YES_NO = {0x41: "yes", 0x42: "no"} +DICT_41_AUTO_NONAUTO = {0x41: "auto", 0x42: "non-auto"} +DICT_41_UNLOCK_LOCK = {0x42: DATA_STATE_UNLOCK, 0x41: DATA_STATE_LOCK} +DICT_41_OPEN_CLOSED = {0x41: DATA_STATE_OPEN, 0x42: DATA_STATE_CLOSE} +DICT_41_ENABLED_DISABLED = {0x41: "enabled", 0x42: "disabled"} +DICT_41_AVAILABLE_NOT_AVAILABLE = {0x41: "available", 0x42: "not available"} +DICT_41_HEATING_NOT_HEATING = {0x41: "heating", 0x42: "not heating"} +DICT_41_PERMITTED_PROHIBITED = {0x41: "permitted", 0x42: "prohibited"} +DICT_30_TRUE_FALSE = {0x30: True, 0x31: False} +DICT_30_ON_OFF = {0x30: DATA_STATE_ON, 0x31: DATA_STATE_OFF} +DICT_30_OPEN_CLOSED = {0x30: DATA_STATE_OPEN, 0x31: DATA_STATE_CLOSE} + +# Like select type +DICT_41_AUTO_8_SPEEDS = { + 0x41: "auto", + 0x31: "minimum", + 0x32: "low", + 0x33: "medium-low", + 0x34: "medium", + 0x35: "medium-high", + 0x36: "high", + 0x37: "very-high", + 0x38: "max", +} + + +def _swap_dict(d: dict): + return {v: k for k, v in d.items()} + # ------------ EPC GENERIC FUNCTIONS ------- -def _int(edt): # unsigned int - return int.from_bytes(edt, "big") +def _int(edt, values: dict = {}, non_value: Any = "Invalid setting"): # unsigned int + data_int = int.from_bytes(edt, "big") + if len(values): + return values.get(data_int, non_value) + else: + return int.from_bytes(edt, "big") + + +def _call_int(data: bytes | list): + if type(data) == list: + if len(data) == 3: + return _int(data[0], data[1], data[2]) + elif len(data) == 2: + return _int(data[0], data[1]) + else: + return _int(data[0]) + else: + return _int(data) def _signed_int(edt): # signed ints @@ -35,17 +90,10 @@ def _null_padded_optional_string(edt): ) -def _on_off(edt): - op_mode = int.from_bytes(edt, "big") - values = {0x41: "On", 0x42: "Off"} - return values.get(op_mode, "Invalid setting") - - # Check status of Echonnet Instance # ----------------- EPC SUPER FUNCTIONS ----------------------------- def _0080(edt): - ops_value = int.from_bytes(edt, "big") - return "On" if ops_value == 0x30 else "Off" + return _int(edt, DICT_30_ON_OFF) def _009X(edt): @@ -114,53 +162,3 @@ def _009A(edt): # cumulative runtime 0x9E: _009X, 0x9F: _009X, } - -# ------- EPC FUNCTIONS ------------------------------------------------- -# TODO - Move these to their classes -# ----------------------------------------------------------------------- - -# --- Low voltage smart meter class - - -def _0288E1(edt): - op_mode = int.from_bytes(edt, "big") - values = { - 0x00: 1, - 0x01: 0.1, - 0x02: 0.01, - 0x03: 0.001, - 0x04: 0.0001, - 0x0A: 10, - 0x0B: 100, - 0x0C: 1000, - 0x0D: 10000, - } - return values.get(op_mode, "invalid_setting") - - -# ----- Low voltage smart electric energy meter ------- -def _0288E7(edt): - value = int.from_bytes(edt, "big", signed=True) - return value - - -def _0288E8(edt): - r_phase = float(int.from_bytes(edt[0:2], "big", signed=True)) / 10 # R Phase - t_phase = float(int.from_bytes(edt[2:4], "big", signed=True)) / 10 # T Phase - return {"r_phase_amps": r_phase, "t_phase_amps": t_phase} - - -def _0288EA(edt): - print(edt) - year = int.from_bytes(edt[0:2], "big") - month = int.from_bytes(edt[2:3], "big") - day = int.from_bytes(edt[3:4], "big") - hour = int.from_bytes(edt[4:5], "big") - minute = int.from_bytes(edt[5:6], "big") - second = int.from_bytes(edt[6:7], "big") - culmative = int.from_bytes(edt[7:], "big") - time = datetime(year, month, day, hour, minute, second) - return { - "time": datetime(year, month, day, hour, minute, second).isoformat(), - "culmative_value": culmative, - }