homebridge-tsvesync 1.0.0 → 1.0.1
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/config.schema.json +77 -0
- package/dist/platform.d.ts +2 -0
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +35 -5
- package/dist/platform.js.map +1 -1
- package/package.json +29 -6
- package/src/platform.ts +42 -5
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pluginAlias": "TSVESyncPlatform",
|
|
3
|
+
"pluginType": "platform",
|
|
4
|
+
"singular": true,
|
|
5
|
+
"headerDisplay": "Homebridge plugin for VeSync devices including Levoit air purifiers, humidifiers, and Etekcity smart outlets.",
|
|
6
|
+
"footerDisplay": "For help please visit the [GitHub repository](https://github.com/mickgiles/homebridge-tsvesync).",
|
|
7
|
+
"schema": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"properties": {
|
|
10
|
+
"name": {
|
|
11
|
+
"title": "Name",
|
|
12
|
+
"type": "string",
|
|
13
|
+
"required": true,
|
|
14
|
+
"default": "TSVESync"
|
|
15
|
+
},
|
|
16
|
+
"username": {
|
|
17
|
+
"title": "Email",
|
|
18
|
+
"type": "string",
|
|
19
|
+
"required": true,
|
|
20
|
+
"description": "Your VeSync account email address"
|
|
21
|
+
},
|
|
22
|
+
"password": {
|
|
23
|
+
"title": "Password",
|
|
24
|
+
"type": "string",
|
|
25
|
+
"required": true,
|
|
26
|
+
"description": "Your VeSync account password",
|
|
27
|
+
"typeahead": {
|
|
28
|
+
"source": []
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"updateInterval": {
|
|
32
|
+
"title": "Update Interval",
|
|
33
|
+
"type": "integer",
|
|
34
|
+
"minimum": 10,
|
|
35
|
+
"maximum": 600,
|
|
36
|
+
"default": 30,
|
|
37
|
+
"required": false,
|
|
38
|
+
"description": "How often to update device states (in seconds). Default is 30 seconds."
|
|
39
|
+
},
|
|
40
|
+
"debug": {
|
|
41
|
+
"title": "Debug Logging",
|
|
42
|
+
"type": "boolean",
|
|
43
|
+
"required": false,
|
|
44
|
+
"default": false,
|
|
45
|
+
"description": "Enable debug logging"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"layout": [
|
|
50
|
+
{
|
|
51
|
+
"type": "flex",
|
|
52
|
+
"flex-flow": "row wrap",
|
|
53
|
+
"items": [
|
|
54
|
+
{
|
|
55
|
+
"type": "flex",
|
|
56
|
+
"flex-flow": "column",
|
|
57
|
+
"items": [
|
|
58
|
+
"name",
|
|
59
|
+
"username",
|
|
60
|
+
{
|
|
61
|
+
"key": "password",
|
|
62
|
+
"type": "password"
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"type": "flex",
|
|
68
|
+
"flex-flow": "column",
|
|
69
|
+
"items": [
|
|
70
|
+
"updateInterval",
|
|
71
|
+
"debug"
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
}
|
package/dist/platform.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ export declare class TSVESyncPlatform implements DynamicPlatformPlugin {
|
|
|
8
8
|
readonly accessories: PlatformAccessory[];
|
|
9
9
|
private client;
|
|
10
10
|
private deviceUpdateInterval?;
|
|
11
|
+
private readonly updateInterval;
|
|
12
|
+
private readonly debug;
|
|
11
13
|
constructor(log: Logger, config: PlatformConfig, api: API);
|
|
12
14
|
/**
|
|
13
15
|
* This function is invoked when homebridge restores cached accessories from disk at startup.
|
package/dist/platform.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,qBAAqB,EAAE,MAAM,EAAE,iBAAiB,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAK5H,qBAAa,gBAAiB,YAAW,qBAAqB;
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,qBAAqB,EAAE,MAAM,EAAE,iBAAiB,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAK5H,qBAAa,gBAAiB,YAAW,qBAAqB;aAa1C,GAAG,EAAE,MAAM;aACX,MAAM,EAAE,cAAc;aACtB,GAAG,EAAE,GAAG;IAd1B,SAAgB,OAAO,EAAE,OAAO,OAAO,CAAwB;IAC/D,SAAgB,cAAc,EAAE,OAAO,cAAc,CAA+B;IAGpF,SAAgB,WAAW,EAAE,iBAAiB,EAAE,CAAM;IAEtD,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,oBAAoB,CAAC,CAAiB;IAC9C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAW;gBAGf,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,GAAG;IAmD1B;;OAEG;IACH,kBAAkB,CAAC,SAAS,EAAE,iBAAiB;IAK/C;;OAEG;IACG,eAAe;IAmDrB;;OAEG;YACW,kBAAkB;CAsBjC"}
|
package/dist/platform.js
CHANGED
|
@@ -18,21 +18,34 @@ class TSVESyncPlatform {
|
|
|
18
18
|
log.error('Missing required configuration. Please check your config.json');
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
21
|
+
// Get config values with defaults
|
|
22
|
+
this.updateInterval = config.updateInterval || 30;
|
|
23
|
+
this.debug = config.debug || false;
|
|
21
24
|
// Initialize TSVESync client
|
|
22
25
|
this.client = new tsvesync_1.TSVESync({
|
|
23
26
|
username: config.username,
|
|
24
27
|
password: config.password,
|
|
25
28
|
});
|
|
26
|
-
this.
|
|
29
|
+
if (this.debug) {
|
|
30
|
+
this.log.debug('Initialized platform with config:', {
|
|
31
|
+
name: config.name,
|
|
32
|
+
username: config.username,
|
|
33
|
+
updateInterval: this.updateInterval,
|
|
34
|
+
debug: this.debug,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
this.log.info('Finished initializing platform:', this.config.name);
|
|
27
38
|
// When this event is fired it means Homebridge has restored all cached accessories from disk.
|
|
28
39
|
this.api.on('didFinishLaunching', () => {
|
|
29
|
-
|
|
40
|
+
if (this.debug) {
|
|
41
|
+
this.log.debug('Executed didFinishLaunching callback');
|
|
42
|
+
}
|
|
30
43
|
// run the method to discover / register your devices as accessories
|
|
31
44
|
this.discoverDevices();
|
|
32
|
-
// Set up periodic device updates
|
|
45
|
+
// Set up periodic device updates
|
|
33
46
|
this.deviceUpdateInterval = setInterval(() => {
|
|
34
47
|
this.updateDeviceStates();
|
|
35
|
-
},
|
|
48
|
+
}, this.updateInterval * 1000); // Convert to milliseconds
|
|
36
49
|
});
|
|
37
50
|
// Clean up when shutting down
|
|
38
51
|
this.api.on('shutdown', () => {
|
|
@@ -53,15 +66,23 @@ class TSVESyncPlatform {
|
|
|
53
66
|
*/
|
|
54
67
|
async discoverDevices() {
|
|
55
68
|
try {
|
|
69
|
+
if (this.debug) {
|
|
70
|
+
this.log.debug('Starting device discovery');
|
|
71
|
+
}
|
|
56
72
|
// Login and get devices
|
|
57
73
|
await this.client.login();
|
|
58
74
|
const devices = await this.client.getDevices();
|
|
75
|
+
if (this.debug) {
|
|
76
|
+
this.log.debug('Found devices:', devices.length);
|
|
77
|
+
}
|
|
59
78
|
// Loop over the discovered devices and register each one
|
|
60
79
|
for (const device of devices) {
|
|
61
80
|
const uuid = this.api.hap.uuid.generate(device.id);
|
|
62
81
|
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
63
82
|
if (existingAccessory) {
|
|
64
|
-
this.
|
|
83
|
+
if (this.debug) {
|
|
84
|
+
this.log.debug('Restoring existing accessory from cache:', existingAccessory.displayName);
|
|
85
|
+
}
|
|
65
86
|
existingAccessory.context.device = device;
|
|
66
87
|
new platformAccessory_1.TSVESyncAccessory(this, existingAccessory, this.client);
|
|
67
88
|
}
|
|
@@ -77,6 +98,9 @@ class TSVESyncPlatform {
|
|
|
77
98
|
this.accessories.forEach(accessory => {
|
|
78
99
|
const device = devices.find(device => this.api.hap.uuid.generate(device.id) === accessory.UUID);
|
|
79
100
|
if (!device) {
|
|
101
|
+
if (this.debug) {
|
|
102
|
+
this.log.debug('Removing accessory no longer present:', accessory.displayName);
|
|
103
|
+
}
|
|
80
104
|
this.api.unregisterPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [accessory]);
|
|
81
105
|
}
|
|
82
106
|
});
|
|
@@ -90,11 +114,17 @@ class TSVESyncPlatform {
|
|
|
90
114
|
*/
|
|
91
115
|
async updateDeviceStates() {
|
|
92
116
|
try {
|
|
117
|
+
if (this.debug) {
|
|
118
|
+
this.log.debug('Updating device states');
|
|
119
|
+
}
|
|
93
120
|
await this.client.login();
|
|
94
121
|
const devices = await this.client.getDevices();
|
|
95
122
|
this.accessories.forEach(accessory => {
|
|
96
123
|
const device = devices.find(d => this.api.hap.uuid.generate(d.id) === accessory.UUID);
|
|
97
124
|
if (device) {
|
|
125
|
+
if (this.debug) {
|
|
126
|
+
this.log.debug('Updated state for device:', accessory.displayName);
|
|
127
|
+
}
|
|
98
128
|
accessory.context.device = device;
|
|
99
129
|
}
|
|
100
130
|
});
|
package/dist/platform.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":";;;AACA,yCAAwD;AACxD,2DAAwD;AACxD,uCAAoC;AAEpC,MAAa,gBAAgB;
|
|
1
|
+
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-tsvesync",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Homebridge plugin for
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Homebridge plugin for VeSync devices including Levoit air purifiers, humidifiers, and Etekcity smart outlets",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"lint": "eslint src/**.ts",
|
|
@@ -9,6 +9,32 @@
|
|
|
9
9
|
"build": "rimraf ./dist && tsc",
|
|
10
10
|
"prepublishOnly": "npm run lint && npm run build"
|
|
11
11
|
},
|
|
12
|
+
"author": {
|
|
13
|
+
"name": "Mick Giles",
|
|
14
|
+
"url": "https://github.com/mickgiles"
|
|
15
|
+
},
|
|
16
|
+
"maintainers": [
|
|
17
|
+
{
|
|
18
|
+
"name": "Mick Giles",
|
|
19
|
+
"email": "mick@mickgiles.com"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=14.18.1",
|
|
24
|
+
"homebridge": ">=1.3.5"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/mickgiles/homebridge-tsvesync.git"
|
|
29
|
+
},
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/mickgiles/homebridge-tsvesync/issues"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/mickgiles/homebridge-tsvesync#readme",
|
|
34
|
+
"funding": {
|
|
35
|
+
"type": "github",
|
|
36
|
+
"url": "https://github.com/sponsors/mickgiles"
|
|
37
|
+
},
|
|
12
38
|
"keywords": [
|
|
13
39
|
"homebridge-plugin",
|
|
14
40
|
"tsvesync",
|
|
@@ -61,10 +87,7 @@
|
|
|
61
87
|
"pet-mode",
|
|
62
88
|
"turbo-mode"
|
|
63
89
|
],
|
|
64
|
-
"
|
|
65
|
-
"node": ">=14.18.1",
|
|
66
|
-
"homebridge": ">=1.3.5"
|
|
67
|
-
},
|
|
90
|
+
"license": "MIT",
|
|
68
91
|
"dependencies": {
|
|
69
92
|
"tsvesync": "^1.0.11"
|
|
70
93
|
},
|
package/src/platform.ts
CHANGED
|
@@ -12,6 +12,8 @@ export class TSVESyncPlatform implements DynamicPlatformPlugin {
|
|
|
12
12
|
|
|
13
13
|
private client!: TSVESync;
|
|
14
14
|
private deviceUpdateInterval?: NodeJS.Timeout;
|
|
15
|
+
private readonly updateInterval!: number;
|
|
16
|
+
private readonly debug!: boolean;
|
|
15
17
|
|
|
16
18
|
constructor(
|
|
17
19
|
public readonly log: Logger,
|
|
@@ -24,24 +26,39 @@ export class TSVESyncPlatform implements DynamicPlatformPlugin {
|
|
|
24
26
|
return;
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
// Get config values with defaults
|
|
30
|
+
this.updateInterval = config.updateInterval || 30;
|
|
31
|
+
this.debug = config.debug || false;
|
|
32
|
+
|
|
27
33
|
// Initialize TSVESync client
|
|
28
34
|
this.client = new TSVESync({
|
|
29
35
|
username: config.username,
|
|
30
36
|
password: config.password,
|
|
31
37
|
});
|
|
32
38
|
|
|
33
|
-
this.
|
|
39
|
+
if (this.debug) {
|
|
40
|
+
this.log.debug('Initialized platform with config:', {
|
|
41
|
+
name: config.name,
|
|
42
|
+
username: config.username,
|
|
43
|
+
updateInterval: this.updateInterval,
|
|
44
|
+
debug: this.debug,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.log.info('Finished initializing platform:', this.config.name);
|
|
34
49
|
|
|
35
50
|
// When this event is fired it means Homebridge has restored all cached accessories from disk.
|
|
36
51
|
this.api.on('didFinishLaunching', () => {
|
|
37
|
-
|
|
52
|
+
if (this.debug) {
|
|
53
|
+
this.log.debug('Executed didFinishLaunching callback');
|
|
54
|
+
}
|
|
38
55
|
// run the method to discover / register your devices as accessories
|
|
39
56
|
this.discoverDevices();
|
|
40
57
|
|
|
41
|
-
// Set up periodic device updates
|
|
58
|
+
// Set up periodic device updates
|
|
42
59
|
this.deviceUpdateInterval = setInterval(() => {
|
|
43
60
|
this.updateDeviceStates();
|
|
44
|
-
},
|
|
61
|
+
}, this.updateInterval * 1000); // Convert to milliseconds
|
|
45
62
|
});
|
|
46
63
|
|
|
47
64
|
// Clean up when shutting down
|
|
@@ -65,17 +82,27 @@ export class TSVESyncPlatform implements DynamicPlatformPlugin {
|
|
|
65
82
|
*/
|
|
66
83
|
async discoverDevices() {
|
|
67
84
|
try {
|
|
85
|
+
if (this.debug) {
|
|
86
|
+
this.log.debug('Starting device discovery');
|
|
87
|
+
}
|
|
88
|
+
|
|
68
89
|
// Login and get devices
|
|
69
90
|
await this.client.login();
|
|
70
91
|
const devices = await this.client.getDevices();
|
|
71
92
|
|
|
93
|
+
if (this.debug) {
|
|
94
|
+
this.log.debug('Found devices:', devices.length);
|
|
95
|
+
}
|
|
96
|
+
|
|
72
97
|
// Loop over the discovered devices and register each one
|
|
73
98
|
for (const device of devices) {
|
|
74
99
|
const uuid = this.api.hap.uuid.generate(device.id);
|
|
75
100
|
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
76
101
|
|
|
77
102
|
if (existingAccessory) {
|
|
78
|
-
this.
|
|
103
|
+
if (this.debug) {
|
|
104
|
+
this.log.debug('Restoring existing accessory from cache:', existingAccessory.displayName);
|
|
105
|
+
}
|
|
79
106
|
existingAccessory.context.device = device;
|
|
80
107
|
new TSVESyncAccessory(this, existingAccessory, this.client);
|
|
81
108
|
|
|
@@ -92,6 +119,9 @@ export class TSVESyncPlatform implements DynamicPlatformPlugin {
|
|
|
92
119
|
this.accessories.forEach(accessory => {
|
|
93
120
|
const device = devices.find(device => this.api.hap.uuid.generate(device.id) === accessory.UUID);
|
|
94
121
|
if (!device) {
|
|
122
|
+
if (this.debug) {
|
|
123
|
+
this.log.debug('Removing accessory no longer present:', accessory.displayName);
|
|
124
|
+
}
|
|
95
125
|
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
96
126
|
}
|
|
97
127
|
});
|
|
@@ -106,12 +136,19 @@ export class TSVESyncPlatform implements DynamicPlatformPlugin {
|
|
|
106
136
|
*/
|
|
107
137
|
private async updateDeviceStates() {
|
|
108
138
|
try {
|
|
139
|
+
if (this.debug) {
|
|
140
|
+
this.log.debug('Updating device states');
|
|
141
|
+
}
|
|
142
|
+
|
|
109
143
|
await this.client.login();
|
|
110
144
|
const devices = await this.client.getDevices();
|
|
111
145
|
|
|
112
146
|
this.accessories.forEach(accessory => {
|
|
113
147
|
const device = devices.find(d => this.api.hap.uuid.generate(d.id) === accessory.UUID);
|
|
114
148
|
if (device) {
|
|
149
|
+
if (this.debug) {
|
|
150
|
+
this.log.debug('Updated state for device:', accessory.displayName);
|
|
151
|
+
}
|
|
115
152
|
accessory.context.device = device;
|
|
116
153
|
}
|
|
117
154
|
});
|