PySwitchbot 0.55.2__tar.gz → 0.55.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/PKG-INFO +1 -1
  2. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/PySwitchbot.egg-info/PKG-INFO +1 -1
  3. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/setup.py +1 -1
  4. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parser.py +1 -1
  5. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/relay_switch.py +10 -0
  6. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/discovery.py +4 -0
  7. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/tests/test_adv_parser.py +37 -5
  8. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/tests/test_relay_switch.py +15 -1
  9. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/LICENSE +0 -0
  10. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/MANIFEST.in +0 -0
  11. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/PySwitchbot.egg-info/SOURCES.txt +0 -0
  12. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/PySwitchbot.egg-info/dependency_links.txt +0 -0
  13. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/PySwitchbot.egg-info/requires.txt +0 -0
  14. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/PySwitchbot.egg-info/top_level.txt +0 -0
  15. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/README.md +0 -0
  16. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/setup.cfg +0 -0
  17. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/__init__.py +0 -0
  18. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parsers/__init__.py +0 -0
  19. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parsers/blind_tilt.py +0 -0
  20. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parsers/bot.py +0 -0
  21. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parsers/bulb.py +0 -0
  22. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parsers/ceiling_light.py +0 -0
  23. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parsers/contact.py +0 -0
  24. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parsers/curtain.py +0 -0
  25. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parsers/hub2.py +0 -0
  26. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parsers/humidifier.py +0 -0
  27. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parsers/keypad.py +0 -0
  28. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parsers/leak.py +0 -0
  29. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parsers/light_strip.py +0 -0
  30. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parsers/lock.py +0 -0
  31. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parsers/meter.py +0 -0
  32. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parsers/motion.py +0 -0
  33. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parsers/plug.py +0 -0
  34. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/adv_parsers/relay_switch.py +0 -0
  35. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/api_config.py +0 -0
  36. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/const.py +0 -0
  37. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/__init__.py +0 -0
  38. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/base_cover.py +0 -0
  39. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/base_light.py +0 -0
  40. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/blind_tilt.py +0 -0
  41. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/bot.py +0 -0
  42. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/bulb.py +0 -0
  43. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/ceiling_light.py +0 -0
  44. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/contact.py +0 -0
  45. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/curtain.py +0 -0
  46. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/device.py +0 -0
  47. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/humidifier.py +0 -0
  48. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/keypad.py +0 -0
  49. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/light_strip.py +0 -0
  50. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/lock.py +0 -0
  51. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/meter.py +0 -0
  52. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/motion.py +0 -0
  53. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/devices/plug.py +0 -0
  54. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/enum.py +0 -0
  55. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/switchbot/models.py +0 -0
  56. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/tests/test_base_cover.py +0 -0
  57. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/tests/test_blind_tilt.py +0 -0
  58. {pyswitchbot-0.55.2 → pyswitchbot-0.55.4}/tests/test_curtain.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PySwitchbot
3
- Version: 0.55.2
3
+ Version: 0.55.4
4
4
  Summary: A library to communicate with Switchbot
5
5
  Home-page: https://github.com/sblibs/pySwitchbot/
6
6
  Author: Daniel Hjelseth Hoyer
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PySwitchbot
3
- Version: 0.55.2
3
+ Version: 0.55.4
4
4
  Summary: A library to communicate with Switchbot
5
5
  Home-page: https://github.com/sblibs/pySwitchbot/
6
6
  Author: Daniel Hjelseth Hoyer
@@ -15,7 +15,7 @@ setup(
15
15
  "cryptography>=39.0.0",
16
16
  "pyOpenSSL>=23.0.0",
17
17
  ],
18
- version="0.55.2",
18
+ version="0.55.4",
19
19
  description="A library to communicate with Switchbot",
20
20
  long_description=long_description,
21
21
  long_description_content_type="text/markdown",
@@ -179,7 +179,7 @@ SUPPORTED_TYPES: dict[str, SwitchbotSupportedType] = {
179
179
  "func": process_woblindtilt,
180
180
  "manufacturer_id": 2409,
181
181
  },
182
- "3": {
182
+ "&": {
183
183
  "modelName": SwitchbotModel.LEAK,
184
184
  "modelFriendlyName": "Leak Detector",
185
185
  "func": process_leak,
@@ -17,6 +17,7 @@ COMMAND_TURN_OFF = f"{COMMAND_HEADER}0f70010000"
17
17
  COMMAND_TURN_ON = f"{COMMAND_HEADER}0f70010100"
18
18
  COMMAND_TOGGLE = f"{COMMAND_HEADER}0f70010200"
19
19
  COMMAND_GET_VOLTAGE_AND_CURRENT = f"{COMMAND_HEADER}0f7106000000"
20
+ COMMAND_GET_SWITCH_STATE = f"{COMMAND_HEADER}0f7101000000"
20
21
  PASSIVE_POLL_INTERVAL = 10 * 60
21
22
 
22
23
 
@@ -87,6 +88,15 @@ class SwitchbotRelaySwitch(SwitchbotEncryptedDevice):
87
88
  }
88
89
  return None
89
90
 
91
+ async def get_basic_info(self) -> dict[str, Any] | None:
92
+ """Get the current state of the switch."""
93
+ result = await self._send_command(COMMAND_GET_SWITCH_STATE)
94
+ if self._check_command_result(result, 0, {1}):
95
+ return {
96
+ "is_on": result[1] & 0x01 != 0,
97
+ }
98
+ return None
99
+
90
100
  def poll_needed(self, seconds_since_last_poll: float | None) -> bool:
91
101
  """Return if device needs polling."""
92
102
  if self._force_next_update:
@@ -118,6 +118,10 @@ class GetSwitchbotDevices:
118
118
  """Return all WoContact/Contact sensor devices with services data."""
119
119
  return await self._get_devices_by_model("d")
120
120
 
121
+ async def get_leakdetectors(self) -> dict[str, SwitchBotAdvertisement]:
122
+ """Return all Leak Detectors with services data."""
123
+ return await self._get_devices_by_model("&")
124
+
121
125
  async def get_locks(self) -> dict[str, SwitchBotAdvertisement]:
122
126
  """Return all WoLock/Locks devices with services data."""
123
127
  locks = await self._get_devices_by_model("o")
@@ -1758,7 +1758,7 @@ def test_leak_active():
1758
1758
  "low_battery": False,
1759
1759
  },
1760
1760
  "isEncrypted": False,
1761
- "model": "3",
1761
+ "model": "&",
1762
1762
  "modelFriendlyName": "Leak Detector",
1763
1763
  "modelName": SwitchbotModel.LEAK,
1764
1764
  "rawAdvData": b"&\x00N",
@@ -1782,7 +1782,7 @@ def test_leak_passive():
1782
1782
  data={
1783
1783
  "data": {},
1784
1784
  "isEncrypted": False,
1785
- "model": "3",
1785
+ "model": "&",
1786
1786
  "rawAdvData": None,
1787
1787
  },
1788
1788
  device=ble_device,
@@ -1812,7 +1812,7 @@ def test_leak_no_leak_detected():
1812
1812
  "low_battery": False,
1813
1813
  },
1814
1814
  "isEncrypted": False,
1815
- "model": "3",
1815
+ "model": "&",
1816
1816
  "modelFriendlyName": "Leak Detector",
1817
1817
  "modelName": SwitchbotModel.LEAK,
1818
1818
  "rawAdvData": b"&\x00d",
@@ -1844,7 +1844,7 @@ def test_leak_leak_detected():
1844
1844
  "low_battery": False,
1845
1845
  },
1846
1846
  "isEncrypted": False,
1847
- "model": "3",
1847
+ "model": "&",
1848
1848
  "modelFriendlyName": "Leak Detector",
1849
1849
  "modelName": SwitchbotModel.LEAK,
1850
1850
  "rawAdvData": b"&\x00d",
@@ -1876,7 +1876,7 @@ def test_leak_low_battery():
1876
1876
  "low_battery": False,
1877
1877
  },
1878
1878
  "isEncrypted": False,
1879
- "model": "3",
1879
+ "model": "&",
1880
1880
  "modelFriendlyName": "Leak Detector",
1881
1881
  "modelName": SwitchbotModel.LEAK,
1882
1882
  "rawAdvData": b"&\x00d",
@@ -1885,3 +1885,35 @@ def test_leak_low_battery():
1885
1885
  rssi=-73,
1886
1886
  active=True,
1887
1887
  )
1888
+
1889
+
1890
+ def test_leak_real_data_from_ha():
1891
+ """Test parse_advertisement_data for the leak detector."""
1892
+ ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "Any")
1893
+ adv_data = generate_advertisement_data(
1894
+ manufacturer_data={
1895
+ 2409: b"\\xd6407D1\\x02V\\x90\\x00\\x00\\x00\\x00\\x1e\\x05\\x00\\x00\\x00\\x00"
1896
+ }, # no leak, low battery
1897
+ service_data={"0000fd3d-0000-1000-8000-00805f9b34fb": b"&\\x00V"},
1898
+ rssi=-73,
1899
+ )
1900
+ result = parse_advertisement_data(ble_device, adv_data, SwitchbotModel.LEAK)
1901
+ assert result == SwitchBotAdvertisement(
1902
+ address="aa:bb:cc:dd:ee:ff",
1903
+ data={
1904
+ "data": {
1905
+ "leak": True,
1906
+ "tampered": False,
1907
+ "battery": 68,
1908
+ "low_battery": False,
1909
+ },
1910
+ "isEncrypted": False,
1911
+ "model": "&",
1912
+ "modelFriendlyName": "Leak Detector",
1913
+ "modelName": SwitchbotModel.LEAK,
1914
+ "rawAdvData": b"&\\x00V",
1915
+ },
1916
+ device=ble_device,
1917
+ rssi=-73,
1918
+ active=True,
1919
+ )
@@ -53,8 +53,22 @@ async def test_turn_on():
53
53
 
54
54
 
55
55
  @pytest.mark.asyncio
56
- async def test_trun_off():
56
+ async def test_turn_off():
57
57
  relay_switch_device = create_device_for_command_testing()
58
58
  relay_switch_device._send_command = AsyncMock(return_value=b"\x01")
59
59
  await relay_switch_device.turn_off()
60
60
  assert relay_switch_device.is_on() is False
61
+
62
+
63
+ @pytest.mark.asyncio
64
+ async def test_get_basic_info():
65
+ relay_switch_device = create_device_for_command_testing()
66
+ relay_switch_device._send_command = AsyncMock(return_value=b"\x01\x01")
67
+ info = await relay_switch_device.get_basic_info()
68
+ assert info["is_on"] is True
69
+ relay_switch_device._send_command = AsyncMock(return_value=b"\x01\x00")
70
+ info = await relay_switch_device.get_basic_info()
71
+ assert info["is_on"] is False
72
+ relay_switch_device._send_command = AsyncMock(return_value=b"\x00\x00")
73
+ info = await relay_switch_device.get_basic_info()
74
+ assert info is None
File without changes
File without changes
File without changes
File without changes