GithubHelp home page GithubHelp logo

aws / aws-iot-device-sdk-js Goto Github PK

View Code? Open in Web Editor NEW
967.0 75.0 383.0 476 KB

SDK for connecting to AWS IoT from a device using JavaScript/Node.js

License: Apache License 2.0

JavaScript 88.76% Shell 10.45% Batchfile 0.79%

aws-iot-device-sdk-js's Introduction

New Version Available

A new AWS IoT Device SDK is now available. It is a complete rework, built to improve reliability, performance, and security. We invite your feedback!

This SDK will no longer receive feature updates, but will receive security updates.

AWS IoT SDK for JavaScript

The aws-iot-device-sdk.js package allows developers to write JavaScript applications which access the AWS IoT Platform via MQTT or MQTT over the Secure WebSocket Protocol. It can be used in Node.js environments as well as in browser applications.

Overview

This document provides instructions on how to install and configure the AWS IoT device SDK for JavaScript, and includes examples demonstrating use of the SDK APIs.

MQTT Connection

This package is built on top of mqtt.js and provides three classes: 'device', 'thingShadow' and 'jobs'. The 'device' class wraps mqtt.js to provide a secure connection to the AWS IoT platform and expose the mqtt.js interfaces upward. It provides features to simplify handling of intermittent connections, including progressive backoff retries, automatic re-subscription upon connection, and queued offline publishing with configurable drain rate.

Collection of Metrics

Beginning with Release v2.2.0 of the SDK, AWS collects usage metrics indicating which language and version of the SDK is being used. This allows us to prioritize our resources towards addressing issues faster in SDKs that see the most and is an important data point. However, we do understand that not all customers would want to report this data by default. In that case, the sending of usage metrics can be easily disabled by set options.enableMetrics to false.

Thing Shadows

The 'thingShadow' class implements additional functionality for accessing Thing Shadows via the AWS IoT API; the thingShadow class allows devices to update, be notified of changes to, get the current state of, or delete Thing Shadows from AWS IoT. Thing Shadows allow applications and devices to synchronize their state on the AWS IoT platform. For example, a remote device can update its Thing Shadow in AWS IoT, allowing a user to view the device's last reported state via a mobile app. The user can also update the device's Thing Shadow in AWS IoT and the remote device will synchronize with the new state. The 'thingShadow' class supports multiple Thing Shadows per mqtt connection and allows pass-through of non-Thing-Shadow topics and mqtt events.

Jobs

The 'jobs' class implements functionality to interact with the AWS IoT Jobs service. The IoT Job service manages deployment of IoT fleet wide tasks such as device software/firmware deployments and updates, rotation of security certificates, device reboots, and custom device specific management tasks.

Included in this package is an example 'agent'. The agent can be used either as a stand-alone program to manage installation and maintenance of files and other running processes or it can be incorporated into a customized agent to meet specific application needs.

Installation

NOTE: AWS IoT Node.js SDK will only support Node version 8.17 or above.

You can check your node version by

node -v

Installing with npm:

npm install aws-iot-device-sdk

Installing from github:

git clone https://github.com/aws/aws-iot-device-sdk-js.git
cd aws-iot-device-sdk-js
npm install

Mac-Only TLS Behavior

Please note that on Mac, once a private key is used with a certificate, that certificate-key pair is imported into the Mac Keychain. All subsequent uses of that certificate will use the stored private key and ignore anything passed in programmatically.

Examples

Device Class

// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0
var awsIot = require('aws-iot-device-sdk');

//
// Replace the values of '<YourUniqueClientIdentifier>' and '<YourCustomEndpoint>'
// with a unique client identifier and custom host endpoint provided in AWS IoT.
// NOTE: client identifiers must be unique within your AWS account; if a client attempts
// to connect with a client identifier which is already in use, the existing
// connection will be terminated.
//
var device = awsIot.device({
   keyPath: <YourPrivateKeyPath>,
  certPath: <YourCertificatePath>,
    caPath: <YourRootCACertificatePath>,
  clientId: <YourUniqueClientIdentifier>,
      host: <YourCustomEndpoint>
});

//
// Device is an instance returned by mqtt.Client(), see mqtt.js for full
// documentation.
//
device
  .on('connect', function() {
    console.log('connect');
    device.subscribe('topic_1');
    device.publish('topic_2', JSON.stringify({ test_data: 1}));
  });

device
  .on('message', function(topic, payload) {
    console.log('message', topic, payload.toString());
  });

Thing Shadow Class

// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0
var awsIot = require('aws-iot-device-sdk');

//
// Replace the values of '<YourUniqueClientIdentifier>' and '<YourCustomEndpoint>'
// with a unique client identifier and custom host endpoint provided in AWS IoT cloud
// NOTE: client identifiers must be unique within your AWS account; if a client attempts
// to connect with a client identifier which is already in use, the existing
// connection will be terminated.
//
var thingShadows = awsIot.thingShadow({
   keyPath: <YourPrivateKeyPath>,
  certPath: <YourCertificatePath>,
    caPath: <YourRootCACertificatePath>,
  clientId: <YourUniqueClientIdentifier>,
      host: <YourCustomEndpoint>
});

//
// Client token value returned from thingShadows.update() operation
//
var clientTokenUpdate;

//
// Simulated device values
//
var rval = 187;
var gval = 114;
var bval = 222;

thingShadows.on('connect', function() {
//
// After connecting to the AWS IoT platform, register interest in the
// Thing Shadow named 'RGBLedLamp'.
//
    thingShadows.register( 'RGBLedLamp', {}, function() {

// Once registration is complete, update the Thing Shadow named
// 'RGBLedLamp' with the latest device state and save the clientToken
// so that we can correlate it with status or timeout events.
//
// Thing shadow state
//
       var rgbLedLampState = {"state":{"desired":{"red":rval,"green":gval,"blue":bval}}};

       clientTokenUpdate = thingShadows.update('RGBLedLamp', rgbLedLampState  );
//
// The update method returns a clientToken; if non-null, this value will
// be sent in a 'status' event when the operation completes, allowing you
// to know whether or not the update was successful.  If the update method
// returns null, it's because another operation is currently in progress and
// you'll need to wait until it completes (or times out) before updating the
// shadow.
//
       if (clientTokenUpdate === null)
       {
          console.log('update shadow failed, operation still in progress');
       }
    });
});
thingShadows.on('status',
    function(thingName, stat, clientToken, stateObject) {
       console.log('received '+stat+' on '+thingName+': '+
                   JSON.stringify(stateObject));
//
// These events report the status of update(), get(), and delete()
// calls.  The clientToken value associated with the event will have
// the same value which was returned in an earlier call to get(),
// update(), or delete().  Use status events to keep track of the
// status of shadow operations.
//
    });

thingShadows.on('delta',
    function(thingName, stateObject) {
       console.log('received delta on '+thingName+': '+
                   JSON.stringify(stateObject));
    });

thingShadows.on('timeout',
    function(thingName, clientToken) {
       console.log('received timeout on '+thingName+
                   ' with token: '+ clientToken);
//
// In the event that a shadow operation times out, you'll receive
// one of these events.  The clientToken value associated with the
// event will have the same value which was returned in an earlier
// call to get(), update(), or delete().
//
    });

Jobs Class

// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0
var awsIot = require('aws-iot-device-sdk');

//
// Replace the values of '<YourUniqueClientIdentifier>' and '<YourCustomEndpoint>'
// with a unique client identifier and custom host endpoint provided in AWS IoT cloud
// NOTE: client identifiers must be unique within your AWS account; if a client attempts
// to connect with a client identifier which is already in use, the existing
// connection will be terminated.
//
var jobs = awsIot.jobs({
   keyPath: <YourPrivateKeyPath>,
  certPath: <YourCertificatePath>,
    caPath: <YourRootCACertificatePath>,
  clientId: <YourUniqueClientIdentifier>,
      host: <YourCustomEndpoint>
});

//
// Jobs is built on top of awsIot.device and inherits all of the same functionality.
//
jobs
  .on('connect', function() {
    console.log('connect');
    device.subscribe('topic_1');
    device.publish('topic_2', JSON.stringify({ test_data: 1}));
    });

jobs
  .on('message', function(topic, payload) {
    console.log('message', topic, payload.toString());
  });

//
// To subscribe to job execution events call the subscribeToJobs method which takes
// a callback that will be invoked when a job execution is available or an error
// occurs. The job object passed to the callback contains information about the job
// execution and methods for updating the job execution status. Details covered
// in the API documentation below.
//
jobs.subscribeToJobs(thingName, function(err, job) {
   if (isUndefined(err)) {
      console.log('default job handler invoked, jobId: ' + job.id.toString());
      console.log('job document: ' + job.document);
   }
   else {
      console.error(err);
   }
});

jobs.subscribeToJobs(thingName, 'customJob', function(err, job) {
   if (isUndefined(err)) {
      console.log('customJob operation handler invoked, jobId: ' + job.id.toString());
      console.log('job document: ' + job.document);
   }
   else {
      console.error(err);
   }
});

//
// After calling subscribeToJobs for each operation on a particular thing call
// startJobNotifications to cause any existing queued job executions for the given
// thing to be published to the appropriate subscribeToJobs handler. Only needs
// to be called once per thing.
//
jobs.startJobNotifications(thingName, function(err) {
   if (isUndefined(err)) {
      console.log('job notifications initiated for thing: ' + thingName);
   }
   else {
      console.error(err);
   }
});

API Documentation


awsIot.device(options)

Returns a wrapper for the mqtt.Client() class, configured for a TLS connection with the AWS IoT platform and with arguments as specified in options. The AWSIoT-specific arguments are as follows:

  • host: the AWS IoT endpoint you will use to connect
  • clientId: the client ID you will use to connect to AWS IoT
  • certPath: path of the client certificate file
  • keyPath: path of the private key file associated with the client certificate
  • caPath: path of your CA certificate file
  • clientCert: same as certPath, but can also accept a buffer containing client certificate data
  • privateKey: same as keyPath, but can also accept a buffer containing private key data
  • caCert: same as caPath, but can also accept a buffer containing CA certificate data
  • autoResubscribe: set to 'true' to automatically re-subscribe to topics after reconnection (default 'true')
  • offlineQueueing: set to 'true' to automatically queue published messages while offline (default 'true')
  • offlineQueueMaxSize: enforce a maximum size for the offline message queue (default 0, e.g. no maximum)
  • offlineQueueDropBehavior: set to 'oldest' or 'newest' to define drop behavior on a full queue when offlineQueueMaxSize > 0
  • drainTimeMs: the minimum time in milliseconds between publishes when draining after reconnection (default 250)
  • baseReconnectTimeMs: the base reconnection time in milliseconds (default 1000)
  • maximumReconnectTimeMs: the maximum reconnection time in milliseconds (default 128000)
  • minimumConnectionTimeMs: the minimum time in milliseconds that a connection must be maintained in order to be considered stable (default 20000)
  • protocol: the connection type, either 'mqtts' (default), 'wss' (WebSocket/TLS), or 'wss-custom-auth' (WebSocket/TLS with custom authentication). Note that when set to 'wss', values must be provided for the Access Key ID and Secret Key in either the following options or in environment variables as specified in WebSocket Configuration. When set to 'wss-custom-auth', valid headers must be provided as specified in Custom Auth
  • websocketOptions: if protocol is set to 'wss', you can use this parameter to pass additional options to the underlying WebSocket object; these options are documented here.
  • filename: used to load credentials from the file different than the default location when protocol is set to 'wss'. Default value is '~/.aws/credentials'
  • profile: used to specify which credential profile to be used when protocol is set to 'wss'. Default value is 'default'
  • accessKeyId: used to specify the Access Key ID when protocol is set to 'wss'. Overrides the environment variable AWS_ACCESS_KEY_ID and AWS_ACCESS_KEY_ID from filename if set.
  • secretKey: used to specify the Secret Key when protocol is set to 'wss'. Overrides the environment variable AWS_SECRET_ACCESS_KEYand AWS_SECRET_ACCESS_KEY from filename if set.
  • sessionToken: (required when authenticating via Cognito, optional otherwise) used to specify the Session Token when protocol is set to 'wss'. Overrides the environment variable AWS_SESSION_TOKEN if set.
  • region: used to specify AWS account region (e.g. 'us-east-1') when protocol is set to wss. If undefined, a value is derived from host.
  • customAuthHeaders: used to specify your custom authorization headers when protocol is set to 'wss-custom-auth'. The fields 'X-Amz-CustomAuthorizer-Name', 'X-Amz-CustomAuthorizer-Signature', and the field for your token name are required.
  • servername: used for SNI. If undefined, a value is derived from host.
  • port: used to specify which port to connect to. If undefined, 443 or 8883 will be chosen depending on protocol.
  • customAuthQueryString: used to specify the token credentials in a query string for custom authorization when protocol is set to wss-custom-auth. More info can be found here.
  • keepalive: used to specify the time interval for each ping request. Default is set to 300 seconds to connect to AWS IoT.
  • enableMetrics: used to report SDK version usage metrics. It is set to true by default. To disable metrics collection, set value to false.
  • debug: set to 'true' for verbose logging (default 'false').

All certificates and keys must be in PEM format.

options also contains arguments specific to mqtt. See [the mqtt client documentation] (https://github.com/mqttjs/MQTT.js/blob/master/README.md#client) for details of these arguments. Note, AWS IoT doesn't support retained messages; setting retain flag to 'true' for message publishing, including Last Will and Testament messages, will result in connection termination. For AWS IoT protocol specifics, please visit here.

Supports all events emitted by the mqtt.Client() class.

awsIot.device#updateWebSocketCredentials(accessKeyId, secretKey, sessionToken, expiration)

Update the credentials set used to authenticate via WebSocket/SigV4. This method is designed to be invoked during the callback of the getCredentialsForIdentity method in the AWS SDK for JavaScript.

  • accessKeyId: the latest Access Key to use when connecting via WebSocket/SigV4
  • secretKey: the latest Secret Key to use when connecting via WebSocket/SigV4
  • sessionToken: the latest Session Token to use when connecting via WebSocket/SigV4
  • expiration: the time this credentials set will expire

awsIot.thingShadow(deviceOptions, thingShadowOptions)

The thingShadow class wraps an instance of the device class with additional functionality to operate on Thing Shadows via the AWS IoT API. The arguments in deviceOptions include all those in the device class. thingShadowOptions has the addition of the following arguments specific to the thingShadow class:

  • operationTimeout: the timeout for thing operations (default 10 seconds)

Supports all events emitted by the mqtt.Client() class; however, the semantics for the message event are slightly different and additional events are available as described below:

Event 'message'

function(topic, message) {}

Emitted when a message is received on a topic not related to any Thing Shadows:

  • topic topic of the received packet
  • message payload of the received packet

Event 'status'

function(thingName, stat, clientToken, stateObject) {}

Emitted when an operation update|get|delete completes.

  • thingName name of the Thing Shadow for which the operation has completed
  • stat status of the operation accepted|rejected
  • clientToken the operation's clientToken
  • stateObject the stateObject returned for the operation

Applications can use clientToken values to correlate status events with the operations that they are associated with by saving the clientTokens returned from each operation.

Event 'delta'

function(thingName, stateObject) {}

Emitted when a delta has been received for a registered Thing Shadow.

  • thingName name of the Thing Shadow that has received a delta
  • stateObject the stateObject returned for the operation

Event 'foreignStateChange'

function(thingName, operation, stateObject) {}

Emitted when a different client's update or delete operation is accepted on the shadow.

  • thingName name of the Thing Shadow for which the operation has completed
  • operation operation performed by the foreign client update|delete
  • stateObject the stateObject returned for the operation

This event allows an application to be aware of successful update or delete operations performed by different clients.

Event 'timeout'

function(thingName, clientToken) {}

Emitted when an operation update|get|delete has timed out.

  • thingName name of the Thing Shadow that has received a timeout
  • clientToken the operation's clientToken

Applications can use clientToken values to correlate timeout events with the operations that they are associated with by saving the clientTokens returned from each operation.


awsIot.thingShadow#register(thingName, [options], [callback] )

Register interest in the Thing Shadow named thingName. The thingShadow class will subscribe to any applicable topics, and will fire events for the Thing Shadow until awsIot.thingShadow#unregister() is called with thingName. options can contain the following arguments to modify how this Thing Shadow is processed:

  • ignoreDeltas: set to true to not subscribe to the delta sub-topic for this Thing Shadow; used in cases where the application is not interested in changes (e.g. update only.) (default false)
  • persistentSubscribe: set to false to unsubscribe from all operation sub-topics while not performing an operation (default true)
  • discardStale: set to false to allow receiving messages with old version numbers (default true)
  • enableVersioning: set to true to send version numbers with shadow updates (default true)

The persistentSubscribe argument allows an application to get faster operation responses at the expense of potentially receiving more irrelevant response traffic (i.e., response traffic for other clients who have registered interest in the same Thing Shadow). When persistentSubscribe is set to false, operation sub-topics are only subscribed to during the scope of that operation; note that in this mode, update, get, and delete operations will be much slower; however, the application will be less likely to receive irrelevant response traffic.

The discardStale argument allows applications to receive messages which have obsolete version numbers. This can happen when messages are received out-of-order; applications which set this argument to false should use other methods to determine how to treat the data (e.g. use a time stamp property to know how old/stale it is).

If enableVersioning is set to true, version numbers will be sent with each operation. AWS IoT maintains version numbers for each shadow, and will reject operations which contain the incorrect version; in applications where multiple clients update the same shadow, clients can use versioning to avoid overwriting each other's changes.

If the callback parameter is provided, it will be invoked after registration is complete (i.e., when subscription ACKs have been received for all shadow topics). Applications should wait until shadow registration is complete before performing update/get/delete operations.


awsIot.thingShadow#unregister(thingName)

Unregister interest in the Thing Shadow named thingName. The thingShadow class will unsubscribe from all applicable topics and no more events will be fired for thingName.


awsIot.thingShadow#update(thingName, stateObject)

Update the Thing Shadow named thingName with the state specified in the JavaScript object stateObject. thingName must have been previously registered using awsIot.thingShadow#register(). The thingShadow class will subscribe to all applicable topics and publish stateObject on the update sub-topic.

This function returns a clientToken, which is a unique value associated with the update operation. When a 'status' or 'timeout' event is emitted, the clientToken will be supplied as one of the parameters, allowing the application to keep track of the status of each operation. The caller may create their own clientToken value; if stateObject contains a clientToken property, that will be used rather than the internally generated value. Note that it should be of atomic type (i.e. numeric or string). This function returns 'null' if an operation is already in progress.


awsIot.thingShadow#get(thingName, [clientToken])

Get the current state of the Thing Shadow named thingName, which must have been previously registered using awsIot.thingShadow#register(). The thingShadow class will subscribe to all applicable topics and publish on the get sub-topic.

This function returns a clientToken, which is a unique value associated with the get operation. When a 'status or 'timeout' event is emitted, the clientToken will be supplied as one of the parameters, allowing the application to keep track of the status of each operation. The caller may supply their own clientToken value (optional); if supplied, the value of clientToken will be used rather than the internally generated value. Note that this value should be of atomic type (i.e. numeric or string). This function returns 'null' if an operation is already in progress.


awsIot.thingShadow#delete(thingName, [clientToken])

Delete the Thing Shadow named thingName, which must have been previously registered using awsIot.thingShadow#register(). The thingShadow class will subscribe to all applicable topics and publish on the delete sub-topic.

This function returns a clientToken, which is a unique value associated with the delete operation. When a 'status' or 'timeout' event is emitted, the clientToken will be supplied as one of the parameters, allowing the application to keep track of the status of each operation. The caller may supply their own clientToken value (optional); if supplied, the value of clientToken will be used rather than the internally generated value. Note that this value should be of atomic type (i.e. numeric or string). This function returns 'null' if an operation is already in progress.


awsIot.thingShadow#publish(topic, message, [options], [callback])

Identical to the mqtt.Client#publish() method, with the restriction that the topic may not represent a Thing Shadow. This method allows the user to publish messages to topics on the same connection used to access Thing Shadows.


awsIot.thingShadow#subscribe(topic, [options], [callback])

Identical to the mqtt.Client#subscribe() method, with the restriction that the topic may not represent a Thing Shadow. This method allows the user to subscribe to messages from topics on the same connection used to access Thing Shadows.


awsIot.thingShadow#unsubscribe(topic, [callback])

Identical to the mqtt.Client#unsubscribe() method, with the restriction that the topic may not represent a Thing Shadow. This method allows the user to unsubscribe from topics on the same used to access Thing Shadows.


awsIot.thingShadow#end([force], [callback])

Invokes the mqtt.Client#end() method on the MQTT connection owned by the thingShadow class. The force and callback parameters are optional and identical in function to the parameters in the mqtt.Client#end() method.


awsIot.jobs(deviceOptions)

The jobs class wraps an instance of the device class with additional functionality to handle job execution management through the AWS IoT Jobs platform. Arguments in deviceOptions are the same as those in the device class and the jobs class supports all of the same events and functions as the device class.

The jobs class also supports the following methods:


awsIot.jobs#subscribeToJobs(thingName, [operationName], callback)

Subscribes to job execution notifications for the thing named thingName. If operationName is specified then the callback will only be called when a job ready for execution contains a property called operation in its job document with a value matching operationName. If operationName is omitted then the callback will be called for every job ready for execution that does not match another subscribeToJobs subscription.

  • thingName name of the Thing to receive job execution notifications
  • operationName optionally filter job execution notifications to jobs with a value for the operation property that matches operationName
  • callback - function (err, job) callback for when a job execution is ready for processing or an error occurs - err a subscription error or an error that occurs when client is disconnecting - job an object that contains job execution information and functions for updating job execution status.

awsIot.jobs#unsubscribeFromJobs(thingName, [operationName], callback)

Unsubscribes from job execution notifications for the thing named thingName having operations with a value of the given operationName. If operationName is omitted then the default handler for the thing with the given name is unsubscribed.

  • thingName name of the Thing to cancel job execution notifications for
  • operationName optional name of previously subscribed operation names
  • callback - function (err) callback for when the unsubscribe operation completes

awsIot.jobs#startJobNotifications(thingName, [callback])

Causes any existing queued job executions for the given thing to be published to the appropriate subscribeToJobs handler. Only needs to be called once per thing.

  • thingName name of the Thing to cancel job execution notifications for
  • callback - function (err) callback for when the startJobNotifications operation completes

job

Object that contains job execution information and functions for updating job execution status.


job.document

The JSON document describing details of the job to be executed eg.

{
    "operation": "install",
    "otherProperty": "value",
    ...
}

job.id

Returns the job id.


job.operation

Returns the job operation from the job document. Eg. 'install', 'reboot', etc.


job.status

Returns the current job status according to AWS Orchestra.

{
    "status":"IN_PROGRESS|QUEUED",
    "statusDetails": {
        "progress":"50%"
    }
}

job.inProgress([statusDetails],[callback])

Update the status of the job execution to be IN_PROGRESS for the thing associated with the job.

  • statusDetails optional document describing the status details of the in progress job e.g.
{
    "string": "string",
    "progress": "50%"
}
  • callback - function(err) optional callback for when the operation completes, err is null if no error occurred

job.failed([statusDetails],[callback])

Update the status of the job execution to be FAILED for the thing associated with the job.

  • statusDetails optional document describing the status details of the in progress job e.g.
{
    "string": "string",
    "progress": "0%"
}
  • callback - function(err) optional callback for when the operation completes, err is null if no error occurred

job.succeeded([statusDetails],[callback])

Update the status of the job execution to be SUCCESS for the thing associated with the job.

  • statusDetails optional document describing the status details of the in progress job e.g.
{
    "string": "string",
    "progress": "100%"
}
  • callback - function(err) optional callback for when the operation completes, err is null if no error occurred

Connection Types

This SDK supports three types of connections to the AWS IoT platform:

  • MQTT over TLS with mutual certificate authentication using port 8883
  • MQTT over WebSocket/TLS with SigV4 authentication using port 443
  • MQTT over WebSocket/TLS using a custom authorization function to authenticate

The default connection type is MQTT over TLS with mutual certificate authentication; to configure a WebSocket/TLS connection, set the protocol option to wss when instantiating the awsIot.device() or awsIot.thingShadow() classes. To use custom auth, set the protocol option to wss-custom-auth.

Custom Authorization Configuration

To use custom authorization, you must first set up an authorizer function in Lambda and register it with IoT. Once you do, you will be able to authenticate using this function. There are two ways to use custom auth:

  • set the customAuthHeaders option to your headers object when instantiating the awsIotDevice() or awsIot.thingShadow() classes. The headers object is an object containing the header name and values as key-value pairs:
    {
        'X-Amz-CustomAuthorizer-Name': 'TestAuthorizer',
        'X-Amz-CustomAuthorizer-Signature': 'signature',
        'TestAuthorizerToken': 'token'
    }
  • set the customAuthQueryString option to your headers object when instantiating the awsIotDevice() class. The query string is a string containing the values as key-value pairs:
    '?X-Amz-CustomAuthorizer-Name=TestAuthorizer&X-Amz-CustomAuthorizer-Signature=signature&TestAuthorizerToken=token'

Example Programs

The 'examples' directory contains several programs which demonstrate usage of the AWS IoT APIs:

  • device-example.js: demonstrate simple MQTT publish and subscribe operations.

  • echo-example.js: test Thing Shadow operation by echoing all delta state updates to the update topic; used in conjunction with the AWS IoT Console to verify connectivity with the AWS IoT platform.

  • thing-example.js: use a Thing Shadow to automatically synchronize state between a simulated device and a control application.

  • thing-passthrough-example.js: demonstrate use of a Thing Shadow with pasthrough of standard MQTT publish and subscribe messages.

  • temperature-control/temperature-control.js: an interactive device simulation which uses Thing Shadows.

  • jobs-example.js: receive example job execution messages and update job execution status.

  • jobs-agent.js: example agent to handle standard operations such as reboot, report system status, and shutdown. It also handles installation of files including but not limited to configuration files, program updates and security certificates. It also can install and launch other programs and manage their executions (start, stop and restart).

The example programs use command line parameters to set options. To see the available options, run the program and specify the '-h' option as follows:

node examples/<EXAMPLE-PROGRAM> -h

NOTE: You have to use the certificate created in the same region as your host end point. You will also need to use unique custom endpoint with '-H' command line option when connect examples to IoT cloud.

WebSocket Configuration

The example programs can be configured to use a WebSocket/TLS connection to the AWS IoT platform by adding '--protocol=wss' to the command line to override the default setting of 'mqtts'.

  -P, --protocol=PROTOCOL          connect using PROTOCOL (mqtts|wss)

When using a WebSocket/TLS connection, you have the following options to set credentials.

Export variables to system environment

export AWS_ACCESS_KEY_ID=[a valid AWS access key ID]
export AWS_SECRET_ACCESS_KEY=[a valid AWS secret access key]

Load IAM credentials from shared credential file

The default shared credential file is located in ~/.aws/credentials for Linux users and %UserProfile%\.aws\credentials for Windows users. This could be configured using AWS CLI visit the AWS CLI home page. Alternatively, you could provide credential file in different path or another profile by specifying in the awsIot.device(options) .

The values of AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY must contain valid AWS Identity and Access Management (IAM) credentials. For more information about AWS IAM, visit the AWS IAM home page.

Certificate Configuration

When not configured to use a WebSocket/TLS connection, the example programs require a client certificate and private key (created using either the AWS IoT Console or the AWS IoT CLI) in order to authenticate with AWS IoT. Each example program uses command line options to specify the names and/or locations of certificates as follows:

Specify a directory containing default-named certificates

  -f, --certificate-dir=DIR        look in DIR for certificates

The --certificate-dir (-f) option will read all certificate and key files from the directory specified. Default certificate/key file names are as follows:

Specify certificate names and locations individually

  -k, --private-key=FILE           use FILE as private key
  -c, --client-certificate=FILE    use FILE as client certificate
  -a, --ca-certificate=FILE        use FILE as CA certificate

The '-f' (certificate directory) option can be combined with these so that you don't have to specify absolute pathnames for each file.

Use a configuration file

The AWS IoT Console can generate JSON configuration data specifying the parameters required to connect a device to the AWS IoT Platform. The JSON configuration data includes pathnames to certificates, the hostname and port number, etc... The command line option '--configuration-file (-F)' is used when reading parameters from a configuration file.

  -F, --configuration-file=FILE    use FILE (JSON format) for configuration

The configuration file is in JSON format, and may contain the following properties:

  • host - the host name to connect to
  • port - the port number to use when connecting to the host (8883 for AWS IoT with client certificate)
  • clientId - the client ID to use when connecting
  • privateKey - file containing the private key
  • clientCert - file containing the client certificate
  • caCert - file containing the CA certificate
  • thingName - thing name to use
Tips for using JSON configuration files
  • The '-f' (certificate directory) and '-F' (configuration file) options can be combined so that you don't have to use absolute pathnames in the configuration file.
  • When using a configuration file to run any of the example programs other than echo-example.js, you must specify different client IDs for each process using the '-i' command line option.

device-example.js

device-example.js is run as two processes which communicate with one another via the AWS IoT platform using MQTT publish and subscribe. The command line option '--test-mode (-t)' is used to set which role each process performs. It's easiest to run each process in its own terminal window so that you can see the output generated by each. Note that in the following examples, all certificates are located in the ~/certs directory and have the default names as specified in the Certificate Configuration section.

Terminal Window 1

node examples/device-example.js -f ~/certs --test-mode=1 -H <PREFIX>.iot.<REGION>.amazonaws.com

Terminal Window 2

node examples/device-example.js -f ~/certs --test-mode=2 -H <PREFIX>.iot.<REGION>.amazonaws.com

thing-example.js

Similar to device-example.js, thing-example.js is also run as two processes which communicate with one another via the AWS IoT platform. thing-example.js uses a Thing Shadow to synchronize state between the two processes, and the command line option '--test-mode (-t)' is used to set which role each process performs. As with device-example.js, it's best to run each process in its own terminal window or on separate hosts. In this example, the example programs are configured to use WebSocket/TLS connections to the AWS IoT platform as specified in the WebSocket Configuration.

Terminal Window 1

node examples/thing-example.js -P=wss --test-mode=1 -H <PREFIX>.iot.<REGION>.amazonaws.com

Terminal Window 2

node examples/thing-example.js -P=wss --test-mode=2 -H <PREFIX>.iot.<REGION>.amazonaws.com

thing-passthrough-example.js

Similar to thing-example.js, thing-passthrough-example.js is also run as two processes which communicate with one another via the AWS IoT platform. thing-passthrough-example.js uses a Thing Shadow to synchronize state from one process to another, and uses MQTT publish/subscribe to send information in the other direction. The command line option '--test-mode (-t)' is used to set which role each process performs. As with thing-example.js, it's best to run each process in its own terminal window. Note that in the following examples, all certificates are located in the ~/certs directory and have the default names as specified in the Certificate Configuration section.

Terminal Window 1

node examples/thing-passthrough-example.js -f ~/certs --test-mode=1 -H <PREFIX>.iot.<REGION>.amazonaws.com

Terminal Window 2

node examples/thing-passthrough-example.js -f ~/certs --test-mode=2 -H <PREFIX>.iot.<REGION>.amazonaws.com

echo-example.js

echo-example.js is used in conjunction with the AWS IoT Console to verify connectivity with the AWS IoT platform and to perform interactive observation of Thing Shadow operation. In the following example, the program is run using the configuration file '../config.json', and the certificates are located in the '~/certs' directory. Here, the '-f' (certificate directory) and '-F' (configuration file) options are combined so that the configuration file doesn't need to contain absolute pathnames.

node examples/echo-example.js -F ../config.json -f ~/certs --thing-name testThing1

temperature-control.js

temperature-control.js is an interactive simulation which demonstrates how Thing Shadows can be used to easily synchronize applications and internet-connected devices.

Like thing-example.js, temperature-control.js runs in two separate terminal windows and is configured via command-line options; in the following example, all certificates are located in the ~/certs directory and have the default names as specified in the Certificate Configuration section. The process running with '--test-mode=2' simulates an internet-connected temperature control device, and the process running with '--test-mode=1' simulates a mobile application which is monitoring/controlling it. The processes may be run on different hosts if desired.

Installing Dependencies

temperature-control.js uses the blessed.js and blessed-contrib.js libraries to provide an interactive terminal interface; it looks best on an 80x25 terminal with a black background and white or green text and requires UTF-8 character encoding. You'll need to install these libraries in the examples/temperature-control directory as follows:

cd examples/temperature-control
npm install

Running the Simulation - Terminal Window 1

node examples/temperature-control/temperature-control.js -f ~/certs --test-mode=1 -H <PREFIX>.iot.<REGION>.amazonaws.com

temperature-control.js, 'mobile application' mode

Running the Simulation - Terminal Window 2

node examples/temperature-control/temperature-control.js -f ~/certs --test-mode=2 -H <PREFIX>.iot.<REGION>.amazonaws.com

temperature-control.js, 'device' mode

Using the simulation

The simulated temperature control device has two controls; Setpoint and Status. Status controls whether or not the device is active, and Setpoint controls the interior temperature the device will attempt to achieve. In addition, the device reports the current interior and exterior temperatures as well as its operating state (heating, cooling, or stopped).

Two Thing Shadows are used to connect the simulated device and mobile application; one contains the controls and the other contains the measured temperatures and operating state. Both processes can update the controls, but only the device can update the measured temperatures and the operating state.

Controlling the simulation is done using the up, down, left, right, and Enter keys as follows:

  • up increase the Setpoint
  • down decrease the Setpoint
  • left move left on the menu bar
  • right move right on the menu bar
  • Enter select the current menu option
Operating State

The operating state of the device is indicated by the color of the Interior temperature field as follows:

  • Red: heating
  • Cyan: cooling
  • White: stopped

The following example shows the temperature control simulation in 'device' mode while the operating state is 'heating'.

temperature-control.js, 'device' mode, 'heating' operating state

Log

The log window displays events of interest, e.g. network connectivity, Status toggles, re-synchronization with the Thing Shadow, etc...

Menu Options
  • Mode: Toggle the device Status. Status can be controlled from both the simulated device and the mobile application.
  • Network: Toggle the network connectivity of the device or mobile application; this can be used to observe how both sides re-synchronize when connectivity is restored.

In this example, the mobile application is disconnected from the network. Although it has requested that the Setpoint be lowered to 58 degrees, the command can't be sent to the device as there is no network connectivity, so the operating state still shows as 'stopped'. When the mobile application is reconnected to the network, it will attempt to update the Thing Shadow for the device's controls; if no control changes have been made on the device side during the disconnection period, the device will synchronize to the mobile application's requested state; otherwise, the mobile application will re- synchronize to the device's current state.

temperature-control.js, 'mobile application' mode, network disconnected

Exiting the Simulation

The simulation can be exited at any time by pressing q, Ctrl+c, or by selecting 'exit' on the menu bar.

jobs-example.js

jobs-example.js, like the echo-example.js can receive messages via the AWS IoT Console to verify connectivity with the AWS IoT platform. But it can also receive and process job executions initiated through the AWS IoT device jobs management platform. See the AWS IoT Jobs documentation here for more information on creating and deploying jobs.

Running the jobs-example

node examples/jobs-example.js -f ~/certs -H <PREFIX>.iot.<REGION>.amazonaws.com -T thingName

jobs-agent.js

jobs-agent.js can be run on a device as-is or it can be modified to suit specific use cases. Example job documents are provided below. For more information see the AWS IoT connected device management documentation here.

Running the jobs-agent

node examples/jobs-agent.js -f ~/certs -H <PREFIX>.iot.<REGION>.amazonaws.com -T agentThingName

Using the jobs-agent

systemStatus operation

The jobs-agent will respond to the AWS IoT jobs management platform with system status information when it receives a job execution notification with a job document that looks like this:

 {
  "operation": "systemStatus"
 }
reboot operation

When the jobs-agent receives a reboot job document it will attempt to reboot the device it is running on while sending updates on its progress to the AWS IoT jobs management platform. After the reboot the job execution status will be marked as IN_PROGRESS until the jobs-agent is also restarted at which point the status will be updated to SUCCESS. To avoid manual steps during reboot it is suggested that device be configured to automatically start the jobs-agent at device startup time. Job document format:

 {
  "operation": "reboot"
 }
shutdown operation

When the jobs-agent receives a shutdown job document it will attempt to shutdown the device.

 {
  "operation": "shutdown"
 }
install operation

When the jobs-agent receives an install job document it will attempt to install the files specified in the job document. An install job document should follow this general format.

 {
  "operation": "install",
  "packageName": "uniquePackageName",
  "workingDirectory": "../jobs-example-directory",
  "launchCommand": "node jobs-example.js -f ~/certs -H <PREFIX>.iot.<REGION>.amazonaws.com -T thingName",
  "autoStart": "true",
  "files": [
    {
      "fileName": "jobs-example.js",
      "fileVersion": "1.0.2.10",
      "fileSource": {
        "url": "https://some-bucket.s3.amazonaws.com/jobs-example.js"
      },
      "checksum": {
        "inline": {
          "value": "9569257356cfc5c7b2b849e5f58b5d287f183e08627743498d9bd52801a2fbe4"
        },
        "hashAlgorithm": "SHA256"
      }
    },
    {
      "fileName": "config.json",
      "fileSource": {
        "url": "https://some-bucket.s3.amazonaws.com/config.json"
      }
    }
  ]
}
  • packageName: Each install operation must have a unique package name. If the packageName matches a previous install operation then the new install operation overwrites the previous one.
  • workingDirectory: Optional property for working directory
  • launchCommand: Optional property for launching an application/package. If omitted copy files only.
  • autoStart: If set to true then agent will execute launch command when agent starts up.
  • files: Specifies files to be installed
    • fileName: Name of file as written to file system
    • fileSource.url: Location of file to be downloaded from
    • checksum: Optional file checksum
      • inline.value: Checksum value
      • hashAlgorithm: Checksum hash algorithm used
start operation

When the jobs-agent receives a start job document it will attempt to startup the specified package.

 {
  "operation": "start",
  "packageName": "somePackageName"
 }
stop operation

When the jobs-agent receives a stop job document it will attempt to stop the specified package.

 {
  "operation": "stop",
  "packageName": "somePackageName"
 }
restart operation

When the jobs-agent receives a restart job document it will attempt to restart the specified package.

 {
  "operation": "restart",
  "packageName": "somePackageName"
 }

Browser Applications

This SDK can be packaged to run in a browser using browserify or webpack, and includes helper scripts and example application code to help you get started writing browser applications that use AWS IoT.

Background

Browser applications connect to AWS IoT using MQTT over the Secure WebSocket Protocol. There are some important differences between Node.js and browser environments, so a few adjustments are necessary when using this SDK in a browser application.

When running in a browser environment, the SDK doesn't have access to the filesystem or process environment variables, so these can't be used to store credentials. While it might be possible for an application to prompt the user for IAM credentials, the Amazon Cognito Identity Service provides a more user-friendly way to retrieve credentials which can be used to access AWS IoT. The temperature-monitor browser example application illustrates this use case.

Using SDK with browserify

Installing browserify

This SDK could also work with web applications using browserify. First, you'll need to make sure that browserify is installed. The following instructions and the scripts in this package assume that it is installed globally, as with:

npm install -g browserify

Browser Application Utility

This SDK includes a utility script called scripts/browserize.sh. This script can create a browser bundle containing both the AWS SDK for JavaScript and this SDK, or you can use it to create application bundles for browser applications, like the ones under the examples/browser directory. For Windows user who does not want to use bash shell, the SDK also includes batch file windows-browserize.bat which does the same job as browserize.sh but able to run in Windows CMD. To create the combined AWS SDK browser bundle, run this command in the SDK's top-level directory:

npm run-script browserize

This command will create a browser bundle in browser/aws-iot-sdk-browser-bundle.js. The browser bundle makes both the aws-sdk and aws-iot-device-sdk modules available so that you can require them from your browserified application bundle.

NOTE: For Windows user who running scripts in CMD, since batch script file does not work well with NPM package script, Windows user could just call script directly to replace npm run-script browserize. This also applies for example applications demonstrated below.

.\scripts\windows-browserize.bat

Creating Application Bundles

You can also use the scripts/browserize.sh script to browserify your own applications and use them with the AWS SDK browser bundle. For example, to prepare the temperature-monitor browser example application for use, run this command in the SDK's top-level directory:

npm run-script browserize examples/browser/temperature-monitor/index.js

This command does two things. First, it creates an application bundle from examples/browser/temperature-monitor/index.js and places it in examples/browser/temperature-monitor/bundle.js. Second, it copies the browser/aws-iot-sdk-browser-bundle.js into your application's directory where it can be used, e.g.:

<script src="aws-iot-sdk-browser-bundle.js"></script>
<script src="bundle.js"></script>

Temperature Monitor Browser Example Application

This SDK includes a companion browser application to the Temperature Control Example Application. The browser application allows you to monitor the status of the simulated temperature control device.

  1. Follow the instructions to install the Temperature Control Example Application

  2. In order for the browser application to be able to authenticate and connect to AWS IoT, you'll need to configure a Cognito Identity Pool. In the Amazon Cognito console, use Amazon Cognito to create a new identity pool, and allow unauthenticated identities to connect. Obtain the PoolID constant. Make sure that the policy attached to the unauthenticated role has permissions to access the required AWS IoT APIs. More information about AWS IAM roles and policies can be found here.

  3. Edit examples/browser/temperature-monitor/aws-configuration.js, and replace the values of poolId and region with strings containing the ID of the Cognito Identity Pool and your AWS region (e.g., 'us-east-1') from the previous step.

  4. Create the application browser bundle by executing the following command in the top-level directory of the SDK:

    npm run-script browserize examples/browser/temperature-monitor/index.js
  5. Start an instance of the device simulation using:

    node examples/temperature-control/temperature-control.js -f ~/certs --test-mode=2 -H <PREFIX>.iot.<REGION>.amazonaws.com

NOTE: Although the above example shows connecting using a certificate/private key set, you can use any of the command line options described in the Example Programs Section.

  1. Open examples/browser/temperature-monitor/index.html in your web browser. It should connect to AWS IoT and began displaying the status of the simulated temperature control device you started in the previous step. If you change the device's settings, the browser window should update and display the latest status values.

Lifecycle Event Monitor Browser Example Application

This SDK includes a browser application which demonstrates the functionality of AWS IoT lifecycle events. AWS IoT generates lifecycle events whenever clients connect or disconnect; applications can monitor these and take action when clients connect or disconnect from AWS IoT. Follow these instructions to run the application:

  1. In order for the browser application to be able to authenticate and connect to AWS IoT, you'll need to configure a Cognito Identity Pool. In the Amazon Cognito console, use Amazon Cognito to create a new identity pool, and allow unauthenticated identities to connect. Obtain the PoolID constant. Make sure that the policy attached to the unauthenticated role has permissions to access the required AWS IoT APIs. More information about AWS IAM roles and policies can be found here.

  2. Edit examples/browser/lifecycle/aws-configuration.js, and replace the values of poolId and region with strings containing the ID of the Cognito Identity Pool and your AWS region (e.g., 'us-east-1') from the previous step.

  3. Create the application browser bundle by executing the following command in the top-level directory of the SDK:

    npm run-script browserize examples/browser/lifecycle/index.js
  4. Open examples/browser/lifecycle/index.html in your web browser. After connecting to AWS IoT, it should display 'connected clients'.

  5. Start programs which connect to AWS IoT (e.g., the example programs in this package). Make sure that these programs are connecting to the same AWS region that your Cognito Identity Pool was created in. The browser application will display a green box containing the client ID of each client which connects; when the client disconnects, the box will disappear.

  6. If a DynamoDB table named LifecycleEvents exists in your account and has a primary key named clientId, the lifecycle event browser monitor browser application will display the client ID contained in each row. By updating this table using an AWS IoT rule triggered by lifecycle events, you can maintain a persistent list of all of the currently connected clients within your account.

MQTT Explorer Browser Example Application

This SDK includes a browser application which implements a simple interactive MQTT client. You can use this application to subscribe to a topic and view the messages that arrive on it, or to publish to a topic. Follow these instructions to run the application:

  1. In order for the browser application to be able to authenticate and connect to AWS IoT, you'll need to configure a Cognito Identity Pool. In the Amazon Cognito console, use Amazon Cognito to create a new identity pool, and allow unauthenticated identities to connect. Obtain the PoolID constant. Make sure that the policy attached to the unauthenticated role has permissions to access the required AWS IoT APIs. More information about AWS IAM roles and policies can be found here.

  2. Edit examples/browser/mqtt-explorer/aws-configuration.js, and replace the values of poolId and region with strings containing the ID of the Cognito Identity Pool and your AWS region (e.g., 'us-east-1') from the previous step.

  3. Create the application browser bundle by executing the following command in the top-level directory of the SDK:

    npm run-script browserize examples/browser/mqtt-explorer/index.js
  4. Open examples/browser/mqtt-explorer/index.html in your web browser. After connecting to AWS IoT, it should display input fields allowing you to subscribe or publish to a topic. By subscribing to '#', for example, you will be able to monitor all traffic within your AWS account as allowed by the policy associated with the unauthenticated role of your Cognito Identity Pool.

Reducing Browser Bundle Size

After your application development is complete, you will probably want to reduce the size of the browser bundle. There are a couple of easy techniques to do this, and by combining both of them you can create much smaller browser bundles.

Eliminate unused features from the AWS SDK
  1. The AWS SDK for JavaScript allows you to install only the features you use in your application. In order to use this feature when preparing a browser bundle, first you'll need to remove any existing bundle that you've already created:

    rm browser/aws-iot-sdk-browser-bundle.js
  2. Define the AWS features your application uses as a comma-separated list in the AWS_SERVICES environment variable. For example, the MQTT Explorer example uses only AWS Cognito Identity, so to create a bundle containing only this feature, do:

    export AWS_SERVICES=cognitoidentity

    For a list of the AWS SDK feature names, refer to the features subdirectory of the AWS SDK for JavaScript. As another example, if your application uses Cognito Identity, DynamoDB, S3, and SQS, you would do:

    export AWS_SERVICES=cognitoidentity,dynamodb,s3,sqs
  3. Create the browser app and bundle, e.g. for the MQTT Explorer example, do:

    npm run-script browserize examples/browser/mqtt-explorer/index.js

Uglify the bundle source

Uglify is an npm utility for minimizing the size of JavaScript source files. To use it, first install it as a global npm package:

npm install -g uglify

Once installed, you can use it to reduce the bundle size:

uglify -s ./browser/aws-iot-sdk-browser-bundle.js -o ./browser/aws-iot-sdk-browser-bundle-min.js

After you've created the minimized bundle, you'll need to make sure that your application loads this version rather than the non-minimized version, e.g:

<script src="aws-iot-sdk-browser-bundle-min.js"></script>
Optimization results

By using both of the above techniques for the MQTT Explorer example, the bundle size can be reduced from 2.4MB to 615KB.

Using SDK with webpack

In order to work with webpack, you have to create a webpack package. You can put your file dependencies in entry.js and output it as bundle.js. An example is provided in the location ./examples/browser/mqtt-webpack

cd ./examples/browser/mqtt-webpack
npm install
./node_modules/.bin/webpack --config webpack.config.js

The index.html will load the output file bundle.js and execute functions defined in entry.js. This duplicates the example of mqtt-explore above which loaded SDK into web browser using browserify.

Troubleshooting

If you have problems connecting to the AWS IoT Platform when using this SDK or running the example programs, there are a few things to check:

  • Region Mismatch: You have to use the certificate created in the same region as your host end point.
  • Duplicate Client IDs: Within your AWS account, the AWS IoT platform will only allow one connection per client ID. Many of the example programs run as two processes which communicate with one another. If you don't specify a client ID, the example programs will generate random client IDs, but if you are using a JSON configuration file, you'll need to explictly specify client IDs for both programs using the '-i' command line option.
  • Invalid NPM Version: To run the browserize.sh script which prepares the browser example applications, you'll need to use npm version 3. This is because browserize.sh expects package dependencies to be handled using the npm version 3 strategy, which is different than the strategy used in npm version 2. If you're having trouble running the browser application examples, make sure that you're using npm version 3. You can check your npm version with npm -v.

Unit Tests

This package includes unit tests which can be run as follows:

npm test

Running the unit tests will also generate code coverage data in the 'reports' directory.

License

This SDK is distributed under the Apache License, Version 2.0, see LICENSE.txt and NOTICE.txt for more information.

Support

If you have technical questions about AWS IoT Device SDK, use the AWS IoT Forum. For any other questions on AWS IoT, contact AWS Support.

aws-iot-device-sdk-js's People

Contributors

ajorg-aws avatar awssteveha avatar bretambrose avatar christophsaalfeld avatar dependabot[bot] avatar fengsongaws avatar gkwicker avatar graebm avatar hyandell avatar jmklix avatar justinboswell avatar kaibalopez avatar kellertk avatar khushail avatar liuszeng avatar robberfree avatar somayab avatar theryanburke avatar twistedtwigleg avatar xiazhvera avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aws-iot-device-sdk-js's Issues

where is config.json

So in the following command, how should I create the config.json and where to put it. It was missing from the tutorial:
node examples/echo-example.js -F ../config.json -f ~/certs --thing-name testThing1

`ReferenceError: Symbol is not defined' will occur with Node V0.10

It seems `ReferenceError: Symbol is not defined" will occur in Node V0.10 or V0.11.
Since I update nodejs to 4.4, issue solved.

This remind of the Map not defined issue. So why not added a nodejs version check in the code, so that designer will not confused with version conflict issues.

Testing?

Any suggestions on how to use this lib in testing (mocha)?

DynamoDB Rule on AWS IoT

What are parameters in DynamoDB Rule to store states of a thing as time series?
I read the code. You guys used this pattern

return '$aws/things/'+thingName+'/shadow/'+operation+'/'+type;

So which Topic Filter should I use? And which Hash Key, Range Key, Payload Field?

Size and MQTT

Hi guys

I'm really keen to use aws iot alot more, but I have some pressing concerns using mqtt currently.

The current size of the module is ~ 12.1mb on my machine with mqtt contributing 11.6 mb, as well as adding in a build phase on the initial install, is there no leaner alternative to this that we can use leveraging net sockets without native build phases? I don't want to push my own agenda but I use my websockets/net library called truflux when I need to have persistent connections and it contributes only 156kb whilst also allowing streaming and a protocol framework. My personal branch I'm working on is only about 720kb.

I understand however that you might need to reconfigure aws' backend to account for this, so I only ask, is it possible we seek an alternative?

Cannot update/get after thingShadow reconnect

After thingShadow offline, it will try to reconnect automatically, but the problem I come across is , even after it reconnect, there will be no more response from aws - iot for new update/get operation, and the thingShadow will be silent for ever. Did I miss some thing about reconnect?
And will timeout trigger reconnect in aws-iot?

Thanks

How to trigger delta event when want to delete an element inside desired section

I have a thing shadow state like

{
  "desired": {
    "color": "RED"
  },
  "reported": {
    "color": "GREEN"
  }
}

and I can delete the "color" element from desired, by set "color" : null, but this delete will not trigger delta event, so is there some other way or what is the best of practice to delete an element, which can send a delta event to thingShadow listener? Thanks

Multiple connections from one device and one cert.

I am trying to run the device-example and noticed that when I started the second connection, the first one would disconnect, even though they are running in separate processes. Both processes are using the same cert and have the same option settings. I am on US-West-2.

Documentation - browserize.sh script and browser application examples require npm 3

The browserize.sh script and browser application examples require npm 3. The documentation will be updated to reflect this in a future release. When using older versions of npm, the browserize.sh script will generate the following error and the bundle will not be usable:

./scripts/browserize.sh: line 55: cd: browser/node_modules/mqtt/lib/connect: No such file or directory

Issue with Index.js for aws-iot-device-sdk module

The index.js is missing quotes for device and thing.

It should be -
module.exports.device = require('./device');
module.exports.thingShadow = require('./thing');

instead of -

module.exports.device = require(./device);
module.exports.thingShadow = require(./thing);

After makes the changes , I was able to import the module - require('aws-iot-device-sdk') and connect to AWS IoT platform and send/receive messages. The library made is quite easier, cool !!

client disconnect when doing pub/sub

Yes, I know, I tried the forum, but an error message "Your account is not ready for posting messages yet. Please try again later.". Then I should give a try here, please close this issue if you think that it is inappropriate.

This is my problem: I am doing simple application to sub/sub topics with policy. This is the simple program

var androidApp = awsIot.device({
   keyPath: 'certs/0cd351b0ad-private.pem.key',
  certPath: 'certs/0cd351b0ad-certificate.pem.crt',
    caPath: 'certs/root.pem',
  clientId: 'nexus-5',
    region: 'us-east-1'
});

androidApp
.on('connect', function() {
  console.log('android app connected');
  androidApp.subscribe('res');

  setTimeout(function() {
    androidApp.publish('req',
      JSON.stringify({command: 'on'}));
  }, 1000);
});

androidApp
.on('offline', function() {
  console.log('android app offline');
});

androidApp
.on('error', function(error) {
  console.log('android app error');
  console.log(error);
});

androidApp
.on('message', function(topic, payload) {
  console.log('androidapp: ', topic, ': ', payload.toString());
});

With following policy, it does expected pub/sub:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iot:Connect"
      ],
      "Resource": ["arn:aws:iot:us-east-1:xxxxxxxxxxx:client/nexus-5"]
    },
    {
      "Effect": "Allow",
      "Action": [
        "iot:Publish",
        "iot:Subscribe",
        "iot:Receive"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}

Then I put more more specific topics in the Resource

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iot:Connect"
      ],
      "Resource": ["arn:aws:iot:us-east-1:xxxxxxxxxxx:client/nexus-5"]
    },
    {
      "Effect": "Allow",
      "Action": [
        "iot:Publish",
        "iot:Subscribe",
        "iot:Receive"
      ],
      "Resource": [
        "arn:aws:iot:us-east-1:xxxxxxxxxxx:topic/req",
        "arn:aws:iot:us-east-1:xxxxxxxxxxx:topic/res"
      ]
    }
  ]
}

This policy allows client to connect successfully, but the pub/sub activities seem disconnect the connection, then client triggers the reconnect. The console:

android app connected
android app offline
android app connected
android app offline
....

Could you please give me some hints on this?

Many thanks.

SDK stops receiving shadow deltas when long-running

I'm having an issue with a simple node script running on a raspberry pi. It's using IoT to trigger a siren light, and also watching for direct messages to run some servos.

I'm finding that everything works fine normally. But when I come back a day later, the shadow is no longer receiving deltas. It looks like:

  • Device script is running
  • Device script is still receiving messages on subscribed topics (the servo motor messages)
  • AWS console shows out-of-sync state requiring a delta on the shadow
  • No delta received

The device has connectivity. And if I ssh in, restart the script, everything starts working immediately.

Anyone else encounter issues with long-running node scripts using this SDK? Is there some sort of periodic "re-register" that's necessary for a thingShadow?

Relevant code:

shadow.on('delta',
  function(thingName, stateObject) {
    console.log('received delta '+' on '+thingName+': '+ JSON.stringify(stateObject));
    updateLocalState(stateObject["state"]["siren"]);
});

shadow.on('connect', function() {
    console.log("shadow connected");
    shadow.register( 'Maxwell' );
});

ReferenceError: Map is not defined

The latest change has caused the SDK to cease working on my device due to the use of the ES6 Map type:

ERROR:    var activeSubscriptions = new Map();                                                                                                                                                    
   ERROR:                               ^                                                                                                                                                         
ERROR: ReferenceError: Map is not defined                                                                                                                                                         
    at new DeviceClient (/home/root/.node_app_slot/node_modules/aws-iot-device-sdk/device/index.js:232:34)                                                                                        
    at Object.DeviceClient [as device] (/home/root/.node_app_slot/node_modules/aws-iot-device-sdk/device/index.js:164:14)                                                                         
    at Object.<anonymous> (/home/root/.node_app_slot/main.js:11:21)                                                                                                                               
    at Module._compile (module.js:456:26)                                                                                                                                                         
    at Object.Module._extensions..js (module.js:474:10)                                                                                                                                           
    at Module.load (module.js:356:32)                                                                                                                                                             
    at Function.Module._load (module.js:312:12)                                                                                                                                                   
    at Function.Module.runMain (module.js:497:10)                                                                                                                                                 
    at startup (node.js:119:16)                                                                                                                                                                   
    at node.js:935:3     

RE: SeedStudio Wiki at http://www.seeedstudio.com/wiki/Beagle_Bone_Green_and_Grove_IoT_Starter_Kit_Powered_by_AWS

Hello Again,

I think the instructions are incorrect. Now, it could be something I am doing but I think I followed the instructions. I am getting some bugs on the two .js files.

module.js:340
throw err;
^
Error: Cannot find module '..'
at Function.Module._resolveFilename (module.js:338:15)
at Function.Module._load (module.js:280:25)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at Object. (/var/lib/cloud9/examples/awsCerts/shadow.js:1:76)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)

When I run (node shadow.js) on Cloud9, I get the above error code. I downloaded the .js files directly.

Sincerely,

Seth

P.S. If you have time in the next couple of days, please look into these two .js files. I just do not think I can debug them.

Off Topic: MQTT Browser Client

I apologize for opening an issue that is not directly related to this project but i'm not sure how else to engage with AWS Javascript teams. I am hopeful that you could get me or point me to the information.

In AWS IoT there is a tab for "MQTT Client" which is a GREAT testing tool. Is that source could something that could be made available?

modify ThingShadow desired state from Lambda Function

Hi,
I'm trying to modify the shadow of a Thing from a lambda function, but my code still not works.
Someone can correct me?
Here is the code I used (this way I obtain the following error from logs: "missing required node:state")

console.log('lambda function');

var AWS=require('aws-sdk');
var iotdata = new AWS.IotData({endpoint: 'my-end-point.iot.eu-west-1.amazonaws.com'});  

exports.handler = function(event, context){
var params = {
  payload: new Buffer('66') || '{"state": {"desired": {"windowOpen": false,"posto2": true}}}', 
  thingName: 'Edison_Seba' 
};
iotdata.updateThingShadow(params, function(err, data) {
  if (err) console.log(err, err.stack); // an error occurred
  else     console.log(data);           // successful response
});

}

Another try of updating the shadow is(from logs I obtain: "{}" but it doesn't modify the shadow):

console.log('lambda function');

var AWS=require('aws-sdk');
var iotdata = new AWS.IotData({endpoint: 'my-end-point.iot.eu-west-1.amazonaws.com'});  

exports.handler = function(event, context){

var params = {
  topic: '$aws/things/Edison_Seba/shadow/update', 
  payload: new Buffer('60') || '{\"state\": {\"desired\": {\"windowOpen\": true,\"posto2\": true}}}', 
  qos: 0
};
iotdata.publish(params, function(err, data) {
  if (err) console.log(err, err.stack); // an error occurred
  else     console.log(data);           // successful response
});

}

Thank you

is it possible to subscribe to more than 7 shadows?

We are running into an issue where we can only subscribe up to 7 shadows. We get time out issue after number 7. Is it possible to subscribe to more than 7 shadows?

Here is the test code:

var iotShadowConnection = awsIot.thingShadow(iotconfigParam);

    iotShadowConnection.on("connect", function () {
        console.log("Connected to AWS-iot");
    });

    iotShadowConnection.on("status", function (thingName, stat, clientToken, stateObject) {
        console.log("thingName: " + thingName + "\n stat: " + stat + "\n clientToken: " + clientToken + "\n stateObject: " + JSON.stringify(stateObject));
    });

    iotShadowConnection.on("timeout", function(thingName){
        console.log("Time out for " + thingName);
    });

    var deviceList = [  "876053d9-f549-4ad3-b036-e4fc7f05f642",
                        "7f86a005-530a-431d-8267-19572180b15c",
                        "61dcbcfd-3f21-4cfd-880c-9f540b3f24f2",
                        "91d98e0e-3b8e-4344-8239-f28d349dadf2",
                        "9793432d-53db-47a9-9c0e-c312110a9b70",
                        "e6c426d7-c3aa-4c14-bef5-de9c6c2880c3",
                        "f80095ac-219e-400e-a453-c611fcb23932",
                        "1698ace6-f6ae-4d16-96a2-f1b4b9de425a",
                        "b7edee1e-7107-4aa1-b18c-01c2fb324ac9",
                        "b297d5ed-8f28-4c96-b3df-bcf9cff18433"

    ];
    async.eachSeries(deviceList,function(device,callback) {

        iotShadowConnection.register(device);
        setTimeout(function(){
            iotShadowConnection.get(device);
            callback();
        }, 2000);
    });

Here is the result:

Connected to AWS-iot
thingName: 876053d9-f549-4ad3-b036-e4fc7f05f642
 stat: accepted
 clientToken: 847283250964-0
 stateObject: {"state":{"desired":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":"3364161a-91b0-4840-9d79-89b672e0c4cf"}},"delta":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":"3364161a-91b0-4840-9d79-89b672e0c4cf"}}},"metadata":{"desired":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":{"timestamp":1457485486}}}},"timestamp":1457644073}
thingName: 7f86a005-530a-431d-8267-19572180b15c
 stat: accepted
 clientToken: 847283250964-1
 stateObject: {"state":{"desired":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":"b0280274-c770-4bae-b502-3b210f01ece4"}},"delta":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":"b0280274-c770-4bae-b502-3b210f01ece4"}}},"metadata":{"desired":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":{"timestamp":1457485486}}}},"timestamp":1457644073}
thingName: 61dcbcfd-3f21-4cfd-880c-9f540b3f24f2
 stat: accepted
 clientToken: 847283250964-2
 stateObject: {"state":{"desired":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":"2c2dd796-ffc9-4f4b-be53-0e13aa870a98"}},"delta":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":"2c2dd796-ffc9-4f4b-be53-0e13aa870a98"}}},"metadata":{"desired":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":{"timestamp":1457485486}}}},"timestamp":1457644073}
thingName: 91d98e0e-3b8e-4344-8239-f28d349dadf2
 stat: accepted
 clientToken: 847283250964-3
 stateObject: {"state":{"desired":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":"76ddff04-4fcf-41f6-91d2-da2302c37765"}},"delta":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":"76ddff04-4fcf-41f6-91d2-da2302c37765"}}},"metadata":{"desired":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":{"timestamp":1457485486}}}},"timestamp":1457644073}
thingName: 9793432d-53db-47a9-9c0e-c312110a9b70
 stat: accepted
 clientToken: 847283250964-4
 stateObject: {"state":{"desired":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":"a9795375-08bd-410d-9f4a-e4e1090bafab"}},"delta":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":"a9795375-08bd-410d-9f4a-e4e1090bafab"}}},"metadata":{"desired":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":{"timestamp":1457485486}}}},"timestamp":1457644074}
thingName: e6c426d7-c3aa-4c14-bef5-de9c6c2880c3
 stat: accepted
 clientToken: 847283250964-5
 stateObject: {"state":{"desired":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":"b330658f-15cd-45a7-bcc6-b26d8fbedc61"}},"delta":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":"b330658f-15cd-45a7-bcc6-b26d8fbedc61"}}},"metadata":{"desired":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":{"timestamp":1457485485}}}},"timestamp":1457644075}
thingName: f80095ac-219e-400e-a453-c611fcb23932
 stat: accepted
 clientToken: 847283250964-6
 stateObject: {"state":{"desired":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":"2b5897b6-5ea2-49dc-b071-8af3aca099a5"}},"delta":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":"2b5897b6-5ea2-49dc-b071-8af3aca099a5"}}},"metadata":{"desired":{"settings":{"lock_codes":{},"daily_codes":[],"last_change_number":{"timestamp":1457485485}}}},"timestamp":1457644077}
connection lost - will attempt reconnection in 1 seconds...
Connected to AWS-iot
Time out for 1698ace6-f6ae-4d16-96a2-f1b4b9de425a
Time out for b7edee1e-7107-4aa1-b18c-01c2fb324ac9
Time out for b297d5ed-8f28-4c96-b3df-bcf9cff18433

Error when install aws-iot-device-sdk

Got this error when run npm install aws-iot-device-sdk

> bufferutil@1.1.0 install /Users/vinhlh/Works/demeter/test/aws-iot/node_modules/aws-iot-device-sdk/node_modules/mqtt/node_modules/websocket-stream/node_modules/ws/node_modules/bufferutil
> node-gyp rebuild

  CXX(target) Release/obj.target/bufferutil/src/bufferutil.o
In file included from ../src/bufferutil.cc:16:
../node_modules/nan/nan.h:261:25: error: redefinition of '_NanEnsureLocal'
NAN_INLINE v8::Local<T> _NanEnsureLocal(v8::Local<T> val) {
                        ^
../node_modules/nan/nan.h:256:25: note: previous definition is here
NAN_INLINE v8::Local<T> _NanEnsureLocal(v8::Handle<T> val) {
                        ^
../node_modules/nan/nan.h:661:13: error: no member named 'smalloc' in namespace 'node'
    , node::smalloc::FreeCallback callback
      ~~~~~~^
../node_modules/nan/nan.h:672:12: error: no matching function for call to 'New'
    return node::Buffer::New(v8::Isolate::GetCurrent(), data, size);
           ^~~~~~~~~~~~~~~~~
/Users/vinhlh/.node-gyp/4.1.2/include/node/node_buffer.h:31:40: note: candidate function not viable: no known conversion from 'uint32_t' (aka 'unsigned int') to 'enum encoding' for 3rd argument
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate,
                                       ^
/Users/vinhlh/.node-gyp/4.1.2/include/node/node_buffer.h:43:40: note: candidate function not viable: 2nd argument ('const char *') would lose const qualifier
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate,
                                       ^
/Users/vinhlh/.node-gyp/4.1.2/include/node/node_buffer.h:28:40: note: candidate function not viable: requires 2 arguments, but 3 were provided
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate, size_t length);
                                       ^
/Users/vinhlh/.node-gyp/4.1.2/include/node/node_buffer.h:36:40: note: candidate function not viable: requires 5 arguments, but 3 were provided
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate,
                                       ^
In file included from ../src/bufferutil.cc:16:
../node_modules/nan/nan.h:676:12: error: no viable conversion from 'v8::MaybeLocal<v8::Object>' to 'v8::Local<v8::Object>'
    return node::Buffer::New(v8::Isolate::GetCurrent(), size);
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:210:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'v8::MaybeLocal<v8::Object>' to
      'const v8::Local<v8::Object> &' for 1st argument
class Local {
      ^
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:210:7: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'v8::MaybeLocal<v8::Object>' to
      'v8::Local<v8::Object> &&' for 1st argument
class Local {
      ^
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:214:13: note: candidate template ignored: could not match 'Local' against 'MaybeLocal'
  V8_INLINE Local(Local<S> that)
            ^
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:326:13: note: candidate template ignored: could not match 'S *' against 'v8::MaybeLocal<v8::Object>'
  V8_INLINE Local(S* that)
            ^
In file included from ../src/bufferutil.cc:16:
../node_modules/nan/nan.h:683:26: error: no member named 'Use' in namespace 'node::Buffer'
    return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size);
           ~~~~~~~~~~~~~~^
In file included from ../src/bufferutil.cc:7:
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:221:5: error: assigning to 'v8::Primitive *volatile' from incompatible type 'v8::Value *'
    TYPE_CHECK(T, S);
    ^~~~~~~~~~~~~~~~
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:180:37: note: expanded from macro 'TYPE_CHECK'
    *(static_cast<T* volatile*>(0)) = static_cast<S*>(0);      \
                                    ^ ~~~~~~~~~~~~~~~~~~
../node_modules/nan/nan.h:414:12: note: in instantiation of function template specialization 'v8::Local<v8::Primitive>::Local<v8::Value>' requested here
    return NanEscapeScope(NanNew(v8::Undefined(v8::Isolate::GetCurrent())));
           ^
../node_modules/nan/nan.h:398:30: note: expanded from macro 'NanEscapeScope'
# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
                             ^
In file included from ../src/bufferutil.cc:7:
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:221:5: error: assigning to 'v8::Boolean *volatile' from incompatible type 'v8::Value *'
    TYPE_CHECK(T, S);
    ^~~~~~~~~~~~~~~~
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:180:37: note: expanded from macro 'TYPE_CHECK'
    *(static_cast<T* volatile*>(0)) = static_cast<S*>(0);      \
                                    ^ ~~~~~~~~~~~~~~~~~~
../node_modules/nan/nan.h:424:12: note: in instantiation of function template specialization 'v8::Local<v8::Boolean>::Local<v8::Value>' requested here
    return NanEscapeScope(NanNew(v8::True(v8::Isolate::GetCurrent())));
           ^
../node_modules/nan/nan.h:398:30: note: expanded from macro 'NanEscapeScope'
# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
                             ^
In file included from ../src/bufferutil.cc:7:
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:221:5: error: assigning to 'v8::Function *volatile' from incompatible type 'v8::Value *'
    TYPE_CHECK(T, S);
    ^~~~~~~~~~~~~~~~
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:180:37: note: expanded from macro 'TYPE_CHECK'
    *(static_cast<T* volatile*>(0)) = static_cast<S*>(0);      \
                                    ^ ~~~~~~~~~~~~~~~~~~
../node_modules/nan/nan.h:1514:12: note: in instantiation of function template specialization 'v8::Local<v8::Function>::Local<v8::Value>' requested here
    return NanEscapeScope(NanNew(handle)->Get(kCallbackIndex)
           ^
../node_modules/nan/nan.h:398:30: note: expanded from macro 'NanEscapeScope'
# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
                             ^
In file included from ../src/bufferutil.cc:7:
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:221:5: error: assigning to 'v8::Object *volatile' from incompatible type 'v8::Value *'
    TYPE_CHECK(T, S);
    ^~~~~~~~~~~~~~~~
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:180:37: note: expanded from macro 'TYPE_CHECK'
    *(static_cast<T* volatile*>(0)) = static_cast<S*>(0);      \
                                    ^ ~~~~~~~~~~~~~~~~~~
../node_modules/nan/nan.h:1632:12: note: in instantiation of function template specialization 'v8::Local<v8::Object>::Local<v8::Value>' requested here
    return NanEscapeScope(handle->Get(NanNew(key)).As<v8::Object>());
           ^
../node_modules/nan/nan.h:398:30: note: expanded from macro 'NanEscapeScope'
# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
                             ^
9 errors generated.
make: *** [Release/obj.target/bufferutil/src/bufferutil.o] Error 1
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:270:23)
gyp ERR! stack     at emitTwo (events.js:87:13)
gyp ERR! stack     at ChildProcess.emit (events.js:172:7)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
gyp ERR! System Darwin 15.0.0
gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/vinhlh/Works/demeter/test/aws-iot/node_modules/aws-iot-device-sdk/node_modules/mqtt/node_modules/websocket-stream/node_modules/ws/node_modules/bufferutil
gyp ERR! node -v v4.1.2
gyp ERR! node-gyp -v v3.0.3
gyp ERR! not ok

> utf-8-validate@1.1.0 install /Users/vinhlh/Works/demeter/test/aws-iot/node_modules/aws-iot-device-sdk/node_modules/mqtt/node_modules/websocket-stream/node_modules/ws/node_modules/utf-8-validate
> node-gyp rebuild

  CXX(target) Release/obj.target/validation/src/validation.o
In file included from ../src/validation.cc:15:
../node_modules/nan/nan.h:261:25: error: redefinition of '_NanEnsureLocal'
NAN_INLINE v8::Local<T> _NanEnsureLocal(v8::Local<T> val) {
                        ^
../node_modules/nan/nan.h:256:25: note: previous definition is here
NAN_INLINE v8::Local<T> _NanEnsureLocal(v8::Handle<T> val) {
                        ^
../node_modules/nan/nan.h:661:13: error: no member named 'smalloc' in namespace 'node'
    , node::smalloc::FreeCallback callback
      ~~~~~~^
../node_modules/nan/nan.h:672:12: error: no matching function for call to 'New'
    return node::Buffer::New(v8::Isolate::GetCurrent(), data, size);
           ^~~~~~~~~~~~~~~~~
/Users/vinhlh/.node-gyp/4.1.2/include/node/node_buffer.h:31:40: note: candidate function not viable: no known conversion from 'uint32_t' (aka 'unsigned int') to 'enum encoding' for 3rd argument
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate,
                                       ^
/Users/vinhlh/.node-gyp/4.1.2/include/node/node_buffer.h:43:40: note: candidate function not viable: 2nd argument ('const char *') would lose const qualifier
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate,
                                       ^
/Users/vinhlh/.node-gyp/4.1.2/include/node/node_buffer.h:28:40: note: candidate function not viable: requires 2 arguments, but 3 were provided
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate, size_t length);
                                       ^
/Users/vinhlh/.node-gyp/4.1.2/include/node/node_buffer.h:36:40: note: candidate function not viable: requires 5 arguments, but 3 were provided
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate,
                                       ^
In file included from ../src/validation.cc:15:
../node_modules/nan/nan.h:676:12: error: no viable conversion from 'v8::MaybeLocal<v8::Object>' to 'v8::Local<v8::Object>'
    return node::Buffer::New(v8::Isolate::GetCurrent(), size);
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:210:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'v8::MaybeLocal<v8::Object>' to
      'const v8::Local<v8::Object> &' for 1st argument
class Local {
      ^
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:210:7: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'v8::MaybeLocal<v8::Object>' to
      'v8::Local<v8::Object> &&' for 1st argument
class Local {
      ^
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:214:13: note: candidate template ignored: could not match 'Local' against 'MaybeLocal'
  V8_INLINE Local(Local<S> that)
            ^
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:326:13: note: candidate template ignored: could not match 'S *' against 'v8::MaybeLocal<v8::Object>'
  V8_INLINE Local(S* that)
            ^
In file included from ../src/validation.cc:15:
../node_modules/nan/nan.h:683:26: error: no member named 'Use' in namespace 'node::Buffer'
    return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size);
           ~~~~~~~~~~~~~~^
In file included from ../src/validation.cc:7:
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:221:5: error: assigning to 'v8::Primitive *volatile' from incompatible type 'v8::Value *'
    TYPE_CHECK(T, S);
    ^~~~~~~~~~~~~~~~
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:180:37: note: expanded from macro 'TYPE_CHECK'
    *(static_cast<T* volatile*>(0)) = static_cast<S*>(0);      \
                                    ^ ~~~~~~~~~~~~~~~~~~
../node_modules/nan/nan.h:414:12: note: in instantiation of function template specialization 'v8::Local<v8::Primitive>::Local<v8::Value>' requested here
    return NanEscapeScope(NanNew(v8::Undefined(v8::Isolate::GetCurrent())));
           ^
../node_modules/nan/nan.h:398:30: note: expanded from macro 'NanEscapeScope'
# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
                             ^
In file included from ../src/validation.cc:7:
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:221:5: error: assigning to 'v8::Boolean *volatile' from incompatible type 'v8::Value *'
    TYPE_CHECK(T, S);
    ^~~~~~~~~~~~~~~~
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:180:37: note: expanded from macro 'TYPE_CHECK'
    *(static_cast<T* volatile*>(0)) = static_cast<S*>(0);      \
                                    ^ ~~~~~~~~~~~~~~~~~~
../node_modules/nan/nan.h:424:12: note: in instantiation of function template specialization 'v8::Local<v8::Boolean>::Local<v8::Value>' requested here
    return NanEscapeScope(NanNew(v8::True(v8::Isolate::GetCurrent())));
           ^
../node_modules/nan/nan.h:398:30: note: expanded from macro 'NanEscapeScope'
# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
                             ^
In file included from ../src/validation.cc:7:
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:221:5: error: assigning to 'v8::Function *volatile' from incompatible type 'v8::Value *'
    TYPE_CHECK(T, S);
    ^~~~~~~~~~~~~~~~
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:180:37: note: expanded from macro 'TYPE_CHECK'
    *(static_cast<T* volatile*>(0)) = static_cast<S*>(0);      \
                                    ^ ~~~~~~~~~~~~~~~~~~
../node_modules/nan/nan.h:1514:12: note: in instantiation of function template specialization 'v8::Local<v8::Function>::Local<v8::Value>' requested here
    return NanEscapeScope(NanNew(handle)->Get(kCallbackIndex)
           ^
../node_modules/nan/nan.h:398:30: note: expanded from macro 'NanEscapeScope'
# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
                             ^
In file included from ../src/validation.cc:7:
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:221:5: error: assigning to 'v8::Object *volatile' from incompatible type 'v8::Value *'
    TYPE_CHECK(T, S);
    ^~~~~~~~~~~~~~~~
/Users/vinhlh/.node-gyp/4.1.2/include/node/v8.h:180:37: note: expanded from macro 'TYPE_CHECK'
    *(static_cast<T* volatile*>(0)) = static_cast<S*>(0);      \
                                    ^ ~~~~~~~~~~~~~~~~~~
../node_modules/nan/nan.h:1632:12: note: in instantiation of function template specialization 'v8::Local<v8::Object>::Local<v8::Value>' requested here
    return NanEscapeScope(handle->Get(NanNew(key)).As<v8::Object>());
           ^
../node_modules/nan/nan.h:398:30: note: expanded from macro 'NanEscapeScope'
# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
                             ^
9 errors generated.
make: *** [Release/obj.target/validation/src/validation.o] Error 1
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:270:23)
gyp ERR! stack     at emitTwo (events.js:87:13)
gyp ERR! stack     at ChildProcess.emit (events.js:172:7)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
gyp ERR! System Darwin 15.0.0
gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/vinhlh/Works/demeter/test/aws-iot/node_modules/aws-iot-device-sdk/node_modules/mqtt/node_modules/websocket-stream/node_modules/ws/node_modules/utf-8-validate
gyp ERR! node -v v4.1.2
gyp ERR! node-gyp -v v3.0.3
gyp ERR! not ok
npm WARN optional dep failed, continuing bufferutil@1.1.0
npm WARN optional dep failed, continuing utf-8-validate@1.1.0
aws-iot-device-sdk@1.0.4 node_modules/aws-iot-device-sdk
├── minimist@1.2.0
├── blessed-contrib@2.3.3 (ansi-term@0.0.1, memorystream@0.3.1, term-canvas@0.0.5, marked@0.3.5, lodash@3.10.1, memory-streams@0.1.0, chalk@1.1.1, drawille-canvas-blessed-contrib@0.1.2, sparkline@0.1.2, picture-tube@0.0.4, map-canvas@0.1.5, marked-terminal@1.6.1, request@2.64.0)
└── mqtt@1.3.5 (inherits@2.0.1, xtend@4.0.0, readable-stream@1.0.33, commist@1.0.0, mqtt-connection@2.1.1, mqtt-packet@3.4.3, end-of-stream@1.1.0, help-me@0.1.0, concat-stream@1.5.0, websocket-stream@1.5.2)

Node version: v4.1.2

node vs. javascript

it seems like this SDK only works in Node and isn't pure javascript. Is it possible to adapt it for browsers so that it could be used in something like Cordova?

Actually i noticed in the AWS IoT documentation that this was referred to as an SDK for NodeJS. Maybe just retitle the github README.

Certificate X.509

Do I have to call AWS command to create cert.pem?

aws iot --endpoint-url https://i.us-east-1.pb.iot.amazonaws.com describe-certificate --certificate-id --output text --query certificateDescription.certificatePem > cert.pem

or is there any OpenSSL command available? My use case is to create cert.pem without relying on AWS. Because i created initial certificates with OpenSSL commands,

$ openssl genrsa -out privateKey.pem 2048
$ openssl req -new -key privateKey.pem -out cert.csr

I would like to understand what the above aws command does.

Can't handle Error: Error: write EPROTO

In device/index.js an error will be thrown if there are problems with SSL. In our use case it might happen that we revoke certificates server side but this causes the application to crash. Is is possible to move the new Error code to a callback or pass it with EventEmitter?

This causes the crash:

 //handle some exceptions
  device 
    .on('error', function(error) {
      //certificate issue
      if (error.code === 'EPROTO') {
        throw new Error(error);
      }
    });

Or how do we have to treat this situation?

Question about connect, reconnect, offline events in aws-iot

At which instance will "connect', 'reconnect' and 'offline' these three events triggered? And after thing shadow offline, will it reconnect to iot by itself, or should I manually reconnect it by some way? If by manual, what is the best practice to do that?

Thanks

root-CA.crt

README mentions to use the Symantec's

https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem 
  Subject: subject= /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5

as the root-CA.crt for all the examples.

However, the certificates issued from the IoT Console are issued by an apparently intermediate CA:

issuer= /OU=Amazon Web Services O=Amazon.com Inc. L=Seattle ST=Washington C=US

The documentation doesn't mention where to get this intermediary CA.

Problem with running the examples behind PROXY

Hello AWS Team!
I am trying to walk through the AWS IoT examples. But I am stuck:
I got the CLI running on my linux machine:

ubuntu@linux-server:~/aws-iot-device-sdk$ aws iot list-things
{
    "things": [
        {
            "attributes": {
                "VIN": "4711_EU_Ireland_Dummy_VIN"
            },
            "thingName": "Vehicle-EU-Ireland"
        }
    ]
}

But when I try to run the device-example.js it seems that it cannot connect:

ubuntu@linux-server:~/aws-iot-device-sdk$ nodejs examples/device-example.js -F ./certs.json --test-mode=1
error { [Error: getaddrinfo ENOTFOUND] code: 'ENOTFOUND', errno: 'ENOTFOUND', syscall: 'getaddrinfo' }
offline
close
reconnect
error { [Error: getaddrinfo ENOTFOUND] code: 'ENOTFOUND', errno: 'ENOTFOUND', syscall: 'getaddrinfo' }
offline
close

I am behind a corporate proxy. All settings for that are configured:

  • all certificats and private keys are configured in certs.json
  • environment variables HTTP_PROXY and HTTP PROXY are set correctly
  • I did set the node proxy with npm config set proxy http://user:[email protected]:port and the same for parameter https-proxy
  • And i also configured the AWS-SDK for proxy as described in the AWS-SDK docs

What else did I miss?

Last Will troubles

According to documentation of awsIot.thingShadow(options)

the arguments in options include all those in the device class, with the addition of the following arguments specific to the thingShadow class:

  • operationTimeout: the timeout for thing operations (default 10 seconds)

which means options of awsIot.device(options) and therefore :

options also contains arguments specific to mqtt. See the mqtt client documentation for details of these arguments.

So to sum up, options of awsIot.thingShadow should be :

from awsIot.thingShadow

  • operationTimeout: the timeout for thing operations (default 10 seconds)

from awsIot.device

  • region: the AWS IoT region you will operate in (default 'us-east-1')
  • clientId: the client ID you will use to connect to AWS IoT
  • certPath: path of the client certificate file
  • keyPath: path of the private key file associated with the client certificate
  • caPath: path of your CA certificate file
  • clientCert: same as certPath, but can also accept a buffer containing client certificate data
  • privateKey: same as keyPath, but can also accept a buffer containing private key data
  • caCert: same as caPath, but can also accept a buffer containing CA certificate data
  • autoResubscribe: set to 'true' to automatically re-subscribe to topics after reconnection (default 'true')
  • offlineQueueing: set to 'true' to automatically queue published messages while offline (default 'true')
  • offlineQueueMaxSize: enforce a maximum size for the offline message queue (default 0, e.g. no maximum)
  • offlineQueueDropBehavior: set to 'oldest' or 'newest' to define drop behavior on a full queue when offlineQueueMaxSize > 0
  • drainTimeMs: the minimum time in milliseconds between publishes when draining after reconnection (default 250)
  • baseReconnectTimeMs: the base reconnection time in milliseconds (default 1000)
  • maximumReconnectTimeMs: the maximum reconnection time in milliseconds (default 128000)
  • minimumConnectionTimeMs: the minimum time in milliseconds that a connection must be maintained in order to be considered stable (default 20000)
  • protocol: the connection type, either 'mqtts' (default) or 'wss' (WebSocket/TLS). Note that when set to 'wss', values must be provided for the Access Key ID and Secret Key in either the following options or in environment variables as specified in WebSocket Configuration.
  • websocketOptions: if protocol is set to 'wss', you can use this parameter to pass additional options to the underlying WebSocket object; these options are documented here.
  • accessKeyId: used to specify the Access Key ID when protocol is set to 'wss'. Overrides the environment variable AWS_ACCESS_KEY_ID if set.
  • secretKey: used to specify the Secret Key when protocol is set to 'wss'. Overrides the environment variable AWS_SECRET_ACCESS_KEY if set.
  • sessionToken: (required when authenticating via Cognito, optional otherwise) used to specify the Session Token when protocol is set to 'wss'. Overrides the environment variable AWS_SESSION_TOKEN if set.

from mqtt.Client

  • keepalive: 10 seconds, set to 0 to disable
  • reschedulePings: reschedule ping messages after sending packets (default true)
  • clientId: 'mqttjs_' + Math.random().toString(16).substr(2, 8) duplicate
  • protocolId: 'MQTT'
  • protocolVersion: 4
  • clean: true, set to false to receive QoS 1 and 2 messages while offline
  • reconnectPeriod: 1000 milliseconds, interval between two reconnections
  • connectTimeout: 30 * 1000 milliseconds, time to wait before a CONNACK is received
  • username: the username required by your broker, if any
  • password: the password required by your broker, if any
  • incomingStore: a Store for the incoming packets
  • outgoingStore: a Store for the outgoing packets
  • queueQoSZero: if connection is broken, queue outgoing QoS zero messages (default true)
  • will: a message that will sent by the broker automatically when the client disconnect badly. The format is:
    • topic: the topic to publish
    • payload: the message to publish
    • qos: the QoS
    • retain: the retain flag

BUT, when i connect a thingShadow with following options:

  • clientId
  • caCert
  • clientCert
  • privateKey
  • region
  • will
    • topic : "topicblahblah"
    • payload : "disconnected"
    • qos :0
    • retain : true

the thing enters directly to a 'offline, close, reconnect, offline... loop, without any connect event !

After few tests, it appears that giving "retain:true" makes it work improperly !
With "retain:false", it works as expected !

Is it a bug or because AWS message broker cannot retain last wills?

aws-iot-device-sdk-js cannt work

Hello
I have installed the sdk on my beaglebone.
root@beaglebone:~# node

var awsIot = require('aws-iot-device-sdk')
undefined

and request the certificate file from https://us-west-2.console.aws.amazon.com/iot/home?region=us-west-2#/dashboard. Change the file name.

root@beaglebone:# ls awsCerts/
certificate.pem.crt private.pem.key root-CA.crt
root@beaglebone:
#
root@beaglebone:~# cat test.js
var awsIot = require('aws-iot-device-sdk');

var device = awsIot.device({
keyPath: '/root/awsCerts/private.pem.key',
certPath: '/root/awsCerts/certificate.pem.crt',
caPath: '/root/awsCerts/root-CA.crt',
clientId: 'myAwsClientId',
region: 'us-east-1'
});

//
// Device is an instance returned by mqtt.Client(), see mqtt.js for full
// documentation.
//
device
.on('connect', function() {
console.log('connect');
device.subscribe('topic_1');
device.publish('topic_2', JSON.stringify({ test_data: 1}));
});

device
.on('message', function(topic, payload) {
console.log('message', topic, payload.toString());
});
Run the example. But it print nothing. so What's wrong?

When using the wss protocol missing region is not checked

When using the wss protocol, you might forget to include the region parameter. This is said to be defaulted, but the generated wss protocol url doesn't include the defaulted region. Instead it shows up as undefined in the string. This is how i noticed the issue.
Instead verify and error out if the region option is not set correctly, or at least use the defaulted value.

thingShadow.subscribe & event (message)

Hi

I tried to use thingShadow.subscribe and nothing happened ! no error but no handling of message from topic ! The thingShadow can update, register, unregister, get the Shadow... it can also publish on topics that are not $aws/things... !
But no event.on('message'..), no on.('error')...

Could come from code ? or do i miss something about AWS IOT / mqtt?

Dham

Error: Error: write EPROTO

I am trying to run the examples, and i get the following error

➜  examples git:(master) ✗ node device-example.js -k private.pem.key -c certificate.pem.crt -a VeriSign-Class\ 3-Public-Primary-Certification-Authority-G5.pem.txt
/Users/anuj/projects/aws-iot-device-sdk-js/device/index.js:68
        throw new Error(error);
        ^

Error: Error: write EPROTO
    at MqttClient.<anonymous> (/Users/anuj/projects/aws-iot-device-sdk-js/device/index.js:68:15)
    at emitOne (events.js:82:20)
    at MqttClient.emit (events.js:169:7)
    at TLSSocket.handleTLSerrors (/Users/anuj/projects/aws-iot-device-sdk-js/node_modules/mqtt/lib/connect/tls.js:39:18)
    at emitOne (events.js:82:20)
    at TLSSocket.emit (events.js:169:7)
    at onwriteError (_stream_writable.js:304:10)
    at onwrite (_stream_writable.js:322:5)
    at WritableState.onwrite (_stream_writable.js:89:5)
    at fireErrorCallbacks (net.js:442:13)

Get errors when run tempturature control example

Error: Error: write EPROTO
    at MqttClient.<anonymous> (/Users/vinhlh/Works/demeter.vn/aws/aws-iot-device-sdk-js/device/index.js:68:15)
    at emitOne (events.js:82:20)
    at MqttClient.emit (events.js:169:7)
    at TLSSocket.handleTLSerrors (/Users/vinhlh/Works/demeter.vn/aws/aws-iot-device-sdk-js/node_modules/mqtt/lib/connect/tls.js:39:18)
    at emitOne (events.js:82:20)
    at TLSSocket.emit (events.js:169:7)
    at onwriteError (_stream_writable.js:304:10)
    at onwrite (_stream_writable.js:322:5)
    at WritableState.onwrite (_stream_writable.js:89:5)
    at fireErrorCallbacks (net.js:442:13)

Device config values differ from Console

The console gives a config object with your certificate names etc, host + port and so on however they don't match what Device and more specifically, tls-reader.js is expecting. caPath, certPath and keyPath and being called caCert, clientCert, privateKey - also, the config object is missing the region, which is fine if you're in us-east-1 but otherwise it also throws an exception.

How to stream data over AWS IoT

Dear All,
My goal is to connect a control device and an EA-Hub (i.e., an MySQL database of real-time data) via AWS IoT. I already installed aws-iot-device-sdk-js on my control device and EA-Hub (they are Linux-based systems). Now I want to perform the action that when the control device publishes a message to IoT device gateway, the EA-Hub as a subscriber will stream the data from its mySQL table to IoT device gateway, and require the AWS service to perform an analysis (e.g., K-mean clustering) on the data, finally send the result to the control device. Note that the connection between the EA-Hub, the control device is based on MQTT.
Please let me know whether or not the MQTT connection is suitable for streaming data from my EA-Hub to AWS IoT device gateway? Which AWS service should I use to perform the data analysis like K-mean clustering via AWS IoT?
I would appreciate much if anyone can give me any advice to implement my system.

Thank in advanced!

Competition between thingShadows generated with same client id but different certificates

I have created two different thingShadows with two different groups of keyPath, certPath, caPath and region (both generated from same AWS account), but with same clientId. Each one works well individually, but when they start at the same time, they will compete with each other and both show "connection lost - will attempt reconnection". Is this normal? If not, how can I fix this problem?

Thanks

connection lost - will attempt reconnection in 1 seconds...

Hi,

I am trying to create a basic IoT appliance. I'm using a Raspberry Pi 3 with Raspbian, but I have also reproduced this error on Windows 10.

I have the following code:

var awsIot = require('aws-iot-device-sdk');

var device = awsIot.device({
    keyPath: "/home/pi/share/MyDevice/private.pem.key",
    certPath: "/home/pi/share/MyDevice/certificate.pem.crt",
    caPath: "/home/pi/share/MyDevice/root-CA.pem",
    clientId: "MyDevice",
    host: "XXXXXXXXXXXXXX.iot.ap-southeast-1.amazonaws.com",
    region: "ap-southeast-1",
    port: 8883,
    debug: true
});

device.on('connect', function() {
    console.log('connected');
    device.subscribe('myevent');
    device.publish('deviceonline', JSON.stringify({ online: true}));
});

device.on('close', function() {
    console.log('disconnected', arguments);
});

device.on('error', function() {
    console.log('error', arguments);
});

device.on('reconnect', function() {
    console.log('reconnecting', arguments);
});

device.on('message', function(topic, payload) {
    console.log('message', topic, payload.toString());
});

device.on('timeout', function(thingName, clientToken) {
    console.log('received timeout');
});

When I run this I get the following output

attempting new mqtt connection...
connection lost - will attempt reconnection in 1 seconds...
disconnected {}
reconnecting {}
connection lost - will attempt reconnection in 2 seconds...
disconnected {}
reconnecting {}
connection lost - will attempt reconnection in 4 seconds...
disconnected {}
reconnecting {}
connection lost - will attempt reconnection in 8 seconds...
disconnected {}
reconnecting {}
connection lost - will attempt reconnection in 16 seconds...
disconnected {}
reconnecting {}
connection lost - will attempt reconnection in 32 seconds...
disconnected {}
reconnecting {}
connection lost - will attempt reconnection in 64 seconds...
disconnected {}
reconnecting {}
connection lost - will attempt reconnection in 128 seconds...
disconnected {}
reconnecting {}
connection lost - will attempt reconnection in 128 seconds...
disconnected {}

I'm able to connect by changing the protocol to wss, but I would much rather use MQTT.

Thanks,

YM

Unable to install

I think you have a bad version published as 'latest' on NPM:

$ npm i aws-iot-device-sdk
npm ERR! Darwin 15.0.0
npm ERR! argv "/Users/matteo/.nvm/versions/node/v4.2.0/bin/node" "/Users/matteo/.nvm/versions/node/v4.2.0/bin/npm" "i" "aws-iot-device-sdk"
npm ERR! node v4.2.0
npm ERR! npm  v3.4.1

npm ERR! No compatible version found: aws-iot-device-sdk
npm ERR! Valid install targets:
npm ERR! 1.0.9, 1.0.8, 1.0.7, 1.0.6, 1.0.5, 1.0.4
npm ERR!
npm ERR!
npm ERR! If you need help, you may report this error at:
npm ERR!     <https://github.com/npm/npm/issues>

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/matteo/Temp/aaa/npm-debug.log

This works:

$ npm i [email protected]

> [email protected] install /Users/matteo/Temp/aaa/node_modules/bufferutil
> node-gyp rebuild

  CXX(target) Release/obj.target/bufferutil/src/bufferutil.o
  SOLINK_MODULE(target) Release/bufferutil.node

> [email protected] install /Users/matteo/Temp/aaa/node_modules/utf-8-validate
> node-gyp rebuild

  CXX(target) Release/obj.target/validation/src/validation.o
  SOLINK_MODULE(target) Release/validation.node
/Users/matteo/Temp/aaa
└─┬ [email protected]
  ├── [email protected]
  └─┬ [email protected]
    ├─┬ [email protected]
    │ └── [email protected]
    ├─┬ [email protected]
    │ ├─┬ [email protected]
    │ │ ├── [email protected]
    │ │ └── [email protected]
    │ └── [email protected]
    ├─┬ [email protected]
    │ └─┬ [email protected]
    │   └── [email protected]
    ├─┬ [email protected]
    │ └── [email protected]
    ├── [email protected]
    ├─┬ [email protected]
    │ ├── [email protected]
    │ └── [email protected]
    ├─┬ [email protected]
    │ └── [email protected]
    ├─┬ [email protected]
    │ ├── [email protected]
    │ ├── [email protected]
    │ └── [email protected]
    ├─┬ [email protected]
    │ ├─┬ [email protected]
    │ │ ├── [email protected]
    │ │ └── [email protected]
    │ ├─┬ [email protected]
    │ │ └── [email protected]
    │ └─┬ [email protected]
    │   ├─┬ [email protected]
    │   │ ├── [email protected]
    │   │ └── [email protected]
    │   ├── [email protected]
    │   ├── [email protected]
    │   └── [email protected]
    └── [email protected]

running echo-example.js not working

Hello,

I would like to run the echo-example.js example with "node examples/echo-example.js -F config.json -f . --thing-name testThing1". Unfortunately it seems that the client certificate is rejected by aws.

error [Error: 140735187984384:error:14094416:SSL routines:SSL3_READ_BYTES:sslv3 alert certificate unknown:../deps/openssl/openssl/ssl/s3_pkt.c:1275:SSL alert number 46
]

I'm using all the assets which were created during the "connect a device" workflow. Maybe you have hints what it wrong.

Thanks

Custom CA

Following the guide http://docs.aws.amazon.com/iot/latest/developerguide/iot-dg.pdf, I'm trying to use my own CA (self signed according to the instruction in the guide) to issue certificates.

This is the error I am getting:

Error: unable to get local issuer certificate
    at Error (native)
    at TLSSocket.<anonymous> (_tls_wrap.js:1065:38)
    at emitNone (events.js:80:13)
    at TLSSocket.emit (events.js:179:7)
    at TLSSocket._init.ssl.onclienthello.ssl.oncertcb.TLSSocket._finishInit (_tls_wrap.js:593:8)
    at TLSWrap.ssl.onclienthello.ssl.oncertcb.ssl.onnewsession.ssl.onhandshakedone (_tls_wrap.js:425:38)

Question: Shadow Device

I am not clear on the reason for a shadow device. The reason I am confused is that I understood the MQTT "Last Will and testament" to fulfil this function.

The client will (or message)
When a client connects to a server, it can inform the server that it has a will, or a message, that will be published to a specific topic or topics in the event of an unexpected disconnection. A will is particularly useful in alarm or security settings where system managers must know immediately when a remote sensor has lost contact with the network.

Otherwise, why do you care. The device comes online and begins it comms.

Can't subscribe to topic on a thingShadow

I try to subscribe to a non thing topic in a thingShadow but it throws an error. In the connect event I try to subscribe but it throws the following error 'TypeError: device.operation is not a function'. I'm using node 0.12.x.

My code:

    var thingName = config.awsiot.thingName;
    var deviceShadow = awsIot.thingShadow({
        keyPath: config.awsiot.keyPath,
        certPath: config.awsiot.certPath,
        caPath: config.awsiot.caPath,
        clientId: thingName + "Shadow",
        region: 'eu-west-1'
    });

    deviceShadow.on('connect', function() {
        winston.info("MQTT Shadow: connected");

        deviceShadow.register(thingName, {persistentSubscribe: true});

        deviceShadow.subscribe("hello");
    });

The stacktrace:

/Users/maartenhuijsmans/GitProjects/triflux/node_modules/aws-iot-device-sdk/thing/index.js:650
            device.operation( topic, options, callback );
                   ^

TypeError: device.operation is not a function
    at thingShadowsClient._nonThingOperation (/Users/maartenhuijsmans/GitProjects/triflux/node_modules/aws-iot-device-sdk/thing/index.js:650:20)
    at thingShadowsClient.subscribe (/Users/maartenhuijsmans/GitProjects/triflux/node_modules/aws-iot-device-sdk/thing/index.js:672:12)
    at thingShadowsClient.<anonymous> (/Users/maartenhuijsmans/GitProjects/triflux/src/iot.js:142:22)
    at emitNone (events.js:67:13)
    at thingShadowsClient.emit (events.js:166:7)
    at MqttClient.<anonymous> (/Users/maartenhuijsmans/GitProjects/triflux/node_modules/aws-iot-device-sdk/thing/index.js:291:13)
    at emitNone (events.js:72:20)
    at MqttClient.emit (events.js:166:7)
    at MqttClient._handleConnack (/Users/maartenhuijsmans/GitProjects/triflux/node_modules/mqtt/lib/client.js:667:10)
    at MqttClient._handlePacket (/Users/maartenhuijsmans/GitProjects/triflux/node_modules/mqtt/lib/client.js:271:12)

Add .end() function to thingShadow

Allow end(froce, cb) function on the thingShadow client. Similar to the end function on the mqtt client: https://github.com/mqttjs/MQTT.js/blob/master/README.md#end

I've created an AWS Lambda function where I try to put the state on a thingShadow. Once that is done I want to close the client. If i'm not closing the client the AWS Lambda function acts erratic. When I push a state it tries to push the previous state as well which results in a 409 error conflict. This should be solved when i'm able to close the client.

I've tested it by adding the following snippet directly to thing/index.js:

   this.end = function(force, callback) {
     device.end(force, callback);
   }

Failing to Build aws-iot-device-sdk...ChildProcess.onExit error

Hi

I am facing the same issue as was logged in
#4 (Sorry for opening a new issue...I was not sure if the comments to the old issue are being tracked. If so, please close this as a duplicate. But please help give a resolution to this.)

The MQTT version is 1.4.3 as advised. Yet I am not able to have a successful build
"mqtt": "1.4.3",
"minimist": "1.2.0"

Node version is v4.2.2
node-gyp v3.0.3

Enclosed the cmd and the build output files
output.txt
image

Documentation for iOT SDK

Hello,

For each device how to create individual connections which can be maintained. For example.
I have one Hub which can communicate to Server and there are 3 Mobile devices who wants to control one Hub. As i have already developed similar thing but using signalr of asp.net. If i want to replace signalr with aws iot what should i do ? as my mobile app is already working calling asp.net web api.
So when web api receives event i want to publish that event to iot subscriber which is only one Hub.
Can you provide any good documentation for creating and maintaining connections. I am already maintaining connections in database so all i need is when iot connections starts from node.js i want to store in the same database that particular connection and when mobile app sends event i want to pass that event on that connection then my node.js program can handle it.

Device registry confusion

I'm confused by the concept of the "Device Registry" and while I know this isn't a help forum, it begs the question anyway, so here goes. At first I thought it was a Device MODEL Registry but as I read more in the docs, it appears to be a literal 1:1 Device Registry where every single serial numbered device needs to be registered. I'm fine with either approach but....

I thought the AWS IoT dashboard was just a friendly hand-holding exercise to introduce the concept and that's fine. But let's say I need to add thousands of devices to the registry? Maybe I have 50K devices that exist now and I'm shipping 1K devices every week.

I need to register these existing devices somehow as well as future ones that I'm shipping. I'm obviously not going to do that through the dashboard one at a time nor would I do that from AWS CLI, so what part of the docs am I completely missing? How does a newborn device attaining internet access for the first time provision itself with AWS IoT?

None of the examples show a device registering itself with the registry right?

connecting devices through a node js gateway

Hi Guys,

I have a setup where I have a bunch of devices behind a gateway running node js. Currently the node application receives messages and then ferries those to the cloud and receives messages from the cloud and then sends those to the devices.

Is there anway to use this SDK to enable a gateway device to pass messages between aws iot and my devices behind the node gateway?

Question: React Native

Hello 😀 . I'd like to know if there's any advise regarding using this with React Native. I'm aware of certain node core dependencies and that a browser version would be more suitable. I got the Paho browser client working and was able to successfully communicate with the AWS MQTT broker but using that approach would mean implementing by myself certain functionality which is already present in the AWS IoT JS SDK. So I tried both the browserize script (with a slight modification to generate a UMD bundle) and using webpack with the options seen in #58 but the code I ran did nothing (no errors popped up, which is good, but got no successful output either). I haven't done front end development for a while so I really don't know what I'm doing in the bundling process. Any pointers would be appreciated.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.