UNPKG

iss-gateway

Version:
828 lines (771 loc) 19.2 kB
var nconf = require('nconf'); var request = require('./request'); var logging = require('./logging'); var domoticz = {}; /** * Return the Domoticz URL * @returns {[[Type]]} Domoticz URL string */ domoticz.getURL = function () { var protocole = nconf.get('domoticz:ssl') === true ? 'https' : 'http'; var host = nconf.get('domoticz:host'); var port = nconf.get('domoticz:port'); var path = nconf.get('domoticz:path'); var cmd = "json.htm"; // In case of AUTH Basic authentication var secure = false; if (nconf.get('domoticz:auth') && nconf.get('domoticz:auth:username') && nconf.get('domoticz:auth:password')) { var secure = nconf.get('domoticz:auth:username') + ":" + nconf.get('domoticz:auth:password') + "@"; } if (secure) { var url = protocole + '://' + secure + host + ':' + port + path + cmd; } else { var url = protocole + '://' + host + ':' + port + path + cmd; } return url; }; /** * Convert Domoticz scene to an ImperiHome scene * @param {object} scene Domoticz scene * @returns {object} ImperiHome scene object */ domoticz.convertScene = function (scene) { var device = {}; device.id = 'scene-' + scene.idx, device.name = scene.Name, device.type = 'DevScene', device.room = '', device.params = []; device.params.push({ 'key': 'LastRun', 'value': scene.LastUpdate }); return device; } /** * Convert Domoticz camera device to an ImperiHome camera device. * @param {object} camera Domoticz camera device * @returns {object} ImperiHome camera device object */ domoticz.convertCamera = function (camera) { var device = {}; device.id = 'camera-' + camera.idx; device.name = camera.Name; device.type = 'DevCamera'; device.room = ""; //no room by default device.params = []; // FIXME: Seems to currently not working with D-Link DCS 932L. //var cameraURL = "http://" + camera.Username + ":" + camera.Password + "@" + camera.Address + ':' + camera.Port + '/'; var cameraURL = "http://" + camera.Address + ':' + camera.Port + '/'; //var cameraURL = "http://" + camera.Address + '/'; device.params.push({ 'key': 'localjpegurl', 'value': cameraURL + camera.ImageURL }); device.params.push({ 'key': 'remotejpegurl', 'value': cameraURL + camera.ImageURL }); // "url_cam_video": "video/mjpg.cgi" if (nconf.get('domoticz:url_cam_video')) { device.params.push({ 'key': 'localmjpegurl', 'value': cameraURL + nconf.get('domoticz:url_cam_video') }); device.params.push({ 'key': 'remotemjpegurl', 'value': cameraURL + nconf.get('domoticz:url_cam_video') }); } device.params.push({ 'key': 'Login', 'value': camera.Username }); device.params.push({ 'key': 'Password', 'value': camera.Password }); return device; } /** * Convert Domoticz device(s) to ImperiHome device(s). * It can return multiples devices for specific sensors (Temperature, Humidity, & Barometer). * @param {object} device Domoticz device * @returns {Array} ImperiHome device array */ domoticz.convertDevice = function (device) { var arDevices = []; // TODO: Add history system and change graphable attribue to true switch (device.Type) { case 'Temp': var newDevice = {}; newDevice.id = device.idx + '-t'; newDevice.name = device.Name; newDevice.type = 'DevTemperature'; newDevice.room = device.PlanID != 0 ? device.PlanID : ""; newDevice.params = []; var param = {}; param.key = 'Value'; param.value = device.Temp; param.unit = '°C'; param.graphable = false; newDevice.params.push(param); arDevices.push(newDevice); break; case 'Temp + Humidity': var newDevice = {}; newDevice.id = device.idx + '-t'; newDevice.name = device.Name; newDevice.type = 'DevTemperature'; newDevice.room = device.PlanID != 0 ? device.PlanID : ""; newDevice.params = []; var param = {}; param.key = 'Value'; param.value = device.Temp; param.unit = '°C'; param.graphable = false; newDevice.params.push(param); arDevices.push(newDevice); var newDevice = {}; newDevice.id = device.idx + '-h'; newDevice.name = device.Name; newDevice.type = 'DevHygrometry'; newDevice.room = device.PlanID != 0 ? device.PlanID : ""; newDevice.params = []; var param = {}; param.key = 'Value'; param.value = device.Humidity; param.unit = '%'; param.graphable = false; newDevice.params.push(param); arDevices.push(newDevice); break; case 'Temp + Humidity + Baro': var newDevice = {}; newDevice.id = device.idx + '-t'; newDevice.name = device.Name; newDevice.type = 'DevTemperature'; newDevice.room = device.PlanID != 0 ? device.PlanID : ""; newDevice.params = []; var param = {}; param.key = 'Value'; param.value = device.Temp; param.unit = '°C'; param.graphable = false; newDevice.params.push(param); arDevices.push(newDevice); var newDevice = {}; newDevice.id = device.idx + '-h'; newDevice.name = device.Name; newDevice.type = 'DevHygrometry'; newDevice.room = device.PlanID != 0 ? device.PlanID : ""; newDevice.params = []; var param = {}; param.key = 'Value'; param.value = device.Humidity; param.unit = '%'; param.graphable = false; newDevice.params.push(param); arDevices.push(newDevice); var newDevice = {}; newDevice.id = device.idx + '-b'; newDevice.name = device.Name; newDevice.type = 'DevPressure'; newDevice.room = device.PlanID != 0 ? device.PlanID : ""; newDevice.params = []; var param = {}; param.key = 'Value'; param.value = device.Barometer; param.unit = 'mbar'; param.graphable = false; newDevice.params.push(param); arDevices.push(newDevice); break; default: // others devices var newDevice = {}; newDevice.id = device.idx; newDevice.name = device.Name; newDevice.type = this.convertDeviceType(device); newDevice.room = device.PlanID != 0 ? device.PlanID : ""; newDevice.params = this.convertDeviceStatus(device); arDevices.push(newDevice); break; } return arDevices; }; /** * Conver a domoticz device status to an ImperiHome device status * @param {object} device Domoticz device * @returns {Array} ImperiHome device status array */ domoticz.convertDeviceStatus = function (device) { var output = []; switch (device.Type) { case "Light/Switch": case "Lighting Limitless/Applamp": case "Lighting 1": case "Lighting 2": switch (device.SwitchType) { case 'On/Off': output.push({ 'key': 'Status', 'value': 'Off' == device.Status ? '0' : '1', }); break; case 'Push On Button': output.push({ 'key': 'Status', 'value': 'Off' == device.Status ? '0' : '1', }); break; case 'Push Off Button': output.push({ 'key': 'Status', 'value': 'Off' == device.Status ? '0' : '1', }); break; case 'Smoke Detector': output.push({ 'key': 'Tripped', 'value': 'Off' == device.Status ? '0' : '1', }); output.push({ 'key': 'Armed', 'value': '1', }); output.push({ 'key': 'Ackable', 'value': '1', }); output.push({ 'key': 'Armable', 'value': '1', }); break; case 'Door Lock': output.push({ 'key': 'Tripped', 'value': 'Closed' == device.Status ? '0' : '1', }); output.push({ 'key': 'Armed', 'value': '1', }); output.push({ 'key': 'Ackable', 'value': '1', }); output.push({ 'key': 'Armable', 'value': '1', }); break; case 'Motion Sensor': output.push({ 'key': 'Tripped', 'value': 'Off' == device.Status ? '0' : '1', }); output.push({ 'key': 'Armed', 'value': '1', }); output.push({ 'key': 'Ackable', 'value': '1', }); output.push({ 'key': 'Armable', 'value': '1', }); break; case 'Blinds Inverted': output.push({ 'key': 'Level', 'value': 'Closed' == device.Status ? '0' : '100', }); output.push({ 'key': 'stopable', 'value': '0', }); output.push({ 'key': 'pulseable', 'value': '0', }); break; case 'Blinds': output.push({ 'key': 'Level', 'value': 'Closed' == device.Status ? '0' : '100', }); output.push({ 'key': 'stopable', 'value': '0', }); output.push({ 'key': 'pulseable', 'value': '0', }); break; case 'Blinds Percentage': output.push({ 'key': 'Level', 'value': 'Closed' == device.Status ? '0' : '100', }); output.push({ 'key': 'stopable', 'value': '1', }); output.push({ 'key': 'pulseable', 'value': '0', }); break; break; case 'Dimmer': output.push({ 'key': 'Level', 'value': 'Off' == device.Status ? '0' : '100', }); output.push({ 'key': 'Status', 'value': 'Off' == device.Status ? '0' : '1', }); break; case 'Dusk Sensor': output.push({ 'key': 'Value', 'value': device.Data, }); break; default: output.push({ 'key': 'Status', 'value': 'Off' == device.Status ? '0' : '1', }); } break; case 'General': switch (device['Name']) { case (0 === device.Name.indexOf('Freebox')): var dataDevice = device.Data.split('.'); var ddDevice = dataDevice[0]; output.push({ 'key': 'Value', 'value': ddDevice, 'unit': 'rpm', }); break; default: output.push({ 'key': 'Value', 'value': device.Data, 'unit': '', }); break; } break; case 'RFY': output.push({ 'key': 'Level', 'value': 'Closed' == device.Status ? '0' : '100', }); output.push({ 'key': 'stopable', 'value': '0', }); output.push({ 'key': 'pulseable', 'value': '0', }); break; case 'UV': output.push({ 'key': 'Value', 'value': device['UVI'], 'unit': 'UVI', }); break; case 'Lux': var words = device.Data.split(/\s+/); var data = words[0]; output.push({ 'key': 'Value', 'value': data, 'unit': 'lux', }); break; case 'Rain': output.push({ 'key': 'Value', 'value': device.RainRate, 'unit': 'mm/h', }); output.push({ 'key': 'Accumulation', 'value': device.Rain, 'unit': 'mm', }); break; case 'Wind': output.push({ 'key': 'Speed', 'value': device.Speed, 'unit': 'km/h', }); break; case 'Usage': var words = device.Data.split(/\s+/); var data = words[0]; output.push({ 'key': 'Watts', 'value': data, 'unit': 'Watt', }); output.push({ 'key': 'ConsoTotal', 'value': data, 'unit': 'kWh', }); break; case 'Current/Energy': var words = device.Data.split(/\s+/); var data = words[0]; output.push({ 'key': 'Watts', 'value': data, 'unit': 'Watt', }); output.push({ 'key': 'ConsoTotal', 'value': data, 'unit': 'kWh', }); break; case 'Energy': var wordsUsage = device.Usage.split(/\s+/); var dataUsage = wordsUsage[0]; var wordsData = device.Data.split(/\s+/); var dataData = wordsData[0]; output.push({ 'key': 'Watts', 'value': dataUsage, 'unit': 'Watt', }); output.push({ 'key': 'ConsoTotal', 'value': dataData, 'unit': 'kWh', }); break; case 'P1 Smart Meter': var wordsUsage = device.Usage.split(/\s+/); var dataUsage = wordsUsage[0]; var wordsData = device.CounterToday.split(/\s+/); var dataData = wordsData[0]; output.push({ 'key': 'Watts', 'value': dataUsage, 'unit': 'Watt', }); output.push({ 'key': 'ConsoTotal', 'value': dataData, 'unit': 'kWh', }); break; case 'Thermostat': // TODO: Manage mode, current mode, and all values of Thermostat output.push({ 'key': 'curmode', 'value': 'Off', }); output.push({ 'key': 'curtemp', 'value': device.Data, }); output.push({ 'key': 'cursetpoint', 'value': device.Data, }); output.push({ 'key': 'step', 'value': '0.5', }); output.push({ 'key': 'minVal', 'value': '12.0', }); output.push({ 'key': 'maxVal', 'value': '28.0', }); output.push({ 'key': 'availablemodes', 'value': 'On, Off', }); break; case 'Security': switch (device.SwitchType) { case 'Smoke Detector': output.push({ 'key': 'Tripped', 'value': 'Normal' == device.Status ? '0' : '1', }); output.push({ 'key': 'Armed', 'value': '1', }); output.push({ 'key': 'Ackable', 'value': '1', }); output.push({ 'key': 'Armable', 'value': '1', }); break; } } return output; } /** * Conver a domoticz device type to an ImperiHome device type * @param {object} device Domoticz device * @returns {string} ImperiHome device type */ domoticz.convertDeviceType = function (device) { switch (device.Type) { case "Light/Switch": case "Lighting Limitless/Applamp": case "Lighting 1": case "Lighting 2": switch (device.SwitchType) { case 'On/Off': type = 'DevSwitch'; break; case 'Push On Button': type = 'DevSwitch'; break; case 'Push Off Button': type = 'DevSwitch'; break; case 'Smoke Detector': type = 'DevSmoke'; break; case 'Door Lock': type = 'DevDoor'; break; case 'Motion Sensor': type = 'DevMotion'; break; case 'Blinds Inverted': type = 'DevShutter'; break; case 'Blinds': type = 'DevShutter'; break; case 'Blinds Percentage': type = 'DevShutter'; break; case 'Dimmer': type = 'DevDimmer'; break; case 'Dusk Sensor': type = 'DevLuminosity'; break; default: type = 'DevSwitch'; break; } break; case 'Temp': type = 'DevTemperature'; break; case 'Wind': type = 'DevWind'; break; case 'Rain': type = 'DevRain'; break; case 'General': type = 'DevGenericSensor'; break; case 'UV': type = 'DevUV'; break; case 'RFY': type = 'DevShutter'; break; case 'Energy': type = 'DevElectricity'; break; case 'P1 Smart Meter': type = 'DevElectricity'; break; case 'Usage': type = 'DevElectricity'; break; case 'Lux': type = 'DevLuminosity'; break; case 'Current/Energy': type = 'DevElectricity'; break; case 'Thermostat': type = 'DevThermostat'; break; case 'Security': switch (device.SwitchType) { case 'Smoke Detector': type = 'DevSmoke'; break; default: type = 'DevGenericSensor'; break; } break; default: type = 'DevGenericSensor'; break; } logging.log("Type '" + device.Type + "' -> '" + type + "'"); return type; }; /** * Parse an action and send it to an Domoticz device * @param {string} action Action name * @param {string} deviceId Device ID * @param {string} param Action parameter (may be undefined) * @returns {Object} JSON response */ domoticz.parseAction = function (action, deviceId, param) { logging.log('SendAction'); var status = false; var retMessage = 'An error occured...'; // NOTE: Specific dimmer value is not taken in account. // This command is ignored : type=command&param=switchlight&idx=99&switchcmd=Set%20Level&level=6 // See FYI https://www.domoticz.com/wiki/Domoticz_API/JSON_URL's#Turn_a_light.2Fswitch_on if (action && deviceId) { switch (action) { case 'setLevel': case 'setStatus': action = 'switchlight'; case 'pulseShutter': param = (param && param == '0') ? 'Off' : 'On'; break; case 'launchScene': action = "switchscene"; param = 'On'; // Scene can only be turn On // Split scene id (scene-XX) deviceId = deviceId.split("-")[1]; break; } } // Build query string var query = { 'idx': deviceId, 'param': action }; // if defined, add parameter as switchcmd if (param) query.switchcmd = param; this.sendAction(query).then(function (response) { logging.log('Response : ' + JSON.stringify(response)); // return response return { 'success': status, 'errormsg': status ? '' : retMessage }; });; }; domoticz.sendAction = function (queryString) { logging.log("SendAction with query " + JSON.stringify(queryString)); var options = { uri: this.getURL(), qs: queryString, headers: { 'User-Agent': nconf.get('domoticz:user-agent') }, json: true }; // Add 'type=command' parameter options.qs.type = 'command'; return request.sendRequest(options); }; /** * Get Domoticz rooms list * @returns {Promise} Request promise */ domoticz.getRooms = function () { logging.log("GetRooms"); var options = { uri: this.getURL(), qs: { type: 'plans', order: 'name', 'used': 'true' }, headers: { 'User-Agent': nconf.get('domoticz:user-agent') }, json: true }; return request.sendRequest(options); }; /** * Get Domoticz scenes list * @returns {Promise} Request promise */ domoticz.getScenes = function () { logging.log("GetScenes"); var options = { uri: this.getURL(), qs: { type: 'scenes' // -> uri + '?type=scenes' }, headers: { 'User-Agent': nconf.get('domoticz:user-agent') }, json: true }; return request.sendRequest(options); }; /** * Get Domoticz camera list * @returns {Promise} Request promise */ domoticz.getCameras = function () { logging.log("GetCameras"); var options = { uri: this.getURL(), qs: { type: 'cameras' // -> uri + '?type=cameras' }, headers: { 'User-Agent': nconf.get('domoticz:user-agent') }, json: true }; return request.sendRequest(options); }; /** * Get Domoticz devices list * @param {String} Room ID (leave null for all devices) * @returns {Promise} Request promise */ domoticz.getDevices = function (room) { logging.log("GetDevices"); var options = { uri: this.getURL(), qs: { type: 'devices' // -> uri + '?type=device' }, headers: { 'User-Agent': nconf.get('domoticz:user-agent') }, json: true }; // Add plan parameter in query string if room number is present if (room) options.qs.plan = room; return request.sendRequest(options); }; module.exports = domoticz;