Question:
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
Answer:
This is how its done, works perfectly fine:
1 2 3 4 5 6 |
cp this libaries into your html.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
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!