Skip to content

Instantly share code, notes, and snippets.

@kntyskw
Created December 13, 2015 17:29
Show Gist options
  • Select an option

  • Save kntyskw/40d144e47ed0067e125b to your computer and use it in GitHub Desktop.

Select an option

Save kntyskw/40d144e47ed0067e125b to your computer and use it in GitHub Desktop.

Revisions

  1. kntyskw created this gist Dec 13, 2015.
    125 changes: 125 additions & 0 deletions gistfile1.txt
    Original 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);