Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,47 @@ Plug Mini (US). Where several values are listed, each identifies the same
product. Values are Byte 0 of the service data with Bit 7 cleared, as
listed in pySwitchbot's `SUPPORTED_TYPES`.

Newer products have no single-byte Device Type (Byte 0 of their service data, usually `0x00`, is
not in the table above). They are identified by a 4-byte **Product ID** at the end of the service
data: read the last 4 bytes; if they are not a known Product ID, read the 4 bytes before the last
byte. Most products have a `0x00…` and a `0x01…` form. These are the Product IDs in pySwitchbot's
`SUPPORTED_TYPES` (`_find_model_from_service_data_suffix`):

| Device Type | Product ID |
|----------------------------|------------|
| Art Frame | 0x00113e10, 0x01113e10 |
| Candle Warmer Lamp | 0x001122b8, 0x011122b8 |
| Circulator Fan Pro | 0x0011b340, 0x0111b340 |
| Climate Panel | 0x0010f3d8, 0x0110f3d8 |
| Floor Lamp | 0x0010d0b0, 0x0110d0b0 |
| Hub3 | 0x0010b940, 0x0110b940 |
| Hub4 | 0x00128248, 0x01128248 |
| K11+ Vacuum | 0x0010fba8, 0x0110fba8 |
| Keypad Vision | 0x00110378, 0x01110378 |
| Keypad Vision Pro | 0x00115198, 0x01115198 |
| Lock Nano | 0x00122488, 0x01122488 |
| Lock Pro Wifi | 0x0010ff90, 0x0110ff90 |
| Lock Ultra | 0x0010a5b8, 0x0110a5b8 |
| Lock Ultra Max | 0x00119fb8, 0x01119fb8 |
| Lock Vision | 0x00116908, 0x01116908 |
| Lock Vision Pro | 0x00116909, 0x01116909 |
| Outdoor Plug (EU) | 0x001218d0 |
| Permanent Outdoor Light | 0x0010d0b7, 0x0110d0b7 |
| Plug Mini (IT) | 0x001243c8, 0x011243c8 |
| Presence Sensor | 0x0010ccc8, 0x0110ccc8 |
| RGBIC Neon Rope Light | 0x0010d0b6, 0x0110d0b6 |
| RGBIC Neon Wire Rope Light | 0x0010d0b5, 0x0110d0b5 |
| RGBICWW Ceiling Light | 0x0011bb10, 0x0111bb10 |
| RGBICWW Floor Lamp | 0x0010d0b4, 0x0110d0b4 |
| RGBICWW Light Bars | 0x0011bef8, 0x0111bef8 |
| RGBICWW Strip Light | 0x0010d0b3, 0x0110d0b3 |
| S20 Vacuum | 0x0010e050, 0x0110e050 |
| Smart Thermostat Radiator | 0x00113640, 0x01113640 |
| Standing Fan | 0x00110760, 0x01110760 |
| Strip Light 3 | 0x0010d0b1, 0x0110d0b1 |
| UWB Lock | 0x00121100, 0x01121100 |
| Weather Station | 0x001053b0, 0x011053b0 |

The device type is in the service data of SCAN_RSP.

| Service data | | |
Expand Down
75 changes: 69 additions & 6 deletions devicetypes/lock.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ The following table is the Service Data of SCAN_RSP.

## Lock Pro, Lock Ultra and Lock Vision Pro Broadcast Message

Lock Pro (`$` / `0x04`), Lock Pro WiFi, Lock Ultra, Lock Ultra Max and Lock Vision Pro use a
different manufacturer data layout from the Lock and Lock Lite. Byte offsets below count from the
Lock Pro (`$` / `0x04`), Lock Pro WiFi, Lock Ultra, Lock Ultra Max, UWB Lock and Lock Vision Pro
use a different manufacturer data layout from the Lock and Lock Lite. Byte offsets below count from the
start of the manufacturer data payload, after the 2-byte company ID `0x0969`. This is the layout
[pySwitchbot](https://github.com/sblibs/pySwitchbot) parses (`switchbot/adv_parsers/lock.py`).

Expand All @@ -58,10 +58,32 @@ start of the manufacturer data payload, after the 2-byte company ID `0x0969`. Th
<tr><td>8</td><td>Door Info</td><td>bit7-6: update from secondary lock<br>bit5: door open, reported by the secondary lock<br>bit4: door open (0 closed, 1 open)<br>bit3: automatic locking paused<br>bit2-0: reserved</td></tr>
<tr><td>9</td><td>Battery</td><td>bit7: reserved<br>bit6-0: battery 0~100%</td></tr>
<tr><td>10</td><td>Double Lock</td><td>bit7: double lock mode<br>bit6: this is the secondary lock<br>bit5: manual unlock linkage<br>bit4-0: reserved</td></tr>
<tr><td>11</td><td>Alarms</td><td>bit7: unclosed door alarm<br>bit6: unlocked alarm<br><b>Lock Pro / Lock Pro WiFi:</b> bit5: low temperature alarm, bit2: left battery compartment alarm, bit1: right battery compartment alarm<br><b>Lock Ultra / Ultra Max / Vision Pro:</b> bit4: power alarm, bit2-0: battery status</td></tr>
<tr><td>11</td><td>Alarms</td><td>bit7: unclosed door alarm<br>bit6: unlocked alarm<br><b>Lock Pro / Lock Pro WiFi:</b> bit5: low temperature alarm, bit2: left battery compartment alarm, bit1: right battery compartment alarm<br><b>Lock Ultra / Ultra Max / UWB Lock / Vision Pro:</b> bit4: power alarm, bit2-0: battery status</td></tr>
</tbody>
</table>

## Lock Nano Broadcast Message

Lock Nano uses its own manufacturer data layout (pySwitchbot `process_lock_nano`). Byte offsets
count from the start of the manufacturer data payload, after the company ID.

<table>
<thead>
<tr><th>Byte</th><th>Field</th><th>Value</th></tr>
</thead>
<tbody>
<tr><td>0~5</td><td>MAC Address</td><td>Device MAC address</td></tr>
<tr><td>6</td><td>Sequence Number</td><td>Increases when the broadcast data is updated</td></tr>
<tr><td>7</td><td>Lock Info</td><td>bit7: calibrated<br>bit6-3: lock status (see <a href="#lock-status">Lock status</a>)</td></tr>
<tr><td>8</td><td>State</td><td>bit3: automatic locking paused<br>bit1: night latch<br>bit0: charging status, high bit</td></tr>
<tr><td>9</td><td>Battery</td><td>bit7: charging status, low bit<br>bit6-0: battery 0~100%</td></tr>
<tr><td>10</td><td>Alarms</td><td>bit6: unlocked alarm<br>bit5: low temperature alarm<br>bit4: power alarm<br>bit2-1: battery status<br>bit0: charging fault</td></tr>
</tbody>
</table>

The charging status is the 2-bit value from Byte 8 bit0 (high) and Byte 9 bit7 (low); `1` means
the battery is charging.

### Lock status

| Value | Status |
Expand All @@ -84,7 +106,7 @@ low battery.

<table>
<thead>
<tr><th>Command</th><th>Lock / Lock Lite</th><th>Lock Pro, Ultra, Ultra Max, Vision, Vision Pro, Pro WiFi</th></tr>
<tr><th>Command</th><th>Lock / Lock Lite</th><th>Lock Pro, Ultra, Ultra Max, UWB Lock, Nano, Vision, Vision Pro, Pro WiFi</th></tr>
</thead>
<tbody>
<tr><td>Lock</td><td><code>0x570f4e01011000</code></td><td><code>0x570f4e0101000000</code></td></tr>
Expand All @@ -101,7 +123,8 @@ The lock info and enable-notification commands end with a model byte:
| ----- | --------- | --------------------------- |
| Lock, Lock Lite | `0x570f4f8101` | `0x570e01001e00008101` |
| Lock Pro | `0x570f4f8104` | `0x570e01001e00008104` |
| Lock Ultra, Lock Ultra Max | `0x570f4f8107` | `0x570e01001e00008107` |
| Lock Ultra, Lock Ultra Max, UWB Lock | `0x570f4f8107` | `0x570e01001e00008107` |
| Lock Nano | `0x570f4f810c` | `0x570e01001e0000810c` |
| Lock Vision, Lock Vision Pro | `0x570f4f8102` | `0x570e01001e00008102` |
| Lock Pro WiFi | `0x570f4f810a` | `0x570e01001e0000810a` |

Expand All @@ -113,7 +136,7 @@ lock info data is the decrypted payload from Byte 4.

<table>
<thead>
<tr><th>Byte</th><th>Lock, Lock Lite, Lock Vision, Lock Vision Pro</th><th>Lock Pro, Ultra, Ultra Max, Pro WiFi</th></tr>
<tr><th>Byte</th><th>Lock, Lock Lite, Lock Vision, Lock Vision Pro</th><th>Lock Pro, Ultra, Ultra Max, UWB Lock, Pro WiFi</th></tr>
</thead>
<tbody>
<tr><td>0</td><td>bit7: calibrated<br>bit6-4: lock status<br>bit2: door open (Lock and Lock Vision Pro only)</td><td>bit7: calibrated<br>bit6-3: lock status</td></tr>
Expand All @@ -123,3 +146,43 @@ lock info data is the decrypted payload from Byte 4.
</table>

Lock Vision Pro uses the Lock layout here, although its broadcast uses the Lock Pro layout.

Lock Nano lock info data: Byte 0 bit7 calibrated, bit6-3 lock status; Byte 1 bit3 automatic
locking paused; Byte 5 bit6 unlocked alarm.

## Lock Ultra Quick Key

The Lock Ultra's Quick Key and basic properties are read and written with these commands (sent
encrypted, like the other lock commands). pySwitchbot implements them for the Lock Ultra only.

| Command | Bytes |
| ------- | ----- |
| Read settings | `0x570f4f0401` |
| Write settings | `0x570f4e040100` + update byte + value byte + motor speed byte |

The read response is: status, config byte, secondary config byte, motor speed, secondary motor
speed, then model-specific data. The config byte (and the write value byte) is:

<table>
<thead>
<tr><th>Bit</th><th>Setting</th></tr>
</thead>
<tbody>
<tr><td>7</td><td>Light (0 off, 1 on)</td></tr>
<tr><td>6</td><td>Sound (0 off, 1 on)</td></tr>
<tr><td>5</td><td>Reserved</td></tr>
<tr><td>4</td><td>Manual unlock linkage (0 off, 1 on)</td></tr>
<tr><td>3</td><td>Quick Key enabled (0 off, 1 on)</td></tr>
<tr><td>2</td><td>Quick Key trigger (0 single press, 1 double press)</td></tr>
<tr><td>1~0</td><td>Quick Key function: <code>00</code> lock only, <code>01</code> unlock only, <code>10</code> lock and unlock</td></tr>
</tbody>
</table>

In a write, each set bit of the update byte selects the setting in the same bit position for
writing (bit1 selects the whole 2-bit function field; bits 5 and 0 are always 0). The motor speed
is `0x00` high, `0x01` normal, `0x02` quiet, or `0xFF` to keep the current speed. The write
response is the status (`0x01`, or `0x06` with a low battery) followed by the new config byte.

Example: enable the Quick Key with double press and lock-and-unlock, keeping the motor speed:
`0x570f4e0401000e0eff`.