diff --git a/CHANGELOG.md b/CHANGELOG.md index df89777..4a05e1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - v3 After update to v3 from previous versions the plugin need to be configured using Config UI X. - do not configure it manually, always using Config UI X +## [3.0.7] - (30.08.2024) + +## Changes + +- improvements in plugin config UI +- config schema update +- cleanup + ## [3.0.0] - (29.08.2024) ## Changes diff --git a/README.md b/README.md index c58d702..19e64a3 100644 --- a/README.md +++ b/README.md @@ -177,6 +177,7 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation | `ataDevices` | Array of ATA devices created automatically after login to MELCloud from plugin config UI. | | `ataDevices.id` | Read only data, do not change it. | | `ataDevices.type` | Read only data, do not change it. | +| `ataDevices.typeString` | Read only data, do not change it. | | `ataDevices.name` | Here You can schange the `Accessory Name` which is exposed to the `Homebridge/HomeKit`. | | `ataDevices.displayMode` | Here select device control mode `None/Disabled`, `Heater/Cooler`, `Thermostat`. | | `ataDevices.heatDryFanMode` | Here select the operatiing mode for `Heat`, if this mode is not supported, it will be disabled. | @@ -193,6 +194,7 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation | `atwDevices` | Array of ATA devices created automatically after login to MELCloud from plugin config UI. | | `atwDevices.id` | Read only data, do not change it. | | `atwDevices.type` | Read only data, do not change it. | +| `atwDevices.typeString` | Read only data, do not change it. | | `atwDevices.name` | Here You can schange the `Accessory Name` which is exposed to the `Homebridge/HomeKit`. | | `atwDevices.displayMode` | Here select main control mode `None/Disabled`, `Heater/Cooler`, `Thermostat`. | | `atwDevices.temperatureSensor` | This enable extra `Room` temperature sensors to use with automations in HomeKit app. | @@ -213,6 +215,7 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation | `ervDevices` | Array of ATA devices created automatically after login to MELCloud from plugin config UI. | | `ervDevices.id` | Read only data, do not change it. | | `ervDevices.type` | Read only data, do not change it. | +| `ervDevices.typeString` | Read only data, do not change it. | | `ervDevices.name` | Here You can schange the `Accessory Name` which is exposed to the `Homebridge/HomeKit`. | | `ervDevices.displayMode` | Here select main control mode `None/Disabled`, `Heater/Cooler`, `Thermostat`. | | `ervDevices.temperatureSensor` | This enable extra `Room` temperature sensors to use with automations in HomeKit app. | diff --git a/config.schema.json b/config.schema.json index 5705c8e..aa53aa8 100644 --- a/config.schema.json +++ b/config.schema.json @@ -15,7 +15,7 @@ "type": "object", "properties": { "name": { - "title": "Account", + "title": "Name", "type": "string", "placeholder": "Account name", "description": "Your own account name.", @@ -220,6 +220,11 @@ "type": "integer", "required": false }, + "typeString": { + "title": "Type", + "type": "string", + "required": false + }, "name": { "title": "Name", "type": "string", @@ -691,6 +696,11 @@ "type": "integer", "required": false }, + "typeString": { + "title": "Type", + "type": "string", + "required": false + }, "name": { "title": "Name", "type": "string", @@ -1029,6 +1039,11 @@ "type": "integer", "required": false }, + "typeString": { + "title": "Type", + "type": "string", + "required": false + }, "name": { "title": "Name", "type": "string", @@ -1463,15 +1478,24 @@ "readonly": true }, { - "key": "accounts[].ataDevices[].type", + "key": "accounts[].ataDevices[].typeString", "readonly": true }, - "accounts[].ataDevices[].name", - "accounts[].ataDevices[].displayMode", - "accounts[].ataDevices[].heatDryFanMode", - "accounts[].ataDevices[].coolDryFanMode", - "accounts[].ataDevices[].autoDryFanMode", - "accounts[].ataDevices[].presets", + { + "key": "accounts[].ataDevices[]", + "type": "section", + "title": "Configuration", + "expandable": true, + "expanded": false, + "items": [ + "accounts[].ataDevices[].name", + "accounts[].ataDevices[].displayMode", + "accounts[].ataDevices[].heatDryFanMode", + "accounts[].ataDevices[].coolDryFanMode", + "accounts[].ataDevices[].autoDryFanMode", + "accounts[].ataDevices[].presets" + ] + }, { "key": "accounts[].ataDevices[]", "type": "section", @@ -1521,12 +1545,21 @@ "readonly": true }, { - "key": "accounts[].atwDevices[].type", + "key": "accounts[].atwDevices[].typeString", "readonly": true }, - "accounts[].atwDevices[].name", - "accounts[].atwDevices[].displayMode", - "accounts[].atwDevices[].presets", + { + "key": "accounts[].atwDevices[]", + "type": "section", + "title": "Configuration", + "expandable": true, + "expanded": false, + "items": [ + "accounts[].atwDevices[].name", + "accounts[].atwDevices[].displayMode", + "accounts[].atwDevices[].presets" + ] + }, { "key": "accounts[].atwDevices[]", "type": "section", @@ -1583,12 +1616,21 @@ "readonly": true }, { - "key": "accounts[].ervDevices[].type", + "key": "accounts[].ervDevices[].typeString", "readonly": true }, - "accounts[].ervDevices[].name", - "accounts[].ervDevices[].displayMode", - "accounts[].ervDevices[].presets", + { + "key": "accounts[].ervDevices[]", + "type": "section", + "title": "Configuration", + "expandable": true, + "expanded": false, + "items": [ + "accounts[].ervDevices[].name", + "accounts[].ervDevices[].displayMode", + "accounts[].ervDevices[].presets" + ] + }, { "key": "accounts[].ervDevices[]", "type": "section", @@ -1624,50 +1666,72 @@ ] } ] - }, - { - "key": "accounts[]", - "title": "System", - "items": [ - "accounts[].enableDebugMode", - "accounts[].disableLogInfo", - "accounts[].disableLogDeviceInfo", - "accounts[].refreshInterval", - "accounts[].deviceRefreshInterval" - ] - }, + } + ] + }, + { + "key": "accounts[]", + "type": "section", + "title": "Advanced Settings", + "expandable": true, + "expanded": false, + "items": [ { "key": "accounts[]", - "title": "External Integrations", + "type": "tabarray", + "title": "{{ value.name }}", "items": [ { "key": "accounts[]", - "type": "tabarray", - "title": "{{ value.title }}", + "title": "Data Refresh", + "items": [ + "accounts[].refreshInterval", + "accounts[].deviceRefreshInterval" + ] + }, + { + "key": "accounts[]", + "title": "Log", + "items": [ + "accounts[].enableDebugMode", + "accounts[].disableLogInfo", + "accounts[].disableLogDeviceInfo" + ] + }, + { + "key": "accounts[]", + "title": "External Integrations", "items": [ { - "key": "accounts[].restFul", - "title": "RESTFul", - "items": [ - "accounts[].restFul.enable", - "accounts[].restFul.debug" - ] - }, - { - "key": "accounts[].mqtt", - "title": "MQTT", + "key": "accounts[]", + "type": "tabarray", + "title": "{{ value.title }}", "items": [ - "accounts[].mqtt.enable", - "accounts[].mqtt.debug", - "accounts[].mqtt.host", - "accounts[].mqtt.port", - "accounts[].mqtt.clientId", - "accounts[].mqtt.prefix", - "accounts[].mqtt.auth", - "accounts[].mqtt.user", { - "key": "accounts[].mqtt.passwd", - "type": "password" + "key": "accounts[].restFul", + "title": "RESTFul", + "items": [ + "accounts[].restFul.enable", + "accounts[].restFul.debug" + ] + }, + { + "key": "accounts[].mqtt", + "title": "MQTT", + "items": [ + "accounts[].mqtt.enable", + "accounts[].mqtt.debug", + "accounts[].mqtt.host", + "accounts[].mqtt.port", + "accounts[].mqtt.clientId", + "accounts[].mqtt.prefix", + "accounts[].mqtt.auth", + "accounts[].mqtt.user", + { + "key": "accounts[].mqtt.passwd", + "type": "password" + } + ] } ] } diff --git a/homebridge-ui/public/index.html b/homebridge-ui/public/index.html index f810f17..1bf81b4 100644 --- a/homebridge-ui/public/index.html +++ b/homebridge-ui/public/index.html @@ -1,13 +1,13 @@ -
- -
-
-
+
+ + Image +

+ @@ -74,8 +76,9 @@ button.setAttribute("type", "button"); button.setAttribute("id", `button${i}`); button.setAttribute("class", "btn btn-primary"); + button.style.textTransform = 'none'; button.innerText = pluginConfig[0].accounts[i].name; - document.getElementById("accounts").appendChild(button); + document.getElementById("accountButton").appendChild(button); //get actuall value on account select document.getElementById(`button${i}`).addEventListener('click', async () => { @@ -147,15 +150,23 @@ const info = response.info ?? ''; const status = response.status; const devices = response.data ?? []; - const newDevices = []; + const newDevices = { + ata: [], + atw: [], + erv: [] + }; + let textAta = 'ATA: 0'; + let textAtw = 'ATW: 0'; + let textErv = 'ERV: 0'; switch (status) { case 0: //get device info fom devices - devices.forEach((deviceInfo, index) => { - const deviceType = deviceInfo.Type; - const deviceId = deviceInfo.DeviceID; - const deviceName = deviceInfo.DeviceName; + devices.forEach((device, index) => { + const deviceId = device.DeviceID; + const deviceType = device.Type; + const deviceTypeText = ["Air Conditioner", "Heat Pump", "Unknown", "Energy Recovery Ventilation"][deviceType]; + const deviceName = device.DeviceName; //config account keys const accountKeys = Object.keys(pluginConfig[0].accounts[this.deviceIndex]); @@ -163,9 +174,10 @@ //devices ata if (deviceType === 0) { const deviceAta = { - name: deviceName, id: deviceId, type: deviceType, + typeString: deviceTypeText, + name: deviceName, displayMode: 0, heatDryFanMode: 0, coolDryFanMode: 0, @@ -180,15 +192,18 @@ const ataDevices = ataDevicesExist ? pluginConfig[0].accounts[this.deviceIndex].ataDevices : pluginConfig[0].accounts[this.deviceIndex].ataDevices = []; const ataDeviceIdExist = ataDevices.some(device => device.id === deviceId); const pushTypeAta = ataDeviceIdExist ? false : ataDevices.push(deviceAta); - const pushNewDevice = ataDeviceIdExist ? false : newDevices.push(deviceId); + const pushNewDevice = ataDeviceIdExist ? false : newDevices.ata.push(device); + const devicesCount = newDevices.ata.length; + textAta = `ATA: ${devicesCount}` }; //devices atw if (deviceType === 1) { const deviceAtw = { - name: deviceName, id: deviceId, type: deviceType, + typeString: deviceTypeText, + name: deviceName, displayMode: 0, temperatureSensor: false, temperatureSensorFlow: false, @@ -208,15 +223,18 @@ const atwDevices = atwDevicesExist ? pluginConfig[0].accounts[this.deviceIndex].atwDevices : pluginConfig[0].accounts[this.deviceIndex].atwDevices = []; const atwDeviceIdExist = atwDevices.some(device => device.id === deviceId); const pushTypeatw = atwDeviceIdExist ? false : atwDevices.push(deviceAtw); - const pushNewDevice = atwDeviceIdExist ? false : newDevices.push(deviceId); + const pushNewDevice = atwDeviceIdExist ? false : newDevices.atw.push(device); + const devicesCount = newDevices.ata.length; + textAtw = `ATW: ${devicesCount}` }; //devices erv if (deviceType === 3) { const deviceErv = { - name: deviceName, id: deviceId, type: deviceType, + typeString: deviceTypeText, + name: deviceName, displayMode: 0, temperatureSensor: false, temperatureSensorOutdoor: false, @@ -230,12 +248,14 @@ const ervDevices = ervDevicesExist ? pluginConfig[0].accounts[this.deviceIndex].ervDevices : pluginConfig[0].accounts[this.deviceIndex].ervDevices = []; const ervDeviceIdExist = ervDevices.some(device => device.id === deviceId); const pushTypeerv = ervDeviceIdExist ? false : ervDevices.push(deviceErv); - const pushNewDevice = ervDeviceIdExist ? false : newDevices.push(deviceId); + const pushNewDevice = ervDeviceIdExist ? false : newDevices.erv.push(device); + const devicesCount = newDevices.ata.length; + textErv = `ERV: ${devicesCount}` }; }); - const devicesCount = newDevices.length; - document.getElementById('info').innerHTML = `Check devices complete, found ${devicesCount} ${devicesCount !== 1 ? 'new devices' : 'new device'}. ${devicesCount === 0 ? '' : 'Now You can start to configure it.'}`; + const newDevicesCount = newDevices.ata.length + newDevices.atw.length + newDevices.erv.length; + document.getElementById('info').innerHTML = `Found in MELCloud, ${textAta}, ${textAtw}, ${textErv}. ${newDevicesCount === 0 ? '' : 'Now You can start to configure it.'}`; document.getElementById('info').style.color = 'green'; await homebridge.updatePluginConfig(pluginConfig); diff --git a/homebridge-ui/server.js b/homebridge-ui/server.js index f5fab5d..afe224f 100644 --- a/homebridge-ui/server.js +++ b/homebridge-ui/server.js @@ -38,7 +38,8 @@ class PluginUiServer extends HomebridgePluginUiServer { } catch (error) { return data = { info: error, - status: 1 + status: 1, + data: data }; }; }; diff --git a/index.js b/index.js index 086c945..8a6b46c 100644 --- a/index.js +++ b/index.js @@ -89,7 +89,7 @@ class MelCloudPlatform { const deviceId = device.id.toString(); const deviceType = device.type ?? 0; const deviceName = device.name; - const deviceTypeText = CONSTANTS.DeviceType[deviceType]; + const deviceTypeText = device.typeString; const deviceInfoFile = `${prefDir}/${accountName}_Device_${deviceId}`; const airConditioner = new DeviceAta(api, account, device, melCloud, accountInfo, contextKey, accountName, deviceId, deviceName, deviceTypeText, accountInfoFile, deviceInfoFile, deviceRefreshInterval) airConditioner.on('publishAccessory', (accessory) => { @@ -205,7 +205,7 @@ class MelCloudPlatform { .on('warn', (warn) => { log.warn(`Account ${accountName}, ${warn}`); }) - .on('error', async (error) => { + .on('error', (error) => { log.error(`Account ${accountName}, ${error}.`); }); } catch (error) { diff --git a/package.json b/package.json index 72ad66b..9ae2395 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "displayName": "MELCloud Control", "name": "homebridge-melcloud-control", - "version": "3.0.6", + "version": "3.0.7", "description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.", "license": "MIT", "author": "grzegorz914", diff --git a/src/deviceata.js b/src/deviceata.js index 4c89948..96449ea 100644 --- a/src/deviceata.js +++ b/src/deviceata.js @@ -17,7 +17,7 @@ class DeviceAta extends EventEmitter { AccessoryUUID = api.hap.uuid; //account config - this.displayMode = device.displayMode || 0; + this.displayMode = device.displayMode; this.temperatureSensor = device.temperatureSensor || false; this.temperatureSensorOutdoor = device.temperatureSensorOutdoor || false; this.presetsEnabled = device.presets || false; diff --git a/src/deviceatw.js b/src/deviceatw.js index dd1af42..5304de6 100644 --- a/src/deviceatw.js +++ b/src/deviceatw.js @@ -17,7 +17,7 @@ class DeviceAtw extends EventEmitter { AccessoryUUID = api.hap.uuid; //account config - this.displayMode = device.displayMode || 0; + this.displayMode = device.displayMode; this.temperatureSensor = device.temperatureSensor || false; this.temperatureSensorFlow = device.temperatureSensorFlow || false; this.temperatureSensorReturn = device.temperatureSensorReturn || false; diff --git a/src/deviceerv.js b/src/deviceerv.js index d94354b..8290773 100644 --- a/src/deviceerv.js +++ b/src/deviceerv.js @@ -17,7 +17,7 @@ class DeviceErv extends EventEmitter { AccessoryUUID = api.hap.uuid; //account config - this.displayMode = device.displayMode || 0; + this.displayMode = device.displayMode; this.temperatureSensor = device.temperatureSensor || false; this.temperatureSensorOutdoor = device.temperatureSensorOutdoor || false; this.temperatureSensorSupply = device.temperatureSensorSupply || false;