Skip to content

Commit

Permalink
release 0.13.0
Browse files Browse the repository at this point in the history
  • Loading branch information
grzegorz914 committed Jul 30, 2023
1 parent e3b3a54 commit bcc8d9e
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 13 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Important changes v0.4.0 and above!!!
* Main control mode, buttons and presets need to be configured again!!!

## [0.12.0] - (21.07.2023)
## [0.13.0] - (30.07.2023)
## Changes
- added RESTFul server
- code refactor and cleanup
- config.schema updated

## [0.12.0] - (21.07.2023)
## Changes
- added extra temperature sensor for Heater/Cooler control mode to use with automations
- config.schema updeted
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
* Support direct device controll creating extra `Buttons`, appiled for all devices of same type in account.
* Support identify all states of device creating `Sensors`, appiled for all devices of same type in account.
* Support automations, shortcuts and siri.
* RESTful server:
* Request: `http//homebridge_ip_address:port/path`.
* Port is based on last 4 numbers of `device Id`, displayed in HB log during start.
* Path: `info`, `state`.
* Respone as JSON data.
* MQTT client:
* Topic: `Info`, `State`.
* Publish as JSON data.
Expand Down Expand Up @@ -191,6 +196,8 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
| `enableDebugMode` | This enable deep log in homebridge console. |
| `disableLogInfo` | This disable display log values and states on every it change. |
| `disableLogDeviceInfo` | This disable display log device info on plugin start. |
| `enableRestFul` | If enabled, RESTful server will start automatically and respond to any path request. |
| `restFulDebug` | If enabled, deep log will be present in homebridge console for RESTFul server. |
| `enableMqtt` | This enabled MQTT Broker and publish to it all awailable data. |
| `mqttDebug` | This enabled deep log in homebridge console for MQTT. |
| `mqttHost` | Here set the `IP Address` or `Hostname` for MQTT Broker. |
Expand Down
28 changes: 28 additions & 0 deletions config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1006,6 +1006,23 @@
"description": "This enable debug mode.",
"required": false
},
"enableRestFul": {
"title": "Enable",
"type": "boolean",
"default": false,
"required": false,
"description": "This enable RESTful server."
},
"restFulDebug": {
"title": "Debug",
"type": "boolean",
"default": false,
"required": false,
"description": "This enable debug mode for RESTFul.",
"condition": {
"functionBody": "return model.accounts[arrayIndices].enableRestFul === true;"
}
},
"enableMqtt": {
"title": "Enable",
"type": "boolean",
Expand Down Expand Up @@ -1190,6 +1207,17 @@
"accounts[].disableLogDeviceInfo"
]
},
{
"key": "accounts[]",
"type": "section",
"title": "RESTful",
"expandable": true,
"expanded": false,
"items": [
"accounts[].enableRestFul",
"accounts[].restFulDebug"
]
},
{
"key": "accounts[]",
"type": "section",
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"displayName": "MELCloud Control",
"name": "homebridge-melcloud-control",
"version": "0.12.6",
"version": "0.13.0",
"description": "Homebridge plugin (https://github.com/homebridge/homebridge) - control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
"license": "MIT",
"author": "grzegorz914",
Expand Down Expand Up @@ -29,7 +29,8 @@
},
"dependencies": {
"async-mqtt": "^2.6.3",
"axios": "^1.4.0"
"axios": "^1.4.0",
"express": "^4.18.2"
},
"keywords": [
"homebridge",
Expand Down
2 changes: 2 additions & 0 deletions sample-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
"disableLogDeviceInfo": false,
"enableDebugMode": false,
"mqttDebug": false,
"enableRestFul": false,
"restFulDebug": false,
"enableMqtt": false,
"mqttHost": "192.168.1.33",
"mqttPort": 1883,
Expand Down
17 changes: 15 additions & 2 deletions src/melcloudata.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class MelCloudAta extends EventEmitter {
const buildingId = config.buildingId;
const deviceId = config.deviceId;
const debugLog = config.debugLog;
const restFulEnabled = config.restFulEnabled;
const mqttEnabled = config.mqttEnabled;
const deviceInfoFile = `${prefDir}/${accountName}_Device_${deviceId}`;

//set default values
Expand Down Expand Up @@ -315,7 +317,12 @@ class MelCloudAta extends EventEmitter {
const permissionCanDisableLocalController = deviceInfo.Permissions.CanDisableLocalController;

this.emit('deviceInfo', manufacturer, modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion, presets, presetsCount, hasAutomaticFanSpeed, airDirectionFunction, swingFunction, numberOfFanSpeeds, temperatureIncrement, minTempCoolDry, maxTempCoolDry, minTempHeat, maxTempHeat, minTempAutomatic, maxTempAutomatic, modelSupportsFanSpeed, modelSupportsAuto, modelSupportsHeat, modelSupportsDry);
this.emit('mqtt', `Info`, deviceInfo);

//restFul
const restFul = restFulEnabled ? this.emit('restFul', 'info', deviceInfo) : false;

//mqtt
const mqtt = mqttEnabled ? this.emit('mqtt', `Info`, deviceInfo) : false;

//check device state
await new Promise(resolve => setTimeout(resolve, 1000));
Expand Down Expand Up @@ -407,7 +414,13 @@ class MelCloudAta extends EventEmitter {
this.offline = offline;

this.emit('deviceState', deviceState, roomTemperature, setTemperature, setFanSpeed, operationMode, vaneHorizontal, vaneVertical, defaultHeatingSetTemperature, defaultCoolingSetTemperature, hideVaneControls, hideDryModeControl, inStandbyMode, prohibitSetTemperature, prohibitOperationMode, prohibitPower, power, offline);
this.emit('mqtt', `State`, deviceState);

//restFul
const restFul = restFulEnabled ? this.emit('restFul', 'state', deviceState) : false;

//mqtt
const mqtt = mqttEnabled ? this.emit('mqtt', `State`, deviceState) : false;

this.checkDeviceInfo();
} catch (error) {
this.emit('error', `check device state error, ${error}, check again in 60s.`);
Expand Down
17 changes: 15 additions & 2 deletions src/melcloudatw.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class MelCloudAtw extends EventEmitter {
const buildingId = config.buildingId;
const deviceId = config.deviceId;
const debugLog = config.debugLog;
const restFulEnabled = config.restFulEnabled;
const mqttEnabled = config.mqttEnabled;
const deviceInfoFile = `${prefDir}/${accountName}_Device_${deviceId}`;

this.axiosInstanceGet = axios.create({
Expand Down Expand Up @@ -405,7 +407,12 @@ class MelCloudAtw extends EventEmitter {
};

this.emit('deviceInfo', manufacturer, modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion, presets, presetsCount, zonesCount, heatPumpZoneName, hotWaterZoneName, hasHotWaterTank, temperatureIncrement, maxTankTemperature, hasZone2, zone1Name, zone2Name, heatCoolModes, caseHotWater, caseZone2);
this.emit('mqtt', `Info`, deviceInfo);

//restFul
const restFul = restFulEnabled ? this.emit('restFul', 'info', deviceInfo) : false;

//mqtt
const mqtt = mqttEnabled ? this.emit('mqtt', `Info`, deviceInfo) : false;

//check device state
await new Promise(resolve => setTimeout(resolve, 1000));
Expand Down Expand Up @@ -525,7 +532,13 @@ class MelCloudAtw extends EventEmitter {
this.offline = offline;

this.emit('deviceState', deviceState, setTemperatureZone1, setTemperatureZone2, roomTemperatureZone1, roomTemperatureZone2, operationMode, operationModeZone1, operationModeZone2, setHeatFlowTemperatureZone1, setHeatFlowTemperatureZone2, setCoolFlowTemperatureZone1, setCoolFlowTemperatureZone2, hcControlType, tankWaterTemperature, setTankWaterTemperature, forcedHotWaterMode, unitStatus, outdoorTemperature, ecoHotWater, holidayMode, prohibitZone1, prohibitZone2, prohibitHotWater, idleZone1, idleZone2, power, offline);
this.emit('mqtt', `State`, deviceState);

//restFul
const restFul = restFulEnabled ? this.emit('restFul', 'state', deviceState) : false;

//mqtt
const mqtt = mqttEnabled ? this.emit('mqtt', `State`, deviceState) : false;

this.checkDeviceInfo();
} catch (error) {
this.emit('error', `check device state error, ${error}, check again in 60s.`);
Expand Down
46 changes: 42 additions & 4 deletions src/melclouddevice.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use strict";
const EventEmitter = require('events');
const RestFul = require('./restful.js');
const Mqtt = require('./mqtt.js');
const MelCloudAta = require('./melcloudata.js');
const MelCloudAtw = require('./melcloudatw.js');
Expand Down Expand Up @@ -50,7 +51,29 @@ class MelCloudDevice extends EventEmitter {
this.startPrepareAccessory = true;
this.displayDeviceInfo = true;

//mqtt client
//RESTFul server
const restFulEnabled = account.enableRestFul || false;
this.restFulConnected = false;
if (restFulEnabled) {
const restFulPort = deviceId.slice(-4);
this.restFul = new RestFul({
port: restFulPort,
debug: account.restFulDebug || false
});

this.restFul.on('connected', (message) => {
this.emit('message', `${message}`);
this.restFulConnected = true;
})
.on('error', (error) => {
this.emit('error', error);
})
.on('debug', (debug) => {
this.emit('debug', debug);
});
}

//MQTT client
const mqttEnabled = account.enableMqtt || false;
this.mqttConnected = false;
if (mqttEnabled) {
Expand Down Expand Up @@ -95,7 +118,9 @@ class MelCloudDevice extends EventEmitter {
contextKey: contextKey,
buildingId: buildingId,
deviceId: deviceId,
debugLog: this.enableDebugMode
debugLog: this.enableDebugMode,
restFulEnabled: account.enableRestFul,
mqttEnabled: account.enableMqtt
});

this.melCloudAta.on('deviceInfo', (manufacturer, modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion, presets, presetsCount, hasAutomaticFanSpeed, airDirectionFunction, swingFunction, numberOfFanSpeeds, temperatureIncrement, minTempCoolDry, maxTempCoolDry, minTempHeat, maxTempHeat, minTempAutomatic, maxTempAutomatic, modelSupportsFanSpeed, modelSupportsAuto, modelSupportsHeat, modelSupportsDry) => {
Expand Down Expand Up @@ -516,6 +541,9 @@ class MelCloudDevice extends EventEmitter {
.on('error', (error) => {
this.emit('error', error);
})
.on('restFul', (path, data) => {
const restFul = this.restFulConnected ? this.restFul.update(path, data) : false;
})
.on('mqtt', (topic, message) => {
const mqtt = this.mqttConnected ? this.mqtt.send(topic, message) : false;
});
Expand All @@ -527,7 +555,9 @@ class MelCloudDevice extends EventEmitter {
contextKey: contextKey,
buildingId: buildingId,
deviceId: deviceId,
debugLog: this.enableDebugMode
debugLog: this.enableDebugMode,
restFulEnabled: account.enableRestFul,
mqttEnabled: account.enableMqtt
});

this.melCloudAtw.on('deviceInfo', (manufacturer, modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion, presets, presetsCount, zonesCount, heatPumpZoneName, hotWaterZoneName, hasHotWaterTank, temperatureIncrement, maxTankTemperature, hasZone2, zone1Name, zone2Name, heatCoolModes, caseHotWater, caseZone2) => {
Expand Down Expand Up @@ -972,6 +1002,9 @@ class MelCloudDevice extends EventEmitter {
.on('error', (error) => {
this.emit('error', error);
})
.on('restFul', (path, data) => {
const restFul = this.restFulConnected ? this.restFul.update(path, data) : false;
})
.on('mqtt', (topic, message) => {
const mqtt = this.mqttConnected ? this.mqtt.send(topic, message) : false;
});
Expand All @@ -983,7 +1016,9 @@ class MelCloudDevice extends EventEmitter {
contextKey: contextKey,
buildingId: buildingId,
deviceId: deviceId,
debugLog: this.enableDebugMode
debugLog: this.enableDebugMode,
restFulEnabled: account.enableRestFul,
mqttEnabled: account.enableMqtt
});

this.melCloudErv.on('deviceInfo', (manufacturer, modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion, presets, presetsCount, hasCoolOperationMode, hasHeatOperationMode, hasAutoOperationMode, hasRoomTemperature, hasSupplyTemperature, hasOutdoorTemperature, hasCO2Sensor, hasPM25Sensor, pM25SensorStatus, pM25Level, hasAutoVentilationMode, hasBypassVentilationMode, hasAutomaticFanSpeed, coreMaintenanceRequired, filterMaintenanceRequired, roomCO2Level, actualVentilationMode, numberOfFanSpeeds, temperatureIncrement) => {
Expand Down Expand Up @@ -1336,6 +1371,9 @@ class MelCloudDevice extends EventEmitter {
.on('error', (error) => {
this.emit('error', error);
})
.on('restFul', (path, data) => {
const restFul = this.restFulConnected ? this.restFul.update(path, data) : false;
})
.on('mqtt', (topic, message) => {
const mqtt = this.mqttConnected ? this.mqtt.send(topic, message) : false;
});
Expand Down
17 changes: 15 additions & 2 deletions src/melclouderv.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class MelCloudErv extends EventEmitter {
const buildingId = config.buildingId;
const deviceId = config.deviceId;
const debugLog = config.debugLog;
const restFulEnabled = config.restFulEnabled;
const mqttEnabled = config.mqttEnabled;
const deviceInfoFile = `${prefDir}/${accountName}_Device_${deviceId}`;

this.axiosInstanceGet = axios.create({
Expand Down Expand Up @@ -306,7 +308,12 @@ class MelCloudErv extends EventEmitter {
const permissionCanDisableLocalController = deviceInfo.Permissions.CanDisableLocalController;

this.emit('deviceInfo', manufacturer, modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion, presets, presetsCount, hasCoolOperationMode, hasHeatOperationMode, hasAutoOperationMode, hasRoomTemperature, hasSupplyTemperature, hasOutdoorTemperature, hasCO2Sensor, hasPM25Sensor, pM25SensorStatus, pM25Level, hasAutoVentilationMode, hasBypassVentilationMode, hasAutomaticFanSpeed, coreMaintenanceRequired, filterMaintenanceRequired, roomCO2Level, actualVentilationMode, numberOfFanSpeeds, temperatureIncrement);
this.emit('mqtt', `Info`, deviceInfo);

//restFul
const restFul = restFulEnabled ? this.emit('restFul', 'info', deviceInfo) : false;

//mqtt
const mqtt = mqttEnabled ? this.emit('mqtt', `Info`, deviceInfo) : false;

//check device state
await new Promise(resolve => setTimeout(resolve, 1000));
Expand Down Expand Up @@ -397,7 +404,13 @@ class MelCloudErv extends EventEmitter {
this.offline = offline;

this.emit('deviceState', deviceState, roomTemperature, supplyTemperature, outdoorTemperature, nightPurgeMode, setTemperature, setFanSpeed, operationMode, ventilationMode, defaultHeatingSetTemperature, defaultCoolingSetTemperature, hideRoomTemperature, hideSupplyTemperature, hideOutdoorTemperature, power, offline);
this.emit('mqtt', `State`, deviceState);

//restFul
const restFul = restFulEnabled ? this.emit('restFul', 'state', deviceState) : false;

//mqtt
const mqtt = mqttEnabled ? this.emit('mqtt', `State`, deviceState) : false;

this.checkDeviceInfo();
} catch (error) {
this.emit('error', `check device state error, ${error}, check again in 60s.`);
Expand Down
49 changes: 49 additions & 0 deletions src/restful.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"use strict";
const express = require('express');
const EventEmitter = require('events');

class RestFul extends EventEmitter {
constructor(config) {
super();
this.restFulPort = config.port;
this.restFulDebug = config.debug;

this.restFulData = {
info: 'This data is not available at this time.',
state: 'This data is not available at this time.'
};

this.connect();
};

connect() {
try {
const restFul = express();
restFul.set('json spaces', 2);
restFul.get('/info', (req, res) => { res.json(this.restFulData.info) });
restFul.get('/state', (req, res) => { res.json(this.restFulData.state) });

restFul.listen(this.restFulPort, () => {
this.emit('connected', `RESTful started on port: ${this.restFulPort}`)
});

} catch (error) {
this.emit('error', `RESTful error: ${error}`)
}
};

update(path, data) {
switch (path) {
case 'info':
this.restFulData.info = data;
break;
case 'state':
this.restFulData.state = data;
break;
default:
break;
};
const emitDebug = this.restFulDebug ? this.emit('debug', `RESTFul update path: ${path}, data: ${data}`) : false;
};
};
module.exports = RestFul;

0 comments on commit bcc8d9e

Please sign in to comment.