Skip to content

Commit 04b493f

Browse files
committed
Add Lock Ultra Support
1 parent 1db1d3b commit 04b493f

3 files changed

Lines changed: 43 additions & 1 deletion

File tree

src/device.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ export enum SwitchBotModel {
163163
PlugMiniJP = 'W2001400/W2001401',
164164
Lock = 'W1601700',
165165
LockPro = 'W3500000',
166+
LockUltra = 'W3600000',
166167
Keypad = 'W2500010',
167168
KeypadTouch = 'W2500020',
168169
K10 = 'K10+',
@@ -212,6 +213,7 @@ export enum SwitchBotBLEModel {
212213
PlugMiniJP = 'j', // Only available in Japan.
213214
Lock = 'o',
214215
LockPro = '$',
216+
LockUltra = 'U',
215217
CeilingLight = 'q', // Currently only available in Japan.
216218
CeilingLightPro = 'n', // Currently only available in Japan.
217219
BlindTilt = 'x',
@@ -240,6 +242,7 @@ export enum SwitchBotBLEModelName {
240242
MeterProCO2 = 'WoSensorTHPc',
241243
Lock = 'WoSmartLock',
242244
LockPro = 'WoSmartLockPro',
245+
LockUltra = 'WoSmartLockUltra',
243246
PresenceSensor = 'WoPresence',
244247
PlugMini = 'WoPlugMini',
245248
StripLight = 'WoStrip',
@@ -271,6 +274,7 @@ export enum SwitchBotBLEModelFriendlyName {
271274
Meter = 'Meter',
272275
Lock = 'Lock',
273276
LockPro = 'Lock Pro',
277+
LockUltra = 'Lock Ultra',
274278
PlugMini = 'Plug Mini',
275279
StripLight = 'Strip Light',
276280
MeterPlus = 'Meter Plus',
@@ -1093,6 +1097,8 @@ export class Advertising {
10931097
return WoSmartLock.parseServiceData(serviceData, manufacturerData, emitLog)
10941098
case SwitchBotBLEModel.LockPro:
10951099
return WoSmartLockPro.parseServiceData(serviceData, manufacturerData, emitLog)
1100+
case SwitchBotBLEModel.LockUltra:
1101+
return WoSmartLockUltra.parseServiceData(serviceData, manufacturerData, emitLog)
10961102
case SwitchBotBLEModel.BlindTilt:
10971103
return WoBlindTilt.parseServiceData(serviceData, manufacturerData, emitLog)
10981104
case SwitchBotBLEModel.Leak:
@@ -3648,6 +3654,30 @@ export class WoSmartLockPro extends SwitchbotDevice {
36483654
}
36493655
}
36503656

3657+
/**
3658+
* Class representing a WoSmartLockUltra device.
3659+
* Reuses the LockPro parsing and encrypted command behavior but reports a distinct model.
3660+
*/
3661+
export class WoSmartLockUltra extends WoSmartLockPro {
3662+
constructor(peripheral: NobleTypes['peripheral'], noble: NobleTypes['noble']) {
3663+
super(peripheral, noble)
3664+
}
3665+
3666+
static async parseServiceData(
3667+
serviceData: Buffer,
3668+
manufacturerData: Buffer,
3669+
emitLog: (level: string, message: string) => void,
3670+
) {
3671+
const data = await WoSmartLockPro.parseServiceData(serviceData, manufacturerData, emitLog)
3672+
if (!data) return null
3673+
const out = data as any
3674+
out.model = SwitchBotBLEModel.LockUltra
3675+
out.modelName = SwitchBotBLEModelName.LockUltra
3676+
out.modelFriendlyName = SwitchBotBLEModelFriendlyName.LockUltra
3677+
return out
3678+
}
3679+
}
3680+
36513681
/**
36523682
* Class representing a WoStrip device.
36533683
* @see https://github.com/OpenWonderLabs/SwitchBotAPI-BLE/blob/latest/devicetypes/ledstriplight.md

src/settings.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,14 @@ export enum WoSmartLockCommands {
7373
ENABLE_NOTIFICATIONS = '570e01001e00008101',
7474
DISABLE_NOTIFICATIONS = '570e00',
7575
}
76+
77+
// Lock Ultra uses the same command structure as Lock Pro (AES/IV based).
78+
export enum WoSmartLockUltraCommands {
79+
GET_CKIV = '570f2103',
80+
LOCK_INFO = '570f4f8102',
81+
UNLOCK = '570f4e0101000080',
82+
UNLOCK_NO_UNLATCH = '570f4e01010000a0',
83+
LOCK = '570f4e0101000000',
84+
ENABLE_NOTIFICATIONS = '570e01001e00008101',
85+
DISABLE_NOTIFICATIONS = '570e00',
86+
}

src/switchbot-ble.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type { ad, NobleTypes, onadvertisement, ondiscover, Params, Rule } from '
66

77
import { EventEmitter } from 'node:events'
88

9-
import { Advertising, LogLevel, SwitchBotBLEModel, SwitchbotDevice, WoBlindTilt, WoBulb, WoCeilingLight, WoContact, WoCurtain, WoHand, WoHub2, WoHumi, WoHumi2, WoIOSensorTH, WoKeypad, WoLeak, WoPlugMiniJP, WoPlugMiniUS, WoPresence, WoRelaySwitch1, WoRelaySwitch1PM, WoRemote, WoSensorTH, WoSensorTHPlus, WoSensorTHPro, WoSensorTHProCO2, WoSmartLock, WoSmartLockPro, WoStrip } from './device.js'
9+
import { Advertising, LogLevel, SwitchBotBLEModel, SwitchbotDevice, WoBlindTilt, WoBulb, WoCeilingLight, WoContact, WoCurtain, WoHand, WoHub2, WoHumi, WoHumi2, WoIOSensorTH, WoKeypad, WoLeak, WoPlugMiniJP, WoPlugMiniUS, WoPresence, WoRelaySwitch1, WoRelaySwitch1PM, WoRemote, WoSensorTH, WoSensorTHPlus, WoSensorTHPro, WoSensorTHProCO2, WoSmartLock, WoSmartLockPro, WoSmartLockUltra, WoStrip } from './device.js'
1010
import { parameterChecker } from './parameter-checker.js'
1111
import { DEFAULT_DISCOVERY_DURATION, PRIMARY_SERVICE_UUID_LIST } from './settings.js'
1212

@@ -232,6 +232,7 @@ export class SwitchBotBLE extends EventEmitter {
232232
case SwitchBotBLEModel.PlugMiniJP: return new WoPlugMiniJP(peripheral, this.noble)
233233
case SwitchBotBLEModel.Lock: return new WoSmartLock(peripheral, this.noble)
234234
case SwitchBotBLEModel.LockPro: return new WoSmartLockPro(peripheral, this.noble)
235+
case (SwitchBotBLEModel.LockUltra as any): return new WoSmartLockUltra(peripheral, this.noble)
235236
case SwitchBotBLEModel.BlindTilt: return new WoBlindTilt(peripheral, this.noble)
236237
case SwitchBotBLEModel.Keypad: return new WoKeypad(peripheral, this.noble)
237238
case SwitchBotBLEModel.RelaySwitch1: return new WoRelaySwitch1(peripheral, this.noble)

0 commit comments

Comments
 (0)