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.
@@ -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
+ }
@@ -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.
@@ -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;aAW1C,GAAG,EAAE,MAAM;aACX,MAAM,EAAE,cAAc;aACtB,GAAG,EAAE,GAAG;IAZ1B,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;gBAG5B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,GAAG;IAoC1B;;OAEG;IACH,kBAAkB,CAAC,SAAS,EAAE,iBAAiB;IAK/C;;OAEG;IACG,eAAe;IAsCrB;;OAEG;YACW,kBAAkB;CAejC"}
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.log.debug('Finished initializing platform:', this.config.name);
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
- log.debug('Executed didFinishLaunching callback');
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 (every 30 seconds)
45
+ // Set up periodic device updates
33
46
  this.deviceUpdateInterval = setInterval(() => {
34
47
  this.updateDeviceStates();
35
- }, 30000);
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.log.info('Restoring existing accessory from cache:', existingAccessory.displayName);
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
  });
@@ -1 +1 @@
1
- {"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
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.0",
4
- "description": "Homebridge plugin for TSVESync devices",
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
- "engines": {
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.log.debug('Finished initializing platform:', this.config.name);
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
- log.debug('Executed didFinishLaunching callback');
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 (every 30 seconds)
58
+ // Set up periodic device updates
42
59
  this.deviceUpdateInterval = setInterval(() => {
43
60
  this.updateDeviceStates();
44
- }, 30000);
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.log.info('Restoring existing accessory from cache:', existingAccessory.displayName);
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
  });