PySwitchbot 2.7.0__tar.gz → 2.8.0__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.
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/PKG-INFO +9 -9
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/README.md +8 -8
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/pyproject.toml +1 -1
- pyswitchbot-2.8.0/switchbot/__version__.py +1 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/ceiling_light.py +47 -5
- pyswitchbot-2.7.0/switchbot/__version__.py +0 -1
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/LICENSE +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/__init__.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parser.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/__init__.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/_sensor_th.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/air_purifier.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/art_frame.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/blind_tilt.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/bot.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/bulb.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/ceiling_light.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/climate_panel.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/contact.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/curtain.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/fan.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/hub2.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/hub3.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/hubmini_matter.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/humidifier.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/keypad.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/keypad_vision.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/leak.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/light_strip.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/lock.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/meter.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/motion.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/plug.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/presence_sensor.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/relay_switch.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/remote.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/roller_shade.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/smart_thermostat_radiator.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/vacuum.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/adv_parsers/weather_station.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/api_config.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/const/__init__.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/const/air_purifier.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/const/climate.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/const/evaporative_humidifier.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/const/fan.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/const/hub2.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/const/hub3.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/const/light.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/const/lock.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/const/presence_sensor.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/__init__.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/air_purifier.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/art_frame.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/base_cover.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/base_light.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/blind_tilt.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/bot.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/bulb.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/contact.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/curtain.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/device.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/evaporative_humidifier.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/fan.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/humidifier.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/keypad.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/keypad_vision.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/light_strip.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/lock.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/meter.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/meter_pro.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/motion.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/plug.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/relay_switch.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/roller_shade.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/smart_thermostat_radiator.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/universal_remote.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/devices/vacuum.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/discovery.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/enum.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/helpers.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/models.py +0 -0
- {pyswitchbot-2.7.0 → pyswitchbot-2.8.0}/switchbot/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PySwitchbot
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.8.0
|
|
4
4
|
Summary: A library to communicate with Switchbot
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -93,10 +93,10 @@ from switchbot.discovery import GetSwitchbotDevices
|
|
|
93
93
|
from switchbot.devices import lock
|
|
94
94
|
from switchbot.const import SwitchbotModel
|
|
95
95
|
|
|
96
|
-
BLE_MAC="XX:XX:XX:XX:XX:XX"
|
|
97
|
-
KEY_ID="XX"
|
|
98
|
-
ENC_KEY="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
|
99
|
-
LOCK_MODEL=SwitchbotModel.LOCK_PRO
|
|
96
|
+
BLE_MAC = "XX:XX:XX:XX:XX:XX" # The MAC of your lock
|
|
97
|
+
KEY_ID = "XX" # The key-ID of your encryption-key for your lock
|
|
98
|
+
ENC_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" # The encryption-key with key-ID "XX"
|
|
99
|
+
LOCK_MODEL = SwitchbotModel.LOCK_PRO # Your lock model (here we use the Lock-Pro)
|
|
100
100
|
|
|
101
101
|
|
|
102
102
|
async def main():
|
|
@@ -117,10 +117,10 @@ from switchbot.discovery import GetSwitchbotDevices
|
|
|
117
117
|
from switchbot.devices import lock
|
|
118
118
|
from switchbot.const import SwitchbotModel
|
|
119
119
|
|
|
120
|
-
BLE_MAC="XX:XX:XX:XX:XX:XX"
|
|
121
|
-
KEY_ID="XX"
|
|
122
|
-
ENC_KEY="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
|
123
|
-
LOCK_MODEL=SwitchbotModel.LOCK_PRO
|
|
120
|
+
BLE_MAC = "XX:XX:XX:XX:XX:XX" # The MAC of your lock
|
|
121
|
+
KEY_ID = "XX" # The key-ID of your encryption-key for your lock
|
|
122
|
+
ENC_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" # The encryption-key with key-ID "XX"
|
|
123
|
+
LOCK_MODEL = SwitchbotModel.LOCK_PRO # Your lock model (here we use the Lock-Pro)
|
|
124
124
|
|
|
125
125
|
|
|
126
126
|
async def main():
|
|
@@ -62,10 +62,10 @@ from switchbot.discovery import GetSwitchbotDevices
|
|
|
62
62
|
from switchbot.devices import lock
|
|
63
63
|
from switchbot.const import SwitchbotModel
|
|
64
64
|
|
|
65
|
-
BLE_MAC="XX:XX:XX:XX:XX:XX"
|
|
66
|
-
KEY_ID="XX"
|
|
67
|
-
ENC_KEY="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
|
68
|
-
LOCK_MODEL=SwitchbotModel.LOCK_PRO
|
|
65
|
+
BLE_MAC = "XX:XX:XX:XX:XX:XX" # The MAC of your lock
|
|
66
|
+
KEY_ID = "XX" # The key-ID of your encryption-key for your lock
|
|
67
|
+
ENC_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" # The encryption-key with key-ID "XX"
|
|
68
|
+
LOCK_MODEL = SwitchbotModel.LOCK_PRO # Your lock model (here we use the Lock-Pro)
|
|
69
69
|
|
|
70
70
|
|
|
71
71
|
async def main():
|
|
@@ -86,10 +86,10 @@ from switchbot.discovery import GetSwitchbotDevices
|
|
|
86
86
|
from switchbot.devices import lock
|
|
87
87
|
from switchbot.const import SwitchbotModel
|
|
88
88
|
|
|
89
|
-
BLE_MAC="XX:XX:XX:XX:XX:XX"
|
|
90
|
-
KEY_ID="XX"
|
|
91
|
-
ENC_KEY="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
|
92
|
-
LOCK_MODEL=SwitchbotModel.LOCK_PRO
|
|
89
|
+
BLE_MAC = "XX:XX:XX:XX:XX:XX" # The MAC of your lock
|
|
90
|
+
KEY_ID = "XX" # The key-ID of your encryption-key for your lock
|
|
91
|
+
ENC_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" # The encryption-key with key-ID "XX"
|
|
92
|
+
LOCK_MODEL = SwitchbotModel.LOCK_PRO # Your lock model (here we use the Lock-Pro)
|
|
93
93
|
|
|
94
94
|
|
|
95
95
|
async def main():
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.8.0"
|
|
@@ -27,6 +27,7 @@ class SwitchbotCeilingLight(SwitchbotSequenceBaseLight):
|
|
|
27
27
|
_turn_off_command = f"{CEILING_LIGHT_CONTROL_HEADER}02FF01FFFF"
|
|
28
28
|
_set_brightness_command = f"{CEILING_LIGHT_CONTROL_HEADER}01FF01{{}}"
|
|
29
29
|
_set_color_temp_command = f"{CEILING_LIGHT_CONTROL_HEADER}01FF01{{}}"
|
|
30
|
+
_set_night_light_command = f"{CEILING_LIGHT_CONTROL_HEADER}01{{}}01{{}}"
|
|
30
31
|
_get_basic_info_command = ["5702", "570f5581"]
|
|
31
32
|
|
|
32
33
|
@property
|
|
@@ -37,9 +38,8 @@ class SwitchbotCeilingLight(SwitchbotSequenceBaseLight):
|
|
|
37
38
|
@property
|
|
38
39
|
def color_mode(self) -> ColorMode:
|
|
39
40
|
"""Return the current color mode."""
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
)
|
|
41
|
+
value = self._state.get("color_mode", self._get_adv_value("color_mode"))
|
|
42
|
+
device_mode = CeilingLightColorMode(value if value is not None else 10)
|
|
43
43
|
return _CEILING_LIGHT_COLOR_MODE_MAP.get(device_mode, ColorMode.OFF)
|
|
44
44
|
|
|
45
45
|
@update_after_operation
|
|
@@ -52,6 +52,40 @@ class SwitchbotCeilingLight(SwitchbotSequenceBaseLight):
|
|
|
52
52
|
result = await self._send_command(self._set_brightness_command.format(hex_data))
|
|
53
53
|
return self._check_command_result(result, 0, {1})
|
|
54
54
|
|
|
55
|
+
@update_after_operation
|
|
56
|
+
async def set_night_light(self, is_on: bool, brightness: int | None = None) -> bool:
|
|
57
|
+
"""
|
|
58
|
+
Toggle night light color mode on or off.
|
|
59
|
+
|
|
60
|
+
Powers the light on and, unless `brightness` is given, resets
|
|
61
|
+
brightness to 20% (night) or 100% (otherwise) — mirroring the
|
|
62
|
+
official app's night light toggle.
|
|
63
|
+
"""
|
|
64
|
+
color_mode = (
|
|
65
|
+
CeilingLightColorMode.NIGHT if is_on else CeilingLightColorMode.COLOR_TEMP
|
|
66
|
+
)
|
|
67
|
+
hex_mode = f"{color_mode.value:02X}"
|
|
68
|
+
if brightness is None:
|
|
69
|
+
# The app's night light toggle always pairs NIGHT with 20%
|
|
70
|
+
# brightness and COLOR_TEMP with 100%, carrying over the
|
|
71
|
+
# last-set color temp.
|
|
72
|
+
brightness = 20 if is_on else 100
|
|
73
|
+
else:
|
|
74
|
+
self._validate_brightness(brightness)
|
|
75
|
+
color_temp = self._state.get("cw", DEFAULT_COLOR_TEMP)
|
|
76
|
+
hex_data = f"{brightness:02X}{color_temp:04X}"
|
|
77
|
+
result = await self._send_command(
|
|
78
|
+
self._set_night_light_command.format(hex_mode, hex_data)
|
|
79
|
+
)
|
|
80
|
+
return self._check_command_result(result, 0, {1})
|
|
81
|
+
|
|
82
|
+
def is_night_light_on(self) -> bool | None:
|
|
83
|
+
"""Return the cached night light color mode state."""
|
|
84
|
+
value = self._state.get("color_mode")
|
|
85
|
+
if value is None:
|
|
86
|
+
return None
|
|
87
|
+
return value == CeilingLightColorMode.NIGHT.value
|
|
88
|
+
|
|
55
89
|
async def get_basic_info(self) -> dict[str, Any] | None:
|
|
56
90
|
"""Get device basic settings."""
|
|
57
91
|
if not (
|
|
@@ -60,11 +94,19 @@ class SwitchbotCeilingLight(SwitchbotSequenceBaseLight):
|
|
|
60
94
|
return None
|
|
61
95
|
_version_info, _data = res
|
|
62
96
|
|
|
63
|
-
|
|
97
|
+
color_temp = int.from_bytes(_data[3:5], "big")
|
|
98
|
+
if self.min_temp <= color_temp <= self.max_temp:
|
|
99
|
+
self._state["cw"] = color_temp
|
|
100
|
+
else:
|
|
101
|
+
self._state.setdefault("cw", DEFAULT_COLOR_TEMP)
|
|
102
|
+
# Cached in self._state (not the adv-data merge) because the
|
|
103
|
+
# advertisement parser hardcodes color_mode, which would otherwise
|
|
104
|
+
# clobber this value on the next advertisement.
|
|
105
|
+
self._state["color_mode"] = (_data[1] & 0b01000000) >> 6
|
|
64
106
|
|
|
65
107
|
return {
|
|
66
108
|
"isOn": bool(_data[1] & 0b10000000),
|
|
67
|
-
"color_mode":
|
|
109
|
+
"color_mode": self._state["color_mode"],
|
|
68
110
|
"brightness": _data[2] & 0b01111111,
|
|
69
111
|
"cw": self._state["cw"],
|
|
70
112
|
"firmware": _version_info[2] / 10.0,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.7.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|