Skip to content

Commit

Permalink
Lock And Raspbery Pi Zero support (#4) (#232)
Browse files Browse the repository at this point in the history
* make compatible with ras pi zero w (node 12 max)

* set correct manufacturerdata length for lock

* add wolock encrypted command support

* resolve discover even if no devices found

* update readme
  • Loading branch information
brozef authored Feb 13, 2024
1 parent c0a3668 commit 7553f11
Show file tree
Hide file tree
Showing 4 changed files with 323 additions and 65 deletions.
56 changes: 52 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</span>

The node-switchbot is a Node.js module which allows you to move your [Switchbot (Bot)'s](https://www.switch-bot.com/bot) arm
and [Switchbot Curtain](https://www.switch-bot.com/products/switchbot-curtain),
and [Switchbot Curtain](https://www.switch-bot.com/products/switchbot-curtain), operate your [Switchbot Lock](https://www.switch-bot.com/products/switchbot-lock),
also monitor the temperature/humidity from [SwitchBot Thermometer & Hygrometer (Meter)](https://www.switch-bot.com/meter)
as well as the status from [SwitchBot Motion Sensor](https://www.switch-bot.com/products/motion-sensor)
and [SwitchBot Contact Sensor](https://www.switch-bot.com/products/contact-sensor)
Expand Down Expand Up @@ -43,21 +43,26 @@ But some functionalities of this module were developed through trial and error.
- [`disconnect()` method](#disconnect-method)
- [`onconnect` event handler](#onconnect-event-handler)
- [`ondisconnect` event handler](#ondisconnect-event-handler)
- [`WoHand` object](#switchbotdevicewohand-object)
- [`WoHand` object](#wohand-object)
- [`press()` method](#press-method)
- [`turnOn()` method](#turnon-method)
- [`turnOff()` method](#turnoff-method)
- [`down()` method](#down-method)
- [`up()` method](#up-method)
- [`WoCurtain` object](#switchbotdevicewocurtain-object)
- [`WoCurtain` object](#wocurtain-object)
- [`open()` method](#open-method)
- [`close()` method](#close-method)
- [`pause()` method](#pause-method)
- [`runToPos()` method](#runtopos-method)
- [`WoPlugMini` object](#switchbotdevicewoplugmini-object)
- [`WoPlugMini` object](#woplugmini-object)
- [`turnOn()` method](#turnon-method)
- [`turnOff()` method](#turnoff-method)
- [`toggle()` method](#toggle-method)
- [`WoSmartLock` object](#wosmartlock-object)
- [`lock()` method](#lock-method)
- [`unlock()` method](#unlock-method)
- [`unlock_no_unlatch()` method](#unlock_no_unlatch-method)
- [`info()` method](#info-method)
- [Advertisement data](#advertisement-data)
- [Bot (WoHand)](#bot-wohand)
- [Meter (WoSensorTH)](#meter-wosensorth)
Expand Down Expand Up @@ -876,6 +881,49 @@ If no connection is established with the device, this method automatically estab

---

---
## `WoSmartLock` object

The `WoSmartLock ` object represents a SmartLock, which is created through the discovery process triggered by the [`Switchbot.discover()`](#Switchbot-discover-method) method.

Actually, the `WoSmartLock ` is an object inherited from the [`SwitchbotDevice`](#SwitchbotDevice-object). You can use not only the method described in this section but also the properties and methods implemented in the [`SwitchbotDevice`](#SwitchbotDevice-object) object.

### `setKey()` method

The `setKey()` method initialises the key information required for encrypted communication with the SmartLock

This must be set before any control commands are sent to the device. To obtain the key information you will need to use an external tool - see [`pySwitchbot`](https://github.com/Danielhiversen/pySwitchbot/tree/master?tab=readme-ov-file#obtaining-locks-encryption-key) project for an example script.

| Property | Type | Description |
| :--------------- | :------ | :------------------------------------------------------------------------------------------------------------------------------------- |
| `keyId` | String | unique2 character ID for the key. (e.g., `"ff"`) returned from the SwitchBot api for your device |
| `encryptionKey` | String | the unique encryption key returned from the SwitchBot api for your device |

### `lock()` method

The `lock()` method sends a lock command to the SmartLock. This method returns a `Promise` object. A `boolean` value indicating whether the SmartLock is locked (`true`), is passed to the `resolve()` method of the Promise.

If no connection is established with the device, this method automatically establishes a connection with the device, then finally closes the connection. You don't have to call the [`connect()`](#SwitchbotDevice-connect-method) method in advance.

### `unlock()` method

The `unlock()` method sends an unlock command to the SmartLock. This method returns a `Promise` object. A `boolean` value indicating whether the SmartLock is locked (`false`), is passed to the `resolve()` method of the Promise.

If no connection is established with the device, this method automatically establishes a connection with the device, then finally closes the connection. You don't have to call the [`connect()`](#SwitchbotDevice-connect-method) method in advance.

### `unlockNoUnlatch()` method

The `unlockNoUnlatch()` method sends a partial unlock command to the SmartLock, unlocking without the full unlatch.

If no connection is established with the device, this method automatically establishes a connection with the device, then finally closes the connection. You don't have to call the [`connect()`](#SwitchbotDevice-connect-method) method in advance.

### `info()` method

The `info()` method retreieves state information from the SmartLock, This method returns a `Promise` object. An `object` value indicating with the state infor, is passed to the `resolve()` method of the Promise.

If no connection is established with the device, this method automatically establishes a connection with the device, then finally closes the connection. You don't have to call the [`connect()`](#SwitchbotDevice-connect-method) method in advance.


## Advertisement data

After the [`startScan()`](#startscan-method) method is invoked, the [`onadvertisement`](#Switchbot-onadvertisement-event-handler) event handler will be called whenever an advertising packet comes from the switchbot devices. An object containing the properties as follows will be passed to the event handler:
Expand Down
23 changes: 12 additions & 11 deletions src/device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/
import { Characteristic, Peripheral, Service } from '@abandonware/noble';
import { ParameterChecker } from './parameter-checker.js';
import { Advertising } from './advertising.js';
import { Advertising, Ad } from './advertising.js';

type Chars = {
write: Characteristic | null,
Expand Down Expand Up @@ -47,11 +47,12 @@ export class SwitchbotDevice {
this._chars = null;

// Save the device information
const ad = Advertising.parse(peripheral);
this._id = ad?.id;
this._address = ad?.address;
this._model = ad?.serviceData.model;
this._modelName = ad?.serviceData.modelName;
const ad: Ad = Advertising.parse(peripheral);
this._id = ad ? ad.id : null;
this._address = ad ? ad.address : null;
this._model = ad ? ad.serviceData.model : null;
this._modelName = ad ? ad.serviceData.modelName : null;


this._was_connected_explicitly = false;
this._connected = false;
Expand Down Expand Up @@ -286,7 +287,7 @@ export class SwitchbotDevice {

_subscribe() {
return new Promise<void>((resolve, reject) => {
const char = this._chars?.notify;
const char = this._chars ? this._chars.notify : null;
if (!char) {
reject(new Error('No notify characteristic was found.'));
return;
Expand All @@ -306,7 +307,7 @@ export class SwitchbotDevice {

_unsubscribe() {
return new Promise<void>((resolve) => {
const char = this._chars?.notify;
const char = this._chars ? this._chars.notify : null;
if (!char) {
resolve();
return;
Expand Down Expand Up @@ -380,7 +381,7 @@ export class SwitchbotDevice {
let name = '';
this._connect()
.then(() => {
if (!this._chars?.device) {
if (!this._chars || !this._chars.device) {
// Some models of Bot don't seem to support this characteristic UUID
throw new Error(
'The device does not support the characteristic UUID 0x' +
Expand Down Expand Up @@ -434,7 +435,7 @@ export class SwitchbotDevice {
const buf = Buffer.from(name, 'utf8');
this._connect()
.then(() => {
if (!this._chars?.device) {
if (!this._chars || !this._chars.device) {
// Some models of Bot don't seem to support this characteristic UUID
throw new Error(
'The device does not support the characteristic UUID 0x' +
Expand Down Expand Up @@ -470,7 +471,7 @@ export class SwitchbotDevice {

this._connect()
.then(() => {
if (!this._chars?.write) {
if (!this._chars || !this._chars.write) {
return reject(new Error('No characteristics available.'));
}
return this._write(this._chars.write, req_buf);
Expand Down
Loading

0 comments on commit 7553f11

Please sign in to comment.