Created
December 13, 2015 17:29
-
-
Save kntyskw/40d144e47ed0067e125b to your computer and use it in GitHub Desktop.
Revisions
-
kntyskw created this gist
Dec 13, 2015 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,125 @@ var ssdp = require('node-upnp-ssdp'); var UPnPDeviceClient = require('upnp-device-client'); var mqtt = require('mqtt'); var clientId = 'kenta-upnp-gateway'; var mqttOptions = { clientId: clientId }; var mqttEndpoint = 'mqtt://beam.soracom.io'; var mqttClient = mqtt.connect(mqttEndpoint, mqttOptions); var topicUpdateAccepted = '$aws/things/' + clientId + '/shadow/update/accepted'; var topicUpdateDelta = '$aws/things/' + clientId + '/shadow/update/delta'; var topicDevicesRoot = '$aws/things/' + clientId + '/devices'; var devices = {}; var addOrUpdateDevice = function(info){ var udn = info.usn.split('::')[0]; if (!devices[udn]){ var client = new UPnPDeviceClient(info.location); client.getDeviceDescription(function(err, device){ if (!err){ console.log('UPnP: Device ' + device.friendlyName + ' found'); device.client = client; device.online = true; publish(createDevicePresense(udn, device)); devices[udn] = device; } else { console.error('UPnP: ' + err); } }); } else { publish(createDevicePresense(udn, {online: true})); } }; var createDevicePresense = function(udn, device){ var presense = { devices: {} }; presense.devices[udn] = {}; for (var key in device){ if (key !== 'client'){ presense.devices[udn][key] = device[key]; } } return presense; }; var removeDevice = function(info){ var udn = info.usn.split('::')[0]; var device = devices[udn]; if (device){ console.log('UPnP: Device ' + device.friendlyName + ' gets offline'); delete devices[udn]; publish(createDevicePresense(udn, {online: false})); } }; var publish = function(state){ var event = { state: { reported: state } }; mqttClient.publish('$aws/things/kenta-upnp-gateway/shadow/update', JSON.stringify(event)); }; var getContextFromTopic = function(topic){ var path = topic.substring(topicDevicesRoot.length + 1); var elems = path.split('/'); var context = { udn: elems[0], service: elems[1], action: elems[2] }; console.log(context); return context; }; var executeAction = function(context, args){ if (devices[context.udn]){ var client = devices[context.udn].client; client.callAction(context.service, context.action, args, function(err, result) { if (!err){ console.log(result); } else { console.error(err); } }); } else { console.error("No such device found"); } }; ssdp.on('DeviceFound', addOrUpdateDevice); ssdp.on('DeviceAvailable:upnp:rootdevice', addOrUpdateDevice); ssdp.on('DeviceUnavailable:upnp:rootdevice', removeDevice); ssdp.on('DeviceError', console.error); ssdp.mSearch('upnp:rootdevice'); mqttClient.on('connect', function () { mqttClient.subscribe([topicUpdateDelta, topicUpdateAccepted, topicDevicesRoot + '/#']); }); mqttClient.on('message', function (topic, buffer) { if (topic === topicUpdateAccepted){ console.log('MQTT: Device shadow update accepted by AWS IoT'); } else if (topic === topicUpdateDelta){ console.log('MQTT: Delta is received from AWS IoT'); var delta = JSON.parse(buffer.toString()); console.log(delta); } else if (topic.indexOf(topicDevicesRoot) === 0){ console.log('MQTT: Message to a device received'); executeAction(getContextFromTopic(topic), JSON.parse(buffer.toString())); } else { console.error('MQTT: Unknown message received on topic ' + topic); console.error(buffer.toString()); } }); mqttClient.on('error', console.error);