diff --git a/src/advertising.ts b/src/advertising.ts index 1dddc3a4..3350c429 100644 --- a/src/advertising.ts +++ b/src/advertising.ts @@ -1,5 +1,7 @@ import { Buffer } from 'buffer'; +import { Peripheral } from '@abandonware/noble'; + import { WoHand } from './device/wohand.js'; import { WoCurtain } from './device/wocurtain.js'; import { WoBlindTilt } from './device/woblindtilt.js'; @@ -13,6 +15,13 @@ import { WoBulb } from './device/wobulb.js'; import { WoStrip } from './device/wostrip.js'; import { WoSmartLock } from './device/wosmartlock.js'; +export type Ad = { + id: string; + address: string; + rssi: number, + serviceData: any; +} | null + export class Advertising { constructor() {} @@ -81,7 +90,7 @@ export class Advertising { * @param onlog - The logging function. * @returns The parsed data of the peripheral device. */ - static parse(peripheral, onlog?) { + static parse(peripheral: Peripheral, onlog?: (message: string) => void) { const ad = peripheral.advertisement; if (!ad || !ad.serviceData) { return null; @@ -150,16 +159,14 @@ export class Advertising { } let address = peripheral.address || ''; if (address === '') { - address = peripheral.advertisement.manufacturerData || ''; - if (address !== '') { - const str = peripheral.advertisement.manufacturerData - .toString('hex') - .slice(4, 16); + const str = peripheral.advertisement.manufacturerData + .toString('hex') + .slice(4, 16); + if (str !== '') { address = str.substr(0, 2); for (let i = 2; i < str.length; i += 2) { address = address + ':' + str.substr(i, 2); } - // console.log("address", typeof(address), address); } } else { address = address.replace(/-/g, ':'); diff --git a/src/device.ts b/src/device.ts index 9aa60753..f11405b2 100644 --- a/src/device.ts +++ b/src/device.ts @@ -1,26 +1,26 @@ import { Buffer } from 'buffer'; +import { Characteristic, Peripheral, Service } from '@abandonware/noble'; import { ParameterChecker } from './parameter-checker.js'; import { Advertising } from './advertising.js'; -type ad = { - id: any; - address: any; - rssi: any; - serviceData: any; +type Chars = { + write: Characteristic | null, + notify: Characteristic | null, + device: Characteristic | null, } | null; export class SwitchbotDevice { _peripheral; _noble; - _chars; - _SERV_UUID_PRIMARY; - _CHAR_UUID_WRITE; - _CHAR_UUID_NOTIFY; - _CHAR_UUID_DEVICE; - _READ_TIMEOUT_MSEC; - _WRITE_TIMEOUT_MSEC; - _COMMAND_TIMEOUT_MSEC; + _chars: Chars; + _SERV_UUID_PRIMARY = 'cba20d00224d11e69fb80002a5d5c51b'; + _CHAR_UUID_WRITE = 'cba20002224d11e69fb80002a5d5c51b'; + _CHAR_UUID_NOTIFY = 'cba20003224d11e69fb80002a5d5c51b'; + _CHAR_UUID_DEVICE = '2a00'; + _READ_TIMEOUT_MSEC = 3000; + _WRITE_TIMEOUT_MSEC = 3000; + _COMMAND_TIMEOUT_MSEC = 3000; _id; _address; _model; @@ -39,22 +39,13 @@ export class SwitchbotDevice { * | | | which represents this device * - noble | Noble | Required | The Noble object created by the noble module. * ---------------------------------------------------------------- */ - constructor(peripheral, noble) { + constructor(peripheral: Peripheral, noble: any) { this._peripheral = peripheral; this._noble = noble; this._chars = null; - this._SERV_UUID_PRIMARY = 'cba20d00224d11e69fb80002a5d5c51b'; - this._CHAR_UUID_WRITE = 'cba20002224d11e69fb80002a5d5c51b'; - this._CHAR_UUID_NOTIFY = 'cba20003224d11e69fb80002a5d5c51b'; - this._CHAR_UUID_DEVICE = '2a00'; - - this._READ_TIMEOUT_MSEC = 3000; - this._WRITE_TIMEOUT_MSEC = 3000; - this._COMMAND_TIMEOUT_MSEC = 3000; - // Save the device information - const ad: ad = Advertising.parse(peripheral); + const ad = Advertising.parse(peripheral); this._id = ad?.id; this._address = ad?.address; this._model = ad?.serviceData.model; @@ -95,14 +86,14 @@ export class SwitchbotDevice { } // Setters - set onconnect(func) { + set onconnect(func: () => void) { if (!func || typeof func !== 'function') { throw new Error('The `onconnect` must be a function.'); } this._onconnect = func; } - set ondisconnect(func) { + set ondisconnect(func: () => void) { if (!func || typeof func !== 'function') { throw new Error('The `ondisconnect` must be a function.'); } @@ -185,7 +176,7 @@ export class SwitchbotDevice { }); } - _getCharacteristics() { + _getCharacteristics(): Promise { return new Promise((resolve, reject) => { // Set timeout timer let timer: NodeJS.Timeout | null = setTimeout(() => { @@ -279,7 +270,7 @@ export class SwitchbotDevice { }); } - _discoverCharacteristics(service) { + _discoverCharacteristics(service: Service) { return new Promise((resolve, reject) => { service.discoverCharacteristics([], (error, char_list) => { if (error) { @@ -293,7 +284,7 @@ export class SwitchbotDevice { _subscribe() { return new Promise((resolve, reject) => { - const char = this._chars.notify; + const char = this._chars?.notify; if (!char) { reject(new Error('No notify characteristic was found.')); return; @@ -313,7 +304,7 @@ export class SwitchbotDevice { _unsubscribe() { return new Promise((resolve) => { - const char = this._chars.notify; + const char = this._chars?.notify; if (!char) { resolve(); return; @@ -387,7 +378,7 @@ export class SwitchbotDevice { let name = ''; this._connect() .then(() => { - if (!this._chars.device) { + if (!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' + @@ -422,7 +413,7 @@ export class SwitchbotDevice { * - Promise object * Nothing will be passed to the `resolve()`. * ---------------------------------------------------------------- */ - setDeviceName(name) { + setDeviceName(name: string) { return new Promise((resolve, reject) => { // Check the parameters const valid = ParameterChecker.check( @@ -441,7 +432,7 @@ export class SwitchbotDevice { const buf = Buffer.from(name, 'utf8'); this._connect() .then(() => { - if (!this._chars.device) { + if (!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' + @@ -477,7 +468,7 @@ export class SwitchbotDevice { this._connect() .then(() => { - if (!this._chars) { + if (!this._chars?.write) { return reject(new Error('No characteristics available.')); } return this._write(this._chars.write, req_buf); @@ -518,7 +509,7 @@ export class SwitchbotDevice { } // Read data from the specified characteristic - _read(char) { + _read(char: Characteristic) { return new Promise((resolve, reject) => { // Set a timeout timer let timer: NodeJS.Timeout | undefined = setTimeout(() => { @@ -541,7 +532,7 @@ export class SwitchbotDevice { } // Write the specified Buffer data to the specified characteristic - _write(char, buf) { + _write(char: Characteristic, buf: Buffer) { return new Promise((resolve, reject) => { // Set a timeout timer let timer: NodeJS.Timeout | undefined = setTimeout(() => { diff --git a/src/device/woblindtilt.ts b/src/device/woblindtilt.ts index d53ded56..529c59a4 100644 --- a/src/device/woblindtilt.ts +++ b/src/device/woblindtilt.ts @@ -7,7 +7,7 @@ import { Buffer } from 'buffer'; import { SwitchbotDevice } from '../device.js'; export class WoBlindTilt extends SwitchbotDevice { - static parseServiceData(buf, onlog) { + static parseServiceData(buf: Buffer, onlog: ((message: string) => void) | undefined) { if (buf.length !== 5 && buf.length !== 6) { if (onlog && typeof onlog === 'function') { onlog( @@ -94,7 +94,7 @@ export class WoBlindTilt extends SwitchbotDevice { * - Promise object * Nothing will be passed to the `resolve()`. * ---------------------------------------------------------------- */ - runToPos(percent, mode) { + runToPos(percent: number, mode: number) { if (typeof percent !== 'number') { return new Promise((resolve, reject) => { reject( @@ -127,7 +127,7 @@ export class WoBlindTilt extends SwitchbotDevice { return this._operateBlindTilt([0x57, 0x0f, 0x45, 0x01, 0x05, mode, percent]); } - _operateBlindTilt(bytes) { + _operateBlindTilt(bytes: number[]) { return new Promise((resolve, reject) => { const req_buf = Buffer.from(bytes); this._command(req_buf) diff --git a/src/device/wobulb.ts b/src/device/wobulb.ts index 38250b34..a00e3b1c 100644 --- a/src/device/wobulb.ts +++ b/src/device/wobulb.ts @@ -10,7 +10,7 @@ import { SwitchbotDevice } from '../device.js'; * @see https://github.com/OpenWonderLabs/SwitchBotAPI-BLE/blob/latest/devicetypes/colorbulb.md */ export class WoBulb extends SwitchbotDevice { - static parseServiceData(manufacturerData, onlog) { + static parseServiceData(manufacturerData: Buffer, onlog: ((message: string) => void) | undefined) { if (manufacturerData.length !== 13) { if (onlog && typeof onlog === 'function') { onlog( @@ -73,7 +73,7 @@ export class WoBulb extends SwitchbotDevice { /** * @private */ - _setState(reqByteArray) { + _setState(reqByteArray: number[]) { const base = [0x57, 0x0f, 0x47, 0x01]; return this._operateBot(base.concat(reqByteArray)); } @@ -95,7 +95,7 @@ export class WoBulb extends SwitchbotDevice { /** * @returns {Promise} resolves with brightness percent */ - setBrightness(brightness) { + setBrightness(brightness: number) { if (typeof brightness !== 'number') { return new Promise((resolve, reject) => { reject( @@ -117,7 +117,7 @@ export class WoBulb extends SwitchbotDevice { /** * @returns {Promise} resolves with color_temperature percent */ - setColorTemperature(color_temperature) { + setColorTemperature(color_temperature: number) { if (typeof color_temperature !== 'number') { return new Promise((resolve, reject) => { reject( @@ -139,7 +139,7 @@ export class WoBulb extends SwitchbotDevice { /** * @returns {Promise} resolves with brightness percent */ - setRGB(brightness, red, green, blue) { + setRGB(brightness: number, red: number, green: number, blue: number) { if (typeof brightness !== 'number') { return new Promise((resolve, reject) => { reject( @@ -206,7 +206,7 @@ export class WoBulb extends SwitchbotDevice { /** * @private */ - _operateBot(bytes) { + _operateBot(bytes: number[]) { const req_buf = Buffer.from(bytes); return new Promise((resolve, reject) => { this._command(req_buf) diff --git a/src/device/wocontact.ts b/src/device/wocontact.ts index 3232dd44..ddaf250c 100644 --- a/src/device/wocontact.ts +++ b/src/device/wocontact.ts @@ -5,7 +5,7 @@ import { SwitchbotDevice } from '../device.js'; export class WoContact extends SwitchbotDevice { - static parseServiceData(buf, onlog) { + static parseServiceData(buf: Buffer, onlog: ((message: string) => void) | undefined) { if (buf.length !== 9) { if (onlog && typeof onlog === 'function') { onlog( diff --git a/src/device/wocurtain.ts b/src/device/wocurtain.ts index 618a8a71..e890336d 100644 --- a/src/device/wocurtain.ts +++ b/src/device/wocurtain.ts @@ -7,7 +7,7 @@ import { Buffer } from 'buffer'; import { SwitchbotDevice } from '../device.js'; export class WoCurtain extends SwitchbotDevice { - static parseServiceData(buf, onlog) { + static parseServiceData(buf: Buffer, onlog: ((message: string) => void) | undefined) { if (buf.length !== 5 && buf.length !== 6) { if (onlog && typeof onlog === 'function') { onlog( @@ -54,7 +54,7 @@ export class WoCurtain extends SwitchbotDevice { * - Promise object * Nothing will be passed to the `resolve()`. * ---------------------------------------------------------------- */ - open(mode) { + open(mode?: number) { return this.runToPos(0, mode); } @@ -69,7 +69,7 @@ export class WoCurtain extends SwitchbotDevice { * - Promise object * Nothing will be passed to the `resolve()`. * ---------------------------------------------------------------- */ - close(mode) { + close(mode?: number) { return this.runToPos(100, mode); } @@ -100,7 +100,7 @@ export class WoCurtain extends SwitchbotDevice { * - Promise object * Nothing will be passed to the `resolve()`. * ---------------------------------------------------------------- */ - runToPos(percent, mode = 0xff) { + runToPos(percent: number, mode = 0xff) { if (typeof percent !== 'number') { return new Promise((resolve, reject) => { reject( @@ -129,7 +129,7 @@ export class WoCurtain extends SwitchbotDevice { return this._operateCurtain([0x57, 0x0f, 0x45, 0x01, 0x05, mode, percent]); } - _operateCurtain(bytes) { + _operateCurtain(bytes: number[]) { return new Promise((resolve, reject) => { const req_buf = Buffer.from(bytes); this._command(req_buf) diff --git a/src/device/wohand.ts b/src/device/wohand.ts index 5bf16f45..c285ab30 100644 --- a/src/device/wohand.ts +++ b/src/device/wohand.ts @@ -3,7 +3,7 @@ import { Buffer } from 'buffer'; import { SwitchbotDevice } from '../device.js'; export class WoHand extends SwitchbotDevice { - static parseServiceData(buf, onlog) { + static parseServiceData(buf: Buffer, onlog: ((message: string) => void) | undefined) { if (buf.length !== 3) { if (onlog && typeof onlog === 'function') { onlog( @@ -104,7 +104,7 @@ export class WoHand extends SwitchbotDevice { return this._operateBot([0x57, 0x01, 0x04]); } - _operateBot(bytes) { + _operateBot(bytes: number[]) { return new Promise((resolve, reject) => { const req_buf = Buffer.from(bytes); this._command(req_buf) diff --git a/src/device/wohumi.ts b/src/device/wohumi.ts index 34c79bf1..f8a6fb8d 100644 --- a/src/device/wohumi.ts +++ b/src/device/wohumi.ts @@ -3,7 +3,7 @@ import { Buffer } from 'buffer'; import { SwitchbotDevice } from '../device.js'; export class WoHumi extends SwitchbotDevice { - static parseServiceData(buf, onlog) { + static parseServiceData(buf: Buffer, onlog: ((message: string) => void) | undefined) { if (buf.length !== 8) { if (onlog && typeof onlog === 'function') { onlog( @@ -106,7 +106,7 @@ export class WoHumi extends SwitchbotDevice { return this._operateBot([0x57, 0x01, 0x04]); } - _operateBot(bytes) { + _operateBot(bytes: number[]) { return new Promise((resolve, reject) => { const req_buf = Buffer.from(bytes); this._command(req_buf) diff --git a/src/device/woiosensorth.ts b/src/device/woiosensorth.ts index 824cd733..1e99d816 100644 --- a/src/device/woiosensorth.ts +++ b/src/device/woiosensorth.ts @@ -1,7 +1,7 @@ import { SwitchbotDevice } from '../device.js'; export class WoIOSensorTH extends SwitchbotDevice { - static parseServiceData(serviceDataBuf, manufacturerDataBuf, onlog) { + static parseServiceData(serviceDataBuf: Buffer, manufacturerDataBuf: Buffer, onlog: ((message: string) => void) | undefined) { if (serviceDataBuf.length !== 3) { if (onlog && typeof onlog === 'function') { onlog( diff --git a/src/device/woplugmini.ts b/src/device/woplugmini.ts index 51dda560..bce3404c 100644 --- a/src/device/woplugmini.ts +++ b/src/device/woplugmini.ts @@ -6,7 +6,7 @@ import { SwitchbotDevice } from '../device.js'; * @see https://github.com/OpenWonderLabs/SwitchBotAPI-BLE/blob/latest/devicetypes/plugmini.md */ export class WoPlugMini extends SwitchbotDevice { - static parseServiceData_US(manufacturerData, onlog) { + static parseServiceData_US(manufacturerData: Buffer, onlog: ((message: string) => void) | undefined) { if (manufacturerData.length !== 14) { if (onlog && typeof onlog === 'function') { onlog( @@ -45,7 +45,7 @@ export class WoPlugMini extends SwitchbotDevice { return data; } - static parseServiceData_JP(manufacturerData, onlog) { + static parseServiceData_JP(manufacturerData: Buffer, onlog: ((message: string) => void) | undefined) { if (manufacturerData.length !== 14) { if (onlog && typeof onlog === 'function') { onlog( @@ -94,7 +94,7 @@ export class WoPlugMini extends SwitchbotDevice { /** * @private */ - _setState(reqByteArray) { + _setState(reqByteArray: number[]) { const base = [0x57, 0x0f, 0x50, 0x01]; return this._operateBot([...base, ...reqByteArray]); } @@ -123,7 +123,7 @@ export class WoPlugMini extends SwitchbotDevice { /** * @private */ - _operateBot(bytes) { + _operateBot(bytes: number[]) { const req_buf = Buffer.from(bytes); return new Promise((resolve, reject) => { this._command(req_buf) diff --git a/src/device/wopresence.ts b/src/device/wopresence.ts index 44641e26..2d2619d9 100644 --- a/src/device/wopresence.ts +++ b/src/device/wopresence.ts @@ -1,7 +1,7 @@ import { SwitchbotDevice } from '../device.js'; export class WoPresence extends SwitchbotDevice { - static parseServiceData(buf, onlog) { + static parseServiceData(buf: Buffer, onlog: ((message: string) => void) | undefined) { if (buf.length !== 6) { if (onlog && typeof onlog === 'function') { onlog( diff --git a/src/device/wosensorth.ts b/src/device/wosensorth.ts index 81262d85..cef0da94 100644 --- a/src/device/wosensorth.ts +++ b/src/device/wosensorth.ts @@ -1,7 +1,7 @@ import { SwitchbotDevice } from '../device.js'; export class WoSensorTH extends SwitchbotDevice { - static parseServiceData(buf, onlog) { + static parseServiceData(buf: Buffer, onlog: ((message: string) => void) | undefined) { if (buf.length !== 6) { if (onlog && typeof onlog === 'function') { onlog( @@ -34,7 +34,7 @@ export class WoSensorTH extends SwitchbotDevice { return data; } - static parseServiceData_Plus(buf, onlog) { + static parseServiceData_Plus(buf: Buffer, onlog: ((message: string) => void) | undefined) { if (buf.length !== 6) { if (onlog && typeof onlog === 'function') { onlog( diff --git a/src/device/wosmartlock.ts b/src/device/wosmartlock.ts index fab89c63..9c4bf6a3 100644 --- a/src/device/wosmartlock.ts +++ b/src/device/wosmartlock.ts @@ -7,7 +7,7 @@ import { SwitchbotDevice } from '../device.js'; export class WoSmartLock extends SwitchbotDevice { - static parseServiceData(manufacturerData, onlog) { + static parseServiceData(manufacturerData: Buffer, onlog: ((message: string) => void) | undefined) { if (manufacturerData.length !== 6) { if (onlog && typeof onlog === 'function') { onlog( diff --git a/src/device/wostrip.ts b/src/device/wostrip.ts index be8c3ccf..f92e96f6 100644 --- a/src/device/wostrip.ts +++ b/src/device/wostrip.ts @@ -6,7 +6,7 @@ import { SwitchbotDevice } from '../device.js'; * @see https://github.com/OpenWonderLabs/SwitchBotAPI-BLE/blob/latest/devicetypes/colorbulb.md */ export class WoStrip extends SwitchbotDevice { - static parseServiceData(buf, onlog) { + static parseServiceData(buf: Buffer, onlog: ((message: string) => void) | undefined) { if (buf.length !== 18) { if (onlog && typeof onlog === 'function') { onlog( @@ -65,7 +65,7 @@ export class WoStrip extends SwitchbotDevice { /** * @private */ - _setState(reqByteArray) { + _setState(reqByteArray: number[]) { const base = [0x57, 0x0f, 0x49, 0x01]; return this._operateBot([...base, ...reqByteArray]); } @@ -87,7 +87,7 @@ export class WoStrip extends SwitchbotDevice { /** * @returns {Promise} resolves with brightness percent */ - setBrightness(brightness) { + setBrightness(brightness: number) { if (typeof brightness !== 'number') { return new Promise((resolve, reject) => { reject( @@ -109,7 +109,7 @@ export class WoStrip extends SwitchbotDevice { /** * @returns {Promise} resolves with color temperature */ - setColorTemperature(color_temperature) { + setColorTemperature(color_temperature: unknown) { if (color_temperature) { return new Promise((resolve, reject) => { reject( @@ -125,7 +125,7 @@ export class WoStrip extends SwitchbotDevice { /** * @returns {Promise} resolves with brightness + rgb */ - setRGB(brightness, red, green, blue) { + setRGB(brightness: number, red: number, green: number, blue: number) { if (typeof brightness !== 'number') { return new Promise((resolve, reject) => { reject( @@ -192,7 +192,7 @@ export class WoStrip extends SwitchbotDevice { /** * @private */ - _operateBot(bytes) { + _operateBot(bytes: number[]) { const req_buf = Buffer.from(bytes); return new Promise((resolve, reject) => { this._command(req_buf) diff --git a/src/parameter-checker.ts b/src/parameter-checker.ts index baf94db9..7fe10f55 100644 --- a/src/parameter-checker.ts +++ b/src/parameter-checker.ts @@ -8,11 +8,12 @@ type Rule = { maxBytes?: number; pattern?: RegExp; enum?: any[]; + type?: 'float' | 'integer' | 'boolean' | 'array' | 'object' | 'string'; }; export class ParameterChecker { - _error; + _error: Error | null; static error: any; constructor() { this._error = null; @@ -30,7 +31,7 @@ export class ParameterChecker { return this._error; } - static isSpecified(value) { + static isSpecified(value: unknown) { return value === void 0 ? false : true; } @@ -67,7 +68,7 @@ export class ParameterChecker { * throw new Error(message); * } * ---------------------------------------------------------------- */ - static check(obj, rules, required) { + static check(obj: Record, rules: {[key: string]: Rule}, required: boolean) { this.error; if (required) { if (!this.isSpecified(obj)) { @@ -97,7 +98,7 @@ export class ParameterChecker { for (let i = 0; i < name_list.length; i++) { const name = name_list[i]; const v = obj[name]; - let rule = rules[name]; + let rule: Rule = rules[name as keyof typeof rules] as Rule; if (!rule) { rule = {}; @@ -169,7 +170,7 @@ export class ParameterChecker { * - If the value is invalid, this method will return `false` and * an `Error` object will be set to `this._error`. * ---------------------------------------------------------------- */ - static isFloat(value, rule: Rule, name = 'value') { + static isFloat(value: unknown, rule: Rule, name = 'value'): boolean { this.error; if (!rule.required && !this.isSpecified(value)) { @@ -251,7 +252,7 @@ export class ParameterChecker { * - If the value is invalid, this method will return `false` and * an `Error` object will be set to `this._error`. * ---------------------------------------------------------------- */ - static isInteger(value, rule: Rule, name = 'value') { + static isInteger(value: unknown, rule: Rule, name = 'value') { this.error = null; if (!rule.required && !this.isSpecified(value)) { @@ -259,7 +260,7 @@ export class ParameterChecker { } if (this.isFloat(value, rule)) { - if (value % 1 === 0) { + if ((value as number) % 1 === 0) { return true; } else { this.error = { @@ -288,7 +289,7 @@ export class ParameterChecker { * - If the value is invalid, this method will return `false` and * an `Error` object will be set to `this._error`. * ---------------------------------------------------------------- */ - static isBoolean(value, rule: Rule, name = 'value') { + static isBoolean(value: unknown, rule: Rule, name = 'value') { this.error = null; if (!rule.required && !this.isSpecified(value)) { @@ -320,7 +321,7 @@ export class ParameterChecker { * - If the value is invalid, this method will return `false` and * an `Error` object will be set to `this._error`. * ---------------------------------------------------------------- */ - static isObject(value, rule: Rule, name = 'value') { + static isObject(value: unknown, rule: Rule, name = 'value') { this.error = null; if (!rule.required && !this.isSpecified(value)) { return true; @@ -356,7 +357,7 @@ export class ParameterChecker { * - If the value is invalid, this method will return `false` and * an `Error` object will be set to `this._error`. * ---------------------------------------------------------------- */ - static isArray(value, rule: Rule, name = 'value') { + static isArray(value: unknown, rule: Rule, name = 'value') { this.error = null; if (!rule.required && !this.isSpecified(value)) { @@ -427,7 +428,7 @@ export class ParameterChecker { * - If the value is invalid, this method will return `false` and * an `Error` object will be set to `this._error`. * ---------------------------------------------------------------- */ - static isString(value, rule: Rule, name = 'value') { + static isString(value: unknown, rule: Rule, name = 'value') { this.error = null; if (!rule.required && !this.isSpecified(value)) { diff --git a/src/switchbot.ts b/src/switchbot.ts index 9475ca5f..590d8ff7 100644 --- a/src/switchbot.ts +++ b/src/switchbot.ts @@ -13,8 +13,11 @@ import { WoHumi } from './device/wohumi.js'; import { WoPlugMini } from './device/woplugmini.js'; import { WoBulb } from './device/wobulb.js'; import { WoStrip } from './device/wostrip.js'; +import { Ad } from './advertising.js'; -type params = { +import { Peripheral } from '@abandonware/noble'; + +type Params = { duration?: number, model?: string, id?: string, @@ -22,20 +25,15 @@ type params = { noble?: any, } -type peripherals = { - addr?: string, - id?: string, -} - export class SwitchBot { private ready: Promise; - noble; - ondiscover; - onadvertisement; - onlog; - scanning; - DEFAULT_DISCOVERY_DURATION; - PRIMARY_SERVICE_UUID_LIST; + noble?: any; + ondiscover?: (device: SwitchbotDevice) => void; + onadvertisement?: (ad: Ad) => void; + onlog: ((message: string) => void) | undefined; + scanning = false; + DEFAULT_DISCOVERY_DURATION = 5000; + PRIMARY_SERVICE_UUID_LIST = []; static onlog: any; static noble: any; /* ------------------------------------------------------------------ @@ -50,15 +48,13 @@ export class SwitchBot { * ---------------------------------------------------------------- */ - constructor(params?: params) { - this.DEFAULT_DISCOVERY_DURATION = 5000; - this.PRIMARY_SERVICE_UUID_LIST = []; + constructor(params?: Params) { this.ready = this.init(params); } // Check parameters - async init(params?: params) { - let noble: any; + async init(params?: Params) { + let noble; if (params && params.noble) { noble = params.noble; } else { @@ -67,9 +63,6 @@ export class SwitchBot { // Public properties this.noble = noble; - this.ondiscover = null; - this.onadvertisement = null; - this.onlog = null; // Private properties this.scanning = false; @@ -113,7 +106,7 @@ export class SwitchBot { * An array will be passed to the `resolve()`, which includes * `SwitchbotDevice` objects representing the found devices. * ---------------------------------------------------------------- */ - discover(params: params = {}) { + discover(params: Params = {}) { const promise = new Promise((resolve, reject) => { // Check the parameters const valid = ParameterChecker.check( @@ -167,14 +160,14 @@ export class SwitchBot { // Initialize the noble object this._init() .then(() => { - const peripherals: peripherals = {}; + const peripherals: Record = {}; let timer: NodeJS.Timeout = setTimeout(() => { }, 0); const finishDiscovery = () => { if (timer) { clearTimeout(timer); } - this.noble.removeAllListeners('discover'); - this.noble.stopScanning(); + this.noble?.removeAllListeners('discover'); + this.noble?.stopScanning(); const device_list: SwitchbotDevice[] = []; for (const addr in peripherals) { device_list.push(peripherals[addr]); @@ -185,12 +178,12 @@ export class SwitchBot { }; // Set a handler for the 'discover' event - this.noble.on('discover', (peripheral) => { + this.noble?.on('discover', (peripheral: Peripheral) => { const device = this.getDeviceObject(peripheral, p.id, p.model) as SwitchbotDevice; if (!device) { return; } - const id = device.id; + const id = device.id as string; peripherals[id] = device; if (this.ondiscover && typeof this.ondiscover === 'function') { @@ -204,10 +197,10 @@ export class SwitchBot { }); // Start scanning - this.noble.startScanning( + this.noble?.startScanning( this.PRIMARY_SERVICE_UUID_LIST, false, - (error) => { + (error: Error) => { if (error) { reject(error); return; @@ -233,7 +226,7 @@ export class SwitchBot { resolve(); return; } - this.noble.once('stateChange', state => { + this.noble?.once('stateChange', (state: any) => { switch (state) { case 'unsupported': case 'unauthorized': @@ -265,7 +258,7 @@ export class SwitchBot { return promise; } - getDeviceObject(peripheral, id, model) { + getDeviceObject(peripheral: Peripheral, id: string, model: string) { const ad = Advertising.parse(peripheral, this.onlog); if (this.filterAdvertising(ad, id, model)) { let device; @@ -322,7 +315,7 @@ export class SwitchBot { } } - filterAdvertising(ad, id, model) { + filterAdvertising(ad: Ad, id: string, model: string) { if (!ad) { return false; } @@ -399,7 +392,7 @@ export class SwitchBot { * - Promise object * Nothing will be passed to the `resolve()`. * ---------------------------------------------------------------- */ - startScan(params?: params) { + startScan(params: Params = {}) { const promise = new Promise((resolve, reject) => { // Check the parameters const valid = ParameterChecker.check( @@ -435,21 +428,17 @@ export class SwitchBot { return; } - if (!params) { - params = {}; - } - // Initialize the noble object this._init() .then(() => { // Determine the values of the parameters const p = { - model: params?.model || '', - id: params?.id || '', + model: params.model || '', + id: params.id || '', }; // Set a handler for the 'discover' event - this.noble.on('discover', (peripheral) => { + this.noble?.on('discover', (peripheral: Peripheral) => { const ad = Advertising.parse(peripheral, this.onlog); if (this.filterAdvertising(ad, p.id, p.model)) { if ( @@ -462,10 +451,10 @@ export class SwitchBot { }); // Start scanning - this.noble.startScanning( + this.noble?.startScanning( this.PRIMARY_SERVICE_UUID_LIST, true, - (error) => { + (error: Error) => { if (error) { reject(error); } else { @@ -492,8 +481,8 @@ export class SwitchBot { * - none * ---------------------------------------------------------------- */ stopScan() { - this.noble.removeAllListeners('discover'); - this.noble.stopScanning(); + this.noble?.removeAllListeners('discover'); + this.noble?.stopScanning(); } /* ------------------------------------------------------------------ @@ -515,7 +504,7 @@ export class SwitchBot { { msec: { required: true, type: 'integer', min: 0 }, }, - {}, // Add an empty object as the third argument + true, // Add the required argument ); if (!valid) { diff --git a/tsconfig.json b/tsconfig.json index b5ad9a38..cff6cbcd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,7 +13,7 @@ "rootDir": "src", "strict": true, "esModuleInterop": true, - "noImplicitAny": false, + "noImplicitAny": true, "allowSyntheticDefaultImports": true, "forceConsistentCasingInFileNames": true, "moduleResolution": "node",