thing-it-device-enocean-ip
Version:
[thing-it-node] Device Plugin for EnOcean IP products.
471 lines (438 loc) • 15.7 kB
JavaScript
module.exports = {
metadata: {
plugin: "heatingSystem",
label: "Micropelt to Thermokon Heating System",
role: "actor",
family: "heatingSystem",
deviceTypes: ["enocean-ip/gateway"],
tangible: false,
services: [{
label: "Set Temperature",
id: "setTemperature"
}, {
label: "Close Valve",
id: "closeValve"
}],
events: [{
label:"Low Battery",
id: "lowBattery"
}, {
label: 'Button A0 Pressed',
id: 'buttonA0Pressed'
}, {
label: 'Button A0 Released',
id: 'buttonA0Released'
}, {
label: 'Button AI Pressed',
id: 'buttonAIPressed'
}, {
label: 'Button AI Released',
id: 'buttonAIReleased'
}, {
label: 'Button B0 Pressed',
id: 'buttonB0Pressed'
}, {
label: 'Button B0 Released',
id: 'buttonB0Released'
}, {
label: 'Button BI Pressed',
id: 'buttonBIPressed'
}, {
label: 'Button BI Released',
id: 'buttonBIReleased'
}, {
label: 'Set',
id: 'set'
}, {
label: 'Valve Closed',
id: 'valveClosed'
}],
state: [{
label: "Valve",
id: "valve",
type: {
id: "decimal"
}
}, {
label: "Battery Low",
id: "batteryLow",
type: {
id: "boolean"
}
}, {
label: "Actuator Obstructed",
id: "actuatorObstructed",
type: {
id: "boolean"
}
}, {
label: "Temperature",
id: "temperature",
type: {
id: "decimal"
}
}, {
label: "Temperature Setpoint",
id: "setpoint",
type: {
id: "decimal"
}
}, {
label: 'Last Button Operation',
id: 'lastButtonOperation'
}, {
label: "Heat Active",
id:"heatActive",
type: {
id: "boolean"
}
}, {
label: "Cool Active",
id: "coolActive",
type: {
id: "boolean"
}
}, {
label: "Window is Open",
id: "window",
type: {
id: "boolean"
}
}],
configuration: [{
label: "Micropelt Device ID",
id: "micropeltDeviceId",
type: {
id: "string"
}
}, {
label: "Thermokon Device ID",
id: "thermokonDeviceId",
type: {
id: "string"
}
}, {
label: "Button Device ID",
id: "buttonDeviceId",
type: {
id: "string"
}
}, {
label: "Temperature Base Point",
id:"temperatureBasePoint",
type: {
id: "decimal"
},
defaultValue: 22.00
}, {
label: "Set Point Scale",
id: "setPointScale",
type:{
id: "decimal"
},
defaultValue: 1.0
}]
},
create: function () {
return new HeatingSystem();
}
};
var q = require('q');
var _ = require('lodash');
/**
*
*/
function HeatingSystem() {
/**
*
*/
HeatingSystem.prototype.start = function () {
var deferred = q.defer();
this.state = {window: false};
if (this.isSimulated()) {
this.publishStateChange();
}
else {
//Set Thermokon Basepoint and Setpoint values
if(this.configuration.setPointScale < 1.0 || this.configuration.setPointScale > 10.0){
this.logInfo("Set Point Scale value invalid. Setting to default.");
this.configuration.setPointScale = 1;
}
if(this.configuration.temperatureBasePoint < 15 || this.configuration.temperatureBasePoint > 30){
this.logInfo("Temperature Base Point value invalid. Setting to default.");
this.configuration.temperatureBasePoint = 22;
}
//Retrieve Thermokon Current State
this.device.adapter.getDeviceState(this.configuration.thermokonDeviceId).then(function(body){
let tempDiff;
for(let n in body.state.functions){
//console.log(body.state.functions[n]);
if (body.state.functions[n].key === "temperature") {
this.state.temperature = body.state.functions[n].value;
//console.log(this.state.temperature);
}
}
tempDiff = this.state.temperature - this.state.setpoint;
if (tempDiff > 0) {
this.state.coolActive = true;
this.state.heatActive = false;
}
else if (tempDiff < 0) {
this.state.coolActive = false;
this.state.heatActive = true;
}
else {
this.state.coolActive = false;
this.state.heatActive = false;
}
this.publishStateChange();
console.log(this.state);
}.bind(this), function (err){
console.log(err)
}.bind(this));
// Retrieve Radiator current state
this.device.adapter.getDeviceState(this.configuration.micropeltDeviceId).then(function(body){
for(let n in body.state.functions){
console.log(body.state.functions[n]);
if(body.state.functions[n].key === "valve"){
this.state.valve = body.state.functions[n].value;
}
if(body.state.functions[n].key === "batteryLow"){
if(body.state.functions[n].value === "true"){
this.state.batteryLow = true;
this.publishEvent("lowBattery", {});
}
else this.state.batteryLow = false;
}
if(body.state.functions[n].key === "actuatorObstructed"){
if(body.state.functions[n].value === "true"){
this.state.actuatorObstructed = true;
}
else this.state.actuatorObstructed = false;
}
}
this.publishStateChange();
console.log(this.state);
}.bind(this), function (err){
console.log(err)
}.bind(this));
//Retrieve incoming state changes
this.device.adapter.listeners.push(telegram => {
// Updates the state of radiator valve
if (telegram.deviceId === this.configuration.micropeltDeviceId) {
console.log(telegram.functions);
for(let n in telegram.functions){
if(telegram.functions[n].key === "valve"){
this.state.valve = telegram.functions[n].value;
}
if(telegram.functions[n].key === "batteryLow"){
if(telegram.functions[n].value === "true"){
this.state.batteryLow = true;
this.publishEvent("lowBattery", {});
}
else this.state.batteryLow = false;
}
if(telegram.functions[n].key === "actuatorObstructed"){
if(telegram.functions[n].value === "true"){
this.state.actuatorObstructed = true;
}
else this.state.actuatorObstructed = false;
}
}
this.publishStateChange();
}
// Updates the state of the thermostat
if(telegram.deviceId === this.configuration.thermokonDeviceId) {
for (let n in telegram.functions) {
let tempDiff;
if (telegram.functions[n].key === "temperature") {
this.state.temperature = telegram.functions[n].value;
}
if (telegram.functions[n].key === "setpoint") {
this.state.setpoint = setpointConversion(telegram.functions[n].value, this.configuration.temperatureBasePoint, this.configuration.setPointScale);
}
//this.publishStateChange();
tempDiff = this.state.temperature - this.state.setpoint;
if (tempDiff > 0) {
this.state.coolActive = true;
this.state.heatActive = false;
}
else if (tempDiff < 0){
this.state.coolActive = false;
this.state.heatActive = true;
}
else {
this.state.coolActive = false;
this.state.heatActive = false;
}
}
if(!this.state.window || this.state.window === false) {
this.setTemperature(this.state.setpoint, this.state.temperature);
}
this.publishStateChange();
}
// Updates the state of the light switches
if(telegram.deviceId === this.configuration.buttonDeviceId){
for (let n in telegram.functions) {
if (telegram.functions[n].key.indexOf('button') === 0) {
this.publishEvent(telegram.functions[n].key + capitalizeFirstLetter(telegram.functions[n].value), {});
this.state.lastButtonOperation = capitalizeFirstLetter(telegram.functions[n].key) + ' ' + capitalizeFirstLetter(telegram.functions[n].value);
//this.publishStateChange();
}
}
this.publishStateChange();
}
});
deferred.resolve();
}
this.logInfo("Actor Started");
return deferred.promise;
};
/**
*
*/
HeatingSystem.prototype.getState = function () {
return this.state;
};
/**
*
*/
HeatingSystem.prototype.setState = function (state) {
let updatedState = this.updateState(state);
this.state = updatedState;
this.publishStateChange();
this.publishEvent('set', {});
};
/**
*
*/
HeatingSystem.prototype.stop = function () {
if (this.isSimulated()) {
if (this.interval) {
clearInterval(this.interval);
}
}
};
/**
* Sends the Temperature values to the radiator valve
*/
HeatingSystem.prototype.setTemperature = function (setPointTemperature, currentTemperature) {
if(setPointTemperature === undefined || currentTemperature === undefined) return;
let deltaTemperature = currentTemperature - setPointTemperature;
let functions = [];
if(deltaTemperature !== 0){
this.logInfo("Setting Temperature to: ", setPointTemperature);
functions = [{"key": "temperature", "value": currentTemperature},{"key": "temperatureSetpoint", "value": setPointTemperature}];
this.device.adapter.setDeviceState(this.configuration.micropeltDeviceId, functions);
console.log('######## Temperature has been set to: ', setPointTemperature, ' ########')
}
}
/**
* Closes the valve of the radiator
*/
HeatingSystem.prototype.closeValve = function () {
this.device.adapter.setDeviceState(this.configuration.micropeltDeviceId,[{"key": "valve", "value": 0}])
this.publishEvent('valveClosed', {});
}
/**
* updates this.state so that the setState function does not clear other state values
*/
HeatingSystem.prototype.updateState = function(state){
if (_.isObjectLike(state)) {
if (_.isNumber(state.setpoint) && state.setpoint !== this.state.setpoint) {
this.state.setpoint = state.setpoint;
if(!this.state.window || state.window === false) {
this.setTemperature(this.state.setpoint, this.state.temperature);
}
}
if(_.isBoolean(state.window) && state.window !== this.state.window) {
this.state.window = state.window;
if (this.state.window || this.state.window === true){
this.closeValve();
}
else{
this.setTemperature(this.state.setpoint, this.state.temperature);
}
}
}
return this.state;
}
}
/**
* Using the bit value given by Theromokon Room Controller, determines the setpoint temperature
*/
function setpointConversion(value, baseTemp, scale){
let setVar;
let setPoint;
switch (value) {
case 0.00:
setVar = -3.0;
setPoint = baseTemp + scale*setVar;
break;
case 21.00:
setVar = -2.5;
setPoint = baseTemp + scale*setVar;
break;
case 42.00:
setVar = -2.0;
setPoint = baseTemp + scale*setVar;
break;
case 63.00:
setVar = -1.5;
setPoint = baseTemp + scale*setVar;
break;
case 85.00:
setVar = -1.0;
setPoint = baseTemp + scale*setVar;
break;
case 106.00:
setVar = -0.5;
setPoint = baseTemp + scale*setVar;
break;
case 128.00:
setVar = 0.0;
setPoint = baseTemp + scale*setVar;
break;
case 149.00:
setVar = 0.5;
setPoint = baseTemp + scale*setVar;
break;
case 171.00:
setVar = 1.0;
setPoint = baseTemp + scale*setVar;
break;
case 192.00:
setVar = 1.5;
setPoint = baseTemp + scale*setVar;
break;
case 213.00:
setVar = 2.0;
setPoint = baseTemp + scale*setVar;
break;
case 234.00:
setVar = 2.5;
setPoint = baseTemp + scale*setVar;
break;
case 255.00:
setVar = 3.0;
setPoint = baseTemp + scale*setVar;
break;
}
if(setPoint < 15.00){
setPoint = 15.00;
return setPoint;
}
else if(setPoint > 30.00){
setPoint = 30.00;
return setPoint;
}
else{
return setPoint;
}
}
/**
* Caplitalizes the fist letter in a string
*/
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}