homebridge-myplace 2.1.4 → 2.2.0

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/CHANGELOG.md CHANGED
@@ -1,4 +1,4 @@
1
1
  ### Homebridge-myplace - An independent plugin for Homebridge bringing Advantage Air MyPlace system, its smaller siblings (E-zone, MyAir, MyAir4, etc) and its cousins (e.g. Fujitsu AnywAir) to Homekit
2
- ##### v2.1.4 (2025-03-10)
2
+ ##### v2.2.0 (2025-06-27)
3
3
 
4
- ###### (1) A minor bug fix to resolve the `TypeError` while loading plugin if `homebridge-cmd4` is also installed
4
+ ###### (1) Simplified the setup process
package/Cmd5Platform.js CHANGED
@@ -5,9 +5,6 @@ const { getAccessoryName,
5
5
  getAccessoryDisplayName } = require( "./utils/getAccessoryNameFunctions" );
6
6
  const { parseAddQueueTypes } = require( "./Cmd5PriorityPollingQueue" );
7
7
 
8
-
9
-
10
-
11
8
  let Logger = require( "./utils/Logger" );
12
9
  let getAccessoryUUID = require( "./utils/getAccessoryUUID" );
13
10
  let lcFirst = require( "./utils/lcFirst" );
@@ -17,6 +14,8 @@ let trueTypeOf = require( "./utils/trueTypeOf" );
17
14
  // Hierarchy variables
18
15
  let HV = require( "./utils/HV" );
19
16
 
17
+ // Essential variables
18
+ const { spawnSync } = require('child_process');
20
19
  let createAccessorysInformationService = require( "./utils/createAccessorysInformationService" );
21
20
 
22
21
  // Pretty Colors
@@ -37,6 +36,8 @@ const Cmd5Accessory = require( "./Cmd5Accessory" ).Cmd5Accessory;
37
36
  // Settings, Globals and Constants
38
37
  let settings = require( "./cmd5Settings" );
39
38
  const constants = require( "./cmd5Constants" );
39
+ const path = require('path');
40
+ const fs = require('fs');
40
41
 
41
42
  // Platform definition
42
43
  class Cmd5Platform
@@ -102,23 +103,85 @@ class Cmd5Platform
102
103
  // Create the hierarhy variables
103
104
  this.hV = new HV();
104
105
 
105
- this.parseConfigForCmd5Directives( this.config );
106
-
107
- // Update the namespace for stored variables
108
- // like timeout, stateChangeResponseTime ... As it may require
109
- // changes from parseConfig.
110
- this.hV.update( this );
111
-
112
- this.processNewCharacteristicDefinitions( );
113
-
114
-
115
106
  // didFinishLaunching is only called after the
116
107
  // registerPlatform completes.
117
108
  api.on( "didFinishLaunching", ( ) =>
118
109
  {
119
- this.log.info( chalk.blue( "Cmd5Platform didFinishLaunching" ) );
110
+ this.log.info( chalk.green( "MyPlace Platform didFinishLaunching" ) );
111
+
112
+ // Remove MyPlace shell script temporary working directories on Homebridge RESTART
113
+ this.log.info( chalk.yellow( "Removing temporary working directories" ) );
114
+ try {
115
+ const directoryPath = process.env.TMPDIR || "/tmp";
116
+ const files = fs.readdirSync(directoryPath);
117
+ const filteredFiles = files.filter(file => file.match(/^(AA|BB)-\d{3}$/));
118
+
119
+ filteredFiles.forEach(file => {
120
+ const sdir = `${directoryPath}/${file}`;
121
+
122
+ try {
123
+ fs.rmSync(sdir, { recursive: true, force: true });
124
+ this.log.info(`Temporary working directory ${sdir} removed`);
125
+ } catch (err) {
126
+ this.log.error(` Unable to remove temporary working directory ${sdir}: [${err}]`);
127
+ }
128
+ });
129
+ } catch (err) {
130
+ this.log.error(`Unable to scan and remove temporary working directory: [${err}]`);
131
+ }
132
+
133
+ // Run ConfigCreator to update/refresh the MyPlace config
134
+ this.log.info( chalk.yellow( "Running createMyPlacConfig..." ) );
135
+ try {
136
+ // Build args for up to 3 devices
137
+ let args = [];
138
+ for (let i = 0; i < 3; i++) {
139
+ const device = this.config.devices[i];
140
+ if (device) {
141
+ const ipPort = `${device.ipAddress || ''}:${device.port || ''}`;
142
+ const name = device.name || '';
143
+ const extraTimers = device.extraTimers ?? false;
144
+ const debug = device.debug ?? false;
145
+ args.push(ipPort, name, extraTimers, debug);
146
+ } else {
147
+ // If device is missing, push empty args
148
+ args.push('', '', '', '');
149
+ }
150
+ }
151
+
152
+ // Add __dirname and "homebridge" as last two arguments
153
+ args.push(`${__dirname}/MyPlace.sh`);
154
+
155
+ // Run the createMyPlaceconfig.js script
156
+ const scriptPath = path.resolve(__dirname, 'utils', 'createMyPlaceConfig.js');
157
+ this.log.debug('Running script:', scriptPath, args);
158
+
159
+ const result = spawnSync('node', [scriptPath, ...args], { encoding: 'utf8' });
160
+ const feedback = result.stdout.trim();
161
+
162
+ const lines = feedback.split('\n');
163
+ const status = lines.shift();
164
+ const jsonText = lines.join('\n').trim();
165
+
166
+ if (status.includes('DONE')) {
167
+ this.config = JSON.parse(jsonText);
168
+ this.log.info(status);
169
+ this.log.debug('Updated config:\n' + JSON.stringify(this.config, null, 2));
170
+ } else {
171
+ this.log.error('ERROR: Errors encountered running createMyPlaceConfig', status);
172
+ this.log.warn('Proceeding with original config — no accessories will be created.');
173
+ }
174
+ } catch (err) {
175
+ this.log.warn('ERROR: createMyPlaceConfig failed:', err);
176
+ this.log.warn('Proceeding with original config — no accessories will be created.');
177
+ }
178
+
179
+ // Now process these using the updated config
180
+ this.parseConfigForCmd5Directives( this.config );
181
+ this.hV.update( this );
182
+ this.processNewCharacteristicDefinitions( );
120
183
 
121
- this.log.info( chalk.magenta( "Scanning config.json and the cache for devices to be removed/restored from cache" ) );
184
+ this.log.info( chalk.yellow( "Scanning the config and the cache for devices to be removed or restored from cache" ) );
122
185
  // scan the platform devices to identify which ones to be restored from cache
123
186
  this.scanToBeRestoredDevices( this.log );
124
187
 
package/README.md CHANGED
@@ -25,99 +25,43 @@ An independent plugin bringing [Advantage Air](https://www.advantageair.com.au/)
25
25
  * [Fujitsu anywAIR](https://apps.apple.com/au/app/anywair/id1509639853)
26
26
 
27
27
  ## Installation
28
- ### Raspbian/HOOBS/macOS/NAS
29
28
  1. Install Homebridge via these instructions for [Raspbian](https://github.com/homebridge/homebridge/wiki/Install-Homebridge-on-Raspbian), [HOOBS](https://support.hoobs.org/docs) or [macOS](https://github.com/homebridge/homebridge/wiki/Install-Homebridge-on-macOS), if you have not already.
30
29
 
31
- 2. Check if <B>jq</B> and <B>curl</B> are installed (<B>curl</B> should already be):
32
- ```shell
33
- jq --version
34
- curl --version
35
- ```
36
- If they are installed, the above command should return a version number. If not, install them:
37
- ##### For Raspbian/Hoobs:
38
- ```shell
39
- sudo apt-get install <jq or curl>
40
- ```
41
- ##### For MacOS:
42
- ```shell
43
- brew install <jq or curl>
44
- ```
45
- ##### For Synology NAS:
46
- ```shell
47
- apt-get install <jq or curl>
48
- ```
49
- ##### For QNAP NAS:
50
- ```shell
51
- apk add <jq or curl>
52
- ```
53
- #### Important note:
54
- At the time of updating this README, the `apt-get insatall` only allow jq-1.6 to be installed, which is notorously slow! To install the lastest and **MUCH faster** version of jq-1.7.1, please follow the step-by-step guide below:
55
- 1. Download the Source Code:
56
-
57
- You can download the source code "jq-1.7.1.tar.gz" for jq 1.7.1 from the official GitHub releases page (https://github.com/jqlang/jq/releases) or use the link below:
58
- ```shell
59
- wget https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-1.7.1.tar.gz
60
- ```
61
- 2. Install Dependencies:
62
-
63
- Ensure you have the necessary build tools and dependencies installed. You can do this by running:
64
- ```shell
65
- sudo apt-get update
66
- sudo apt-get install -y autoconf automake libtool make gcc
67
- ```
68
- 3. Extract and Build:
69
-
70
- Extract the downloaded tarball and navigate to the directory:
71
- ```shell
72
- tar -xvzf jq-1.7.1.tar.gz
73
- cd jq-1.7.1
74
- chmod +x configure
75
- ```
76
- 4. Run the following commands to build and install jq:
77
- ```shell
78
- ./configure
79
- make
80
- sudo make install
81
- ```
82
- 5. Verify Installation:
83
-
84
- After installation, you can verify that jq is installed correctly by running:
85
- ```shell
86
- jq --version
87
- ```
30
+ 2. Make sure that <B>jq</B> and <B>curl</B> are installed. Try to install <B>jq-1.7</B> if you can. It is much faster.
31
+
88
32
  3. Find the `homebridge-myplace` plugin via the Homebridge UI 'Plugins' tab search function, once found, click the blue *down-arrow* at the bottom right to install.
89
33
 
90
34
  <p align="left">
91
35
  <img width="400px" src="Screenshots/MyPlaceInstall3.png">
92
36
  </p>
93
37
 
94
- Once install, `Config: homebridge-myplace` UI will pop up, then follow the steps shown in Step 4 below.
38
+ Once installed, `Config: homebridge-myplace` UI will pop up, then follow the steps outlined in Step 4 below.
39
+
40
+ ![MyPlace_setting_UI](https://github.com/user-attachments/assets/49d49852-908b-4479-aebc-81337c820b1a)
95
41
 
96
42
  If for some reasons, the `Config: homebridge-myplace` UI did not pop up, locate your newly installed `Homebridge Myplace` plugin and click on the three dots at the bottom right and select `Plugin Config` to get the `Config: homebridge-myplace` UI.
97
43
 
98
- 4. Create MyPlace configuration file:
44
+ 5. Configuring MyPlace plugin:
99
45
 
100
- This is the `Config: homebridge-myplace` UI where you register your system parameters and create/check the required configuration file to run this plugin.
101
- <p align="left">
102
- <img width="600px" src="Screenshots/MyPlaceConfigCreator.png">
103
- </p>
104
-
105
- In <B>Device Settings</B> area, fill out the `Name`, `IP Address` and `PORT used` fields (default PORT is `2025` for most users, Fujitsu anywAIR users set this to `10211` ) and check/uncheck the self-explanatory checkboxes for `Include extra timers` and `Enable detailed debug log`, then click `SAVE`. This is to save your system parameters. Click `CLOSE` if a pop up urging you to `RESTART`.
46
+ In <B>Device Settings</B> area, fill out the `Name`, `IP Address` and `PORT used` fields (default PORT is `2025` for most users, Fujitsu anywAIR users set this to `10211` ) and check/uncheck the self-explanatory checkboxes for `Include extra timers` and `Enable detailed debug log`, click `SAVE` then `RESTART`.
106
47
 
107
- Go back to `Config: homebridge-myplace` UI agina (by clicking the the 3 dots at the bottom right and click `Plugin Config`) and press the `CREATE CONFIGURATION` button to create the required configuration file.
108
-
109
- On a sucess, you may click `CHECK CONFIGURATION`to check the configuration file just created is in order. On a success it will say `Passed`; if something is incorrect, an error message will pop up telling you what needs to be fixed.
110
-
111
- Otherwise, click `SAVE` then `RESTART`.
112
-
113
- **HOOBS** users who do not have access to Homebridge UI (for now!) will have to run the Config Creator on a terminal:
114
- ```shell
115
- cd
116
- <Plugin Path>/node_modules/homebridge-myplace/ConfigCreator.sh
48
+ For users who do not have access to Homebridge UI have to make sure that a config, as shown in the example below, is in the homebridge config.json:
49
+
50
+ ```
51
+ {
52
+ "name": "MyPlace",
53
+ "devices": [
54
+ {
55
+ "name": "Aircon",
56
+ "ipAddress": "192.168.1.3",
57
+ "port": 2025,
58
+ "extraTimers": true,
59
+ "debug": false
60
+ }
61
+ ],
62
+ "platform": "MyPlace"
63
+ }
117
64
  ```
118
- then follow the on-screen instructions.
119
-
120
- *typical `<Plugin Path>` is `/var/lib/hoobs/<bridge>`
121
65
 
122
66
  ## How it Looks and Works
123
67
  ### (A) Aircon System (MyAir, E-zone, etc) has the following typical Homekit tiles:
@@ -1,4 +1,8 @@
1
1
  ### Homebridge-myplace - An independent plugin for Homebridge bringing Advantage Air MyPlace system, its smaller siblings (E-zone, MyAir, MyAir4, etc) and its cousins (e.g. Fujitsu AnywAir) to Homekit
2
+ ##### v2.2.0 (2025-06-27)
3
+
4
+ ###### (1) Simplified the setup process
5
+
2
6
  ##### v2.1.4 (2025-03-10)
3
7
 
4
8
  ###### (1) A minor bug fix to resolve the `TypeError` while loading plugin if `homebridge-cmd4` is also installed
@@ -9,11 +9,12 @@
9
9
  "properties": {
10
10
  "name": {
11
11
  "type": "string",
12
- "default": "MyPlace",
13
- "required": true
12
+ "default": "MyPlace"
14
13
  },
15
14
  "devices": {
16
15
  "type": "array",
16
+ "minItems": 1,
17
+ "maxItems": 3,
17
18
  "items": {
18
19
  "title": "AdvantageAir device",
19
20
  "type": "object",
@@ -22,7 +23,6 @@
22
23
  "title": "Name",
23
24
  "description": "The name of the AdvantageAir device, default=Aircon",
24
25
  "type": "string",
25
- "required": true,
26
26
  "default": "Aircon"
27
27
  },
28
28
  "ipAddress": {
@@ -30,357 +30,32 @@
30
30
  "description": "The device's IP address. It is recommended to set a static IP for this device.",
31
31
  "type": "string",
32
32
  "format": "ipv4",
33
- "required": true,
34
33
  "placeholder": "192.168.0.1"
35
34
  },
36
35
  "port": {
37
36
  "title": "PORT used",
38
37
  "description": "The PORT number used for this device, default=2025.",
39
38
  "type": "number",
40
- "required": true,
41
- "default": "2025"
39
+ "default": 2025
42
40
  },
43
41
  "extraTimers": {
44
42
  "title": "Include extra timers",
45
43
  "description": "Include extra timers to turn on the Aircon in specific mode: Cool, Heat or Vent.",
46
44
  "type": "boolean",
47
- "required": false,
48
45
  "default": false
49
46
  },
50
47
  "debug": {
51
48
  "title": "Enable detailed debug log",
52
49
  "description": "Enables a detailed debug log. Useful when trying to figure out issues with the plugin.",
53
50
  "type": "boolean",
54
- "required": false,
55
51
  "default": false
56
52
  }
57
- }
58
- }
59
- },
60
- "title": {
61
- "type": "string"
62
- },
63
- "debug": {
64
- "type": "boolean"
65
- },
66
- "outputConstants": {
67
- "type": "boolean"
68
- },
69
- "statusMsg": {
70
- "type": "boolean"
71
- },
72
- "timeout": {
73
- "type": "number"
74
- },
75
- "stateChangeResponseTime": {
76
- "type": "number"
77
- },
78
- "constants": {
79
- "type": "array",
80
- "required": false,
81
- "items": {
82
- "type": "object",
83
- "properties": {
84
- "key": {
85
- "type": "string"
86
- },
87
- "value": {
88
- "type": "string"
89
- }
90
- }
91
- }
92
- },
93
- "queueTypes": {
94
- "type": "array",
95
- "required": false,
96
- "items": {
97
- "type": "object",
98
- "properties": {
99
- "queue": {
100
- "type": "string"
101
- },
102
- "queueType": {
103
- "type": "string"
104
- }
105
- }
106
- }
107
- },
108
- "accessories": {
109
- "type": "array",
110
- "required": false,
111
- "items": {
112
- "type": "object",
113
- "properties": {
114
- "type": {
115
- "type": "string"
116
- },
117
- "displayName": {
118
- "type": "string"
119
- },
120
- "active": {
121
- "type": "number"
122
- },
123
- "brightness": {
124
- "type": "number"
125
- },
126
- "on": {
127
- "type": "boolean"
128
- },
129
- "rotationSpeed": {
130
- "type": "number"
131
- },
132
- "rotationDirection": {
133
- "type": "number"
134
- },
135
- "currentHeatingCoolingState": {
136
- "type": "string"
137
- },
138
- "targetHeatingCoolingState": {
139
- "type": "string"
140
- },
141
- "currentDoorState": {
142
- "type": "number"
143
- },
144
- "targetDoorState": {
145
- "type": "number"
146
- },
147
- "currentPosition": {
148
- "type": "number"
149
- },
150
- "targetPosition": {
151
- "type": "number"
152
- },
153
- "currentTemperature": {
154
- "type": "number"
155
- },
156
- "targetTemperature": {
157
- "type": "number"
158
- },
159
- "temperatureDisplayUnits": {
160
- "type": "string"
161
- },
162
- "obstructionDetected": {
163
- "type": "boolean"
164
- },
165
- "name": {
166
- "type": "string"
167
- },
168
- "manufacturer": {
169
- "type": "string"
170
- },
171
- "model": {
172
- "type": "string"
173
- },
174
- "positionState": {
175
- "type": "number"
176
- },
177
- "serialNumber": {
178
- "type": "string"
179
- },
180
- "queue": {
181
- "type": "string"
182
- },
183
- "polling": {
184
- "type": "boolean"
185
- },
186
- "polling": {
187
- "type": "array",
188
- "required": false,
189
- "items": {
190
- "type": "object",
191
- "properties": {
192
- "characteristic": {
193
- "type": "string"
194
- }
195
- }
196
- }
197
- },
198
- "props": {
199
- "type": "object",
200
- "required": false,
201
- "properties": {
202
- "brightness": {
203
- "type": "object",
204
- "properties": {
205
- "minStep": {
206
- "type": "number"
207
- }
208
- }
209
- },
210
- "currentTemperature": {
211
- "type": "object",
212
- "properties": {
213
- "maxValue": {
214
- "type": "number"
215
- },
216
- "minValue": {
217
- "type": "number"
218
- },
219
- "minStep": {
220
- "type": "number"
221
- }
222
- }
223
- },
224
- "rotationSpeed": {
225
- "type": "object",
226
- "properties": {
227
- "minStep": {
228
- "type": "number"
229
- }
230
- }
231
- },
232
- "targetTemperature": {
233
- "type": "object",
234
- "properties": {
235
- "maxValue": {
236
- "type": "number"
237
- },
238
- "minValue": {
239
- "type": "number"
240
- },
241
- "minStep": {
242
- "type": "number"
243
- }
244
- }
245
- }
246
- }
247
- },
248
- "state_cmd": {
249
- "type": "string"
250
- },
251
- "state_cmd_suffix": {
252
- "type": "string"
253
- },
254
- "linkedTypes": {
255
- "type": "array",
256
- "required": false,
257
- "items": {
258
- "type": "object",
259
- "properties": {
260
- "type": {
261
- "type": "string"
262
- },
263
- "displayName": {
264
- "type": "string"
265
- },
266
- "active": {
267
- "type": "number"
268
- },
269
- "on": {
270
- "type": "boolean"
271
- },
272
- "brightness": {
273
- "type": "number"
274
- },
275
- "currentTemperature": {
276
- "type": "number"
277
- },
278
- "targetTemperature": {
279
- "type": "number"
280
- },
281
- "currentHeatingCoolingState": {
282
- "type": "string"
283
- },
284
- "targetHeatingCoolingState": {
285
- "type": "string"
286
- },
287
- "temperatureDisplayUnits": {
288
- "type": "string"
289
- },
290
- "rotationSpeed": {
291
- "type": "number"
292
- },
293
- "rotationDirection": {
294
- "type": "number"
295
- },
296
- "name": {
297
- "type": "string"
298
- },
299
- "manufacturer": {
300
- "type": "string"
301
- },
302
- "model": {
303
- "type": "string"
304
- },
305
- "serialNumber": {
306
- "type": "string"
307
- },
308
- "queue": {
309
- "type": "string"
310
- },
311
- "polling": {
312
- "type": "array",
313
- "items": {
314
- "type": "object",
315
- "properties": {
316
- "characteristic": {
317
- "type": "string"
318
- }
319
- }
320
- }
321
- },
322
- "props": {
323
- "type": "object",
324
- "properties": {
325
- "brightness": {
326
- "type": "object",
327
- "properties": {
328
- "minStep": {
329
- "type": "number"
330
- }
331
- }
332
- },
333
- "currentTemperature": {
334
- "type": "object",
335
- "properties": {
336
- "maxValue": {
337
- "type": "number"
338
- },
339
- "minValue": {
340
- "type": "number"
341
- },
342
- "minStep": {
343
- "type": "number"
344
- }
345
- }
346
- },
347
- "rotationSpeed": {
348
- "type": "object",
349
- "properties": {
350
- "minStep": {
351
- "type": "number"
352
- }
353
- }
354
- },
355
- "targetTemperature": {
356
- "type": "object",
357
- "properties": {
358
- "maxValue": {
359
- "type": "number"
360
- },
361
- "minValue": {
362
- "type": "number"
363
- },
364
- "minStep": {
365
- "type": "number"
366
- }
367
- }
368
- }
369
- }
370
- },
371
- "state_cmd": {
372
- "type": "string"
373
- },
374
- "state_cmd_suffix": {
375
- "type": "string"
376
- }
377
- }
378
- }
379
- }
380
- }
53
+ },
54
+ "required": ["name", "ipAddress", "port"]
381
55
  }
382
56
  }
383
- }
57
+ },
58
+ "required": ["name", "devices"]
384
59
  },
385
60
  "layout": [
386
61
  {