Using Node-RED for publishing Telldus Live data to MQTT

The code in this entry will retrieve sensor and device data from Telldus Live, and then output that same data in a structured way to MQTT topics of your choice. Devices are typically various kinds of actuators, for example radio controlled mains switches.

Other applications can then subscribe to the MQTT topics, and provide for example visualisations of the sensor data, send alerts when certain conditions occur, or store the data in some kind of database.

Please note that the code in this repo is intended to go inside a Node-RED function - it is not a Node-RED module in itself.

More related information, ideas and code can be found at https://www.ptarmiganlabs.com/2015/08/31/using-node-red-for-publishing-telldus-live-data-to-mqtt/

[{"id":"6df5285e.920ad8","type":"function","name":"Read all device and sensor data from Telldus Live","func":"// Node-RED function to\n// a) extract data from TelldusLive API, and\n// b) send that data to MQTT for later consumption by various MQTT clients\n//\n// The code below relies on the following modules to be installed in the Node-RED environment, including being set up\n// in the functionGlobalContext section of the Node-RED settings.js config file (see last section of http://nodered.org/docs/writing-functions.html page)\n//\n// a) MQTT module (https://www.npmjs.com/package/mqtt)\n// b) Telldus-Live module (https://github.com/TheThingSystem/node-telldus-live)\n//\n//\n// Code below borrows a lot from the test script at https://github.com/TheThingSystem/node-telldus-live, with main addition being the use of MQTT client to publish such messages.\n//\n\n// Define Telldus Live API credentials\nvar publicKey    = '<enter your public key here>'\n  , privateKey   = '<enter your private key here>'\n  , token        = '<enter your token here>'\n  , tokenSecret  = '<enter your token secret here>'\n  , cloud\n  ;\n\nvar mqtt = context.global.mqttModule;\nvar mqttClient = mqtt.connect('mqtt://<IP of your mqtt broker>');\n\nvar batteryStatus;\n\n\n// Convenience function to format datetimes in nice human readable format\nfunction formatDate(d){\n  if(typeof d === 'number') d = new Date(d);\n  if(!(d instanceof Date)) return d;\n  function pad(n){return n<10 ? '0'+n : n}\n  return d.getFullYear()+'-'\n        + pad(d.getMonth()+1)+'-'\n        + pad(d.getDate())+' '\n        + pad(d.getHours()) + \":\"\n        + pad(d.getMinutes()) + \":\"\n        + pad(d.getSeconds());\n}\n\n\n// Create and log into new TelldusAPI object\ncloud = new context.global.telldusLive.TelldusAPI({ publicKey  : publicKey\n                                  , privateKey : privateKey });\n\ncloud.login(token, tokenSecret, function(err, user) {\n\n  if (!!err) return console.log('login error: ' + err.message);\n\n  console.log('user: ');\n  console.log(user);\n  console.log('');\n  console.log('');\n\n  // \n  cloud.getSensors(function(err, sensors) {\n    var f, i;\n\n    if (!!err) return console.log('getSensors: ' + err.message);\n\n    f = function(offset, p, s) {\n\n      return function(err, sensor) {\n        var i, prop, props, type;\n\n        if (!!err) return console.log(s + ' id=' + p.id + ': ' + err.message);\n\n        console.log('sensor #' + offset + ' ' + s + ': '); console.log(sensor);\n        props =  { temp     : [ 'temperature', 'celcius',    'meteo' ]\n                 , humidity : [ 'humidity',    'percentage', 'meteo' ]\n                 };\n\n        type = null;\n        for (i = 0; i < sensor.data.length; i++) {\n          type = props[sensor.data[i].name];\n          if (!!type) break;\n        }\n        if (!type) return;\n\n        console.log('/device/climate/' + (sensor.protocol || 'telldus') + '/' + type[2]);\n        console.log('    uuid=teldus:' + sensor.id);\n        console.log('    name: ' + sensor.name);\n        console.log('    status: ' + (p.online === '1' ? 'present' : 'absent'));\n        console.log('    battery: ' + sensor.battery);\n        console.log('    lastSample: ' + sensor.lastUpdated * 1000);\n        console.log('    lastSample: ' + '' + formatDate(sensor.lastUpdated * 1000));\n        console.log('    info:');\n\n\n        batteryStatus = '-'\n        if (sensor.battery === '253') {\n            batteryStatus = 'ok';\n        } else if (sensor.battery === '254') {\n            batteryStatus = 'unknown';\n        } else if (sensor.battery === '255') {\n            batteryStatus = 'low battery';\n        } else {\n            batteryStatus = sensor.battery;\n        }\n\n\n        mqttClient.publish('common/telldus live/' + sensor.clientName + '/sensors/' + sensor.name + '/telldus id', sensor.id);\n        mqttClient.publish('common/telldus live/' + sensor.clientName + '/sensors/' + sensor.name + '/protocol', '' + sensor.protocol);\n        mqttClient.publish('common/telldus live/' + sensor.clientName + '/sensors/' + sensor.name + '/last update', '' + sensor.lastUpdated * 1000);\n        mqttClient.publish('common/telldus live/' + sensor.clientName + '/sensors/' + sensor.name + '/last update nice', '' + formatDate(sensor.lastUpdated * 1000));\n        mqttClient.publish('common/telldus live/' + sensor.clientName + '/sensors/' + sensor.name + '/ignored', '' + sensor.ignored);\n        mqttClient.publish('common/telldus live/' + sensor.clientName + '/sensors/' + sensor.name + '/editable', '' + sensor.editable);\n        mqttClient.publish('common/telldus live/' + sensor.clientName + '/sensors/' + sensor.name + '/status', (p.online === '1' ? 'present' : 'absent'));\n        mqttClient.publish('common/telldus live/' + sensor.clientName + '/sensors/' + sensor.name + '/sensor id', sensor.sensorId);\n        mqttClient.publish('common/telldus live/' + sensor.clientName + '/sensors/' + sensor.name + '/timezone offset', '' + sensor.timezoneoffset);\n        mqttClient.publish('common/telldus live/' + sensor.clientName + '/sensors/' + sensor.name + '/battery status', batteryStatus);\n        mqttClient.publish('common/telldus live/' + sensor.clientName + '/sensors/' + sensor.name + '/mqtt last update', '' + Date.now());\n        mqttClient.publish('common/telldus live/' + sensor.clientName + '/sensors/' + sensor.name + '/mqtt last update nice', '' + formatDate(Date.now()));\n\n        for (i = 0; i < sensor.data.length; i++) {\n          prop =  props[sensor.data[i].name];\n          if (prop) console.log('      ' + prop[0] + ': \"' + prop[1] + '\"');\n        }\n        console.log('    values:');\n        for (i = 0; i < sensor.data.length; i++) {\n          prop =  props[sensor.data[i].name];\n          if (prop) console.log('      ' + prop[0] + ': ' + sensor.data[i].value);\n          mqttClient.publish('common/telldus live/' + sensor.clientName + '/sensors/' + sensor.name + '/data/' + prop[0] + '/value', sensor.data[i].value);\n          mqttClient.publish('common/telldus live/' + sensor.clientName + '/sensors/' + sensor.name + '/data/' + prop[0] + '/unit', prop[1]);\n        }\n        console.log('');\n      };\n    };\n\n    for (i = 0; i < sensors.length; i++) cloud.getSensorInfo(sensors[i], f(i, sensors[i], 'getSensorInfo'));\n\n  }).getDevices(function(err, devices) {\n    var f, i;\n\n    if (!!err) return console.log('getDevices: ' + err.message);\n\n    f = function(offset, p, s) {\n      return function(err, device) {\n        var d, type, types;\n\n        if (!!err) return console.log(s + ' id=' + p.id + ': ' + err.message);\n\n        console.log('device #' + offset + ' ' + s + ': '); console.log(device);\n        types = { 'selflearning-switch' : 'onoff'\n                , 'selflearning-dimmer' : 'dimmer'\n                , 'codeswitch'          : 'onoff' };\n\n        type = null;\n        d = device.model.split(':');\n        type = types[d[0]];\n        if (!type) return;\n\n        console.log('/device/switch' + '/' + (d[d.length - 1] || 'telldus') + '/' + type);\n        console.log('    uuid=teldus:' + device.id);\n        console.log('    perform: off, on');\n        console.log('    name: ' + device.name);\n        console.log('last update: ' + device.lastUpdated*1000);\n        console.log('    status: ' + (device.online === '0' ? 'absent' : device.status));\n        console.log('    info:');\n        if (type === 'dimmer') console.log('      dimmer: percentage');\n        console.log('    values:');\n        if (type === 'dimmer') console.log('      dimmer: ' + Math.round((1-(255 - device.statevalue)/255)*100) + '%');\n        console.log('');\n\n        mqttClient.publish('common/telldus live/' + device.client + '/devices/' + device.name + '/telldus id', device.id);\n        mqttClient.publish('common/telldus live/' + device.client + '/devices/' + device.name + '/protocol', '' + device.protocol);\n        mqttClient.publish('common/telldus live/' + device.client + '/devices/' + device.name + '/model', '' + device.model);\n        mqttClient.publish('common/telldus live/' + device.client + '/devices/' + device.name + '/state', '' + device.state);\n        mqttClient.publish('common/telldus live/' + device.client + '/devices/' + device.name + '/state value', '' + device.statevalue);\n        mqttClient.publish('common/telldus live/' + device.client + '/devices/' + device.name + '/methods', '' + device.methods);\n        mqttClient.publish('common/telldus live/' + device.client + '/devices/' + device.name + '/type', '' + type);\n        mqttClient.publish('common/telldus live/' + device.client + '/devices/' + device.name + '/client', '' + device.client);\n        mqttClient.publish('common/telldus live/' + device.client + '/devices/' + device.name + '/online', '' + device.online);\n        mqttClient.publish('common/telldus live/' + device.client + '/devices/' + device.name + '/editable', '' + device.editable);\n        mqttClient.publish('common/telldus live/' + device.client + '/devices/' + device.name + '/status', '' + (device.online === '0' ? 'absent' : device.status));\n        mqttClient.publish('common/telldus live/' + device.client + '/devices/' + device.name + '/mqtt last update', '' + Date.now());\n        mqttClient.publish('common/telldus live/' + device.client + '/devices/' + device.name + '/mqtt last update nice', '' + formatDate(Date.now()));\n\n        for (j = 0; j < device.parameter.length; j++) {\n          mqttClient.publish('common/telldus live/' + device.client + '/devices/' + device.name + '/data/' + device.parameter[j].name , '' + device.parameter[j].value);\n        }\n      };\n    };\n\n    for (i = 0; i < devices.length; i++) {\n      if (devices[i].type === 'device') cloud.getDeviceInfo(devices[i], f(i, devices[i], 'getDeviceInfo'));\n    }\n  });\n}).on('error', function(err) {\n  console.log('background error: ' + err.message);\n});\n\n\nreturn msg;","outputs":1,"noerr":0,"x":425,"y":400,"z":"6b400632.94bff8","wires":[[]]}]
mountaindude

Flow Info

created 2 years, 4 months ago

Node Types

Core
  • function (x1)

Tags

  • telldus
  • mqtt
  • tellduslive
  • homeautomation
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option