UNPKG

thing-it-device-radio-thermostat

Version:
550 lines (482 loc) 15 kB
module.exports = { metadata: { plugin: "radioThermostat", label: "Radio Thermostat", role: "device", family: "radioThermostat", tangible: true, deviceTypes: [], services: [ {id: "incrementSetpoint", label: "Increment Setpoint"}, {id: "decrementSetpoint", label: "Decrement Setpoint"}, {id: "holdOn", label: "Hold On"}, {id: "holdOff", label: "Hold Off"}, {id: "holdToggle", label: "Hold Toggle"}, { id: "changeMode", label: "Change Mode", parameters: [{ id: "mode", label: "Mode", type: {id: "string"} }] }, {id: "modeOff", label: "Mode Off"}, {id: "modeHeat", label: "Mode Heat"}, {id: "modeCool", label: "Mode Cool"}, {id: "modeAuto", label: "Mode Auto"}, {id: "changeFanMode", label: "Change Mode"}, {id: "fanModeAuto", label: "Fan Mode Auto"}, {id: "fanModeAutoCirculate", label: "Fan Mode Auto Circulate"}, {id: "fanModeOn", label: "Fan Mode On"}, ], state: [{ id: "mode", label: "Mode", type: { id: "string" } }, { id: "operatingState", label: "Operating State", type: { id: "string" } }, { id: "setpoint", label: "Setpoint", type: { id: "decimal" } }, { id: "temperature", label: "Temperature", type: { id: "decimal" } }, { id: "fanMode", label: "Fan Mode", type: { id: "string" } }, { id: "fanState", label: "Fan State", type: { id: "string" } }, { id: "hold", label: "Hold", type: { id: "boolean" } }, { id: "override", label: "Overrride", type: { id: "boolean" } }], configuration: [ { label: "Host", id: "host", type: { id: "string" }, defaultValue: "" }, { label: "Name", id: "name", type: { id: "name" }, defaultValue: "" }, { label: "Update Interval", id: "updateInterval", type: { id: "integer" }, defaultValue: "3000" }, ] }, create: function () { return new RadioThermostat(); } }; var q = require('q'); var request; var tstat = "/tstat"; var updating = false; /** * */ function RadioThermostat() { /** * */ RadioThermostat.prototype.start = function () { var deferred = q.defer(); this.state = {}; if (this.isSimulated()) { this.state = { temperature: 64, mode: "HEAT", setpoint: 64, operatingState: "OFF", fmode: "OFF", hold: false, override: false, }; this.simulationInterval = setInterval(function () { if (this.state.mode == "HEAT") { if (this.state.operatingState == "OFF") { this.state.temperature -= 0.5; if (this.state.temperature < (this.state.setpoint - 1)) { this.state.operatingState = "ON"; } } else { this.state.temperature += 0.5; if (this.state.temperature > (this.state.setpoint + 1)) { this.state.operatingState = "OFF"; } } } else { if (this.state.operatingState == "ON") { this.state.temperature -= 0.5; if (this.state.temperature < (this.state.setpoint - 1)) { this.state.operatingState = "OFF"; } } else { this.state.temperature += 0.5; if (this.state.temperature > (this.state.setpoint + 1)) { this.state.operatingState = "ON"; } } } this.publishStateChange(); }.bind(this), 10000); } else { this.state = {}; this.pollState(); this.pollInterval = setInterval(function () { this.pollState(); }.bind(this), 30000); } deferred.resolve(); return deferred.promise; }; /** * */ RadioThermostat.prototype.stop = function () { var deferred = q.defer(); if (this.pollInterval) { clearInterval(this.pollInterval); } if (this.simulationInterval) { clearInterval(this.simulationInterval); } deferred.resolve(); return deferred.promise; }; /** * */ RadioThermostat.prototype.getState = function () { return this.state; }; /** * */ RadioThermostat.prototype.setState = function (state) { //TODO implement properly }; RadioThermostat.prototype.pollState = function (callback) { this.logDebug("Polling state for Radio Thermostat with name " + this.configuration.name + " located at " + this.configuration.host); var url = "http://" + this.configuration.host + tstat; if (!request) { request = require('request'); } request.get({ url: url }, function (error, response, body) { if (!updating) { if (error) { this.logError("Error communicating to Radio Thermostat.", error, body); if (callback) { callback(error, null); } } else { var thermostatState = JSON.parse(body); this.state.temperature = thermostatState.temp; switch (thermostatState.tmode) { case 0: this.state.mode = "OFF"; break; case 1: this.state.mode = "HEAT"; this.state.setpoint = thermostatState.t_heat; break; case 2: this.state.mode = "COOL"; this.state.setpoint = thermostatState.t_cool; break; case 3: this.state.mode = "AUTO"; if (thermostatState.t_heat) { this.state.setpoint = thermostatState.t_heat; } else if (thermostatState.t_cool) { this.state.setpoint = thermostatState.t_cool; } break; } switch (thermostatState.tstate) { case 0: this.state.operatingState = "OFF"; break; case 1: this.state.operatingState = "HEAT"; break; case 2: this.state.operatingState = "COOL"; break; } switch (thermostatState.fmode) { case 0: this.state.fanMode = "AUTO"; break; case 1: this.state.fanMode = "AUTO/CIRCULATE"; break; case 2: this.state.fanMode = "ON"; break; } switch (thermostatState.fstate) { case 0: this.state.fanState = "AUTO"; break; case 1: this.state.fanState = "AUTO/CIRCULATE"; break; case 2: this.state.fanState = "ON"; break; } switch (thermostatState.hold) { case 0: this.state.hold = false; break; case 1: this.state.hold = true; break; } switch (thermostatState.override) { case 0: this.state.override = false; break; case 1: this.state.override = true; break; } this.logDebug("State", this.state); this.publishStateChange(); } } else { this.logDebug("Ignoring stale update."); } }.bind(this)); } /** * */ RadioThermostat.prototype.setSetpoint = function (targetTemperature) { this.state.setpoint = targetTemperature; var body; if (this.state.mode == "HEAT") { body = '{"it_heat":' + targetTemperature + '}'; } else if (this.state.mode == "COOL") { body = '{"it_cool":' + targetTemperature + '}'; } else { // Cannot set temperature in auto mode } if (body) { this.sendPostRequest(body); } } /** * */ RadioThermostat.prototype.incrementSetpoint = function () { this.logDebug("Called incrementSetpoint()"); this.setSetpoint(this.state.setpoint + 1); }; /** * */ RadioThermostat.prototype.decrementSetpoint = function () { this.logDebug("Called decrementSetpoint()"); this.setSetpoint(this.state.setpoint - 1); }; /** * */ RadioThermostat.prototype.setHold = function (hold) { var body; this.state.hold = hold; if (hold) { body = '{"hold":1}'; } else { body = '{"hold":0}'; } this.sendPostRequest(body); } /** * */ RadioThermostat.prototype.holdOn = function () { this.setHold(true); } /** * */ RadioThermostat.prototype.holdOff = function () { this.setHold(false); } /** * */ RadioThermostat.prototype.holdToggle = function () { if (this.state.hold) { this.holdOff(); } else { this.holdOn(); } } /** * * @param parameters */ RadioThermostat.prototype.changeFanMode = function (parameters) { this.logDebug("ChangeFanMode called: ", parameters); this.setFanMode(parameters.fanMode); } /** * */ RadioThermostat.prototype.setFanMode = function (fanMode) { var body; this.state.mode = fanMode; if (fanMode == "AUTO") { body = '{"fmode":0}'; } else if (fanMode == "AUTO/CIRCULATE") { body = '{"fmode":1}'; } else if (fanMode == "ON") { body = '{"fmode":2}'; } this.sendPostRequest(body); } /** * */ RadioThermostat.prototype.fanModeAuto = function (fanMode) { this.setFanMode("AUTO"); } /** * */ RadioThermostat.prototype.fanModeAutoCirculate = function (fanMode) { this.setFanMode("AUTO/CIRCULATE"); } /** * */ RadioThermostat.prototype.fanModeOn = function (fanMode) { this.setFanMode("ON"); } /** * * @param parameters */ RadioThermostat.prototype.changeMode = function (parameters) { this.logDebug("ChangeMode called: ", parameters); this.setMode(parameters.mode); } /** * */ RadioThermostat.prototype.setMode = function (mode) { var body; this.state.mode = mode; if (mode == "OFF") { body = '{"tmode":0}'; } else if (mode == "HEAT") { body = '{"tmode":1}'; } else if (mode == "COOL") { body = '{"tmode":2}'; } else if (mode == "AUTO") { body = '{"tmode":3}'; } else { this.logDebug("Unrecognized mode.", mode); } this.sendPostRequest(body); } /** * */ RadioThermostat.prototype.modeOff = function () { this.setMode("OFF"); } /** * */ RadioThermostat.prototype.modeHeat = function () { this.setMode("HEAT"); } /** * */ RadioThermostat.prototype.modeCool = function () { this.setMode("COOL"); } /** * */ RadioThermostat.prototype.modeAuto = function () { this.setMode("AUTO"); } /** * */ RadioThermostat.prototype.sendPostRequest = function (body, callback) { this.publishStateChange(); if (this.isSimulated()) { } else { updating = true; var url = "http://" + this.configuration.host + tstat; var updatingTimeout = setTimeout(function () { updating = false; }, 10000); if (body) { if (!request) { request = require('request'); } request.post({ url: url, method: 'POST', body: body }, function (error, response, body) { updating = false; if (error) { this.logError("Error communicating to Radio Thermostat.", error, body); } else { this.pollState(); if (callback) { callback(body); } } if (updatingTimeout) { clearTimeout(updatingTimeout); } }.bind(this)); } } } };