2222DEVICE_SET_MODE_KEY = "5703"
2323DEVICE_SET_EXTENDED_KEY = "570f"
2424
25+ # Plug Mini keys
26+ PLUG_ON_KEY = "570f50010180"
27+ PLUG_OFF_KEY = "570f50010100"
28+
2529# Bot keys
2630PRESS_KEY = "570100"
2731ON_KEY = "570101"
@@ -56,7 +60,7 @@ def _sb_uuid(comms_type: str = "service") -> UUID | str:
5660 return "Incorrect type, choose between: tx, rx or service"
5761
5862
59- def _process_wohand (data : bytes ) -> dict [str , bool | int ]:
63+ def _process_wohand (data : bytes , mfr_data : bytes | None ) -> dict [str , bool | int ]:
6064 """Process woHand/Bot services data."""
6165 _switch_mode = bool (data [1 ] & 0b10000000 )
6266
@@ -69,7 +73,9 @@ def _process_wohand(data: bytes) -> dict[str, bool | int]:
6973 return _bot_data
7074
7175
72- def _process_wocurtain (data : bytes , reverse : bool = True ) -> dict [str , bool | int ]:
76+ def _process_wocurtain (
77+ data : bytes , mfr_data : bytes | None , reverse : bool = True
78+ ) -> dict [str , bool | int ]:
7379 """Process woCurtain/Curtain services data."""
7480
7581 _position = max (min (data [3 ] & 0b01111111 , 100 ), 0 )
@@ -86,7 +92,7 @@ def _process_wocurtain(data: bytes, reverse: bool = True) -> dict[str, bool | in
8692 return _curtain_data
8793
8894
89- def _process_wosensorth (data : bytes ) -> dict [str , object ]:
95+ def _process_wosensorth (data : bytes , mfr_data : bytes | None ) -> dict [str , object ]:
9096 """Process woSensorTH/Temp sensor services data."""
9197
9298 _temp_sign = 1 if data [4 ] & 0b10000000 else - 1
@@ -104,7 +110,7 @@ def _process_wosensorth(data: bytes) -> dict[str, object]:
104110 return _wosensorth_data
105111
106112
107- def _process_wocontact (data : bytes ) -> dict [str , bool | int ]:
113+ def _process_wocontact (data : bytes , mfr_data : bytes | None ) -> dict [str , bool | int ]:
108114 """Process woContact Sensor services data."""
109115 return {
110116 "tested" : bool (data [1 ] & 0b10000000 ),
@@ -117,6 +123,15 @@ def _process_wocontact(data: bytes) -> dict[str, bool | int]:
117123 }
118124
119125
126+ def _process_woplugmini (data : bytes , mfr_data : bytes | None ) -> dict [str , bool | int ]:
127+ """Process plug mini."""
128+ return {
129+ "switchMode" : True ,
130+ "isOn" : mfr_data [7 ] == 0x80 ,
131+ "wifi_rssi" : mfr_data [9 ],
132+ }
133+
134+
120135@dataclass
121136class SwitchBotAdvertisement :
122137 """Switchbot advertisement."""
@@ -131,9 +146,12 @@ def parse_advertisement_data(
131146) -> SwitchBotAdvertisement | None :
132147 """Parse advertisement data."""
133148 _services = list (advertisement_data .service_data .values ())
149+ _mgr_datas = list (advertisement_data .manufacturer_data .values ())
150+
134151 if not _services :
135152 return
136153 _service_data = _services [0 ]
154+ _mfr_data = _mgr_datas [0 ] if _mgr_datas else None
137155 _model = chr (_service_data [0 ] & 0b01111111 )
138156
139157 supported_types : dict [str , dict [str , Any ]] = {
@@ -142,6 +160,7 @@ def parse_advertisement_data(
142160 "c" : {"modelName" : "WoCurtain" , "func" : _process_wocurtain },
143161 "T" : {"modelName" : "WoSensorTH" , "func" : _process_wosensorth },
144162 "i" : {"modelName" : "WoSensorTH" , "func" : _process_wosensorth },
163+ "g" : {"modelName" : "WoPlug" , "func" : _process_woplugmini },
145164 }
146165
147166 data = {
@@ -159,7 +178,7 @@ def parse_advertisement_data(
159178 "isEncrypted" : bool (_service_data [0 ] & 0b10000000 ),
160179 "model" : _model ,
161180 "modelName" : supported_types [_model ]["modelName" ],
162- "data" : supported_types [_model ]["func" ](_service_data ),
181+ "data" : supported_types [_model ]["func" ](_service_data , _mfr_data ),
163182 }
164183 )
165184
@@ -722,3 +741,34 @@ def is_calibrated(self) -> Any:
722741 """Return True curtain is calibrated."""
723742 # To get actual light level call update() first.
724743 return self ._get_adv_value ("calibration" )
744+
745+
746+ class SwitchbotPlugMini (SwitchbotDevice ):
747+ """Representation of a Switchbot plug mini."""
748+
749+ def __init__ (self , * args : Any , ** kwargs : Any ) -> None :
750+ """Switchbot plug mini constructor."""
751+ super ().__init__ (* args , ** kwargs )
752+ self ._settings : dict [str , Any ] = {}
753+
754+ async def update (self , interface : int | None = None ) -> None :
755+ """Update state of device."""
756+ await self .get_device_data (retry = self ._retry_count , interface = interface )
757+
758+ async def turn_on (self ) -> bool :
759+ """Turn device on."""
760+ result = await self ._sendcommand (PLUG_ON_KEY , self ._retry_count )
761+ return result [1 ] == 0x80
762+
763+ async def turn_off (self ) -> bool :
764+ """Turn device off."""
765+ result = await self ._sendcommand (PLUG_OFF_KEY , self ._retry_count )
766+ return result [1 ] == 0x00
767+
768+ def is_on (self ) -> Any :
769+ """Return switch state from cache."""
770+ # To get actual position call update() first.
771+ value = self ._get_adv_value ("isOn" )
772+ if value is None :
773+ return None
774+ return value
0 commit comments