From eae7b3d99d4e992d94a2886af297f3e933a5e8e6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 25 May 2026 05:05:44 +0000 Subject: [PATCH 1/2] Initial plan From 73f6d582cac1fcdaf8e0388186bec192e735eb67 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 25 May 2026 05:10:23 +0000 Subject: [PATCH 2/2] Add mapping support for BWT MEDO CONNECT Wi-Fi model PDPH1H1HAW1B0 --- README.md | 1 + docs/device-support.md | 1 + .../model_PDPH1H1HAW1B0_FW539494.json | 128 ++++++++++++++++++ tests/test_mapping_info.py | 34 +++++ 4 files changed, 164 insertions(+) create mode 100644 src/pooldose/mappings/model_PDPH1H1HAW1B0_FW539494.json diff --git a/README.md b/README.md index 2faaf08..1478243 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,7 @@ See [docs/cli.md](docs/cli.md) for full CLI documentation and device analysis de | SEKO PoolDose Double Spa | PDPR1H04AW100 | 539292 | | | SEKO POOLDOSE pH+ORP CF Group Wi-Fi | PDPR1H1HAW102 | 539187 | Alias for PDPR1H1HAW100 mapping | | SEKO PoolDose pH | PDPH1H1HAW100 | 539176 | pH-only device | +| BWT MEDO CONNECT Wi-Fi | PDPH1H1HAW1B0 | 539494 | Based on SEKO PoolDose pH mapping | | VÁGNER POOL VA DOS BASIC | PDHC1H1HAR1V0 | 539224 | | | VÁGNER POOL VA DOS EXACT | PDHC1H1HAR1V1 | 539224 | Alias for PDPR1H1HAR1V0 mapping | diff --git a/docs/device-support.md b/docs/device-support.md index 8ebf393..da477fe 100644 --- a/docs/device-support.md +++ b/docs/device-support.md @@ -10,6 +10,7 @@ This client has been tested with: | SEKO PoolDose Double Spa | PDPR1H04AW100 | 539292 | | | SEKO POOLDOSE pH+ORP CF Group Wi-Fi | PDPR1H1HAW102 | 539187 | Alias for PDPR1H1HAW100 mapping | | SEKO PoolDose pH | PDPH1H1HAW100 | 539176 | pH-only device | +| BWT MEDO CONNECT Wi-Fi | PDPH1H1HAW1B0 | 539494 | Based on SEKO PoolDose pH mapping | | VÁGNER POOL VA DOS BASIC | PDHC1H1HAR1V0 | 539224 | | | VÁGNER POOL VA DOS EXACT | PDHC1H1HAR1V1 | 539224 | Alias for PDPR1H1HAR1V0 mapping | diff --git a/src/pooldose/mappings/model_PDPH1H1HAW1B0_FW539494.json b/src/pooldose/mappings/model_PDPH1H1HAW1B0_FW539494.json new file mode 100644 index 0000000..37376db --- /dev/null +++ b/src/pooldose/mappings/model_PDPH1H1HAW1B0_FW539494.json @@ -0,0 +1,128 @@ +{ + "temperature": { + "key": "w_1eomiide3", + "type": "sensor" + }, + "ph": { + "key": "w_1ekeigkin", + "type": "sensor" + }, + "orp": { + "key": "w_1eklenb23", + "type": "sensor" + }, + "ph_type_dosing": { + "key": "w_1eklg44ro", + "type": "sensor", + "conversion": { + "|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklg44ro_ALCALYNE|": "alcalyne", + "|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklg44ro_ACID|": "acid" + } + }, + "peristaltic_ph_dosing": { + "key": "w_1eklj6euj", + "type": "sensor", + "conversion": { + "|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklj6euj_OFF|": "off", + "|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklj6euj_PROPORTIONAL|": "proportional", + "|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklj6euj_ON_OFF|": "on / off", + "|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklj6euj_TIMED|": "timed" + } + }, + "orp_type_dosing": { + "key": "w_1eklgnolb", + "type": "sensor", + "conversion": { + "|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklgnolb_LOW|": "low", + "|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklgnolb_HIGH|": "high" + } + }, + "peristaltic_orp_dosing": { + "key": "w_1eklj12vv", + "type": "sensor", + "conversion": { + "|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklj12vv_OFF|": "off", + "|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklj12vv_PROPORTIONAL|": "proportional", + "|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklj12vv_ON_OFF|": "on / off", + "|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklj12vv_TIMED|": "timed" + } + }, + "ph_calibration_type": { + "key": "w_1eklh8gb7", + "type": "sensor", + "conversion": { + "|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklh8gb7_OFF|": "off", + "|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklh8gb7_REFERENCE|": "reference", + "|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklh8gb7_1_POINT|": "1_point", + "|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklh8gb7_2_POINTS|": "2_points" + } + }, + "ph_calibration_offset": { + "key": "w_1eklhs3b4", + "type": "sensor" + }, + "ph_calibration_slope": { + "key": "w_1eklhs65u", + "type": "sensor" + }, + "orp_calibration_slope": { + "key": "w_1eklhsase", + "type": "sensor" + }, + "ofa_value": { + "key": "w_1eklhj58e", + "type": "sensor" + }, + "pump_alarm": { + "key": "w_1ekga097n", + "type": "binary_sensor" + }, + "ph_level_alarm": { + "key": "w_1eklf77pm", + "type": "binary_sensor" + }, + "relay_alarm": { + "key": "w_1eklffdl0", + "type": "binary_sensor" + }, + "relay_aux": { + "key": "w_1eklfgs1t", + "type": "binary_sensor" + }, + "alarm_ofa_ph": { + "key": "w_1eklfb73r", + "type": "binary_sensor" + }, + "alarm_ofa_orp": { + "key": "w_1eklfb8ob", + "type": "binary_sensor" + }, + "ph_target": { + "key": "w_1ekeiqfat", + "type": "number" + }, + "pause_dosing": { + "key": "w_1emtltkel", + "type": "switch" + }, + "pump_monitoring": { + "key": "w_1eklft47q", + "type": "switch" + }, + "frequency_input": { + "key": "w_1eklft5qt", + "type": "switch" + }, + "water_meter_unit": { + "key": "w_1eklinki6", + "type": "select", + "options": { + "0": "PDPH1H1HAW1B0_FW539494_COMBO_w_1eklinki6_M_", + "1": "PDPH1H1HAW1B0_FW539494_COMBO_w_1eklinki6_LITER" + }, + "conversion": { + "PDPH1H1HAW1B0_FW539494_COMBO_w_1eklinki6_M_": "m3", + "PDPH1H1HAW1B0_FW539494_COMBO_w_1eklinki6_LITER": "L" + } + } +} diff --git a/tests/test_mapping_info.py b/tests/test_mapping_info.py index d187fe0..be16cf3 100644 --- a/tests/test_mapping_info.py +++ b/tests/test_mapping_info.py @@ -192,3 +192,37 @@ async def test_double_spa_entity_counts(self): assert len(types.get("number", [])) == 11 assert len(types.get("switch", [])) == 3 assert len(types.get("select", [])) == 1 + + +class TestMedoConnectMapping: + """Tests for the BWT MEDO CONNECT Wi-Fi mapping file (PDPH1H1HAW1B0_FW539494).""" + + @pytest.mark.asyncio + async def test_load_medo_connect_mapping(self): + """Test that the MEDO CONNECT mapping file loads successfully.""" + mapping_info = await MappingInfo.load("PDPH1H1HAW1B0", "539494") + assert mapping_info.status == RequestStatus.SUCCESS + assert mapping_info.mapping is not None + + @pytest.mark.asyncio + async def test_medo_connect_conversion_prefixes(self): + """Test conversion entries use the expected model/firmware label prefix.""" + mapping_info = await MappingInfo.load("PDPH1H1HAW1B0", "539494") + sensors = mapping_info.available_sensors() + + ph_type = sensors["ph_type_dosing"] + assert ph_type.conversion is not None + assert "|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklg44ro_ACID|" in ph_type.conversion + assert ph_type.conversion["|PDPH1H1HAW1B0_FW539494_LABEL_w_1eklg44ro_ACID|"] == "acid" + + @pytest.mark.asyncio + async def test_medo_connect_entity_counts(self): + """Test the total entity counts for the MEDO CONNECT mapping.""" + mapping_info = await MappingInfo.load("PDPH1H1HAW1B0", "539494") + types = mapping_info.available_types() + + assert len(types.get("sensor", [])) == 12 + assert len(types.get("binary_sensor", [])) == 6 + assert len(types.get("number", [])) == 1 + assert len(types.get("switch", [])) == 3 + assert len(types.get("select", [])) == 1