Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- var request = require('request');
- // enable debugging mode
- //request.debug = true;
- var lastEventTime = new Date().getTime();
- var rawDeviceData = false;
- var tahomaJar = request.jar();
- var baseRequest = request.defaults({
- headers: {
- 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36'},
- jar: tahomaJar
- });
- var tahomaDevices = {};
- var Map_DeviceURL2StateName = {};
- var userName = "";
- var passWord = "";
- var baseURL = 'https://www.tahomalink.com/enduser-mobile-web/externalAPI/json/';
- var baseURLApply = 'https://www.tahomalink.com/enduser-mobile-web/enduserAPI/';
- var isConnectedInternal = false;
- createState('tahoma.connected', false, {
- read: true,
- write: true,
- name: "connection status of tahoma",
- type: "boolean",
- def: false
- });
- createOrUpdateState('tahoma.update', false, {
- read: true,
- write: true,
- role: "button"
- });
- on('javascript.0.tahoma.update', function(obj)
- {
- log("tahoma refresh states requested: " + obj);
- if (obj.newState.val)
- {
- getAllStates(function ()
- {
- setState("javascript.0.tahoma.update", false);
- });
- }
- });
- function isConnected()
- {
- return isConnectedInternal;
- }
- function setConnected(connected)
- {
- isConnectedInternal = connected;
- setState('javascript.0.tahoma.connected', connected, true);
- }
- function getCreateStateOptions4Widget(widget)
- {
- if (widget === 'PositionableRollerShutter')
- {
- return {
- "role": "blind",
- };
- }
- if (widget === 'LuminanceSensor')
- {
- return {
- "role": "sensor"
- };
- }
- return {
- read: true,
- write: false,
- role: "state"
- };
- }
- function getCreateStateOptions4State(widget, stateName)
- {
- if (stateName === "core:ClosureState" || stateName === "core:TargetClosureState")
- {
- return {
- "type": "number", // optional, default "number"
- "read": true, // mandatory, default true
- "write": true, // mandatory, default true
- "min": 0, // optional, default 0
- "max": 100, // optional, default 100
- "unit": "%", // optional, default %
- "role": "level.blind" // mandatory
- };
- }
- if (stateName === "core:SlateOrientationState")
- {
- return {
- "type": "number", // optional, default "number"
- "read": true, // mandatory, default true
- "write": true, // mandatory, default true
- "min": 0, // optional, default 0
- "max": 100, // optional, default 100
- "unit": "%", // optional, default %
- "role": "level.blind.orientation" // mandatory
- };
- }
- if (stateName === "core:LuminanceState")
- {
- return {
- "type": "number", // optional, default "number"
- "read": true, // mandatory, default true
- "write": false, // mandatory, default true
- "min": 0, // optional, default 0
- "max": 100000, // optional, default 100
- "unit": "Lux", // optional, default %
- "role": "level.color.luminance" // mandatory
- };
- }
- return {
- read: true,
- write: false,
- role: "state"
- };
- }
- function send(requestPath, payload, callback)
- {
- login(function(err,data)
- {
- if (err)
- {
- return callback(err, data);
- }
- sendInternal(requestPath, payload, callback);
- });
- }
- function sendInternal(requestPath, payload, callback)
- {
- var url = baseURL + requestPath;
- if (requestPath.endsWith("apply"))
- {
- url = baseURLApply + requestPath + "/highPriority";
- }
- else if (requestPath === '/setup/devices/states/refresh')
- {
- url = baseURLApply + requestPath;
- }
- var formPayload = null;
- var jsonPayload = null;
- if (requestPath === 'login')
- {
- formPayload = payload;
- }
- else
- {
- jsonPayload = payload;
- }
- log("perform " + requestPath + " with payload:" + JSON.stringify(payload), 'debug');
- baseRequest.post(
- {
- url: url,
- json: jsonPayload,
- form: formPayload
- },
- cb(function(error, response, body)
- {
- if (!error && response.statusCode === 200)
- {
- if (requestPath === 'login')
- {
- callback(false, JSON.parse(body));
- }
- else
- {
- callback(false, body);
- }
- }
- else if (response && requestPath !== 'logout'
- && (response.statusCode === 401 || response.statusCode === 403))
- {
- //log("error during tahomalink request: " + response.statusText + " ->" + response.statusCode + " retry " + requestPath, 'error');
- // session expired?
- setConnected(false);
- send(requestPath, payload, callback);
- }
- else
- {
- log("error during tahomalink request: " + error, 'error');
- var result = {};
- result.error = error;
- if(typeof response !== "undefined")
- {
- log("response status: " + response.statusCode + " " + response.statusText,'debug');
- result.responseStatusCode = response.statusCode;
- result.responseStatusText = response.statusText;
- }
- callback(true, result);
- }
- }));
- }
- function logout(callback)
- {
- var performLogout = isConnected();
- setConnected(false);
- if (performLogout)
- {
- sendInternal("logout", {}, function (err, data)
- {
- callback(err, data);
- });
- }
- else
- {
- callback(false, {});
- }
- }
- function login(callback)
- {
- if (!isConnected())
- {
- var payload = {'userId': userName, 'userPassword': passWord};
- var result = sendInternal("login", payload, cb(function (err, data)
- {
- if (err || !data.success)
- {
- return callback(true, data);
- }
- lastEventTime = new Date().getTime();
- setConnected(true);
- getUserInfo(function (err,data)
- {
- if (!err)
- {
- return getSetup(callback);
- }
- callback(err, data);
- });
- }));
- }
- else
- {
- callback(false, {});
- }
- }
- function getUserInfo(callback)
- {
- send('getEndUser', {},function (err, data)
- {
- if (!err)
- {
- updateData('userdata', data.endUser);
- callback(false, data);
- }
- else
- {
- log("getUserInfo failed!", 'error');
- }
- });
- }
- function updateGateWayData(gateways)
- {
- for (var i in gateways)
- {
- var gateway = gateways[i];
- updateData(gateway.gatewayId, gateway);
- }
- }
- function updateDevices(devices)
- {
- tahomaDevices = devices;
- for (var i in devices)
- {
- var device = devices[i];
- // just set the raw data from tahoma
- updateDevice('devices.' + device.label, device);
- }
- }
- function updateDevice(name, deviceData)
- {
- createOrUpdateState('tahoma.' + name, '',
- getCreateStateOptions4Widget(deviceData.widget));
- // device URL
- createOrUpdateState('tahoma.' + name + '.deviceURL', deviceData.deviceURL);
- // states
- for (var stateKey in deviceData.states)
- {
- var state = deviceData.states[stateKey];
- createOrUpdateState('tahoma.' + name + '.states.' + state.name,
- mapValueTahoma2ioBroker(state.name, state.value),
- getCreateStateOptions4State(deviceData.widget, state.name));
- }
- // commands
- for (var commandKey in deviceData.definition.commands)
- {
- var command = deviceData.definition.commands[commandKey];
- if (command.nparams === 0)
- {
- createOrUpdateState('tahoma.' + name + '.commands.' + command.commandName, false, {
- read: true,
- write: true,
- role: "button"
- });
- }
- }
- // raw data
- if (rawDeviceData)
- {
- for (var p in deviceData)
- {
- var value = deviceData[p];
- if (typeof(value) === 'object')
- {
- updateData('raw.' + name + '.' + p, value);
- }
- else
- {
- createOrUpdateState('tahoma.raw.' + name + '.' + p, value);
- }
- }
- }
- }
- function mapValueTahoma2ioBroker(stateName, stateValue)
- {
- if (stateName === 'core:ClosureState' || stateName === 'core:TargetClosureState')
- {
- stateValue = parseInt(stateValue,10);
- }
- return stateValue;
- }
- function mapValueioBroker2Tahoma(stateName, stateValue)
- {
- if (stateName === 'core:ClosureState' || stateName === 'core:TargetClosureState')
- {
- stateValue = parseInt(stateValue,10);
- }
- return stateValue;
- }
- function updateData(type, data)
- {
- for (var p in data)
- {
- var value = data[p];
- if (typeof(value) === 'object')
- {
- updateData(type + '.' + p, value);
- }
- else
- {
- createOrUpdateState('tahoma.' + type + '.' + p, value);
- }
- }
- }
- function createOrUpdateState(key, value, options)
- {
- key = key.replace(' ' , '_');
- var state = getState("javascript.0." + key);
- if (value === "true" || value === "false")
- {
- value = value == "true";
- }
- if (state.notExist)
- {
- if (typeof(options) === 'undefined')
- {
- options = {
- read: true,
- write: false,
- type: "string"
- };
- }
- // create state
- createState(key, value, 0, options);
- }
- else
- {
- setState("javascript.0." + key, value, true);
- }
- }
- function getSetup(callback)
- {
- send('getSetup', {},function (err, data)
- {
- if (!err)
- {
- updateGateWayData(data.setup.gateways);
- updateData('location', data.setup.location);
- updateDevices(data.setup.devices);
- // delete old devices
- deleteOldDevices();
- // update mapping table device URL to state key with label
- $('javascript.0.tahoma.devices.*.deviceURL').each(function (id, i)
- {
- var state = getState(id);
- Map_DeviceURL2StateName[state.val] = id.substr(0, id.indexOf(".deviceURL"));
- //log("set mapping deviceURL to name: " + state.val + " -> " + id.substr(0, id.indexOf(".deviceURL")),'debug');
- });
- // refresh
- send('/setup/devices/states/refresh', {}, function (err,data)
- {
- if (err)
- {
- log("refresh device state failed");
- }
- callback(err, {});
- });
- }
- else
- {
- log("getSetup failed!",'error');
- callback(err, {});
- }
- });
- }
- function getAllStates()
- {
- login(function (err, data)
- {
- if (err)
- {
- return;
- }
- send("getEvents", {}, function (err,data)
- {
- if (err)
- {
- return;
- }
- updateDeviceStateFromEvent(data);
- });
- });
- }
- function updateDeviceStateFromEvent(events)
- {
- for (var i in events)
- {
- lastEventTime = new Date().getTime();
- var event = events[i];
- if (event.name === 'DeviceStateChangedEvent')
- {
- updateDeviceState(event);
- }
- }
- }
- function updateDeviceState(event)
- {
- var deviceURL = event.deviceURL;
- var states = event.deviceStates;
- var devicePath = Map_DeviceURL2StateName[deviceURL];
- // tahoma.devices.XXX
- // tahoma.devices.XXX.states.Y
- log("got event for device " + devicePath);
- for (var i in event.deviceStates)
- {
- var state = event.deviceStates[i];
- var name = state.name;
- var value = mapValueTahoma2ioBroker(name, state.value);
- log("found " + devicePath + '.states.' + name + " -> " + value);
- setState(devicePath + '.states.' + name, value, true);
- }
- }
- function deleteOldDevices()
- {
- var currentTime = new Date().getTime();
- $('javascript.0.tahoma.devices.*.lastUpdateTime').each(function (id, i)
- {
- var state = getState(id);
- var device = id.substr(0, id.indexOf(".lastUpdateTime"));
- if (currentTime - state.ts > 5 * 60 * 1000)
- {
- // update older than 1 minute -> drop
- log ("found old " + device + " -> " + new Date(state.ts),'debug');
- $(device + '.*').each(function (id, i)
- {
- //log("delete state:" + id);
- deleteState(id);
- });
- }
- });
- }
- on(/^javascript\.0\.tahoma\.devices.*\.commands/,function(obj)
- {
- if (obj.state.val)
- {
- var id = obj.id;
- log("button pressed: " + id + " -> " + JSON.stringify(obj));
- var commandName = id.substr(id.lastIndexOf(".")+1);
- var deviceURL = getState(id.substr(0, id.indexOf(".commands.")) + ".deviceURL").val;
- var payload = {'label':'command ' + commandName + ' from ioBroker',
- 'actions':[{
- 'deviceURL': deviceURL,
- 'commands': [{
- 'name': commandName,
- 'parameters': []
- }]}]};
- send("exec/apply", payload, function(err, data)
- {
- // reset state
- setState(obj.id, !obj.state.val);
- });
- }
- });
- on(/^javascript\.0\.tahoma\.devices.*\.states.core:ClosureState/,function(obj)
- {
- onClosureStateChange(obj);
- });
- on(/^javascript\.0\.tahoma\.devices.*\.states.core:TargetClosureState/,function(obj)
- {
- onClosureStateChange(obj);
- });
- function onClosureStateChange(obj)
- {
- if (!obj.newState.ack)
- {
- var id = obj.id;
- log("closure state changed: " + id + " -> " + JSON.stringify(obj));
- var commandName = "setClosure";
- var deviceURL = getState(id.substr(0, id.indexOf(".states.")) + ".deviceURL").val;
- var stateValue = obj.newState.val;
- var roomName = id.substr(id.indexOf('.devices.')+9);
- roomName = roomName.substr(0,roomName.indexOf('.states'));
- var payload = {'label': roomName + ' - Positioniere auf ' + stateValue + ' % - ioBroker',
- 'actions':[{
- 'deviceURL': deviceURL,
- 'commands': [{
- 'name': commandName,
- 'parameters': [ mapValueioBroker2Tahoma('core:ClosureState', stateValue) ]
- }]}]};
- send("exec/apply", payload, function(err, data)
- {
- // reset state
- //setState(obj.id, !obj.state.val);
- });
- }
- };
- on(/^javascript\.0\.tahoma\.devices.*\.states.core:SlateOrientationState/,function(obj)
- {
- if (!obj.newState.ack)
- {
- var id = obj.id;
- var commandName = "setOrientation";
- var deviceURL = getState(id.substr(0, id.indexOf(".states.")) + ".deviceURL").val;
- var stateValue = obj.newState.val;
- var roomName = id.substr(id.indexOf('.devices.')+9);
- roomName = roomName.substr(0,roomName.indexOf('.states'));
- log("slate orientation changed: " + roomName + " -> " + stateValue);
- var payload = {'label':roomName + ' - Ausrichtung ' + stateValue + ' % - ioBroker',
- 'actions':[{
- 'deviceURL': deviceURL,
- 'commands': [{
- 'name': commandName,
- 'parameters': [ mapValueioBroker2Tahoma('core:SlateOrientationState', stateValue) ]
- }]}]};
- send("exec/apply", payload, function(err, data)
- {
- // reset state
- //setState(obj.id, !obj.state.val);
- });
- }
- });
- // if connected, update state all 5 seconds
- schedule("*/5 * * * * *", function ()
- {
- // if connected, update states
- if (isConnected())
- {
- getAllStates();
- if (new Date().getTime() - lastEventTime > 60 * 1000)
- {
- // no events within last 60 seconds
- logout(function () {});
- }
- }
- });
- // update state all 5 minutes
- schedule("*/5 * * * *", function ()
- {
- log("update tahoma all 5 minutes");
- getAllStates();
- });
- onStop(function (callback) {
- logout(function (err, data)
- {
- callback();
- });
- }, 10000 /*ms*/);
- // start script
- getAllStates();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement