├── .jshintignore ├── common ├── core │ ├── .npmignore │ ├── devdoc │ │ ├── connection_string.docm │ │ ├── message_requirements.docm │ │ ├── dictionary_requirements.docm │ │ ├── shared_access_signature.docm │ │ ├── authorization_requirements.docm │ │ ├── errors_requirements.md │ │ ├── retry_operation_requirements.md │ │ └── properties_requirements.md │ ├── typings.json │ ├── tsconfig.json │ ├── readme.md │ ├── src │ │ ├── endpoint.ts │ │ ├── dictionary.ts │ │ ├── authorization.ts │ │ └── retry_error_filter.ts │ ├── common.js │ ├── test │ │ ├── _authorization_test.js │ │ ├── _endpoint_test.js │ │ ├── _message_test.js │ │ ├── _errors_test.js │ │ └── _connection_string_test.js │ ├── common.d.ts │ └── package.json └── transport │ ├── amqp │ ├── .npmignore │ ├── typings.json │ ├── tsconfig.json │ ├── index.d.ts │ ├── readme.md │ ├── index.js │ ├── package.json │ └── devdoc │ │ └── amqp_common_errors_requirements.md │ └── http │ ├── .npmignore │ ├── typings.json │ ├── index.d.ts │ ├── tsconfig.json │ ├── readme.md │ ├── index.js │ └── package.json ├── device ├── core │ ├── .npmignore │ ├── typings.json │ ├── tsconfig.json │ ├── src │ │ ├── device_method │ │ │ ├── index.ts │ │ │ └── device_method_request.ts │ │ ├── blob_upload │ │ │ ├── index.ts │ │ │ └── blob_upload_errors.ts │ │ └── shared_access_signature.ts │ ├── device.d.ts │ ├── test │ │ ├── blob_upload │ │ │ └── fake_storage_api.js │ │ ├── fake_transport.js │ │ ├── device_method │ │ │ └── _device_method_request_test.js │ │ └── _shared_access_signature_test.js │ ├── devdoc │ │ ├── device_method │ │ │ ├── device_method_request_requirements.md │ │ │ └── device_method_response_requirements.md │ │ ├── twin_errors_requirements.md │ │ ├── shared_access_signature.md │ │ ├── blob_upload │ │ │ ├── blob_uploader_requirements.md │ │ │ └── blob_upload_client_requirements.md │ │ └── connection_string_requirement.md │ ├── device.js │ └── package.json ├── transport │ ├── amqp │ │ ├── .npmignore │ │ ├── tsconfig.json │ │ ├── typings.json │ │ ├── index.d.ts │ │ ├── devdoc │ │ │ ├── amqp_device_errors_requirements.md │ │ │ └── amqp_receiver_requirements.md │ │ ├── test │ │ │ ├── _client_amqp_test_integration.js │ │ │ ├── _client_amqp_ws_test_integration.js │ │ │ └── _amqp_device_errors_test.js │ │ ├── index.js │ │ ├── src │ │ │ └── amqp_ws.ts │ │ ├── readme.md │ │ └── package.json │ ├── http │ │ ├── .npmignore │ │ ├── typings.json │ │ ├── tsconfig.json │ │ ├── index.d.ts │ │ ├── test │ │ │ └── _client_test_integration.js │ │ ├── index.js │ │ ├── readme.md │ │ ├── package.json │ │ └── devdoc │ │ │ └── http_errors_requirements.md │ └── mqtt │ │ ├── .npmignore │ │ ├── typings.json │ │ ├── tsconfig.json │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── test │ │ ├── _fake_mqtt.js │ │ └── _mqtt_ws_test.js │ │ ├── readme.md │ │ ├── src │ │ └── mqtt_ws.ts │ │ ├── package.json │ │ └── devdoc │ │ └── mqtt_translate_errors_requirements.md ├── ts-samples │ ├── tsconfig.json │ ├── package.json │ └── sample_device.ts ├── node-red │ ├── azureiothub │ │ ├── icons │ │ │ └── azureiothub.png │ │ └── azureiothub.html │ ├── package.json │ ├── LICENSE │ └── README.md ├── samples │ ├── package.json │ ├── device_blob_upload.js │ ├── send_batch_http.js │ ├── dmpatterns_reboot_device.js │ └── device_methods.js └── readme.md ├── lts_branches.png ├── service ├── .npmignore ├── typings.json ├── samples │ ├── typescript_sample │ │ ├── tsconfig.json │ │ ├── typings.json │ │ ├── package.json │ │ └── registry_sample.ts │ ├── package.json │ ├── job_query.js │ ├── twin_query.js │ ├── device_method.js │ ├── create_device_with_cert.js │ ├── receive_file_notifications.js │ ├── send_c2d_message.js │ ├── twin.js │ ├── registry_sample.js │ ├── dmpatterns_reboot_service.js │ ├── dmpatterns_fwupdate_service.js │ └── registry_addUpdateRemoveDevicesSample.js ├── tsconfig.json ├── devdoc │ ├── amqp_service_errors_requirements.md │ ├── connection_string_requirements.md │ ├── device_requirements.md │ ├── shared_access_signature_requirements.md │ └── service_amqp_ws_requirement.md ├── iothub.d.ts ├── test │ ├── _client_test_integration.js │ ├── _connection_string_test.js │ ├── _amqp_ws_test.js │ ├── _amqp_service_errors_test.js │ ├── amqp_simulated.js │ └── _shared_access_signature_test.js ├── src │ ├── interfaces.ts │ ├── connection_string.ts │ ├── amqp_service_errors.ts │ ├── amqp_ws.ts │ └── shared_access_signature.ts ├── iothub.js └── package.json ├── ts-e2e ├── tsconfig.json ├── package.json └── src │ ├── registry.tests.ts │ └── testUtils.ts ├── network_e2e ├── Dockerfile.win.test ├── Dockerfile.win.base ├── run-badnetwork-e2e.cmd ├── tests │ ├── delete-device.js │ ├── create-device.js │ └── package.json └── docker-compose.yml ├── jenkins ├── node_docker │ ├── dockerfiles │ │ ├── aziot-node4.dockerfile │ │ ├── aziot-node5.dockerfile │ │ ├── aziot-node6.dockerfile │ │ ├── aziot-node010.dockerfile │ │ └── aziot-node012.dockerfile │ ├── docker_build_cleanup.sh │ ├── docker-compose.yml │ └── docker_build.sh ├── linux_node.sh └── windows_node.cmd ├── .jshintrc ├── .gitattributes ├── e2etests ├── test │ ├── device_teardown.js │ ├── service.js │ └── testUtils.js └── package.json ├── .github ├── PULL_REQUEST_TEMPLATE.md └── ISSUE_TEMPLATE.md ├── LICENSE ├── doc └── dmpatterns.md └── tslint.json /.jshintignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | **/coverage -------------------------------------------------------------------------------- /common/core/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | lib/**/*.map -------------------------------------------------------------------------------- /device/core/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | lib/**/*.map -------------------------------------------------------------------------------- /lts_branches.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikyau/azure-iot-sdk-node/master/lts_branches.png -------------------------------------------------------------------------------- /common/transport/amqp/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | lib/**/*.map -------------------------------------------------------------------------------- /common/transport/http/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | lib/**/*.map -------------------------------------------------------------------------------- /device/transport/amqp/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | lib/**/*.map -------------------------------------------------------------------------------- /device/transport/http/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | lib/**/*.map -------------------------------------------------------------------------------- /device/transport/mqtt/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | lib/**/*.map -------------------------------------------------------------------------------- /service/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | lib/**/*.map 7 | typings/ -------------------------------------------------------------------------------- /device/ts-samples/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "sourceMap": true 5 | } 6 | } -------------------------------------------------------------------------------- /common/core/devdoc/connection_string.docm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikyau/azure-iot-sdk-node/master/common/core/devdoc/connection_string.docm -------------------------------------------------------------------------------- /common/core/devdoc/message_requirements.docm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikyau/azure-iot-sdk-node/master/common/core/devdoc/message_requirements.docm -------------------------------------------------------------------------------- /common/core/devdoc/dictionary_requirements.docm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikyau/azure-iot-sdk-node/master/common/core/devdoc/dictionary_requirements.docm -------------------------------------------------------------------------------- /common/core/devdoc/shared_access_signature.docm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikyau/azure-iot-sdk-node/master/common/core/devdoc/shared_access_signature.docm -------------------------------------------------------------------------------- /common/core/devdoc/authorization_requirements.docm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikyau/azure-iot-sdk-node/master/common/core/devdoc/authorization_requirements.docm -------------------------------------------------------------------------------- /device/node-red/azureiothub/icons/azureiothub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikyau/azure-iot-sdk-node/master/device/node-red/azureiothub/icons/azureiothub.png -------------------------------------------------------------------------------- /ts-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "lib", 4 | "target": "es5", 5 | "sourceRoot": "src", 6 | "sourceMap": true 7 | } 8 | } -------------------------------------------------------------------------------- /network_e2e/Dockerfile.win.test: -------------------------------------------------------------------------------- 1 | FROM networke2e/node-base 2 | ARG SDK_ROOT 3 | COPY . $SDK_ROOT 4 | ENV SDK_ROOT=$SDK_ROOT 5 | RUN %SDK_ROOT%\build\dev-setup.cmd --network_e2e 6 | -------------------------------------------------------------------------------- /jenkins/node_docker/dockerfiles/aziot-node4.dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:4 2 | COPY . /tmp/azure-iot-sdks 3 | ENV NPM_CONFIG_LOGLEVEL warn 4 | CMD /tmp/azure-iot-sdks/jenkins/linux_node.sh 5 | -------------------------------------------------------------------------------- /jenkins/node_docker/dockerfiles/aziot-node5.dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:5 2 | COPY . /tmp/azure-iot-sdks 3 | ENV NPM_CONFIG_LOGLEVEL warn 4 | CMD /tmp/azure-iot-sdks/jenkins/linux_node.sh 5 | -------------------------------------------------------------------------------- /jenkins/node_docker/dockerfiles/aziot-node6.dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:6 2 | COPY . /tmp/azure-iot-sdks 3 | ENV NPM_CONFIG_LOGLEVEL warn 4 | CMD /tmp/azure-iot-sdks/jenkins/linux_node.sh 5 | -------------------------------------------------------------------------------- /service/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iothub", 3 | "main": "iothub.d.ts", 4 | "dependencies": { 5 | "amqp10": "registry:npm/amqp10#3.3.1+20170124180914" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /jenkins/node_docker/dockerfiles/aziot-node010.dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:0.10 2 | COPY . /tmp/azure-iot-sdks 3 | ENV NPM_CONFIG_LOGLEVEL warn 4 | CMD /tmp/azure-iot-sdks/jenkins/linux_node.sh 5 | -------------------------------------------------------------------------------- /jenkins/node_docker/dockerfiles/aziot-node012.dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:0.12 2 | COPY . /tmp/azure-iot-sdks 3 | ENV NPM_CONFIG_LOGLEVEL warn 4 | CMD /tmp/azure-iot-sdks/jenkins/linux_node.sh 5 | -------------------------------------------------------------------------------- /common/core/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-common", 3 | "main": "common.d.ts", 4 | "dependencies": {}, 5 | "globalDependencies": { 6 | "node": "registry:dt/node#6.0.0+20160807145350" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /device/core/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-device", 3 | "main": "device.d.ts", 4 | "dependencies": {}, 5 | "globalDependencies": { 6 | "node": "registry:dt/node#6.0.0+20160813124416" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /common/transport/http/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-http-base", 3 | "main": "index.d.ts", 4 | "dependencies": {}, 5 | "globalDependencies": { 6 | "node": "registry:dt/node#6.0.0+20160807145350" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /device/transport/http/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-device-http", 3 | "main": "index.d.ts", 4 | "dependencies": {}, 5 | "globalDependencies": { 6 | "node": "registry:dt/node#6.0.0+20160813124416" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /device/transport/mqtt/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-device-mqtt", 3 | "main": "index.d.ts", 4 | "dependencies": {}, 5 | "globalDependencies": { 6 | "node": "registry:dt/node#6.0.0+20160815222444" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /common/transport/http/index.d.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | export { Http } from './lib/http'; 5 | -------------------------------------------------------------------------------- /common/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target":"es5", 5 | "sourceMap": true, 6 | "declaration": true 7 | }, 8 | "include": [ 9 | "./src/**/*" 10 | ] 11 | } -------------------------------------------------------------------------------- /device/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target":"es5", 5 | "sourceMap": true, 6 | "declaration": true 7 | }, 8 | "include": [ 9 | "./src/**/*.ts" 10 | ] 11 | } -------------------------------------------------------------------------------- /common/transport/amqp/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-amqp-base", 3 | "main": "index.d.ts", 4 | "dependencies": { 5 | "amqp10": "registry:npm/amqp10#3.3.1+20170124180914", 6 | "bluebird": "registry:npm/bluebird#3.5.0+20170314181206" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /common/transport/http/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target":"es5", 5 | "sourceMap": true, 6 | "declaration": true 7 | }, 8 | "include": [ 9 | "./src/**/*" 10 | ] 11 | } -------------------------------------------------------------------------------- /device/transport/amqp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target":"es5", 5 | "sourceMap": true, 6 | "declaration": true 7 | }, 8 | "include": [ 9 | "./src/**/*.ts" 10 | ] 11 | } -------------------------------------------------------------------------------- /device/transport/http/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target":"es5", 5 | "sourceMap": true, 6 | "declaration": true 7 | }, 8 | "include": [ 9 | "./src/**/*.ts" 10 | ] 11 | } -------------------------------------------------------------------------------- /device/transport/mqtt/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target":"es5", 5 | "sourceMap": true, 6 | "declaration": true 7 | }, 8 | "include": [ 9 | "./src/**/*.ts" 10 | ] 11 | } -------------------------------------------------------------------------------- /service/samples/typescript_sample/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "removeComments": false, 7 | "noImplicitAny": true, 8 | "suppressImplicitAnyIndexErrors": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /device/transport/amqp/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-device-amqp", 3 | "main": "index.d.ts", 4 | "dependencies": { 5 | "amqp10": "registry:npm/amqp10#3.3.1+20170124180914" 6 | }, 7 | "globalDependencies": { 8 | "node": "registry:dt/node#6.0.0+20160813124416" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /service/samples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "registry_sample", 3 | "version": "0.0.1", 4 | "private": true, 5 | "main": "registry_sample.js", 6 | "author": "Microsoft Corp.", 7 | "license": "MIT", 8 | "dependencies": { 9 | "azure-iothub": "1.1.15", 10 | "azure-storage": "^1.2.0" 11 | } 12 | } -------------------------------------------------------------------------------- /device/core/src/device_method/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | export { DeviceMethodRequest } from './device_method_request'; 7 | export { DeviceMethodResponse } from './device_method_response'; 8 | -------------------------------------------------------------------------------- /common/transport/amqp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target":"es5", 5 | "sourceMap": true, 6 | "declaration": true 7 | }, 8 | "include": [ 9 | "typings/index.d.ts", 10 | "./src/**/*.ts" 11 | ], 12 | "exclude": [ 13 | "./lib" 14 | ] 15 | } -------------------------------------------------------------------------------- /device/core/src/blob_upload/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | export { BlobUploadClient } from './blob_upload_client'; 7 | export { BlobSasError, BlobUploadNotificationError } from './blob_upload_errors'; 8 | -------------------------------------------------------------------------------- /device/transport/http/index.d.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | import { Client } from 'azure-iot-device'; 5 | export { Http } from './lib/http'; 6 | 7 | export declare function clientFromConnectionString(connectionString: string): Client; 8 | -------------------------------------------------------------------------------- /service/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target":"es5", 5 | "sourceMap": true, 6 | "declaration": true 7 | }, 8 | "include": [ 9 | "typings/index.d.ts", 10 | "./src/**/*.ts" 11 | ], 12 | "exclude": [ 13 | "./lib", 14 | "./samples" 15 | ] 16 | } -------------------------------------------------------------------------------- /network_e2e/Dockerfile.win.base: -------------------------------------------------------------------------------- 1 | FROM microsoft/windowsservercore 2 | RUN @powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%ALLUSERPROFILE%\chocolatey\bin 3 | RUN choco install nodejs -yfd 4 | RUN choco install git -yfd 5 | RUN choco install docker -yfd 6 | RUN choco install yarn -yfd 7 | -------------------------------------------------------------------------------- /device/transport/amqp/index.d.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | import { Client } from 'azure-iot-device'; 5 | 6 | export { Amqp } from './lib/amqp'; 7 | export { AmqpWs } from './lib/amqp_ws'; 8 | export declare function clientFromConnectionString(connectionString: string): Client; 9 | -------------------------------------------------------------------------------- /device/transport/mqtt/index.d.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | import { Client } from 'azure-iot-device'; 5 | 6 | export { Mqtt } from './lib/mqtt'; 7 | export { MqttWs } from './lib/mqtt_ws'; 8 | export declare function clientFromConnectionString(connectionString: string): Client; 9 | -------------------------------------------------------------------------------- /common/transport/amqp/index.d.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | export { Amqp } from './lib/amqp'; 5 | export { AmqpMessage } from './lib/amqp_message'; 6 | export { AmqpReceiver } from './lib/amqp_receiver'; 7 | export { AmqpTransportError, translateError } from './lib/amqp_common_errors'; 8 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "mocha": true, 4 | "bitwise": true, 5 | "curly": false, 6 | "eqeqeq": true, 7 | "forin": true, 8 | "immed": true, 9 | "latedef": false, 10 | "newcap": true, 11 | "noarg": true, 12 | "noempty": true, 13 | "nonew": true, 14 | "regexp": true, 15 | "undef": true, 16 | "unused": true, 17 | "strict": true, 18 | "globalstrict": true, 19 | "trailing": true 20 | } -------------------------------------------------------------------------------- /service/samples/typescript_sample/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "registry_sample", 3 | "dependencies": { 4 | "amqp10": "registry:npm/amqp10#3.1.4+20160601175358", 5 | "bluebird": "registry:npm/bluebird#3.4.1+20160811213708" 6 | }, 7 | "globalDependencies": { 8 | "es2015-promise": "registry:env/es2015-promise#1.0.0+20160526151700", 9 | "node": "registry:dt/node#6.0.0+20160807145350" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /common/core/readme.md: -------------------------------------------------------------------------------- 1 | #azure-iot-common 2 | Internal library of components shared between the Azure IoT device and service SDKs. 3 | 4 | [![npm version](https://badge.fury.io/js/azure-iot-common.svg)](https://badge.fury.io/js/azure-iot-common) 5 | 6 | NOTE: You generally don't want to reference this package directly. The components you need should be exposed by packages in the device (`azure-iot-device*`) or service (`azure-iothub`) SDKs. -------------------------------------------------------------------------------- /jenkins/node_docker/docker_build_cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | build_root=$(cd "$(dirname "$0")/../.." && pwd) 4 | dockerdir=$build_root/jenkins/node_docker 5 | 6 | # Stop all containers 7 | docker-compose -f $dockerdir/docker-compose.yml down 8 | 9 | # Remove containers 10 | docker-compose -f $dockerdir/docker-compose.yml ps -q | xargs docker rm -f 11 | 12 | # Remove temporary images used by containers 13 | docker images -q nodebuild | xargs docker rmi -------------------------------------------------------------------------------- /network_e2e/run-badnetwork-e2e.cmd: -------------------------------------------------------------------------------- 1 | @setlocal 2 | @echo off 3 | 4 | set PROTOCOL=%1 5 | set TESTNAME=%2 6 | 7 | set SDK_ROOT=C:\\node-sdk 8 | set TESTS_ROOT=%SDK_ROOT%\\network_e2e\\tests 9 | 10 | pushd %TESTS_ROOT% 11 | call node run-badnetwork-e2e.js --protocol=%PROTOCOL% --testName=%TESTNAME% --deviceConnectionString=%DEVICE_CONNECTION_STRING% 12 | set exitcode=%errorlevel% 13 | popd 14 | 15 | :exitcode 16 | exit /b %exitcode% 17 | 18 | @endlocal 19 | -------------------------------------------------------------------------------- /common/transport/amqp/readme.md: -------------------------------------------------------------------------------- 1 | #azure-iot-amqp-base 2 | Internal library of AMQP-specific components shared between the Azure IoT device and service SDKs. 3 | 4 | [![npm version](https://badge.fury.io/js/azure-iot-amqp-base.svg)](https://badge.fury.io/js/azure-iot-amqp-base) 5 | 6 | NOTE: You generally don't want to reference this package directly. The AMQP components you need should be exposed by packages in the device (`azure-iot-device-amqp`) or service (`azure-iothub`) SDKs. -------------------------------------------------------------------------------- /common/transport/http/readme.md: -------------------------------------------------------------------------------- 1 | #azure-iot-http-base 2 | Internal library of HTTP-specific components shared between the Azure IoT device and service SDKs. 3 | 4 | [![npm version](https://badge.fury.io/js/azure-iot-http-base.svg)](https://badge.fury.io/js/azure-iot-http-base) 5 | 6 | NOTE: You generally don't want to reference this package directly. The HTTP components you need should be exposed by packages in the device (`azure-iot-device-http`) or service (`azure-iothub`) SDKs. -------------------------------------------------------------------------------- /common/transport/http/index.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | /** 7 | * The `azure-iot-http-base` module contains HTTP support code common to the Azure IoT Hub Device and Service SDKs. 8 | * @private 9 | * @module azure-iot-http-base 10 | */ 11 | 12 | module.exports = { 13 | Http: require('./lib/http.js').Http 14 | }; -------------------------------------------------------------------------------- /network_e2e/tests/delete-device.js: -------------------------------------------------------------------------------- 1 | var Registry = require('azure-iothub').Registry; 2 | var DeviceConnectionString = require('azure-iot-device').ConnectionString; 3 | 4 | var registry = Registry.fromConnectionString(process.env.IOTHUB_CONNECTION_STRING); 5 | var deviceId = process.argv[2]; 6 | 7 | registry.delete(deviceId, function(err, deviceInfo) { 8 | if (err) { 9 | console.error(err.toString()); 10 | process.exit(1); 11 | } else { 12 | process.exit(0); 13 | } 14 | }); -------------------------------------------------------------------------------- /service/samples/typescript_sample/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "registry_sample", 3 | "version": "0.0.1", 4 | "private": true, 5 | "main": "registry_sample.js", 6 | "author": "Microsoft Corp.", 7 | "license": "MIT", 8 | "dependencies": { 9 | "azure-iothub": "1.1.9" 10 | }, 11 | "scripts": { 12 | "build": "tsc -p .", 13 | "lint": "tslint -c ../../../tslint.json --type-check --project tsconfig.json", 14 | "test": "npm -s run lint", 15 | "postinstall": "typings install" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /service/devdoc/amqp_service_errors_requirements.md: -------------------------------------------------------------------------------- 1 | # azure-iothub.translateError Requirements 2 | 3 | ## Overview 4 | `translateError` is a method that translates AMQP errors that are specific to the service SDK into Azure IoT Hub errors, effectively abstracting the error that is returned to the SDK user of from the transport layer. 5 | 6 | ## Requirements 7 | 8 | **SRS_NODE_DEVICE_AMQP_SERVICE_ERRORS_16_001: [** `translateError` shall return an `DeviceMaximumQueueDepthExceededError` if the AMQP error condition is `amqp:resource-limit-exceeded`. **]** -------------------------------------------------------------------------------- /device/transport/amqp/devdoc/amqp_device_errors_requirements.md: -------------------------------------------------------------------------------- 1 | # azure-iot-device-amqp.translateError Requirements 2 | 3 | ## Overview 4 | `translateError` is a method that translates AMQP errors that are specific to the device SDK into Azure IoT Hub errors, effectively abstracting the error that is returned to the SDK user of from the transport layer. 5 | 6 | ## Requirements 7 | 8 | **SRS_NODE_DEVICE_AMQP_DEVICE_ERRORS_16_001: [** `translateError` shall return an `IotHubQuotaExceededError` if the AMQP error condition is `amqp:resource-limit-exceeded`. **]** -------------------------------------------------------------------------------- /device/node-red/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-red-contrib-azureiothubnode", 3 | "version": "0.1.17", 4 | "description": "An Azure IoT Hub node for node-red", 5 | "author": "Microsoft Corp.", 6 | "license": "MIT", 7 | "dependencies": { 8 | "azure-iot-device": "1.1.17", 9 | "azure-iot-device-amqp": "1.1.17", 10 | "azure-iot-device-http": "1.1.17", 11 | "azure-iot-device-mqtt": "1.1.17" 12 | }, 13 | "node-red": { 14 | "nodes": { 15 | "azureiothubnode": "azureiothub/azureiothub.js" 16 | } 17 | }, 18 | "keywords": [ 19 | "node-red" 20 | ] 21 | } -------------------------------------------------------------------------------- /device/core/device.d.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | export { Client } from './lib/client'; 5 | export import ConnectionString = require('./lib/connection_string'); 6 | export import SharedAccessSignature = require('./lib/shared_access_signature'); 7 | export { StableConnectionTransport, TwinTransport, BatchingTransport, ClientConfig } from './lib/interfaces'; 8 | export { Message } from 'azure-iot-common'; 9 | export { DeviceMethodRequest, DeviceMethodResponse } from './lib/device_method'; 10 | -------------------------------------------------------------------------------- /device/transport/amqp/test/_client_amqp_test_integration.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var Registry = require('azure-iothub').Registry; 7 | var Amqp = require('../lib/amqp.js').Amqp; 8 | var clientTests = require('azure-iot-device/test/_client_common_testrun.js'); 9 | 10 | describe('Over real AMQPS', function () { 11 | this.timeout(60000); 12 | var registry = Registry.fromConnectionString(process.env.IOTHUB_CONNECTION_STRING); 13 | clientTests.sendEventTests(Amqp, registry); 14 | }); -------------------------------------------------------------------------------- /device/transport/amqp/test/_client_amqp_ws_test_integration.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var Registry = require('azure-iothub').Registry; 7 | var AmqpWs = require('../lib/amqp_ws.js').AmqpWs; 8 | var clientTests = require('azure-iot-device/test/_client_common_testrun.js'); 9 | 10 | 11 | describe('Over AMQP/WS', function () { 12 | this.timeout(60000); 13 | var registry = Registry.fromConnectionString(process.env.IOTHUB_CONNECTION_STRING); 14 | clientTests.sendEventTests(AmqpWs, registry); 15 | }); -------------------------------------------------------------------------------- /service/iothub.d.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | export { Client } from './lib/client'; 5 | export import ConnectionString = require('./lib/connection_string'); 6 | export { Registry } from './lib/registry'; 7 | export import SharedAccessSignature = require('./lib/shared_access_signature'); 8 | export { Amqp } from './lib/amqp'; 9 | export { AmqpWs } from './lib/amqp_ws'; 10 | export { DeviceMethodParams } from './lib/interfaces'; 11 | export { JobClient } from './lib/job_client'; 12 | export { Device } from './lib/device'; 13 | -------------------------------------------------------------------------------- /common/core/devdoc/errors_requirements.md: -------------------------------------------------------------------------------- 1 | # azure-iot-common.errors Requirements 2 | 3 | ## Overview 4 | the `errors` module contain custom errors used by the SDK to abstract user code from transport-specific errors. 5 | 6 | ## Requirements: All errors 7 | 8 | **SRS_NODE_COMMON_ERRORS_16_001: [** All custom error types shall inherit from the standard Javascript error object. **]** 9 | 10 | **SRS_NODE_COMMON_ERRORS_16_002: [** All custom error types shall contain a valid call stack. **]** 11 | 12 | **SRS_NODE_COMMON_ERRORS_16_003: [** All custom error types shall accept a message as an argument of the constructor and shall populate their message property with it. **]** 13 | -------------------------------------------------------------------------------- /common/transport/amqp/index.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | /** 7 | * The `azure-iot-amqp-base` module contains AMQP support code common to the Azure IoT Hub Device and Service SDKs. 8 | * 9 | * @private 10 | * @module azure-iot-amqp-base 11 | */ 12 | 13 | module.exports = { 14 | Amqp: require('./lib/amqp.js').Amqp, 15 | AmqpMessage: require('./lib/amqp_message.js').AmqpMessage, 16 | AmqpReceiver: require('./lib/amqp_receiver.js').AmqpReceiver, 17 | translateError: require('./lib/amqp_common_errors.js').translateError 18 | }; -------------------------------------------------------------------------------- /device/transport/http/test/_client_test_integration.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var Registry = require('azure-iothub').Registry; 7 | var Http = require('../lib/http.js').Http; 8 | var clientTests = require('azure-iot-device/test/_client_common_testrun.js'); 9 | 10 | describe('Over real HTTPS', function () { 11 | this.timeout(60000); 12 | var registry = Registry.fromConnectionString(process.env.IOTHUB_CONNECTION_STRING); 13 | clientTests.sendEventTests(Http, registry); 14 | clientTests.sendEventBatchTests(Http, registry); 15 | }); 16 | -------------------------------------------------------------------------------- /device/samples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iot-device-samples", 3 | "version": "0.0.1", 4 | "private": true, 5 | "description": "Simple samples demonstrating how to use the Azure IoT device SDK for Node.js", 6 | "author": "Microsoft Corp.", 7 | "license": "MIT", 8 | "dependencies": { 9 | "azure-iot-device": "1.1.17", 10 | "azure-iot-device-amqp": "1.1.17", 11 | "azure-iot-device-http": "1.1.17", 12 | "azure-iot-device-mqtt": "1.1.17", 13 | "es5-shim": "^4.5.9", 14 | "lodash": "^4.15.0" 15 | }, 16 | "devDependencies": { 17 | "jshint": "^2.9.2" 18 | }, 19 | "scripts": { 20 | "lint": "jshint --show-non-errors .", 21 | "test": "npm -s run lint" 22 | } 23 | } -------------------------------------------------------------------------------- /device/transport/http/index.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var device = require('azure-iot-device'); 7 | var Http = require('./lib/http.js').Http; 8 | 9 | /** 10 | * The `azure-iot-device-http` module provides support for the HTTPS protocol to the device [client]{@link module:azure-iot-device.Client}. 11 | * 12 | * @module azure-iot-device-http 13 | * @requires module:azure-iot-device 14 | */ 15 | 16 | module.exports = { 17 | Http: Http, 18 | clientFromConnectionString: function (connectionString) { 19 | return device.Client.fromConnectionString(connectionString, Http); 20 | } 21 | }; -------------------------------------------------------------------------------- /device/core/test/blob_upload/fake_storage_api.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | function FakeBlobService() {} 7 | 8 | FakeBlobService.prototype.createBlockBlobFromStream = function (containerName, blobName, stream, streamLength, done) { 9 | done('fakeError', 'fakeBody', 'fakeResponse'); 10 | }; 11 | 12 | function createBlobServiceWithSas (host, sasToken) { 13 | if (!host) throw new ReferenceError('host cannot be falsy'); 14 | if (!sasToken) throw new ReferenceError('host cannot be falsy'); 15 | 16 | return new FakeBlobService(); 17 | } 18 | 19 | module.exports = { 20 | createBlobServiceWithSas: createBlobServiceWithSas 21 | }; -------------------------------------------------------------------------------- /jenkins/linux_node.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Microsoft. All rights reserved. 3 | # Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | 5 | build_root=$(cd "$(dirname "$0")/.." && pwd) 6 | cd $build_root 7 | 8 | # Disable the npm progress bar (supposedly faster) 9 | npm set progress=false 10 | 11 | # Set up links in the npm cache to ensure we're exercising all the code in 12 | # the repo, rather than downloading released versions of our packages from 13 | # npm. 14 | build/dev-setup.sh 15 | [ $? -eq 0 ] || exit $? 16 | 17 | # Lint all JavaScript code and run unit + integration tests 18 | build/build.sh --min --integration-tests --e2e-tests 19 | [ $? -eq 0 ] || exit $? 20 | 21 | # No need to run dev-teardown.sh anymore since we're running of containers -------------------------------------------------------------------------------- /common/core/src/endpoint.ts: -------------------------------------------------------------------------------- 1 | /*! Copyright (c) Microsoft. All rights reserved. 2 | *! Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | export const apiVersion = '2017-06-30'; 8 | 9 | export function devicePath(id: string): string { 10 | return '/devices/' + id; 11 | } 12 | 13 | export function eventPath(id: string): string { 14 | return devicePath(id) + '/messages/events'; 15 | } 16 | 17 | export function messagePath(id: string): string { 18 | return devicePath(id) + '/messages/devicebound'; 19 | } 20 | 21 | export function feedbackPath(id: string, lockToken: string): string { 22 | return messagePath(id) + '/' + lockToken; 23 | } 24 | 25 | export function versionQueryString(): string { 26 | return '?api-version=' + apiVersion; 27 | } 28 | -------------------------------------------------------------------------------- /device/transport/mqtt/index.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var device = require('azure-iot-device'); 7 | var Mqtt = require('./lib/mqtt.js').Mqtt; 8 | var MqttWs = require('./lib/mqtt_ws.js').MqttWs; 9 | 10 | /** 11 | * The `azure-iot-device-mqtt` module provides support the MQTT protocol to the device [client]{@link module:azure-iot-device.Client} using secure sockets. 12 | * 13 | * @module azure-iot-device-mqtt 14 | * @requires module:azure-iot-device 15 | */ 16 | 17 | module.exports = { 18 | Mqtt: Mqtt, 19 | MqttWs: MqttWs, 20 | clientFromConnectionString: function (connectionString) { 21 | return device.Client.fromConnectionString(connectionString, Mqtt); 22 | } 23 | }; -------------------------------------------------------------------------------- /device/transport/amqp/index.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var device = require('azure-iot-device'); 7 | var Amqp = require('./lib/amqp.js').Amqp; 8 | var AmqpWs = require('./lib/amqp_ws.js').AmqpWs; 9 | 10 | /** 11 | * The `azure-iot-device-amqp` module provides support for the AMQP protocol over secure 12 | * sockets to the device [client]{@link module:azure-iot-device.Client}. 13 | * 14 | * @module azure-iot-device-amqp 15 | * @requires module:azure-iot-device 16 | */ 17 | 18 | module.exports = { 19 | Amqp: Amqp, 20 | AmqpWs: AmqpWs, 21 | clientFromConnectionString: function (connectionString) { 22 | return device.Client.fromConnectionString(connectionString, Amqp); 23 | } 24 | }; -------------------------------------------------------------------------------- /service/samples/job_query.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 'use strict'; 4 | 5 | var JobClient = require('azure-iothub').JobClient; 6 | 7 | var connectionString = ''; 8 | var jobClient = JobClient.fromConnectionString(connectionString); 9 | 10 | var query = jobClient.createQuery(); 11 | var onResults = function(err, results) { 12 | if (err) { 13 | console.error('Failed to fetch the results: ' + err.message); 14 | } else { 15 | // Do something with the results 16 | results.forEach(function(job) { 17 | console.log(JSON.stringify(job, null, 2)); 18 | }); 19 | 20 | if (query.hasMoreResults) { 21 | query.next(onResults); 22 | } 23 | } 24 | }; 25 | 26 | query.next(onResults); -------------------------------------------------------------------------------- /service/samples/twin_query.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 'use strict'; 4 | 5 | var Registry = require('azure-iothub').Registry; 6 | 7 | var connectionString = ''; 8 | var registry = Registry.fromConnectionString(connectionString); 9 | 10 | var query = registry.createQuery('SELECT * FROM devices', 100); 11 | var onResults = function(err, results) { 12 | if (err) { 13 | console.error('Failed to fetch the results: ' + err.message); 14 | } else { 15 | // Do something with the results 16 | results.forEach(function(twin) { 17 | console.log(twin.deviceId); 18 | }); 19 | 20 | if (query.hasMoreResults) { 21 | query.nextAsTwin(onResults); 22 | } 23 | } 24 | }; 25 | 26 | query.nextAsTwin(onResults); -------------------------------------------------------------------------------- /network_e2e/tests/create-device.js: -------------------------------------------------------------------------------- 1 | var uuid = require('uuid'); 2 | 3 | var Registry = require('azure-iothub').Registry; 4 | var ServiceConnectionString = require('azure-iothub').ConnectionString; 5 | var DeviceConnectionString = require('azure-iot-device').ConnectionString; 6 | 7 | var registry = Registry.fromConnectionString(process.env.IOTHUB_CONNECTION_STRING); 8 | var hostName = ServiceConnectionString.parse(process.env.IOTHUB_CONNECTION_STRING).HostName; 9 | var deviceDesc = { 10 | deviceId: process.argv[2] 11 | }; 12 | 13 | registry.create(deviceDesc, function(err, deviceInfo) { 14 | if (err) { 15 | console.error(err.toString()); 16 | process.exit(1); 17 | } else { 18 | var connStr = DeviceConnectionString.createWithSharedAccessKey(hostName, deviceInfo.deviceId, deviceInfo.authentication.symmetricKey.primaryKey); 19 | console.log(connStr); 20 | process.exit(0); 21 | } 22 | }); -------------------------------------------------------------------------------- /network_e2e/tests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "az-iot-sdk-node-network-e2e-test", 3 | "version": "0.0.1", 4 | "description": "Suite of tests messing with the network connection in order to test the device client reliability", 5 | "author": "Microsoft Corp.", 6 | "license": "MIT", 7 | "main": "run-test.js", 8 | "bin": { 9 | "create-device": "./create-device.js", 10 | "delete-device": "./delete-device.js" 11 | }, 12 | "scripts": { 13 | "test": "echo \"Error: no test specified\" && exit 1" 14 | }, 15 | "keywords": [], 16 | "dependencies": { 17 | "azure-iothub": "^1.1.7", 18 | "azure-iot-common": "^1.1.5", 19 | "azure-iot-device": "^1.1.7", 20 | "azure-iot-device-amqp": "^1.1.7", 21 | "azure-iot-device-http": "^1.1.7", 22 | "azure-iot-device-mqtt": "^1.1.7", 23 | "network": "^0.3.2", 24 | "yargs": "^7.0.2", 25 | "uuid": "^3.0.1" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Default behavior: if Git thinks a file is text (as opposed to binary), it 2 | # will normalize line endings to LF in the repository, but convert to your 3 | # platform's native line endings on checkout (e.g., CRLF for Windows). 4 | * text=auto 5 | 6 | # Explicitly declare text files you want to always be normalized and converted 7 | # to native line endings on checkout. E.g., 8 | #*.c text 9 | 10 | # Declare files that will always have CRLF line endings on checkout. E.g., 11 | #*.sln text eol=crlf 12 | 13 | # Declare files that will always have LF line endings on checkout. E.g., 14 | *.sh text eol=lf 15 | *.json text eol=lf 16 | 17 | # Denote all files that should not have line endings normalized, should not be 18 | # merged, and should not show in a textual diff. 19 | *.docm binary 20 | *.docx binary 21 | *.ico binary 22 | *.lib binary 23 | *.png binary 24 | *.pptx binary 25 | *.snk binary 26 | *.vsdx binary 27 | *.xps binary 28 | -------------------------------------------------------------------------------- /service/samples/device_method.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var Client = require('azure-iothub').Client; 7 | 8 | var connectionString = ''; 9 | var targetDevice = ''; 10 | var methodParams = { 11 | methodName: '', 12 | payload: '[Method Payload]', 13 | responseTimeoutInSeconds: 15 // set response timeout as 15 seconds 14 | }; 15 | 16 | var client = Client.fromConnectionString(connectionString); 17 | 18 | client.invokeDeviceMethod(targetDevice, methodParams, function (err, result) { 19 | if (err) { 20 | console.error('Failed to invoke method \'' + methodParams.methodName + '\': ' + err.message); 21 | } else { 22 | console.log(methodParams.methodName + ' on ' + targetDevice + ':'); 23 | console.log(JSON.stringify(result, null, 2)); 24 | } 25 | }); -------------------------------------------------------------------------------- /device/samples/device_blob_upload.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var Protocol = require('azure-iot-device-mqtt').Mqtt; 7 | var Client = require('azure-iot-device').Client; 8 | var fs = require('fs'); 9 | 10 | var deviceConnectionString = '[Device Connection String]'; 11 | var filePath = '[path/to/file]'; 12 | 13 | var client = Client.fromConnectionString(deviceConnectionString, Protocol); 14 | fs.stat(filePath, function (err, fileStats) { 15 | var fileStream = fs.createReadStream(filePath); 16 | 17 | client.uploadToBlob('testblob.txt', fileStream, fileStats.size, function (err, result) { 18 | if (err) { 19 | console.error('error uploading file: ' + err.constructor.name + ': ' + err.message); 20 | } else { 21 | console.log('Upload successful - ' + result); 22 | } 23 | fileStream.destroy(); 24 | }); 25 | }); -------------------------------------------------------------------------------- /device/core/devdoc/device_method/device_method_request_requirements.md: -------------------------------------------------------------------------------- 1 | # azure-iot-device.deviceMethod.DeviceMethodRequest requirements 2 | 3 | # Overview 4 | `DeviceMethodRequest` is a class that captures the data passed in from the service when a device method call is made. 5 | 6 | # Public API 7 | 8 | ## DeviceMethodRequest(requestId, methodName, body) [constructor] 9 | Initializes a new instance of the `DeviceMethodRequest` class. 10 | 11 | **SRS_NODE_DEVICE_METHOD_REQUEST_13_001: [** `DeviceMethodRequest` shall throw a `ReferenceError` if `requestId` is falsy or is not a string. **]** 12 | 13 | **SRS_NODE_DEVICE_METHOD_REQUEST_13_002: [** `DeviceMethodRequest` shall throw an `Error` if `requestId` is an empty string. **]** 14 | 15 | **SRS_NODE_DEVICE_METHOD_REQUEST_13_003: [** `DeviceMethodRequest` shall throw a `ReferenceError` if `methodName` is falsy or is not a string. **]** 16 | 17 | **SRS_NODE_DEVICE_METHOD_REQUEST_13_004: [** `DeviceMethodRequest` shall throw an `Error` if `methodName` is an empty string. **]** 18 | 19 | -------------------------------------------------------------------------------- /service/samples/create_device_with_cert.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var iothub = require('azure-iothub'); 7 | 8 | var connectionString = ''; 9 | var registry = iothub.Registry.fromConnectionString(connectionString); 10 | var device = { 11 | deviceId: '', 12 | status: 'enabled', 13 | authentication: { 14 | x509Thumbprint: { 15 | primaryThumbprint: "", 16 | secondaryThumbprint: "" 17 | } 18 | } 19 | }; 20 | 21 | registry.create(device, function (err) { 22 | if(err) { 23 | console.error('Could not create device: ' + err.message); 24 | } else { 25 | registry.get(device.deviceId, function(err, deviceInfo) { 26 | if(err) { 27 | console.error('Could not get device: ' + err.message); 28 | } else { 29 | console.log(JSON.stringify(deviceInfo)); 30 | } 31 | }); 32 | } 33 | }); 34 | -------------------------------------------------------------------------------- /service/test/_client_test_integration.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | var Registry = require('../lib/registry.js').Registry; 6 | var AmqpWs = require('../lib/amqp_ws.js').AmqpWs; 7 | 8 | var transportSpecificTests = require('./_client_common_testrun.js'); 9 | 10 | describe('Over real AMQP (Default Transport)', function () { 11 | this.timeout(60000); 12 | var opts = { 13 | transport: null, 14 | connectionString: process.env.IOTHUB_CONNECTION_STRING, 15 | registry: Registry.fromConnectionString(process.env.IOTHUB_CONNECTION_STRING) 16 | }; 17 | transportSpecificTests(opts); 18 | }); 19 | 20 | describe('Over real AMQP over Websockets', function () { 21 | this.timeout(60000); 22 | var opts = { 23 | transport: AmqpWs, 24 | connectionString: process.env.IOTHUB_CONNECTION_STRING, 25 | registry: Registry.fromConnectionString(process.env.IOTHUB_CONNECTION_STRING) 26 | }; 27 | transportSpecificTests(opts); 28 | }); 29 | -------------------------------------------------------------------------------- /device/ts-samples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-device-ts-samples", 3 | "version": "0.0.1", 4 | "description": "Device code samples for the Azure IoT Hub Device SDK", 5 | "main": "sample_device.js", 6 | "scripts": { 7 | "lint": "tslint --project . --type-check -c ../../tslint.json", 8 | "build": "tsc", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/azure/azure-iot-sdk-node.git" 14 | }, 15 | "author": "Microsoft Corporation", 16 | "license": "MIT", 17 | "bugs": { 18 | "url": "https://github.com/azure/azure-iot-sdk-node/issues" 19 | }, 20 | "homepage": "https://github.com/azure/azure-iot-sdk-node#readme", 21 | "dependencies": { 22 | "@types/node": "^7.0.14", 23 | "azure-iot-common": "^1.1.6", 24 | "azure-iot-device": "^1.1.10", 25 | "azure-iot-device-amqp": "^1.1.10", 26 | "azure-iot-device-http": "^1.1.10", 27 | "azure-iot-device-mqtt": "^1.1.10", 28 | "tslint": "^5.1.0", 29 | "typescript": "^2.2.2" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /e2etests/test/device_teardown.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var Registry = require('azure-iothub').Registry; 7 | var chalk = require('chalk'); 8 | 9 | var device_teardown = function (hubConnectionString, provisionedDevices) { 10 | describe('Clean up e2e test', function () { 11 | provisionedDevices.forEach(function(deviceToDelete) { 12 | it('delete provisioned e2e device ' + deviceToDelete.deviceId, function (done) { 13 | this.timeout(120000); 14 | var registry = Registry.fromConnectionString(hubConnectionString); 15 | registry.delete(deviceToDelete.deviceId, function(err) { 16 | if (err) { 17 | console.log(chalk.red('Device ' + deviceToDelete.deviceId + ' could not be deleted: ' + err.constructor.name)); 18 | done(err); 19 | } else { 20 | done(); 21 | } 22 | }); 23 | }); 24 | }); 25 | }); 26 | }; 27 | module.exports = device_teardown; -------------------------------------------------------------------------------- /jenkins/node_docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | node4: 5 | image: nodebuild:node4 6 | build: 7 | context: ../.. 8 | dockerfile: ./jenkins/node_docker/dockerfiles/aziot-node4.dockerfile 9 | env_file: ./env/aziot-node4.env 10 | node5: 11 | image: nodebuild:node5 12 | build: 13 | context: ../.. 14 | dockerfile: ./jenkins/node_docker/dockerfiles/aziot-node5.dockerfile 15 | env_file: ./env/aziot-node5.env 16 | node6: 17 | image: nodebuild:node6 18 | build: 19 | context: ../.. 20 | dockerfile: ./jenkins/node_docker/dockerfiles/aziot-node6.dockerfile 21 | env_file: ./env/aziot-node6.env 22 | node010: 23 | image: nodebuild:node010 24 | build: 25 | context: ../.. 26 | dockerfile: ./jenkins/node_docker/dockerfiles/aziot-node010.dockerfile 27 | env_file: ./env/aziot-node010.env 28 | node012: 29 | image: nodebuild:node012 30 | build: 31 | context: ../.. 32 | dockerfile: ./jenkins/node_docker/dockerfiles/aziot-node012.dockerfile 33 | env_file: ./env/aziot-node012.env 34 | -------------------------------------------------------------------------------- /service/src/interfaces.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | import { IncomingMessage } from 'http'; 7 | 8 | /** 9 | * @private 10 | */ 11 | export type Callback = (err?: Error, result?: T, response?: IncomingMessage) => void; 12 | 13 | /** 14 | * Describes the parameters that are available for use with direct methods (also called device methods) 15 | */ 16 | export interface DeviceMethodParams { 17 | /** 18 | * The name of the method to call on the device. 19 | */ 20 | methodName: string; 21 | /** 22 | * The method payload that will be sent to the device. 23 | */ 24 | payload?: any; 25 | /** 26 | * The maximum time a device should take to respond to the method. 27 | */ 28 | responseTimeoutInSeconds?: number; 29 | /** 30 | * The maximum time the service should try to connect to the device before declaring the device is unreachable. 31 | */ 32 | connectTimeoutInSeconds?: number; // default is 0 33 | } 34 | -------------------------------------------------------------------------------- /ts-e2e/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-e2e", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "lint": "tslint --type-check --project . -c ../tslint.json", 8 | "pretest": "tsc", 9 | "test": "mocha ./lib/*.tests.js" 10 | }, 11 | "keywords": [], 12 | "author": "Microsoft Corporation", 13 | "license": "MIT", 14 | "dependencies": { 15 | "@types/bluebird": "^3.5.0", 16 | "@types/chai": "^3.5.1", 17 | "@types/debug": "0.0.29", 18 | "@types/mocha": "^2.2.41", 19 | "@types/node": "^7.0.8", 20 | "@types/uuid": "^2.0.29", 21 | "azure-event-hubs": "0.0.8", 22 | "azure-iot-common": "^1.1.6", 23 | "azure-iot-device": "^1.1.10", 24 | "azure-iot-device-amqp": "^1.1.10", 25 | "azure-iot-device-http": "^1.1.10", 26 | "azure-iot-device-mqtt": "^1.1.10", 27 | "azure-iothub": "^1.1.9", 28 | "chai": "^3.5.0", 29 | "debug": "^2.6.6", 30 | "jest": "^19.0.2", 31 | "mocha": "^3.3.0", 32 | "ts-jest": "^19.0.0", 33 | "tslint": "^4.5.1", 34 | "typescript": "^2.2.1", 35 | "uuid": "^3.0.1" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | # Checklist 9 | - [ ] I have read the [contribution guidelines] (https://github.com/Azure/azure-iot-sdk-node/blob/master/.github/CONTRIBUTING.md). 10 | - [ ] I added or modified the existing tests to cover the change (we do not allow our test coverage to go down). 11 | - If this is a modification that impacts the behavior of a public API 12 | - [ ] I edited the corresponding document in the `devdoc` folder and added or modified requirements. 13 | 14 | # Reference/Link to the issue solved with this PR (if any) 15 | 16 | # Description of the problem 17 | 18 | 19 | # Description of the solution 20 | 21 | -------------------------------------------------------------------------------- /device/node-red/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Microsoft Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /common/core/common.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | /** 7 | * The `azure-iot-common` module contains code common to the Azure IoT Hub Device and Service SDKs. 8 | * 9 | * @module azure-iot-common 10 | */ 11 | 12 | module.exports = { 13 | anHourFromNow: require('./lib/authorization.js').anHourFromNow, 14 | encodeUriComponentStrict: require('./lib/authorization.js').encodeUriComponentStrict, 15 | ConnectionString: require('./lib/connection_string.js').ConnectionString, 16 | endpoint: require('./lib/endpoint.js'), 17 | errors: require('./lib/errors.js'), 18 | results: require('./lib/results.js'), 19 | Message: require('./lib/message.js').Message, 20 | SharedAccessSignature: require('./lib/shared_access_signature.js').SharedAccessSignature, 21 | RetryOperation: require('./lib/retry_operation.js').RetryOperation, 22 | RetryPolicy: require('./lib/retry_policy.js').RetryPolicy, 23 | NoRetry: require('./lib/retry_policy.js').NoRetry, 24 | ExponentialBackOffWithJitter: require('./lib/retry_policy.js').ExponentialBackOffWithJitter, 25 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Microsoft Azure IoT SDK for Node 2 | Copyright (c) Microsoft Corporation 3 | All rights reserved. 4 | MIT License 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the ""Software""), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /service/src/connection_string.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | import { ConnectionString } from 'azure-iot-common'; 7 | 8 | /** 9 | * Parses a connection string from a string. 10 | * See {@link https://blogs.msdn.microsoft.com/iotdev/2017/05/09/understand-different-connection-strings-in-azure-iot-hub/|Understanding Connection Strings in Azure IoT Hub} for more details. 11 | * 12 | * @param source the string from which the {@link ConnectionString} object should be parsed. 13 | * 14 | * @throws {azure-iot-common.ArgumentError} if the string is missing one of the required attributes. 15 | */ 16 | export function parse(source: string): ConnectionString { 17 | /*Codes_SRS_NODE_IOTHUB_CONNSTR_05_001: [The parse method shall return the result of calling azure-iot-common.ConnectionString.parse.]*/ 18 | /*Codes_SRS_NODE_IOTHUB_CONNSTR_05_002: [It shall throw ArgumentError if any of 'HostName', 'SharedAccessKeyName', or 'SharedAccessKey' fields are not found in the source argument.]*/ 19 | return ConnectionString.parse(source, ['HostName', 'SharedAccessKeyName', 'SharedAccessKey']); 20 | } 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | # Context 9 | - **OS and version used:** 10 | - **Node.js version:** 11 | - **npm version:** 12 | - **list of installed packages:** 13 | - **cloned repo:** 14 | 15 | # Description of the issue: 16 | 17 | 18 | # Code sample exhibiting the issue: 19 | 20 | 21 | # Console log of the issue: 22 | 23 | 24 | -------------------------------------------------------------------------------- /service/samples/receive_file_notifications.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var Client = require('azure-iothub').Client; 7 | 8 | var connectionString = '[IoT Hub connection string]'; 9 | 10 | var client = Client.fromConnectionString(connectionString); 11 | 12 | client.open(function (err) { 13 | if (err) { 14 | console.error('Could not connect: ' + err.message); 15 | } else { 16 | console.log('Client connected'); 17 | 18 | client.getFileNotificationReceiver(function(err, receiver) { 19 | if(err) { 20 | console.error('Could not get file notification receiver: ' + err.message); 21 | } else { 22 | receiver.on('message', function(msg) { 23 | console.log('File uploaded: '); 24 | console.log(msg.data.toString()); 25 | receiver.complete(msg, function(err) { 26 | if (err) { 27 | console.error('Could not complete the message: ' + err.message); 28 | } else { 29 | console.log('Message completed'); 30 | } 31 | }); 32 | }); 33 | } 34 | }); 35 | } 36 | }); -------------------------------------------------------------------------------- /jenkins/windows_node.cmd: -------------------------------------------------------------------------------- 1 | @REM Copyright (c) Microsoft. All rights reserved. 2 | @REM Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | @setlocal 5 | @echo off 6 | 7 | set build-root=%~dp0.. 8 | REM Resolve to fully qualified path 9 | for %%i in ("%build-root%") do set build-root=%%~fi 10 | 11 | cd %build-root% 12 | 13 | REM Disable the npm progress bar (supposedly faster) 14 | call npm set progress=false 15 | 16 | REM Set up links in the npm cache to ensure we're exercising all the code in 17 | REM the repo, rather than downloading released versions of our packages from 18 | REM npm. 19 | call build\dev-setup.cmd 20 | if errorlevel 1 goto :eof 21 | 22 | REM Lint all JavaScript code and run unit + integration tests 23 | call build\build.cmd --min --integration-tests --e2e-tests 24 | if errorlevel 1 goto :eof 25 | 26 | REM The 'npm link' commands in this script create symlinks to tracked repo 27 | REM files from ignored locations (under ./node_modules). This means a call to 28 | REM 'git clean -xdf' will delete tracked files from the repo's working 29 | REM directory. To avoid any complications, we'll unlink everything before 30 | REM exiting. 31 | call build\dev-teardown.cmd 32 | if errorlevel 1 goto :eof -------------------------------------------------------------------------------- /common/core/test/_authorization_test.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var assert = require('chai').assert; 7 | var authorization = require('../lib/authorization.js'); 8 | 9 | var key = new Buffer('password').toString('base64'); 10 | 11 | describe('authorization', function () { 12 | describe('#stringToSign', function () { 13 | /*Tests_SRS_NODE_COMMON_SAS_05_014: [ shall be a concatenation of resourceUri + '\n' + expiry.]*/ 14 | it('returns \\n', function () { 15 | var stringToSign = authorization.stringToSign('blah/blah', 12345); 16 | assert.equal('blah/blah\n12345', stringToSign); 17 | }); 18 | }); 19 | 20 | describe('#hmacHash', function () { 21 | /*Tests_SRS_NODE_COMMON_SAS_05_013: [ shall be an HMAC-SHA256 hash of the value , which is then base64-encoded.]*/ 22 | it('returns base64-encoded HMAC SHA-256 hash of string-to-sign', function () { 23 | var hash = authorization.hmacHash(key, 'string-to-sign'); 24 | assert.equal('o1n1hiIVgzVA2+krq9ty1Z4xsIJKJZP3dYT8MOi65Y4=', hash); 25 | }); 26 | }); 27 | }); -------------------------------------------------------------------------------- /device/transport/amqp/src/amqp_ws.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | import { Amqp } from './amqp.js'; 7 | import { ClientConfig, Client, StableConnectionTransport } from 'azure-iot-device'; 8 | 9 | /** 10 | * Constructs a transport object that can be used by the device {@link azure-iot-device.Client} to send and receive messages to and from an IoT Hub instance, using the AMQP protocol over secure websockets. 11 | * This class overloads the constructor of the base {@link azure-iot-device-amqp.Amqp} class from the AMQP transport, and inherits all methods from it. 12 | * 13 | * @augments module:azure-iot-device-amqp.Amqp 14 | */ 15 | export class AmqpWs extends Amqp implements Client.Transport, StableConnectionTransport { 16 | /** 17 | * @private 18 | * @constructor 19 | * @param {Object} config Configuration object generated from the connection string by the client. 20 | */ 21 | constructor(config: ClientConfig) { 22 | super(config); 23 | } 24 | 25 | protected _getConnectionUri(): string { 26 | return 'wss://' + this._config.host + ':443/$iothub/websocket'; 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /device/readme.md: -------------------------------------------------------------------------------- 1 | # Microsoft Azure IoT device SDK for Node.js 2 | 3 | The Azure IoT device SDK for Node allows to build devices that communicate with Azure IoT Hub. 4 | 5 | ## Features 6 | 7 | Use the device SDK to: 8 | * Send event data to Azure IoT Hub. 9 | * Receive messages from IoT Hub. 10 | * Communicate with the service via MQTT (optionally over WebSockets), AMQP (optionally over WebSockets), or HTTP. 11 | * Synchronize an Azure IoT Hub device Twin with Azure IoT Hub from a device 12 | * Implement Azure IoT Hub Direct Device Methods on devices 13 | * Implement Azure IoT Device Mangement features on devices 14 | 15 | ## How to use the Azure IoT device SDK for Node.js 16 | 17 | * [Get started in minutes with the azure-iot-device npm package](./core/readme.md) 18 | * [Check out the simple samples provided in this repository](./samples/) 19 | * [Try out the Node-RED node for Azure IoT Hub](./node-red/) 20 | 21 | ## Directory structure 22 | 23 | Device SDK subfolders: 24 | 25 | ### /core 26 | 27 | Protocol-independent device SDK package. 28 | 29 | ### /node-red 30 | 31 | Node-RED module for Azure IoT Hub. 32 | 33 | ### /samples 34 | 35 | Sample applications exercising basic features. 36 | 37 | ### /transport 38 | 39 | Protocol-specific SDK packages for: AMQP, AMQP over WebSockets, MQTT, and HTTP. 40 | -------------------------------------------------------------------------------- /device/samples/send_batch_http.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var clientFromConnectionString = require('azure-iot-device-http').clientFromConnectionString; 7 | var Message = require('azure-iot-device').Message; 8 | 9 | // String containing Hostname, Device Id & Device Key in the following formats: 10 | // "HostName=;DeviceId=;SharedAccessKey=" 11 | var connectionString = '[IoT Hub device connection string]'; 12 | var client = clientFromConnectionString(connectionString); 13 | 14 | // Create two messages and send them to the IoT hub as a batch. 15 | var data = [ 16 | { id: 1, message: 'hello' }, 17 | { id: 2, message: 'world' } 18 | ]; 19 | 20 | var messages = []; 21 | data.forEach(function (value) { 22 | messages.push(new Message(JSON.stringify(value))); 23 | }); 24 | 25 | console.log('sending ' + messages.length + ' events in a batch'); 26 | 27 | client.sendEventBatch(messages, printResultFor('send')); 28 | 29 | function printResultFor(op) { 30 | return function printResult(err, res) { 31 | if (err) console.log(op + ' error: ' + err.toString()); 32 | if (res) console.log(op + ' status: ' + res.statusCode + ' ' + res.statusMessage); 33 | }; 34 | } -------------------------------------------------------------------------------- /service/samples/send_c2d_message.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var Client = require('azure-iothub').Client; 7 | var Message = require('azure-iot-common').Message; 8 | 9 | var connectionString = '[IoT Hub Connection String]'; 10 | var targetDevice = '[Target device that will receive the message]'; 11 | 12 | var client = Client.fromConnectionString(connectionString); 13 | 14 | client.open(function (err) { 15 | if (err) { 16 | console.error('Could not connect: ' + err.message); 17 | } else { 18 | console.log('Client connected'); 19 | 20 | // Create a message and send it to the IoT Hub every second 21 | setInterval(function () { 22 | var data = JSON.stringify({ text : 'foo' }); 23 | var message = new Message(data); 24 | console.log('Sending message: ' + message.getData()); 25 | client.send(targetDevice, message, printResultFor('send')); 26 | }, 2000); 27 | } 28 | }); 29 | 30 | // Helper function to print results in the console 31 | function printResultFor(op) { 32 | return function printResult(err, res) { 33 | if (err) { 34 | console.log(op + ' error: ' + err.toString()); 35 | } else { 36 | console.log(op + ' status: ' + res.constructor.name); 37 | } 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /ts-e2e/src/registry.tests.ts: -------------------------------------------------------------------------------- 1 | import {Registry} from 'azure-iothub'; 2 | import * as uuid from 'uuid'; 3 | import { assert } from 'chai'; 4 | 5 | describe('Registry', function() { 6 | this.timeout(20000); 7 | it('creates a device -> gets it -> updates it -> deletes it', (testCallback) => { 8 | const testDeviceId = uuid.v4(); 9 | const registry = Registry.fromConnectionString(process.env.IOTHUB_CONNECTION_STRING); 10 | registry.create({ deviceId: testDeviceId }, (err, createDevDesc) => { 11 | if (err) throw err; 12 | assert.strictEqual(createDevDesc.deviceId, testDeviceId); 13 | registry.get(testDeviceId, (err, getDevDesc) => { 14 | if (err) throw err; 15 | assert.strictEqual(getDevDesc.deviceId, testDeviceId); 16 | assert.strictEqual(getDevDesc.status, 'enabled'); 17 | registry.update({ deviceId: testDeviceId, status: 'disabled' }, (err, updateDevDesc) => { 18 | assert.strictEqual(updateDevDesc.deviceId, testDeviceId); 19 | assert.strictEqual(updateDevDesc.status, 'disabled'); 20 | registry.delete(testDeviceId, (err) => { 21 | if (err) throw err; 22 | registry.get(testDeviceId, (err, getDevDesc2) => { 23 | assert.instanceOf(err, Error); 24 | testCallback(); 25 | }); 26 | }); 27 | }); 28 | }); 29 | }); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /device/transport/mqtt/test/_fake_mqtt.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | var EventEmitter = require('events').EventEmitter; 6 | var util = require('util'); 7 | 8 | var FakeMqtt = function() { 9 | EventEmitter.call(this); 10 | 11 | this.publishShouldSucceed = function (shouldSucceed) { 12 | this._publishSucceeds = shouldSucceed; 13 | }; 14 | 15 | this.publish = function(topic, message, options, callback) { 16 | this.publishoptions = options; 17 | this.topicString = topic; 18 | if (this._publishSucceeds) { 19 | callback(null, {puback: 'success'}); 20 | } else { 21 | callback(new Error('Invalid topic')); 22 | } 23 | }; 24 | 25 | this.connect = function() { 26 | return this; 27 | }; 28 | 29 | this.subscribe = function(topicName, param, done) { 30 | if (this.subscribeShouldFail) { 31 | done (new Error('Not authorized')); 32 | } else { 33 | done(null, 'fake_object'); 34 | } 35 | }; 36 | 37 | this.unsubscribe = function(topicName, done) { 38 | done(); 39 | }; 40 | 41 | this.fakeMessageFromService = function(topic, message) { 42 | this.emit('message', topic, message); 43 | }; 44 | }; 45 | 46 | util.inherits(FakeMqtt, EventEmitter); 47 | 48 | module.exports = FakeMqtt; 49 | -------------------------------------------------------------------------------- /service/src/amqp_service_errors.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | import { errors } from 'azure-iot-common'; 7 | import { translateError as translateCommonError } from 'azure-iot-amqp-base'; 8 | import { Errors as Amqp10Errors } from 'amqp10'; 9 | 10 | /** 11 | * @private 12 | */ 13 | export interface AmqpTransportError extends Error { 14 | amqpError?: Error; 15 | } 16 | 17 | /*Codes_SRS_NODE_DEVICE_AMQP_COMMON_ERRORS_16_010: [ `translateError` shall accept 2 argument: 18 | *- A custom error message to give context to the user. 19 | *- the AMQP error object itself] 20 | */ 21 | /** 22 | * @private 23 | */ 24 | export function translateError(message: string, amqpError: Error): AmqpTransportError { 25 | let error: AmqpTransportError; 26 | /*Codes_SRS_NODE_DEVICE_AMQP_SERVICE_ERRORS_16_001: [ `translateError` shall return an `DeviceMaximumQueueDepthExceededError` if the AMQP error condition is `amqp:resource-limit-exceeded`.] */ 27 | if ((amqpError as Amqp10Errors.ProtocolError).condition === 'amqp:resource-limit-exceeded') { 28 | error = new errors.DeviceMaximumQueueDepthExceededError(message); 29 | } else { 30 | error = translateCommonError(message, amqpError); 31 | } 32 | 33 | error.amqpError = amqpError; 34 | 35 | return error; 36 | } 37 | -------------------------------------------------------------------------------- /service/devdoc/connection_string_requirements.md: -------------------------------------------------------------------------------- 1 | # azure-iothub.ConnectionString Requirements 2 | 3 | ## Overview 4 | `ConnectionString` is a type representing an IoT Hub connection string. It exposes a static factory method for creating a connection string object from a string, and exposes properties for each of the parsed fields in the string. It also validates the required properties of the connection string. 5 | 6 | ## Example usage 7 | ```javascript 8 | 'use strict'; 9 | var ConnectionString = require('azure-iothub').ConnectionString; 10 | 11 | var cn = ConnectionString.parse('[Connection string]'); 12 | console.log('HostName=' + cn.HostName); 13 | console.log('SharedAccessKeyName=' + cn.SharedAccessKeyName); 14 | console.log('SharedAccessKey=' + cn.SharedAccessKey); 15 | ``` 16 | 17 | ## Public Interface 18 | ### ConnectionString constructor 19 | Creates a new instance of the object. 20 | 21 | ### parse(source) [static] 22 | The `parse` static method returns a new instance of the `ConnectionString` object with properties corresponding to each `name=value` field found in source. 23 | **SRS_NODE_IOTHUB_CONNSTR_05_001: [** The `parse` method shall return the result of calling `azure-iot-common.ConnectionString.parse`.**]** 24 | **SRS_NODE_IOTHUB_CONNSTR_05_002: [** It shall throw `ArgumentError` if any of `HostName`, `SharedAccessKeyName`, or `SharedAccessKey` fields are not found in the source argument.**]** 25 | -------------------------------------------------------------------------------- /service/test/_connection_string_test.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var assert = require('chai').assert; 7 | var ArgumentError = require('azure-iot-common').errors.ArgumentError; 8 | var ConnectionString = require('../lib/connection_string.js'); 9 | 10 | var incompleteConnectionStrings = { 11 | HostName: 'SharedAccessKeyName=keyname;SharedAccessKey=key', 12 | SharedAccessKeyName: 'HostName=hostname;SharedAccessKey=key', 13 | SharedAccessKey: 'HostName=name;SharedAccessKeyName=keyname' 14 | }; 15 | 16 | describe('ConnectionString', function () { 17 | describe('#parse', function () { 18 | /*Tests_SRS_NODE_IOTHUB_CONNSTR_05_001: [The parse method shall return the result of calling azure-iot-common.ConnectionString.parse.]*/ 19 | /*Tests_SRS_NODE_IOTHUB_CONNSTR_05_002: [It shall throw ArgumentError if any of 'HostName', 'SharedAccessKeyName', or 'SharedAccessKey' fields are not found in the source argument.]*/ 20 | ['HostName', 'SharedAccessKeyName', 'SharedAccessKey'].forEach(function (key) { 21 | it('throws if connection string is missing ' + key, function () { 22 | assert.throws(function () { 23 | ConnectionString.parse(incompleteConnectionStrings[key]); 24 | }, ArgumentError); 25 | }); 26 | }); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /device/core/src/blob_upload/blob_upload_errors.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | /** 7 | * @private 8 | * @class module:azure-iot-device.BlobSasError 9 | * @classdesc Error used when the client fails to get a blob shared access signature from the IoT Hub service. 10 | * 11 | * @params {string} message Error message 12 | * @augments {Error} 13 | */ 14 | export class BlobSasError extends Error { 15 | innerError: Error; 16 | 17 | constructor(message: string) { 18 | super(message); 19 | this.name = 'BlobSasError'; 20 | this.message = message; 21 | Error.captureStackTrace(this, this.constructor); 22 | } 23 | } 24 | 25 | /** 26 | * @private 27 | * @class module:azure-iot-device.BlobUploadNotificationError 28 | * @classdesc Error used when the client fails to notify the IoT Hub service that the upload is complete. 29 | * 30 | * @params {string} message Error message 31 | * @augments {Error} 32 | */ 33 | export class BlobUploadNotificationError extends Error { 34 | innerError: Error; 35 | 36 | constructor(message: string) { 37 | super(message); 38 | this.message = message; 39 | this.name = 'BlobUploadNotificationError'; 40 | Error.captureStackTrace(this, this.constructor); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /device/transport/mqtt/test/_mqtt_ws_test.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var assert = require('chai').assert; 7 | var MqttWs = require('../lib/mqtt_ws.js').MqttWs; 8 | 9 | describe('MqttWs', function () { 10 | var fakeConfig = { 11 | host: 'host.name', 12 | deviceId: 'deviceId' 13 | }; 14 | 15 | describe('#constructor', function () { 16 | /* Tests_SRS_NODE_DEVICE_MQTT_12_001: [The `Mqtt` constructor shall accept the transport configuration structure */ 17 | /* Tests_SRS_NODE_DEVICE_MQTT_12_002: [The `Mqtt` constructor shall store the configuration structure in a member variable */ 18 | it('stores config and created transport in member', function () { 19 | var mqttWs = new MqttWs(fakeConfig); 20 | assert.notEqual(mqttWs, null); 21 | assert.notEqual(mqttWs, undefined); 22 | assert.equal(mqttWs._config, fakeConfig); 23 | }); 24 | 25 | /*Tests_SRS_NODE_DEVICE_MQTT_16_017: [The `MqttWs` constructor shall initialize the `uri` property of the `config` object to `wss://:443/$iothub/websocket`.]*/ 26 | it('sets the uri property to \'wss://:443/$iothub/websocket\'', function () { 27 | var mqttWs = new MqttWs(fakeConfig); 28 | assert.equal(mqttWs._config.uri, 'wss://' + fakeConfig.host + ':443/$iothub/websocket'); 29 | }); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /jenkins/node_docker/docker_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo ${IOTHUB_DEVICE_ID?Error \$IOTHUB_DEVICE_ID is not defined.} 4 | echo ${IOTHUB_DEVICE_KEY?Error \$IOTHUB_DEVICE_KEY is not defined.} 5 | echo ${IOTHUB_CONNECTION_STRING?Error \$IOTHUB_CONNECTION_STRING is not defined.} 6 | echo ${STORAGE_CONNECTION_STRING?Error \$STORAGE_CONNECTION_STRING is not defined.} 7 | 8 | build_root=$(cd "$(dirname "$0")/../.." && pwd) 9 | dockerdir=$build_root/jenkins/node_docker 10 | envdir=$dockerdir/env 11 | 12 | mkdir $envdir 13 | 14 | for build_container in "aziot-node010" "aziot-node012" "aziot-node4" "aziot-node5" "aziot-node6" 15 | do 16 | ENV_FILE=$envdir/$build_container.env 17 | echo IOTHUB_DEVICE_ID=$IOTHUB_DEVICE_ID > $ENV_FILE 18 | echo IOTHUB_DEVICE_KEY=$IOTHUB_DEVICE_KEY >> $ENV_FILE 19 | echo IOTHUB_CONNECTION_STRING=$IOTHUB_CONNECTION_STRING >> $ENV_FILE 20 | echo STORAGE_CONNECTION_STRING=$STORAGE_CONNECTION_STRING >> $ENV_FILE 21 | done 22 | 23 | # Build and start all containers 24 | docker-compose -f $dockerdir/docker-compose.yml up --force-recreate 25 | 26 | 27 | docker-compose -f $dockerdir/docker-compose.yml ps -q | xargs docker inspect -f '{{ .Config.Image }} finished with ExitCode {{ .State.ExitCode }}' 28 | # Compute exit code: count the number of containers for which the exit code was not 0 29 | BUILD_EXIT_CODE=$(docker-compose -f $dockerdir/docker-compose.yml ps -q | xargs docker inspect -f '{{ .State.ExitCode }}' | grep -v 0 | wc -l) 30 | 31 | exit $BUILD_EXIT_CODE 32 | -------------------------------------------------------------------------------- /common/core/test/_endpoint_test.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var assert = require('chai').assert; 7 | 8 | var endpoint = require('../lib/endpoint.js'); 9 | 10 | describe('endpoint', function () { 11 | describe('#devicePath', function () { 12 | it('matches /devices/', function () { 13 | var path = endpoint.devicePath('mydevice'); 14 | assert.equal('/devices/mydevice', path); 15 | }); 16 | }); 17 | 18 | describe('#eventPath', function () { 19 | it('matches /devices//messages/events', function () { 20 | var path = endpoint.eventPath('mydevice'); 21 | assert.equal('/devices/mydevice/messages/events', path); 22 | }); 23 | }); 24 | 25 | describe('#messagePath', function () { 26 | it('matches /devices//messages/devicebound', function () { 27 | var path = endpoint.messagePath('mydevice'); 28 | assert.equal('/devices/mydevice/messages/devicebound', path); 29 | }); 30 | }); 31 | 32 | describe('#feedbackPath', function () { 33 | it('matches /devices//messages/devicebound/', function () { 34 | var path = endpoint.feedbackPath('mydevice', '55E68746-0AD9-4DCF-9906-79CDAC14FFBA'); 35 | assert.equal('/devices/mydevice/messages/devicebound/55E68746-0AD9-4DCF-9906-79CDAC14FFBA', path); 36 | }); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /service/samples/twin.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | "use strict"; 5 | 6 | var Registry = require('azure-iothub').Registry; 7 | 8 | var connectionString = "[IoT Hub Connection String]"; 9 | var deviceId = '[Device ID]'; 10 | 11 | var registry = Registry.fromConnectionString(connectionString); 12 | registry.getTwin(deviceId, function(err, twin) { 13 | if (err) { 14 | console.error(err.message); 15 | } else { 16 | console.log(JSON.stringify(twin, null, 2)); 17 | var twinPatch = { 18 | tags: { 19 | city: "Redmond" 20 | }, 21 | properties: { 22 | desired: { 23 | telemetryInterval: 1000 24 | } 25 | } 26 | }; 27 | 28 | // method 1: using the update method directly on the twin 29 | twin.update(twinPatch, function(err, twin) { 30 | if (err) { 31 | console.error(err.message); 32 | } else { 33 | console.log(JSON.stringify(twin, null, 2)); 34 | // method 2: using the updateTwin method on the Registry object 35 | registry.updateTwin(twin.deviceId, { properties: { desired: { telemetryInterval: 2000 }}}, twin.etag, function(err, twin) { 36 | if (err) { 37 | console.error(err.message); 38 | } else { 39 | console.log(JSON.stringify(twin, null, 2)); 40 | } 41 | }); 42 | } 43 | }); 44 | } 45 | }); -------------------------------------------------------------------------------- /service/test/_amqp_ws_test.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | var Amqp = require('../lib/amqp.js').Amqp; 6 | var AmqpWs = require('../lib/amqp_ws.js').AmqpWs; 7 | var assert = require('chai').assert; 8 | var sinon = require('sinon'); 9 | 10 | describe('AmqpWs', function() { 11 | describe('#constructor', function() { 12 | /*Tests_SRS_NODE_IOTHUB_SERVICE_AMQP_WS_16_002: [`AmqpWs` should inherit from `Amqp`.]*/ 13 | it('inherits from `Amqp`', function() { 14 | var amqpWs = new AmqpWs({ 15 | host: 'host', 16 | hubName: 'hubName', 17 | keyName: 'keyName', 18 | sharedAccessSignature: 'sas' 19 | }); 20 | 21 | assert.instanceOf(amqpWs, Amqp); 22 | }); 23 | }); 24 | 25 | describe('#connect', function() { 26 | it('calls the connect method on the base AMQP object with the correct URL', function() { 27 | var testConfig = { 28 | host: 'host', 29 | hubName: 'hubName', 30 | keyName: 'keyName', 31 | sharedAccessSignature: 'sas' 32 | }; 33 | 34 | var amqpWs = new AmqpWs(testConfig); 35 | 36 | sinon.spy(amqpWs._amqp, 'connect'); 37 | amqpWs.connect(function(){}); 38 | assert.strictEqual(amqpWs._amqp.connect.args[0][0].indexOf('wss://'), 0); 39 | assert(amqpWs._amqp.connect.args[0][0].indexOf('$iothub/websocket') > 0); 40 | }); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /device/transport/amqp/readme.md: -------------------------------------------------------------------------------- 1 | #azure-iot-device-amqp 2 | Communicate with Azure IoT Hub from any device over AMQP. 3 | 4 | [![npm version](https://badge.fury.io/js/azure-iot-device-amqp.svg)](https://badge.fury.io/js/azure-iot-device-amqp) 5 | 6 | ## Install 7 | 8 | `npm install -g azure-iot-device-amqp@latest` to get the latest (pre-release) version. 9 | 10 | ## Getting Started 11 | 12 | Create a device client: 13 | 14 | ```js 15 | var clientFromConnectionString = require('azure-iot-device-amqp').clientFromConnectionString; 16 | var Message = require('azure-iot-device').Message; 17 | 18 | var connectionString = '[IoT Hub device connection string]'; 19 | 20 | var client = clientFromConnectionString(connectionString); 21 | ``` 22 | 23 | Create a callback that sends a message and receives messages. When it receives a message it sends an acknowledgement receipt to the server: 24 | 25 | ```js 26 | var connectCallback = function (err) { 27 | if (err) { 28 | console.error('Could not connect: ' + err); 29 | } else { 30 | console.log('Client connected'); 31 | var message = new Message('some data from my device'); 32 | client.sendEvent(message, function (err) { 33 | if (err) console.log(err.toString()); 34 | }); 35 | 36 | client.on('message', function (msg) { 37 | console.log(msg); 38 | client.complete(msg, function () { 39 | console.log('completed'); 40 | }); 41 | }); 42 | } 43 | }; 44 | ``` 45 | 46 | Open the connection and invoke the callback: 47 | 48 | ```js 49 | client.open(connectCallback); 50 | ``` -------------------------------------------------------------------------------- /device/transport/mqtt/readme.md: -------------------------------------------------------------------------------- 1 | #azure-iot-device-mqtt 2 | Communicate with Azure IoT Hub from any device over MQTT. 3 | 4 | [![npm version](https://badge.fury.io/js/azure-iot-device-mqtt.svg)](https://badge.fury.io/js/azure-iot-device-mqtt) 5 | 6 | ## Install 7 | 8 | `npm install -g azure-iot-device-mqtt@latest` to get the latest (pre-release) version. 9 | 10 | ## Getting Started 11 | 12 | Create a device client: 13 | 14 | ```js 15 | var clientFromConnectionString = require('azure-iot-device-mqtt').clientFromConnectionString; 16 | var Message = require('azure-iot-device').Message; 17 | 18 | var connectionString = '[IoT Hub device connection string]'; 19 | 20 | var client = clientFromConnectionString(connectionString); 21 | ``` 22 | 23 | Create a callback that sends a message and receives messages. When it receives a message it sends an acknowledgement receipt to the server: 24 | 25 | ```js 26 | var connectCallback = function (err) { 27 | if (err) { 28 | console.error('Could not connect: ' + err); 29 | } else { 30 | console.log('Client connected'); 31 | var message = new Message('some data from my device'); 32 | client.sendEvent(message, function (err) { 33 | if (err) console.log(err.toString()); 34 | }); 35 | 36 | client.on('message', function (msg) { 37 | console.log(msg); 38 | client.complete(msg, function () { 39 | console.log('completed'); 40 | }); 41 | }); 42 | } 43 | }; 44 | ``` 45 | 46 | Open the connection and invoke the callback: 47 | 48 | ```js 49 | client.open(connectCallback); 50 | ``` -------------------------------------------------------------------------------- /device/transport/http/readme.md: -------------------------------------------------------------------------------- 1 | #azure-iot-device-http 2 | Communicate with Azure IoT Hub from any device over HTTP 1.1. 3 | 4 | [![npm version](https://badge.fury.io/js/azure-iot-device-http.svg)](https://badge.fury.io/js/azure-iot-device-http) 5 | 6 | ## Install 7 | 8 | `npm install -g azure-iot-device-http@latest` to get the latest (pre-release) version. 9 | 10 | ## Getting Started 11 | 12 | Create a device client: 13 | 14 | ```js 15 | var clientFromConnectionString = require('azure-iot-device-http').clientFromConnectionString; 16 | var Message = require('azure-iot-device').Message; 17 | 18 | var connectionString = '[IoT Hub device connection string]'; 19 | 20 | var client = clientFromConnectionString(connectionString); 21 | ``` 22 | 23 | Create a callback that sends a message and receives messages. When it receives a message it sends an acknowledgement receipt to the server: 24 | 25 | ```js 26 | var connectCallback = function (err) { 27 | if (err) { 28 | console.error('Could not connect: ' + err); 29 | } else { 30 | console.log('Client connected'); 31 | var message = new Message('some data from my device'); 32 | client.sendEvent(message, function (err) { 33 | if (err) console.log(err.toString()); 34 | }); 35 | 36 | client.on('message', function (msg) { 37 | console.log(msg); 38 | client.complete(msg, function () { 39 | console.log('completed'); 40 | }); 41 | }); 42 | } 43 | }; 44 | ``` 45 | 46 | Open the connection and invoke the callback: 47 | 48 | ```js 49 | client.open(connectCallback); 50 | ``` -------------------------------------------------------------------------------- /common/core/common.d.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | import { EventEmitter } from 'events'; 5 | import { Message } from './lib/message'; 6 | 7 | export import endpoint = require('./lib/endpoint'); 8 | export import errors = require('./lib/errors'); 9 | export import results = require('./lib/results'); 10 | export { anHourFromNow, encodeUriComponentStrict } from './lib/authorization'; 11 | export { ConnectionString } from './lib/connection_string'; 12 | export { Message } 13 | export { SharedAccessSignature } from './lib/shared_access_signature'; 14 | export { RetryOperation } from './lib/retry_operation'; 15 | export { RetryPolicy, NoRetry, ExponentialBackOffWithJitter } from './lib/retry_policy'; 16 | 17 | // Typescript only, used by other modules in azure-iot-sdk 18 | export interface X509 { 19 | // https://nodejs.org/api/tls.html#tls_tls_connect_options_callback 20 | cert?: string | string[] | Buffer | Buffer[]; 21 | key?: string | Buffer; 22 | passphrase?: string; 23 | certFile?: string; 24 | keyFile?: string; 25 | } 26 | 27 | export interface Receiver extends EventEmitter { 28 | on(type: 'message', func: (msg: Message) => void): this; 29 | on(type: 'errorReceived', func: (err: Error) => void): this; 30 | 31 | on(type: string, func: Function): this; 32 | } 33 | 34 | export interface TransportConfig { 35 | host: string; 36 | deviceId: string; 37 | sharedAccessSignature?: string; 38 | x509?: X509; 39 | } 40 | -------------------------------------------------------------------------------- /network_e2e/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2.1' 2 | services: 3 | test-AMQP: 4 | image: networke2e/node-test 5 | privileged: true 6 | env_file: amqp_env.txt 7 | command: C:\\node-sdk\\network_e2e\\run-badnetwork-e2e.cmd amqp bad_network 8 | networks: 9 | - default 10 | volumes: 11 | - C:\DockerKeys:C:\users\ContainerAdministrator\.docker 12 | 13 | test-AMQP-WS: 14 | image: networke2e/node-test 15 | privileged: true 16 | env_file: amqp_ws_env.txt 17 | command: C:\\node-sdk\\network_e2e\\run-badnetwork-e2e.cmd amqp-ws bad_network 18 | networks: 19 | - default 20 | volumes: 21 | - C:\DockerKeys:C:\users\ContainerAdministrator\.docker 22 | 23 | test-MQTT: 24 | image: networke2e/node-test 25 | privileged: true 26 | env_file: mqtt_env.txt 27 | command: C:\\node-sdk\\network_e2e\\run-badnetwork-e2e.cmd mqtt bad_network 28 | networks: 29 | - default 30 | volumes: 31 | - C:\DockerKeys:C:\users\ContainerAdministrator\.docker 32 | 33 | test-MQTT-WS: 34 | image: networke2e/node-test 35 | privileged: true 36 | env_file: mqtt_ws_env.txt 37 | command: C:\\node-sdk\\network_e2e\\run-badnetwork-e2e.cmd mqtt-ws bad_network 38 | networks: 39 | - default 40 | volumes: 41 | - C:\DockerKeys:C:\users\ContainerAdministrator\.docker 42 | 43 | networks: 44 | default: 45 | external: 46 | name: nat 47 | 48 | -------------------------------------------------------------------------------- /device/transport/mqtt/src/mqtt_ws.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | import { ClientConfig, Client, StableConnectionTransport, TwinTransport } from 'azure-iot-device'; 7 | import { Mqtt } from './mqtt'; 8 | 9 | /** 10 | * Provides MQTT over WebSockets transport for the device [client]{@link module:azure-iot-device.Client} class. 11 | * This class is not meant to be used directly, instead it should just be passed to the [client]{@link module:azure-iot-device.Client} object. 12 | */ 13 | /*Codes_SRS_NODE_DEVICE_MQTT_12_001: [The constructor shall accept the transport configuration structure.]*/ 14 | /*Codes_SRS_NODE_DEVICE_MQTT_12_002: [The constructor shall store the configuration structure in a member variable.]*/ 15 | /*Codes_SRS_NODE_DEVICE_MQTT_12_003: [The constructor shall create an base transport object and store it in a member variable.]*/ 16 | export class MqttWs extends Mqtt implements Client.Transport, StableConnectionTransport, TwinTransport { 17 | /** 18 | * @private 19 | * @constructor 20 | * @param {Object} config Configuration object derived from the connection string by the client. 21 | */ 22 | constructor(config: ClientConfig) { 23 | super(config); 24 | /*Codes_SRS_NODE_DEVICE_MQTT_16_017: [The `MqttWs` constructor shall initialize the `uri` property of the `config` object to `wss://:443/$iothub/websocket`.]*/ 25 | (this._config as any).uri = 'wss://' + config.host + ':443/$iothub/websocket'; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /device/node-red/azureiothub/azureiothub.html: -------------------------------------------------------------------------------- 1 | 20 | 21 | 40 | 41 | 44 | 45 | -------------------------------------------------------------------------------- /service/src/amqp_ws.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | import { Amqp } from './amqp'; 7 | import { Client } from './client'; 8 | 9 | /** 10 | * Transport class used by the [service client]{@link azure-iothub.Client} to connect to the Azure IoT hub using the AMQP protocol over secure websockets. 11 | * This class should not be used directly and instead be passed to one of the {@link azure-iothub.Client} factory methods: {@link azure-iothub.Client.fromConnectionString|fromConnectionString} or {@link azure-iothub.Client.fromSharedAccessSignature|fromSharedAccessSignature}. 12 | */ 13 | /*Codes_SRS_NODE_IOTHUB_SERVICE_AMQP_WS_16_001: [The `AmqpWs` constructor shall accept a config object with those four properties: 14 | - `host` – (string) the fully-qualified DNS hostname of an IoT Hub 15 | - `hubName` - (string) the name of the IoT Hub instance (without suffix such as .azure-devices.net). 16 | - `keyName` – (string) the name of a key that can be used to communicate with the IoT Hub instance 17 | - `sharedAccessSignature–` (string) the key associated with the key name.]*/ 18 | /*Codes_SRS_NODE_IOTHUB_SERVICE_AMQP_WS_16_002: [`AmqpWs` should inherit from `Amqp`.]*/ 19 | export class AmqpWs extends Amqp implements Client.Transport { 20 | /** 21 | * @private 22 | */ 23 | constructor(config: Client.TransportConfigOptions) { 24 | super(config); 25 | } 26 | 27 | protected _getConnectionUri(): string { 28 | return 'wss://' + this._config.host + ':443/$iothub/websocket'; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /service/iothub.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | /** 7 | * The Azure IoT Service SDK for Node.js allows applications to interact with an Azure IoT hub with: 8 | * A messaging {@link azure-iothub.Client} using either AMQP or AMQP over Websockets that enables: 9 | * - sending cloud-to-device messages (also known as commands) to devices 10 | * - execute direct methods on devices 11 | * - listening for feedback when cloud-to-device messages are delivered 12 | * - listening for file upload notifications from devices 13 | * 14 | * It also supports Device identity registry operations with the {@link azure-iothub.Registry} object: 15 | * - creating, removing, updating, and listing device identities registered with an IoT hub 16 | * - get and update and query device twins 17 | * 18 | * Finally, the `{@link azure-iothub.JobClient} object allows to schedule long running tasks that: 19 | * - execute direct methods on one or more devices at a specific time 20 | * - update one or more device twins at a specific time 21 | * 22 | * @module azure-iothub 23 | */ 24 | module.exports = { 25 | Client: require('./lib/client.js').Client, 26 | ConnectionString: require('./lib/connection_string.js'), 27 | Registry: require('./lib/registry.js').Registry, 28 | SharedAccessSignature: require('./lib/shared_access_signature.js'), 29 | Amqp: require('./lib/amqp.js').Amqp, 30 | AmqpWs: require('./lib/amqp_ws.js').AmqpWs, 31 | JobClient: require('./lib/job_client.js').JobClient, 32 | Device: require('./lib/device.js').Device 33 | }; -------------------------------------------------------------------------------- /device/core/test/fake_transport.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict' 5 | 6 | var EventEmitter = require('events').EventEmitter; 7 | var util = require('util'); 8 | var results = require('azure-iot-common').results; 9 | 10 | function FakeTransport() { 11 | EventEmitter.call(this); 12 | this.connect = function (callback) { 13 | callback(null, new results.Connected()); 14 | }; 15 | 16 | this.disconnect = function (callback) { 17 | callback(null, new results.Disconnected()); 18 | }; 19 | 20 | this.sendEvent = function (msg, callback) { 21 | callback(null, new results.MessageEnqueued()); 22 | }; 23 | 24 | this.sendEventBatch = function (msg, callback) { 25 | callback(null, new results.MessageEnqueued()); 26 | }; 27 | 28 | this.complete = function (msg, callback) { 29 | callback(null, new results.MessageCompleted()); 30 | }; 31 | 32 | this.abandon = function (msg, callback) { 33 | callback(null, new results.MessageAbandoned()); 34 | }; 35 | 36 | this.reject = function (msg, callback) { 37 | callback(null, new results.MessageRejected()); 38 | }; 39 | 40 | this.getReceiver = function (callback) { 41 | callback(null, new EventEmitter()); 42 | }; 43 | 44 | this.updateSharedAccessSignature = function (newSas, callback) { 45 | callback(null, new results.SharedAccessSignatureUpdated(false)); 46 | }; 47 | 48 | this.setOptions = function (newSas, callback) { 49 | callback(null, new results.TransportConfigured()); 50 | }; 51 | } 52 | 53 | util.inherits(FakeTransport, EventEmitter); 54 | 55 | module.exports = FakeTransport; -------------------------------------------------------------------------------- /ts-e2e/src/testUtils.ts: -------------------------------------------------------------------------------- 1 | import {Registry, ConnectionString as ServiceConnectionString} from 'azure-iothub'; 2 | import * as uuid from 'uuid'; 3 | import * as dbg from 'debug'; 4 | const debug = dbg('ts-e2e-utils'); 5 | 6 | export interface TestDevice { 7 | deviceId: string; 8 | status?: 'enabled' | 'disabled'; 9 | authentication?: { 10 | symmetricKey?: { 11 | primaryKey?: string; 12 | secondaryKey?: string; 13 | }; 14 | }; 15 | } 16 | 17 | export function createTestDevice(): TestDevice { 18 | return { 19 | deviceId: 'node-ts-e2e-' + uuid.v4(), 20 | status: 'enabled', 21 | authentication: { 22 | symmetricKey: { 23 | primaryKey: new Buffer(uuid.v4()).toString('base64'), 24 | secondaryKey: new Buffer(uuid.v4()).toString('base64') 25 | } 26 | } 27 | }; 28 | } 29 | 30 | export function addTestDeviceToRegistry(testDevice: TestDevice, addCallback: (err?: Error) => void): void { 31 | const reg = Registry.fromConnectionString(process.env.IOTHUB_CONNECTION_STRING); 32 | debug('creating device ' + testDevice.deviceId); 33 | reg.create(testDevice, (err, createdDev) => { 34 | if (err) debug('failed to create device ' + testDevice.deviceId + ': ' + err.toString()); 35 | addCallback(err); 36 | }); 37 | } 38 | 39 | 40 | export function removeTestDeviceFromRegistry(testDevice: TestDevice, removeCallback: (err?: Error) => void): void { 41 | const reg = Registry.fromConnectionString(process.env.IOTHUB_CONNECTION_STRING); 42 | debug('deleting device ' + testDevice.deviceId); 43 | reg.delete(testDevice.deviceId, (err) => { 44 | if (err) debug('failed to delete device ' + testDevice.deviceId + ': ' + err.toString()); 45 | removeCallback(err); 46 | }); 47 | } 48 | -------------------------------------------------------------------------------- /service/samples/registry_sample.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var iothub = require('azure-iothub'); 7 | 8 | var connectionString = '[IoT Connection String]'; 9 | 10 | var registry = iothub.Registry.fromConnectionString(connectionString); 11 | 12 | // List devices 13 | console.log('**listing devices...'); 14 | registry.list(function (err, deviceList) { 15 | deviceList.forEach(function (device) { 16 | var key = device.authentication ? device.authentication.symmetricKey.primaryKey : ''; 17 | console.log(device.deviceId + ': ' + key); 18 | }); 19 | 20 | // Create a new device 21 | var device = { 22 | deviceId: 'sample-device-' + Date.now() 23 | }; 24 | console.log('\n**creating device \'' + device.deviceId + '\''); 25 | registry.create(device, printAndContinue('create', function next() { 26 | 27 | // Get the newly-created device 28 | console.log('\n**getting device \'' + device.deviceId + '\''); 29 | registry.get(device.deviceId, printAndContinue('get', function next() { 30 | 31 | // Delete the new device 32 | console.log('\n**deleting device \'' + device.deviceId + '\''); 33 | registry.delete(device.deviceId, printAndContinue('delete')); 34 | })); 35 | })); 36 | }); 37 | 38 | function printAndContinue(op, next) { 39 | return function printResult(err, deviceInfo, res) { 40 | if (err) console.log(op + ' error: ' + err.toString()); 41 | if (res) console.log(op + ' status: ' + res.statusCode + ' ' + res.statusMessage); 42 | if (deviceInfo) console.log(op + ' device info: ' + JSON.stringify(deviceInfo)); 43 | if (next) next(); 44 | }; 45 | } -------------------------------------------------------------------------------- /device/core/test/device_method/_device_method_request_test.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | require('es5-shim'); 7 | var assert = require('chai').assert; 8 | var DeviceMethodRequest = require('../../lib/device_method').DeviceMethodRequest; 9 | 10 | describe('DeviceMethodRequest', function() { 11 | describe('#constructor', function() { 12 | var inputs = [ 13 | { val: undefined, err: ReferenceError }, 14 | { val: null, err: ReferenceError }, 15 | { val: '', err: Error } 16 | ]; 17 | 18 | // Tests_SRS_NODE_DEVICE_METHOD_REQUEST_13_001: [ DeviceMethodRequest shall throw a ReferenceError if requestId is falsy or is not a string. ] 19 | // Tests_SRS_NODE_DEVICE_METHOD_REQUEST_13_002: [ DeviceMethodRequest shall throw an Error if requestId is an empty string. ] 20 | inputs.forEach(function(inp) { 21 | it('throws a ' + inp.err.name + ' if \'requestId\' is \'' + inp.val + '\'', function() { 22 | assert.throws(function() { 23 | return new DeviceMethodRequest(inp.val, 'Reboot'); 24 | }, inp.err); 25 | }); 26 | }); 27 | 28 | // Tests_SRS_NODE_DEVICE_METHOD_REQUEST_13_003: [ DeviceMethodRequest shall throw a ReferenceError if methodName is falsy or is not a string. ] 29 | // Tests_SRS_NODE_DEVICE_METHOD_REQUEST_13_004: [ DeviceMethodRequest shall throw an Error if methodName is an empty string. ] 30 | inputs.forEach(function(inp) { 31 | it('throws a ' + inp.err.name + ' if \'methodName\' is \'' + inp.val + '\'', function() { 32 | assert.throws(function() { 33 | return new DeviceMethodRequest('1', inp.val); 34 | }, inp.err); 35 | }); 36 | }); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /common/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-common", 3 | "version": "1.1.11", 4 | "description": "Common components shared by Azure IoT device and service SDKs", 5 | "author": "Microsoft Corporation", 6 | "license": "MIT", 7 | "main": "common.js", 8 | "typings": "common.d.ts", 9 | "dependencies": { 10 | "crypto": "^0.0.3" 11 | }, 12 | "devDependencies": { 13 | "@types/node": "^7.0.5", 14 | "chai": "^3.5.0", 15 | "istanbul": "^0.4.4", 16 | "jshint": "^2.9.2", 17 | "mocha": "^3.0.1", 18 | "sinon": "^3.2.1", 19 | "tslint": "^4.5.1", 20 | "typescript": "2.0.6" 21 | }, 22 | "scripts": { 23 | "lint": "tslint --type-check --project . -c ../../tslint.json", 24 | "build": "tsc", 25 | "unittest-min": "istanbul cover --report none node_modules/mocha/bin/_mocha -- --reporter dot test/_*_test.js", 26 | "alltest-min": "istanbul cover --report none node_modules/mocha/bin/_mocha -- --reporter dot test/_*_test*.js", 27 | "unittest": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec test/_*_test.js", 28 | "alltest": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec test/_*_test*.js", 29 | "ci": "npm -s run lint && npm -s run build && npm -s run alltest-min && npm -s run check-cover", 30 | "test": "npm -s run lint && npm -s run build && npm -s run unittest", 31 | "check-cover": "istanbul check-coverage --statements 99 --branches 97 --functions 98 --lines 99" 32 | }, 33 | "engines": { 34 | "node": ">= 0.10" 35 | }, 36 | "repository": { 37 | "type": "git", 38 | "url": "git+https://github.com/Azure/azure-iot-sdk-node.git" 39 | }, 40 | "bugs": { 41 | "url": "https://github.com/Azure/azure-iot-sdk-node/issues" 42 | }, 43 | "homepage": "https://github.com/Azure/azure-iot-sdk-node#readme" 44 | } 45 | -------------------------------------------------------------------------------- /service/samples/typescript_sample/registry_sample.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | import { Registry, Device } from '../../iothub'; 5 | 6 | const connectionString = '[IoT Connection String]'; 7 | 8 | let registry = Registry.fromConnectionString(connectionString); 9 | 10 | 11 | // List devices 12 | console.log('**listing devices..'); 13 | registry.list((err, deviceList) => { 14 | deviceList.forEach((device) => { 15 | let key = device.authentication ? device.authentication.symmetricKey.primaryKey : ''; 16 | console.log(device.deviceId + ': ' + key); 17 | }); 18 | }); 19 | 20 | // Create a new device 21 | let device = new Device(); 22 | device.deviceId = 'sample-device-' + Date.now(); 23 | console.log('\n**creating device \'' + device.deviceId + '\''); 24 | registry.create(device, printAndContinue('create', () => { 25 | 26 | // Get the newly-create device 27 | console.log('\n**getting device \'' + device.deviceId + '\''); 28 | registry.get(device.deviceId, printAndContinue('get', () => { 29 | 30 | // Delete the new device 31 | console.log('\n**deleting device \'' + device.deviceId + '\''); 32 | registry.delete(device.deviceId, printAndContinue('delete')); 33 | })); 34 | })); 35 | 36 | function printAndContinue(op: string, next?: () => void): Registry.ResponseCallback { 37 | return (err, deviceInfo, res) => { 38 | if (err) console.log(op + ' error: ' + err.toString()); 39 | if (res) console.log(op + ' status: ' + res.statusCode + ' ' + res.statusMessage); 40 | if (deviceInfo) console.log(op + ' device info: ' + JSON.stringify(deviceInfo)); 41 | if (next) next(); 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /common/transport/http/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-http-base", 3 | "version": "1.1.11", 4 | "description": "HTTP operations used by Azure IoT device and service SDKs", 5 | "author": "Microsoft Corporation", 6 | "license": "MIT", 7 | "main": "index.js", 8 | "typings": "index.d.ts", 9 | "dependencies": { 10 | "azure-iot-common": "1.1.11", 11 | "debug": "^2.2.0" 12 | }, 13 | "devDependencies": { 14 | "chai": "^3.5.0", 15 | "istanbul": "^0.4.4", 16 | "jshint": "^2.9.2", 17 | "mocha": "^3.0.1", 18 | "tslint": "^5.1.0", 19 | "typescript": "2.2.2", 20 | "@types/node": "^7.0.12" 21 | }, 22 | "scripts": { 23 | "lint": "tslint --type-check --project . -c ../../../tslint.json", 24 | "build": "tsc", 25 | "unittest-min": "istanbul cover --report none node_modules/mocha/bin/_mocha -- --reporter dot test/_*_test.js", 26 | "alltest-min": "istanbul cover --report none node_modules/mocha/bin/_mocha -- --reporter dot test/_*_test*.js", 27 | "unittest": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec test/_*_test.js", 28 | "alltest": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec test/_*_test*.js", 29 | "ci": "npm -s run lint && npm -s run build && npm -s run alltest-min && npm -s run check-cover", 30 | "test": "npm -s run lint && npm -s run build && npm -s run unittest", 31 | "check-cover": "istanbul check-coverage --statements 51 --branches 37 --functions 37 --lines 51" 32 | }, 33 | "engines": { 34 | "node": ">= 0.10" 35 | }, 36 | "repository": { 37 | "type": "git", 38 | "url": "git+https://github.com/Azure/azure-iot-sdk-node.git" 39 | }, 40 | "bugs": { 41 | "url": "https://github.com/Azure/azure-iot-sdk-node/issues" 42 | }, 43 | "homepage": "https://github.com/Azure/azure-iot-sdk-node#readme" 44 | } -------------------------------------------------------------------------------- /e2etests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-e2etests", 3 | "description": "Azure IoT end-to-end tests", 4 | "author": "Microsoft Corporation", 5 | "version": "1.1.17", 6 | "private": true, 7 | "license": "MIT", 8 | "main": "e2etests.js", 9 | "dependencies": { 10 | "async": "^2.1.2", 11 | "azure-event-hubs": "0.0.8", 12 | "azure-iot-common": "1.1.11", 13 | "azure-iot-device": "1.1.17", 14 | "azure-iot-device-amqp": "1.1.17", 15 | "azure-iot-device-http": "1.1.17", 16 | "azure-iot-device-mqtt": "1.1.17", 17 | "azure-iothub": "1.1.15", 18 | "azure-storage": "^1.2.0", 19 | "bluebird": "^3.3.0", 20 | "debug": "^2.2.0", 21 | "lodash": "^4.15.0", 22 | "pem": "^1.8.3", 23 | "uuid": "^2.0.1", 24 | "yargs": "^4.7.1" 25 | }, 26 | "devDependencies": { 27 | "chai": "^3.5.0", 28 | "jshint": "^2.9.2", 29 | "mocha": "^3.0.1" 30 | }, 31 | "scripts": { 32 | "lint": "jshint --show-non-errors .", 33 | "unittest-min": "echo \"No tests\"", 34 | "unittest": "echo \"No tests\"", 35 | "alltest-min": "mocha --delay -i -g \"Imports then exports devices|device successfully uploads\" --reporter dot e2etests.js", 36 | "alltest": "mocha --delay --reporter spec e2etests.js", 37 | "ci": "npm -s run lint && npm -s run alltest-min", 38 | "test": "npm -s run lint && npm -s run unittest" 39 | }, 40 | "engines": { 41 | "node": ">= 0.10" 42 | }, 43 | "repository": { 44 | "type": "git", 45 | "url": "git+https://github.com/Azure/azure-iot-sdk-node.git" 46 | }, 47 | "keywords": [ 48 | "azure", 49 | "iot", 50 | "iothub", 51 | "e2e", 52 | "tests" 53 | ], 54 | "bugs": { 55 | "url": "https://github.com/Azure/azure-iot-sdk-node/issues" 56 | }, 57 | "homepage": "https://github.com/Azure/azure-iot-sdk-node#readme" 58 | } -------------------------------------------------------------------------------- /common/core/test/_message_test.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var assert = require('chai').assert; 7 | var Message = require('../lib/message.js').Message; 8 | 9 | var stringTestMsg = "message"; 10 | 11 | describe('message', function () { 12 | 13 | describe('#getData', function () { 14 | 15 | /*Tests_SRS_NODE_IOTHUB_MESSAGE_07_003: [The getData function shall return a representation of the body of the message as the type that was presented during construction.]*/ 16 | it('returns the underlying data', function () { 17 | var message = new Message(stringTestMsg); 18 | assert.equal(message.getData(), stringTestMsg); 19 | }); 20 | 21 | }); 22 | 23 | describe('#getBytes', function () { 24 | 25 | /*Tests_SRS_NODE_IOTHUB_MESSAGE_07_001: [If the data message that is store is of type Buffer then the data object will get returned unaltered.]*/ 26 | it('returns a Buffer when the underlying data is a Buffer', function () { 27 | var original = new Buffer(stringTestMsg); 28 | var message = new Message(original); 29 | var buffer = message.getBytes(); 30 | assert.instanceOf(buffer, Buffer); 31 | assert.equal(buffer, original); 32 | }); 33 | 34 | /*Tests_SRS_NODE_IOTHUB_MESSAGE_07_002: [If the data message is of any other type then the data will be converted to a Buffer object and returned.]*/ 35 | it('returns a Buffer when the underlying data is NOT a Buffer', function () { 36 | var message = new Message(stringTestMsg); 37 | var buffer = message.getBytes(); 38 | assert.instanceOf(buffer, Buffer); 39 | assert.equal(buffer.toString('ascii'), stringTestMsg); 40 | }); 41 | 42 | }); 43 | 44 | }); 45 | -------------------------------------------------------------------------------- /device/core/device.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | /** 5 | * The `azure-iot-device` module provides a means for devices to send events to and 6 | * receive messages from an Azure IoT Hub. The client handles 7 | * communication with the IoT Hub through a transport supplied by the caller 8 | * (e.g., [Http]{@linkcode module:adapters/https.Http}). 9 | * 10 | * @example 11 | * var Device = require('azure-iot-device'); 12 | * var Client = Device.Client; 13 | * var Message = Device.Message; 14 | * var Http = Device.Http; 15 | * 16 | * function print(err, res) { 17 | * if (err) console.log(err.toString()); 18 | * if (res) console.log(res.statusCode + ' ' + res.statusMessage); 19 | * } 20 | * 21 | * var config = { 22 | * host: 'hostname', 23 | * keyName: 'deviceId', 24 | * key: 'password' 25 | * }; 26 | * 27 | * var client = new Client(new Http(config)); 28 | * 29 | * client.sendEvent(new Message('hello world'), print); 30 | * 31 | * client.receive (function (err, res, msg) { 32 | * print(err, res); 33 | * if (msg) console.log('Message: ' + msg); 34 | * if (!err && res.statusCode !== 204) { 35 | * client.complete(msg, print); 36 | * } 37 | * }); 38 | * 39 | * @module azure-iot-device 40 | */ 41 | 42 | 'use strict'; 43 | 44 | var common = require('azure-iot-common'); 45 | 46 | module.exports = { 47 | Client: require('./lib/client.js').Client, 48 | ConnectionString: require('./lib/connection_string.js'), 49 | Message: common.Message, 50 | SharedAccessSignature: require('./lib/shared_access_signature.js'), 51 | DeviceMethodRequest: require('./lib/device_method').DeviceMethodRequest, 52 | DeviceMethodResponse: require('./lib/device_method').DeviceMethodResponse 53 | }; -------------------------------------------------------------------------------- /service/devdoc/device_requirements.md: -------------------------------------------------------------------------------- 1 | #azure-iothub.Device Requirements 2 | 3 | ## Overview 4 | `Device` is a deprecated class that is present only for backward compatibility purposes and shall be deprecated with the next major version of the SDK. 5 | 6 | ##Example usage 7 | ```js 8 | 'use strict'; 9 | 10 | var Device = require('azure-iothub').Device; 11 | 12 | var device1 = new Device(null); 13 | device.deviceId = 'foo'; 14 | 15 | var device2 = new Device({ deviceId: 'foo' }); 16 | var device3 = new Device("{ \"deviceId\": \"foo\" }"); 17 | ``` 18 | 19 | ##Public Interface 20 | 21 | ### Device(deviceDescription) [constructor] 22 | 23 | **SRS_NODE_SERVICE_DEVICE_16_001: [** The constructor shall accept a `null` or `undefined` value as argument and create an empty `Device` object. **]** 24 | 25 | **SRS_NODE_SERVICE_DEVICE_16_002: [** If the `deviceDescription` argument is provided as a string, it shall be parsed as JSON and the properties of the new `Device` object shall be populated with the values provided in the `deviceDescription` JSON string. **]** 26 | 27 | **SRS_NODE_SERVICE_DEVICE_16_003: [** If the `deviceDescription` argument if provided as an object, the properties of the new `Device` object shall be populated with the values provided in the `deviceDescription` JSON string. **]** 28 | 29 | **SRS_NODE_SERVICE_DEVICE_16_004: [** The constructor shall throw a `ReferenceError` if the `deviceDescription` argument doesn't contain a `deviceId` property. **]** 30 | 31 | ### authentication.SymmetricKey 32 | The `authentication.SymmetricKey` property is here only for backward compatibility purposes and its usage is deprecated. 33 | 34 | **SRS_NODE_SERVICE_DEVICE_16_005: [** The `authentication.SymmetricKey` property shall return the content of the `authentication.symmetricKey` property (the latter being the valid property returned by the IoT hub in the device description). **]** -------------------------------------------------------------------------------- /common/core/devdoc/retry_operation_requirements.md: -------------------------------------------------------------------------------- 1 | # azure-iot-common.RetryOperation Requirements 2 | 3 | ## Overview 4 | 5 | the `RetryOperation` class implements the necessary logic to retry operations such as connecting, receiving C2D messages, sending telemetry, twin updates, etc. 6 | 7 | ## Usage example 8 | 9 | ```js 10 | var op = new RetryOperation(new ExponentialBackoffWithJitter(), 120000); 11 | op.retry(function (retryCallback) { 12 | callSomethingAsync(someParam, retryCallback); 13 | }, function (err, result) { 14 | if (err) { 15 | console.log('error after retrying: ' + err.toString()); 16 | } else { 17 | console.log('successful operation result: ' + result.toString()); 18 | } 19 | }); 20 | ``` 21 | 22 | ## Public API 23 | 24 | ### retry(operation, finalCallback) 25 | 26 | **SRS_NODE_COMMON_RETRY_OPERATION_16_001: [** The `operation` function should be called at every retry. **]** 27 | 28 | **SRS_NODE_COMMON_RETRY_OPERATION_16_002: [** If the `operation` is successful the `finalCallback` function should be called with a `null` error parameter and the result of the operation.**]** 29 | 30 | **SRS_NODE_COMMON_RETRY_OPERATION_16_003: [** If the `operation` fails with an error the `retry` method should determine whether to retry or not using the `shouldRetry` method of the policy passed to the constructor.**]** 31 | 32 | **SRS_NODE_COMMON_RETRY_OPERATION_16_004: [** If the `operation` fails and should not be retried, the `finalCallback` should be called with the last error as the only parameter. **]** 33 | 34 | **SRS_NODE_COMMON_RETRY_OPERATION_16_005: [** If the `operation` fails and should be retried, the time at which to try again the `operation` should be computed using the `nextRetryTimeout` method of the policy passed to the constructor. **]** 35 | 36 | **SRS_NODE_COMMON_RETRY_OPERATION_16_006: [** The `operation` should not be retried past the `maxTimeout` parameter passed to the constructor.**]** 37 | -------------------------------------------------------------------------------- /device/core/devdoc/twin_errors_requirements.md: -------------------------------------------------------------------------------- 1 | # azure-iot-device-http.translateError Requirements 2 | 3 | ## Overview 4 | `translateError` is a method that translates Twin errors into Azure IoT Hub errors, effectively abstracting the error that is returned to the SDK user of from the transport layer. 5 | 6 | ## Requirements 7 | 8 | **SRS_NODE_DEVICE_TWIN_ERRORS_18_002: [** If the error code is unknown, `translateError` should return a generic Javascript `Error` object. **]** 9 | 10 | **SRS_NODE_DEVICE_TWIN_ERRORS_18_003: [** `translateError` shall return an `ArgumentError` if the response status code is `400`. **]** 11 | 12 | **SRS_NODE_DEVICE_TWIN_ERRORS_18_004: [** `translateError` shall return an `UnauthorizedError` if the response status code is `401`. **]** 13 | 14 | **SRS_NODE_DEVICE_TWIN_ERRORS_18_005: [** `translateError` shall return an `IotHubQuotaExceededError` if the response status code is `403`. **]** 15 | 16 | **SRS_NODE_DEVICE_TWIN_ERRORS_18_006: [** `translateError` shall return an `DeviceNotFoundError` if the response status code is `404`. **]** 17 | 18 | **SRS_NODE_DEVICE_TWIN_ERRORS_18_007: [** `translateError` shall return an `MessageTooLargeError` if the response status code is `413`. **]** 19 | 20 | **SRS_NODE_DEVICE_TWIN_ERRORS_18_008: [** `translateError` shall return an `InternalServerError` if the response status code is `500`. **]** 21 | 22 | **SRS_NODE_DEVICE_TWIN_ERRORS_18_009: [** `translateError` shall return an `ServiceUnavailableError` if the response status code is `503`. **]** 23 | 24 | **SRS_NODE_DEVICE_TWIN_ERRORS_18_011: [** `translateError` shall return an `ServiceUnavailableError` if the response status code is `504`. **]** 25 | 26 | **SRS_NODE_DEVICE_TWIN_ERRORS_18_012: [** `translateError` shall return an `ThrottlingError` if the response status code is `429`. **]** 27 | 28 | **SRS_NODE_DEVICE_TWIN_ERRORS_18_013: [** `translateError` shall return an `InvalidEtagError` if the response status code is `412`. **]** 29 | -------------------------------------------------------------------------------- /service/samples/dmpatterns_reboot_service.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 'use strict'; 4 | 5 | var Registry = require('azure-iothub').Registry; 6 | var Client = require('azure-iothub').Client; 7 | var async = require('async'); 8 | 9 | // receive the IoT Hub connection string as a command line parameter 10 | if(process.argv.length < 4) { 11 | console.error('Usage: node dmpatterns_reboot_service.js <> <>'); 12 | process.exit(1); 13 | } 14 | 15 | var connectionString = process.argv[2]; 16 | var registry = Registry.fromConnectionString(connectionString); 17 | var client = Client.fromConnectionString(connectionString); 18 | var deviceToReboot = process.argv[3]; 19 | 20 | // Initiate the reboot process on the device using a device method 21 | async.waterfall([ 22 | invokeReboot, 23 | displayRebootStatus 24 | ], 25 | function(err) { 26 | if (err){ 27 | console.error(err); 28 | } else { 29 | console.log('Reboot complete'); 30 | } 31 | }); 32 | 33 | // Initiate the reboot through a method 34 | function invokeReboot(callback) { 35 | client.invokeDeviceMethod(deviceToReboot, 36 | { 37 | methodName: "reboot", 38 | payload: null, 39 | timeoutInSeconds: 30 40 | }, function (err, result) { 41 | console.log(JSON.stringify(result, null, 2)); 42 | callback(err); 43 | } 44 | ); 45 | } 46 | 47 | // Get the twin and output the reboot status from reported properties 48 | function displayRebootStatus(callback) { 49 | registry.getTwin(deviceToReboot, function(err, twin){ 50 | if (err) { 51 | callback(err); 52 | } 53 | else { 54 | // Output the value of twin reported properties, which includes the reboot details 55 | console.log(twin.properties.reported); 56 | callback(null); 57 | } 58 | }); 59 | } 60 | 61 | -------------------------------------------------------------------------------- /device/transport/http/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-device-http", 3 | "version": "1.1.17", 4 | "description": "HTTP transport for Azure IoT device SDK", 5 | "author": "Microsoft Corporation", 6 | "license": "MIT", 7 | "main": "index.js", 8 | "typings": "index.d.ts", 9 | "dependencies": { 10 | "azure-iot-http-base": "1.1.11", 11 | "azure-iot-common": "1.1.11", 12 | "azure-iot-device": "1.1.17", 13 | "node-crontab": "^0.0.8" 14 | }, 15 | "devDependencies": { 16 | "azure-iothub": "1.1.15", 17 | "chai": "^3.5.0", 18 | "istanbul": "^0.4.4", 19 | "jshint": "^2.9.2", 20 | "mocha": "^3.0.1", 21 | "sinon": "^1.17.5", 22 | "tslint": "^5.1.0", 23 | "typescript": "2.2.2", 24 | "@types/node": "^7.0.5" 25 | }, 26 | "scripts": { 27 | "lint": "tslint --type-check --project . -c ../../../tslint.json", 28 | "build": "tsc", 29 | "unittest-min": "istanbul cover --report none node_modules/mocha/bin/_mocha -- --reporter dot test/_*_test.js", 30 | "alltest-min": "istanbul cover --report none node_modules/mocha/bin/_mocha -- --reporter dot test/_*_test*.js", 31 | "unittest": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec test/_*_test.js", 32 | "alltest": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec test/_*_test*.js", 33 | "ci": "npm -s run lint && npm -s run build && npm -s run alltest-min && npm -s run check-cover", 34 | "test": "npm -s run lint && npm -s run build && npm -s run unittest", 35 | "check-cover": "istanbul check-coverage --statements 86 --branches 72 --lines 88 --functions 83" 36 | }, 37 | "engines": { 38 | "node": ">= 0.10" 39 | }, 40 | "repository": { 41 | "type": "git", 42 | "url": "git+https://github.com/Azure/azure-iot-sdk-node.git" 43 | }, 44 | "bugs": { 45 | "url": "https://github.com/Azure/azure-iot-sdk-node/issues" 46 | }, 47 | "homepage": "https://github.com/Azure/azure-iot-sdk-node#readme" 48 | } -------------------------------------------------------------------------------- /doc/dmpatterns.md: -------------------------------------------------------------------------------- 1 | # The device management patterns samples 2 | 3 | The device management pattern samples support the following device management tutorials, which provide both the device and service side code ready to execute. 4 | 5 | - [Get started with device management][get-started-dm-doc] 6 | - [How to do a firmware update][fw-update-doc] 7 | 8 | To learn more about Azure IoT Hub device management, see [Overview of Azure IoT Hub device management][overview-iot-dm-doc]. 9 | 10 | ## Running the samples 11 | 12 | From the root directory of the repository, run through the following steps to see the device and service interacting to enable the device management patterns: 13 | 14 | ### Reboot device management pattern: 15 | 16 | 1. Start the device side first, as it will register the C2D method listener for reboot: 17 | ``` 18 | node device\samples\dmpatterns_reboot_device.js 19 | ``` 20 | 21 | 2. In a new terminal window, start the service side to initate the reboot: 22 | 23 | ``` 24 | node service\samples\dmpatterns_reboot_service.js 25 | ``` 26 | 27 | ### Firmware Update device management pattern: 28 | 29 | 1. Start the device side first, as it will register the C2D method listener for firmware update: 30 | 31 | ``` 32 | node device\samples\dmpatterns_fwupdate_device.js 33 | ``` 34 | 35 | 2. In a new terminal window, start the service side to initate the firmware update: 36 | 37 | ``` 38 | node service\samples\dmpatterns_fwupdate_service.js 39 | ``` 40 | 41 | [overview-iot-dm-doc]: https://azure.microsoft.com/en-us/documentation/articles/iot-hub-device-management-overview/ 42 | [get-started-dm-doc]: https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-node-node-device-management-get-started 43 | [fw-update-doc]: https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-node-node-firmware-update 44 | -------------------------------------------------------------------------------- /device/transport/mqtt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-device-mqtt", 3 | "version": "1.1.17", 4 | "description": "MQTT transport for Azure IoT device SDK", 5 | "author": "Microsoft Corporation", 6 | "license": "MIT", 7 | "main": "index.js", 8 | "typings": "index.d.ts", 9 | "dependencies": { 10 | "azure-iot-common": "1.1.11", 11 | "azure-iot-device": "1.1.17", 12 | "debug": "^2.6.0", 13 | "mqtt": "^1.14.1" 14 | }, 15 | "devDependencies": { 16 | "chai": "^3.5.0", 17 | "istanbul": "^0.4.5", 18 | "jshint": "^2.9.4", 19 | "mocha": "^3.2.0", 20 | "sinon": "^1.17.7", 21 | "es5-shim": "^4.5.9", 22 | "tslint": "^5.1.0", 23 | "typescript": "2.2.2", 24 | "@types/node": "^7.0.5", 25 | "@types/mqtt": "0.0.34" 26 | }, 27 | "scripts": { 28 | "lint": "tslint --type-check --project . -c ../../../tslint.json", 29 | "build": "tsc", 30 | "unittest-min": "istanbul cover --report none node_modules/mocha/bin/_mocha -- --reporter dot test/_*_test.js", 31 | "alltest-min": "istanbul cover --report none node_modules/mocha/bin/_mocha -- --reporter dot test/_*_test*.js", 32 | "unittest": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec test/_*_test.js", 33 | "alltest": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec test/_*_test*.js", 34 | "ci": "npm -s run lint && npm -s run build && npm -s run alltest-min && npm -s run check-cover", 35 | "test": "npm -s run lint && npm -s run build && npm -s run unittest", 36 | "check-cover": "istanbul check-coverage --statements 89 --branches 76 --functions 76 --lines 90" 37 | }, 38 | "engines": { 39 | "node": ">= 0.10" 40 | }, 41 | "repository": { 42 | "type": "git", 43 | "url": "git+https://github.com/Azure/azure-iot-sdk-node.git" 44 | }, 45 | "bugs": { 46 | "url": "https://github.com/Azure/azure-iot-sdk-node/issues" 47 | }, 48 | "homepage": "https://github.com/Azure/azure-iot-sdk-node#readme" 49 | } -------------------------------------------------------------------------------- /common/core/src/dictionary.ts: -------------------------------------------------------------------------------- 1 | /*! Copyright (c) Microsoft. All rights reserved. 2 | *! Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | /*Codes_SRS_NODE_COMMON_DICTIONARY_05_001: [The function createDictionary shall accept as arguments the source string and a field separator string.]*/ 8 | export function createDictionary(source: string, separator: string): createDictionary.Dictionary { 9 | let dict: createDictionary.Dictionary = {}; 10 | /*Codes_SRS_NODE_COMMON_DICTIONARY_05_003: [createDictionary shall search the source string for elements of the form 'key=value', where the element is found either at the beginning of the source string, or immediately following an instance of the field separator string.]*/ 11 | /*Codes_SRS_NODE_COMMON_DICTIONARY_05_002: [createDictionary shall convert the source and separator arguments to type String before using them.]*/ 12 | /*Codes_SRS_NODE_COMMON_DICTIONARY_05_006: [If the source string is falsy, createDictionary shall return an object with no properties.]*/ 13 | const elems: string[] = String(source).split(String(separator)); 14 | 15 | elems.forEach(function (elem: string): void { 16 | const pos = elem.indexOf('='); 17 | if (pos < 0) return; 18 | 19 | const name = elem.substring(0, pos); 20 | const value = elem.substring(pos + 1); 21 | 22 | if (name && value) { 23 | /*Codes_SRS_NODE_COMMON_DICTIONARY_05_004: [If there are multiple pairs with the same key, createDictionary shall keep the last pair.]*/ 24 | dict[name] = value; 25 | } 26 | }); 27 | 28 | /*Codes_SRS_NODE_COMMON_DICTIONARY_05_005: [createDictionary shall return an object with properties matching each discovered element in the source string.]*/ 29 | return dict; 30 | } 31 | 32 | export namespace createDictionary { 33 | /** 34 | * @private 35 | */ 36 | export interface Dictionary { 37 | [key: string]: T; 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /common/core/src/authorization.ts: -------------------------------------------------------------------------------- 1 | /*! Copyright (c) Microsoft. All rights reserved. 2 | *! Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import * as crypto from 'crypto'; 8 | 9 | /** 10 | * Returns the seconds elapsed since 1 January 1970 00:00:00 UTC until one 11 | * hour from now. 12 | * @function anHourFromNow 13 | */ 14 | export function anHourFromNow(): number { 15 | const raw = (Date.now() / 1000) + 3600; 16 | return Math.ceil(raw); 17 | } 18 | 19 | /*Codes_SRS_NODE_COMMON_AUTHORIZATION_05_004: [ shall be the URL-encoded .]*/ 20 | /*Codes_SRS_NODE_COMMON_AUTHORIZATION_05_007: [ shall be the URL-encoded .]*/ 21 | export function encodeUriComponentStrict(str: string): string { 22 | // this stricter version of encodeURIComponent is a recommendation straight out of the MDN docs, see: 23 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#Description 24 | return encodeURIComponent(str).replace(/[!'()*]/g, function(c: string): string { 25 | return '%' + c.charCodeAt(0).toString(16); 26 | }); 27 | } 28 | 29 | /*Codes_SRS_NODE_COMMON_AUTHORIZATION_05_006: [ shall be a concatenation of + '\n' + .]*/ 30 | export function stringToSign(resourceUri: string, expiry: string): string { 31 | return resourceUri + '\n' + expiry; 32 | } 33 | 34 | /*Codes_SRS_NODE_COMMON_AUTHORIZATION_05_005: [ shall be an HMAC-SHA256 hash of , which is then base64-encoded.]*/ 35 | /*Codes_SRS_NODE_COMMON_AUTHORIZATION_05_011: [The crypto algorithm should directly convert from base64 encoded password buffer to ensure JS compatibility]*/ 36 | export function hmacHash(password: string, stringToSign: string): string { 37 | let hmac = crypto.createHmac('sha256', new Buffer(password, 'base64')); 38 | hmac.update(stringToSign); 39 | return hmac.digest('base64'); 40 | } 41 | -------------------------------------------------------------------------------- /service/devdoc/shared_access_signature_requirements.md: -------------------------------------------------------------------------------- 1 | # azure-iothub.SharedAccessSignature Requirements 2 | 3 | ## Overview 4 | `SharedAccessSignature` is a type representing an IoT Hub shared access signature. It exposes a static factory method for creating a shared access signature object from a string, and exposes properties for each of the parsed fields in the string. It also validates the required properties of the shared access signature. 5 | 6 | ## Example usage 7 | ```javascript 8 | 'use strict'; 9 | var SharedAccessSignature = require('azure-iothub'). SharedAccessSignature; 10 | 11 | var sas = SharedAccessSignature.parse('[Shared access signature]'); 12 | console.log('sr=' + sas.sr); 13 | console.log('sig=' + sas.sig); 14 | console.log('skn=' + sas.skn); 15 | console.log('se=' + sas.se); 16 | ``` 17 | 18 | ## Public Interface 19 | 20 | ### SharedAccessSignature constructor 21 | Creates a new instance of the object. Normally callers will use one of the static factory methods (`create`, `parse`) to create a `SharedAccessSignature`. 22 | 23 | ### create(host, policy, key, expiry) [static] 24 | The `create` static method returns a new instance of the `SharedAccessSignature` object with `sr`, `sig`, `skn`, and `se` properties. 25 | 26 | **SRS_NODE_IOTHUB_SAS_05_003: [** The `create` method shall return the result of calling `azure-iot-common.SharedAccessSignature.create` with following arguments: 27 | ``` 28 | resourceUri - host 29 | keyName - policy 30 | key - key 31 | expiry - expiry 32 | ``` 33 | **]** 34 | 35 | ### parse(source) [static] 36 | The `parse` static method returns a new instance of the `SharedAccessSignature` object with properties corresponding to each `name=value` field found in source. 37 | 38 | **SRS_NODE_IOTHUB_SAS_05_001: [** The `parse` method shall return the result of calling `azure-iot-common.SharedAccessSignature.parse`.**]** 39 | **SRS_NODE_IOTHUB_SAS_05_002: [** It shall throw `ArgumentError` if any of `sr`, `sig`, `skn` or `se` fields are not found in the source argument.**]** 40 | -------------------------------------------------------------------------------- /device/transport/amqp/test/_amqp_device_errors_test.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var assert = require('chai').assert; 7 | var errors = require('azure-iot-common').errors; 8 | var translateError = require('azure-iot-amqp-base').translateError; 9 | 10 | describe('translateError', function() { 11 | /*Tests_SRS_NODE_DEVICE_AMQP_DEVICE_ERRORS_16_001: [`translateError` shall return an `IotHubQuotaExceededError` if the AMQP error condition is `amqp:resource-limit-exceeded`.]*/ 12 | [ 13 | { errorDescription: 'amqp:resource-limit-exceeded', errorMessage: 'Fake forbidden', expectedErrorType: errors.IotHubQuotaExceededError }, 14 | ].forEach(function(testParams) { 15 | it('returns an \'' + testParams.expectedErrorType.name + '\' if the amqp error description is \'' + testParams.errorDescription + '\'', function(){ 16 | var AMQPError = function AMQPError() { 17 | Error.call(this); 18 | }; 19 | 20 | var fake_error = new AMQPError(); 21 | fake_error.condition = testParams.errorDescription; 22 | 23 | /*Tests_SRS_NODE_DEVICE_AMQP_ERRORS_16_010: [ `translateError` shall accept 2 argument: 24 | *- A custom error message to give context to the user. 25 | *- the AMQP error object itself] 26 | */ 27 | var err = translateError(new Error(testParams.errorMessage), fake_error); 28 | assert.instanceOf(err, testParams.expectedErrorType); 29 | 30 | /*Tests_SRS_NODE_DEVICE_AMQP_ERRORS_16_001: [Any error object returned by `translateError` shall inherit from the generic `Error` Javascript object and have 2 properties: 31 | *- `amqpError` shall contain the error object returned by the AMQP layer. 32 | *- `message` shall contain a human-readable error message] 33 | */ 34 | assert.equal(err.message, 'Error: ' + testParams.errorMessage); 35 | assert.equal(err.amqpError, fake_error); 36 | }); 37 | }); 38 | }); -------------------------------------------------------------------------------- /common/transport/amqp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-amqp-base", 3 | "version": "1.1.12", 4 | "description": "AMQP operations used by Azure IoT device and service SDKs", 5 | "author": "Microsoft Corporation", 6 | "license": "MIT", 7 | "main": "main.js", 8 | "typings": "index.d.ts", 9 | "dependencies": { 10 | "amqp10": "3.5.0", 11 | "amqp10-transport-ws": "^0.0.5", 12 | "azure-iot-common": "1.1.11", 13 | "bluebird": "^3.5.0", 14 | "debug": "^2.6.0", 15 | "uuid": "^3.0.1" 16 | }, 17 | "devDependencies": { 18 | "sinon": "^1.17.7", 19 | "sinon-as-promised": "^4.0.2", 20 | "chai": "^3.5.0", 21 | "istanbul": "^0.4.5", 22 | "jshint": "^2.9.4", 23 | "mocha": "^3.2.0", 24 | "tslint": "^5.1.0", 25 | "typescript": "2.2.2", 26 | "@types/node": "^7.0.12", 27 | "uuid": "^3.0.1" 28 | }, 29 | "scripts": { 30 | "lint": "tslint --type-check --project . -c ../../../tslint.json", 31 | "build": "tsc", 32 | "unittest-min": "istanbul cover --report none node_modules/mocha/bin/_mocha -- --reporter dot test/_*_test.js", 33 | "alltest-min": "istanbul cover --report none node_modules/mocha/bin/_mocha -- --reporter dot test/_*_test*.js", 34 | "unittest": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec test/_*_test.js", 35 | "alltest": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec test/_*_test*.js", 36 | "ci": "npm -s run lint && npm -s run build && npm -s run alltest-min && npm -s run check-cover", 37 | "test": "npm -s run lint && npm -s run build && npm -s run unittest", 38 | "check-cover": "istanbul check-coverage --statements 95 --branches 83 --functions 89 --lines 95" 39 | }, 40 | "engines": { 41 | "node": ">= 0.10" 42 | }, 43 | "repository": { 44 | "type": "git", 45 | "url": "git+https://github.com/Azure/azure-iot-sdk-node.git" 46 | }, 47 | "bugs": { 48 | "url": "https://github.com/Azure/azure-iot-sdk-node/issues" 49 | }, 50 | "homepage": "https://github.com/Azure/azure-iot-sdk-node#readme" 51 | } -------------------------------------------------------------------------------- /service/test/_amqp_service_errors_test.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var assert = require('chai').assert; 7 | var errors = require('azure-iot-common').errors; 8 | var translateError = require('../lib/amqp_service_errors.js').translateError; 9 | 10 | describe('translateError', function() { 11 | /*Tests_SRS_NODE_DEVICE_AMQP_SERVICE_ERRORS_16_001: [ `translateError` shall return an `DeviceMaximumQueueDepthExceededError` if the AMQP error condition is `amqp:resource-limit-exceeded`.] */ 12 | [ 13 | { errorDescription: 'amqp:resource-limit-exceeded', errorMessage: 'Fake forbidden', expectedErrorType: errors.DeviceMaximumQueueDepthExceededError }, 14 | ].forEach(function(testParams) { 15 | it('returns an \'' + testParams.expectedErrorType.name + '\' if the amqp error description is \'' + testParams.errorDescription + '\'', function(){ 16 | var AMQPError = function AMQPError() { 17 | Error.call(this); 18 | }; 19 | 20 | var fake_error = new AMQPError(); 21 | fake_error.condition = testParams.errorDescription; 22 | 23 | /*Tests_SRS_NODE_DEVICE_AMQP_ERRORS_16_010: [ `translateError` shall accept 2 argument: 24 | *- A custom error message to give context to the user. 25 | *- the AMQP error object itself] 26 | */ 27 | var err = translateError(new Error(testParams.errorMessage), fake_error); 28 | assert.instanceOf(err, testParams.expectedErrorType); 29 | 30 | /*Tests_SRS_NODE_DEVICE_AMQP_ERRORS_16_001: [Any error object returned by `translateError` shall inherit from the generic `Error` Javascript object and have 2 properties: 31 | *- `amqpError` shall contain the error object returned by the AMQP layer. 32 | *- `message` shall contain a human-readable error message] 33 | */ 34 | assert.equal(err.message, 'Error: ' + testParams.errorMessage); 35 | assert.equal(err.amqpError, fake_error); 36 | }); 37 | }); 38 | }); -------------------------------------------------------------------------------- /service/test/amqp_simulated.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var errors = require('azure-iot-common').errors; 7 | var results = require('azure-iot-common').results; 8 | var EventEmitter = require('events').EventEmitter; 9 | var util = require('util'); 10 | var AmqpReceiver = require('azure-iot-amqp-base').AmqpReceiver; 11 | 12 | function SimulatedAmqp() { 13 | EventEmitter.call(this); 14 | this._config = { 15 | sharedAccessSignature: 'ok' 16 | }; 17 | this._receiver = new AmqpReceiver(new EventEmitter()); 18 | this.FeedbackReceiver = AmqpReceiver; 19 | } 20 | 21 | util.inherits(SimulatedAmqp, EventEmitter); 22 | 23 | SimulatedAmqp.prototype.connect = function connect(done) { 24 | if (!!done) done(); 25 | }; 26 | 27 | SimulatedAmqp.prototype.disconnect = function disconnect(done) { 28 | if (!!done) done(); 29 | }; 30 | 31 | SimulatedAmqp.prototype.send = function send(deviceId, message, done) { 32 | if (done) { 33 | if (deviceId.search(/^no-device/) !== -1) { 34 | done(new errors.DeviceNotFoundError()); 35 | } 36 | else { 37 | done(null, new results.MessageEnqueued()); 38 | if (message.ack === 'full') { 39 | this._receiver.emit('message', { 40 | body: [{ 41 | originalMessageId: message.messageId, 42 | deviceId: deviceId 43 | }] 44 | }); 45 | } 46 | } 47 | } 48 | }; 49 | 50 | SimulatedAmqp.prototype.getFeedbackReceiver = function (done) { 51 | if (this._config.sharedAccessSignature === 'fail') { 52 | done(new Error('error')); 53 | } 54 | else { 55 | done(null, this._receiver); 56 | } 57 | }; 58 | 59 | SimulatedAmqp.prototype.getFileNotificationReceiver = function (done) { 60 | if (this._config.sharedAccessSignature === 'fail') { 61 | done(new Error('error')); 62 | } 63 | else { 64 | done(null, this._receiver); 65 | } 66 | }; 67 | 68 | module.exports = SimulatedAmqp; 69 | -------------------------------------------------------------------------------- /device/transport/amqp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-device-amqp", 3 | "version": "1.1.17", 4 | "description": "AMQP transport for Azure IoT device SDK", 5 | "author": "Microsoft Corporation", 6 | "license": "MIT", 7 | "main": "index.js", 8 | "typings": "index.d.ts", 9 | "dependencies": { 10 | "azure-iot-amqp-base": "1.1.12", 11 | "azure-iot-common": "1.1.11", 12 | "azure-iot-device": "1.1.17", 13 | "debug": "^2.6.0", 14 | "machina": "^2.0.0", 15 | "uuid": "^3.0.1" 16 | }, 17 | "devDependencies": { 18 | "azure-iothub": "1.1.15", 19 | "bluebird": "^3.5.0", 20 | "chai": "^3.5.0", 21 | "istanbul": "^0.4.5", 22 | "jshint": "^2.9.4", 23 | "mocha": "^3.2.0", 24 | "sinon": "^1.17.7", 25 | "tslint": "^5.1.0", 26 | "typescript": "2.2.2", 27 | "@types/node": "^7.0.5", 28 | "@types/debug": "0.0.29" 29 | }, 30 | "scripts": { 31 | "lint": "tslint --type-check --project . -c ../../../tslint.json", 32 | "build": "tsc", 33 | "unittest-min": "istanbul cover --report none node_modules/mocha/bin/_mocha -- --reporter dot test/_*_test.js", 34 | "alltest-min": "istanbul cover --report none node_modules/mocha/bin/_mocha -- --reporter dot test/_*_test*.js", 35 | "unittest": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec test/_*_test.js", 36 | "alltest": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec test/_*_test*.js", 37 | "ci": "npm -s run lint && npm -s run build && npm -s run alltest-min && npm -s run check-cover", 38 | "test": "npm -s run lint && npm -s run build && npm -s run unittest", 39 | "check-cover": "istanbul check-coverage --statements 95 --branches 80 --lines 96 --functions 92" 40 | }, 41 | "engines": { 42 | "node": ">= 0.10" 43 | }, 44 | "repository": { 45 | "type": "git", 46 | "url": "git+https://github.com/Azure/azure-iot-sdk-node.git" 47 | }, 48 | "bugs": { 49 | "url": "https://github.com/Azure/azure-iot-sdk-node/issues" 50 | }, 51 | "homepage": "https://github.com/Azure/azure-iot-sdk-node#readme" 52 | } -------------------------------------------------------------------------------- /device/core/devdoc/shared_access_signature.md: -------------------------------------------------------------------------------- 1 | # azure-iot-device.SharedAccessSignature Requirements 2 |   3 | ## Overview 4 | `SharedAccessSignature` is a type representing an IoT Hub device shared access signature. It exposes a static factory method for creating a shared access signature object from a string, and exposes properties for each of the parsed fields in the string. It also validates the required properties of the shared access signature. 5 | 6 | ## Example usage 7 | ```js 8 | 'use strict'; 9 | var SharedAccessSignature = require('azure-iot-device'). SharedAccessSignature; 10 | 11 | var sas = SharedAccessSignature.parse('[Shared access signature]'); 12 | console.log('sr=' + sas.sr); 13 | console.log('sig=' + sas.sig); 14 | console.log('se=' + sas.se); 15 | ``` 16 | 17 | ## Public Interface 18 | ### SharedAccessSignature constructor 19 | Creates a new instance of the object. Normally callers will use one of the static factory methods (`create`, `parse`) to create a `SharedAccessSignature`. 20 | 21 | ### create(host, deviceId, key, expiry) [static] 22 | The `create` static method returns a new instance of the `SharedAccessSignature` object with `sr`, `sig`, and `se` properties. 23 | 24 | **SRS_NODE_DEVICE_SAS_05_003: [**The create method shall return the result of calling `azure-iot-common.SharedAccessSignature.create` with following arguments: 25 | ``` 26 | resourceUri - host + '%2Fdevices%2f' + 27 | keyName - null 28 | key - key 29 | expiry - expiry 30 | ``` 31 | **]** 32 | 33 | **SRS_NODE_DEVICE_SAS_05_004: [**`` shall be the URL-encoded value of deviceId.**]** 34 | 35 | ### parse(source) [static] 36 | The `parse` static method returns a new instance of the `SharedAccessSignature` object with properties corresponding to each 'name=value' field found in source. 37 | 38 | **SRS_NODE_DEVICE_SAS_05_001: [**The `parse` method shall return the result of calling `azure-iot-common.SharedAccessSignature.parse`.**]** 39 | 40 | **SRS_NODE_DEVICE_SAS_05_002: [**It shall throw `ArgumentError` if any of `sr`, `sig`, `se` fields are not found in the source argument.**]** 41 | -------------------------------------------------------------------------------- /device/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-device", 3 | "version": "1.1.17", 4 | "description": "Azure IoT device SDK", 5 | "author": "Microsoft Corporation", 6 | "license": "MIT", 7 | "main": "device.js", 8 | "typings": "device.d.ts", 9 | "dependencies": { 10 | "azure-iot-common": "1.1.11", 11 | "azure-iot-http-base": "1.1.11", 12 | "azure-storage": "^2.0.0", 13 | "debug": "^2.6.0", 14 | "lodash": "^4.17.4", 15 | "machina": "^2.0.0", 16 | "traverse": "^0.6.6" 17 | }, 18 | "devDependencies": { 19 | "chai": "^3.5.0", 20 | "istanbul": "^0.4.5", 21 | "jshint": "^2.9.4", 22 | "mocha": "^3.2.0", 23 | "sinon": "^1.17.7", 24 | "es5-shim": "^4.5.9", 25 | "tslint": "^5.1.0", 26 | "typescript": "2.2.2", 27 | "@types/node": "^7.0.5", 28 | "@types/debug": "0.0.29", 29 | "@types/traverse": "^0.6.29" 30 | }, 31 | "scripts": { 32 | "lint": "tslint --type-check --project . -c ../../tslint.json", 33 | "build": "tsc", 34 | "unittest-min": "istanbul cover --report none node_modules/mocha/bin/_mocha -- --reporter dot \"test/**/_*_test.js\"", 35 | "alltest-min": "istanbul cover --report none node_modules/mocha/bin/_mocha -- --reporter dot \"test/**/_*_test*.js\"", 36 | "unittest": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec \"test/**/_*_test.js\"", 37 | "alltest": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec \"test/**/_*_test*.js\"", 38 | "ci": "npm -s run lint && npm -s run build && npm -s run alltest-min && npm -s run check-cover", 39 | "test": "npm -s run lint && npm -s run build && npm -s run unittest", 40 | "check-cover": "istanbul check-coverage --statements 97 --branches 87 --lines 98 --functions 94" 41 | }, 42 | "engines": { 43 | "node": ">= 0.10" 44 | }, 45 | "repository": { 46 | "type": "git", 47 | "url": "git+https://github.com/Azure/azure-iot-sdk-node.git" 48 | }, 49 | "bugs": { 50 | "url": "https://github.com/Azure/azure-iot-sdk-node/issues" 51 | }, 52 | "homepage": "https://github.com/Azure/azure-iot-sdk-node#readme" 53 | } -------------------------------------------------------------------------------- /service/samples/dmpatterns_fwupdate_service.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 'use strict'; 4 | 5 | var Registry = require('azure-iothub').Registry; 6 | var Client = require('azure-iothub').Client; 7 | var async = require('async'); 8 | 9 | // receive the IoT Hub connection string as a command line parameter 10 | if (process.argv.length < 4) { 11 | console.error('Usage: node dmpatterns_fwupdate_service.js <> <>'); 12 | process.exit(1); 13 | } 14 | 15 | var connectionString = process.argv[2]; 16 | var registry = Registry.fromConnectionString(connectionString); 17 | var client = Client.fromConnectionString(connectionString); 18 | var deviceToUpdate = process.argv[3]; 19 | 20 | // Service entry point: Initiate the firmware update process on the device using a device method 21 | async.waterfall([ 22 | invokeFirmwareUpdate, 23 | displayFirmwareUpdateStatus 24 | ], 25 | function(err) { 26 | if (err) { 27 | console.error(err); 28 | } else { 29 | console.log('Fimware update complete'); 30 | } 31 | }); 32 | 33 | // Initiate the firmware update through a method 34 | function invokeFirmwareUpdate(callback) { 35 | client.invokeDeviceMethod(deviceToUpdate, 36 | { 37 | methodName: "firmwareUpdate", 38 | payload: { 39 | fwPackageUri: 'https://secureurl' 40 | }, 41 | timeoutInSeconds: 30 42 | }, function (err, result) { 43 | console.log(JSON.stringify(result, null, 2)); 44 | callback(err); 45 | } 46 | ); 47 | } 48 | 49 | // Get the twin and output the firmwareUpdate status from reported properties 50 | function displayFirmwareUpdateStatus(callback) { 51 | registry.getTwin(deviceToUpdate, function(err, twin){ 52 | if (err) { 53 | callback(err); 54 | } else { 55 | // Output the value of twin reported properties, which includes the firmwareUpdate details 56 | console.log(twin.properties.reported); 57 | callback(null); 58 | } 59 | }); 60 | } 61 | 62 | -------------------------------------------------------------------------------- /service/devdoc/service_amqp_ws_requirement.md: -------------------------------------------------------------------------------- 1 | #azure-iothub.AmqpWs requirements 2 | 3 | ## Overview 4 | `AmqpWs` provides transport functionality for applications that want to communicate with an Azure IoT Hub using the AMQP protocol **over websockets**. 5 | It provides an additional level of abstraction on top of the `AmqpTransport` class which is not specific to the device or service side (and is located in the `azure-iot-common` package). 6 | Based on the configuration parameters given to the constructor, the Amqp object will build the SASL-Plain URL used to communicate with the IoT Hub instance, as well as the sending and receiving endpoints, and will instantiate an `AmqpTransport` object to use with these parameters. 7 | 8 | ## Usage 9 | ```js 10 | 'use strict'; 11 | var Amqp = require('./lib/amqp_ws.js').Amqp; 12 | var Message = require('azure-iot-common').Message; 13 | 14 | function print(err, res) { 15 | if (err) console.log(err.toString()); 16 | if (res) console.log(res.constructor.name); 17 | } 18 | 19 | var serviceConfig = { 20 | host: 'hostname', 21 | keyName: 'keyname' , 22 | key: 'key' 23 | }; 24 | 25 | var serviceAmqp = new Amqp(serviceConfig); 26 | serviceAmqp.send(deviceId, new Message('hello world'), print); 27 | serviceAmqp.getReceiver(function (receiver) { 28 | receiver.on('message', function (msg) { 29 | receiver.complete(msg, print); 30 | }); 31 | receiver.on('errorReceived', function (err) { 32 | print(err); 33 | }); 34 | }); 35 | 36 | ``` 37 | ## Public API 38 | ### constructor 39 | 40 | **SRS_NODE_IOTHUB_SERVICE_AMQP_WS_16_001: [** The `AmqpWs` constructor shall accept a config object with those four properties: 41 | - `host` – (string) the fully-qualified DNS hostname of an IoT Hub 42 | - `hubName` - (string) the name of the IoT Hub instance (without suffix such as .azure-devices.net). 43 | - `keyName` – (string) the name of a key that can be used to communicate with the IoT Hub instance 44 | - `sharedAccessSignature–` (string) the key associated with the key name. **]** 45 | 46 | **SRS_NODE_IOTHUB_SERVICE_AMQP_WS_16_002: [** `AmqpWs` should inherit from `Amqp`. **]** 47 | -------------------------------------------------------------------------------- /service/test/_shared_access_signature_test.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var assert = require('chai').assert; 7 | var ArgumentError = require('azure-iot-common').errors.ArgumentError; 8 | var SharedAccessSignature = require('../lib/shared_access_signature.js'); 9 | 10 | var incompleteSignatures = { 11 | sr: 'SharedAccessSignature sig=signature&skn=keyname&se=expiry', 12 | sig: 'SharedAccessSignature sr=audience&skn=keyname&se=expiry', 13 | skn: 'SharedAccessSignature sr=audience&sig=signature&se=expiry', 14 | se: 'SharedAccessSignature sr=audience&sig=signature&skn=keyname' 15 | }; 16 | 17 | describe('SharedAccessSignature', function () { 18 | describe('#create', function () { 19 | /*Tests_SRS_NODE_IOTHUB_SAS_05_003: [The create method shall return the result of calling azure-iot-common.SharedAccessSignature.create with following arguments: 20 | resourceUri - host 21 | keyName - policy 22 | key - key 23 | expiry - expiry]*/ 24 | it('creates a shared access signature', function () { 25 | var expect = 'SharedAccessSignature sr=host&sig=88JmrIsVYOGmRSjCO1x1LLbv0K001Gikh1rjfJqbQXA%3D&skn=policy&se=12345'; 26 | var sas = SharedAccessSignature.create('host', 'policy', 'key', 12345); 27 | assert.equal(expect, sas.toString()); 28 | }); 29 | }); 30 | 31 | describe('#parse', function () { 32 | /*Tests_SRS_NODE_IOTHUB_SAS_05_001: [The parse method shall return the result of calling azure-iot-common.SharedAccessSignature.parse.]*/ 33 | /*Tests_SRS_NODE_IOTHUB_SAS_05_002: [It shall throw ArgumentError if any of 'sr', 'sig', 'skn' or 'se' fields are not found in the source argument.]*/ 34 | ['sr', 'sig', 'skn', 'se'].forEach(function (key) { 35 | it('throws if shared access signature is missing ' + key, function () { 36 | assert.throws(function () { 37 | SharedAccessSignature.parse(incompleteSignatures[key]); 38 | }, ArgumentError); 39 | }); 40 | }); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /device/core/devdoc/device_method/device_method_response_requirements.md: -------------------------------------------------------------------------------- 1 | # azure-iot-device.deviceMethod.DeviceMethodResponse requirements 2 | 3 | # Overview 4 | `DeviceMethodResponse` provides functionality that allows a device method implementation to construct and send a response back to the service for a device method call. An instance of this class is passed as the second parameter to the callback registered via the `azure-iot-device.Client.onDeviceMethod` method. 5 | 6 | # Public API 7 | 8 | ## DeviceMethodResponse(requestId, transport) [constructor] 9 | Initializes a new instance of the `DeviceMethodResponse` class. 10 | 11 | **SRS_NODE_DEVICE_METHOD_RESPONSE_13_001: [** `DeviceMethodResponse` shall throw a `ReferenceError` if `requestId` is falsy or is not a string. **]** 12 | 13 | **SRS_NODE_DEVICE_METHOD_RESPONSE_13_002: [** `DeviceMethodResponse` shall throw an `Error` if `requestId` is an empty string. **]** 14 | 15 | **SRS_NODE_DEVICE_METHOD_RESPONSE_13_006: [** `DeviceMethodResponse` shall throw a `ReferenceError` if `transport` is falsy. **]** 16 | 17 | ## send(status, payload, done) 18 | Sends the device method's response back to the service via the underlying transport object using the `status` parameter as the status of the method call. 19 | 20 | **SRS_NODE_DEVICE_METHOD_RESPONSE_13_007: [** `DeviceMethodResponse.send` shall throw a `ReferenceError` if `status` is undefined or not a number. **]** 21 | 22 | **SRS_NODE_DEVICE_METHOD_RESPONSE_13_008: [** `DeviceMethodResponse.send` shall notify the service and supply the response for the request along with the `status` by calling `sendMethodResponse` on the underlying transport object. **]** 23 | 24 | **SRS_NODE_DEVICE_METHOD_RESPONSE_13_009: [** `DeviceMethodResponse.send` shall throw an `Error` object if it is called more than once for the same request. **]** 25 | 26 | **SRS_NODE_DEVICE_METHOD_RESPONSE_13_010: [** `DeviceMethodResponse.send` shall invoke the callback specified by `done` if it is not falsy. **]** 27 | 28 | **SRS_NODE_DEVICE_METHOD_RESPONSE_13_011: [** `DeviceMethodResponse.send` shall pass the status of sending the response to the service to `done`. **]** 29 | -------------------------------------------------------------------------------- /e2etests/test/service.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var serviceSdk = require('azure-iothub'); 7 | var serviceSas = require('azure-iothub').SharedAccessSignature; 8 | var anHourFromNow = require('azure-iot-common').anHourFromNow; 9 | var Amqp = require('azure-iothub').Amqp; 10 | var AmqpWs = require('azure-iothub').AmqpWs; 11 | 12 | var assert = require('chai').assert; 13 | 14 | var runTests = function (hubConnectionString) { 15 | describe('Service Client', function () { 16 | [Amqp, AmqpWs].forEach(function (Transport) { 17 | it('Service client can connect over ' + Transport.name + ' using a shared access signature', function(done) { 18 | this.timeout(60000); 19 | var connStr = serviceSdk.ConnectionString.parse(hubConnectionString); 20 | var sas = serviceSas.create(connStr.HostName, connStr.SharedAccessKeyName, connStr.SharedAccessKey, anHourFromNow()).toString(); 21 | var serviceClient = serviceSdk.Client.fromSharedAccessSignature(sas, Transport); 22 | serviceClient.open(function(err, result) { 23 | if(err) { 24 | done(err); 25 | } else { 26 | assert.equal(result.constructor.name, 'Connected'); 27 | serviceClient.close(function (err) { 28 | done(err); 29 | }); 30 | } 31 | }); 32 | }); 33 | 34 | it('Service client can connect over ' + Transport.name + ' using a connection string', function(done) { 35 | this.timeout(60000); 36 | var serviceClient = serviceSdk.Client.fromConnectionString(hubConnectionString, Transport); 37 | serviceClient.open(function(err, result) { 38 | if(err) { 39 | done(err); 40 | } else { 41 | assert.equal(result.constructor.name, 'Connected'); 42 | serviceClient.close(function (err) { 43 | done(err); 44 | }); 45 | } 46 | }); 47 | }); 48 | }); 49 | }); 50 | }; 51 | 52 | module.exports = runTests; -------------------------------------------------------------------------------- /service/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iothub", 3 | "version": "1.1.15", 4 | "description": "Azure IoT SDK - IoT Hub", 5 | "author": "Microsoft Corporation", 6 | "license": "MIT", 7 | "main": "iothub.js", 8 | "typings": "iothub.d.ts", 9 | "dependencies": { 10 | "azure-iot-amqp-base": "1.1.12", 11 | "azure-iot-common": "1.1.11", 12 | "azure-iot-http-base": "1.1.11", 13 | "debug": "^2.6.3", 14 | "lodash": "^4.15.0", 15 | "uuid": "^2.0.1" 16 | }, 17 | "devDependencies": { 18 | "chai": "^3.5.0", 19 | "sinon": "^1.17.5", 20 | "istanbul": "^0.4.4", 21 | "jshint": "^2.9.2", 22 | "mocha": "^3.0.1", 23 | "typings": "^2.1.1", 24 | "tslint": "^5.1.0", 25 | "typescript": "2.2.2", 26 | "@types/node": "^7.0.5", 27 | "@types/debug": "0.0.29" 28 | }, 29 | "scripts": { 30 | "lint": "tslint --exclude ./samples --type-check --project . -c ../tslint.json", 31 | "typings": "typings install", 32 | "build": "tsc", 33 | "unittest-min": "istanbul cover --report none node_modules/mocha/bin/_mocha -- --reporter dot test/_*_test.js", 34 | "alltest-min": "istanbul cover --report none node_modules/mocha/bin/_mocha -- --reporter dot test/_*_test*.js", 35 | "unittest": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec test/_*_test.js", 36 | "alltest": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec test/_*_test*.js", 37 | "ci": "npm run typings && npm -s run lint && npm -s run build && npm -s run alltest-min && npm -s run check-cover", 38 | "test": "npm run typings && npm -s run lint && npm -s run build && npm -s run unittest", 39 | "check-cover": "istanbul check-coverage --statements 96 --branches 91 --lines 97 --functions 93", 40 | "cover": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec test/_*_test*.js" 41 | }, 42 | "engines": { 43 | "node": ">= 0.10" 44 | }, 45 | "repository": { 46 | "type": "git", 47 | "url": "git+https://github.com/Azure/azure-iot-sdk-node.git" 48 | }, 49 | "bugs": { 50 | "url": "https://github.com/Azure/azure-iot-sdk-node/issues" 51 | }, 52 | "homepage": "https://github.com/Azure/azure-iot-sdk-node#readme" 53 | } -------------------------------------------------------------------------------- /device/transport/http/devdoc/http_errors_requirements.md: -------------------------------------------------------------------------------- 1 | # azure-iot-device-http.translateError Requirements 2 | 3 | ## Overview 4 | `translateError` is a method that translates HTTP errors into Azure IoT Hub errors, effectively abstracting the error that is returned to the SDK user of from the transport layer. 5 | 6 | ## Requirements 7 | 8 | **SRS_NODE_DEVICE_HTTP_ERRORS_16_001: [** Any error object returned by `translateError` shall inherit from the generic `Error` Javascript object and have 3 properties: 9 | - `response` shall contain the `IncomingMessage` object returned by the HTTP layer. 10 | - `reponseBody` shall contain the content of the HTTP response. 11 | - `message` shall contain a human-readable error message **]** 12 | 13 | **SRS_NODE_DEVICE_HTTP_ERRORS_16_002: [** If the HTTP error code is unknown, `translateError` should return a generic Javascript `Error` object. **]** 14 | 15 | **SRS_NODE_DEVICE_HTTP_ERRORS_16_003: [** `translateError` shall return an `ArgumentError` if the HTTP response status code is `400`. **]** 16 | 17 | **SRS_NODE_DEVICE_HTTP_ERRORS_16_004: [** `translateError` shall return an `UnauthorizedError` if the HTTP response status code is `401`. **]** 18 | 19 | **SRS_NODE_DEVICE_HTTP_ERRORS_16_005: [** `translateError` shall return an `IotHubQuotaExceededError` if the HTTP response status code is `403`. **]** 20 | 21 | **SRS_NODE_DEVICE_HTTP_ERRORS_16_006: [** `translateError` shall return an `DeviceNotFoundError` if the HTTP response status code is `404`. **]** 22 | 23 | **SRS_NODE_DEVICE_HTTP_ERRORS_16_007: [** `translateError` shall return an `MessageTooLargeError` if the HTTP response status code is `413`. **]** 24 | 25 | **SRS_NODE_DEVICE_HTTP_ERRORS_16_008: [** `translateError` shall return an `InternalServerError` if the HTTP response status code is `500`. **]** 26 | 27 | **SRS_NODE_DEVICE_HTTP_ERRORS_16_009: [** `translateError` shall return an `ServiceUnavailableError` if the HTTP response status code is `503`. **]** 28 | 29 | **SRS_NODE_DEVICE_HTTP_ERRORS_16_010: [** `translateError` shall accept 3 arguments: 30 | - A custom error message to give context to the user. 31 | - the body of the HTTP response, containing the explanation of why the request failed 32 | - the HTTP response object itself **]** -------------------------------------------------------------------------------- /device/core/devdoc/blob_upload/blob_uploader_requirements.md: -------------------------------------------------------------------------------- 1 | # azure-iot-device.blobUpload.BlobUploader requirements 2 | 3 | # Overview 4 | `BlobUploader` uploads data from a given stream into an Azure block blob. 5 | 6 | # Usage 7 | 8 | ```js 9 | var fs = require('fs'); 10 | 11 | var filePath = './README.md'; 12 | 13 | fs.stat(filePath, function (err, fileStats) { 14 | var fileStream = fs.createReadStream(filePath); 15 | var uploader = new BlobUploader(); 16 | var blobInfo = { 17 | hostName: '', 18 | containerName: '', 19 | blobName: '', 20 | sasToken: '' 21 | }; 22 | uploader.uploadToBlob(blobInfo, fileStream, fileStats.size, function (err) { 23 | if (err) { 24 | console.log('Upload failed: ' + err.message); 25 | } else { 26 | console.log('Upload succeeded'); 27 | } 28 | fileStream.destroy(); 29 | }); 30 | }); 31 | ``` 32 | 33 | # Public API 34 | ## BlobUploader(storageApi) constructor 35 | **SRS_NODE_DEVICE_BLOB_UPLOAD_16_008: [** `BlobUploader` should use the `storageApi` object to upload data if `storageApi` is truthy. **]** 36 | 37 | **SRS_NODE_DEVICE_BLOB_UPLOAD_06_001: [** `BlobUploader` should denote delay loading with null for the storageApi property if `storageApi` is falsy **]** 38 | 39 | **SRS_NODE_DEVICE_BLOB_UPLOAD_06_002: [** `BlobUploader` should delay load azure-storage into the storageAPI property if `storageApi` is falsy **]** 40 | 41 | ## uploadToBlob(blobInfo, stream, streamSize, done) 42 | **SRS_NODE_DEVICE_BLOB_UPLOAD_16_001: [** `uploadToBlob` shall throw a `ReferenceError` if `blobInfo` is falsy. **]** 43 | 44 | **SRS_NODE_DEVICE_BLOB_UPLOAD_16_002: [** `uploadToBlob` shall throw a `ReferenceError` if `stream` is falsy. **]** 45 | 46 | **SRS_NODE_DEVICE_BLOB_UPLOAD_16_003: [** `uploadToBlob` shall throw a `ReferenceError` if `streamSize` is falsy. **]** 47 | 48 | **SRS_NODE_DEVICE_BLOB_UPLOAD_16_004: [** `uploadToBlob` shall throw an `ArgumentError` if `blobInfo` is missing one or more of the following properties: `hostName`, `containerName`, `blobName`, `sasToken`). **]** 49 | 50 | **SRS_NODE_DEVICE_BLOB_UPLOAD_16_005: [** `uploadToBlob` shall call the `done` calback with the result of the storage api call. **]** -------------------------------------------------------------------------------- /device/core/src/device_method/device_method_request.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | import { Client } from '../client'; 6 | 7 | /** 8 | * Represents the data passed in from the service to the device when a device method is called from the cloud. 9 | * An instance of this class is passed to the callback registered via {@link azure-iot-device.Client.onDeviceMethod}. 10 | */ 11 | export class DeviceMethodRequest implements Client.DeviceMethodRequest { 12 | /** 13 | * The request identifier supplied by the service for this device method call. 14 | */ 15 | requestId: string; 16 | /** 17 | * The name of the method to be called. 18 | */ 19 | methodName: string; 20 | /** 21 | * A Node `Buffer` representing the payload of the method call request. 22 | */ 23 | payload: any; 24 | 25 | constructor(requestId: string, methodName: string, body?: any) { 26 | // Codes_SRS_NODE_DEVICE_METHOD_REQUEST_13_002: [ DeviceMethodRequest shall throw an Error if requestId is an empty string. ] 27 | if (typeof(requestId) === 'string' && requestId.length === 0) { 28 | throw new Error('requestId must not be an empty string'); 29 | } 30 | // Codes_SRS_NODE_DEVICE_METHOD_REQUEST_13_001: [ DeviceMethodRequest shall throw a ReferenceError if requestId is falsy or is not a string. ] 31 | if (typeof(requestId) !== 'string') { 32 | throw new ReferenceError('requestId must be a string'); 33 | } 34 | 35 | // Codes_SRS_NODE_DEVICE_METHOD_REQUEST_13_004: [ DeviceMethodRequest shall throw an Error if methodName is an empty string. ] 36 | if (typeof(methodName) === 'string' && methodName.length === 0) { 37 | throw new Error('methodName must not be an empty string'); 38 | } 39 | // Codes_SRS_NODE_DEVICE_METHOD_REQUEST_13_003: [ DeviceMethodRequest shall throw a ReferenceError if methodName is falsy or is not a string. ] 40 | if (typeof(methodName) !== 'string') { 41 | throw new ReferenceError('methodName must be a string'); 42 | } 43 | 44 | this.requestId = requestId; 45 | this.methodName = methodName; 46 | this.payload = JSON.parse(body.toString()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /device/samples/dmpatterns_reboot_device.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 'use strict'; 4 | 5 | var Client = require('azure-iot-device').Client; 6 | var Protocol = require('azure-iot-device-mqtt').Mqtt; 7 | 8 | // receive the IoT Hub device connection string as a command line parameter 9 | if(process.argv.length < 3) { 10 | console.error('Usage: node dmpatterns_getstarted_device.js <>'); 11 | process.exit(1); 12 | } 13 | 14 | var connectionString = process.argv[2]; 15 | var client = Client.fromConnectionString(connectionString, Protocol); 16 | 17 | client.open(function(err) { 18 | if (!err) { 19 | client.onDeviceMethod('reboot', function onReboot(request, response) { 20 | response.send(200, 'Reboot started', function(err) { 21 | if (err) { 22 | console.error('An error occured when sending a method response:\n' + err.toString()); 23 | } else { 24 | console.log('Response to method \'' + request.methodName + '\' sent successfully.'); 25 | } 26 | }); 27 | 28 | // Get device Twin 29 | client.getTwin(function(err, twin) { 30 | if (err) { 31 | console.error('could not get twin'); 32 | } else { 33 | console.log('twin acquired'); 34 | 35 | // Update the reported properties for this device through the 36 | // twin. This enables the back end app to query for all device that 37 | // have completed a reboot based on the lastReboot property. 38 | twin.properties.reported.update({ 39 | iothubDM : { 40 | reboot : { 41 | startedRebootTime : new Date().toISOString(), 42 | } 43 | } 44 | }, function(err) { 45 | if (err) console.error('Error updating twin'); 46 | else console.log('Device reboot twin state reported') 47 | }); 48 | } 49 | }); 50 | 51 | // Add your device's reboot API for physical restart. 52 | console.log('Rebooting!'); 53 | }); 54 | console.log('Client connected to IoT Hub. Waiting for reboot device method.'); 55 | } else { 56 | console.error(err); 57 | } 58 | }); 59 | -------------------------------------------------------------------------------- /device/transport/mqtt/devdoc/mqtt_translate_errors_requirements.md: -------------------------------------------------------------------------------- 1 | # azure-iot-device-mqtt.translateError Requirements 2 | 3 | ## Overview 4 | `translateError` is a method that translates MQTT errors into Azure IoT Hub errors, effectively abstracting the error that is returned to the SDK user of from the transport layer. 5 | 6 | ## Requirements 7 | **SRS_NODE_DEVICE_MQTT_ERRORS_18_001: [** Any error object returned by `translateError` shall inherit from the generic `Error` Javascript object and have 2 properties: 8 | - `message` shall contain a human-readable error message 9 | - `transportError` shall contain the MQTT error object **]** 10 | 11 | **SRS_NODE_DEVICE_MQTT_ERRORS_18_002: [** `translateError` shall return a `NotConnectedError` if the MQTT error message contains the string 'client disconnecting' **]** 12 | 13 | **SRS_NODE_DEVICE_MQTT_ERRORS_18_003: [** `translateError` shall return a `FormatError` if the MQTT error message contains the string 'Invalid topic' **]** 14 | 15 | **SRS_NODE_DEVICE_MQTT_ERRORS_18_004: [** `translateError` shall return a `NotConnectedError` if the MQTT error message contains the string 'No connection to broker' **]** 16 | 17 | **SRS_NODE_DEVICE_MQTT_ERRORS_18_005: [** `translateError` shall return a `NotImplementedError` if the MQTT error message contains the string 'Unacceptable protocol version' **]** 18 | 19 | **SRS_NODE_DEVICE_MQTT_ERRORS_18_006: [** `translateError` shall return a `UnauthorizedError` if the MQTT error message contains the string 'Identifier rejected' **]** 20 | 21 | **SRS_NODE_DEVICE_MQTT_ERRORS_18_007: [** `translateError` shall return a `ServiceUnavailableError` if the MQTT error message contains the string 'Server unavailable' **]** 22 | 23 | **SRS_NODE_DEVICE_MQTT_ERRORS_18_008: [** `translateError` shall return a `UnauthorizedError` if the MQTT error message contains the string 'Bad username or password' **]** 24 | 25 | **SRS_NODE_DEVICE_MQTT_ERRORS_18_009: [** `translateError` shall return a `UnauthorizedError` if the MQTT error message contains the string 'Not authorized' **]** 26 | 27 | **SRS_NODE_DEVICE_MQTT_ERRORS_18_010: [** `translateError` shall return a `InternalServerError` if the MQTT error message contains the string 'unrecognized packet type' **]** 28 | 29 | **SRS_NODE_DEVICE_MQTT_ERRORS_18_011: [** `translateError` shall return an `Error` if none of the other string rules match **]** 30 | -------------------------------------------------------------------------------- /common/core/devdoc/properties_requirements.md: -------------------------------------------------------------------------------- 1 | azure-iot-common.properties Requirements 2 | ======================================== 3 | 4 | Overview 5 | -------- 6 | 7 | Properties is a collection of user defined properties. Values can only be 8 | strings. 9 | 10 | Public Interface 11 | ---------------- 12 | 13 | | **Member** | **Type** | **Description** | 14 | |--------------------------------------|----------------|----------------------------------------------------------------| 15 | | `Properties.add(itemKey, itemValue)` | void | Adds the key-value pair to the collection. | 16 | | `Properties.getItem(index)` | Key/value Pair | Returns the key/value pair corresponding to the given index. | 17 | | `Properties.getValue(key)` | Any | Returns the value corresponding to the given key. | 18 | | `Properties.count` | Number | Returns the number of items in the collection. | 19 | 20 | Requirements 21 | ------------ 22 | 23 | ### Properties.add(itemKey, itemValue) 24 | 25 | **SRS_NODE_IOTHUB_PROPERTIES_07_003: [** The add function shall push the supplied `itemKey` and `itemValue` to the property object map. **]** 26 | 27 | **SRS_NODE_IOTHUB_PROPERTIES_07_004: [** If `itemKey` contains any of the reserved key names then the `add` function will return `false`. **]** 28 | 29 | ### Properties.getItem(index) 30 | 31 | **SRS_NODE_IOTHUB_PROPERTIES_07_001: [** If the supplied index is greater or equal to zero and is less than property map length, then it shall return the property object. **]** 32 | 33 | **SRS_NODE_IOTHUB_PROPERTIES_13_001: [** If the supplied index is less than zero or greater than or equal to the property map length then it shall return `undefined`. **]** 34 | 35 | ### Properties.count() 36 | 37 | **SRS_NODE_IOTHUB_PROPERTIES_07_002: [** `Properties.count()` shall return the number of items in the Properties map. **]** 38 | 39 | ### Properties.getValue(key) 40 | **SRS_NODE_IOTHUB_PROPERTIES_16_001: [** `Properties.getValue` should return `undefined` if no element within the `propertyList` array contains `key`. **]** 41 | 42 | **SRS_NODE_IOTHUB_PROPERTIES_16_002: [** `Properties.getValue` should return the corresponding value of the `value` property of the element with the `key` property passed as argument. **]** 43 | -------------------------------------------------------------------------------- /common/core/test/_errors_test.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var assert = require('chai').assert; 7 | var errors = require('../lib/errors.js'); 8 | 9 | describe('errors', function() { 10 | 11 | [ 12 | errors.ArgumentError, 13 | errors.ArgumentOutOfRangeError, 14 | errors.DeviceMaximumQueueDepthExceededError, 15 | errors.DeviceNotFoundError, 16 | errors.DeviceMessageLockLostError, 17 | errors.FormatError, 18 | errors.InternalServerError, 19 | errors.InvalidOperationError, 20 | errors.PreconditionFailedError, 21 | errors.IotHubQuotaExceededError, 22 | errors.MessageTooLargeError, 23 | errors.NotConnectedError, 24 | errors.NotImplementedError, 25 | errors.ServiceUnavailableError, 26 | errors.UnauthorizedError, 27 | errors.IotHubNotFoundError, 28 | errors.JobNotFoundError, 29 | errors.TooManyDevicesError, 30 | errors.ThrottlingError, 31 | errors.IoTHubSuspendedError, 32 | errors.DeviceAlreadyExistsError, 33 | errors.InvalidEtagError, 34 | errors.TimeoutError, 35 | errors.BadDeviceResponseError, 36 | errors.GatewayTimeoutError, 37 | errors.DeviceTimeoutError 38 | ].forEach(function(ErrorCtor) { 39 | /*Tests_SRS_NODE_COMMON_ERRORS_16_001: All custom error types shall inherit from the standard Javascript error object.*/ 40 | it(ErrorCtor.name + ' inherits from the standard javascript \'Error\' object', function() { 41 | var err = new ErrorCtor('test'); 42 | assert.instanceOf(err, Error); 43 | }); 44 | 45 | /*Tests_SRS_NODE_COMMON_ERRORS_16_002: All custom error types shall contain a valid call stack.*/ 46 | it(ErrorCtor.name + ' contains a valid call stack', function () { 47 | var err = new ErrorCtor('test'); 48 | assert.isOk(err.stack); 49 | }); 50 | 51 | /*Tests_SRS_NODE_COMMON_ERRORS_16_003: All custom error types shall accept a message as an argument of the constructor and shall populate their message property with it.*/ 52 | it(ErrorCtor.name + ' accepts a message as a constructor argument and populates its message property with it', function() { 53 | var errorMessage = 'test error message'; 54 | var err = new ErrorCtor(errorMessage); 55 | assert.equal(err.message, errorMessage); 56 | }); 57 | }); 58 | }); -------------------------------------------------------------------------------- /device/core/devdoc/blob_upload/blob_upload_client_requirements.md: -------------------------------------------------------------------------------- 1 | # azure-iot-device.blobUpload.BlobUploadClient requirements 2 | 3 | # Overview 4 | `BlobUploadClient` is the class that implements data upload to Azure Blob Storage using the IoT Hub APIs. 5 | 6 | # Public API 7 | 8 | ## BlobUploadClient(config, fileUploadApi, blobUploader) [constructor] 9 | Initializes a new instance of the `BlobUploadClient` class. 10 | 11 | **SRS_NODE_DEVICE_BLOB_UPLOAD_CLIENT_16_001: [** `BlobUploadClient` shall throw a `ReferenceError` if `config` is falsy. **]** 12 | 13 | **SRS_NODE_DEVICE_BLOB_UPLOAD_CLIENT_16_002: [** If specified, `BlobUploadClient` shall use the `fileUploadApi` passed as a parameter instead of the default one. **]** 14 | 15 | **SRS_NODE_DEVICE_BLOB_UPLOAD_CLIENT_16_003: [** If specified, `BlobUploadClient` shall use the `blobUploader` passed as a parameter instead of the default one. **]** 16 | 17 | ## updateSharedAccessSignature(sharedAccessSignature) 18 | Updates the current value shared access signature. 19 | 20 | **SRS_NODE_DEVICE_BLOB_UPLOAD_CLIENT_16_011: [** `updateSharedAccessSignature` shall update the value used by the `BlobUploadClient` instance to the value passed as an argument. **]** 21 | 22 | ## uploadToBlob(blobName, stream, streamLength, done) 23 | Uploads the specified stream to the specified blob. 24 | 25 | **SRS_NODE_DEVICE_BLOB_UPLOAD_CLIENT_16_004: [** `uploadToBlob` shall obtain a blob SAS token using the IoT Hub service file upload API endpoint. **]** 26 | 27 | **SRS_NODE_DEVICE_BLOB_UPLOAD_CLIENT_16_005: [** `uploadToBlob` shall call the `done` callback with a `BlobSasError` parameter if retrieving the SAS token fails. **]** 28 | 29 | **SRS_NODE_DEVICE_BLOB_UPLOAD_CLIENT_16_006: [** `uploadToBlob` shall upload the stream to the specified blob using its BlobUploader instance. **]** 30 | 31 | **SRS_NODE_DEVICE_BLOB_UPLOAD_CLIENT_16_008: [** `uploadToBlob` shall notify the result of a blob upload to the IoT Hub service using the file upload API endpoint. **]** 32 | 33 | **SRS_NODE_DEVICE_BLOB_UPLOAD_CLIENT_16_009: [** `uploadToBlob` shall call the `done` callback with a `BlobUploadNotificationError` if notifying the IoT Hub instance of the transfer outcome fails. **]** 34 | 35 | **SRS_NODE_DEVICE_BLOB_UPLOAD_CLIENT_16_010: [** `uploadToBlob` shall call the `done` callback with no arguments if IoT Hub was successfully notified of the blob upload outcome, regardless of the success state of the transfer itself. **]** -------------------------------------------------------------------------------- /device/core/test/_shared_access_signature_test.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var assert = require('chai').assert; 7 | var ArgumentError = require('azure-iot-common').errors.ArgumentError; 8 | var SharedAccessSignature = require('../lib/shared_access_signature.js'); 9 | 10 | var incompleteSignatures = { 11 | sr: 'SharedAccessSignature sig=signature&se=expiry', 12 | sig: 'SharedAccessSignature sr=audience&se=expiry', 13 | se: 'SharedAccessSignature sr=audience&sig=signature' 14 | }; 15 | 16 | describe('SharedAccessSignature', function () { 17 | describe('#create', function () { 18 | /*Tests_SRS_NODE_DEVICE_SAS_05_004: [ shall be the URL-encoded value of deviceId.]*/ 19 | /*Tests_SRS_NODE_DEVICE_SAS_05_003: [The create method shall return the result of calling azure-iot-common.SharedAccessSignature.create with following arguments: 20 | resourceUri - host + '/devices/' + 21 | keyName - null 22 | key - key 23 | expiry - expiry]*/ 24 | it('creates a shared access signature', function () { 25 | var expect = 'SharedAccessSignature sr=host%2Fdevices%2Fdevice&sig=wM3XiP6gD960IxP7J5WHqnxQHEcWC6YaQCtoMT%2BkKHc%3D&se=12345'; 26 | var sas = SharedAccessSignature.create('host', 'device', 'key', 12345); 27 | assert.equal(expect, sas.toString()); 28 | }); 29 | }); 30 | 31 | describe('#parse', function () { 32 | /*Tests_SRS_NODE_DEVICE_SAS_05_001: [The parse method shall return the result of calling azure-iot-common.SharedAccessSignature.parse.]*/ 33 | /*Tests_SRS_NODE_DEVICE_SAS_05_002: [It shall throw ArgumentError if any of 'sr', 'sig', 'se' fields are not found in the source argument.]*/ 34 | ['sr', 'sig', 'se'].forEach(function (key) { 35 | it('throws if shared access signature is missing ' + key, function () { 36 | assert.throws(function () { 37 | SharedAccessSignature.parse(incompleteSignatures[key]); 38 | }, ArgumentError); 39 | }); 40 | }); 41 | 42 | it('does not throw if shared access signature is missing skn', function () { 43 | assert.doesNotThrow(function () { 44 | SharedAccessSignature.parse('SharedAccessSignature sr=audience&sig=signature&skn=keyname&se=expiry'); 45 | }, ArgumentError); 46 | }); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /service/src/shared_access_signature.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | import { SharedAccessSignature } from 'azure-iot-common'; 7 | 8 | /** 9 | * Creates a shared access signature token to authenticate a service connection with an Azure IoT hub. 10 | * 11 | * @param {string} host Hostname of the Azure IoT hub. 12 | * @param {string} policy Name of the policy to use to connect to the Azure IoT hub (typically `ServiceConnect`, `iothubowner` etc. See [Control access to your Azure IoT hub]{@link https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-security}. 13 | * @param {string} key Symmetric key to use to create shared access signature tokens. 14 | * @param {string} expiry Expiry time for the token that will be created. 15 | * 16 | * @throws {ReferenceError} If one of the parameters is falsy. 17 | * 18 | * @returns {SharedAccessSignature} A shared access signature to be used to connect with an Azure IoT hub. 19 | */ 20 | export function create(host: string, policy: string, key: string, expiry: string | number): SharedAccessSignature { 21 | /*Codes_SRS_NODE_IOTHUB_SAS_05_003: [The create method shall return the result of calling azure-iot-common.SharedAccessSignature.create with following arguments: 22 | resourceUri - host 23 | keyName - policy 24 | key - key 25 | expiry - expiry]*/ 26 | return SharedAccessSignature.create(host, policy, key, expiry); 27 | } 28 | 29 | /** 30 | * Parses a string in the format of a Shared Access Signature token and returns a {@link SharedAccessSignature}. 31 | * 32 | * @param source A shared access signature string. 33 | * @returns {SharedAccessSignature} An object containing the different shared access signature properties extracted from the string given as a parameter 34 | * 35 | * @throws {FormatError} If the string cannot be parsed or is missing required parameters. 36 | */ 37 | export function parse(source: string): SharedAccessSignature { 38 | /*Codes_SRS_NODE_IOTHUB_SAS_05_001: [The parse method shall return the result of calling azure-iot-common.SharedAccessSignature.parse.]*/ 39 | /*Codes_SRS_NODE_IOTHUB_SAS_05_002: [It shall throw ArgumentError if any of 'sr', 'sig', 'skn' or 'se' fields are not found in the source argument.]*/ 40 | return SharedAccessSignature.parse(source, ['sr', 'sig', 'skn', 'se']); 41 | } 42 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "member-ordering": [ 4 | true, 5 | { "order": "instance-sandwich" } 6 | ], 7 | "no-var-requires": true, 8 | "typedef": [ 9 | true, 10 | "call-signature", 11 | "parameter", 12 | "property-declaration", 13 | "member-variable-declaration" 14 | ], 15 | "typedef-whitespace": [ 16 | true, 17 | { 18 | "call-signature": "nospace", 19 | "index-signature": "nospace", 20 | "parameter": "nospace", 21 | "property-declaration": "nospace", 22 | "variable-declaration": "nospace" 23 | }, 24 | { 25 | "call-signature": "onespace", 26 | "index-signature": "onespace", 27 | "parameter": "onespace", 28 | "property-declaration": "onespace", 29 | "variable-declaration": "onespace" 30 | } 31 | ], 32 | "no-construct": true, 33 | "no-duplicate-variable": true, 34 | "no-empty": true, 35 | "no-invalid-this": true, 36 | "no-null-keyword": false, 37 | "no-string-literal": true, 38 | "no-switch-case-fall-through": true, 39 | "no-unsafe-finally": true, 40 | "no-unused-expression": true, 41 | "no-unused-variable": true, 42 | "no-use-before-declare": true, 43 | "no-var-keyword": true, 44 | "triple-equals": [true, "allow-null-check", "allow-undefined-check"], 45 | "use-isnan": true, 46 | "eofline": true, 47 | "indent": [true, "spaces"], 48 | "no-trailing-whitespace": true, 49 | "arrow-parens": true, 50 | "class-name": true, 51 | "comment-format": [true, "check-space"], 52 | "interface-name": [true, "never-prefix"], 53 | "jsdoc-format": true, 54 | "new-parens": true, 55 | "one-line": [true, "check-catch", "check-finally", "check-else", "check-open-brace"], 56 | "one-variable-per-declaration": [true, "ignore-for-loop"], 57 | "quotemark": [true, "single"], 58 | "semicolon": [true, "always"], 59 | "variable-name": [true, "check-format", "allow-leading-underscore", "ban-keywords"], 60 | "whitespace": [true, "check-branch", "check-decl", "check-operator", "check-module", "check-seperator", "check-type"] 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /e2etests/test/testUtils.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var deviceSdk = require('azure-iot-device'); 7 | 8 | function createDeviceClient(deviceTransport, provisionedDevice) { 9 | var deviceClient; 10 | if (provisionedDevice.hasOwnProperty('primaryKey')) { 11 | deviceClient = deviceSdk.Client.fromConnectionString(provisionedDevice.connectionString, deviceTransport); 12 | } else if (provisionedDevice.hasOwnProperty('certificate')) { 13 | deviceClient = deviceSdk.Client.fromConnectionString(provisionedDevice.connectionString, deviceTransport); 14 | var options = { 15 | cert: provisionedDevice.certificate, 16 | key: provisionedDevice.clientKey, 17 | }; 18 | deviceClient.setOptions(options); 19 | } else { 20 | deviceClient = deviceSdk.Client.fromSharedAccessSignature(provisionedDevice.connectionString, deviceTransport); 21 | } 22 | return deviceClient; 23 | } 24 | 25 | function closeDeviceServiceClients(deviceClient, serviceClient, done) { 26 | var serviceErr = null; 27 | var deviceErr = null; 28 | serviceClient.close(function (err) { 29 | serviceErr = err || deviceErr; 30 | serviceClient = null; 31 | if (serviceErr || !deviceClient) { 32 | done(serviceErr); 33 | } 34 | }); 35 | deviceClient.close(function (err) { 36 | deviceErr = err || serviceErr; 37 | deviceClient = null; 38 | if (deviceErr || !serviceClient) { 39 | done(deviceErr); 40 | } 41 | }); 42 | } 43 | 44 | function closeDeviceEventHubClients(deviceClient, eventHubClient, done) { 45 | var eventHubErr = null; 46 | var deviceErr = null; 47 | eventHubClient.close().then(function () { 48 | eventHubErr = deviceErr; 49 | eventHubClient = null; 50 | if (!deviceClient) { 51 | done(eventHubErr); 52 | } 53 | }).catch(function (err) { 54 | eventHubErr = err; 55 | eventHubClient = null; 56 | if (!deviceClient) { 57 | done(eventHubErr); 58 | } 59 | }); 60 | deviceClient.close(function (err) { 61 | deviceErr = err || eventHubErr; 62 | deviceClient = null; 63 | if (deviceErr || !eventHubClient) { 64 | done(deviceErr); 65 | } 66 | }); 67 | } 68 | 69 | module.exports = { 70 | createDeviceClient: createDeviceClient, 71 | closeDeviceServiceClients: closeDeviceServiceClients, 72 | closeDeviceEventHubClients: closeDeviceEventHubClients 73 | }; 74 | -------------------------------------------------------------------------------- /device/core/src/shared_access_signature.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | import { SharedAccessSignature, encodeUriComponentStrict } from 'azure-iot-common'; 7 | 8 | /** 9 | * Creates a shared access signature token to authenticate a device connection with an Azure IoT hub. 10 | * 11 | * @param {string} host Hostname of the Azure IoT hub. 12 | * @param {string} deviceId Unique device identifier as it exists in the device registry. 13 | * @param {string} key Symmetric key to use to create shared access signature tokens. 14 | * @param {string} expiry Expiry time for the token that will be created. 15 | * 16 | * @throws {ReferenceError} If one of the parameters is falsy. 17 | * 18 | * @returns {SharedAccessSignature} A shared access signature to be used to connect with an Azure IoT hub. 19 | */ 20 | export function create(host: string, deviceId: string, key: string, expiry: string | number): SharedAccessSignature { 21 | /*Codes_SRS_NODE_DEVICE_SAS_05_004: [ shall be the URL-encoded value of deviceId.]*/ 22 | const uri = encodeUriComponentStrict(host + '/devices/' + deviceId); 23 | /*Codes_SRS_NODE_DEVICE_SAS_05_003: [The create method shall return the result of calling azure-iot-common.SharedAccessSignature.create with following arguments: 24 | resourceUri - host + '%2Fdevices%2F' + 25 | keyName - null 26 | key - key 27 | expiry - expiry]*/ 28 | return SharedAccessSignature.create(uri, null, key, expiry); 29 | } 30 | 31 | /** 32 | * Parses a string in the format of a Shared Access Signature token and returns a {@link SharedAccessSignature}. 33 | * 34 | * @param source A shared access signature string. 35 | * @returns {SharedAccessSignature} An object containing the different shared access signature properties extracted from the string given as a parameter 36 | * 37 | * @throws {FormatError} If the string cannot be parsed or is missing required parameters. 38 | */ 39 | export function parse(source: string): SharedAccessSignature { 40 | /*Codes_SRS_NODE_DEVICE_SAS_05_001: [The parse method shall return the result of calling azure-iot-common.SharedAccessSignature.parse.]*/ 41 | /*Codes_SRS_NODE_DEVICE_SAS_05_002: [It shall throw ArgumentError if any of 'sr', 'sig', 'se' fields are not found in the source argument.]*/ 42 | return SharedAccessSignature.parse(source, ['sr', 'sig', 'se']); 43 | } 44 | -------------------------------------------------------------------------------- /common/core/src/retry_error_filter.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | export interface ErrorFilter { 7 | ArgumentError: boolean; 8 | ArgumentOutOfRangeError: boolean; 9 | DeviceMaximumQueueDepthExceededError: boolean; // ?? 10 | DeviceNotFoundError: boolean; 11 | FormatError: boolean; 12 | UnauthorizedError: boolean; 13 | NotImplementedError: boolean; 14 | NotConnectedError: boolean; 15 | IotHubQuotaExceededError: boolean; 16 | MessageTooLargeError: boolean; 17 | InternalServerError: boolean; 18 | ServiceUnavailableError: boolean; 19 | IotHubNotFoundError: boolean; 20 | IoTHubSuspendedError: boolean; // ?? 21 | JobNotFoundError: boolean; 22 | TooManyDevicesError: boolean; 23 | ThrottlingError: boolean; 24 | DeviceAlreadyExistsError: boolean; 25 | DeviceMessageLockLostError: boolean; 26 | InvalidEtagError: boolean; 27 | InvalidOperationError: boolean; 28 | PreconditionFailedError: boolean; // ?? 29 | TimeoutError: boolean; 30 | BadDeviceResponseError: boolean; 31 | GatewayTimeoutError: boolean; // ?? 32 | DeviceTimeoutError: boolean;// ?? 33 | } 34 | 35 | /* tslint:disable:variable-name */ 36 | export class DefaultErrorFilter implements ErrorFilter { 37 | ArgumentError: boolean = false; 38 | ArgumentOutOfRangeError: boolean = false; 39 | DeviceMaximumQueueDepthExceededError: boolean = false; // ?? 40 | DeviceNotFoundError: boolean = false; 41 | FormatError: boolean = false; 42 | UnauthorizedError: boolean = false; 43 | NotImplementedError: boolean = false; 44 | NotConnectedError: boolean = true; 45 | IotHubQuotaExceededError: boolean = false; 46 | MessageTooLargeError: boolean = false; 47 | InternalServerError: boolean = false; 48 | ServiceUnavailableError: boolean = true; 49 | IotHubNotFoundError: boolean = false; 50 | IoTHubSuspendedError: boolean = false; // ?? 51 | JobNotFoundError: boolean = false; 52 | TooManyDevicesError: boolean = false; 53 | ThrottlingError: boolean = true; 54 | DeviceAlreadyExistsError: boolean = false; 55 | DeviceMessageLockLostError: boolean = false; 56 | InvalidEtagError: boolean = false; 57 | InvalidOperationError: boolean = false; 58 | PreconditionFailedError: boolean = false; // ?? 59 | TimeoutError: boolean = true; 60 | BadDeviceResponseError: boolean = false; 61 | GatewayTimeoutError: boolean = false; // ?? 62 | DeviceTimeoutError: boolean = false;// ?? 63 | } 64 | /* tslint:enable:variable-name */ 65 | -------------------------------------------------------------------------------- /device/transport/amqp/devdoc/amqp_receiver_requirements.md: -------------------------------------------------------------------------------- 1 | # AmqpReceiver Requirements (Device SDK) 2 | 3 | 4 | ## Overview 5 | The `AmqpReceiver` object emits events when messages are received by the device and provides a way to listen to device method calls. 6 | The goal of this object is to maintain a consistent API across AMQP and MQTT transports and isolate AMQP-specific logic from the Device Client. 7 | As such, it hides an underlying `azure-iot-amqp-base.AmqpReceiver` object for messaging, and an `azure-iot-device-amqp.AmqpDeviceMethodClient` object 8 | and redirects calls to its own method to those clients. 9 | 10 | ## Public Interface 11 | ### AmqpReceiver(config, amqpClient, deviceMethodClient) [constructor] 12 | **SRS_NODE_DEVICE_AMQP_RECEIVER_16_001: [** The `AmqpReceiver` constructor shall initialize a new instance of an `AmqpReceiver` object. **]** 13 | 14 | **SRS_NODE_DEVICE_AMQP_RECEIVER_16_002: [** The `AmqpReceiver` object shall inherit from the `EventEmitter` node object. **]** 15 | 16 | ### on('message', messageCallback) 17 | **SRS_NODE_DEVICE_AMQP_RECEIVER_16_003: [** The `AmqpReceiver` shall forward any new listener of the `message` event to the underlying amqp message receiver. **]** 18 | 19 | **SRS_NODE_DEVICE_AMQP_RECEIVER_16_008: [** The `AmqpReceiver` shall remove any listener of its `message` event from the underlying amqp message receiver. **]** 20 | 21 | ### complete(message, callback) [deprecated] 22 | NOTE: This method is deprecated and the `azure-iot-device-amqp.Amqp.complete` method should be used instead. 23 | 24 | **SRS_NODE_DEVICE_AMQP_RECEIVER_16_004: [** The `complete` method shall forward the `message` and `callback` arguments to the underlying message receiver. **]** 25 | 26 | ### reject(message, callback) [deprecated] 27 | NOTE: This method is deprecated and the `azure-iot-device-amqp.Amqp.reject` method should be used instead. 28 | 29 | **SRS_NODE_DEVICE_AMQP_RECEIVER_16_005: [** The `reject` method shall forward the `message` and `callback` arguments to the underlying message receiver. **]** 30 | 31 | ### abandon(message, callback) [deprecated] 32 | NOTE: This method is deprecated and the `azure-iot-device-amqp.Amqp.abandon` method should be used instead. 33 | 34 | **SRS_NODE_DEVICE_AMQP_RECEIVER_16_006: [** The `abandon` method shall forward the `message` and `callback` arguments to the underlying message receiver. **]** 35 | 36 | ### onDeviceMethod(methodName, methodCallback) 37 | **SRS_NODE_DEVICE_AMQP_RECEIVER_16_007: [** The `onDeviceMethod` method shall forward the `methodName` and `methodCallback` arguments to the underlying `AmqpDeviceMethodClient` object. **]** 38 | -------------------------------------------------------------------------------- /device/core/devdoc/connection_string_requirement.md: -------------------------------------------------------------------------------- 1 | #azure-iot-device.ConnectionString Requirements 2 | 3 | ##Overview 4 | `ConnectionString` is a type representing an IoT Hub device connection string. It exposes a static factory method for creating a connection string object from a string, and exposes properties for each of the parsed fields in the string. It also validates the required properties of the connection string. 5 | 6 | ## Example usage 7 | ```js 8 | 'use strict'; 9 | 10 | /* "HostName=;DeviceId=;SharedAccessKey=" */ 11 | /* "HostName=;DeviceId=;SharedAccessSignature=" */ 12 | 13 | var ConnectionString = require('azure-iot-device').ConnectionString; 14 | 15 | var cn = ConnectionString.parse('[Connection string]'); 16 | console.log('HostName=' + cn.HostName); 17 | console.log('DeviceId=' + cn.DeviceId); 18 | console.log('SharedAccessKey=' + cn.SharedAccessKey); 19 | ``` 20 | 21 | ## Public Interface 22 | ### ConnectionString constructor 23 | Creates a new instance of the object. 24 | 25 | ### parse(source) [static] 26 | The `parse` static method returns a new instance of the `ConnectionString` object with properties corresponding to each 'name=value' field found in source. 27 | 28 | **SRS_NODE_DEVICE_CONNSTR_05_001: [** The `parse` method shall return the result of calling `azure-iot-common.ConnectionString.parse`.**]** 29 | 30 | **SRS_NODE_DEVICE_CONNSTR_05_002: [** It shall throw `ArgumentError` if any of `HostName` or `DeviceId` fields are not found in the source argument.**]** 31 | 32 | **SRS_NODE_DEVICE_CONNSTR_16_001: [** It shall throw `ArgumentError` if `SharedAccessKey` and `x509` are present at the same time or if none of them are present. **]** 33 | 34 | ### createWithSharedAccessKey(hostName, deviceId, sharedAccessKey) [static] 35 | 36 | **SRS_NODE_DEVICE_CONNSTR_16_002: [** The `createWithSharedAccessKey` static method shall returns a valid connection string with the values passed as arguments. **]** 37 | 38 | **SRS_NODE_DEVICE_CONNSTR_16_003: [** The `createWithSharedAccessKey` static method shall throw a `ReferenceError` if one or more of the `hostName`, `deviceId` or `sharedAccessKey` are falsy. **]** 39 | 40 | ### createWithX509Certificate(hostName, deviceId) [static] 41 | 42 | **SRS_NODE_DEVICE_CONNSTR_16_004: [** The `createWithX509Certificate` static method shall returns a valid x509 connection string with the values passed as arguments. **]** 43 | 44 | **SRS_NODE_DEVICE_CONNSTR_16_005: [** The `createWithX509Certificate` static method shall throw a `ReferenceError` if one or more of the `hostName` or `deviceId` are falsy. **]** -------------------------------------------------------------------------------- /service/samples/registry_addUpdateRemoveDevicesSample.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var iothub = require('azure-iothub'); 7 | var uuid = require('uuid'); 8 | 9 | var connectionString = '[IoT Connection String]'; 10 | 11 | var registry = iothub.Registry.fromConnectionString(connectionString); 12 | 13 | // Specify the new devices. 14 | var deviceAddArray = [ 15 | { 16 | deviceId: 'Device1', 17 | status: 'disabled', 18 | authentication: { 19 | symmetricKey: { 20 | primaryKey: new Buffer(uuid.v4()).toString('base64'), 21 | secondaryKey: new Buffer(uuid.v4()).toString('base64') 22 | } 23 | } 24 | }, 25 | { 26 | deviceId: 'Device2', 27 | status: 'disabled', 28 | authentication: { 29 | symmetricKey: { 30 | primaryKey: new Buffer(uuid.v4()).toString('base64'), 31 | secondaryKey: new Buffer(uuid.v4()).toString('base64') 32 | } 33 | } 34 | }, 35 | { 36 | deviceId: 'Device3', 37 | status: 'disabled', 38 | authentication: { 39 | symmetricKey: { 40 | primaryKey: new Buffer(uuid.v4()).toString('base64'), 41 | secondaryKey: new Buffer(uuid.v4()).toString('base64') 42 | } 43 | } 44 | } 45 | ]; 46 | 47 | var deviceUpdateArray = [ 48 | { 49 | deviceId: deviceAddArray[0].deviceId, 50 | status: 'enabled' 51 | }, 52 | { 53 | deviceId: deviceAddArray[1].deviceId, 54 | status: 'enabled' 55 | }, 56 | { 57 | deviceId: deviceAddArray[2].deviceId, 58 | status: 'enabled' 59 | } 60 | ]; 61 | 62 | var deviceRemoveArray = [ 63 | { 64 | deviceId: deviceAddArray[0].deviceId 65 | }, 66 | { 67 | deviceId: deviceAddArray[1].deviceId 68 | }, 69 | { 70 | deviceId: deviceAddArray[2].deviceId 71 | } 72 | ]; 73 | 74 | console.log('Adding devices: ' + JSON.stringify(deviceAddArray)); 75 | registry.addDevices(deviceAddArray, printAndContinue( 'adding', function next() { 76 | registry.updateDevices(deviceUpdateArray, true, printAndContinue('updating', function next() { 77 | registry.removeDevices(deviceRemoveArray, true, printAndContinue('removing')); 78 | })); 79 | })); 80 | 81 | 82 | 83 | function printAndContinue(op, next) { 84 | return function printResult(err, resultData) { 85 | if (err) console.log(op + ' error: ' + err.toString()); 86 | if (resultData) { 87 | var arrayString = resultData.errors.length === 0 ? 'no errors' : JSON.stringify(resultData.errors); 88 | console.log(op + ' isSuccessful: ' + resultData.isSuccessful + ', errors returned: ' + arrayString); 89 | } 90 | if (next) next(); 91 | }; 92 | } -------------------------------------------------------------------------------- /common/transport/amqp/devdoc/amqp_common_errors_requirements.md: -------------------------------------------------------------------------------- 1 | # azure-iot-amqp-base.translateError Requirements 2 | 3 | ## Overview 4 | `translateError` is a method that translates AMQP errors into Azure IoT Hub errors, effectively abstracting the error that is returned to the SDK user of from the transport layer. 5 | 6 | ## Requirements 7 | 8 | **SRS_NODE_DEVICE_AMQP_COMMON_ERRORS_16_001: [** Any error object returned by `translateError` shall inherit from the generic `Error` Javascript object and have 2 properties: 9 | - `amqpError` shall contain the error object returned by the AMQP layer. 10 | - `message` shall contain a human-readable error message **]** 11 | 12 | **SRS_NODE_DEVICE_AMQP_COMMON_ERRORS_16_002: [** If the AMQP error code is unknown, `translateError` should return a generic Javascript `Error` object. **]** 13 | 14 | **SRS_NODE_DEVICE_AMQP_COMMON_ERRORS_16_012: [** `translateError` shall return a custom error type according to this table if the AMQP error condition is one of the following: 15 | | AMQP Error Condition | Custom Error Type | 16 | | ------------------------------------------ | ------------------------------------ | 17 | | "amqp:internal-error" | InternalServerError | 18 | | "amqp:link:message-size-exceeded" | MessageTooLargeError | 19 | | "amqp:not-found" | DeviceNotFoundError | 20 | | "amqp:not-implemented" | NotImplementedError | 21 | | "amqp:not-allowed" | InvalidOperationError | 22 | | "amqp:resource-limit-exceeded" | IotHubQuotaExceededError | 23 | | "amqp:unauthorized-access" | UnauthorizedError | 24 | | "com.microsoft:argument-error" | ArgumentError | 25 | | "com.microsoft:argument-out-of-range" | ArgumentOutOfRangeError | 26 | | "com.microsoft:device-already-exists" | DeviceAlreadyExistsError | 27 | | "com.microsoft:device-container-throttled" | IoTHubThrottledError | 28 | | "com.microsoft:iot-hub-suspended" | IoTHubSuspendedError | 29 | | "com.microsoft:message-lock-lost" | DeviceMessageLockLostError | 30 | | "com.microsoft:precondition-failed" | PreconditionFailedError | 31 | | "com.microsoft:quota-exceeded" | IotHubQuotaExceededError | 32 | | "com.microsoft:timeout" | ServiceUnavailableError | 33 | **]** 34 | 35 | **SRS_NODE_DEVICE_AMQP_COMMON_ERRORS_16_010: [** `translateError` shall accept 2 argument: 36 | - A custom error message to give context to the user. 37 | - the AMQP error object itself **]** -------------------------------------------------------------------------------- /device/samples/device_methods.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | require('es5-shim'); 7 | var Protocol = require('azure-iot-device-mqtt').Mqtt; 8 | var Client = require('azure-iot-device').Client; 9 | 10 | var client = null; 11 | 12 | function main() { 13 | // receive the IoT Hub connection string as a command line parameter 14 | if(process.argv.length < 3) { 15 | console.error('Usage: node device_methods.js <>'); 16 | process.exit(1); 17 | } 18 | 19 | // open a connection to the device 20 | var deviceConnectionString = process.argv[2]; 21 | client = Client.fromConnectionString(deviceConnectionString, Protocol); 22 | client.open(onConnect); 23 | } 24 | 25 | function onConnect(err) { 26 | if(!!err) { 27 | console.error('Could not connect: ' + err.message); 28 | } else { 29 | console.log('Connected to device. Registering handlers for methods.'); 30 | 31 | // register handlers for all the method names we are interested in 32 | client.onDeviceMethod('getDeviceLog', onGetDeviceLog); 33 | client.onDeviceMethod('lockDoor', onLockDoor); 34 | } 35 | } 36 | 37 | function onGetDeviceLog(request, response) { 38 | printDeviceMethodRequest(request); 39 | 40 | // Implement actual logic here. 41 | 42 | // complete the response 43 | response.send(200, 'example payload', function(err) { 44 | if(!!err) { 45 | console.error('An error ocurred when sending a method response:\n' + 46 | err.toString()); 47 | } else { 48 | console.log('Response to method \'' + request.methodName + 49 | '\' sent successfully.' ); 50 | } 51 | }); 52 | } 53 | 54 | function onLockDoor(request, response) { 55 | printDeviceMethodRequest(request); 56 | 57 | // Implement actual logic here. 58 | 59 | // complete the response 60 | response.send(200, function(err) { 61 | if(!!err) { 62 | console.error('An error ocurred when sending a method response:\n' + 63 | err.toString()); 64 | } else { 65 | console.log('Response to method \'' + request.methodName + 66 | '\' sent successfully.' ); 67 | } 68 | }); 69 | } 70 | 71 | function printDeviceMethodRequest(request) { 72 | // print method name 73 | console.log('Received method call for method \'' + request.methodName + '\''); 74 | 75 | // if there's a payload just do a default console log on it 76 | if(!!(request.payload)) { 77 | console.log('Payload:\n' + request.payload); 78 | } 79 | } 80 | 81 | // get the app rolling 82 | main(); -------------------------------------------------------------------------------- /device/node-red/README.md: -------------------------------------------------------------------------------- 1 | # Node-Red node for Azure IoT Hub 2 | 3 | This Node-RED node adds Azure IoT connectivity to your Node-RED flow. 4 | 5 | ## Prerequisites 6 | To use the Azure IoT Hub Node-RED node, you need to have the following installed on the target machine: 7 | 8 | - Node.js v0.10 or above. (Check out [Nodejs.org](https://nodejs.org/) for more info) 9 | - Node-RED. To install Node-RED, run the following command: 10 | ``` 11 | npm install -g node-red 12 | ``` 13 | - Azure IoT Hub instance deployed in an Azure subscription with a device ID provisionned. You can learn how to deploy an Azure IoT Hub instance, create a Device ID and retrieve its connection string [here][lnk-setup-iot-hub]. 14 | 15 | ## Install the Node-RED node 16 | To install the node, run the following command from the folder containing the package.json file for the node. 17 | ``` 18 | npm install -g node-red-contrib-azureiothubnode 19 | ``` 20 | 21 | ## First simple flow 22 | To learn how to use the Azure IoT Hub node, here is a simple example: 23 | 1. run Node-RED typing the following command 24 | ``` 25 | node-red 26 | ``` 27 | 1. Open your Web browser and navigate to [http://localhost:1880](http://localhost:1880) 28 | 1. Click on the top right menu and select **Import | Clipboard** 29 | 1. Paste the below in the popup window: 30 | ``` 31 | [{"id":"7b108cb1.4807c8","type":"azureiothub","z":"8d630437.6181a8","name":"Azure IoT Hub","protocol":"amqp","x":379.5,"y":89.22000122070312,"wires":[["b79e7772.b39cc8"]]},{"id":"2269b09.2499b5","type":"inject","z":"8d630437.6181a8","name":"Inject data","topic":"","payload":"Hello from device","payloadType":"str","repeat":"","crontab":"","once":false,"x":209.5,"y":196.01998901367187,"wires":[["7b108cb1.4807c8"]]},{"id":"b79e7772.b39cc8","type":"function","z":"8d630437.6181a8","name":"Convert Bytes to String","func":"msg.payload = msg.payload.toString();\nreturn msg;","outputs":1,"noerr":0,"x":614.5,"y":201.57000732421875,"wires":[["a142535d.158f4"]]},{"id":"a142535d.158f4","type":"debug","z":"8d630437.6181a8","name":"","active":true,"console":"false","complete":"false","x":762.5,"y":320.1499938964844,"wires":[]}] 32 | ``` 33 | 1. Double click on the **Azure IoT Hub** node. 34 | 1. Select the protocol of your choice. 35 | 1. Enter the connection string for the device (see prerequisites for details). 36 | 1. Click OK to validate 37 | 1. Click on the **Deploy** red button in the top left to deploy the flow. Note that if you change the settings (protocol or connection string) you will need to redeploy the flow for the settings to be taken into account. 38 | 1. You can now click on the **Inject Data** node to send messages to Azure IoT Hub 39 | 1. When receiving messages from Azure IoT Hub, they will be displayed in the debug tab. 40 | 41 | [lnk-setup-iot-hub]: https://aka.ms/howtocreateazureiothub 42 | -------------------------------------------------------------------------------- /device/ts-samples/sample_device.ts: -------------------------------------------------------------------------------- 1 | import { Message } from 'azure-iot-common'; 2 | import { Client } from 'azure-iot-device'; 3 | // import { Amqp as Protocol } from 'azure-iot-device-amqp'; 4 | // import { AmqpWs as Protocol } from 'azure-iot-device-amqp'; 5 | import { Mqtt as Protocol } from 'azure-iot-device-mqtt'; 6 | // import { MqttWs as Protocol } from 'azure-iot-device-mqtt'; 7 | // import { Http as Protocol } from 'azure-iot-device-http'; 8 | 9 | const client = Client.fromConnectionString(process.argv[2], Protocol); 10 | 11 | client.open(() => { 12 | // Set up error handler 13 | client.on('error', (err) => { 14 | console.error(err.toString()); 15 | }); 16 | 17 | // Set up disconnect handler 18 | client.on('disconnect', () => { 19 | console.error('Client was disconnected'); 20 | }); 21 | 22 | // Set up C2D message receiver 23 | client.on('message', (msg) => { 24 | console.log('----- Message Received ' + msg.messageId); 25 | console.log('--------- Properties:'); 26 | for (let i = 0; i < msg.properties.count(); 27 | i++) { 28 | const prop = msg.properties.getItem(i); 29 | console.log(prop.key + ': ' + prop.value); 30 | } 31 | console.log('--------- Body:'); 32 | console.log(msg.getData().toString()); 33 | 34 | client.complete(msg, (err) => { 35 | if (err) console.error('Error completing message: ' + err.toString()); 36 | else console.log('Message completed successfully'); 37 | }); 38 | }); 39 | 40 | // Set up Device Method receiver 41 | client.onDeviceMethod('method1', (request, response) => { 42 | console.log('----- Received method call'); 43 | console.log(request.requestId + '(' + request.methodName + ')'); 44 | console.log(JSON.stringify(request.payload, undefined, 2)); 45 | response.send(200, { 46 | responseKey: 'responseValue' 47 | }, (err) => { 48 | if (err) console.error('Error sending method response: ' + err.toString()); 49 | else console.log('Method response sent successfully'); 50 | }); 51 | }); 52 | 53 | // Get the Twin and set up desired properties listener 54 | client.getTwin((err, twin) => { 55 | if (err) { 56 | console.error('Error getting twin: ' + err.toString()); 57 | } else { 58 | twin.on('properties.desired', (props) => { 59 | console.log('----- Desired properties update: '); 60 | console.log(JSON.stringify(props, undefined, 2)); 61 | twin.properties.reported.update({ prop1: 'val1' }, (err) => { 62 | if (err) console.error('Error sending reported properties update: ' + err.toString()); 63 | else console.log('Twin reported properties update sent successfully'); 64 | }); 65 | }); 66 | } 67 | }); 68 | 69 | // Send a sample telemetry event 70 | client.sendEvent(new Message('ready!!'), (err) => { 71 | console.log('Message sent'); 72 | }); 73 | }); 74 | -------------------------------------------------------------------------------- /common/core/test/_connection_string_test.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 'use strict'; 5 | 6 | var assert = require('chai').assert; 7 | var ArgumentError = require('../lib/errors.js').ArgumentError; 8 | var ConnectionString = require('../lib/connection_string.js').ConnectionString; 9 | 10 | describe('ConnectionString', function () { 11 | describe('#constructor', function() { 12 | it('creates a ConnectionString object', function() { 13 | assert.instanceOf(new ConnectionString(), ConnectionString); 14 | }); 15 | }); 16 | 17 | describe('#parse', function () { 18 | /*Tests_SRS_NODE_CONNSTR_05_005: [The parse method shall throw ArgumentError if any of fields in the requiredFields argument are not found in the source argument.]*/ 19 | it('throws if connection string is missing a required field', function () { 20 | assert.throws(function () { 21 | ConnectionString.parse('one=abc;two=123', ['one', 'two', 'three']); 22 | }, ArgumentError, 'The connection string is missing the property: three'); 23 | }); 24 | 25 | /*Tests_SRS_NODE_CONNSTR_05_002: [The parse method shall create a new instance of ConnectionString.]*/ 26 | /*Tests_SRS_NODE_CONNSTR_05_003: [It shall accept a string argument of the form 'name=value[;name=value…]' and for each name extracted it shall create a new property on the ConnectionString object instance.]*/ 27 | /*Tests_SRS_NODE_CONNSTR_05_004: [The value of the property shall be the value extracted from the source argument for the corresponding name.]*/ 28 | /*Tests_SRS_NODE_CONNSTR_05_006: [The generated ConnectionString object shall be returned to the caller.]*/ 29 | /*Tests_SRS_NODE_CONNSTR_05_007: [If requiredFields is falsy, parse shall not validate fields.]*/ 30 | it('returns an object with all the properties of the connection string', function () { 31 | var str = 'HostName=name;DeviceId=id;SharedAccessKey=key;GatewayHostName=name'; 32 | var cn = ConnectionString.parse(str); 33 | assert.deepEqual(cn, { 34 | HostName: 'name', 35 | DeviceId: 'id', 36 | SharedAccessKey: 'key', 37 | GatewayHostName: 'name' 38 | }); 39 | }); 40 | 41 | /*Tests_SRS_NODE_CONNSTR_05_001: [The input argument source shall be converted to string if necessary.]*/ 42 | it('accepts an argument that can be converted to String', function () { 43 | var obj = { 44 | value: 'HostName=name;DeviceId=id;SharedAccessKey=key;GatewayHostName=name', 45 | toString: function () { return this.value; } 46 | }; 47 | var cn = ConnectionString.parse(obj); 48 | assert.deepEqual(cn, { 49 | HostName: 'name', 50 | DeviceId: 'id', 51 | SharedAccessKey: 'key', 52 | GatewayHostName: 'name' 53 | }); 54 | }); 55 | }); 56 | }); --------------------------------------------------------------------------------