Skip to content

Commit 234d170

Browse files
committed
Release of version 2.2.0
1 parent 8095037 commit 234d170

16 files changed

+2760
-63
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
## [2.2.0](https://github.com/aws/aws-iot-device-sdk-js/releases/tag/v2.2.0) (Nov 29, 2017)
2+
3+
Features
4+
- Added AWS IoT Job API
5+
- Added options to enable AWS IoT Custom Auth
6+
- Added options to enalbe/disable AWS IoT metrics collection
7+
- Added new API to support packetsend and packetreceive events
8+
9+
Bugfixes/Imporovements
10+
- Modify Keepalive defaults to 300 secs to maintain consistency across SDKs
11+
- Expose shadow version from raw json object
12+
- Added samples to demonstrate AWS IoT Job API
13+
- Disabled MQTT.js default resubscribe.
14+
115
## [2.1.0](https://github.com/aws/aws-iot-device-sdk-js/releases/tag/v2.0.1) (Sep 28, 2017)
216

317
Features

README.md

Lines changed: 390 additions & 7 deletions
Large diffs are not rendered by default.

device/index.js

Lines changed: 121 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,28 @@ function prepareWebSocketUrl(options, awsAccessId, awsSecretKey, awsSTSToken) {
160160
awsAccessId, awsSecretKey, options.region, awsServiceName, '', today, now, options.debug, awsSTSToken);
161161
}
162162

163+
function prepareWebSocketCustomAuthUrl(options) {
164+
var path = '/mqtt';
165+
var hostName = options.host;
166+
167+
// Include the port number in the hostname if it's not
168+
// the standard wss port (443).
169+
//
170+
if (!isUndefined(options.port) && options.port !== 443) {
171+
hostName = options.host + ':' + options.port;
172+
}
173+
174+
return 'wss://' + hostName + path;
175+
}
176+
163177
function arrayEach(array, iterFunction) {
164178
for (var idx in array) {
165179
if (Object.prototype.hasOwnProperty.call(array, idx)) {
166180
iterFunction.call(this, array[idx], parseInt(idx, 10));
167181
}
168182
}
169-
}
183+
}
184+
170185
function getCredentials(ini) {
171186
//Get shared credential function from AWS SDK.
172187
var map = {};
@@ -295,6 +310,8 @@ function DeviceClient(options) {
295310
var drainingTimer = null;
296311
var drainTimeMs = 250;
297312

313+
//Default keep alive time interval in seconds.
314+
var defaultKeepalive = 300;
298315
//
299316
// These properties control the reconnect behavior of the MQTT Client. If
300317
// the MQTT client becomes disconnected, it will attempt to reconnect after
@@ -342,10 +359,28 @@ function DeviceClient(options) {
342359
//
343360
// Validate options, set default reconnect period if not specified.
344361
//
362+
var metricPrefix = "?SDK=JavaScript&Version=";
363+
var pjson = require('../package.json');
364+
var sdkVersion = pjson.version;
365+
var defaultUsername = metricPrefix + sdkVersion;
366+
345367
if (isUndefined(options) ||
346368
Object.keys(options).length === 0) {
347369
throw new Error(exceptions.INVALID_CONNECT_OPTIONS);
348370
}
371+
if (isUndefined(options.keepalive)) {
372+
options.keepalive = defaultKeepalive;
373+
}
374+
//
375+
// Metrics will be enabled by default unless the user explicitly disables it
376+
//
377+
if (isUndefined(options.enableMetrics) || options.enableMetrics === true){
378+
if (isUndefined(options.username)) {
379+
options.username = defaultUsername;
380+
} else {
381+
options.username += defaultUsername;
382+
}
383+
}
349384
if (!isUndefined(options.baseReconnectTimeMs)) {
350385
baseReconnectTimeMs = options.baseReconnectTimeMs;
351386
}
@@ -373,6 +408,10 @@ function DeviceClient(options) {
373408
currentReconnectTimeMs = baseReconnectTimeMs;
374409
options.reconnectPeriod = currentReconnectTimeMs;
375410
options.fastDisconnectDetection = true;
411+
//
412+
//SDK has its own logic to deal with auto resubscribe
413+
//
414+
options.resubscribe = false;
376415

377416
//
378417
// Verify that the reconnection timing parameters make sense.
@@ -414,47 +453,60 @@ function DeviceClient(options) {
414453

415454
//read and map certificates
416455
tlsReader(options);
417-
} else if (options.protocol === 'wss') {
418-
//
419-
// AWS access id and secret key
420-
// It first check Input options and Environment variables
421-
// If that not available, it will try to load credentials from default credential file
422-
if (!isUndefined(options.accessKeyId)) {
423-
awsAccessId = options.accessKeyId;
424-
} else {
425-
awsAccessId = process.env.AWS_ACCESS_KEY_ID;
426-
}
427-
if (!isUndefined(options.secretKey)) {
428-
awsSecretKey = options.secretKey;
429-
} else {
430-
awsSecretKey = process.env.AWS_SECRET_ACCESS_KEY;
431-
}
432-
if (!isUndefined(options.sessionToken)) {
433-
awsSTSToken = options.sessionToken;
434-
} else {
435-
awsSTSToken = process.env.AWS_SESSION_TOKEN;
436-
}
437-
if (isUndefined(awsAccessId) || isUndefined(awsSecretKey)) {
438-
var filename;
439-
try {
440-
if(!isUndefined(options.filename)) {
441-
filename = options.filename;
442-
} else {
443-
filename = _loadDefaultFilename();
444-
}
445-
var user_profile = options.profile || process.env.AWS_PROFILE || 'default';
446-
var creds = getCredentials(fs.readFileSync(filename, 'utf-8'));
447-
var profile = creds[user_profile];
448-
awsAccessId = profile.aws_access_key_id;
449-
awsSecretKey = profile.aws_secret_access_key;
450-
awsSTSToken = profile.aws_session_token;
456+
} else if (options.protocol === 'wss' || options.protocol === 'wss-custom-auth') {
457+
if (options.protocol === 'wss') {
458+
//
459+
// AWS access id and secret key
460+
// It first check Input options and Environment variables
461+
// If that not available, it will try to load credentials from default credential file
462+
if (!isUndefined(options.accessKeyId)) {
463+
awsAccessId = options.accessKeyId;
464+
} else {
465+
awsAccessId = process.env.AWS_ACCESS_KEY_ID;
466+
}
467+
if (!isUndefined(options.secretKey)) {
468+
awsSecretKey = options.secretKey;
469+
} else {
470+
awsSecretKey = process.env.AWS_SECRET_ACCESS_KEY;
471+
}
472+
if (!isUndefined(options.sessionToken)) {
473+
awsSTSToken = options.sessionToken;
474+
} else {
475+
awsSTSToken = process.env.AWS_SESSION_TOKEN;
476+
}
477+
if (isUndefined(awsAccessId) || isUndefined(awsSecretKey)) {
478+
var filename;
479+
try {
480+
if (!isUndefined(options.filename)) {
481+
filename = options.filename;
482+
} else {
483+
filename = _loadDefaultFilename();
484+
}
485+
var user_profile = options.profile || process.env.AWS_PROFILE || 'default';
486+
var creds = getCredentials(fs.readFileSync(filename, 'utf-8'));
487+
var profile = creds[user_profile];
488+
awsAccessId = profile.aws_access_key_id;
489+
awsSecretKey = profile.aws_secret_access_key;
490+
awsSTSToken = profile.aws_session_token;
451491
} catch (e) {
452492
console.log(e);
453-
console.log("Failed to read credentials from " + filename);
493+
console.log('Failed to read credentials from ' + filename);
454494
}
495+
}
496+
// AWS Access Key ID and AWS Secret Key must be defined
497+
if (isUndefined(awsAccessId) || (isUndefined(awsSecretKey))) {
498+
console.log('To connect via WebSocket/SigV4, AWS Access Key ID and AWS Secret Key must be passed either in options or as environment variables; see README.md');
499+
throw new Error(exceptions.INVALID_CONNECT_OPTIONS);
500+
}
501+
} else {
502+
if (isUndefined(options.customAuthHeaders)) {
503+
console.log('To authenticate with a custom authorizer, you must provide the required HTTP headers; see README.md');
504+
throw new Error(exceptions.INVALID_CONNECT_OPTIONS);
505+
}
455506
}
456-
if (!isUndefined(options.host)) {
457-
var pattern =/[a-zA-Z0-9]+\.iot\.([a-z]+-[a-z]+-[0-9]+)\.amazonaws\..+/;
507+
508+
if (!isUndefined(options.host) && isUndefined(options.region)) {
509+
var pattern = /[a-zA-Z0-9]+\.iot\.([a-z]+-[a-z]+-[0-9]+)\.amazonaws\..+/;
458510
var region = pattern.exec(options.host);
459511
if (region === null) {
460512
console.log('Host endpoint is not valid');
@@ -463,11 +515,6 @@ function DeviceClient(options) {
463515
options.region = region[1];
464516
}
465517
}
466-
// AWS Access Key ID and AWS Secret Key must be defined
467-
if (isUndefined(awsAccessId) || (isUndefined(awsSecretKey))) {
468-
console.log('To connect via WebSocket/SigV4, AWS Access Key ID and AWS Secret Key must be passed either in options or as environment variables; see README.md');
469-
throw new Error(exceptions.INVALID_CONNECT_OPTIONS);
470-
}
471518
// set port, do not override existing definitions if available
472519
if (isUndefined(options.port)) {
473520
options.port = 443;
@@ -480,7 +527,11 @@ function DeviceClient(options) {
480527
} else {
481528
options.websocketOptions.protocol = 'mqttv3.1';
482529
}
483-
}
530+
531+
if (options.protocol === 'wss-custom-auth') {
532+
options.websocketOptions.headers = options.customAuthHeaders;
533+
}
534+
}
484535

485536
if ((!isUndefined(options)) && (options.debug === true)) {
486537
console.log(options);
@@ -556,7 +607,8 @@ function DeviceClient(options) {
556607
}
557608

558609
function _wrapper(client) {
559-
if (options.protocol === 'wss') {
610+
var protocol = options.protocol;
611+
if (protocol === 'wss') {
560612
var url;
561613
//
562614
// If the access id and secret key are available, prepare the URL.
@@ -573,8 +625,15 @@ function DeviceClient(options) {
573625
}
574626

575627
options.url = url;
628+
} else if (protocol === 'wss-custom-auth') {
629+
options.url = prepareWebSocketCustomAuthUrl(options);
630+
if (options.debug === true) {
631+
console.log('using websockets custom auth, will connect to \'' + options.url + '\'...');
632+
}
633+
// Treat the request as a standard websocket request from here onwards
634+
protocol = 'wss';
576635
}
577-
return protocols[options.protocol](client, options);
636+
return protocols[protocol](client, options);
578637
}
579638

580639
var device = new mqtt.MqttClient(_wrapper, options);
@@ -748,6 +807,12 @@ function DeviceClient(options) {
748807
device.on('error', function(error) {
749808
that.emit('error', error);
750809
});
810+
device.on('packetsend', function(packet) {
811+
that.emit('packetsend', packet);
812+
});
813+
device.on('packetreceive', function(packet) {
814+
that.emit('packetreceive', packet);
815+
});
751816
device.on('message', function(topic, message, packet) {
752817
that.emit('message', topic, message, packet);
753818
});
@@ -834,6 +899,15 @@ function DeviceClient(options) {
834899
awsSecretKey = secretKey;
835900
awsSTSToken = sessionToken;
836901
};
902+
this.getWebsocketHeaders = function() {
903+
return options.websocketOptions.headers;
904+
};
905+
//
906+
// Call this function to update the custom auth headers
907+
//
908+
this.updateCustomAuthHeaders = function(newHeaders) {
909+
options.websocketOptions.headers = newHeaders;
910+
};
837911
//
838912
// Used for integration testing only
839913
//
@@ -855,3 +929,4 @@ module.exports.DeviceClient = DeviceClient;
855929
// Exported for unit testing only
856930
//
857931
module.exports.prepareWebSocketUrl = prepareWebSocketUrl;
932+
module.exports.prepareWebSocketCustomAuthUrl = prepareWebSocketCustomAuthUrl;

0 commit comments

Comments
 (0)