From c4172727bc71aa4127bc30ac248f06839081fec3 Mon Sep 17 00:00:00 2001 From: "Kramp, Maximilian" Date: Mon, 13 May 2024 14:33:05 +0200 Subject: [PATCH 1/2] Name to dyson code translation Grizzelbee/ioBroker.dysonairpurifier#273 --- .gitignore | 5 ++++- .npmignore | 3 +++ dysonConstants.js | 17 +++++++++++++++-- dysonConstants.test.js | 40 ++++++++++++++++++++++++++++++++++++++++ main.js | 24 +++++++++++++++--------- 5 files changed, 77 insertions(+), 12 deletions(-) create mode 100644 dysonConstants.test.js diff --git a/.gitignore b/.gitignore index f64df5b..57246f3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,7 @@ Thumbs.db # i18n intermediate files admin/i18n/flat.txt -admin/i18n/*/flat.txt \ No newline at end of file +admin/i18n/*/flat.txt + +# ioBroker dev-server +.dev-server/ diff --git a/.npmignore b/.npmignore index 610bc93..21d5f79 100644 --- a/.npmignore +++ b/.npmignore @@ -1,3 +1,6 @@ +# exclude all dot-files and directories +.* + .git .idea node_modules/ diff --git a/dysonConstants.js b/dysonConstants.js index 6e89132..4633440 100644 --- a/dysonConstants.js +++ b/dysonConstants.js @@ -772,7 +772,7 @@ const datapoints = new Map([ writeable: true, // TODO: Should this be writable? role: 'value', unit: '', - displayValues: { '0675': 'Hard', '1350': 'Medium', '2025': 'Soft' } + displayValues: { '0675': 'Hard', 1350: 'Medium', 2025: 'Soft' } } ], [ @@ -1413,11 +1413,24 @@ function getDatapoint(searchValue) { return datapoints.get(searchValue); } +const nameToDysoncodeTranslation = new Map( + Array.from(datapoints.entries()).map(([key, { name }]) => [name, key]) +); + +/** + * @param {string} name - name to search for. + * @returns {string | undefined} returns the dyson code + */ +function getNameToDysoncodeTranslation(name) { + return nameToDysoncodeTranslation.get(name); +} + module.exports = { API_BASE_URI, HTTP_HEADERS, PRODUCTS, FIELDSTODELETE, SPECIAL_PROPERTIES, - getDatapoint + getDatapoint, + getNameToDysoncodeTranslation }; diff --git a/dysonConstants.test.js b/dysonConstants.test.js new file mode 100644 index 0000000..3033122 --- /dev/null +++ b/dysonConstants.test.js @@ -0,0 +1,40 @@ +'use strict'; + +const { expect } = require('chai'); + +const { + getDatapoint, + getNameToDysoncodeTranslation +} = require('./dysonConstants'); + +describe('dysonConstants', () => { + describe('getDatapoint', () => { + context('given a dyson code', () => { + it('returns the corresponding datapoint', () => { + const datapoint = getDatapoint('fpwr'); + expect(datapoint).to.be.an('object'); + }); + }); + context('given a non dyson code', () => { + it('returns undefined', () => { + const datapoint = getDatapoint('MainPower'); + expect(datapoint).to.equal(undefined); + }); + }); + }); + + describe('getNameToDysoncodeTranslation', () => { + context('given a dyson code', () => { + it('returns undefined', () => { + const datapoint = getNameToDysoncodeTranslation('fpwr'); + expect(datapoint).to.equal(undefined); + }); + }); + context('given a non dyson code', () => { + it('returns the corresponding dyson code', () => { + const datapoint = getNameToDysoncodeTranslation('MainPower'); + expect(datapoint).to.be.a('string'); + }); + }); + }); +}); diff --git a/main.js b/main.js index 369e971..0ea6080 100644 --- a/main.js +++ b/main.js @@ -37,7 +37,8 @@ const dysonUtils = require('./dyson-utils.js'); const { getDatapoint, PRODUCTS, - SPECIAL_PROPERTIES + SPECIAL_PROPERTIES, + getNameToDysoncodeTranslation } = require('./dysonConstants.js'); // Variable definitions @@ -313,13 +314,16 @@ class dysonAirPurifier extends utils.Adapter { return; } - // you can use the ack flag to detect if it is status (true) or command (false) - // get the whole data field array - const ActionData = getDatapoint(action); // if dysonAction is undefined it's an adapter internal action and has to be handled with the given Name // pick the dyson internal Action from the result row - const dysonAction = ActionData?.[0] ?? action; - this.log.debug(`onStateChange: Using dysonAction: [${dysonAction}]`); + const dysonAction = getNameToDysoncodeTranslation(action); + if (!dysonAction) { + this.log.warn(`Unknown Dyson Action ${action}`); + return; + } + // you can use the ack flag to detect if it is status (true) or command (false) + // get the whole data field array + const ActionData = getDatapoint(dysonAction); const value = state.val; let messageData = await this.#getMessageData(dysonAction, value, id, state); @@ -328,7 +332,10 @@ class dysonAirPurifier extends utils.Adapter { // this is to translate between the needed states for ioBroker and the device // boolean switches are better for visualizations and other adapters like text2command if (typeof ActionData !== 'undefined') { - if (ActionData[3] === 'boolean' && ActionData[5].startsWith('switch')) { + if ( + ActionData.type === 'boolean' && + ActionData.role.startsWith('switch') + ) { // current state is TRUE! if (state.val) { // handle special action "humidification" where ON is not ON but HUME @@ -800,8 +807,7 @@ class dysonAirPurifier extends utils.Adapter { ? message[dysonCode][1] : message[dysonCode]; //this.log.debug(`${getDataPointName(deviceConfig)} is a bool switch. Current state: [${testValue}]`); - value = - ['ON', 'HUMD', 'HEAT'].includes(testValue); // testValue === 'ON' || testValue === 'HUMD' || testValue === 'HEAT'; + value = ['ON', 'HUMD', 'HEAT'].includes(testValue); // testValue === 'ON' || testValue === 'HUMD' || testValue === 'HEAT'; } else if ( deviceConfig.type === 'boolean' && deviceConfig.role.startsWith('indicator') From d876be8bb335e2525c47fec7d20a4b42191ad665 Mon Sep 17 00:00:00 2001 From: grizzelbee Date: Mon, 13 May 2024 15:58:49 +0200 Subject: [PATCH 2/2] v3.1.9 --- README.md | 8 ++++++-- dyson-utils.js | 2 ++ io-package.json | 15 ++++++++++++++- main.js | 3 ++- package.json | 2 +- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7bf9b83..8e8bc8c 100644 --- a/README.md +++ b/README.md @@ -185,13 +185,17 @@ All states report whether there is a failure or not. `True` means a failure, `fa ### **WORK IN PROGRESS** +### 3.1.9 (2024-05-13) (Marching on) + +- (arcticon) Fix: [#278](https://github.com/Grizzelbee/ioBroker.dysonairpurifier/issues/278) Changeable fields are working again. + ### 3.1.8 (2024-05-10) (Marching on) - (arcticon) Upd: Dependencies got updated - (grizzelbee) Chg: code refactoring - (arcticon) Chg: code refactoring -- (arcticon) Chg: [#273](https://github.com/Grizzelbee/ioBroker.dysonairpurifier/issues/273) Performance improvements -- (arcticon) Chg: [#274](https://github.com/Grizzelbee/ioBroker.dysonairpurifier/issues/274) Update of outdated certificate +- (arcticon) Chg: [#273](https://github.com/Grizzelbee/ioBroker.dysonairpurifier/issues/273) Performance improvements +- (arcticon) Chg: [#274](https://github.com/Grizzelbee/ioBroker.dysonairpurifier/issues/274) Update of outdated certificate ### 3.1.7 (2024-04-24) (Marching on) diff --git a/dyson-utils.js b/dyson-utils.js index e375138..bc07b3e 100644 --- a/dyson-utils.js +++ b/dyson-utils.js @@ -407,6 +407,8 @@ module.exports.deleteUnusedFields = async function (self, device) { if (!err && oldObj) { self.log.info(`Deleting deprecated field: ${id}`); self.delObject(id); + } else { + self.log.debug(`deprecated field: ${id} not found - nothing to do.`); } }); } diff --git a/io-package.json b/io-package.json index c6c7f77..caf1950 100644 --- a/io-package.json +++ b/io-package.json @@ -1,8 +1,21 @@ { "common": { "name": "dysonairpurifier", - "version": "3.1.8", + "version": "3.1.9", "news": { + "3.1.9": { + "en": "Changeable fields are working again.", + "de": "Änderbare Felder funktionieren wieder.", + "ru": "Изменяемые поля снова работают.", + "pt": "Os campos alteráveis ​​estão funcionando novamente.", + "nl": "Veranderlijke velden werken weer.", + "fr": "Les champs modifiables fonctionnent à nouveau.", + "it": "I campi modificabili funzionano di nuovo.", + "es": "Los campos modificables están funcionando nuevamente.", + "pl": "Zmienne pola znów działają.", + "uk": "Змінні поля знову працюють.", + "zh-cn": "可变字段再次发挥作用。" + }, "3.1.8": { "en": "Dependencies got updated\nCode refactoring\nPerformance improvements\nUpdate of outdated certificate", "de": "Abhängigkeiten wurden aktualisiert\nCode-Refactoring\nLeistungsverbesserungen\nAktualisierung des veralteten Zertifikats", diff --git a/main.js b/main.js index 0ea6080..189414e 100644 --- a/main.js +++ b/main.js @@ -1519,7 +1519,8 @@ class dysonAirPurifier extends utils.Adapter { */ onUnload(callback) { try { - for (const thisDevice of devices) { + for (const DEVICE in devices) { + const thisDevice = devices[DEVICE]; clearTimeout(thisDevice.updateIntervalHandle); this.log.info(`Cleaned up timeout for ${thisDevice.Serial}.`); // todo unsubscribe to any subscribes diff --git a/package.json b/package.json index df42648..a5cc117 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iobroker.dysonairpurifier", - "version": "3.1.8", + "version": "3.1.9", "description": "dyson air purifiers and fans", "author": { "name": "grizzelbee",