ソースを参照

feat: expose Climate Panel keystate for HA automations (#537)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Onero-testdev 4 日 前
コミット
b592cbb6bd
2 ファイル変更60 行追加0 行削除
  1. 18 0
      switchbot/adv_parsers/climate_panel.py
  2. 42 0
      tests/test_adv_parser.py

+ 18 - 0
switchbot/adv_parsers/climate_panel.py

@@ -28,6 +28,18 @@ def process_climate_panel(
     pir_state = bool(mfr_data[15] & 0x80)
     is_light = ((mfr_data[15] >> 1) & 0x03) == 0x02
 
+    # Keystate bytes report physical ON/OFF button presses. For each byte,
+    # Bit[7:5] is the press mode (0: power-on init, 1: single, 2: double,
+    # 3: long) and Bit[4:0] is a 1-30 cyclic counter that resets to 1 when the
+    # mode changes. A value of 0x00 is the power-on state and must not trigger.
+    # The raw byte is also exposed so consumers can watch it for any change.
+    on_keystate = mfr_data[13]
+    off_keystate = mfr_data[14]
+    on_keystate_mode = (on_keystate >> 5) & 0x07
+    on_keystate_counter = on_keystate & 0x1F
+    off_keystate_mode = (off_keystate >> 5) & 0x07
+    off_keystate_counter = off_keystate & 0x1F
+
     result = {
         "sequence_number": seq_number,
         "isOn": isOn,
@@ -38,6 +50,12 @@ def process_climate_panel(
         "humidity_alarm": humidity_alarm,
         "motion_detected": pir_state,
         "is_light": is_light,
+        "on_keystate": on_keystate,
+        "off_keystate": off_keystate,
+        "on_keystate_mode": on_keystate_mode,
+        "on_keystate_counter": on_keystate_counter,
+        "off_keystate_mode": off_keystate_mode,
+        "off_keystate_counter": off_keystate_counter,
     }
 
     _LOGGER.debug(

+ 42 - 0
tests/test_adv_parser.py

@@ -3801,6 +3801,12 @@ def test_humidifer_with_empty_data() -> None:
                 "motion_detected": True,
                 "temp_alarm": 0,
                 "temperature": 25.5,
+                "on_keystate": 0,
+                "off_keystate": 0,
+                "on_keystate_mode": 0,
+                "on_keystate_counter": 0,
+                "off_keystate_mode": 0,
+                "off_keystate_counter": 0,
             },
             b"\x00\x10\xf3\xd8",
             "Climate Panel",
@@ -3819,6 +3825,36 @@ def test_humidifer_with_empty_data() -> None:
                 "motion_detected": True,
                 "temp_alarm": 0,
                 "temperature": 25.9,
+                "on_keystate": 0,
+                "off_keystate": 0,
+                "on_keystate_mode": 0,
+                "on_keystate_counter": 0,
+                "off_keystate_mode": 0,
+                "off_keystate_counter": 0,
+            },
+            b"\x00\x10\xf3\xd8",
+            "Climate Panel",
+            SwitchbotModel.CLIMATE_PANEL,
+        ),
+        AdvTestCase(
+            b"\xb0\xe9\xfe\x84\x38\x05\x06\x14\x05\x99\x2d\x00\x00\x25\x62\xd4\x00\x0c\x04\x00",
+            b"\x00 _\x00\x10\xf3\xd8@",
+            {
+                "battery": 20,
+                "humidity": 45,
+                "sequence_number": 6,
+                "humidity_alarm": 0,
+                "isOn": False,
+                "is_light": True,
+                "motion_detected": True,
+                "temp_alarm": 0,
+                "temperature": 25.5,
+                "on_keystate": 37,
+                "off_keystate": 98,
+                "on_keystate_mode": 1,
+                "on_keystate_counter": 5,
+                "off_keystate_mode": 3,
+                "off_keystate_counter": 2,
             },
             b"\x00\x10\xf3\xd8",
             "Climate Panel",
@@ -4253,6 +4289,12 @@ def test_adv_active(test_case: AdvTestCase) -> None:
                 "motion_detected": True,
                 "temp_alarm": 0,
                 "temperature": 26.6,
+                "on_keystate": 0,
+                "off_keystate": 0,
+                "on_keystate_mode": 0,
+                "on_keystate_counter": 0,
+                "off_keystate_mode": 0,
+                "off_keystate_counter": 0,
             },
             b"\x00\x10\xf3\xd8",
             "Climate Panel",