@switchbot/homebridge-switchbot 3.5.1-beta.4 → 3.5.1-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/platform.d.ts +12 -11
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +54 -55
- package/dist/platform.js.map +1 -1
- package/dist/types/devicewebhookstatus.d.ts +2 -3
- package/dist/types/devicewebhookstatus.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/platform.ts +58 -58
- package/src/types/devicewebhookstatus.ts +2 -4
package/src/platform.ts
CHANGED
|
@@ -34,23 +34,24 @@ import { AirConditioner } from './irdevice/airconditioner.js';
|
|
|
34
34
|
import { Buffer } from 'buffer';
|
|
35
35
|
import { request } from 'undici';
|
|
36
36
|
import asyncmqtt from 'async-mqtt';
|
|
37
|
-
import { isBlindTiltDevice, isCurtainDevice, sleep } from './utils.js';
|
|
38
37
|
import { createServer } from 'http';
|
|
39
38
|
import { queueScheduler } from 'rxjs';
|
|
40
39
|
import fakegato from 'fakegato-history';
|
|
41
40
|
import crypto, { randomUUID } from 'crypto';
|
|
42
41
|
import { readFileSync, writeFileSync } from 'fs';
|
|
43
42
|
import { EveHomeKitTypes } from 'homebridge-lib/EveHomeKitTypes';
|
|
43
|
+
import { isBlindTiltDevice, isCurtainDevice, sleep } from './utils.js';
|
|
44
44
|
import { PLATFORM_NAME, PLUGIN_NAME, Devices, setupWebhook, updateWebhook, deleteWebhook, queryWebhook } from './settings.js';
|
|
45
45
|
|
|
46
46
|
import type { UrlObject } from 'url';
|
|
47
47
|
import type { MqttClient } from 'mqtt';
|
|
48
48
|
import type { Dispatcher } from 'undici';
|
|
49
|
+
import type { irdevice } from './types/irdevicelist.js';
|
|
49
50
|
import type { Server, IncomingMessage, ServerResponse } from 'http';
|
|
51
|
+
import type { deviceWebhook } from './types/devicewebhookstatus.js';
|
|
52
|
+
import type { blindTilt, curtain, curtain3, device } from './types/devicelist.js';
|
|
50
53
|
import type { API, DynamicPlatformPlugin, Logging, PlatformAccessory } from 'homebridge';
|
|
51
54
|
import type { SwitchBotPlatformConfig, devicesConfig, irDevicesConfig } from './settings.js';
|
|
52
|
-
import type { irdevice } from './types/irdevicelist.js';
|
|
53
|
-
import type { blindTilt, curtain, curtain3, device } from './types/devicelist.js';
|
|
54
55
|
|
|
55
56
|
/**
|
|
56
57
|
* HomebridgePlatform
|
|
@@ -76,7 +77,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
76
77
|
|
|
77
78
|
public readonly fakegatoAPI: any;
|
|
78
79
|
public readonly eve: any;
|
|
79
|
-
public readonly webhookEventHandler;
|
|
80
|
+
public readonly webhookEventHandler!: deviceWebhook;
|
|
80
81
|
|
|
81
82
|
constructor(
|
|
82
83
|
log: Logging,
|
|
@@ -154,27 +155,27 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
154
155
|
try {
|
|
155
156
|
const { connectAsync } = asyncmqtt;
|
|
156
157
|
this.mqttClient = await connectAsync(this.config.options?.mqttURL, this.config.options.mqttOptions || {});
|
|
157
|
-
this.debugLog('MQTT connection has been established successfully.');
|
|
158
|
-
this.mqttClient.on('error', (e: Error) => {
|
|
159
|
-
this.errorLog(`Failed to publish MQTT messages. ${e}`);
|
|
158
|
+
await this.debugLog('MQTT connection has been established successfully.');
|
|
159
|
+
this.mqttClient.on('error', async (e: Error) => {
|
|
160
|
+
await this.errorLog(`Failed to publish MQTT messages. ${e}`);
|
|
160
161
|
});
|
|
161
162
|
if (!this.config.options?.webhookURL) {
|
|
162
163
|
// receive webhook events via MQTT
|
|
163
|
-
this.infoLog(`Webhook is configured to be received through ${this.config.options.mqttURL}/homebridge-switchbot/webhook.`);
|
|
164
|
+
await this.infoLog(`Webhook is configured to be received through ${this.config.options.mqttURL}/homebridge-switchbot/webhook.`);
|
|
164
165
|
this.mqttClient.subscribe('homebridge-switchbot/webhook/+');
|
|
165
166
|
this.mqttClient.on('message', async (topic: string, message) => {
|
|
166
167
|
try {
|
|
167
|
-
this.debugLog(`Received Webhook via MQTT: ${topic}=${message}`);
|
|
168
|
+
await this.debugLog(`Received Webhook via MQTT: ${topic}=${message}`);
|
|
168
169
|
const context = JSON.parse(message.toString());
|
|
169
170
|
this.webhookEventHandler[context.deviceMac]?.(context);
|
|
170
171
|
} catch (e: any) {
|
|
171
|
-
this.errorLog(`Failed to handle webhook event. Error:${e}`);
|
|
172
|
+
await this.errorLog(`Failed to handle webhook event. Error:${e}`);
|
|
172
173
|
}
|
|
173
174
|
});
|
|
174
175
|
}
|
|
175
176
|
} catch (e) {
|
|
176
177
|
this.mqttClient = null;
|
|
177
|
-
this.errorLog(`Failed to establish MQTT connection. ${e}`);
|
|
178
|
+
await this.errorLog(`Failed to establish MQTT connection. ${e}`);
|
|
178
179
|
}
|
|
179
180
|
}
|
|
180
181
|
}
|
|
@@ -298,9 +299,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
298
299
|
}),
|
|
299
300
|
});
|
|
300
301
|
const response: any = await body.json();
|
|
301
|
-
this.debugLog(`deleteWebhook: url:${url}`);
|
|
302
|
-
this.debugLog(`deleteWebhook: body:${JSON.stringify(response)}`);
|
|
303
|
-
this.debugLog(`deleteWebhook: statusCode:${statusCode}`);
|
|
302
|
+
this.debugLog(`deleteWebhook: url:${url}, body:${JSON.stringify(response)}, statusCode:${statusCode}`);
|
|
304
303
|
if (statusCode !== 200 || response?.statusCode !== 100) {
|
|
305
304
|
this.errorLog(`Failed to delete webhook. HTTP:${statusCode} API:${response?.statusCode} message:${response?.message}`);
|
|
306
305
|
} else {
|
|
@@ -2660,67 +2659,67 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
2660
2659
|
async statusCode(statusCode: number): Promise<void> {
|
|
2661
2660
|
switch (statusCode) {
|
|
2662
2661
|
case 151:
|
|
2663
|
-
this.errorLog(`Command not supported by this device type, statusCode: ${statusCode}, Submit Feature Request Here: ` +
|
|
2662
|
+
await this.errorLog(`Command not supported by this device type, statusCode: ${statusCode}, Submit Feature Request Here: ` +
|
|
2664
2663
|
'https://tinyurl.com/SwitchBotFeatureRequest');
|
|
2665
2664
|
break;
|
|
2666
2665
|
case 152:
|
|
2667
|
-
this.errorLog(`Device not found, statusCode: ${statusCode}`);
|
|
2666
|
+
await this.errorLog(`Device not found, statusCode: ${statusCode}`);
|
|
2668
2667
|
break;
|
|
2669
2668
|
case 160:
|
|
2670
|
-
this.errorLog(`Command is not supported, statusCode: ${statusCode}, Submit Bugs Here: https://tinyurl.com/SwitchBotBug`);
|
|
2669
|
+
await this.errorLog(`Command is not supported, statusCode: ${statusCode}, Submit Bugs Here: https://tinyurl.com/SwitchBotBug`);
|
|
2671
2670
|
break;
|
|
2672
2671
|
case 161:
|
|
2673
|
-
this.errorLog(`Device is offline, statusCode: ${statusCode}`);
|
|
2672
|
+
await this.errorLog(`Device is offline, statusCode: ${statusCode}`);
|
|
2674
2673
|
break;
|
|
2675
2674
|
case 171:
|
|
2676
|
-
this.errorLog(`is offline, statusCode: ${statusCode}`);
|
|
2675
|
+
await this.errorLog(`is offline, statusCode: ${statusCode}`);
|
|
2677
2676
|
break;
|
|
2678
2677
|
case 190:
|
|
2679
|
-
this.errorLog(`Requests reached the daily limit, statusCode: ${statusCode}`);
|
|
2678
|
+
await this.errorLog(`Requests reached the daily limit, statusCode: ${statusCode}`);
|
|
2680
2679
|
break;
|
|
2681
2680
|
case 100:
|
|
2682
|
-
this.debugLog(`Command successfully sent, statusCode: ${statusCode}`);
|
|
2681
|
+
await this.debugLog(`Command successfully sent, statusCode: ${statusCode}`);
|
|
2683
2682
|
break;
|
|
2684
2683
|
case 200:
|
|
2685
|
-
this.debugLog(`Request successful, statusCode: ${statusCode}`);
|
|
2684
|
+
await this.debugLog(`Request successful, statusCode: ${statusCode}`);
|
|
2686
2685
|
break;
|
|
2687
2686
|
case 400:
|
|
2688
|
-
this.errorLog('Bad Request, The client has issued an invalid request. This is commonly used to specify validation errors in a request '
|
|
2687
|
+
await this.errorLog('Bad Request, The client has issued an invalid request. This is commonly used to specify validation errors in a request '
|
|
2689
2688
|
+ `payload, statusCode: ${statusCode}`);
|
|
2690
2689
|
break;
|
|
2691
2690
|
case 401:
|
|
2692
|
-
this.errorLog('Unauthorized, Authorization for the API is required, but the request has not been authenticated, '
|
|
2691
|
+
await this.errorLog('Unauthorized, Authorization for the API is required, but the request has not been authenticated, '
|
|
2693
2692
|
+ `statusCode: ${statusCode}`);
|
|
2694
2693
|
break;
|
|
2695
2694
|
case 403:
|
|
2696
|
-
this.errorLog('Forbidden, The request has been authenticated but does not have appropriate permissions, or a requested resource is not '
|
|
2695
|
+
await this.errorLog('Forbidden, The request has been authenticated but does not have appropriate permissions, or a requested resource is not '
|
|
2697
2696
|
+ `found, statusCode: ${statusCode}`);
|
|
2698
2697
|
break;
|
|
2699
2698
|
case 404:
|
|
2700
|
-
this.errorLog(`Not Found, Specifies the requested path does not exist, statusCode: ${statusCode}`);
|
|
2699
|
+
await this.errorLog(`Not Found, Specifies the requested path does not exist, statusCode: ${statusCode}`);
|
|
2701
2700
|
break;
|
|
2702
2701
|
case 406:
|
|
2703
|
-
this.errorLog('Not Acceptable, The client has requested a MIME type via the Accept header for a value not supported by the server, '
|
|
2702
|
+
await this.errorLog('Not Acceptable, The client has requested a MIME type via the Accept header for a value not supported by the server, '
|
|
2704
2703
|
+ `statusCode: ${statusCode}`);
|
|
2705
2704
|
break;
|
|
2706
2705
|
case 415:
|
|
2707
|
-
this.errorLog('Unsupported Media Type, The client has defined a contentType header that is not supported by the server, '
|
|
2706
|
+
await this.errorLog('Unsupported Media Type, The client has defined a contentType header that is not supported by the server, '
|
|
2708
2707
|
+ `statusCode: ${statusCode}`);
|
|
2709
2708
|
break;
|
|
2710
2709
|
case 422:
|
|
2711
|
-
this.errorLog('Unprocessable Entity, The client has made a valid request, but the server cannot process it. This is often used for '
|
|
2710
|
+
await this.errorLog('Unprocessable Entity, The client has made a valid request, but the server cannot process it. This is often used for '
|
|
2712
2711
|
+ `APIs for which certain limits have been exceeded, statusCode: ${statusCode}`);
|
|
2713
2712
|
break;
|
|
2714
2713
|
case 429:
|
|
2715
|
-
this.errorLog('Too Many Requests, The client has exceeded the number of requests allowed for a given time window, '
|
|
2714
|
+
await this.errorLog('Too Many Requests, The client has exceeded the number of requests allowed for a given time window, '
|
|
2716
2715
|
+ `statusCode: ${statusCode}`);
|
|
2717
2716
|
break;
|
|
2718
2717
|
case 500:
|
|
2719
|
-
this.errorLog('Internal Server Error, An unexpected error on the SmartThings servers has occurred. These errors should be rare, '
|
|
2718
|
+
await this.errorLog('Internal Server Error, An unexpected error on the SmartThings servers has occurred. These errors should be rare, '
|
|
2720
2719
|
+ `statusCode: ${statusCode}`);
|
|
2721
2720
|
break;
|
|
2722
2721
|
default:
|
|
2723
|
-
this.errorLog(`Unknown statusCode, statusCode: ${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`);
|
|
2722
|
+
await this.errorLog(`Unknown statusCode, statusCode: ${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`);
|
|
2724
2723
|
}
|
|
2725
2724
|
}
|
|
2726
2725
|
|
|
@@ -2736,13 +2735,13 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
2736
2735
|
if (statusCode === 200 || statusCode === 100) {
|
|
2737
2736
|
return { body, statusCode };
|
|
2738
2737
|
} else {
|
|
2739
|
-
this.debugLog(`Received status code: ${statusCode}`);
|
|
2738
|
+
await this.debugLog(`Received status code: ${statusCode}`);
|
|
2740
2739
|
}
|
|
2741
2740
|
} catch (error: any) {
|
|
2742
|
-
this.errorLog(`Error making request: ${error.message}`);
|
|
2741
|
+
await this.errorLog(`Error making request: ${error.message}`);
|
|
2743
2742
|
}
|
|
2744
2743
|
retryCount++;
|
|
2745
|
-
this.debugLog(`Retry attempt ${retryCount} of ${maxRetries}`);
|
|
2744
|
+
await this.debugLog(`Retry attempt ${retryCount} of ${maxRetries}`);
|
|
2746
2745
|
await sleep(delayBetweenRetries);
|
|
2747
2746
|
}
|
|
2748
2747
|
return { body: null, statusCode: -1 };
|
|
@@ -2754,9 +2753,10 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
2754
2753
|
try {
|
|
2755
2754
|
const SwitchBot = (await import('node-switchbot')).SwitchBot;
|
|
2756
2755
|
queueScheduler.schedule(() => (switchbot = new SwitchBot()));
|
|
2756
|
+
await this.debugLog(`${device.deviceType}: ${accessory.displayName} 'node-switchbot' found: ${switchbot}`);
|
|
2757
2757
|
} catch (e: any) {
|
|
2758
2758
|
switchbot = false;
|
|
2759
|
-
this.errorLog(`${device.deviceType}: ${accessory.displayName} 'node-switchbot' found: ${switchbot}, Error: ${e}`);
|
|
2759
|
+
await this.errorLog(`${device.deviceType}: ${accessory.displayName} 'node-switchbot' found: ${switchbot}, Error: ${e}`);
|
|
2760
2760
|
}
|
|
2761
2761
|
return switchbot;
|
|
2762
2762
|
}
|
|
@@ -2768,7 +2768,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
2768
2768
|
'utf-8',
|
|
2769
2769
|
),
|
|
2770
2770
|
);
|
|
2771
|
-
this.debugLog(`Plugin Version: ${json.version}`);
|
|
2771
|
+
await this.debugLog(`Plugin Version: ${json.version}`);
|
|
2772
2772
|
this.version = json.version;
|
|
2773
2773
|
}
|
|
2774
2774
|
|
|
@@ -2804,7 +2804,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
2804
2804
|
platformConfig.delayBetweenRetries = this.delayBetweenRetries / 1000;
|
|
2805
2805
|
}
|
|
2806
2806
|
if (Object.entries(platformConfig).length !== 0) {
|
|
2807
|
-
this.debugLog(`Platform Config: ${JSON.stringify(platformConfig)}`);
|
|
2807
|
+
await this.debugLog(`Platform Config: ${JSON.stringify(platformConfig)}`);
|
|
2808
2808
|
}
|
|
2809
2809
|
this.platformConfig = platformConfig;
|
|
2810
2810
|
}
|
|
@@ -2814,13 +2814,13 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
2814
2814
|
this.debugMode = process.argv.includes('-D') || process.argv.includes('--debug');
|
|
2815
2815
|
if (this.config.options?.logging === 'debug' || this.config.options?.logging === 'standard' || this.config.options?.logging === 'none') {
|
|
2816
2816
|
this.platformLogging = this.config.options.logging;
|
|
2817
|
-
this.debugWarnLog(`Using Config Logging: ${this.platformLogging}`);
|
|
2817
|
+
await this.debugWarnLog(`Using Config Logging: ${this.platformLogging}`);
|
|
2818
2818
|
} else if (this.debugMode) {
|
|
2819
2819
|
this.platformLogging = 'debugMode';
|
|
2820
|
-
this.debugWarnLog(`Using ${this.platformLogging} Logging`);
|
|
2820
|
+
await this.debugWarnLog(`Using ${this.platformLogging} Logging`);
|
|
2821
2821
|
} else {
|
|
2822
2822
|
this.platformLogging = 'standard';
|
|
2823
|
-
this.debugWarnLog(`Using ${this.platformLogging} Logging`);
|
|
2823
|
+
await this.debugWarnLog(`Using ${this.platformLogging} Logging`);
|
|
2824
2824
|
}
|
|
2825
2825
|
}
|
|
2826
2826
|
|
|
@@ -2828,56 +2828,56 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
2828
2828
|
* If device level logging is turned on, log to log.warn
|
|
2829
2829
|
* Otherwise send debug logs to log.debug
|
|
2830
2830
|
*/
|
|
2831
|
-
infoLog(...log: any[]): void {
|
|
2832
|
-
if (this.enablingPlatformLogging()) {
|
|
2831
|
+
async infoLog(...log: any[]): Promise<void> {
|
|
2832
|
+
if (await this.enablingPlatformLogging()) {
|
|
2833
2833
|
this.log.info(String(...log));
|
|
2834
2834
|
}
|
|
2835
2835
|
}
|
|
2836
2836
|
|
|
2837
|
-
successLog(...log: any[]): void {
|
|
2838
|
-
if (this.enablingPlatformLogging()) {
|
|
2837
|
+
async successLog(...log: any[]): Promise<void> {
|
|
2838
|
+
if (await this.enablingPlatformLogging()) {
|
|
2839
2839
|
this.log.success(String(...log));
|
|
2840
2840
|
}
|
|
2841
2841
|
}
|
|
2842
2842
|
|
|
2843
|
-
debugSuccessLog(...log: any[]): void {
|
|
2844
|
-
if (this.enablingPlatformLogging()) {
|
|
2843
|
+
async debugSuccessLog(...log: any[]): Promise<void> {
|
|
2844
|
+
if (await this.enablingPlatformLogging()) {
|
|
2845
2845
|
if (this.platformLogging?.includes('debug')) {
|
|
2846
2846
|
this.log.success('[DEBUG]', String(...log));
|
|
2847
2847
|
}
|
|
2848
2848
|
}
|
|
2849
2849
|
}
|
|
2850
2850
|
|
|
2851
|
-
warnLog(...log: any[]): void {
|
|
2852
|
-
if (this.enablingPlatformLogging()) {
|
|
2851
|
+
async warnLog(...log: any[]): Promise<void> {
|
|
2852
|
+
if (await this.enablingPlatformLogging()) {
|
|
2853
2853
|
this.log.warn(String(...log));
|
|
2854
2854
|
}
|
|
2855
2855
|
}
|
|
2856
2856
|
|
|
2857
|
-
debugWarnLog(...log: any[]): void {
|
|
2858
|
-
if (this.enablingPlatformLogging()) {
|
|
2857
|
+
async debugWarnLog(...log: any[]): Promise<void> {
|
|
2858
|
+
if (await this.enablingPlatformLogging()) {
|
|
2859
2859
|
if (this.platformLogging?.includes('debug')) {
|
|
2860
2860
|
this.log.warn('[DEBUG]', String(...log));
|
|
2861
2861
|
}
|
|
2862
2862
|
}
|
|
2863
2863
|
}
|
|
2864
2864
|
|
|
2865
|
-
errorLog(...log: any[]): void {
|
|
2866
|
-
if (this.enablingPlatformLogging()) {
|
|
2865
|
+
async errorLog(...log: any[]): Promise<void> {
|
|
2866
|
+
if (await this.enablingPlatformLogging()) {
|
|
2867
2867
|
this.log.error(String(...log));
|
|
2868
2868
|
}
|
|
2869
2869
|
}
|
|
2870
2870
|
|
|
2871
|
-
debugErrorLog(...log: any[]): void {
|
|
2872
|
-
if (this.enablingPlatformLogging()) {
|
|
2871
|
+
async debugErrorLog(...log: any[]): Promise<void> {
|
|
2872
|
+
if (await this.enablingPlatformLogging()) {
|
|
2873
2873
|
if (this.platformLogging?.includes('debug')) {
|
|
2874
2874
|
this.log.error('[DEBUG]', String(...log));
|
|
2875
2875
|
}
|
|
2876
2876
|
}
|
|
2877
2877
|
}
|
|
2878
2878
|
|
|
2879
|
-
debugLog(...log: any[]): void {
|
|
2880
|
-
if (this.enablingPlatformLogging()) {
|
|
2879
|
+
async debugLog(...log: any[]): Promise<void> {
|
|
2880
|
+
if (await this.enablingPlatformLogging()) {
|
|
2881
2881
|
if (this.platformLogging === 'debugMode') {
|
|
2882
2882
|
this.log.debug(String(...log));
|
|
2883
2883
|
} else if (this.platformLogging === 'debug') {
|
|
@@ -2886,7 +2886,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
2886
2886
|
}
|
|
2887
2887
|
}
|
|
2888
2888
|
|
|
2889
|
-
enablingPlatformLogging(): boolean {
|
|
2889
|
+
async enablingPlatformLogging(): Promise<boolean> {
|
|
2890
2890
|
return this.platformLogging?.includes('debug') || this.platformLogging === 'standard';
|
|
2891
2891
|
}
|
|
2892
2892
|
}
|
|
@@ -2,15 +2,13 @@
|
|
|
2
2
|
*
|
|
3
3
|
* devicestatus.ts: @switchbot/homebridge-switchbot platform class.
|
|
4
4
|
*/
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
type deviceWebhook = {
|
|
5
|
+
export type deviceWebhook = {
|
|
8
6
|
eventType: string,
|
|
9
7
|
eventVersion: string,
|
|
10
8
|
context: deviceWebhookContext
|
|
11
9
|
};
|
|
12
10
|
|
|
13
|
-
type deviceWebhookContext = {
|
|
11
|
+
export type deviceWebhookContext = {
|
|
14
12
|
//properties on all devices
|
|
15
13
|
deviceMac: string;
|
|
16
14
|
deviceType: string;
|