diff --git a/src/ramses_tx/parsers.py b/src/ramses_tx/parsers.py index 081b9fe1..291304da 100644 --- a/src/ramses_tx/parsers.py +++ b/src/ramses_tx/parsers.py @@ -40,6 +40,7 @@ SZ_DEVICE_ID, SZ_DEVICE_ROLE, SZ_DEVICES, + SZ_DEWPOINT_TEMP, SZ_DHW_FLOW_RATE, SZ_DOMAIN_ID, SZ_DOMAIN_IDX, @@ -2153,27 +2154,46 @@ def parser_31d9(payload: str, msg: Message) -> dict[str, Any]: # ventilation state (extended), HVAC def parser_31da(payload: str, msg: Message) -> PayDictT._31DA: # see: https://github.com/python/typing/issues/1445 - return { # type: ignore[typeddict-unknown-key] - **parse_exhaust_fan_speed(payload[38:40]), # maybe 31D9[4:6] for some? - **parse_fan_info(payload[36:38]), # 22F3-ish - # - **parse_air_quality(payload[2:6]), # 12C8[2:6] - **parse_co2_level(payload[6:10]), # 1298[2:6] - **parse_indoor_humidity(payload[10:12]), # 12A0? - **parse_outdoor_humidity(payload[12:14]), - **parse_exhaust_temp(payload[14:18]), # to outside - **parse_supply_temp(payload[18:22]), # to home - **parse_indoor_temp(payload[22:26]), # in home - **parse_outdoor_temp(payload[26:30]), # 1290? - **parse_capabilities(payload[30:34]), - **parse_bypass_position(payload[34:36]), # 22F7-ish - **parse_supply_fan_speed(payload[40:42]), - **parse_remaining_mins(payload[42:46]), # mins, ~22F3[2:6] - **parse_post_heater(payload[46:48]), - **parse_pre_heater(payload[48:50]), - **parse_supply_flow(payload[50:54]), # NOTE: is supply, not exhaust - **parse_exhaust_flow(payload[54:58]), # NOTE: order switched from others - } + if msg.len == 30 and payload[30:38] == "BE09001F": # ClimaRad VenturaV1x 2021 + assert payload[12:14] == "EF", f"Ventura 31DA 12: {payload[12:14]}" + assert payload[18:22] == "7FFF", f"Ventura 31DA 18: {payload[18:22]}" + assert payload[38:40] == payload[40:42], f"Ventura 31DA twin {payload[40:42]}" + assert payload[42:60] == "000000008500850000" + return { + "zone": f"0x{payload[0:2]}", # zone + **parse_air_quality( + payload[2:6] + ), # N/A in VenturaV1x (reports CO2 in 12A0) but must include for Mypy?? + SZ_DEWPOINT_TEMP: hex_to_temp(payload[6:10]), # confirmed + "_unknown_1": f"0x{payload[10:12]}", # 0x00|08|3E|52|7F|9A|AF|D3 = ? + **parse_indoor_temp(payload[22:26]), + **parse_exhaust_temp(payload[26:30]), + **parse_bypass_position(payload[38:40]), # 0x00|14 TODO confirm in summer + } # type: ignore[return-value] + else: + return { + **parse_exhaust_fan_speed( + payload[38:40] + ), # indeed in 31D9[4:6] for some, like Vasco D60 + **parse_fan_info(payload[36:38]), # 22F3-ish + # + **parse_air_quality(payload[2:6]), # 12C8[2:6] + **parse_co2_level(payload[6:10]), # 1298[2:6] + **parse_indoor_humidity(payload[10:12]), # 12A0? + **parse_outdoor_humidity(payload[12:14]), + **parse_exhaust_temp(payload[14:18]), # to outside + **parse_supply_temp(payload[18:22]), # to home + **parse_indoor_temp(payload[22:26]), # in home + **parse_outdoor_temp(payload[26:30]), # 1290? + **parse_capabilities(payload[30:34]), + **parse_bypass_position(payload[34:36]), # 22F7-ish + **parse_supply_fan_speed(payload[40:42]), + **parse_remaining_mins(payload[42:46]), # mins, ~22F3[2:6] + **parse_post_heater(payload[46:48]), + **parse_pre_heater(payload[48:50]), + **parse_supply_flow(payload[50:54]), # NOTE: is supply, not exhaust + **parse_exhaust_flow(payload[54:58]), # NOTE: order switched from others + } # type: ignore[return-value] # From an Orcon 15RF Display # 1 Software version diff --git a/src/ramses_tx/typed_dicts.py b/src/ramses_tx/typed_dicts.py index a06380b5..843552ba 100644 --- a/src/ramses_tx/typed_dicts.py +++ b/src/ramses_tx/typed_dicts.py @@ -200,6 +200,22 @@ class _313f(TypedDict): _unknown_0: str +class AirQuality(TypedDict): + air_quality: float | None + air_quality_basis: NotRequired[str] + + +class _31da_v(TypedDict): # v for ClimaRad Ventura + zone: str | None + air_quality: AirQuality + air_quality_basis: NotRequired[str] + SZ_DEWPOINT_TEMP: float | None + _unknown_1: str | None + SZ_INDOOR_TEMP: float | None + SZ_EXHAUST_TEMP: float | None + SZ_BYPASS_POSITION: float | None + + class _3220(TypedDict): msg_id: int # OtDataId msg_type: str # OtMsgType @@ -282,9 +298,9 @@ class FaultLogEntry(TypedDict): # NOTE: not identical to _0418 # These are from 31DA... -class AirQuality(TypedDict): - air_quality: float | None - air_quality_basis: NotRequired[str] +# class AirQuality(TypedDict): # moved before 31DA +# air_quality: float | None +# air_quality_basis: NotRequired[str] class Co2Level(TypedDict): @@ -427,7 +443,7 @@ class PayDictT: _2E04: TypeAlias = _2e04 _3110: TypeAlias = _3110 _313F: TypeAlias = _313f - _31DA: TypeAlias = _VentilationState + _31DA: TypeAlias = _VentilationState | _31da_v _3200: TypeAlias = _Temperature _3210: TypeAlias = _Temperature _3B00: TypeAlias = _3b00 diff --git a/tests/tests/parsers/code_31da.log b/tests/tests/parsers/code_31da.log index af543c54..75dbc9b9 100644 --- a/tests/tests/parsers/code_31da.log +++ b/tests/tests/parsers/code_31da.log @@ -300,3 +300,34 @@ # Siber DF EVO 2 2024-06-21T04:47:19.545913 ... I --- 32:137185 --:------ 32:137185 31DA 030 00EF007FFFEFEF080607D809480737F002AA02344000005CEF7FFF7FFF00 # {'hvac_id': '00', 'exhaust_fan_speed': 0.26, 'fan_info': 'speed 2, medium', '_unknown_fan_info_flags': [0, 0, 0], 'air_quality': None, 'co2_level': None, 'indoor_humidity': None, 'outdoor_humidity': None, 'exhaust_temp': 20.54, 'supply_temp': 20.08, 'indoor_temp': 23.76, 'outdoor_temp': 18.47, 'speed_capabilities': ['off', 'low_med_high', 'timer', 'boost', 'post_heater'], 'bypass_position': 0.85, 'supply_fan_speed': 0.32, 'remaining_mins': 0, 'post_heat': 0.46, 'pre_heat': None, 'supply_flow': None, 'exhaust_flow': None} 2024-06-21T04:49:59.398298 ... I --- 32:137185 --:------ 32:137185 31DA 030 00EF007FFFEFEF086C07CC09380730F002A0023440000068EF7FFF7FFF00 # {'hvac_id': '00', 'exhaust_fan_speed': 0.26, 'fan_info': 'speed 2, medium', '_unknown_fan_info_flags': [0, 0, 0], 'air_quality': None, 'co2_level': None, 'indoor_humidity': None, 'outdoor_humidity': None, 'exhaust_temp': 21.56, 'supply_temp': 19.96, 'indoor_temp': 23.60, 'outdoor_temp': 18.40, 'speed_capabilities': ['off', 'low_med_high', 'timer', 'boost', 'post_heater'], 'bypass_position': 0.80, 'supply_fan_speed': 0.32, 'remaining_mins': 0, 'post_heat': 0.52, 'pre_heat': None, 'supply_flow': None, 'exhaust_flow': None} + +# Vasco D60 HRU +2024-10-15T12:46:03.623447 082 I --- 32:022222 --:------ 32:022222 31DA 030 00EF007FFFEFEF058506EE0773051FA800EF0232320000EF00051902EE00 # {'hvac_id': '00', 'exhaust_fan_speed': 0.25, 'fan_info': 'speed 2, medium', '_unknown_fan_info_flags': [0, 0, 0], 'air_quality': None, 'co2_level': None, 'indoor_humidity': None, 'outdoor_humidity': None, 'exhaust_temp': 14.13, 'supply_temp': 17.74, 'indoor_temp': 19.07, 'outdoor_temp': 13.11, 'speed_capabilities': ['off', 'timer', 'auto'], 'bypass_position': None, 'supply_fan_speed': 0.25, 'remaining_mins': 0, 'post_heat': None, 'pre_heat': 0.0, 'supply_flow': 13.05, 'exhaust_flow': 7.5} +2024-10-15T13:53:09.930437 083 I --- 32:022222 --:------ 32:022222 31DA 030 00EF007FFFEFEF05F8075207B705B1A800EF0232320000EF000263018400 # {'hvac_id': '00', 'exhaust_fan_speed': 0.25, 'fan_info': 'speed 2, medium', '_unknown_fan_info_flags': [0, 0, 0], 'air_quality': None, 'co2_level': None, 'indoor_humidity': None, 'outdoor_humidity': None, 'exhaust_temp': 15.28, 'supply_temp': 18.74, 'indoor_temp': 19.75, 'outdoor_temp': 14.57, 'speed_capabilities': ['off', 'timer', 'auto'], 'bypass_position': None, 'supply_fan_speed': 0.25, 'remaining_mins': 0, 'post_heat': None, 'pre_heat': 0.0, 'supply_flow': 6.11, 'exhaust_flow': 3.88} +2024-10-15T13:21:16.306823 084 I --- 32:022222 --:------ 32:022222 31DA 030 00EF007FFFEFEF05CC07220795057AA800EF0232320000EF0003CC026300 # {'hvac_id': '00', 'exhaust_fan_speed': 0.25, 'fan_info': 'speed 2, medium', '_unknown_fan_info_flags': [0, 0, 0], 'air_quality': None, 'co2_level': None, 'indoor_humidity': None, 'outdoor_humidity': None, 'exhaust_temp': 14.84, 'supply_temp': 18.26, 'indoor_temp': 19.41, 'outdoor_temp': 14.02, 'speed_capabilities': ['off', 'timer', 'auto'], 'bypass_position': None, 'supply_fan_speed': 0.25, 'remaining_mins': 0, 'post_heat': None, 'pre_heat': 0.0, 'supply_flow': 9.72, 'exhaust_flow': 6.11} +2024-10-15T15:45:21.214426 086 I --- 32:022222 --:------ 32:022222 31DA 030 00EF007FFFEFEF062C7FFF7FFF05AAA800EF0128280000EF007FFF7FFF00 # {'hvac_id': '00', 'exhaust_fan_speed': 0.2, 'fan_info': 'speed 1, low', '_unknown_fan_info_flags': [0, 0, 0], 'air_quality': None, 'co2_level': None, 'indoor_humidity': None, 'outdoor_humidity': None, 'exhaust_temp': 15.8, 'supply_temp': None, 'indoor_temp': None, 'outdoor_temp': 14.5, 'speed_capabilities': ['off', 'timer', 'auto'], 'bypass_position': None, 'supply_fan_speed': 0.2, 'remaining_mins': 0, 'post_heat': None, 'pre_heat': 0.0, 'supply_flow': None, 'exhaust_flow': None} +2024-10-15T22:54:16.347179 085 I --- 32:022222 --:------ 32:022222 31DA 030 00EF007FFFEFEF04D0070507A30443A800EF011E1E0000EF0002EE020F00 # {'hvac_id': '00', 'exhaust_fan_speed': 0.15, 'fan_info': 'speed 1, low', '_unknown_fan_info_flags': [0, 0, 0], 'air_quality': None, 'co2_level': None, 'indoor_humidity': None, 'outdoor_humidity': None, 'exhaust_temp': 12.32, 'supply_temp': 17.97, 'indoor_temp': 19.55, 'outdoor_temp': 10.91, 'speed_capabilities': ['off', 'timer', 'auto'], 'bypass_position': None, 'supply_fan_speed': 0.15, 'remaining_mins': 0, 'post_heat': None, 'pre_heat': 0.0, 'supply_flow': 7.5, 'exhaust_flow': 5.27} + +# ClimaRad Ventura +# .I + 31DA 030 00 EF 00 029C 00 EF 070D 7FFF 0833 07A8 BE09001F 0000 000000008500850000 (auto) +# .I + 31DA 030 00 EF 00 02C8 00 EF 07AA 7FFF 07CB 05F0 BE09001F 0808 000000008500850000 (speed 1) +# .I + 31DA 030 00 EF 00 023B 00 EF 0751 7FFF 0732 055A BE09001F 1414 000000008500850000 (speed 2) +# .I + 31DA 030 00 EF 00 019F 00 EF 067A 7FFF 0807 074E BE09001F 0000 000000008500850000 (auto) +# .I + 31DA 030 00 EF 00 0195 F7 EF 0621 7FFF 0846 0773 BE09001F 0000 000000008500850000 (wake up button press, no changes) +# .I + 31DA 030 00 EF 00 01AB 3E EF 0572 7FFF 07BC 06EA BE09001F 0000 000000008500850000 +# airQ? | | | | | no ascii |—|———| +# Deduction: | | | | | |___0502-07F7_| << 0-255 = speed% ? +# hexStr4 temp___| | | | |___055A-0813=hexStr4 temp +# 00|08|52|9A|D3_| | |___(00|08|14){2} +# | |___0300-D7CA_ << 0-255 = ? +# temp1 temp2 temp3 temp4 +# Previous parser raises invalid_fan_info +# New parser: +2024-10-18T00:03:42.690880 065 I --- 37:153226 --:------ 37:153226 31DA 030 00EF00024300EF06E77FFF08190775BE09001F0000000000008500850000 # {'hvac_id': '00', 'zone': '0x00', 'air_quality': None, 'dewpoint_temp': 5.79, '_unknown_1': '0x00', 'indoor_temp': 20.73, 'exhaust_temp': 19.09, 'bypass_position': 0.0} + +2024-10-18T00:03:42.690881 065 I --- 37:153226 --:------ 37:153226 31DA 030 00EF00029C00EF070D7FFF083307A8BE09001F0000000000008500850000 # {'hvac_id': '00', 'zone': '0x00', 'air_quality': None, 'dewpoint_temp': 6.68, '_unknown_1': '0x00', 'indoor_temp': 20.99, 'exhaust_temp': 19.6, 'bypass_position': 0.0} # auto +2024-10-18T00:03:42.690882 065 I --- 37:153226 --:------ 37:153226 31DA 030 00EF0002C800EF07AA7FFF07CB05F0BE09001F0808000000008500850000 # {'hvac_id': '00', 'zone': '0x00', 'air_quality': None, 'dewpoint_temp': 7.12, '_unknown_1': '0x00', 'indoor_temp': 19.95, 'exhaust_temp': 15.2, 'bypass_position': 0.04} # speed 1 +2024-10-18T00:03:42.690883 065 I --- 37:153226 --:------ 37:153226 31DA 030 00EF00023B00EF07517FFF0732055ABE09001F1414000000008500850000 # {'hvac_id': '00', 'zone': '0x00', 'air_quality': None, 'dewpoint_temp': 5.71, '_unknown_1': '0x00', 'indoor_temp': 18.42, 'exhaust_temp': 13.7, 'bypass_position': 0.1} # speed 2 +2024-10-18T00:03:42.690884 065 I --- 37:153226 --:------ 37:153226 31DA 030 00EF00019F00EF067A7FFF0807074EBE09001F0000000000008500850000 # {'hvac_id': '00', 'zone': '0x00', 'air_quality': None, 'dewpoint_temp': 4.15, '_unknown_1': '0x00', 'indoor_temp': 20.55, 'exhaust_temp': 18.7, 'bypass_position': 0.0} # auto +2024-10-18T00:03:42.690885 065 I --- 37:153226 --:------ 37:153226 31DA 030 00EF000195F7EF06217FFF08460773BE09001F0000000000008500850000 # {'hvac_id': '00', 'zone': '0x00', 'air_quality': None, 'dewpoint_temp': 4.05, '_unknown_1': '0xF7', 'indoor_temp': 21.18, 'exhaust_temp': 19.07, 'bypass_position': 0.0} # 1st button press = no changes +2024-10-18T00:03:42.690886 065 I --- 37:153226 --:------ 37:153226 31DA 030 00EF0001AB3EEF05727FFF07BC06EABE09001F0000000000008500850000 # {'hvac_id': '00', 'zone': '0x00', 'air_quality': None, 'dewpoint_temp': 4.27, '_unknown_1': '0x3E', 'indoor_temp': 19.8, 'exhaust_temp': 17.7, 'bypass_position': 0.0} #