iobroker.panasonic-comfort-cloud 1.2.8 → 1.2.9

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,59 @@
1
+ name: Test and Release
2
+
3
+ # Run this job on all pushes and pull requests
4
+ # as well as tags with a semantic version
5
+ on:
6
+ push:
7
+ branches:
8
+ - "*"
9
+ tags:
10
+ # normal versions
11
+ - "v[0-9]+.[0-9]+.[0-9]+"
12
+ # pre-releases
13
+ - "v[0-9]+.[0-9]+.[0-9]+-**"
14
+ pull_request: {}
15
+
16
+ jobs:
17
+ # Performs quick checks before the expensive test runs
18
+ check-and-lint:
19
+ if: contains(github.event.head_commit.message, '[skip ci]') == false
20
+
21
+ runs-on: ubuntu-latest
22
+
23
+ steps:
24
+ - uses: ioBroker/testing-action-check@v1
25
+ with:
26
+ node-version: '14.x'
27
+ lint: true
28
+
29
+ adapter-tests:
30
+ if: contains(github.event.head_commit.message, '[skip ci]') == false
31
+
32
+ runs-on: ${{ matrix.os }}
33
+ strategy:
34
+ matrix:
35
+ node-version: [12.x, 14.x, 16.x]
36
+ os: [ubuntu-latest, windows-latest, macos-latest]
37
+
38
+ steps:
39
+ - uses: ioBroker/testing-action-adapter@v1
40
+ with:
41
+ node-version: ${{ matrix.node-version }}
42
+ os: ${{ matrix.os }}
43
+
44
+ deploy:
45
+ needs: [check-and-lint, adapter-tests]
46
+
47
+ if: |
48
+ contains(github.event.head_commit.message, '[skip ci]') == false &&
49
+ github.event_name == 'push' &&
50
+ startsWith(github.ref, 'refs/tags/v')
51
+
52
+ runs-on: ubuntu-latest
53
+
54
+ steps:
55
+ - uses: ioBroker/testing-action-deploy@v1
56
+ with:
57
+ node-version: '14.x'
58
+ npm-token: ${{ secrets.NPM_TOKEN }}
59
+ github-token: ${{ secrets.GITHUB_TOKEN }}
package/README.md CHANGED
@@ -12,80 +12,41 @@
12
12
 
13
13
  ## panasonic-comfort-cloud adapter for ioBroker
14
14
 
15
- Adapter for Panasonic Comfort Cloud
16
-
17
- ## Developer manual
18
- This section is intended for the developer. It can be deleted later
19
-
20
- ### Getting started
21
-
22
- You are almost done, only a few steps left:
23
- 1. Create a new repository on GitHub with the name `ioBroker.panasonic-comfort-cloud`
24
- 1. Initialize the current folder as a new git repository:
25
- ```bash
26
- git init
27
- git add .
28
- git commit -m "Initial commit"
29
- ```
30
- 1. Link your local repository with the one on GitHub:
31
- ```bash
32
- git remote add origin https://github.com/marc2016/ioBroker.panasonic-comfort-cloud
33
- ```
34
-
35
- 1. Push all files to the GitHub repo:
36
- ```bash
37
- git push origin master
38
- ```
39
- 1. Head over to [src/main.ts](src/main.ts) and start programming!
40
-
41
- ### Scripts in `package.json`
42
- Several npm scripts are predefined for your convenience. You can run them using `npm run <scriptname>`
43
- | Script name | Description |
44
- |-------------|----------------------------------------------------------|
45
- | `build` | Re-compile the TypeScript sources. |
46
- | `watch` | Re-compile the TypeScript sources and watch for changes. |
47
- | `test:ts` | Executes the tests you defined in `*.test.ts` files. |
48
- | `test:package` | Ensures your `package.json` and `io-package.json` are valid. |
49
- | `test:unit` | Tests the adapter startup with unit tests (fast, but might require module mocks to work). |
50
- | `test:integration`| Tests the adapter startup with an actual instance of ioBroker. |
51
- | `test` | Performs a minimal test run on package files and your tests. |
52
- | `coverage` | Generates code coverage using your test files. |
53
-
54
- ### Writing tests
55
- When done right, testing code is invaluable, because it gives you the
56
- confidence to change your code while knowing exactly if and when
57
- something breaks. A good read on the topic of test-driven development
58
- is https://hackernoon.com/introduction-to-test-driven-development-tdd-61a13bc92d92.
59
- Although writing tests before the code might seem strange at first, but it has very
60
- clear upsides.
61
-
62
- The template provides you with basic tests for the adapter startup and package files.
63
- It is recommended that you add your own tests into the mix.
64
-
65
- ### Publishing the adapter
66
- See the documentation of [ioBroker.repositories](https://github.com/ioBroker/ioBroker.repositories#requirements-for-adapter-to-get-added-to-the-latest-repository).
67
-
68
- ### Test the adapter manually on a local ioBroker installation
69
- In order to install the adapter locally without publishing, the following steps are recommended:
70
- 1. Create a tarball from your dev directory:
71
- ```bash
72
- npm pack
73
- ```
74
- 1. Upload the resulting file to your ioBroker host
75
- 1. Install it locally (The paths are different on Windows):
76
- ```bash
77
- cd /opt/iobroker
78
- npm i /path/to/tarball.tgz
79
- ```
80
-
81
- For later updates, the above procedure is not necessary. Just do the following:
82
- 1. Overwrite the changed files in the adapter directory (`/opt/iobroker/node_modules/iobroker.panasonic-comfort-cloud`)
83
- 1. Execute `iobroker upload panasonic-comfort-cloud` on the ioBroker host
15
+ Adapter to control devices in the Panasonic Comfort Cloud. It uses REST calls which are extracetd from the official Comfort Cloud app.
16
+ To use the a adpter you need to enter your username and password in the configuration. They are used to authenticate access to the Comfort Cloud. Information of all devices is automatically retrieved and inserted as an object. The adpter polls the device information cyclically (see interval in the settings) and sends commands directly to the cloud.
17
+
18
+ With the method used, only one client can be logged on with the account at a time.
19
+ It is recommended that a second account, for which the devices have been shared, is used.
20
+
84
21
 
85
22
  ## Changelog
86
23
 
87
- ### 0.0.1
88
- * (marc) initial release
24
+ ### 1.2.8
25
+ * Fixed bug in Comfort Cloud client.
26
+
27
+ ### 1.2.7
28
+ * Comfort Cloud client updated.
29
+
30
+ ### 1.2.6
31
+ * Fixed bug that guid is null in device creation.
32
+
33
+ ### 1.2.5
34
+ * *Comfort Cloud client updated.
35
+
36
+ ### 1.2.4
37
+ * Fixed bug with undefined guid. Log messages added.
38
+
39
+ ### 1.2.3
40
+ * Set parameters only for writable states.
41
+
42
+ ### 1.2.2
43
+ * *Fixed error handling and added stack info.
44
+
45
+ ### 1.2.1
46
+ * Fixed bug in refesh device method.
47
+
48
+ ### 1.2.0
49
+ * States insideTemperature, outTemperature and Nanoe added.
89
50
 
90
51
  ## License
91
52
  MIT License
@@ -19,7 +19,7 @@ function isObject(it) {
19
19
  // typeof null === 'object'
20
20
  // typeof [] === 'object'
21
21
  // [] instanceof Object === true
22
- return Object.prototype.toString.call(it) === "[object Object]";
22
+ return Object.prototype.toString.call(it) === '[object Object]';
23
23
  }
24
24
  exports.isObject = isObject;
25
25
  /**
@@ -29,7 +29,7 @@ exports.isObject = isObject;
29
29
  function isArray(it) {
30
30
  if (Array.isArray != null)
31
31
  return Array.isArray(it);
32
- return Object.prototype.toString.call(it) === "[object Array]";
32
+ return Object.prototype.toString.call(it) === '[object Array]';
33
33
  }
34
34
  exports.isArray = isArray;
35
35
  /**
@@ -39,7 +39,7 @@ exports.isArray = isArray;
39
39
  */
40
40
  function translateText(text, targetLang) {
41
41
  return __awaiter(this, void 0, void 0, function* () {
42
- if (targetLang === "en")
42
+ if (targetLang === 'en')
43
43
  return text;
44
44
  try {
45
45
  const url = `http://translate.googleapis.com/translate_a/single?client=gtx&sl=en&tl=${targetLang}&dt=t&q=${encodeURIComponent(text)}&ie=UTF-8&oe=UTF-8`;
@@ -48,7 +48,7 @@ function translateText(text, targetLang) {
48
48
  // we got a valid response
49
49
  return response.data[0][0][0];
50
50
  }
51
- throw new Error("Invalid response for translate request");
51
+ throw new Error('Invalid response for translate request');
52
52
  }
53
53
  catch (e) {
54
54
  throw new Error(`Could not translate to "${targetLang}": ${e}`);
package/build/main.js CHANGED
@@ -21,12 +21,12 @@ const _ = require("lodash");
21
21
  const comfortCloudClient = new panasonic_comfort_cloud_client_1.ComfortCloudClient();
22
22
  class PanasonicComfortCloud extends utils.Adapter {
23
23
  constructor(options = {}) {
24
- super(Object.assign(Object.assign({}, options), { name: "panasonic-comfort-cloud" }));
25
- this.on("ready", this.onReady.bind(this));
26
- this.on("objectChange", this.onObjectChange.bind(this));
27
- this.on("stateChange", this.onStateChange.bind(this));
24
+ super(Object.assign(Object.assign({}, options), { name: 'panasonic-comfort-cloud' }));
25
+ this.on('ready', this.onReady.bind(this));
26
+ this.on('objectChange', this.onObjectChange.bind(this));
27
+ this.on('stateChange', this.onStateChange.bind(this));
28
28
  // this.on('message', this.onMessage.bind(this));
29
- this.on("unload", this.onUnload.bind(this));
29
+ this.on('unload', this.onUnload.bind(this));
30
30
  }
31
31
  /**
32
32
  * Is called when databases are connected and adapter received configuration.
@@ -36,12 +36,12 @@ class PanasonicComfortCloud extends utils.Adapter {
36
36
  return __awaiter(this, void 0, void 0, function* () {
37
37
  const refreshInterval = (_a = this.config.refreshInterval) !== null && _a !== void 0 ? _a : 5;
38
38
  this.refreshJob = node_schedule_1.scheduleJob(`*/${refreshInterval} * * * *`, this.refreshDevices.bind(this));
39
- this.subscribeStates("*");
39
+ this.subscribeStates('*');
40
40
  try {
41
41
  this.log.debug(`Try to login with username ${this.config.username}.`);
42
42
  yield comfortCloudClient.login(this.config.username, this.config.password);
43
- this.log.info("Login successful.");
44
- this.log.debug("Create devices.");
43
+ this.log.info('Login successful.');
44
+ this.log.debug('Create devices.');
45
45
  const groups = yield comfortCloudClient.getGroups();
46
46
  this.createDevices(groups);
47
47
  }
@@ -98,7 +98,7 @@ class PanasonicComfortCloud extends utils.Adapter {
98
98
  refreshDevices() {
99
99
  return __awaiter(this, void 0, void 0, function* () {
100
100
  try {
101
- this.log.debug("Refresh all devices.");
101
+ this.log.debug('Refresh all devices.');
102
102
  const groups = yield comfortCloudClient.getGroups();
103
103
  const devices = _.flatMap(groups, g => g.devices);
104
104
  const deviceInfos = _.map(devices, d => { return { guid: d.guid, name: d.name }; });
@@ -126,40 +126,46 @@ class PanasonicComfortCloud extends utils.Adapter {
126
126
  const deviceInfos = _.map(devicesFromService, d => { return { guid: d.guid, name: d.name }; });
127
127
  yield Promise.all(deviceInfos.map((deviceInfo) => __awaiter(this, void 0, void 0, function* () {
128
128
  this.log.debug(`Device info from group ${deviceInfo.guid}, ${deviceInfo.name}.`);
129
- const device = yield comfortCloudClient.getDevice(deviceInfo.guid);
129
+ let device = null;
130
+ try {
131
+ device = yield comfortCloudClient.getDevice(deviceInfo.guid);
132
+ }
133
+ catch (error) {
134
+ this.handleClientError(error);
135
+ }
130
136
  if (device != null) {
131
137
  if (_.includes(names, deviceInfo.name)) {
132
138
  return;
133
139
  }
134
140
  this.createDevice(deviceInfo.name);
135
- this.createState(deviceInfo.name, "", "guid", { role: "text", write: false, def: deviceInfo.guid, type: "string" }, undefined);
136
- this.createState(deviceInfo.name, "", "operate", {
137
- role: "state",
141
+ this.createState(deviceInfo.name, '', 'guid', { role: 'text', write: false, def: deviceInfo.guid, type: 'string' }, undefined);
142
+ this.createState(deviceInfo.name, '', 'operate', {
143
+ role: 'state',
138
144
  states: { 0: panasonic_comfort_cloud_client_1.Power[0], 1: panasonic_comfort_cloud_client_1.Power[1] },
139
145
  write: true,
140
146
  def: device.operate,
141
- type: "array",
147
+ type: 'array',
142
148
  }, undefined);
143
- this.createState(deviceInfo.name, "", "temperatureSet", {
144
- role: "level.temperature",
149
+ this.createState(deviceInfo.name, '', 'temperatureSet', {
150
+ role: 'level.temperature',
145
151
  write: true,
146
152
  def: device.temperatureSet,
147
- type: "number",
153
+ type: 'number',
148
154
  }, undefined);
149
- this.createState(deviceInfo.name, "", "insideTemperature", {
150
- role: "state",
155
+ this.createState(deviceInfo.name, '', 'insideTemperature', {
156
+ role: 'state',
151
157
  write: false,
152
158
  def: device.insideTemperature,
153
- type: "number",
159
+ type: 'number',
154
160
  }, undefined);
155
- this.createState(deviceInfo.name, "", "outTemperature", {
156
- role: "state",
161
+ this.createState(deviceInfo.name, '', 'outTemperature', {
162
+ role: 'state',
157
163
  write: false,
158
164
  def: device.outTemperature,
159
- type: "number",
165
+ type: 'number',
160
166
  }, undefined);
161
- this.createState(deviceInfo.name, "", "airSwingLR", {
162
- role: "state",
167
+ this.createState(deviceInfo.name, '', 'airSwingLR', {
168
+ role: 'state',
163
169
  states: {
164
170
  0: panasonic_comfort_cloud_client_1.AirSwingLR[0],
165
171
  1: panasonic_comfort_cloud_client_1.AirSwingLR[1],
@@ -169,10 +175,10 @@ class PanasonicComfortCloud extends utils.Adapter {
169
175
  },
170
176
  write: true,
171
177
  def: device.airSwingLR,
172
- type: "array",
178
+ type: 'array',
173
179
  }, undefined);
174
- this.createState(deviceInfo.name, "", "airSwingUD", {
175
- role: "state",
180
+ this.createState(deviceInfo.name, '', 'airSwingUD', {
181
+ role: 'state',
176
182
  states: {
177
183
  0: panasonic_comfort_cloud_client_1.AirSwingUD[0],
178
184
  1: panasonic_comfort_cloud_client_1.AirSwingUD[1],
@@ -182,10 +188,10 @@ class PanasonicComfortCloud extends utils.Adapter {
182
188
  },
183
189
  write: true,
184
190
  def: device.airSwingUD,
185
- type: "array",
191
+ type: 'array',
186
192
  }, undefined);
187
- this.createState(deviceInfo.name, "", "fanAutoMode", {
188
- role: "state",
193
+ this.createState(deviceInfo.name, '', 'fanAutoMode', {
194
+ role: 'state',
189
195
  states: {
190
196
  0: panasonic_comfort_cloud_client_1.FanAutoMode[0],
191
197
  1: panasonic_comfort_cloud_client_1.FanAutoMode[1],
@@ -194,17 +200,17 @@ class PanasonicComfortCloud extends utils.Adapter {
194
200
  },
195
201
  write: true,
196
202
  def: device.fanAutoMode,
197
- type: "array",
203
+ type: 'array',
198
204
  }, undefined);
199
- this.createState(deviceInfo.name, "", "ecoMode", {
200
- role: "state",
205
+ this.createState(deviceInfo.name, '', 'ecoMode', {
206
+ role: 'state',
201
207
  states: { 0: panasonic_comfort_cloud_client_1.EcoMode[0], 1: panasonic_comfort_cloud_client_1.EcoMode[1], 2: panasonic_comfort_cloud_client_1.EcoMode[2] },
202
208
  write: true,
203
209
  def: device.ecoMode,
204
- type: "array",
210
+ type: 'array',
205
211
  }, undefined);
206
- this.createState(deviceInfo.name, "", "operationMode", {
207
- role: "state",
212
+ this.createState(deviceInfo.name, '', 'operationMode', {
213
+ role: 'state',
208
214
  states: {
209
215
  0: panasonic_comfort_cloud_client_1.OperationMode[0],
210
216
  1: panasonic_comfort_cloud_client_1.OperationMode[1],
@@ -214,10 +220,10 @@ class PanasonicComfortCloud extends utils.Adapter {
214
220
  },
215
221
  write: true,
216
222
  def: device.operationMode,
217
- type: "array",
223
+ type: 'array',
218
224
  }, undefined);
219
- this.createState(deviceInfo.name, "", "fanSpeed", {
220
- role: "state",
225
+ this.createState(deviceInfo.name, '', 'fanSpeed', {
226
+ role: 'state',
221
227
  states: {
222
228
  0: panasonic_comfort_cloud_client_1.FanSpeed[0],
223
229
  1: panasonic_comfort_cloud_client_1.FanSpeed[1],
@@ -228,10 +234,10 @@ class PanasonicComfortCloud extends utils.Adapter {
228
234
  },
229
235
  write: true,
230
236
  def: device.fanSpeed,
231
- type: "array",
237
+ type: 'array',
232
238
  }, undefined);
233
- this.createState(deviceInfo.name, "", "actualNanoe", {
234
- role: "state",
239
+ this.createState(deviceInfo.name, '', 'actualNanoe', {
240
+ role: 'state',
235
241
  states: {
236
242
  0: panasonic_comfort_cloud_client_1.NanoeMode[0],
237
243
  1: panasonic_comfort_cloud_client_1.NanoeMode[1],
@@ -241,12 +247,12 @@ class PanasonicComfortCloud extends utils.Adapter {
241
247
  },
242
248
  write: true,
243
249
  def: device.actualNanoe,
244
- type: "array",
250
+ type: 'array',
245
251
  }, undefined);
246
252
  this.log.info(`Device ${deviceInfo.name} created.`);
247
253
  }
248
254
  })));
249
- this.log.debug("Device creation completed.");
255
+ this.log.debug('Device creation completed.');
250
256
  });
251
257
  }
252
258
  updateDevice(deviceName, stateName, state) {
@@ -285,7 +291,7 @@ class PanasonicComfortCloud extends utils.Adapter {
285
291
  onUnload(callback) {
286
292
  var _a;
287
293
  try {
288
- this.log.info("cleaned everything up...");
294
+ this.log.info('cleaned everything up...');
289
295
  (_a = this.refreshJob) === null || _a === void 0 ? void 0 : _a.cancel();
290
296
  callback();
291
297
  }
@@ -311,7 +317,7 @@ class PanasonicComfortCloud extends utils.Adapter {
311
317
  */
312
318
  onStateChange(id, state) {
313
319
  if (state) {
314
- const elements = id.split(".");
320
+ const elements = id.split('.');
315
321
  const deviceName = elements[elements.length - 2];
316
322
  const stateName = elements[elements.length - 1];
317
323
  this.updateDevice(deviceName, stateName, state);
@@ -325,16 +331,16 @@ class PanasonicComfortCloud extends utils.Adapter {
325
331
  }
326
332
  handleClientError(error) {
327
333
  return __awaiter(this, void 0, void 0, function* () {
328
- this.log.debug("Try to handle error.");
334
+ this.log.debug('Try to handle error.');
329
335
  if (error instanceof panasonic_comfort_cloud_client_1.TokenExpiredError) {
330
336
  this.log.info(`Token of comfort cloud client expired. Trying to login again. Code=${error.code}. Stack: ${error.stack}`);
331
337
  yield comfortCloudClient.login(this.config.username, this.config.password);
332
- this.log.info("Login successful.");
338
+ this.log.info('Login successful.');
333
339
  }
334
340
  else if (error instanceof panasonic_comfort_cloud_client_1.ServiceError) {
335
341
  this.log.error(`Service error: ${error.message}. Code=${error.code}. Stack: ${error.stack}`);
336
342
  }
337
- else {
343
+ else if (error instanceof Error) {
338
344
  this.log.error(`Unknown error: ${error}. Stack: ${error.stack}`);
339
345
  }
340
346
  });
package/io-package.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "panasonic-comfort-cloud",
4
- "version": "1.2.8",
4
+ "version": "1.2.9",
5
5
  "news": {
6
+ "1.2.9": {
7
+ "en": "Error handling for get device added.",
8
+ "de": "Fehlerbehandlung beim Abrufen des Geräts hinzugefügt."
9
+ },
6
10
  "1.2.8": {
7
11
  "en": "Fixed bug in Comfort Cloud client.",
8
12
  "de": "Fehler in Comfort Cloud client behoben."
@@ -111,7 +115,7 @@
111
115
  "materialize": true,
112
116
  "dependencies": [
113
117
  {
114
- "js-controller": ">=1.4.2"
118
+ "js-controller": ">=1.5.8"
115
119
  }
116
120
  ]
117
121
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.panasonic-comfort-cloud",
3
- "version": "1.2.8",
3
+ "version": "1.2.9",
4
4
  "description": "Adapter for Panasonic Comfort Cloud",
5
5
  "author": {
6
6
  "name": "marc",