Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS IoT: Subscribe to Topic in Browser

I'm currently developing a Serverless App with AWS.

I want to subscribe to a topic using plain JavaScript (No Node.js, React, Angular etc.)

The IoT and IoTData SDK's doesn't support a "subscribe to topic" function.

To achieve this, i need to implement the aws-iot-device sdk, via require('aws-iot-device') (which i can't use in plain JS).

Unfortunatly this SDK only works with runtimes like Node.js or Browserify. So how can someone subscribe to a topic from browser? Is there a way to implement the SDK into plain JS?

Thanks in advance

like image 763
David Avatar asked Mar 14 '18 12:03

David


2 Answers

This is how its done, works perfectly fine:

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.11.2/moment.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/core-min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/hmac-min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/sha256-min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.min.js" type="text/javascript"></script>

cp this libaries into your html.

 function SigV4Utils(){}

      SigV4Utils.sign = function(key, msg) {
          var hash = CryptoJS.HmacSHA256(msg, key);
          return hash.toString(CryptoJS.enc.Hex);
        };

        SigV4Utils.sha256 = function(msg) {
          var hash = CryptoJS.SHA256(msg);
          return hash.toString(CryptoJS.enc.Hex);
        };

        SigV4Utils.getSignatureKey = function(key, dateStamp, regionName, serviceName) {
          var kDate = CryptoJS.HmacSHA256(dateStamp, 'AWS4' + key);
          var kRegion = CryptoJS.HmacSHA256(regionName, kDate);
          var kService = CryptoJS.HmacSHA256(serviceName, kRegion);
          var kSigning = CryptoJS.HmacSHA256('aws4_request', kService);
          return kSigning;
        };

        function createEndpoint(regionName, awsIotEndpoint, accessKey, secretKey) {
          var time = moment.utc();
          var dateStamp = time.format('YYYYMMDD');
          var amzdate = dateStamp + 'T' + time.format('HHmmss') + 'Z';
          var service = 'iotdevicegateway';
          var region = regionName;
          var secretKey = secretKey;
          var accessKey = accessKey;
          var algorithm = 'AWS4-HMAC-SHA256';
          var method = 'GET';
          var canonicalUri = '/mqtt';
          var host = awsIotEndpoint;
          var credentialScope = dateStamp + '/' + region + '/' + service + '/' + 'aws4_request';
          var canonicalQuerystring = 'X-Amz-Algorithm=AWS4-HMAC-SHA256';
          canonicalQuerystring += '&X-Amz-Credential=' + encodeURIComponent(accessKey + '/' + credentialScope);
          canonicalQuerystring += '&X-Amz-Date=' + amzdate;
          canonicalQuerystring += '&X-Amz-SignedHeaders=host';
          var canonicalHeaders = 'host:' + host + '\n';
          var payloadHash = SigV4Utils.sha256('');
          var canonicalRequest = method + '\n' + canonicalUri + '\n' + canonicalQuerystring + '\n' + canonicalHeaders + '\nhost\n' + payloadHash;
          var stringToSign = algorithm + '\n' +  amzdate + '\n' +  credentialScope + '\n' +  SigV4Utils.sha256(canonicalRequest);
          var signingKey = SigV4Utils.getSignatureKey(secretKey, dateStamp, region, service);
          var signature = SigV4Utils.sign(signingKey, stringToSign);
          canonicalQuerystring += '&X-Amz-Signature=' + signature;
          canonicalQuerystring += '&X-Amz-Security-Token=' + encodeURIComponent(AWS.config.credentials.sessionToken);
          return 'wss://' + host + canonicalUri + '?' + canonicalQuerystring;
        }
        var endpoint = createEndpoint(
        'eu-central-1',  // YOUR REGION
        'xxxxxx.iot.eu-central-1.amazonaws.com', // YOUR IoT ENDPOINT  
        accesskey, // YOUR ACCESS KEY    
        secretkey); // YOUR SECRET ACCESS KEY   

        var clientId = Math.random().toString(36).substring(7);
        var client = new Paho.MQTT.Client(endpoint, clientId);
        var connectOptions = {
          useSSL: true,
          timeout: 3,
          mqttVersion: 4,
          onSuccess: subscribe
        };
        client.connect(connectOptions);
        client.onMessageArrived = onMessage;
        client.onConnectionLost = function(e) {
           console.log(e) 
        };


        function subscribe() {
         client.subscribe("my/things/something");
         console.log("subscribed");
        }

        function onMessage(message) {
          var status = JSON.parse(message.payloadString);
        }

With this code, you can subscribe to IoT Topics in plain client side JavaScript. No Node.js, React.js or similar is needed!

like image 61
David Avatar answered Sep 19 '22 13:09

David


You can use paho js or mqttjs in the browser. The aws-iot-device sdk for javascript is a wrapper around mqttjs.

like image 37
cementblocks Avatar answered Sep 20 '22 13:09

cementblocks