├── .devcontainer ├── Dockerfile └── devcontainer.json ├── .eslintignore ├── .eslintrc.js ├── .gitattributes ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug-report.md │ ├── config.yml │ ├── feature-request.md │ └── technical-question.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── codeql.yml │ ├── issuelabeler.yml │ └── synctodevops.yml ├── .gitignore ├── .jshintignore ├── .jshintrc ├── CODE_OF_CONDUCT.md ├── LICENSE ├── SECURITY.md ├── build └── tools │ ├── create_device_certs.js │ ├── delete_device.js │ └── package.json ├── commitlint.config.js ├── common ├── core │ ├── .eslintignore │ ├── .npmignore │ ├── common.d.ts │ ├── common.js │ ├── devdoc │ │ ├── authorization_requirements.docm │ │ ├── connection_string.docm │ │ ├── dictionary_requirements.docm │ │ ├── errors_requirements.md │ │ ├── message_requirements.md │ │ ├── properties_requirements.md │ │ ├── retry_operation_requirements.md │ │ ├── retry_policy_requirements.md │ │ ├── shared_access_signature.md │ │ └── utils_requirement.md │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── authentication_provider.ts │ │ ├── authorization.ts │ │ ├── connection_string.ts │ │ ├── dictionary.ts │ │ ├── endpoint.ts │ │ ├── errors.ts │ │ ├── message.ts │ │ ├── promise_utils.ts │ │ ├── properties.ts │ │ ├── results.ts │ │ ├── retry_error_filter.ts │ │ ├── retry_operation.ts │ │ ├── retry_policy.ts │ │ ├── shared_access_signature.ts │ │ └── utils.ts │ ├── test │ │ ├── _authorization_test.js │ │ ├── _connection_string_test.js │ │ ├── _dictionary_test.js │ │ ├── _endpoint_test.js │ │ ├── _errors_test.js │ │ ├── _message_test.js │ │ ├── _promise_utils_test.js │ │ ├── _properties_test.js │ │ ├── _retry_operation_test.js │ │ ├── _retry_policy_test.js │ │ ├── _shared_access_signature_test.js │ │ └── _utils_test.js │ └── tsconfig.json └── transport │ ├── amqp │ ├── .eslintignore │ ├── .npmignore │ ├── devdoc │ │ ├── amqp_cbs_requirements.md │ │ ├── amqp_common_errors_requirements.md │ │ ├── amqp_message.md │ │ ├── amqp_requirements.md │ │ ├── receiver_link_requirements.md │ │ └── sender_link_requirements.md │ ├── index.d.ts │ ├── index.js │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── amqp.ts │ │ ├── amqp_cbs.ts │ │ ├── amqp_common_errors.ts │ │ ├── amqp_link_interface.ts │ │ ├── amqp_message.ts │ │ ├── receiver_link.ts │ │ └── sender_link.ts │ ├── test │ │ ├── _amqp_cbs_test.js │ │ ├── _amqp_common_errors_test.js │ │ ├── _amqp_link_test.js │ │ ├── _amqp_message_test.js │ │ ├── _amqp_test.js │ │ ├── _receiver_link_test.js │ │ └── _sender_link_test.js │ └── tsconfig.json │ ├── http │ ├── .eslintignore │ ├── .npmignore │ ├── devdoc │ │ ├── http_requirements.md │ │ └── rest_api_client_requirements.md │ ├── index.d.ts │ ├── index.js │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── http.ts │ │ └── rest_api_client.ts │ ├── test │ │ ├── _http_test.js │ │ └── _rest_api_client_test.js │ └── tsconfig.json │ └── mqtt │ ├── .eslintignore │ ├── .npmignore │ ├── devdoc │ ├── mqtt_base_requirements.md │ └── mqtt_translate_errors_requirements.md │ ├── index.d.ts │ ├── index.js │ ├── package.json │ ├── readme.md │ ├── src │ ├── external_event_tracker.ts │ ├── mqtt_base.ts │ └── mqtt_translate_error.ts │ ├── test │ ├── _external_event_tracker_test.js │ ├── _fake_mqtt.js │ ├── _mqtt_base_test.js │ └── _mqtt_translate_error_test.js │ └── tsconfig.json ├── credscan_suppression.json ├── device ├── core │ ├── .eslintignore │ ├── .npmignore │ ├── devdoc │ │ ├── blob_upload │ │ │ ├── blob_upload_client_requirements.md │ │ │ ├── blob_upload_result_requirements.md │ │ │ ├── blob_uploader_requirements.md │ │ │ └── file_upload_endpoint_requirements.md │ │ ├── connection_string_requirement.md │ │ ├── device_client_requirements.md │ │ ├── device_method │ │ │ ├── device_method_request_requirements.md │ │ │ ├── device_method_response_requirements.md │ │ │ └── method_client_requirements.md │ │ ├── device_twin_requirements.md │ │ ├── internal_client_requirements.md │ │ ├── iotedged_authentication_provider_requirement.md │ │ ├── module_client_requirements.md │ │ ├── modules_events_and_messages_design.md │ │ ├── sak_authentication_provider_requirements.md │ │ ├── sas_authentication_provider_requirements.md │ │ ├── shared_access_signature.md │ │ ├── twin_errors_requirements.md │ │ ├── utils_requirement.md │ │ └── x509_authentication_provider_requirements.md │ ├── device.d.ts │ ├── device.js │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── blob_upload │ │ │ ├── blob_upload_client.ts │ │ │ ├── blob_upload_errors.ts │ │ │ ├── blob_upload_result.ts │ │ │ ├── blob_uploader.ts │ │ │ ├── file_upload_api.ts │ │ │ └── index.ts │ │ ├── connection_string.ts │ │ ├── device_client.ts │ │ ├── device_method │ │ │ ├── device_method_exchange.ts │ │ │ ├── device_method_request.ts │ │ │ ├── device_method_response.ts │ │ │ ├── index.ts │ │ │ └── method_client.ts │ │ ├── interfaces.ts │ │ ├── internal_client.ts │ │ ├── iotedge_authentication_provider.ts │ │ ├── module_client.ts │ │ ├── sak_authentication_provider.ts │ │ ├── sas_authentication_provider.ts │ │ ├── shared_access_signature.ts │ │ ├── twin.ts │ │ ├── twin_errors.ts │ │ ├── utils.ts │ │ └── x509_authentication_provider.ts │ ├── test │ │ ├── _client_common_testrun.js │ │ ├── _client_retry_test.js │ │ ├── _connection_string_test.js │ │ ├── _device_client_test.js │ │ ├── _internal_client_test.js │ │ ├── _iotedge_authentication_provider_test.js │ │ ├── _module_client_test.js │ │ ├── _sak_authentication_provider_test.js │ │ ├── _sas_authentication_provider_test.js │ │ ├── _shared_access_signature_test.js │ │ ├── _twin_test.js │ │ ├── _utils_test.js │ │ ├── _x509_authentication_provider_test.js │ │ ├── blob_upload │ │ │ ├── _blob_upload_client_test.js │ │ │ ├── _blob_upload_result_test.js │ │ │ ├── _blob_uploader_test.js │ │ │ ├── _file_upload_api_test.js │ │ │ └── fake_storage_api.js │ │ ├── device_method │ │ │ ├── _device_method_exchange_test.js │ │ │ ├── _device_method_request_test.js │ │ │ ├── _device_method_response_test.js │ │ │ └── _method_client_test.js │ │ ├── fake_transport.js │ │ └── http_simulated.js │ └── tsconfig.json ├── node-red │ ├── LICENSE │ ├── README.md │ ├── azureiothub │ │ ├── azureiothub.html │ │ ├── azureiothub.js │ │ └── icons │ │ │ └── azureiothub.png │ └── package.json ├── readme.md ├── samples │ ├── helpers │ │ ├── Readme.md │ │ └── device-twin-service │ │ │ ├── .eslintignore │ │ │ ├── Readme.md │ │ │ ├── package.json │ │ │ └── twin-service.js │ ├── javascript │ │ ├── .eslintignore │ │ ├── device_methods.js │ │ ├── device_through_proxy.js │ │ ├── dmpatterns_fwupdate_device.js │ │ ├── dmpatterns_reboot_device.js │ │ ├── edge_downstream_device.js │ │ ├── module_invoke_method.js │ │ ├── package.json │ │ ├── pnp_simple_thermostat.js │ │ ├── pnp_temperature_controller.js │ │ ├── readme.md │ │ ├── remote_monitoring.js │ │ ├── send_batch_http.js │ │ ├── simple_sample_device.js │ │ ├── simple_sample_device_twin.js │ │ ├── simple_sample_device_with_sas.js │ │ ├── simple_sample_device_x509.js │ │ ├── simple_sample_module.js │ │ ├── simple_sample_module_method.js │ │ ├── simple_sample_module_twin.js │ │ ├── upload_to_blob.js │ │ └── upload_to_blob_advanced.js │ ├── media │ │ └── github-codespace.png │ ├── readme.md │ └── typescript │ │ ├── .eslintignore │ │ ├── device_methods.ts │ │ ├── dmpatterns_fwupdate_device.ts │ │ ├── dmpatterns_reboot_device.ts │ │ ├── edge_downstream_device.ts │ │ ├── package.json │ │ ├── pnp_simple_thermostat.ts │ │ ├── pnp_temperature_controller.ts │ │ ├── readme.md │ │ ├── remote_monitoring.ts │ │ ├── send_batch_http.ts │ │ ├── simple_sample_device.ts │ │ ├── simple_sample_device_twin.ts │ │ ├── simple_sample_device_with_sas.ts │ │ ├── simple_sample_device_x509.ts │ │ ├── simple_sample_module.ts │ │ ├── tsconfig.json │ │ ├── upload_to_blob.ts │ │ └── upload_to_blob_advanced.ts └── transport │ ├── amqp │ ├── .eslintignore │ ├── .npmignore │ ├── devdoc │ │ ├── amqp_device_errors_requirements.md │ │ ├── amqp_device_method_client_requirements.md │ │ ├── amqp_twin_client_requirements.md │ │ └── device_amqp_requirements.md │ ├── index.d.ts │ ├── index.js │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── amqp.ts │ │ ├── amqp_device_method_client.ts │ │ ├── amqp_twin_client.ts │ │ └── amqp_ws.ts │ ├── test │ │ ├── _amqp_device_errors_test.js │ │ ├── _amqp_device_method_client_test.js │ │ ├── _amqp_receiver_test.js │ │ ├── _amqp_test.js │ │ ├── _amqp_twin_client_test.js │ │ ├── _amqp_ws_test.js │ │ └── _fake_amqp.js │ └── tsconfig.json │ ├── http │ ├── .eslintignore │ ├── .npmignore │ ├── devdoc │ │ ├── http_errors_requirements.md │ │ └── http_requirements.md │ ├── index.d.ts │ ├── index.js │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── http.ts │ │ └── http_errors.ts │ ├── test │ │ ├── _http_errors_test.js │ │ └── _http_test.js │ └── tsconfig.json │ └── mqtt │ ├── .eslintignore │ ├── .npmignore │ ├── devdoc │ ├── mqtt_requirements.md │ └── mqtt_twin_client_requirements.md │ ├── index.d.ts │ ├── index.js │ ├── package.json │ ├── readme.md │ ├── src │ ├── mqtt.ts │ ├── mqtt_twin_client.ts │ └── mqtt_ws.ts │ ├── test │ ├── _mqtt_receiver_test.js │ ├── _mqtt_test.js │ ├── _mqtt_twin_client_test.js │ └── _mqtt_ws_test.js │ └── tsconfig.json ├── doc ├── device-client.md ├── dmpatterns.md ├── images │ ├── Azure IoT Hub.png │ └── docs-link-buttons │ │ ├── azure-documentation.svg │ │ ├── azure-how-to-guide.svg │ │ ├── azure-quickstart.svg │ │ └── azure-tutorial.svg ├── node-debug-vscode.md ├── node-devbox-setup.md └── node-tests.md ├── e2etests ├── .eslintignore ├── package.json └── test │ ├── authentication.js │ ├── c2d_disconnect.js │ ├── configurations.js │ ├── d2c_disconnect.js │ ├── device_acknowledge_tests.js │ ├── device_identity_helper.js │ ├── device_method.js │ ├── device_service.js │ ├── empty_messages.js │ ├── eventhub_receiver_helper.js │ ├── file_upload.js │ ├── job_client.js │ ├── method_disconnect.js │ ├── module_crud.js │ ├── module_messaging.js │ ├── module_methods.js │ ├── module_test_helper.js │ ├── module_twin.js │ ├── registry.js │ ├── rendezvous_helper.js │ ├── sas_token_tests.js │ ├── server_validation.js │ ├── service.js │ ├── testUtils.js │ ├── twin_disconnect.js │ ├── twin_e2e_tests.js │ └── upload_disconnect.js ├── feature_matrix.md ├── lerna.json ├── lts_branches.png ├── mocha-reports.json ├── node_e2e_resources ├── .gitignore ├── README.md ├── credscan_suppresion.json ├── deploy.sh ├── dps.bicep ├── get_env.sh ├── iot-hub.bicep ├── key-vault.bicep ├── storage-account.bicep └── test-resources.bicep ├── package.json ├── provisioning ├── device │ ├── .npmignore │ ├── devdoc │ │ ├── polling_state_machine_requirements.md │ │ ├── provisioning_client_requirements.md │ │ ├── provisioning_error_requirements.md │ │ ├── symmetric_registration_requirements.md │ │ ├── tpm_registration_requirements.md │ │ └── x509_registration_requirements.md │ ├── index.d.ts │ ├── index.js │ ├── package.json │ ├── readme.md │ ├── samples │ │ ├── getParameters.js │ │ ├── package.json │ │ ├── readme.md │ │ ├── register_symkey.js │ │ ├── register_symkeygroup.js │ │ ├── register_tpm.js │ │ └── register_x509.js │ ├── src │ │ ├── client.ts │ │ ├── constants.ts │ │ ├── interfaces.ts │ │ ├── polling_state_machine.ts │ │ ├── provisioning_errors.ts │ │ ├── symmetric_registration.ts │ │ ├── tpm_registration.ts │ │ └── x509_registration.ts │ ├── test │ │ ├── _polling_state_machine_test.js │ │ ├── _provisioning_client_test.js │ │ ├── _provisioning_errors_test.js │ │ ├── _symmetric_key_registration_test.js │ │ ├── _tpm_registration_test.js │ │ └── _x509_registration_test.js │ ├── ts-samples │ │ ├── package.json │ │ ├── src │ │ │ └── register_symkey.ts │ │ └── tsconfig.json │ └── tsconfig.json ├── e2e │ ├── _provisioning_e2e.js │ ├── _server_validation.js │ ├── _service_create_delete.js │ ├── cert_helper.js │ └── package.json ├── service │ ├── .npmignore │ ├── devdoc │ │ └── provisioningserviceclient.md │ ├── iotprovisioningservice.d.ts │ ├── iotprovisioningservice.js │ ├── package.json │ ├── readme.md │ ├── samples │ │ ├── create_delete.js │ │ ├── create_enrollment_group.js │ │ ├── create_individual_symmetric_enrollment.js │ │ ├── create_individual_tpm_enrollment.js │ │ ├── create_individual_x509_enrollment.js │ │ ├── create_tpm_enrollment_with_token_credential.js │ │ ├── package.json │ │ ├── query.js │ │ ├── readme.md │ │ └── run_bulk_operation.js │ ├── src │ │ ├── interfaces.ts │ │ ├── provisioningserviceclient.ts │ │ └── query.ts │ ├── test │ │ └── _provisioningserviceclient_test.js │ └── tsconfig.json ├── tools │ ├── create_test_cert.js │ ├── package.json │ └── readme.md └── transport │ ├── amqp │ ├── .npmignore │ ├── devdoc │ │ ├── amqp_requirements.md │ │ └── sasl_tpm_requirements.md │ ├── index.d.ts │ ├── index.js │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── amqp.ts │ │ ├── amqp_ws.ts │ │ └── sasl_tpm.ts │ ├── test │ │ ├── _amqp_test.js │ │ └── _sasl_tpm_test.js │ └── tsconfig.json │ ├── http │ ├── .npmignore │ ├── devdoc │ │ └── http_requirements.md │ ├── index.d.ts │ ├── index.js │ ├── package.json │ ├── readme.md │ ├── src │ │ └── http.ts │ ├── test │ │ └── _http_test.js │ ├── tsconfig.json │ └── typings.json │ └── mqtt │ ├── .npmignore │ ├── devdoc │ └── mqtt_requirements.md │ ├── index.d.ts │ ├── index.js │ ├── package.json │ ├── readme.md │ ├── src │ ├── mqtt.ts │ └── mqtt_ws.ts │ ├── test │ └── _mqtt_test.js │ └── tsconfig.json ├── readme-modules.md ├── readme.md ├── sdklab ├── longhaultests │ ├── .eslintignore │ ├── package.json │ ├── src │ │ ├── d2c_sender.ts │ │ └── iothub_longhaul.ts │ └── tsconfig.json ├── mean_time_recovery │ ├── .eslintignore │ ├── README.md │ ├── aedes_server.js │ ├── device.js │ ├── orchestrator.js │ ├── orchestrator.png │ └── package.json └── stress_fault │ ├── .eslintignore │ ├── .prettierignore │ ├── .prettierrc │ ├── package.json │ ├── src │ ├── device_identity_helper.ts │ ├── faults.ts │ ├── stress_fault.ts │ └── utils.ts │ └── tsconfig.json ├── security ├── symmetric │ ├── .eslintignore │ ├── .npmignore │ ├── devdoc │ │ └── symmetric_key.md │ ├── index.d.ts │ ├── index.js │ ├── package.json │ ├── readme.md │ ├── src │ │ └── symmetric_key.ts │ ├── test │ │ └── _symmetric_key_test.js │ └── tsconfig.json ├── tpm │ ├── .eslintignore │ ├── .npmignore │ ├── devdoc │ │ ├── tpm.md │ │ └── tpm_authentication_provider.md │ ├── index.d.ts │ ├── index.js │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── tpm.ts │ │ └── tpm_authentication_provider.ts │ ├── test │ │ ├── _tpm_authentication_provider_test.js │ │ └── _tpm_test.js │ └── tsconfig.json └── x509 │ ├── .eslintignore │ ├── .npmignore │ ├── index.d.ts │ ├── index.js │ ├── package.json │ ├── readme.md │ ├── src │ └── x509.ts │ ├── test │ └── _x509_test.js │ └── tsconfig.json ├── stresstests ├── .eslintignore ├── README.md ├── package.json └── test │ ├── config.js │ ├── device_client_helper.js │ ├── event_hub_helper.js │ ├── stress_measurements_recorder.js │ └── test_d2c_stress.js ├── thirdpartynotice.txt ├── tls_protocol_version_and_ciphers.md ├── ts-e2e ├── .eslintignore ├── package.json ├── src │ ├── c2d.tests.ts │ ├── d2c.tests.ts │ ├── device_methods.tests.ts │ ├── device_twin.tests.ts │ ├── file_upload.tests.ts │ ├── job_client.tests.ts │ ├── registry.tests.ts │ └── testUtils.ts └── tsconfig.json ├── tsconfig.json ├── tslint.json ├── versions.json └── vsts ├── e2e-debug-loop.yaml ├── horton-e2e.yaml ├── node-nightly-df.yaml ├── node-nightly-linux.yaml └── node-nightly-windows.yaml /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | # See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.192.0/containers/javascript-node/.devcontainer/base.Dockerfile 2 | 3 | # [Choice] Node.js version: 16, 14, 12 4 | ARG VARIANT="16-buster" 5 | FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT} 6 | 7 | # [Optional] Uncomment this section to install additional OS packages. 8 | # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 9 | # && apt-get -y install --no-install-recommends 10 | 11 | # [Optional] Uncomment if you want to install an additional version of node using nvm 12 | # ARG EXTRA_NODE_VERSION=10 13 | # RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}" 14 | 15 | # [Optional] Uncomment if you want to install more global node modules 16 | # RUN su node -c "npm install -g " 17 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: 2 | // https://github.com/microsoft/vscode-dev-containers/tree/v0.192.0/containers/javascript-node 3 | { 4 | "name": "Node.js", 5 | "build": { 6 | "dockerfile": "Dockerfile", 7 | // Update 'VARIANT' to pick a Node version: 12, 14, 16 8 | "args": { "VARIANT": "16" } 9 | }, 10 | 11 | // Set *default* container specific settings.json values on container create. 12 | "settings": {}, 13 | 14 | // Add the IDs of extensions you want installed when the container is created. 15 | "extensions": [ 16 | "dbaeumer.vscode-eslint" 17 | ], 18 | 19 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 20 | // "forwardPorts": [], 21 | 22 | // Use 'postCreateCommand' to run commands after the container is created. 23 | "postCreateCommand": "npm run codespaceinstall", 24 | 25 | // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. 26 | "remoteUser": "node" 27 | } 28 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | # don't lint tests 8 | # test 9 | # don't lint generated code 10 | pl 11 | # don't use rules on the config file 12 | .eslintrc.js -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Azure IoT support and help options 4 | url: https://aka.ms/IoTHelp 5 | about: The main landing page for all Azure IoT support options. 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/technical-question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Technical Question 3 | about: Ask a technical question related to the SDK 4 | title: "[Technical Question]" 5 | labels: question 6 | assignees: '' 7 | 8 | --- 9 | 10 | ------------------------------- delete below ------------------------------- 11 | 12 | Thank you for asking a technical question! If your question is "why doesn't my code work?", please see [submit a bug report](https://github.com/Azure/azure-iot-sdk-node/issues/new?assignees=&labels=bug&template=bug-report.md&title=) instead. 13 | 14 | We encourage you to submit technical questions related to the SDK on Stack Overflow. We actively monitor all questions tagged wtih "azure-iot-sdk". 15 | 16 | Additionally, if your technical question requires submitting service logs, you can submit an [Azure Support Ticket](https://docs.microsoft.com/en-us/azure/azure-supportability/how-to-create-azure-support-request). 17 | 18 | If you have a question specifically on a Microsoft page you've read, please open an issue on the document itself. This ensures you get the fastest targeted response, and you can do this by scrolling to the bottom of the page to the **Feedback** section. 19 | 20 | For more information on the support options available to you, please see [Azure IoT support and help options](https://aka.ms/IoTHelp). 21 | 22 | ------------------------------- delete above ------------------------------- 23 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Checklist 15 | - [ ] I have read the [contribution guidelines](https://github.com/Azure/azure-iot-sdk-node/blob/main/.github/CONTRIBUTING.md). 16 | - [ ] I added or modified the existing tests to cover the change (we do not allow our test coverage to go down). 17 | - If this is a modification that impacts the behavior of a public API 18 | - [ ] I edited the corresponding document in the `devdoc` folder and added or modified requirements. 19 | 20 | # Reference/Link to the issue solved with this PR (if any) 21 | 22 | # Description of the problem 23 | 24 | 25 | # Description of the solution 26 | 27 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "Code scanning - action" 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: '0 19 * * 0' 8 | 9 | jobs: 10 | CodeQL-Build: 11 | 12 | # CodeQL runs on ubuntu-latest and windows-latest 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: Checkout repository 17 | uses: actions/checkout@v2 18 | with: 19 | # We must fetch at least the immediate parents so that if this is 20 | # a pull request then we can checkout the head. 21 | fetch-depth: 2 22 | 23 | # If this run was triggered by a pull request event, then checkout 24 | # the head of the pull request instead of the merge commit. 25 | - run: git checkout HEAD^2 26 | if: ${{ github.event_name == 'pull_request' }} 27 | 28 | # Initializes the CodeQL tools for scanning. 29 | - name: Initialize CodeQL 30 | uses: github/codeql-action/init@v1 31 | # Override language selection by uncommenting this and choosing your languages 32 | # with: 33 | # languages: go, javascript, csharp, python, cpp, java 34 | 35 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 36 | # If this step fails, then you should remove it and run the build manually (see below) 37 | - name: Autobuild 38 | uses: github/codeql-action/autobuild@v1 39 | 40 | # ℹ️ Command-line programs to run using the OS shell. 41 | # 📚 https://git.io/JvXDl 42 | 43 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 44 | # and modify them (or add more) to build your code if your project 45 | # uses a compiled language 46 | 47 | #- run: | 48 | # make bootstrap 49 | # make release 50 | 51 | - name: Perform CodeQL Analysis 52 | uses: github/codeql-action/analyze@v1 53 | -------------------------------------------------------------------------------- /.github/workflows/issuelabeler.yml: -------------------------------------------------------------------------------- 1 | name: "Set Issue Label" 2 | on: 3 | issues: 4 | types: [opened] 5 | 6 | jobs: 7 | test: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: Naturalclar/issue-action@v1.0.0 11 | with: 12 | keywords: '[""]' 13 | labels: '["IoTSDK"]' 14 | github-token: "${{ secrets.GITHUB_TOKEN }}" 15 | -------------------------------------------------------------------------------- /.github/workflows/synctodevops.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Sync issue to Azure DevOps work item 3 | 4 | "on": 5 | issues: 6 | types: 7 | [opened, reopened, closed, deleted, assigned, labeled, unlabeled] 8 | 9 | jobs: 10 | alert: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: danhellem/github-actions-issue-to-work-item@master 14 | env: 15 | ado_token: "${{ secrets.ADO_PERSONAL_ACCESS_TOKEN }}" 16 | ado_organization: "${{ secrets.ADO_ORGANIZATION }}" 17 | ado_project: "${{ secrets.ADO_PROJECT }}" 18 | ado_area_path: "${{ secrets.ADO_AREA_PATH }}" 19 | ado_wit: "Bug" 20 | ado_new_state: "New" 21 | ado_active_state: "In Progress" 22 | ado_close_state: "Done" 23 | ado_bypassrules: false 24 | log_level: 300 25 | -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | **/coverage -------------------------------------------------------------------------------- /.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 | "esversion": 8 21 | } 22 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /build/tools/delete_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 | 'use strict'; 5 | 6 | var Registry = require('azure-iothub').Registry; 7 | var chalk = require('chalk'); 8 | var argv = require('yargs') 9 | .usage('Usage: $0 --connectionString --deviceId ') 10 | .demand(['connectionString', 'deviceId']) 11 | .describe('connectionString', 'Azure IoT Hub service connection string that shall have device delete permissions') 12 | .describe('deviceId', 'Unique identifier for the device that shall be deleted') 13 | .argv; 14 | 15 | var registry = Registry.fromConnectionString(argv.connectionString); 16 | registry.delete(argv.deviceId, function(err) { 17 | if (err) { 18 | console.log(chalk.red('Failed to delete device ' + argv.deviceId)); 19 | console.log(chalk.red(err.responseBody)); 20 | process.exit(1); 21 | } else { 22 | console.log(chalk.green('Device \'' + argv.deviceId + '\' successfully deleted.')); 23 | process.exit(0); 24 | } 25 | }); 26 | 27 | -------------------------------------------------------------------------------- /build/tools/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iothub-buildtools", 3 | "version": "0.0.1", 4 | "private": true, 5 | "description": "Build tools for the Azure IoT Hub Node.js SDK Build", 6 | "main": "create_certs.js", 7 | "scripts": { 8 | "npmlockrefresh": "npm i --package-lock-only", 9 | "lint": "jshint --show-non-errors . && tslint -c ../../tslint.json \"{lib,.}/*.ts\"" 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 | "azure-iothub": "1.15.1", 23 | "async": "^3.2.3", 24 | "es5-ext": "0.10.53", 25 | "chalk": "^1.1.3", 26 | "pem": "^1.14.2", 27 | "yargs": "^15.3.1" 28 | } 29 | } -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = {extends: ['@commitlint/config-conventional']} 2 | -------------------------------------------------------------------------------- /common/core/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /common/core/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | dist/**/*.map 7 | .nyc_output -------------------------------------------------------------------------------- /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 './dist/message'; 6 | 7 | export * as endpoint from './dist/endpoint'; 8 | export * as errors from './dist/errors'; 9 | export * as results from './dist/results'; 10 | export { ResultWithHttpResponse } from './dist/results'; 11 | export { anHourFromNow, encodeUriComponentStrict } from './dist/authorization'; 12 | export { ConnectionString } from './dist/connection_string'; 13 | export { Message }; 14 | export { SharedAccessSignature } from './dist/shared_access_signature'; 15 | export { RetryOperation } from './dist/retry_operation'; 16 | export { RetryPolicy, NoRetry, ExponentialBackOffWithJitter } from './dist/retry_policy'; 17 | export { AuthenticationProvider, AuthenticationType } from './dist/authentication_provider'; 18 | export { getAgentPlatformString } from './dist/utils'; 19 | export { Callback, ErrorCallback, NoErrorCallback, DoubleValueCallback, TripleValueCallback, HttpResponseCallback, callbackToPromise, doubleValueCallbackToPromise, errorCallbackToPromise, noErrorCallbackToPromise, tripleValueCallbackToPromise, httpCallbackToPromise } from './dist/promise_utils'; 20 | 21 | export interface Receiver extends EventEmitter { 22 | on(type: 'message', func: (msg: Message) => void): this; 23 | on(type: 'errorReceived', func: (err: Error) => void): this; 24 | // eslint-disable-next-line @typescript-eslint/ban-types 25 | on(type: string, func: Function): this; 26 | } 27 | 28 | export { TransportConfig, X509 } from './dist/authorization'; 29 | -------------------------------------------------------------------------------- /common/core/devdoc/authorization_requirements.docm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-iot-sdk-node/b7ad22ad79baa3069cc16014bef337b65a0d0e97/common/core/devdoc/authorization_requirements.docm -------------------------------------------------------------------------------- /common/core/devdoc/connection_string.docm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-iot-sdk-node/b7ad22ad79baa3069cc16014bef337b65a0d0e97/common/core/devdoc/connection_string.docm -------------------------------------------------------------------------------- /common/core/devdoc/dictionary_requirements.docm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-iot-sdk-node/b7ad22ad79baa3069cc16014bef337b65a0d0e97/common/core/devdoc/dictionary_requirements.docm -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /common/core/devdoc/utils_requirement.md: -------------------------------------------------------------------------------- 1 | # azure-iot-common.utils Requirements 2 | 3 | ## Overview 4 | the `utils` module contain various and sundry utilities 5 | 6 | ## Available functions 7 | ``` 8 | export function getAgentPlatformString(callback: (platformString?: string) => void): void; 9 | ``` 10 | 11 | ## getAgentPlatformString 12 | 13 | **SRS_NODE_COMMON_UTILS_18_001: [** `getAgentPlatformString` shall use `process.version` to get the node.js version. **]** 14 | 15 | **SRS_NODE_COMMON_UTILS_18_002: [** `getAgentPlatformString` shall use `os.platform` to distinguish between linux and non-linux operating systems. **]** 16 | 17 | **SRS_NODE_COMMON_UTILS_18_003: [** if `os.platform` returns "linux", `getAgentPlatformString` shall call `getOs` to the OS version. **]** 18 | 19 | **SRS_NODE_COMMON_UTILS_18_004: [** if the `getOs` call fails, the os version shall be 'unknown'. **]** 20 | 21 | **SRS_NODE_COMMON_UTILS_18_005: [** if the `getOs` call succeeds, the os version shall be built by concatenating the `dist` and `release` members of the returned object with a space in between. **]** 22 | 23 | **SRS_NODE_COMMON_UTILS_18_006: [** if `os.platform` returns anything except 'linux', the os version shall be built by concatenating `os.type` and os.release`` with a space in between. **]** 24 | 25 | **SRS_NODE_COMMON_UTILS_18_007: [** `getAgentPlatformString` shall call `os.arch` to get the CPU architecture. **]** 26 | 27 | **SRS_NODE_COMMON_UTILS_18_008: [** `getAgentPlatformString` shall call its `callback` with the string ';;'. **]** 28 | 29 | 30 | -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /common/core/src/authentication_provider.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 { TransportConfig } from './authorization'; 5 | import { Callback } from './promise_utils'; 6 | 7 | /** 8 | * Designate the type of authentication used by an `AuthenticationProvider`. 9 | */ 10 | export enum AuthenticationType { 11 | /** 12 | * X509 Certificate based authentication. 13 | */ 14 | X509, 15 | /** 16 | * Token-based authentication uses shared access signature security tokens, generated and signed with a secret key. 17 | */ 18 | Token 19 | } 20 | 21 | /** 22 | * Interface that must be implemented by objects that are used to provide credentials to the transports used by the device client 23 | * to authenticate with an Azure IoT hub instance. 24 | */ 25 | export interface AuthenticationProvider { 26 | type: AuthenticationType; 27 | getDeviceCredentials(callback: Callback): void; 28 | getDeviceCredentials(): Promise; 29 | setTokenRenewalValues?(tokenValidTimeInSeconds: number, tokenRenewalMarginInSeconds: number): void; 30 | } 31 | -------------------------------------------------------------------------------- /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 | const 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 elements: string[] = String(source).split(String(separator)); 14 | 15 | elements.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/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 = '2021-04-12'; 8 | 9 | export function devicePath(deviceId: string): string { 10 | return '/devices/' + deviceId; 11 | } 12 | 13 | export function deviceEventPath(deviceId: string): string { 14 | return devicePath(deviceId) + '/messages/events'; 15 | } 16 | 17 | export function deviceMessagePath(deviceId: string): string { 18 | return devicePath(deviceId) + '/messages/devicebound'; 19 | } 20 | 21 | export function deviceMethodPath(deviceId: string): string { 22 | return devicePath(deviceId) + '/methods/devicebound'; 23 | } 24 | 25 | export function deviceTwinPath(deviceId: string): string { 26 | return devicePath(deviceId) + '/twin'; 27 | } 28 | 29 | export function deviceFeedbackPath(deviceId: string, lockToken: string): string { 30 | return deviceMessagePath(deviceId) + '/' + lockToken; 31 | } 32 | 33 | export function deviceBlobUploadPath(deviceId: string): string { 34 | return devicePath(deviceId) + '/files'; 35 | } 36 | 37 | export function deviceBlobUploadNotificationPath(deviceId: string, correlationId: string): string { 38 | return devicePath(deviceId) + '/files/notifications/' + encodeURIComponent(correlationId); 39 | } 40 | 41 | export function modulePath(deviceId: string, moduleId: string): string { 42 | return '/devices/' + deviceId + '/modules/' + moduleId; 43 | } 44 | 45 | export function moduleEventPath(deviceId: string, moduleId: string): string { 46 | return modulePath(deviceId, moduleId) + '/messages/events'; 47 | } 48 | 49 | export function moduleMessagePath(deviceId: string, moduleId: string): string { 50 | return modulePath(deviceId, moduleId) + '/messages/events'; 51 | } 52 | 53 | export function moduleMethodPath(deviceId: string, moduleId: string): string { 54 | return modulePath(deviceId, moduleId) + '/methods/devicebound'; 55 | } 56 | 57 | export function moduleTwinPath(deviceId: string, moduleId: string): string { 58 | return modulePath(deviceId, moduleId) + '/twin'; 59 | } 60 | 61 | export function moduleInputMessagePath(deviceId: string, moduleId: string): string { 62 | return modulePath(deviceId, moduleId) + '/inputs'; 63 | } 64 | 65 | export function versionQueryString(): string { 66 | return '?api-version=' + apiVersion; 67 | } 68 | -------------------------------------------------------------------------------- /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 | const assert = require('chai').assert; 7 | const authorization = require('../dist/authorization.js'); 8 | 9 | const key = Buffer.from('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 | const 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 | const hash = authorization.hmacHash(key, 'string-to-sign'); 24 | assert.equal('o1n1hiIVgzVA2+krq9ty1Z4xsIJKJZP3dYT8MOi65Y4=', hash); 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /common/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "./src/**/*.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /common/transport/amqp/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /common/transport/amqp/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | dist/**/*.map 7 | .nyc_output -------------------------------------------------------------------------------- /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, AmqpBaseTransportConfig } from './dist/amqp'; 5 | export { AmqpMessage } from './dist/amqp_message'; 6 | export { ReceiverLink } from './dist/receiver_link'; 7 | export { SenderLink } from './dist/sender_link'; 8 | export { ReceiverLink as AmqpReceiver } from './dist/receiver_link'; 9 | export { AmqpTransportError, translateError, getErrorName } from './dist/amqp_common_errors'; 10 | -------------------------------------------------------------------------------- /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('./dist/amqp.js').Amqp, 15 | AmqpMessage: require('./dist/amqp_message.js').AmqpMessage, 16 | AmqpReceiver: require('./dist/receiver_link.js').ReceiverLink, 17 | ReceiverLink: require('./dist/receiver_link.js').ReceiverLink, 18 | SenderLink: require('./dist/sender_link.js').SenderLink, 19 | translateError: require('./dist/amqp_common_errors.js').translateError, 20 | getErrorName: require('./dist/amqp_common_errors.js').getErrorName 21 | }; 22 | -------------------------------------------------------------------------------- /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/amqp/src/amqp_link_interface.ts: -------------------------------------------------------------------------------- 1 | import { AmqpError } from 'rhea'; 2 | 3 | export interface AmqpLink { 4 | attach: (callback: (err?: Error) => void) => void; 5 | detach: (callback: (err?: Error) => void, err?: Error | AmqpError) => void; 6 | forceDetach: () => void; 7 | } 8 | -------------------------------------------------------------------------------- /common/transport/amqp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "./src/**/*.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /common/transport/http/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | # don't lint tests 8 | -------------------------------------------------------------------------------- /common/transport/http/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | dist/**/*.map 7 | .nyc_output -------------------------------------------------------------------------------- /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, HttpRequestOptions } from './dist/http'; 5 | export { RestApiClient } from './dist/rest_api_client'; 6 | export { HttpTransportError } from './dist/rest_api_client'; 7 | 8 | -------------------------------------------------------------------------------- /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 | * 9 | * @private 10 | * @module azure-iot-http-base 11 | */ 12 | 13 | module.exports = { 14 | Http: require('./dist/http.js').Http, 15 | HttpTransportError: require('./dist/rest_api_client.js').HttpTransportError, 16 | RestApiClient: require('./dist/rest_api_client.js').RestApiClient 17 | }; 18 | -------------------------------------------------------------------------------- /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/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "./src/**/*.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /common/transport/mqtt/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /common/transport/mqtt/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | dist/**/*.map 7 | .nyc_output -------------------------------------------------------------------------------- /common/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 | export { MqttBase, MqttBaseTransportConfig } from './dist/mqtt_base'; 5 | export { translateError } from './dist/mqtt_translate_error'; 6 | -------------------------------------------------------------------------------- /common/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 | /** 7 | * The `azure-iot-mqtt-base` module contains MQTT support code common to the Azure IoT Hub Device and Service SDKs. 8 | * 9 | * @private 10 | * @module azure-iot-mqtt-base 11 | */ 12 | 13 | module.exports = { 14 | MqttBase: require('./dist/mqtt_base.js').MqttBase, 15 | translateError: require('./dist/mqtt_translate_error.js').translateError 16 | }; 17 | -------------------------------------------------------------------------------- /common/transport/mqtt/readme.md: -------------------------------------------------------------------------------- 1 | #azure-iot-mqtt-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-mqtt-base.svg)](https://badge.fury.io/js/azure-iot-mqtt-base) 5 | 6 | NOTE: You generally don't want to reference this package directly. The MQTT components you need should be exposed by packages in the device (`azure-iot-device`) or service (`azure-iothub`) SDKs. -------------------------------------------------------------------------------- /common/transport/mqtt/src/external_event_tracker.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 | 6 | export class ExternalEventTracker { 7 | private _emitter: EventEmitter; 8 | private _listenerContainer: Map void)[]> = new Map(); 9 | constructor(emitter: EventEmitter) { 10 | this._emitter = emitter; 11 | } 12 | 13 | addTrackedListener(eventName: string, listener: (...args: any[]) => void): void { 14 | this._emitter.addListener(eventName, listener); 15 | if (this._listenerContainer.has(eventName)) { 16 | this._listenerContainer.get(eventName).push(listener); 17 | } else { 18 | this._listenerContainer.set(eventName, [listener]); 19 | } 20 | } 21 | 22 | removeTrackedListener(eventName: string, listener: (...args: any[]) => void): void { 23 | const listeners = this._listenerContainer.get(eventName); 24 | const index = listeners?.indexOf(listener); 25 | if (listeners === undefined || index === -1) return; 26 | 27 | if (listeners.length === 1) { 28 | this._listenerContainer.delete(eventName); 29 | } else { 30 | listeners.splice(index, 1); 31 | } 32 | 33 | this._emitter.removeListener(eventName, listener); 34 | } 35 | 36 | removeAllTrackedListeners(eventName?: string): void { 37 | const eventsToRemove = eventName ? [eventName] : this._listenerContainer.keys(); 38 | for (const event of eventsToRemove) { 39 | for (const listener of (this._listenerContainer.get(event) ?? [])) { 40 | this._emitter.removeListener(event, listener); 41 | } 42 | this._listenerContainer.delete(event); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /common/transport/mqtt/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "./src/**/*.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /credscan_suppression.json: -------------------------------------------------------------------------------- 1 | { 2 | "tool": "Credential Scanner", 3 | "suppressions": [ 4 | { 5 | "placeholder": "XLU2ibNOYBbld3FpFIOHbPZv3Thp4wfK%2BcqZpJz66hE%3D", 6 | "_justification": "Fake shared access signature token" 7 | }, 8 | { 9 | "placeholder": "kcWxXAK2OAaAoq2oCkaGzX2NMqDB8nCyNuq2fPYCDhk%3D", 10 | "_justification": "Fake shared access signature token" 11 | }, 12 | { 13 | "placeholder": "wM3XiP6gD960IxP7J5WHqnxQHEcWC6YaQCtoMT%2BkKHc%3D", 14 | "_justification": "Fake shared access signature token" 15 | }, 16 | { 17 | "placeholder": "bYz5R2IFTaejB6pgYOxns2mw6lcuA4VSy8kJbYQp0Sc%3D", 18 | "_justification": "Fake shared access signature token" 19 | }, 20 | { 21 | "placeholder": "88JmrIsVYOGmRSjCO1x1LLbv0K001Gikh1rjfJqbQXA%3D", 22 | "_justification": "Fake shared access signature token" 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /device/core/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /device/core/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | dist/**/*.map 7 | .nyc_output -------------------------------------------------------------------------------- /device/core/devdoc/blob_upload/blob_upload_result_requirements.md: -------------------------------------------------------------------------------- 1 | # azure-iot-device.blobUpload.BlobUploadResult requirements 2 | 3 | # Overview 4 | `BlobUploadResult` describes the result of an upload to a blob, whether it succeeded or failed. 5 | 6 | # Public API 7 | ## BlobUploadResult(isSuccess, statusCode, statusDescription) [constructor] 8 | **SRS_NODE_DEVICE_BLOB_UPLOAD_RESULT_16_001: [** The `isSuccess` parameter shall be assigned to the the `isSuccess` property of the newly created `BlobUploadResult` instance. **]** 9 | 10 | **SRS_NODE_DEVICE_BLOB_UPLOAD_RESULT_16_002: [** The `statusCode` parameter shall be assigned to the the `statusCode` property of the newly created `BlobUploadResult` instance. **]** 11 | 12 | **SRS_NODE_DEVICE_BLOB_UPLOAD_RESULT_16_003: [** The `statusDescription` parameter shall be assigned to the the `statusDescription` property of the newly created `BlobUploadResult` instance. **]** 13 | 14 | ## fromAzureStorageCallbackArgs(err, body, response) [static factory] 15 | **SRS_NODE_DEVICE_BLOB_UPLOAD_RESULT_41_001: [** If `err` is `null` and `uploadResponse` is falsy a `ReferenceError` shall be thrown **]** 16 | 17 | **SRS_NODE_DEVICE_BLOB_UPLOAD_RESULT_41_002: [** If `err` is not `null`, the `BlobUploadResult` shall have the `isSucess` property set to `false` **]** 18 | 19 | **SRS_NODE_DEVICE_BLOB_UPLOAD_RESULT_41_003: [** If `err` is null but `uploadResponse` is provided, and `uploadResponse.ErrorCode` is not null, `BlobUploadResult` shall have the `isSuccess` property set to `false` **]** 20 | 21 | **SRS_NODE_DEVICE_BLOB_UPLOAD_RESULT_41_004: [** If `err` is null but `uploadResponse` is provided, the `BlobUploadResult` shall have the `statusCode` and `statusDescription` property set to the HTTP status code of the blob upload response **]** 22 | 23 | **SRS_NODE_DEVICE_BLOB_UPLOAD_RESULT_41_005: [** If `uploadResponse._response.status` is a number within the HTTP Status Codes 'success' range, the `isSuccess` property will be set to `true` **]** 24 | 25 | **SRS_NODE_DEVICE_BLOB_UPLOAD_RESULT_41_006: [** If `uploadResponse._response.status` is a number not in the HTTP Status Codes 'success' range, the `isSuccess` property will be set to `false` **]** -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /device/core/devdoc/utils_requirement.md: -------------------------------------------------------------------------------- 1 | #azure-iot-device.utils Requirements 2 | 3 | ## Overview 4 | the `utils` module contain various and sundry utilities 5 | 6 | ## Available functions 7 | ``` 8 | export function getUserAgentString(done: (agent: string) => void): void; 9 | ``` 10 | 11 | ## getsUerAgentString 12 | getUserAgentString returns a user agent string that can be sent to the service. 13 | 14 | **SRS_NODE_DEVICE_UTILS_18_001: [** `getUserAgentString` shall call `getAgentPlatformString` to get the platform string. **]** 15 | 16 | **SRS_NODE_DEVICE_UTILS_18_002: [** `getUserAgentString` shall call its `callback` with a string in the form 'azure-iot-device/()'. **]** 17 | 18 | **SRS_NODE_DEVICE_UTILS_41_001: [** `getUserAgentString` shall not add any custom product Info if a `falsy` value is passed in as the first arg. **]** 19 | 20 | **SRS_NODE_DEVICE_UTILS_41_002: [** `getUserAgentString` shall accept productInfo as a `string` so that the callback is called with a string in the form 'azure-iot-device/()'. **]** 21 | 22 | **SRS_NODE_DEVICE_UTILS_41_003: [** `getUserAgentString` shall throw if the first arg is not `falsy`, or of type `string` or `function`. **]** 23 | -------------------------------------------------------------------------------- /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 './dist/device_client'; 5 | export { ModuleClient } from './dist/module_client'; 6 | export * as ConnectionString from './dist/connection_string'; 7 | export * as SharedAccessSignature from './dist/shared_access_signature'; 8 | export { Message } from 'azure-iot-common'; 9 | export { DeviceMethodRequest, DeviceMethodResponse } from './dist/device_method'; 10 | export { X509AuthenticationProvider } from './dist/x509_authentication_provider'; 11 | export { SharedAccessSignatureAuthenticationProvider } from './dist/sas_authentication_provider'; 12 | export { SharedAccessKeyAuthenticationProvider } from './dist/sak_authentication_provider'; 13 | export { EdgedAuthConfig, IotEdgeAuthenticationProvider } from './dist/iotedge_authentication_provider'; 14 | export { Twin, TwinProperties } from './dist/twin'; 15 | export { DeviceClientOptions, HttpReceiverOptions, AmqpTransportOptions, HttpTransportOptions, MqttTransportOptions } from './dist/interfaces'; 16 | export { getUserAgentString } from './dist/utils'; 17 | export { MethodMessage, DeviceTransport } from './dist/internal_client'; 18 | -------------------------------------------------------------------------------- /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/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 { UploadParams } from './blob_uploader'; 8 | export { BlobSasError, BlobUploadNotificationError } from './blob_upload_errors'; 9 | export { BlobUploadResult } from './blob_upload_result'; 10 | export { FileUploadApi as DefaultFileUploadApi, FileUploadInterface } from './file_upload_api'; 11 | -------------------------------------------------------------------------------- /device/core/src/device_method/device_method_exchange.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 { DeviceMethodRequest, DeviceMethodResponse } from '.'; 5 | 6 | export interface DeviceMethodExchange { 7 | request: DeviceMethodRequest; 8 | response: DeviceMethodResponse; 9 | } 10 | 11 | export function createDeviceMethodExchange(request: DeviceMethodRequest, response: DeviceMethodResponse): DeviceMethodExchange { 12 | return { 13 | request: request, 14 | response: response 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /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 | 6 | /** 7 | * Represents the data passed in from the service to the device when a device method is called from the cloud. 8 | * An instance of this class is passed to the callback registered via {@link azure-iot-device.Client.onDeviceMethod}. 9 | */ 10 | export class DeviceMethodRequest { 11 | /** 12 | * The request identifier supplied by the service for this device method call. 13 | */ 14 | requestId: string; 15 | /** 16 | * The name of the method to be called. 17 | */ 18 | methodName: string; 19 | /** 20 | * A Node `Buffer` representing the payload of the method call request. 21 | */ 22 | payload: any; 23 | 24 | constructor(requestId: string, methodName: string, body?: any) { 25 | // Codes_SRS_NODE_DEVICE_METHOD_REQUEST_13_002: [ DeviceMethodRequest shall throw an Error if requestId is an empty string. ] 26 | if (typeof(requestId) === 'string' && requestId.length === 0) { 27 | throw new Error('requestId must not be an empty string'); 28 | } 29 | // Codes_SRS_NODE_DEVICE_METHOD_REQUEST_13_001: [ DeviceMethodRequest shall throw a ReferenceError if requestId is falsy or is not a string. ] 30 | if (typeof(requestId) !== 'string') { 31 | throw new ReferenceError('requestId must be a string'); 32 | } 33 | 34 | // Codes_SRS_NODE_DEVICE_METHOD_REQUEST_13_004: [ DeviceMethodRequest shall throw an Error if methodName is an empty string. ] 35 | if (typeof(methodName) === 'string' && methodName.length === 0) { 36 | throw new Error('methodName must not be an empty string'); 37 | } 38 | // Codes_SRS_NODE_DEVICE_METHOD_REQUEST_13_003: [ DeviceMethodRequest shall throw a ReferenceError if methodName is falsy or is not a string. ] 39 | if (typeof(methodName) !== 'string') { 40 | throw new ReferenceError('methodName must be a string'); 41 | } 42 | 43 | this.requestId = requestId; 44 | this.methodName = methodName; 45 | 46 | if (body) { 47 | this.payload = JSON.parse(body.toString()); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /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 | import { Callback } from 'azure-iot-common'; 7 | 8 | export { DeviceMethodRequest } from './device_method_request'; 9 | export { DeviceMethodResponse } from './device_method_response'; 10 | export { DeviceMethodExchange, createDeviceMethodExchange } from './device_method_exchange'; 11 | export { MethodClient } from './method_client'; 12 | 13 | export interface MethodParams { 14 | methodName: string; 15 | payload: any; 16 | connectTimeoutInSeconds: number; 17 | responseTimeoutInSeconds: number; 18 | } 19 | 20 | export interface MethodResult { 21 | status: number; 22 | payload: any; 23 | } 24 | 25 | export type MethodCallback = Callback; 26 | -------------------------------------------------------------------------------- /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 | class fakeBlockBlobClient { 7 | constructor() {} 8 | 9 | static uploadStream() { 10 | return new Promise((resolve, _reject) => { 11 | resolve('fakeUploadResponse'); 12 | }); 13 | } 14 | } 15 | 16 | class BlockBlobClient { 17 | constructor(_url, _pipeline) { 18 | return fakeBlockBlobClient 19 | } 20 | } 21 | 22 | function newPipeline() { 23 | return function () {}; 24 | } 25 | 26 | function AnonymousCredential() {} 27 | 28 | 29 | module.exports = { 30 | newPipeline: newPipeline, 31 | AnonymousCredential: AnonymousCredential, 32 | BlockBlobClient: BlockBlobClient, 33 | }; 34 | -------------------------------------------------------------------------------- /device/core/test/device_method/_device_method_exchange_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 | let assert = require('chai').assert; 7 | let createDeviceMethodExchange = require('../../dist/device_method').createDeviceMethodExchange; 8 | let DeviceMethodResponse = require('../../dist/device_method').DeviceMethodResponse; 9 | let DeviceMethodRequest = require('../../dist/device_method').DeviceMethodRequest; 10 | 11 | describe("DeviceMethodRequest", function () { 12 | describe("#createDeviceMethodExchange", function () { 13 | it("creates exchange successfully", function () { 14 | const request = new DeviceMethodRequest("requestId", "methodName"); 15 | const response = new DeviceMethodResponse("otherRequestId", {}); 16 | const exchange = createDeviceMethodExchange(request, response); 17 | assert.deepEqual(request, exchange.request); 18 | assert.deepEqual(response, exchange.response); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /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 | let assert = require('chai').assert; 7 | let DeviceMethodRequest = require('../../dist/device_method').DeviceMethodRequest; 8 | 9 | describe('DeviceMethodRequest', function () { 10 | describe('#constructor', function () { 11 | let inputs = [ 12 | { val: undefined, err: ReferenceError }, 13 | { val: null, err: ReferenceError }, 14 | { val: '', err: Error } 15 | ]; 16 | 17 | // Tests_SRS_NODE_DEVICE_METHOD_REQUEST_13_001: [ DeviceMethodRequest shall throw a ReferenceError if requestId is falsy or is not a string. ] 18 | // Tests_SRS_NODE_DEVICE_METHOD_REQUEST_13_002: [ DeviceMethodRequest shall throw an Error if requestId is an empty string. ] 19 | inputs.forEach(function (inp) { 20 | it('throws a ' + inp.err.name + ' if \'requestId\' is \'' + inp.val + '\'', function () { 21 | assert.throws(function () { 22 | return new DeviceMethodRequest(inp.val, 'Reboot'); 23 | }, inp.err); 24 | }); 25 | }); 26 | 27 | // Tests_SRS_NODE_DEVICE_METHOD_REQUEST_13_003: [ DeviceMethodRequest shall throw a ReferenceError if methodName is falsy or is not a string. ] 28 | // Tests_SRS_NODE_DEVICE_METHOD_REQUEST_13_004: [ DeviceMethodRequest shall throw an Error if methodName is an empty string. ] 29 | inputs.forEach(function (inp) { 30 | it('throws a ' + inp.err.name + ' if \'methodName\' is \'' + inp.val + '\'', function () { 31 | assert.throws(function () { 32 | return new DeviceMethodRequest('1', inp.val); 33 | }, inp.err); 34 | }); 35 | }); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /device/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "./src/**/*.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /device/node-red/azureiothub/icons/azureiothub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-iot-sdk-node/b7ad22ad79baa3069cc16014bef337b65a0d0e97/device/node-red/azureiothub/icons/azureiothub.png -------------------------------------------------------------------------------- /device/node-red/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-red-contrib-azureiothubnode", 3 | "version": "0.5.3", 4 | "description": "An Azure IoT Hub node for node-red", 5 | "author": "Microsoft Corp.", 6 | "license": "MIT", 7 | "dependencies": { 8 | "azure-iot-device": "1.18.3", 9 | "azure-iot-device-amqp": "1.14.3", 10 | "azure-iot-device-http": "1.14.3", 11 | "azure-iot-device-mqtt": "1.16.3" 12 | }, 13 | "node-red": { 14 | "nodes": { 15 | "azureiothubnode": "azureiothub/azureiothub.js" 16 | } 17 | }, 18 | "keywords": [ 19 | "node-red" 20 | ] 21 | } -------------------------------------------------------------------------------- /device/readme.md: -------------------------------------------------------------------------------- 1 | # Azure IoT Node.js Device Client Library 2 | 3 | The Azure IoT Node.js Device Client Library is can be used to build applications on devices that interact with Azure IoT Hub. 4 | 5 | ## Features 6 | 7 | * Send event data to Azure IoT Hub. 8 | * Receive messages from IoT Hub. 9 | * Support for multiple communications protocols, including MQTT (optionally over WebSockets), AMQP (optionally over WebSockets), or HTTP. 10 | * Synchronize an Azure IoT Hub device Twin with Azure IoT Hub from a device 11 | * Implement Azure IoT Hub Direct Device Methods on devices 12 | * Implement Azure IoT Device Mangement features on devices 13 | 14 | ## How to use the Azure IoT device SDK for Node.js 15 | 16 | * [Get started in minutes with the azure-iot-device npm package](./core/readme.md) 17 | * [Check out the simple samples provided in this repository](./samples/) 18 | * [Try out the Node-RED node for Azure IoT Hub](./node-red/) 19 | 20 | ## Directory structure 21 | 22 | Device SDK subfolders: 23 | 24 | ### /core 25 | 26 | Device SDK Client package. This is used in conjunction with a protocol implementation package coming from one of the `transport` folder. 27 | 28 | ### /transport 29 | 30 | Protocol-specific SDK packages for: AMQP, AMQP over WebSockets, MQTT, MQTT over WebSockets and HTTP. 31 | 32 | ### /samples 33 | 34 | Sample applications exercising basic features. 35 | 36 | ### /node-red 37 | 38 | Sample Node-RED module for Azure IoT Hub. 39 | 40 | *This is meant to serve only basic scenarios for testing and is not recommended as a production-ready node-red module.* 41 | -------------------------------------------------------------------------------- /device/samples/helpers/Readme.md: -------------------------------------------------------------------------------- 1 | # Helpers 2 | 3 | ## Device Twin Service 4 | 5 | This project is used to mimic a real world scenario of a backend service sending device twin desired properties update to a device. It works along side the `simple_sample_device_twin` samples. 6 | 7 | [Learn more](./device-twin-service/Readme.md) -------------------------------------------------------------------------------- /device/samples/helpers/device-twin-service/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /device/samples/helpers/device-twin-service/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-helpers-device-twin-service", 3 | "version": "1.0.0", 4 | "description": "Helper project that acts as a backend service to update device twin desired properties on a specific device.", 5 | "main": "twin-service.js", 6 | "scripts": { 7 | "lint": "eslint twin-service.js --ext .js -f visualstudio", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "danhellem", 12 | "license": "ISC", 13 | "dependencies": { 14 | "async": "^3.2.3", 15 | "azure-iothub": "^1.16.1" 16 | }, 17 | "devDependencies": { 18 | "encoding": "^0.1.13", 19 | "eslint": "^8.26.0", 20 | "@typescript-eslint/eslint-plugin": "^5.41.0", 21 | "@typescript-eslint/eslint-plugin-tslint": "^5.41.0", 22 | "@typescript-eslint/parser": "^5.41.0", 23 | "eslint-plugin-jsdoc": "^39.3.25", 24 | "eslint-plugin-mocha": "^10.1.0", 25 | "eslint-plugin-no-null": "^1.0.2", 26 | "eslint-plugin-no-only-tests": "^3.1.0", 27 | "eslint-plugin-promise": "^6.1.1", 28 | "eslint-plugin-security": "^1.5.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /device/samples/javascript/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /device/samples/javascript/module_invoke_method.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Choose a protocol by uncommenting one of these transports. 4 | const Protocol = require('azure-iot-device-mqtt').Mqtt; 5 | // const Protocol = require('azure-iot-device-amqp').Amqp; 6 | // const Protocol = require('azure-iot-device-http').Http; 7 | // const Protocol = require('azure-iot-device-mqtt').MqttWs; 8 | // const Protocol = require('azure-iot-device-amqp').AmqpWs; 9 | 10 | const ModuleClient = require('azure-iot-device').ModuleClient; 11 | 12 | ModuleClient.fromEnvironment(Protocol, (err, client) => { 13 | if (err) { 14 | console.error(err.toString()); 15 | process.exit(-1); 16 | } else { 17 | client.invokeMethod('pierreca-edge-test', 'methodTarget', { 18 | methodName: 'doSomethingInteresting', 19 | payload: 'foo', 20 | responseTimeoutInSeconds: 5, 21 | connectTimeoutInSeconds: 2 22 | }, (err, resp) => { 23 | if (err) { 24 | console.error(err.toString()); 25 | process.exit(-1); 26 | } else { 27 | console.log(JSON.stringify(resp, null, 2)); 28 | process.exit(0); 29 | } 30 | }); 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /device/samples/javascript/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 | "async": "^3.2.3", 10 | "azure-iot-device": "1.18.3", 11 | "azure-iot-device-amqp": "1.14.3", 12 | "azure-iot-device-http": "1.14.3", 13 | "azure-iot-device-mqtt": "1.16.3", 14 | "azure-iot-provisioning-device": "1.9.1", 15 | "azure-iot-provisioning-device-mqtt": "1.8.1", 16 | "azure-iot-security-symmetric-key": "1.8.2", 17 | "https-proxy-agent": "^5.0.0", 18 | "lodash": "^4.17.21" 19 | }, 20 | "devDependencies": { 21 | "eslint": "^8.26.0", 22 | "@typescript-eslint/eslint-plugin": "^5.41.0", 23 | "@typescript-eslint/eslint-plugin-tslint": "^5.41.0", 24 | "@typescript-eslint/parser": "^5.41.0", 25 | "eslint-plugin-jsdoc": "^39.3.25", 26 | "eslint-plugin-mocha": "^10.1.0", 27 | "eslint-plugin-no-null": "^1.0.2", 28 | "eslint-plugin-no-only-tests": "^3.1.0", 29 | "eslint-plugin-promise": "^6.1.1", 30 | "eslint-plugin-security": "^1.5.0" 31 | }, 32 | "scripts": { 33 | "lint": "eslint ./ --ext .js -f visualstudio", 34 | "ci": "npm run lint" 35 | } 36 | } -------------------------------------------------------------------------------- /device/samples/javascript/readme.md: -------------------------------------------------------------------------------- 1 | # Javascript Samples for the Azure IoT device SDK for Node.js 2 | 3 | This folder contains simple samples showing how to use the various features of the Microsoft Azure IoT Hub service from a device written using JavaScript. 4 | 5 | For instructions on running the JavaScript samples, see the [readme.md](../../samples) in the root samples folder. 6 | -------------------------------------------------------------------------------- /device/samples/javascript/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 | const clientFromConnectionString = require('azure-iot-device-http').clientFromConnectionString; 7 | const Message = require('azure-iot-device').Message; 8 | 9 | // String containing Hostname, Device Id & Device Key in the following formats: 10 | // "HostName=;DeviceId=;SharedAccessKey=" 11 | const deviceConnectionString = process.env.IOTHUB_DEVICE_CONNECTION_STRING; 12 | const client = clientFromConnectionString(deviceConnectionString); 13 | 14 | // Create two messages and send them to the IoT hub as a batch. 15 | const data = [ 16 | { id: 1, message: 'hello' }, 17 | { id: 2, message: 'world' } 18 | ]; 19 | 20 | let 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 | } 35 | -------------------------------------------------------------------------------- /device/samples/javascript/simple_sample_module_method.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable security/detect-non-literal-fs-filename */ 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 | 'use strict'; 6 | 7 | // Choose a protocol by uncommenting one of these transports. 8 | const Protocol = require('azure-iot-device-mqtt').Mqtt; 9 | // const Protocol = require('azure-iot-device-amqp').Amqp; 10 | // const Protocol = require('azure-iot-device-http').Http; 11 | // const Protocol = require('azure-iot-device-mqtt').MqttWs; 12 | // const Protocol = require('azure-iot-device-amqp').AmqpWs; 13 | 14 | const ModuleClient = require('azure-iot-device').ModuleClient; 15 | 16 | ModuleClient.fromEnvironment(Protocol, function (err, client) { 17 | if (err) { 18 | console.error("Could not create client: " + err.toString()); 19 | process.exit(-1); 20 | } else { 21 | console.log('got client'); 22 | 23 | client.on('error', function (err) { 24 | console.error(err.message); 25 | }); 26 | 27 | // connect to the edge instance 28 | client.open(function (err) { 29 | if (err) { 30 | console.error('Could not connect: ' + err.message); 31 | } else { 32 | console.log('Client connected'); 33 | 34 | client.onMethod('doSomethingInteresting', function (request, response) { 35 | console.log('doSomethingInteresting called'); 36 | 37 | if(request.payload) { 38 | console.log('Payload:'); 39 | console.dir(request.payload); 40 | } 41 | 42 | const responseBody = { 43 | message: 'doSomethingInteresting succeeded' 44 | }; 45 | response.send(200, responseBody, function (err) { 46 | if (err) { 47 | console.log('failed sending method response: ' + err); 48 | } else { 49 | console.log('successfully sent method response'); 50 | } 51 | }); 52 | 53 | }); 54 | } 55 | }); 56 | } 57 | }); 58 | -------------------------------------------------------------------------------- /device/samples/javascript/upload_to_blob.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable security/detect-non-literal-fs-filename */ 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 | // THIS EXAMPLE IS DEPRECATED 6 | // We recommend you follow the 'upload_to_blob_advanced.js' sample. 7 | 8 | 'use strict'; 9 | 10 | const Protocol = require('azure-iot-device-mqtt').Mqtt; 11 | const Client = require('azure-iot-device').Client; 12 | const fs = require('fs'); 13 | 14 | const deviceConnectionString = process.env.IOTHUB_DEVICE_CONNECTION_STRING; 15 | const filePath = process.env.PATH_TO_FILE; 16 | 17 | const client = Client.fromConnectionString(deviceConnectionString, Protocol); 18 | fs.stat(filePath, function (err, fileStats) { 19 | const fileStream = fs.createReadStream(filePath); 20 | 21 | client.uploadToBlob('testblob.txt', fileStream, fileStats.size, function (err) { 22 | if (err) { 23 | console.error('error uploading file: ' + err.constructor.name + ': ' + err.message); 24 | } else { 25 | console.log('Upload successful'); 26 | } 27 | fileStream.destroy(); 28 | process.exit(); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /device/samples/media/github-codespace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-iot-sdk-node/b7ad22ad79baa3069cc16014bef337b65a0d0e97/device/samples/media/github-codespace.png -------------------------------------------------------------------------------- /device/samples/typescript/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /device/samples/typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "device-samples-typescript", 3 | "version": "0.0.1", 4 | "private": true, 5 | "main": "simple_sample_device.ts", 6 | "author": "Microsoft Corp.", 7 | "license": "MIT", 8 | "dependencies": { 9 | "async": "^3.2.3", 10 | "es5-ext": "0.10.53", 11 | "@azure/storage-blob": "^12.8.0", 12 | "azure-iot-common": "1.13.2", 13 | "azure-iot-device": "1.18.3", 14 | "azure-iot-device-amqp": "1.14.3", 15 | "azure-iot-device-http": "1.14.3", 16 | "azure-iot-device-mqtt": "1.16.3", 17 | "azure-iot-provisioning-device": "1.9.1", 18 | "azure-iot-provisioning-device-mqtt": "1.8.1", 19 | "azure-iot-security-symmetric-key": "1.8.2", 20 | "https-proxy-agent": "^5.0.0" 21 | }, 22 | "devDependencies": { 23 | "@types/async": "^3.2.8", 24 | "@types/node": "^16.10.2", 25 | "@types/ws": "^7.4.7", 26 | "encoding": "^0.1.13", 27 | "source-map-support": "^0.5.16", 28 | "eslint": "^8.26.0", 29 | "@typescript-eslint/eslint-plugin": "^5.41.0", 30 | "@typescript-eslint/eslint-plugin-tslint": "^5.41.0", 31 | "@typescript-eslint/parser": "^5.41.0", 32 | "eslint-plugin-jsdoc": "^39.3.25", 33 | "eslint-plugin-mocha": "^10.1.0", 34 | "eslint-plugin-no-null": "^1.0.2", 35 | "eslint-plugin-no-only-tests": "^3.1.0", 36 | "eslint-plugin-promise": "^6.1.1", 37 | "eslint-plugin-security": "^1.5.0", 38 | "typescript": "4.4.4" 39 | }, 40 | "scripts": { 41 | "prebuild": "npm run lint", 42 | "build": "tsc -p .", 43 | "lint": "eslint ./ --ext .ts -f visualstudio", 44 | "ci": "npm -s run lint && npm -s run build", 45 | "clean": "tsc --build --clean" 46 | } 47 | } -------------------------------------------------------------------------------- /device/samples/typescript/readme.md: -------------------------------------------------------------------------------- 1 | # Typscript Samples for the Azure IoT device SDK for Node.js 2 | 3 | This folder contains simple samples showing how to use the various features of the Microsoft Azure IoT Hub service from a device written using TypeScript. 4 | 5 | For instructions on running the TypeScript samples, see the [readme.md](../../samples) in the root samples folder. -------------------------------------------------------------------------------- /device/samples/typescript/send_batch_http.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 { clientFromConnectionString } from 'azure-iot-device-http'; 5 | import { Client, Message } from 'azure-iot-device'; 6 | 7 | // String containing Hostname, Device Id & Device Key in the following formats: 8 | // "HostName=;DeviceId=;SharedAccessKey=" 9 | const deviceConnectionString: string = process.env.IOTHUB_DEVICE_CONNECTION_STRING || ''; 10 | 11 | if (deviceConnectionString === '') { 12 | console.log('device connection string not set'); 13 | process.exit(-1); 14 | } 15 | 16 | const client: Client = clientFromConnectionString(deviceConnectionString); 17 | 18 | // Create two messages and send them to the IoT hub as a batch. 19 | const data: { id: number; message: string }[] = [ 20 | { id: 1, message: 'hello' }, 21 | { id: 2, message: 'world' }, 22 | ]; 23 | 24 | const messages: any[] = []; 25 | 26 | data.forEach(function (value: { id: number; message: string }): void { 27 | messages.push(new Message(JSON.stringify(value))); 28 | }); 29 | 30 | console.log('sending ' + messages.length + ' events in a batch'); 31 | 32 | client.sendEventBatch(messages, printResultFor('send')); 33 | 34 | function printResultFor(op: any): (err: any, res: any) => void { 35 | return function printResult(err: any, res: any): void { 36 | // console.log(res); 37 | if (err) console.log(op + ' error: ' + err.toString()); 38 | if (res) console.log(op + ' status: ' + res.transportObj.statusCode + ' ' + res.transportObj.statusMessage); 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /device/samples/typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "./*.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /device/samples/typescript/upload_to_blob.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable security/detect-non-literal-fs-filename */ 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 | // THIS EXAMPLE IS DEPRECATED 6 | // We recommend you follow the 'upload_to_blob_advanced.ts' sample. 7 | 8 | import { Client } from 'azure-iot-device'; 9 | import { Mqtt as Protocol } from 'azure-iot-device-mqtt'; 10 | import * as fs from 'fs'; 11 | 12 | const deviceConnectionString: string = process.env.IOTHUB_DEVICE_CONNECTION_STRING || ''; 13 | const filePath: string = process.env.PATH_TO_FILE || ''; 14 | 15 | // check for connection string 16 | if (deviceConnectionString === '') { 17 | console.log('device connection string not set'); 18 | process.exit(-1); 19 | } 20 | 21 | // check for file path 22 | if (filePath === '') { 23 | console.log('file path is not set'); 24 | process.exit(-1); 25 | } 26 | 27 | const client: Client = Client.fromConnectionString( 28 | deviceConnectionString, 29 | Protocol 30 | ); 31 | 32 | fs.stat(filePath, function (err: any | null, fileStats: fs.Stats): void { 33 | const fileStream = fs.createReadStream(filePath); 34 | 35 | if (err) { 36 | console.error('error with fs.stat: ' + err.message); 37 | } 38 | 39 | client.uploadToBlob('testblob.txt', fileStream, fileStats.size).catch((err: Error) => { 40 | console.log('error uploading file: ' + err.message); 41 | }).finally(() => { 42 | fileStream.destroy(); 43 | process.exit(); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /device/transport/amqp/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /device/transport/amqp/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | dist/**/*.map 7 | .nyc_output -------------------------------------------------------------------------------- /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/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 './dist/amqp'; 7 | export { AmqpWs } from './dist/amqp_ws'; 8 | export declare function clientFromConnectionString(connectionString: string): Client; 9 | -------------------------------------------------------------------------------- /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 | const device = require('azure-iot-device'); 7 | const Amqp = require('./dist/amqp.js').Amqp; 8 | const AmqpWs = require('./dist/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 | }; 25 | -------------------------------------------------------------------------------- /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/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 { AuthenticationProvider, TransportConfig } from 'azure-iot-common'; 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 { 16 | /** 17 | * @private 18 | * @constructor 19 | * @param {Object} config Configuration object generated from the connection string by the client. 20 | */ 21 | constructor(authenticationProvider: AuthenticationProvider) { 22 | super(authenticationProvider); 23 | } 24 | 25 | protected _getConnectionUri(credentials: TransportConfig): string { 26 | return 'wss://' + (credentials.gatewayHostName || credentials.host) + ':443/$iothub/websocket'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /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 | const assert = require('chai').assert; 7 | const errors = require('azure-iot-common').errors; 8 | const 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 | const AMQPError = function AMQPError() { 17 | Error.call(this); 18 | }; 19 | 20 | const 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 | const 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 | }); 39 | -------------------------------------------------------------------------------- /device/transport/amqp/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 | 6 | const Amqp = require('../dist/amqp.js').Amqp; 7 | const AmqpWs = require('../dist/amqp_ws.js').AmqpWs; 8 | const EventEmitter = require('events').EventEmitter; 9 | const assert = require('chai').assert; 10 | 11 | describe('AmqpWs', function () { 12 | describe('#constructor', function () { 13 | it ('extends AMQP', function () { 14 | const amqpWs = new AmqpWs(new EventEmitter()); 15 | assert.instanceOf(amqpWs, AmqpWs); 16 | assert.instanceOf(amqpWs, Amqp); 17 | }); 18 | }); 19 | 20 | describe('_getConnectionUri', function () { 21 | it('generates a websocket URI for the hub', function () { 22 | const amqpWs = new AmqpWs(new EventEmitter()); 23 | const testConfig = { 24 | host: 'host.name', 25 | }; 26 | 27 | assert.strictEqual(amqpWs._getConnectionUri(testConfig), 'wss://host.name:443/$iothub/websocket'); 28 | }); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /device/transport/amqp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "./src/**/*.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /device/transport/http/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /device/transport/http/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | dist/**/*.map 7 | .nyc_output -------------------------------------------------------------------------------- /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/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 * as Http from './dist/http'; 6 | 7 | export declare function clientFromConnectionString(connectionString: string): Client; 8 | -------------------------------------------------------------------------------- /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 | const device = require('azure-iot-device'); 7 | const Http = require('./dist/http').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 | }; 22 | -------------------------------------------------------------------------------- /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 | ``` -------------------------------------------------------------------------------- /device/transport/http/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "./src/**/*.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /device/transport/mqtt/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /device/transport/mqtt/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | dist/**/*.map 7 | .nyc_output -------------------------------------------------------------------------------- /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 './dist/mqtt'; 7 | export { MqttWs } from './dist/mqtt_ws'; 8 | export declare function clientFromConnectionString(connectionString: string): Client; 9 | -------------------------------------------------------------------------------- /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 | const device = require('azure-iot-device'); 7 | const Mqtt = require('./dist/mqtt.js').Mqtt; 8 | const MqttWs = require('./dist/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 | }; 24 | -------------------------------------------------------------------------------- /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/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 { Mqtt } from './mqtt'; 7 | import { MqttBaseTransportConfig } from 'azure-iot-mqtt-base'; 8 | import { AuthenticationProvider, TransportConfig } from 'azure-iot-common'; 9 | 10 | /** 11 | * Provides MQTT over WebSockets transport for the device [client]{@link module:azure-iot-device.Client} class. 12 | * 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. 13 | */ 14 | /*Codes_SRS_NODE_DEVICE_MQTT_12_001: [The constructor shall accept the transport configuration structure.]*/ 15 | /*Codes_SRS_NODE_DEVICE_MQTT_12_002: [The constructor shall store the configuration structure in a member variable.]*/ 16 | /*Codes_SRS_NODE_DEVICE_MQTT_12_003: [The constructor shall create an base transport object and store it in a member variable.]*/ 17 | export class MqttWs extends Mqtt { 18 | /** 19 | * @private 20 | * @constructor 21 | * @param {Object} config Configuration object derived from the connection string by the client. 22 | */ 23 | constructor(authenticationProvider: AuthenticationProvider, mqttBase?: any) { 24 | super(authenticationProvider, mqttBase); 25 | /*Codes_SRS_NODE_DEVICE_MQTT_16_017: [The `MqttWs` constructor shall initialize the `uri` property of the `config` object to `wss://:443/$iothub/websocket`.]*/ 26 | } 27 | 28 | protected _getBaseTransportConfig(credentials: TransportConfig): MqttBaseTransportConfig { 29 | const baseConfig: MqttBaseTransportConfig = super._getBaseTransportConfig(credentials); 30 | baseConfig.uri = 'wss://' + (credentials.gatewayHostName || credentials.host) + ':443/$iothub/websocket'; 31 | return baseConfig; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /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 | const EventEmitter = require('events').EventEmitter; 7 | const assert = require('chai').assert; 8 | const sinon = require('sinon'); 9 | const MqttWs = require('../dist/mqtt_ws.js').MqttWs; 10 | 11 | describe('MqttWs', function () { 12 | const fakeConfig = { 13 | host: 'host.name', 14 | deviceId: 'deviceId', 15 | sharedAccessSignature: 'sas' 16 | }; 17 | 18 | const fakeAuthenticationProvider = { 19 | getDeviceCredentials: function (callback) { 20 | callback(null, fakeConfig); 21 | } 22 | }; 23 | 24 | const fakeMqttBase = new EventEmitter(); 25 | fakeMqttBase.connect = sinon.stub().callsArg(1); 26 | fakeMqttBase.disconnect = sinon.stub().callsArg(0); 27 | fakeMqttBase.publish = sinon.stub().callsArg(3); 28 | fakeMqttBase.subscribe = sinon.stub().callsArg(2); 29 | fakeMqttBase.unsubscribe = sinon.stub().callsArg(1); 30 | fakeMqttBase.updateSharedAccessSignature = sinon.stub().callsArg(1); 31 | 32 | describe('#constructor', function () { 33 | /* Tests_SRS_NODE_DEVICE_MQTT_12_001: [The `Mqtt` constructor shall accept the transport configuration structure */ 34 | /* Tests_SRS_NODE_DEVICE_MQTT_12_002: [The `Mqtt` constructor shall store the configuration structure in a member variable */ 35 | it('stores config and created transport in member', function () { 36 | const mqttWs = new MqttWs(fakeAuthenticationProvider); 37 | assert.notEqual(mqttWs, null); 38 | assert.notEqual(mqttWs, undefined); 39 | assert.equal(mqttWs._authenticationProvider, fakeAuthenticationProvider); 40 | }); 41 | }); 42 | 43 | describe('#connect', function () { 44 | /*Tests_SRS_NODE_DEVICE_MQTT_16_017: [The `MqttWs` constructor shall initialize the `uri` property of the `config` object to `wss://:443/$iothub/websocket`.]*/ 45 | it('sets the uri property to \'wss://:443/$iothub/websocket\'', function (testCallback) { 46 | const mqttWs = new MqttWs(fakeAuthenticationProvider, fakeMqttBase); 47 | mqttWs.connect(function () { 48 | assert.strictEqual(fakeMqttBase.connect.firstCall.args[0].uri, 'wss://' + fakeConfig.host + ':443/$iothub/websocket'); 49 | testCallback(); 50 | }); 51 | }); 52 | }) 53 | }); 54 | -------------------------------------------------------------------------------- /device/transport/mqtt/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "./src/**/*.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /doc/images/Azure IoT Hub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-iot-sdk-node/b7ad22ad79baa3069cc16014bef337b65a0d0e97/doc/images/Azure IoT Hub.png -------------------------------------------------------------------------------- /e2etests/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /e2etests/test/eventhub_receiver_helper.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 | let EventHubClient = require('@azure/event-hubs').EventHubClient; 7 | let EventPosition = require('@azure/event-hubs').EventPosition; 8 | let util = require('util'); 9 | let EventEmitter = require('events'); 10 | let closeDeviceEventHubClients = require('./testUtils.js').closeDeviceEventHubClients; 11 | 12 | let hubConnectionString = process.env.IOTHUB_CONNECTION_STRING; 13 | 14 | let EventHubReceiverHelper = function () { 15 | EventEmitter.call(this); 16 | }; 17 | util.inherits(EventHubReceiverHelper, EventEmitter); 18 | 19 | EventHubReceiverHelper.prototype.openClient = function (done) { 20 | let self = this; 21 | // account for potential delays and clock skews 22 | let startTime = Date.now() - 5000; 23 | let onEventHubMessage = function (eventData) { 24 | self.emit('message', eventData); 25 | }; 26 | let onEventHubError = function (err) { 27 | self.emit('error', err); 28 | }; 29 | 30 | EventHubClient.createFromIotHubConnectionString(hubConnectionString) 31 | .then(function (client) { 32 | self.ehClient = client; 33 | }).then(function () { 34 | return self.ehClient.getPartitionIds(); 35 | }).then(function (partitionIds) { 36 | partitionIds.forEach(function (partitionId) { 37 | self.ehClient.receive(partitionId, onEventHubMessage, onEventHubError, { eventPosition: EventPosition.fromEnqueuedTime(startTime) }); 38 | }); 39 | }).then(function () { 40 | done(); 41 | }).catch(function (err) { 42 | done(err); 43 | }); 44 | }; 45 | 46 | EventHubReceiverHelper.prototype.closeClient = function (done) { 47 | closeDeviceEventHubClients(null, this.ehClient, done); 48 | }; 49 | 50 | module.exports = EventHubReceiverHelper; 51 | -------------------------------------------------------------------------------- /e2etests/test/rendezvous_helper.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 Rendezvous(done) { 7 | this.doneYet = {}; 8 | this.done = done; 9 | this.everybodyDone = true; 10 | } 11 | 12 | Rendezvous.prototype.imIn = function (participant) { 13 | if (Object.prototype.hasOwnProperty.call(this.doneYet, participant)) { 14 | throw new Error('can not participate more than once'); 15 | } 16 | this.doneYet[participant] = false; 17 | }; 18 | 19 | Rendezvous.prototype.imDone = function (participant) { 20 | if (Object.keys(this.doneYet).length === 0) { 21 | throw new Error('Nobody joined to rendezvous'); 22 | } 23 | if (this.doneYet[participant]) { 24 | throw new Error('participant can not say done more than once'); 25 | } 26 | this.doneYet[participant] = true; 27 | this.everybodyDone = true; 28 | Object.keys(this.doneYet).forEach(function (aParticipant) { 29 | this.everybodyDone = this.everybodyDone && this.doneYet[aParticipant]; 30 | }.bind(this)); 31 | if (this.everybodyDone) { 32 | return this.done(); 33 | } 34 | }; 35 | 36 | module.exports = { Rendezvous: Rendezvous }; 37 | -------------------------------------------------------------------------------- /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 | let serviceSdk = require('azure-iothub'); 7 | let serviceSas = require('azure-iothub').SharedAccessSignature; 8 | let anHourFromNow = require('azure-iot-common').anHourFromNow; 9 | let Amqp = require('azure-iothub').Amqp; 10 | let AmqpWs = require('azure-iothub').AmqpWs; 11 | 12 | let assert = require('chai').assert; 13 | 14 | let hubConnectionString = process.env.IOTHUB_CONNECTION_STRING; 15 | 16 | describe('Service Client', function () { 17 | // eslint-disable-next-line no-invalid-this 18 | this.timeout(60000); 19 | [Amqp, AmqpWs].forEach(function (Transport) { 20 | it('Service client can connect over ' + Transport.name + ' using a shared access signature', function (done) { 21 | let connStr = serviceSdk.ConnectionString.parse(hubConnectionString); 22 | let sas = serviceSas.create(connStr.HostName, connStr.SharedAccessKeyName, connStr.SharedAccessKey, anHourFromNow()).toString(); 23 | let serviceClient = serviceSdk.Client.fromSharedAccessSignature(sas, Transport); 24 | // eslint-disable-next-line security/detect-non-literal-fs-filename 25 | serviceClient.open(function (err, result) { 26 | if(err) { 27 | done(err); 28 | } else { 29 | assert.equal(result.constructor.name, 'Connected'); 30 | serviceClient.close(function (err) { 31 | done(err); 32 | }); 33 | } 34 | }); 35 | }); 36 | 37 | it('Service client can connect over ' + Transport.name + ' using a connection string', function (done) { 38 | let serviceClient = serviceSdk.Client.fromConnectionString(hubConnectionString, Transport); 39 | // eslint-disable-next-line security/detect-non-literal-fs-filename 40 | serviceClient.open(function (err, result) { 41 | if(err) { 42 | done(err); 43 | } else { 44 | assert.equal(result.constructor.name, 'Connected'); 45 | serviceClient.close(function (err) { 46 | done(err); 47 | }); 48 | } 49 | }); 50 | }); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "lerna": "3.20.2", 3 | "packages": [ 4 | "build/tools", 5 | "common/core", 6 | "common/transport/*", 7 | "device/core", 8 | "device/samples", 9 | "device/samples/javascript", 10 | "device/samples/typescript", 11 | "device/samples/helpers/device-twin-service", 12 | "device/transport/*", 13 | "provisioning/*", 14 | "provisioning/transport/*", 15 | "provisioning/device/samples", 16 | "provisioning/device/ts-samples", 17 | "provisioning/service/samples", 18 | "security/*", 19 | "sdklab/longhaultests", 20 | "sdklab/mean_time_recovery", 21 | "sdklab/stress_fault", 22 | "e2etests", 23 | "ts-e2e", 24 | "stresstests" 25 | ], 26 | "version": "0.0.0", 27 | "maxBuffer": 1048576 28 | } 29 | -------------------------------------------------------------------------------- /lts_branches.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-iot-sdk-node/b7ad22ad79baa3069cc16014bef337b65a0d0e97/lts_branches.png -------------------------------------------------------------------------------- /mocha-reports.json: -------------------------------------------------------------------------------- 1 | { 2 | "reporterEnabled": "spec,mocha-junit-reporter", 3 | "mochaJunitReporterReporterOptions": { 4 | "mochaFile": "test-results.[hash].xml", 5 | "includePending": true 6 | } 7 | } -------------------------------------------------------------------------------- /node_e2e_resources/.gitignore: -------------------------------------------------------------------------------- 1 | secrets/ -------------------------------------------------------------------------------- /node_e2e_resources/credscan_suppresion.json: -------------------------------------------------------------------------------- 1 | { 2 | "tool": "Credential Scanner", 3 | "suppressions": [ 4 | { 5 | "file": "\\test-resources.bicep", 6 | "_justification": "Bicep file containing fake shared access tokens" 7 | }, 8 | { 9 | "file": "\\deploy.sh", 10 | "_justification": "Bash script containing fake shared access tokens" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /node_e2e_resources/dps.bicep: -------------------------------------------------------------------------------- 1 | @minLength(3) 2 | @maxLength(64) 3 | param name string 4 | 5 | @secure() 6 | @description('The connection string of the IoT Hub to link to this DPS instance') 7 | param iotHubConnectionString string 8 | 9 | resource dps 'Microsoft.Devices/provisioningServices@2020-03-01' = { 10 | name: name 11 | location: resourceGroup().location 12 | sku: { 13 | name: 'S1' 14 | } 15 | properties: { 16 | iotHubs: [ 17 | { 18 | connectionString: iotHubConnectionString 19 | location: resourceGroup().location 20 | } 21 | ] 22 | } 23 | } 24 | 25 | output idScope string = dps.properties.idScope 26 | var key = listKeys(resourceId('Microsoft.Devices/provisioningServices/keys', dps.name, 'provisioningserviceowner'), dps.apiVersion).primaryKey 27 | output connectionString string = 'HostName=${dps.properties.serviceOperationsHostName};SharedAccessKeyName=provisioningserviceowner;SharedAccessKey=${key}' 28 | output name string = name 29 | -------------------------------------------------------------------------------- /node_e2e_resources/get_env.sh: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft. All rights reserved. 2 | # Licensed under the MIT license. See LICENSE file in the project root for 3 | # full license information. 4 | 5 | export IOT_PROVISIONING_DEVICE_ENDPOINT=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name IOT-PROVISIONING-DEVICE-ENDPOINT) 6 | export IOTHUB_CA_ROOT_CERT=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name IOTHUB-CA-ROOT-CERT) 7 | export IOTHUB_CA_ROOT_CERT_KEY=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name IOTHUB-CA-ROOT-CERT-KEY) 8 | export IOT_PROVISIONING_DEVICE_IDSCOPE=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name IOT-PROVISIONING-DEVICE-IDSCOPE) 9 | export IOT_PROVISIONING_ROOT_CERT=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name IOT-PROVISIONING-ROOT-CERT) 10 | export IOT_PROVISIONING_ROOT_CERT_KEY=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name IOT-PROVISIONING-ROOT-CERT-KEY) 11 | export IOT_PROVISIONING_SERVICE_CONNECTION_STRING=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name IOT-PROVISIONING-SERVICE-CONNECTION-STRING) 12 | export IOTHUB_CONNECTION_STRING=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name IOTHUB-CONNECTION-STRING) 13 | export STORAGE_CONNECTION_STRING=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name STORAGE-CONNECTION-STRING) 14 | export DPS_CONN_STRING_INVALID_CERT=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name DPS-CONN-STRING-INVALID-CERT) 15 | export DPS_GLOBAL_DEVICE_ENDPOINT_INVALID_CERT=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name DPS-GLOBAL-DEVICE-ENDPOINT-INVALID-CERT) 16 | export IOTHUB_CONN_STRING_INVALID_CERT=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name IOTHUB-CONN-STRING-INVALID-CERT) 17 | export IOTHUB_DEVICE_CONN_STRING_INVALID_CERT=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name IOTHUB-DEVICE-CONN-STRING-INVALID-CERT) -------------------------------------------------------------------------------- /node_e2e_resources/iot-hub.bicep: -------------------------------------------------------------------------------- 1 | @minLength(3) 2 | @maxLength(50) 3 | @description('The name of the IoT Hub to be created') 4 | param name string 5 | 6 | @secure() 7 | @description('The connection string for the storage account') 8 | param storageConnectionString string 9 | 10 | resource iotHub 'Microsoft.Devices/IotHubs@2021-07-01' = { 11 | name: name 12 | location: resourceGroup().location 13 | sku: { 14 | name: 'S1' 15 | capacity: 2 16 | } 17 | properties: { 18 | enableFileUploadNotifications: true 19 | storageEndpoints: { 20 | '$default': { 21 | sasTtlAsIso8601: 'PT1H' 22 | connectionString: storageConnectionString 23 | containerName: 'aziotbld' 24 | } 25 | } 26 | routing: { 27 | routes: [ 28 | { 29 | name: 'twin-update-event' 30 | source: 'TwinChangeEvents' 31 | condition: 'true' 32 | endpointNames: [ 33 | 'events' 34 | ] 35 | isEnabled: true 36 | } 37 | ] 38 | fallbackRoute: { 39 | name: '$fallback' 40 | source: 'DeviceMessages' 41 | condition: 'true' 42 | endpointNames: [ 43 | 'events' 44 | ] 45 | isEnabled: true 46 | } 47 | } 48 | } 49 | } 50 | 51 | var sharedAccessKeyName = '${listKeys(iotHub.id, '2020-04-01').value[0].keyName}' 52 | var sharedAccessKey = '${listKeys(iotHub.id, '2020-04-01').value[0].primaryKey}' 53 | 54 | output connectionString string = 'HostName=${iotHub.name}.azure-devices.net;SharedAccessKeyName=${sharedAccessKeyName};SharedAccessKey=${sharedAccessKey}' 55 | output eventHubConnectionString string = 'Endpoint=${iotHub.properties.eventHubEndpoints.events.endpoint};SharedAccessKeyName=${sharedAccessKeyName};SharedAccessKey=${sharedAccessKey};EntityPath=${iotHub.properties.eventHubEndpoints.events.path}' 56 | output name string = name 57 | -------------------------------------------------------------------------------- /node_e2e_resources/key-vault.bicep: -------------------------------------------------------------------------------- 1 | @minLength(3) 2 | @maxLength(24) 3 | @description('The name of the Key Vault to be created') 4 | param keyVaultName string 5 | 6 | @description('Signed in user objectId') 7 | param userObjectId string 8 | 9 | // TODO: switch to object and use items() when released in Bicep v0.5 10 | // https://github.com/Azure/bicep/pull/4456 11 | param keyVaultSecrets array 12 | 13 | resource keyVault 'Microsoft.KeyVault/vaults@2019-09-01' = { 14 | name: keyVaultName 15 | location: resourceGroup().location 16 | properties: { 17 | sku: { 18 | family: 'A' 19 | name: 'standard' 20 | } 21 | tenantId: subscription().tenantId 22 | accessPolicies: [ 23 | { 24 | objectId: userObjectId 25 | tenantId: subscription().tenantId 26 | permissions: { 27 | secrets: [ 28 | 'all' 29 | ] 30 | certificates: [ 31 | 'all' 32 | ] 33 | keys: [ 34 | 'all' 35 | ] 36 | storage: [ 37 | 'all' 38 | ] 39 | } 40 | } 41 | ] 42 | } 43 | 44 | resource secrets 'secrets' = [for secret in keyVaultSecrets: { 45 | name: secret.name 46 | properties: { 47 | value: secret.value 48 | } 49 | }] 50 | } 51 | 52 | output name string = keyVaultName 53 | -------------------------------------------------------------------------------- /node_e2e_resources/storage-account.bicep: -------------------------------------------------------------------------------- 1 | @minLength(3) 2 | @maxLength(24) 3 | @description('The name of the storage account to be created') 4 | param storageAccountName string 5 | 6 | resource storageAccount 'Microsoft.Storage/storageAccounts@2021-04-01' = { 7 | name: storageAccountName 8 | location: resourceGroup().location 9 | sku: { 10 | name: 'Standard_GRS' 11 | } 12 | kind: 'Storage' 13 | resource blobService 'blobServices' = { 14 | name: 'default' 15 | resource container 'containers' = { 16 | name: 'aziotbld' 17 | } 18 | } 19 | } 20 | 21 | output connectionString string = 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value};EndpointSuffix=${environment().suffixes.storage}' 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "npmlockrefresh": "npm i --package-lock-only", 4 | "codespaceinstall": "(cd device/samples/javascript && npm install & cd ../../../) && (cd device/samples/javascript/pnp && npm install & cd ../../../../) && (cd device/samples/typescript && npm install && npm run build)" 5 | }, 6 | "devDependencies": { 7 | "lerna": "^5.6.2", 8 | "mocha": "^9.2.1" 9 | }, 10 | "engines": { 11 | "node": ">=14.0.0" 12 | }, 13 | "husky": { 14 | "hooks": { 15 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 16 | } 17 | }, 18 | "commitlint": { 19 | "extends": [ 20 | "@commitlint/config-conventional" 21 | ], 22 | "rules": { 23 | "header-max-length": [ 24 | 0, 25 | "always", 26 | 150 27 | ] 28 | } 29 | }, 30 | "config": { 31 | "commitizen": { 32 | "path": "cz-conventional-changelog" 33 | } 34 | }, 35 | "dependencies": { 36 | "eslint-plugin-security": "^1.5.0", 37 | "node-gyp": "^9.0.0", 38 | "nodejs": "^0.0.0", 39 | "typescript": "4.4.4" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /provisioning/device/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | ts-samples/ 5 | samples/ 6 | src/ 7 | dist/**/*.map 8 | .nyc_output -------------------------------------------------------------------------------- /provisioning/device/devdoc/provisioning_client_requirements.md: -------------------------------------------------------------------------------- 1 | # provisioning client requirements 2 | 3 | ## Overview 4 | 5 | The `ProvisioningDeviceClient` class is the factory object used by clients to create a registration clients. 6 | 7 | ## Public API 8 | 9 | ### create(provisioningHost, idScope, transport, securityClient) 10 | 11 | The `create` method is used to retrieve a client object that can be used to register with the Device Provisioning Service 12 | 13 | **SRS_PROVISIONING_CLIENT_06_001: [** The `create` method shall throw `ReferenceError` if the `provisioningHost` argument is falsy. **]** 14 | 15 | **SRS_PROVISIONING_CLIENT_06_002: [** The `create` method shall throw `ReferenceError` if the `idScope` argument is falsy. **]** 16 | 17 | **SRS_PROVISIONING_CLIENT_18_001: [** If `securityClient` implements `X509SecurityClient` and the `transport` implements `X509ProvisioningTransport`, then `create` shall 18 | return an `X509Registration` object. **]** 19 | 20 | **SRS_PROVISIONING_CLIENT_18_002: [** If `securityClient` implements `X509SecurityClient` and the `transport` does not implement `X509ProvisioningTransport`, then `create` shall throw an `ArgumentError` exception. **]** 21 | 22 | **SRS_PROVISIONING_CLIENT_18_003: [** If `securityClient` implements `TPMSecurityClient` and the `transport` implements `TPMProvisioningTransport`, then `create` shall return a `TpmRegistration` object. **]** 23 | 24 | **SRS_PROVISIONING_CLIENT_18_004: [** If `securityClient` implements `TPMSecurityClient` and the `transport` dos not implement `TPMProvisioningTransport`, then `create` shall throw an `ArgumentError` exception. **]** 25 | 26 | **SRS_PROVISIONING_CLIENT_06_003: [** If `securityClient` implements `SymmetricKeySecurityClient` and the `transport` implements `SymmetricKeyProvisioningTransport`, then `create` shall return an `SymmetricKeyRegistration` object. **]** 27 | 28 | **SRS_PROVISIONING_CLIENT_06_004: [** If `securityClient` implements `SymmetricKeySecurityClient` and the `transport` does not implement `SymmetricKeyProvisioningTransport`, then `create` shall throw an `ArgumentError` exception. **]** 29 | 30 | **SRS_PROVISIONING_CLIENT_18_005: [** If `securityClient` does not implement `X509SecurityClient`, `TPMSecurityClient`, or `SymmetricKeySecurityClient` then `create` shall show an `ArgumentError` exception. **]** -------------------------------------------------------------------------------- /provisioning/device/devdoc/provisioning_error_requirements.md: -------------------------------------------------------------------------------- 1 | # azure-iot-provisioning-device.translateError Requirements 2 | 3 | ## Overview 4 | `translateError` is a method that translates provisioning 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_DPS_ERRORS_18_001: [** `translateError` shall accept 4 arguments: 9 | - A custom error message to give context to the user. 10 | - the status code that initiated the error 11 | - the response body 12 | - the transport object that is associated with this error **]** 13 | 14 | ** SRS_NODE_DPS_ERRORS_18_008: [** Any error object returned by `translateError` shall inherit from the generic `Error` Javascript object and have 3 properties: 15 | - `result` shall contain the body of the response 16 | - `transportObject` shall contain the transport object that is associated with this error 17 | - `message` shall contain a human-readable error message **]** 18 | 19 | ** SRS_NODE_DPS_ERRORS_18_002: [** `translateError` shall return an `ArgumentError` if the status code is `400`. **]** 20 | 21 | ** SRS_NODE_DPS_ERRORS_18_003: [** `translateError` shall return an `UnauthorizedError` if the status code is `401`. **]** 22 | 23 | ** SRS_NODE_DPS_ERRORS_18_004: [** `translateError` shall return an `DeviceNotFoundError` if the status code is `404`. **]** 24 | 25 | ** SRS_NODE_DPS_ERRORS_18_005: [** `translateError` shall return an `IotHubQuotaExceededError` if the status code is `429`. **]** 26 | 27 | ** SRS_NODE_DPS_ERRORS_18_006: [** `translateError` shall return an `InternalServerError` if the status code is `500`. **]** 28 | 29 | ** SRS_NODE_DPS_ERRORS_18_007: [** If the status code is unknown, `translateError` should return a generic Javascript `Error` object. **]** 30 | 31 | -------------------------------------------------------------------------------- /provisioning/device/devdoc/symmetric_registration_requirements.md: -------------------------------------------------------------------------------- 1 | # SymmetricKeyRegistration requirements 2 | 3 | ## Overview 4 | 5 | The `SymmetricKeyRegistration` class is used to control the registration flow of a device, regardless of the transport, or `SymmetricKeySecurityClient` implementation. 6 | 7 | ## Example usage 8 | 9 | ```js 10 | // TODO once all the pieces are there in the SDK 11 | 12 | ``` 13 | 14 | ## Public API 15 | 16 | ### register() 17 | 18 | The `register` method completes the authentication and registration flow for the user. 19 | 20 | **SRS_NODE_DPS_SYMMETRIC_REGISTRATION_06_006: [** `register` shall call the `getRegistrationId` method on the security object to acquire the registration id. **]** 21 | 22 | **SRS_NODE_DPS_SYMMETRIC_REGISTRATION_06_007: [** If the `getRegistrationId` fails, the `register` shall call the `_callback` with the error. **]** 23 | 24 | **SRS_NODE_DPS_SYMMETRIC_REGISTRATION_06_008: [** `register` shall invoke `createSharedAccessSignature` method on the security object to acquire a sas token object. **]** 25 | 26 | **SRS_NODE_DPS_SYMMETRIC_REGISTRATION_06_012: [** If `setProvisioningPayload` is invoked prior to invoking `register` than the `payload` property of the `RegistrationRequest` shall be set to the argument provided to the `setProvisioningPayload`. **]** 27 | 28 | **SRS_NODE_DPS_SYMMETRIC_REGISTRATION_06_009: [** If the `createSharedAccessSignature` fails, the `register` shall call the `_callback` with the error. **]** 29 | 30 | **SRS_NODE_DPS_SYMMETRIC_REGISTRATION_06_004: [** `register` shall pass the SAS into the `setSharedAccessSignature` method on the transport. **]** 31 | 32 | **SRS_NODE_DPS_SYMMETRIC_REGISTRATION_06_005: [** `register` shall call `register` on the polling state machine object. **]** 33 | 34 | **SRS_NODE_DPS_SYMMETRIC_REGISTRATION_06_010: [** if the polling register returns an error, the `register` shall invoke the `_callback` with that error. **]** 35 | 36 | **SRS_NODE_DPS_SYMMETRIC_REGISTRATION_06_011: [** Otherwise `register` shall invoke the `_callback` with the resultant `registrationState` as the second argument. **]** 37 | 38 | ### cancel() 39 | 40 | The `cancel` method cancels a registration flow that is in progress. 41 | 42 | **SRS_NODE_DPS_SYMMETRIC_REGISTRATION_06_001: [** `cancel` shall call `cancel` on the transport object. **]** -------------------------------------------------------------------------------- /provisioning/device/devdoc/x509_registration_requirements.md: -------------------------------------------------------------------------------- 1 | # X509registration requirements 2 | 3 | ## Overview 4 | 5 | The `X509Registration` class is used to control the registration flow of an X509-enabled device, regardless of the transport, or `X509SecurityClient` implementation. 6 | 7 | ## Example usage 8 | 9 | ```js 10 | // TODO once all the pieces are there in the SDK 11 | 12 | ``` 13 | 14 | ## Public API 15 | 16 | ### register() 17 | 18 | The `register` method completes the authentication and registration flow for the user. 19 | 20 | **SRS_NODE_DPS_X509_REGISTRATION_06_001: [** If `setProvisioningPayload` is invoked prior to invoking `register` than the `payload` property of the `RegistrationRequest` shall be set to the argument provided to the `setProvisioningPayload`. **]** 21 | 22 | **SRS_NODE_DPS_X509_REGISTRATION_18_001: [** `register` shall call `getCertificate` on the security object to acquire the X509 certificate. **]** 23 | 24 | **SRS_NODE_DPS_X509_REGISTRATION_18_006: [** If `getCertificate`fails, `register` shall call `callback` with the error **]** 25 | 26 | **SRS_NODE_DPS_X509_REGISTRATION_18_004: [** `register` shall pass the certificate into the `setAuthentication` method on the transport **]** 27 | 28 | **SRS_NODE_DPS_X509_REGISTRATION_18_002: [** `register` shall call `register` on the pollingStateMachine and call `callback` with the result. **]** 29 | 30 | **SRS_NODE_DPS_X509_REGISTRATION_18_005: [** If `register` on the pollingStateMachine fails, `register` shall call `callback` with the error **]** 31 | 32 | ### cancel() 33 | 34 | The `cancel` method cancels a registration flow that is in progress. 35 | 36 | **SRS_NODE_DPS_X509_REGISTRATION_18_003: [** `cancel` shall call `cancel` on the transport object. **]** -------------------------------------------------------------------------------- /provisioning/device/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 { ProvisioningTransportOptions } from './dist/interfaces'; 5 | export { RegistrationRequest, RegistrationResult, DeviceRegistrationResult } from './dist/interfaces'; 6 | export { DeviceRegistration, TpmAttestation } from './dist/interfaces'; 7 | export { X509ProvisioningTransport} from './dist/interfaces'; 8 | export { SymmetricKeyProvisioningTransport } from './dist/interfaces'; 9 | export { TpmProvisioningTransport, TpmRegistrationInfo, TpmRegistrationResult } from './dist/interfaces'; 10 | export { PollingStateMachine } from './dist/polling_state_machine'; 11 | export { ProvisioningDeviceClient } from './dist/client'; 12 | export { ProvisioningDeviceConstants } from './dist/constants'; 13 | export { translateError } from './dist/provisioning_errors'; 14 | 15 | -------------------------------------------------------------------------------- /provisioning/device/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-provisioning-device` module provides access to the Azure Device Provisioning Service. 8 | * 9 | * @module azure-iot-provisioning-device 10 | * @requires module:azure-iot-common 11 | */ 12 | 13 | module.exports = { 14 | ProvisioningTransportOptions: require('./dist/interfaces').ProvisioningTransportOptions, 15 | RegistrationRequest: require('./dist/interfaces').RegistrationRequest, 16 | RegistrationResult: require('./dist/interfaces').RegistrationResult, 17 | DeviceRegistrationResult: require('./dist/interfaces').DeviceRegistrationResult, 18 | X509ProvisioningTransport: require('./dist/interfaces').X509ProvisioningTransport, 19 | SymmetricKeyProvisioningTransport: require('./dist/interfaces').SymmetricKeyProvisioningTransport, 20 | PollingStateMachine: require('./dist/polling_state_machine').PollingStateMachine, 21 | ProvisioningDeviceClient: require('./dist/client').ProvisioningDeviceClient, 22 | ProvisioningDeviceConstants: require('./dist/constants').ProvisioningDeviceConstants, 23 | translateError: require('./dist/provisioning_errors').translateError, 24 | DeviceRegistration: require('./dist/interfaces').DeviceRegistration, 25 | TpmAttestation: require('./dist/interfaces').TpmAttestation 26 | }; -------------------------------------------------------------------------------- /provisioning/device/readme.md: -------------------------------------------------------------------------------- 1 | This package (**azure-iot-provisioning-device**) provides the device client that is used to communicate with the Azure IoT Hub Device Provisioning Service. 2 | 3 | [![npm version](https://badge.fury.io/js/azure-iot-provisioning-device.svg)](https://badge.fury.io/js/azure-iot-provisioning-device) 4 | 5 | ## Install 6 | 7 | There are at least 3 different packages involved when writing code to take advantage of the Azure IoT Hub Device Provisioning Service: 8 | - The "client" package that will be used to create a provisioning client. (This package). 9 | - the "transport" package that will decide which protocol will be used to communicate with the provisioning service. One of **azure-iot-provisioning-device-amqp**, **azure-iot-provisioning-device-mqtt**, or **azure-iot-provisioning-device-http**. Please note that X509 authentication is supported with all protocols but TPM authentication is supported only with AMQP and HTTP. 10 | - The "security client" package that will be used to interface with whatever type of security (x509 or TPM) is used to authenticate the device. 11 | 12 | For example: 13 | ``` 14 | npm install --save azure-iot-provisioning-device 15 | npm install --save azure-iot-provisioning-device-amqp # Or -mqtt or -http 16 | npm install --save azure-iot-security-x509 # Or -tpm 17 | ``` 18 | 19 | ## Getting Started 20 | 21 | To get started please read our [Overview of the Device Provisioning Service](https://docs.microsoft.com/en-us/azure/iot-dps/about-iot-dps) and visit [our tutorials pages](https://docs.microsoft.com/en-us/azure/iot-dps/tutorial-set-up-cloud) 22 | 23 | -------------------------------------------------------------------------------- /provisioning/device/samples/getParameters.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 | const tss = require('tss.js'); 7 | const tpm = require('azure-iot-security-tpm'); 8 | const myTpm = new tpm.TpmSecurityClient(undefined, new tss.Tpm(false)); 9 | 10 | myTpm.getEndorsementKey((err, endorsementKey) => { 11 | if (err) { 12 | console.log('The error returned from get ek is: ' + err); 13 | } else { 14 | console.log('The ek is: ' + endorsementKey.toString('base64')); 15 | myTpm.getStorageRootKey(( err, storageRootKey) => { 16 | if (err) { 17 | console.log('The error returned from get storage root key is: ' + err); 18 | } else { 19 | console.log('The srk is: ' + storageRootKey.toString('base64')); 20 | myTpm.getRegistrationId((err, registrationId) => { 21 | if (err) { 22 | console.log('The error returned from get registration id is: ' + err); 23 | } else { 24 | console.log('The registration id is: ' + registrationId); 25 | } 26 | }); 27 | } 28 | }); 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /provisioning/device/samples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-provisioning-device-samples", 3 | "version": "0.0.1", 4 | "description": "Azure IoT SDK - Provisioning Device Client samples", 5 | "author": "Microsoft Corporation", 6 | "license": "MIT", 7 | "dependencies": { 8 | "async": "^3.2.3", 9 | "es5-ext": "0.10.53", 10 | "azure-iot-device": "1.18.3", 11 | "azure-iot-device-amqp": "1.14.3", 12 | "azure-iot-device-http": "1.14.3", 13 | "azure-iot-device-mqtt": "1.16.3", 14 | "azure-iot-provisioning-device": "1.9.1", 15 | "azure-iot-provisioning-device-amqp": "1.9.1", 16 | "azure-iot-provisioning-device-http": "1.9.1", 17 | "azure-iot-provisioning-device-mqtt": "1.8.1", 18 | "azure-iot-security-symmetric-key": "1.8.2", 19 | "azure-iot-security-tpm": "1.9.2", 20 | "azure-iot-security-x509": "1.8.2", 21 | "rhea": "^1.0.15" 22 | }, 23 | "scripts": { 24 | "npmlockrefresh": "npm i --package-lock-only" 25 | }, 26 | "engines": { 27 | "node": ">= 14.0.0" 28 | }, 29 | "repository": { 30 | "type": "git", 31 | "url": "git+https://github.com/Azure/azure-iot-sdk-node.git" 32 | }, 33 | "bugs": { 34 | "url": "https://github.com/Azure/azure-iot-sdk-node/issues" 35 | }, 36 | "homepage": "https://github.com/Azure/azure-iot-sdk-node#readme" 37 | } -------------------------------------------------------------------------------- /provisioning/device/src/constants.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 | // tslint:disable-next-line:no-var-requires 7 | const packageJson = require('../package.json'); 8 | 9 | /** 10 | * @private 11 | */ 12 | export class ProvisioningDeviceConstants { 13 | /** 14 | * User-Agent string passed to the service as part of communication 15 | */ 16 | static userAgent: string = packageJson.name + '/' + packageJson.version; 17 | 18 | /** 19 | * Default interval for polling, to use in case service doesn't provide it to us. 20 | */ 21 | static defaultPollingInterval: number = 2000; 22 | 23 | /** 24 | * apiVersion to use while communicating with service. 25 | */ 26 | static apiVersion: string = '2019-03-31'; 27 | 28 | /** 29 | * default timeout to use when communicating with the service 30 | */ 31 | static defaultTimeoutInterval: number = 30000; 32 | } 33 | -------------------------------------------------------------------------------- /provisioning/device/ts-samples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-provisioning-device-ts-samples", 3 | "version": "0.0.1", 4 | "description": "Azure IoT SDK - Provisioning Device Client typescript samples", 5 | "author": "Microsoft Corporation", 6 | "license": "MIT", 7 | "dependencies": { 8 | "async": "^3.2.3", 9 | "es5-ext": "0.10.53", 10 | "azure-iot-device": "1.18.3", 11 | "azure-iot-device-amqp": "1.14.3", 12 | "azure-iot-device-http": "1.14.3", 13 | "azure-iot-device-mqtt": "1.16.3", 14 | "azure-iot-provisioning-device": "1.9.1", 15 | "azure-iot-provisioning-device-amqp": "1.9.1", 16 | "azure-iot-provisioning-device-http": "1.9.1", 17 | "azure-iot-provisioning-device-mqtt": "1.8.1", 18 | "azure-iot-security-symmetric-key": "1.8.2", 19 | "azure-iot-security-tpm": "1.9.2", 20 | "azure-iot-security-x509": "1.8.2" 21 | }, 22 | "devDependencies": { 23 | "encoding": "^0.1.13", 24 | "tslint": "^6.1.3", 25 | "typescript": "4.4.4" 26 | }, 27 | "scripts": { 28 | "npmlockrefresh": "npm i --package-lock-only", 29 | "lint": "tslint --project . -c ../../../tslint.json", 30 | "build": "tsc", 31 | "test": "mocha ./dist/*.tests.js" 32 | }, 33 | "engines": { 34 | "node": ">= 14.0.0" 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 | } -------------------------------------------------------------------------------- /provisioning/device/ts-samples/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "target":"es2018", 5 | "module": "commonjs", 6 | "sourceMap": true, 7 | "declaration": true, 8 | "noUnusedLocals": true, 9 | "noUnusedParameters": true, 10 | "removeComments": false 11 | }, 12 | "include": [ 13 | "./src/**/*.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /provisioning/device/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "target":"es2018", 5 | "module": "commonjs", 6 | "sourceMap": true, 7 | "declaration": true, 8 | "noUnusedLocals": true, 9 | "noUnusedParameters": true, 10 | "removeComments": false 11 | }, 12 | "include": [ 13 | "./src/**/*.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /provisioning/e2e/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-provisioning-device-e2e", 3 | "version": "1.9.1", 4 | "description": "E2E tests for the Azure Device Provisioning SDK", 5 | "author": "Microsoft Corporation", 6 | "license": "MIT", 7 | "dependencies": { 8 | "async": "^3.2.3", 9 | "es5-ext": "0.10.53", 10 | "azure-iot-common": "1.13.2", 11 | "azure-iot-provisioning-device": "1.9.1", 12 | "azure-iot-provisioning-device-amqp": "1.9.1", 13 | "azure-iot-provisioning-device-http": "1.9.1", 14 | "azure-iot-provisioning-device-mqtt": "1.8.1", 15 | "azure-iot-provisioning-service": "1.10.1", 16 | "azure-iot-security-symmetric-key": "1.8.2", 17 | "azure-iot-security-tpm": "1.9.2", 18 | "azure-iot-security-x509": "1.8.2", 19 | "azure-iothub": "1.15.1", 20 | "chai": "^4.3.3", 21 | "debug": "^4.3.1", 22 | "jshint": "^2.13.4", 23 | "mocha": "^9.2.1", 24 | "mocha-junit-reporter": "^2.0.2", 25 | "mocha-multi-reporters": "^1.1.7", 26 | "nyc": "^15.0.0", 27 | "pem": "^1.14.2", 28 | "sinon": "^11.1.2", 29 | "tss.js": "^2.0.0", 30 | "uuid": "^8.3.2" 31 | }, 32 | "scripts": { 33 | "npmlockrefresh": "npm i --package-lock-only", 34 | "server_validation": "mocha --reporter mocha-multi-reporters --reporter-options configFile=../../mocha-reports.json _server_validation.js", 35 | "service_create_delete": "mocha --reporter mocha-multi-reporters --reporter-options configFile=../../mocha-reports.json _service_create_delete.js", 36 | "provisioning_e2e": "mocha --reporter mocha-multi-reporters --reporter-options configFile=../../mocha-reports.json _provisioning_e2e.js", 37 | "lint": "jshint --show-non-errors .", 38 | "alltest": "mocha -- _*.js", 39 | "e2e": "npm -s run lint && npm -s run alltest" 40 | }, 41 | "engines": { 42 | "node": ">= 14.0.0" 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 | } -------------------------------------------------------------------------------- /provisioning/service/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | dist/**/*.map 7 | .nyc_output -------------------------------------------------------------------------------- /provisioning/service/iotprovisioningservice.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 { ProvisioningServiceClient } from './dist/provisioningserviceclient'; 5 | -------------------------------------------------------------------------------- /provisioning/service/iotprovisioningservice.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 Provisioning Service SDK for Node.js allows applications to perform 8 | * CRUD operations on enrollments and enrollmentGroups as well as deleting device registration 9 | * status objects. 10 | * @module azure-iot-provisioning-service 11 | */ 12 | module.exports = { 13 | ProvisioningServiceClient: require('./dist/provisioningserviceclient.js').ProvisioningServiceClient 14 | }; -------------------------------------------------------------------------------- /provisioning/service/samples/create_enrollment_group.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 fs = require('fs'); 6 | 7 | var provisioningServiceClient = require('azure-iot-provisioning-service').ProvisioningServiceClient; 8 | 9 | var argv = require('yargs') 10 | .usage('Usage: $0 --connectionstring --certificagte ') 11 | .option('connectionstring', { 12 | alias: 'c', 13 | describe: 'The connection string for the Device Provisioning instance', 14 | type: 'string', 15 | demandOption: true 16 | }) 17 | .option('certificate', { 18 | alias: 'ce', 19 | describe: 'certificated used for group enrollment', 20 | type: 'string', 21 | demandOption: true 22 | }) 23 | .argv; 24 | 25 | var connectionString = argv.connectionString; 26 | var certificate = argv.certificate; 27 | var serviceClient = provisioningServiceClient.fromConnectionString(connectionString); 28 | 29 | var enrollment = { 30 | enrollmentGroupId: 'first', 31 | attestation: { 32 | type: 'x509', 33 | x509: { 34 | signingCertificates: { 35 | primary: { 36 | certificate: fs.readFileSync(certificate, 'utf-8').toString() 37 | } 38 | } 39 | } 40 | }, 41 | provisioningStatus: 'disabled' 42 | }; 43 | 44 | serviceClient.createOrUpdateEnrollmentGroup(enrollment, function (err, enrollmentResponse) { 45 | if (err) { 46 | console.log('error creating the group enrollment: ' + err); 47 | } else { 48 | console.log("enrollment record returned: " + JSON.stringify(enrollmentResponse, null, 2)); 49 | enrollmentResponse.provisioningStatus = 'enabled'; 50 | serviceClient.createOrUpdateEnrollmentGroup(enrollmentResponse, function (err, enrollmentResponse) { 51 | if (err) { 52 | console.log('error updating the group enrollment: ' + err); 53 | } else { 54 | console.log("updated enrollment record returned: " + JSON.stringify(enrollmentResponse, null, 2)); 55 | } 56 | }); 57 | } 58 | }); -------------------------------------------------------------------------------- /provisioning/service/samples/create_individual_symmetric_enrollment.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 | var provisioningServiceClient = require('azure-iot-provisioning-service').ProvisioningServiceClient; 5 | 6 | var argv = require('yargs') 7 | .usage('Usage: $0 --deviceid --connectionstring --webhookurl ') 8 | .option('deviceid', { 9 | alias: 'd', 10 | describe: 'Unique identifier for the device that shall be created', 11 | type: 'string', 12 | demandOption: true 13 | }) 14 | .option('connectionstring', { 15 | alias: 'c', 16 | describe: 'The connection string for the Device Provisioning instance', 17 | type: 'string', 18 | demandOption: true 19 | }) 20 | .option('webhookurl', { 21 | alias: 'w', 22 | describe: 'web url of the azure function', 23 | type: 'string', 24 | demandOption: true 25 | }) 26 | .argv; 27 | 28 | var deviceID = argv.deviceid; 29 | var connectionString = argv.connectionstring; 30 | var webHookUrl = argv.webhookurl; 31 | 32 | var serviceClient = provisioningServiceClient.fromConnectionString(connectionString); 33 | 34 | var enrollment = { 35 | registrationId: deviceID, 36 | deviceID: deviceID, 37 | attestation: { 38 | type: 'symmetricKey' 39 | }, 40 | provisioningStatus: 'enabled', 41 | allocationPolicy: 'custom', 42 | customAllocationDefinition: { 43 | webhookUrl: webHookUrl, 44 | apiVersion: '2019-03-31' 45 | } 46 | }; 47 | 48 | serviceClient.createOrUpdateIndividualEnrollment(enrollment, function (err, enrollmentResponse) { 49 | if (err) { 50 | console.log('error creating the individual enrollment: ' + err); 51 | } else { 52 | console.log("enrollment record returned: " + JSON.stringify(enrollmentResponse, null, 2)); 53 | } 54 | }); 55 | -------------------------------------------------------------------------------- /provisioning/service/samples/create_individual_tpm_enrollment.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 provisioningServiceClient = require('azure-iot-provisioning-service').ProvisioningServiceClient; 6 | 7 | var argv = require('yargs') 8 | .usage('Usage: $0 --endorsementkey --connectionstring ') 9 | .option('endorsementKey', { 10 | alias: 'e', 11 | describe: 'Endorsment key for TPM', 12 | type: 'string', 13 | demandOption: true 14 | }) 15 | .option('connectionstring', { 16 | alias: 'c', 17 | describe: 'The connection string for the Device Provisioning instance', 18 | type: 'string', 19 | demandOption: true 20 | }) 21 | .argv; 22 | 23 | var endorsementKey = argv.endorsementKey; 24 | var connectionString = argv.connectionString; 25 | var serviceClient = provisioningServiceClient.fromConnectionString(connectionString); 26 | 27 | var enrollment = { 28 | registrationId: 'first', 29 | attestation: { 30 | type: 'tpm', 31 | tpm: { 32 | endorsementKey: endorsementKey 33 | } 34 | } 35 | }; 36 | 37 | serviceClient.createOrUpdateIndividualEnrollment(enrollment, function (err, enrollmentResponse) { 38 | if (err) { 39 | console.log('error creating the individual enrollment: ' + err); 40 | } else { 41 | console.log("enrollment record returned: " + JSON.stringify(enrollmentResponse, null, 2)); 42 | } 43 | }); 44 | -------------------------------------------------------------------------------- /provisioning/service/samples/create_individual_x509_enrollment.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 | var fs = require('fs'); 5 | var provisioningServiceClient = require('azure-iot-provisioning-service').ProvisioningServiceClient; 6 | const path = require('path'); 7 | 8 | var argv = require('yargs') 9 | .usage('Usage: $0 --deviceid --connectionstring ') 10 | .option('deviceid', { 11 | alias: 'd', 12 | describe: 'Unique identifier for the device that shall be created', 13 | type: 'string', 14 | demandOption: true 15 | }) 16 | .option('connectionstring', { 17 | alias: 'c', 18 | describe: 'The connection string for the Device Provisioning instance', 19 | type: 'string', 20 | demandOption: true 21 | }) 22 | .argv; 23 | 24 | var deviceID = argv.deviceid; 25 | var connectionString = argv.connectionstring; 26 | 27 | var serviceClient = provisioningServiceClient.fromConnectionString(connectionString); 28 | 29 | var certFile = path.join(__dirname, "cert", deviceID + "-cert.pem"); 30 | 31 | if (!fs.existsSync(certFile)) { 32 | console.log('Certificate File not found:' + certFile); 33 | process.exit(); 34 | } else { 35 | var certificate = fs.readFileSync(certFile, 'utf-8').toString(); 36 | } 37 | 38 | var enrollment = { 39 | registrationId: deviceID, 40 | deviceID: deviceID, 41 | attestation: { 42 | type: 'x509', 43 | x509: { 44 | clientCertificates: { 45 | primary: { 46 | certificate: certificate 47 | } 48 | } 49 | } 50 | } 51 | }; 52 | 53 | serviceClient.createOrUpdateIndividualEnrollment(enrollment, function (err, enrollmentResponse) { 54 | if (err) { 55 | console.log('error creating the individual enrollment: ' + err); 56 | } else { 57 | console.log("enrollment record returned: " + JSON.stringify(enrollmentResponse, null, 2)); 58 | } 59 | }); 60 | -------------------------------------------------------------------------------- /provisioning/service/samples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-provisioning-service-samples", 3 | "version": "0.0.1", 4 | "description": "Azure IoT SDK - Provisioning Service Client samples", 5 | "author": "Microsoft Corporation", 6 | "license": "MIT", 7 | "dependencies": { 8 | "@azure/identity": "^2.0.0", 9 | "azure-iot-provisioning-service": "1.10.1", 10 | "yargs": "^15.3.1" 11 | }, 12 | "devDependencies": { 13 | "jshint": "^2.13.4" 14 | }, 15 | "engines": { 16 | "node": ">= 14.0.0" 17 | }, 18 | "scripts": { 19 | "npmlockrefresh": "npm i --package-lock-only", 20 | "lint": "jshint --show-non-errors ." 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/Azure/azure-iot-sdk-node.git" 25 | }, 26 | "bugs": { 27 | "url": "https://github.com/Azure/azure-iot-sdk-node/issues" 28 | }, 29 | "homepage": "https://github.com/Azure/azure-iot-sdk-node#readme" 30 | } -------------------------------------------------------------------------------- /provisioning/service/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "target":"es2018", 5 | "module": "commonjs", 6 | "sourceMap": true, 7 | "declaration": true, 8 | "noUnusedLocals": true, 9 | "noUnusedParameters": true, 10 | "removeComments": false 11 | }, 12 | "include": [ 13 | "./src/**/*.ts" 14 | ], 15 | "exclude": [ 16 | "./dist", 17 | "./samples" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /provisioning/tools/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-provisioning-device-tools", 3 | "version": "0.0.1", 4 | "private": true, 5 | "description": "Build tools for the Azure IoT Hub Node.js SDK Build", 6 | "main": "create_test_cert.js", 7 | "scripts": { 8 | "lint": "jshint --show-non-errors ." 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/azure/azure-iot-sdk-node.git" 13 | }, 14 | "author": "Microsoft Corporation", 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/azure/azure-iot-sdk-node/issues" 18 | }, 19 | "homepage": "https://github.com/azure/azure-iot-sdk-node#readme", 20 | "dependencies": { 21 | "async": "^3.2.3", 22 | "es5-ext": "0.10.53", 23 | "camelcase": "^4.1.0", 24 | "chalk": "^1.1.3", 25 | "pem": "^1.14.2", 26 | "yargs": "^15.3.1" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /provisioning/transport/amqp/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | dist/**/*.map 7 | .nyc_output -------------------------------------------------------------------------------- /provisioning/transport/amqp/devdoc/sasl_tpm_requirements.md: -------------------------------------------------------------------------------- 1 | # SaslTpm Requirements 2 | 3 | The `SaslTpm` class provides TPM sasl functionality for the AMQP transport. 4 | 5 | # Internal API 6 | 7 | These methods are used by the other objects of the SDK but are not public API for the SDK user to call. 8 | 9 | ## constructor(idScope: string, registrationId: string, endorsementKey: Buffer, storageRootKey: Buffer, getSasToken: GetSasToken); 10 | 11 | **SRS_NODE_PROVISIONING_AMQP_SASL_TPM_18_001: [** The `SaslTpm` constructor shall accept the following parameters: 12 | `idScope` - the idScope for the provisioning service instance 13 | `registrationId` - the registrationId for the device being registered 14 | `endorsementKey` - the endorsement key which was acquired from the TPM 15 | `storageRootKey` - the storage root key which was acquired from the TPM 16 | `getSasToken` - The callback to call when the challenge has been completed and the caller needs to formulate the response. **]** 17 | 18 | 19 | ## start(callback: (err?: Error, response?: any) => void): void; 20 | 21 | **SRS_NODE_PROVISIONING_AMQP_SASL_TPM_18_002: [** `start` shall call its callback with the init frame content. **]** 22 | 23 | ## step(challenge: any, callback: (err?: Error, response?: any) => void): void; 24 | 25 | **SRS_NODE_PROVISIONING_AMQP_SASL_TPM_18_003: [** If `step` is called with a 1 byte challenge, it shall call its callback with the the initial response that was passed into the constructor. **]** 26 | 27 | **SRS_NODE_PROVISIONING_AMQP_SASL_TPM_18_004: [** If `step` is called with a first byte that has 1 in the most significant bit, it shall append the challenge to the full challenge buffer and call its callback with `\u0000` **]** 28 | 29 | **SRS_NODE_PROVISIONING_AMQP_SASL_TPM_18_005: [** If `step` is called with a first byte that has 11 in the most significant bits, it shall call the challenge callback with the full challenge buffer. **]** 30 | 31 | **SRS_NODE_PROVISIONING_AMQP_SASL_TPM_18_006: [** If `ChallengeResponseCallback` is called without passing an error, the final `step` promise shall call its callback with the SAS Token. **]** 32 | 33 | **SRS_NODE_PROVISIONING_AMQP_SASL_TPM_18_007: [** If `ChallengeResponseCallback` is called with an error, `step` shall call its callback with an error. **]** 34 | -------------------------------------------------------------------------------- /provisioning/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 './dist/amqp'; 5 | export { AmqpWs } from './dist/amqp_ws'; 6 | -------------------------------------------------------------------------------- /provisioning/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-provisioning-amqp` module provides support for the AMQP protocol to the Azure Device Provisoning Service. 8 | * 9 | * @module azure-iot-provisioning-amqp 10 | * @requires module:azure-iot-amqp-base 11 | * @requires module:azure-iot-common 12 | */ 13 | 14 | module.exports = { 15 | Amqp: require('./dist/amqp.js').Amqp, 16 | AmqpWs: require('./dist/amqp_ws.js').AmqpWs, 17 | }; 18 | -------------------------------------------------------------------------------- /provisioning/transport/amqp/readme.md: -------------------------------------------------------------------------------- 1 | This package (**azure-iot-provisioning-device-amqp**) provides the AMQP and AMQP over Websocket transports that can be used to communicate with the Azure IoT Hub Device Provisioning Service. Please note that the AMQP transport supports both X509 and TPM authentication. 2 | 3 | [![npm version](https://badge.fury.io/js/azure-iot-provisioning-device.svg)](https://badge.fury.io/js/azure-iot-provisioning-device) 4 | 5 | ## Install 6 | 7 | There are at least 3 different packages involved when writing code to take advantage of the Azure IoT Hub Device Provisioning Service: 8 | - The "client" package that will be used to create a provisioning client. This is the **azure-iot-provisioning-device** package. 9 | - the "transport" package that will decide which protocol will be used to communicate with the provisioning service. One of **azure-iot-provisioning-device-amqp** (this package), **azure-iot-provisioning-device-mqtt**, or **azure-iot-provisioning-device-http**. Please note that X509 authentication is supported with all protocols but TPM authentication is supported only with AMQP and HTTP. 10 | - The "security client" package that will be used to interface with whatever type of security (x509 or TPM) is used to authenticate the device. 11 | 12 | For example: 13 | ``` 14 | npm install --save azure-iot-provisioning-device 15 | npm install --save azure-iot-provisioning-device-amqp # Or -mqtt or -http 16 | npm install --save azure-iot-security-x509 # Or -tpm 17 | ``` 18 | 19 | ## Getting Started 20 | 21 | To get started please read our [Overview of the Device Provisioning Service](https://docs.microsoft.com/en-us/azure/iot-dps/about-iot-dps) and visit [our tutorials pages](https://docs.microsoft.com/en-us/azure/iot-dps/tutorial-set-up-cloud) 22 | 23 | -------------------------------------------------------------------------------- /provisioning/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 as Base } from 'azure-iot-amqp-base'; 7 | import { RegistrationRequest } from 'azure-iot-provisioning-device'; 8 | import { Amqp } from './amqp'; 9 | 10 | /** 11 | * Transport used to provision a device over AMQP over Websockets. 12 | */ 13 | export class AmqpWs extends Amqp { 14 | /** 15 | * @private 16 | */ 17 | constructor(amqpBase?: Base) { 18 | super(amqpBase); 19 | } 20 | 21 | /** 22 | * @private 23 | */ 24 | protected _getConnectionUri(request: RegistrationRequest): string { 25 | return 'wss://' + request.provisioningHost + ':443/$iothub/websocket'; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /provisioning/transport/amqp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "target":"es2018", 5 | "module": "commonjs", 6 | "sourceMap": true, 7 | "declaration": true, 8 | "noUnusedLocals": true, 9 | "noUnusedParameters": true, 10 | "removeComments": false 11 | }, 12 | "include": [ 13 | "./src/**/*.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /provisioning/transport/http/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | dist/**/*.map 7 | .nyc_output -------------------------------------------------------------------------------- /provisioning/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 './dist/http'; 5 | 6 | -------------------------------------------------------------------------------- /provisioning/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-provisioning-http` module provides support for the HTTPS protocol to the Azure Device Provisoning Service. 8 | * 9 | * @module azure-iot-provisioning-http 10 | * @requires module:azure-iot-http-base 11 | * @requires module:azure-iot-common 12 | */ 13 | 14 | module.exports = { 15 | Http: require('./dist/http').Http 16 | }; -------------------------------------------------------------------------------- /provisioning/transport/http/readme.md: -------------------------------------------------------------------------------- 1 | This package (**azure-iot-provisioning-device-http**) provides the HTTP transports that can be used to communicate with the Azure IoT Hub Device Provisioning Service. Please note that the HTTP transport supports both X509 and TPM authentication. 2 | 3 | [![npm version](https://badge.fury.io/js/azure-iot-provisioning-device.svg)](https://badge.fury.io/js/azure-iot-provisioning-device) 4 | 5 | ## Install 6 | 7 | There are at least 3 different packages involved when writing code to take advantage of the Azure IoT Hub Device Provisioning Service: 8 | - The "client" package that will be used to create a provisioning client. This is the **azure-iot-provisioning-device** package. 9 | - the "transport" package that will decide which protocol will be used to communicate with the provisioning service. One of **azure-iot-provisioning-device-amqp**, **azure-iot-provisioning-device-mqtt**, or **azure-iot-provisioning-device-http** (this package). Please note that X509 authentication is supported with all protocols but TPM authentication is supported only with AMQP and HTTP. 10 | - The "security client" package that will be used to interface with whatever type of security (x509 or TPM) is used to authenticate the device. 11 | 12 | For example: 13 | ``` 14 | npm install --save azure-iot-provisioning-device 15 | npm install --save azure-iot-provisioning-device-amqp # Or -mqtt or -http 16 | npm install --save azure-iot-security-x509 # Or -tpm 17 | ``` 18 | 19 | ## Getting Started 20 | 21 | To get started please read our [Overview of the Device Provisioning Service](https://docs.microsoft.com/en-us/azure/iot-dps/about-iot-dps) and visit [our tutorials pages](https://docs.microsoft.com/en-us/azure/iot-dps/tutorial-set-up-cloud) 22 | 23 | -------------------------------------------------------------------------------- /provisioning/transport/http/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "target":"es2018", 5 | "module": "commonjs", 6 | "sourceMap": true, 7 | "declaration": true, 8 | "noUnusedLocals": true, 9 | "noUnusedParameters": true, 10 | "removeComments": false 11 | }, 12 | "include": [ 13 | "./src/**/*.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /provisioning/transport/http/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-provisioning-http", 3 | "main": "index.d.ts", 4 | "dependencies": {}, 5 | "globalDependencies": { 6 | "node": "registry:dt/node#6.0.0+20160813124416" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /provisioning/transport/mqtt/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | dist/**/*.map 7 | .nyc_output -------------------------------------------------------------------------------- /provisioning/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 | export { Mqtt } from './dist/mqtt'; 5 | export { MqttWs } from './dist/mqtt_ws'; 6 | 7 | -------------------------------------------------------------------------------- /provisioning/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 | /** 7 | * The `azure-iot-provisioning-device-mqtt` module provides support for the MQTT protocol to the Azure Device Provisoning Service. 8 | * 9 | * @module azure-iot-provisioning-device-mqtt 10 | * @requires module:azure-iot-mqtt-base 11 | * @requires module:azure-iot-common 12 | */ 13 | 14 | module.exports = { 15 | Mqtt: require('./dist/mqtt.js').Mqtt, 16 | MqttWs: require('./dist/mqtt_ws.js').MqttWs 17 | }; 18 | -------------------------------------------------------------------------------- /provisioning/transport/mqtt/readme.md: -------------------------------------------------------------------------------- 1 | This package (**azure-iot-provisioning-device-mqtt**) provides the MQTT and MQTT over Websocket transports that can be used to communicate with the Azure IoT Hub Device Provisioning Service. Please note that the MQTT transport only supports X509 authentication. 2 | 3 | [![npm version](https://badge.fury.io/js/azure-iot-provisioning-device.svg)](https://badge.fury.io/js/azure-iot-provisioning-device) 4 | 5 | ## Install 6 | 7 | There are at least 3 different packages involved when writing code to take advantage of the Azure IoT Hub Device Provisioning Service: 8 | - The "client" package that will be used to create a provisioning client. This is the **azure-iot-provisioning-device** package. 9 | - the "transport" package that will decide which protocol will be used to communicate with the provisioning service. One of **azure-iot-provisioning-device-amqp**, **azure-iot-provisioning-device-mqtt** (this package), or **azure-iot-provisioning-device-http**. Please note that X509 authentication is supported with all protocols but TPM authentication is supported only with AMQP and HTTP. 10 | - The "security client" package that will be used to interface with whatever type of security (x509 or TPM) is used to authenticate the device. 11 | 12 | For example: 13 | ``` 14 | npm install --save azure-iot-provisioning-device 15 | npm install --save azure-iot-provisioning-device-amqp # Or -mqtt or -http 16 | npm install --save azure-iot-security-x509 # Or -tpm 17 | ``` 18 | 19 | ## Getting Started 20 | 21 | To get started please read our [Overview of the Device Provisioning Service](https://docs.microsoft.com/en-us/azure/iot-dps/about-iot-dps) and visit [our tutorials pages](https://docs.microsoft.com/en-us/azure/iot-dps/tutorial-set-up-cloud) 22 | 23 | -------------------------------------------------------------------------------- /provisioning/transport/mqtt/src/mqtt_ws.ts: -------------------------------------------------------------------------------- 1 | 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 | 'use strict'; 6 | 7 | import { Mqtt } from './mqtt'; 8 | import { RegistrationRequest } from 'azure-iot-provisioning-device'; 9 | import { MqttBase } from 'azure-iot-mqtt-base'; 10 | 11 | /** 12 | * Transport used to provision a device over MQTT over Websockets. 13 | */ 14 | export class MqttWs extends Mqtt { 15 | 16 | /** 17 | * @private 18 | */ 19 | constructor(mqttBase?: MqttBase) { 20 | super(mqttBase); 21 | } 22 | 23 | /** 24 | * @private 25 | */ 26 | /* Codes_SRS_NODE_PROVISIONING_MQTT_18_049: [ When connecting using websockets, `Mqtt`Ws shall set the uri passed into the transport to 'wss://:443/$iothub/websocket'.] */ 27 | protected _getConnectionUri(request: RegistrationRequest): string { 28 | return 'wss://' + request.provisioningHost + ':443/$iothub/websocket'; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /provisioning/transport/mqtt/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "target":"es2018", 5 | "module": "commonjs", 6 | "sourceMap": true, 7 | "declaration": true, 8 | "noUnusedLocals": true, 9 | "noUnusedParameters": true, 10 | "removeComments": false 11 | }, 12 | "include": [ 13 | "./src/**/*.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /sdklab/longhaultests/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /sdklab/longhaultests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "longhaultests", 3 | "version": "0.0.1", 4 | "description": "Long haul tests for the Azure IoT SDKs for Node.js", 5 | "main": "./lib/iothub_longhaul.js", 6 | "bin": "./lib/iothub_longhaul.js", 7 | "scripts": { 8 | "lint": "eslint src --ext .ts -f visualstudio", 9 | "build": "tsc", 10 | "setup_links": "npm link azure-iot-common azure-iot-device azure-iot-device-amqp azure-iot-device-mqtt azure-iot-device-http azure-iothub", 11 | "start": "node dist/iothub_longhaul.js" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/azure/azure-iot-sdk-node.git" 16 | }, 17 | "author": "Microsoft Corporation", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/azure/azure-iot-sdk-node/issues" 21 | }, 22 | "homepage": "https://github.com/azure/azure-iot-sdk-node#readme", 23 | "devDependencies": { 24 | "@types/node": "^16.10.2", 25 | "@types/uuid": "^3.4.5", 26 | "encoding": "^0.1.13", 27 | "eslint": "^8.26.0", 28 | "@typescript-eslint/eslint-plugin": "^5.41.0", 29 | "@typescript-eslint/eslint-plugin-tslint": "^5.41.0", 30 | "@typescript-eslint/parser": "^5.41.0", 31 | "eslint-plugin-jsdoc": "^39.3.25", 32 | "eslint-plugin-mocha": "^10.1.0", 33 | "eslint-plugin-no-null": "^1.0.2", 34 | "eslint-plugin-no-only-tests": "^3.1.0", 35 | "eslint-plugin-promise": "^6.1.1", 36 | "eslint-plugin-security": "^1.5.0", 37 | "typescript": "4.4.4" 38 | }, 39 | "dependencies": { 40 | "async": "^3.2.3", 41 | "azure-iot-common": "1.13.2", 42 | "azure-iot-device": "1.18.3", 43 | "azure-iot-device-amqp": "1.14.3", 44 | "azure-iot-device-http": "1.14.3", 45 | "azure-iot-device-mqtt": "1.16.3", 46 | "azure-iothub": "1.15.1", 47 | "debug": "^4.3.1", 48 | "uuid": "^8.3.2" 49 | } 50 | } -------------------------------------------------------------------------------- /sdklab/longhaultests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "./src/**/*.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /sdklab/mean_time_recovery/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /sdklab/mean_time_recovery/aedes_server.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 | // This is all fairly simple MQTT broker code. Even the extra event handlers are not necessary beyond giving some debugs. All it's doing is acting as a dumb broker that receives and acknowledges packets. 5 | 6 | "use strict"; 7 | 8 | const fs = require("fs"); 9 | const aedes = require("aedes")(); 10 | const debug = require("debug")("aedes_server"); 11 | 12 | const port = 8883; 13 | 14 | const options = { 15 | key: fs.readFileSync("./key.pem"), 16 | cert: fs.readFileSync("./certificate.pem"), 17 | }; 18 | 19 | const server = require("tls").createServer(options, aedes.handle); 20 | 21 | server.listen(port, function () { 22 | debug(`server started and listening on port ${port}`); 23 | }); 24 | 25 | aedes.on("clientError", function (client, err) { 26 | debug("client error", client.id, err.message, err.stack); 27 | }); 28 | 29 | aedes.on("connectionError", function (client, err) { 30 | debug("client error", client, err.message, err.stack); 31 | }); 32 | 33 | aedes.on("publish", function (packet, client) { 34 | if (packet && packet.payload) { 35 | debug(`publish packet: ${packet.payload.toString()}`); 36 | } 37 | if (client) { 38 | debug(`message from client ${client.id}`); 39 | } 40 | }); 41 | 42 | aedes.on("subscribe", function (subscriptions, client) { 43 | if (client) { 44 | debug( 45 | `subscribe from client ${JSON.stringify(subscriptions)} ${client.id}` 46 | ); 47 | } 48 | }); 49 | 50 | aedes.on("client", function (client) { 51 | debug(`new client ${client.id}`); 52 | }); 53 | -------------------------------------------------------------------------------- /sdklab/mean_time_recovery/orchestrator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-iot-sdk-node/b7ad22ad79baa3069cc16014bef337b65a0d0e97/sdklab/mean_time_recovery/orchestrator.png -------------------------------------------------------------------------------- /sdklab/mean_time_recovery/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mean_time_recovery", 3 | "version": "1.0.0", 4 | "description": "metric analysis of mean time to recovery for device code", 5 | "main": "ochestrator.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "lint": "eslint . --ext .js -f visualstudio" 9 | }, 10 | "author": "", 11 | "license": "MIT", 12 | "dependencies": { 13 | "async": "^3.2.3", 14 | "aedes": "^0.46.3", 15 | "azure-iot-common": "1.13.2", 16 | "azure-iot-device": "1.18.3", 17 | "azure-iot-device-mqtt": "1.16.3", 18 | "@colors/colors": "^1.5.0" 19 | }, 20 | "devDependencies": { 21 | "eslint": "^8.26.0", 22 | "@typescript-eslint/eslint-plugin": "^5.41.0", 23 | "@typescript-eslint/eslint-plugin-tslint": "^5.41.0", 24 | "@typescript-eslint/parser": "^5.41.0", 25 | "eslint-plugin-jsdoc": "^39.3.25", 26 | "eslint-plugin-mocha": "^10.1.0", 27 | "eslint-plugin-no-null": "^1.0.2", 28 | "eslint-plugin-no-only-tests": "^3.1.0", 29 | "eslint-plugin-promise": "^6.1.1", 30 | "eslint-plugin-security": "^1.5.0", 31 | "encoding": "^0.1.13" 32 | } 33 | } -------------------------------------------------------------------------------- /sdklab/stress_fault/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /sdklab/stress_fault/.prettierignore: -------------------------------------------------------------------------------- 1 | build 2 | dist 3 | node_modules 4 | .eslintrc.js 5 | *.json 6 | *.md 7 | -------------------------------------------------------------------------------- /sdklab/stress_fault/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "tabWidth": 2, 4 | "trailingComma": "es5", 5 | "semi": true, 6 | "singleQuote": true, 7 | "quoteProps": "consistent", 8 | "bracketSpacing": true, 9 | "arrowParens": "always" 10 | } 11 | -------------------------------------------------------------------------------- /sdklab/stress_fault/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stressFault", 3 | "version": "0.0.1", 4 | "description": "Long haul tests for the Azure IoT SDKs for Node.js", 5 | "main": "./dist/stress_fault.js", 6 | "bin": "./dist/stress_fault.js", 7 | "scripts": { 8 | "prettier": "npx prettier --write .", 9 | "lint": "eslint src --ext .ts -f visualstudio", 10 | "build": "tsc", 11 | "start": "node dist/stress_fault.js", 12 | "prep": "npm run prettier && npm run lint && npm run build", 13 | "run": "npm run prep && npm run start" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/azure/azure-iot-sdk-node.git" 18 | }, 19 | "author": "Microsoft Corporation", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/azure/azure-iot-sdk-node/issues" 23 | }, 24 | "homepage": "https://github.com/azure/azure-iot-sdk-node#readme", 25 | "devDependencies": { 26 | "@types/node": "^16.10.2", 27 | "@types/uuid": "^3.4.5", 28 | "encoding": "^0.1.13", 29 | "eslint": "^8.26.0", 30 | "@typescript-eslint/eslint-plugin": "^5.41.0", 31 | "@typescript-eslint/eslint-plugin-tslint": "^5.41.0", 32 | "@typescript-eslint/parser": "^5.41.0", 33 | "eslint-plugin-jsdoc": "^39.3.25", 34 | "eslint-plugin-mocha": "^10.1.0", 35 | "eslint-plugin-no-null": "^1.0.2", 36 | "eslint-plugin-no-only-tests": "^3.1.0", 37 | "eslint-plugin-promise": "^6.1.1", 38 | "eslint-plugin-security": "^1.5.0", 39 | "typescript": "4.4.4" 40 | }, 41 | "dependencies": { 42 | "async": "^3.2.3", 43 | "azure-iot-common": "1.13.2", 44 | "azure-iot-device": "1.18.3", 45 | "azure-iot-device-amqp": "1.14.3", 46 | "azure-iot-device-http": "1.14.3", 47 | "azure-iot-device-mqtt": "1.16.3", 48 | "azure-iothub": "1.15.1", 49 | "debug": "^4.3.1", 50 | "pem": "^1.14.2", 51 | "uuid": "^8.3.2" 52 | } 53 | } -------------------------------------------------------------------------------- /sdklab/stress_fault/src/faults.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 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 | export const amqpFaults = [ 6 | { 7 | operationType: 'KillTcp', 8 | closeReason: ' severs the TCP connection ', 9 | }, 10 | { 11 | operationType: 'KillAmqpConnection', 12 | closeReason: ' severs the AMQP connection ', 13 | }, 14 | { 15 | operationType: 'KillAmqpSession', 16 | closeReason: ' severs the AMQP session ', 17 | }, 18 | { 19 | operationType: 'KillAmqpCBSLinkReq', 20 | closeReason: ' severs AMQP CBS request link ', 21 | }, 22 | { 23 | operationType: 'KillAmqpCBSLinkResp', 24 | closeReason: ' severs AMQP CBS response link ', 25 | }, 26 | { 27 | operationType: 'KillAmqpD2CLink', 28 | closeReason: ' severs AMQP D2C link ', 29 | }, 30 | { 31 | operationType: 'ShutDownAmqp', 32 | closeReason: ' cleanly shutdowns AMQP connection ', 33 | }, 34 | ]; 35 | 36 | export const mqttFaults = [ 37 | { 38 | operationType: 'KillTcp', 39 | closeReason: ' severs the TCP connection ', 40 | }, 41 | { 42 | operationType: 'ShutDownMqtt', 43 | closeReason: ' cleanly shutdowns MQTT connection ', 44 | }, 45 | ]; 46 | -------------------------------------------------------------------------------- /sdklab/stress_fault/src/utils.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 | 'use strict'; 4 | 5 | import { Amqp, AmqpWs } from 'azure-iot-device-amqp'; 6 | import { Mqtt, MqttWs } from 'azure-iot-device-mqtt'; 7 | import { Http } from 'azure-iot-device-http'; 8 | 9 | // Helper function to go from a transport name to an actual transport. 10 | export function getTransport(transport: string): any { 11 | switch (transport.toLowerCase()) { 12 | case 'amqp': 13 | return Amqp; 14 | case 'amqp-ws': 15 | return AmqpWs; 16 | case 'mqtt': 17 | return Mqtt; 18 | case 'mqtt-ws': 19 | return MqttWs; 20 | case 'http': 21 | return Http; 22 | default: 23 | throw new Error('unknown protocol: ' + transport); 24 | } 25 | } 26 | 27 | // Given an interval in milliseconds, return hours, minutes, and seconds as a human readable string. 28 | export function getIntervalString(i: number): string { 29 | let seconds = Math.floor(i / 1000); 30 | 31 | const hours = Math.floor(seconds / 3600); 32 | seconds -= hours * 3600; 33 | 34 | const minutes = Math.floor(seconds / 60); 35 | seconds -= minutes * 60; 36 | 37 | return `${hours} hours, ${minutes} minutes, and ${seconds} seconds`; 38 | } 39 | -------------------------------------------------------------------------------- /sdklab/stress_fault/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "./src/**/*.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /security/symmetric/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /security/symmetric/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | dist/**/*.map 7 | .nyc_output -------------------------------------------------------------------------------- /security/symmetric/devdoc/symmetric_key.md: -------------------------------------------------------------------------------- 1 | # azure-iot-security-symmetric-key.SymmetricKeySecurityClient Requirements 2 | 3 | ## Overview 4 | `SymmetricKeySecurityClient` provides query operations for symmetric key based attestation and a sas token object. 5 | 6 | ## Example usage 7 | 8 | var securityClient = new symmetricKeySecurity.SymmetricKeySecurityClient(); 9 | var provisioningClient = ProvisioningDeviceClient.create(provisioningHost, idScope, new provisioningTransport(), securityClient); 10 | 11 | ### SymmetricKeySecurityClient(registrationId: string, symmetricKey: string) [constructor] 12 | 13 | The `SymmetricKeySecurityClient` constructor initializes a new instance of a `SymmetricKeySecurityClient` object. 14 | 15 | ### getRegistrationId(callback: (err: Error, registrationId: string) => void): void 16 | 17 | **SRS_NODE_SYMMETRIC_KEY_SECURITY_CLIENT_06_004: [** This function returns the `registrationId` for the particular device. **]** 18 | 19 | ### createSharedAccessSignature(idScope: string, callback: (err: Error, sasTokenObject: SharedAccessSignature)) => void): void 20 | 21 | **SRS_NODE_SYMMETRIC_KEY_SECURITY_CLIENT_06_005: [** Will throw `ReferenceError` if `idScope` parameter is falsy. **]** 22 | 23 | **SRS_NODE_SYMMETRIC_KEY_SECURITY_CLIENT_06_006: [** The `idScope` parameter must be of type string. **]** 24 | 25 | **SRS_NODE_SYMMETRIC_KEY_SECURITY_CLIENT_06_007: [** A SharedAccessSignature object shall be returned, based on the `idScope`, and the `registrationId` given in the constructor. **]** 26 | -------------------------------------------------------------------------------- /security/symmetric/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 { SymmetricKeySecurityClient } from './dist/symmetric_key'; 5 | -------------------------------------------------------------------------------- /security/symmetric/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 | module.exports = { 7 | SymmetricKeySecurityClient : require('./dist/symmetric_key').SymmetricKeySecurityClient 8 | }; 9 | -------------------------------------------------------------------------------- /security/symmetric/readme.md: -------------------------------------------------------------------------------- 1 | Security module used to provide Symmetric Key authentication capabilities to the Azure IoT Hub device client and Azure IoT Hub Provisioning Service device client. 2 | 3 | [![npm version](https://badge.fury.io/js/azure-iot-security-symmetric-key.svg)](https://badge.fury.io/js/azure-iot-security-symmmetric-key) 4 | 5 | ## Install 6 | 7 | There are at least 3 different packages involved when writing code to take advantage of the Azure IoT Hub Device Provisioning Service: 8 | - The "client" package that will be used to create a provisioning client. This is the **azure-iot-provisioning-device** package. 9 | - the "transport" package that will decide which protocol will be used to communicate with the provisioning service. One of **azure-iot-provisioning-device-amqp**, **azure-iot-provisioning-device-mqtt**, or **azure-iot-provisioning-device-http**. Please note that Symmetric Key authentication is supported with all protocols but TPM authentication is supported only with AMQP and HTTP. 10 | - The "security client" package that will be used to interface with whatever type of security (x509, TPM, or Symmetric Key) is used to authenticate the device. This package (**azure-iot-security-symmetric-key**) provides Symmetric Key authentication capabilities. 11 | 12 | For example: 13 | ``` 14 | npm install --save azure-iot-provisioning-device 15 | npm install --save azure-iot-provisioning-device-amqp # Or -mqtt or -http 16 | npm install --save azure-iot-security-symmetric-key 17 | ``` 18 | 19 | ## Getting Started 20 | 21 | To get started please read our [Overview of the Device Provisioning Service](https://docs.microsoft.com/en-us/azure/iot-dps/about-iot-dps) and visit [our tutorials pages](https://docs.microsoft.com/en-us/azure/iot-dps/tutorial-set-up-cloud) 22 | 23 | -------------------------------------------------------------------------------- /security/symmetric/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "./src/**/*.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /security/tpm/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /security/tpm/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | dist/**/*.map 7 | .nyc_output -------------------------------------------------------------------------------- /security/tpm/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 { TpmSecurityClient } from './dist/tpm'; 5 | export { TpmAuthenticationProvider } from './dist/tpm_authentication_provider'; 6 | -------------------------------------------------------------------------------- /security/tpm/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 | module.exports = { 7 | TpmSecurityClient : require('./dist/tpm').TpmSecurityClient, 8 | TpmAuthenticationProvider: require('./dist/tpm_authentication_provider').TpmAuthenticationProvider 9 | }; 10 | -------------------------------------------------------------------------------- /security/tpm/readme.md: -------------------------------------------------------------------------------- 1 | Security module used to provide TPM authentication capabilities to the Azure IoT Hub device client and Azure IoT Hub Provisioning Service device client. 2 | 3 | [![npm version](https://badge.fury.io/js/azure-iot-security-tpm.svg)](https://badge.fury.io/js/azure-iot-security-tpm) 4 | 5 | *This package is currently in development and has not been released yet* 6 | 7 | 8 | -------------------------------------------------------------------------------- /security/tpm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "./src/**/*.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /security/x509/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /security/x509/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | devdoc/ 3 | test/ 4 | samples/ 5 | src/ 6 | dist/**/*.map 7 | .nyc_output -------------------------------------------------------------------------------- /security/x509/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 { X509Security } from './dist/x509'; 5 | -------------------------------------------------------------------------------- /security/x509/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 | module.exports = { 7 | X509Security: require('./dist/x509').X509Security 8 | }; 9 | -------------------------------------------------------------------------------- /security/x509/readme.md: -------------------------------------------------------------------------------- 1 | Security module used to provide X509 authentication capabilities to the Azure IoT Hub device client and Azure IoT Hub Provisioning Service device client. 2 | 3 | [![npm version](https://badge.fury.io/js/azure-iot-security-x509.svg)](https://badge.fury.io/js/azure-iot-security-x509) 4 | 5 | ## Install 6 | 7 | There are at least 3 different packages involved when writing code to take advantage of the Azure IoT Hub Device Provisioning Service: 8 | - The "client" package that will be used to create a provisioning client. This is the **azure-iot-provisioning-device** package. 9 | - the "transport" package that will decide which protocol will be used to communicate with the provisioning service. One of **azure-iot-provisioning-device-amqp**, **azure-iot-provisioning-device-mqtt**, or **azure-iot-provisioning-device-http**. Please note that X509 authentication is supported with all protocols but TPM authentication is supported only with AMQP and HTTP. 10 | - The "security client" package that will be used to interface with whatever type of security (x509 or TPM) is used to authenticate the device. This package (**azure-iot-security-x509**) provides x509 authentication capabilities. 11 | 12 | For example: 13 | ``` 14 | npm install --save azure-iot-provisioning-device 15 | npm install --save azure-iot-provisioning-device-amqp # Or -mqtt or -http 16 | npm install --save azure-iot-security-x509 # Or -tpm 17 | ``` 18 | 19 | ## Getting Started 20 | 21 | To get started please read our [Overview of the Device Provisioning Service](https://docs.microsoft.com/en-us/azure/iot-dps/about-iot-dps) and visit [our tutorials pages](https://docs.microsoft.com/en-us/azure/iot-dps/tutorial-set-up-cloud) 22 | 23 | -------------------------------------------------------------------------------- /security/x509/src/x509.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 { X509 } from 'azure-iot-common'; 6 | 7 | /** 8 | * @private 9 | * X509 security client using user-generated cert for Azure IoT 10 | */ 11 | export class X509Security { 12 | private _cert: X509; 13 | private _registrationId: string; 14 | 15 | /** 16 | * Construct a new X509 security object 17 | * 18 | * @param cert certificate to use 19 | */ 20 | constructor(registrationId: string, cert: X509) { 21 | this._cert = cert; 22 | this._registrationId = registrationId; 23 | } 24 | 25 | /** 26 | * return the X509 certificate 27 | * 28 | * @param callback called when the operation is complete 29 | */ 30 | getCertificate(callback: (err?: Error, cert?: X509) => void): void { 31 | callback(null, this._cert); 32 | } 33 | 34 | /** 35 | * return the registration Id for the device 36 | */ 37 | getRegistrationId(): string { 38 | return this._registrationId; 39 | } 40 | 41 | } 42 | 43 | -------------------------------------------------------------------------------- /security/x509/test/_x509_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 | const X509Security = require('../dist/x509').X509Security; 7 | const assert = require('chai').assert; 8 | 9 | const fakeRegistrationId = 'fake registration id'; 10 | const fakeCert = 'fake certificate'; 11 | 12 | describe('x509', function () { 13 | // eslint-disable-next-line no-invalid-this 14 | this.timeout(1000); 15 | 16 | const obj = new X509Security(fakeRegistrationId, fakeCert); 17 | 18 | describe('getCertificate', function () { 19 | it ('returns the cert', function (callback) { 20 | obj.getCertificate(function (err, cert) { 21 | assert(!err); 22 | assert.equal(cert, fakeCert); 23 | callback(); 24 | }); 25 | }); 26 | }); 27 | 28 | describe('getRegistrationId', function () { 29 | it ('returns the registrationId', function (callback) { 30 | const registrationId = obj.getRegistrationId(); 31 | assert.equal(registrationId, fakeRegistrationId); 32 | callback(); 33 | }); 34 | }); 35 | 36 | }); 37 | -------------------------------------------------------------------------------- /security/x509/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "./src/**/*.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /stresstests/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /stresstests/README.md: -------------------------------------------------------------------------------- 1 | TODO -------------------------------------------------------------------------------- /stresstests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "azure-iot-stresstests", 3 | "description": "Azure IoT Stress Tests", 4 | "author": "Microsoft Corporation", 5 | "version": "1.0.0", 6 | "private": true, 7 | "license": "MIT", 8 | "dependencies": { 9 | "async": "^3.2.3", 10 | "azure-iot-common": "1.13.2", 11 | "azure-iot-device": "1.18.3", 12 | "azure-iot-device-amqp": "1.14.3", 13 | "azure-iot-device-http": "1.14.3", 14 | "azure-iot-device-mqtt": "1.16.3", 15 | "azure-iothub": "1.15.1", 16 | "@azure/event-hubs": "^1.0.8", 17 | "uuid": "^8.3.2", 18 | "debug": "^4.3.1", 19 | "chai": "^4.3.3", 20 | "wtfnode": "^0.9.1" 21 | }, 22 | "devDependencies": { 23 | "mocha": "^9.2.1" 24 | }, 25 | "scripts": { 26 | "lint": "eslint test --ext .js -f visualstudio", 27 | "test": "../node_modules/mocha/bin/_mocha --reporter dot ./test/**/*.js" 28 | }, 29 | "engines": { 30 | "node": ">=14.0.0" 31 | }, 32 | "repository": { 33 | "type": "git", 34 | "url": "https://github.com/Azure/azure-iot-sdk-node.git", 35 | "directory": "stresstests" 36 | }, 37 | "bugs": { 38 | "url": "https://github.com/Azure/azure-iot-sdk-node/issues" 39 | }, 40 | "homepage": "https://github.com/Azure/azure-iot-sdk-node#readme" 41 | } -------------------------------------------------------------------------------- /stresstests/test/config.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 | // const deviceHttp = require('azure-iot-device-http'); 7 | // const deviceAmqp = require('azure-iot-device-amqp'); 8 | const deviceMqtt = require('azure-iot-device-mqtt'); 9 | 10 | module.exports = { 11 | d2c: { 12 | transportsToTest: [ 13 | // deviceHttp.Http, 14 | deviceMqtt.Mqtt, 15 | // deviceMqtt.MqttWs, 16 | // deviceAmqp.Amqp, 17 | // deviceAmqp.AmqpWs, 18 | ], 19 | deviceClientHelperMethodsToUse: [ 20 | 'createDeviceClientSas', 21 | // 'createDeviceClientSymmetricKey', 22 | // 'createDeviceClientX509SelfSigned', 23 | // 'createDeviceClientX509CaSigned', 24 | // 'createModuleClientSas', 25 | // 'createModuleClientSymmetricKey', 26 | ], 27 | telemetryPayloadSizeInBytes: 16 * 1024, 28 | memorySamplingIntervalInMs: 5 * 1000, 29 | peakRssFailureTriggerInBytes: Infinity, 30 | peakTelemetryArrivalTimeFailureTriggerInMs: Infinity, 31 | peakReconnectTimeFailureTriggerInMs: Infinity, 32 | continuousTest: { 33 | testDurationInMs: 120 * 1000, 34 | messagesPerSecond: 30, 35 | }, 36 | allAtOnceTest: { 37 | messageCount: 3000, 38 | elapsedTimeFailureTriggerInMs: 5 * 60 * 1000, 39 | }, 40 | }, 41 | 42 | } 43 | -------------------------------------------------------------------------------- /tls_protocol_version_and_ciphers.md: -------------------------------------------------------------------------------- 1 | # IoT Node SDK TLS 2 | 3 | When using the Azure IoT Node SDK in your application, you may wish to control which version of TLS is used and which ciphers are used by TLS. 4 | 5 | ## How to restrict TLS version 6 | 7 | To restrict the TLS version one will need to set the NODE_OPTIONS environment variable to use the min version of the desired tls value 8 | 9 | ``` 10 | NODE_OPTIONS='--tls-min-v1.2' 11 | ``` 12 | 13 | ## TLS Cipher Suites 14 | 15 | Additionally if you would like to specify a list of ciphers can be restricted by adding a NODE_OPTIONS environment variable 16 | 17 | ``` 18 | NODE_OPTIONS='--tls-cipher-list=[cipher1]' 19 | ``` 20 | 21 | for more information see [Modifying the Default TLS Cipher suite](https://nodejs.org/api/tls.html#tls_modifying_the_default_tls_cipher_suite) 22 | -------------------------------------------------------------------------------- /ts-e2e/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage 7 | -------------------------------------------------------------------------------- /ts-e2e/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-e2e", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "lint": "eslint src --ext .ts -f visualstudio", 8 | "build": "tsc", 9 | "test": "../node_modules/mocha/bin/_mocha --reporter dot \"./dist/**/*.tests.js\"" 10 | }, 11 | "keywords": [], 12 | "author": "Microsoft Corporation", 13 | "license": "MIT", 14 | "dependencies": { 15 | "async": "^3.2.3", 16 | "es5-ext": "0.10.53", 17 | "@azure/event-hubs": "^1.0.8", 18 | "@types/chai": "^3.5.1", 19 | "@types/debug": "^4.1.5", 20 | "@types/mocha": "^2.2.41", 21 | "@types/node": "^16.10.2", 22 | "@types/uuid": "^3.4.5", 23 | "azure-iot-common": "1.13.2", 24 | "azure-iot-device": "1.18.3", 25 | "azure-iot-device-amqp": "1.14.3", 26 | "azure-iot-device-http": "1.14.3", 27 | "azure-iot-device-mqtt": "1.16.3", 28 | "azure-iothub": "1.15.1", 29 | "debug": "^4.3.1", 30 | "typescript": "4.4.4", 31 | "uuid": "^8.3.2", 32 | "uuid-buffer": "^1.0.3" 33 | }, 34 | "devDependencies": { 35 | "chai": "^4.3.3", 36 | "mocha": "^9.2.1", 37 | "eslint": "^8.26.0", 38 | "@typescript-eslint/eslint-plugin": "^5.41.0", 39 | "@typescript-eslint/eslint-plugin-tslint": "^5.41.0", 40 | "@typescript-eslint/parser": "^5.41.0", 41 | "eslint-plugin-jsdoc": "^39.3.25", 42 | "eslint-plugin-mocha": "^10.1.0", 43 | "eslint-plugin-no-null": "^1.0.2", 44 | "eslint-plugin-no-only-tests": "^3.1.0", 45 | "eslint-plugin-promise": "^6.1.1", 46 | "eslint-plugin-security": "^1.5.0" 47 | } 48 | } -------------------------------------------------------------------------------- /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 | // eslint-disable-next-line no-invalid-this 7 | (this as any).timeout(60000); 8 | it('creates a device -> gets it -> updates it -> deletes it', function (testCallback: (err?: Error) => void) { 9 | const testDeviceId = uuid.v4(); 10 | const registry = Registry.fromConnectionString(process.env.IOTHUB_CONNECTION_STRING); 11 | registry.create({ deviceId: testDeviceId }, (err, createDevDesc) => { 12 | if (err) throw err; 13 | assert.strictEqual(createDevDesc.deviceId, testDeviceId); 14 | registry.get(testDeviceId, (err, getDevDesc) => { 15 | if (err) throw err; 16 | assert.strictEqual(getDevDesc.deviceId, testDeviceId); 17 | assert.strictEqual(getDevDesc.status, 'enabled'); 18 | registry.update({ deviceId: testDeviceId, status: 'disabled' }, (_err, updateDevDesc) => { 19 | assert.strictEqual(updateDevDesc.deviceId, testDeviceId); 20 | assert.strictEqual(updateDevDesc.status, 'disabled'); 21 | registry.delete(testDeviceId, (err) => { 22 | if (err) throw err; 23 | registry.get(testDeviceId, (err, _getDevDesc2) => { 24 | assert.instanceOf(err, Error); 25 | testCallback(); 26 | }); 27 | }); 28 | }); 29 | }); 30 | }); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /ts-e2e/src/testUtils.ts: -------------------------------------------------------------------------------- 1 | import { Registry } 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: Buffer.from(uuid.v4()).toString('base64'), 24 | secondaryKey: Buffer.from(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 | -------------------------------------------------------------------------------- /ts-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "./src/**/*.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"es2018", 4 | "module": "commonjs", 5 | "sourceMap": true, 6 | "declaration": true, 7 | "noUnusedLocals": true, 8 | "noUnusedParameters": true, 9 | "removeComments": false 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "version": "1.18.2" 4 | } 5 | ] -------------------------------------------------------------------------------- /vsts/horton-e2e.yaml: -------------------------------------------------------------------------------- 1 | variables: 2 | Horton.FrameworkRoot: $(Agent.BuildDirectory)/e2e-fx 3 | Horton.FrameworkRef: master 4 | Horton.Language: node 5 | Horton.Repo: $(Build.Repository.Uri) 6 | Horton.Commit: $(Build.SourceBranch) 7 | Horton.ForcedImage: '' 8 | 9 | resources: 10 | repositories: 11 | - repository: e2e_fx 12 | type: github 13 | name: Azure/iot-sdks-e2e-fx 14 | ref: refs/heads/master 15 | endpoint: 'GitHub OAuth - az-iot-builder-01' 16 | 17 | jobs: 18 | - template: vsts/templates/jobs-gate-node.yaml@e2e_fx 19 | 20 | 21 | -------------------------------------------------------------------------------- /vsts/node-nightly-linux.yaml: -------------------------------------------------------------------------------- 1 | name: $(BuildID)_$(BuildDefinitionName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r) 2 | resources: 3 | - repo: self 4 | clean: true 5 | 6 | jobs: 7 | - job: Phase_2 8 | displayName: Ubuntu 20.04 - Node 14.x 9 | condition: succeededOrFailed() 10 | pool: 11 | vmImage: 'Ubuntu 20.04' 12 | 13 | steps: 14 | - task: NodeTool@0 15 | displayName: 'Use Node 14.x' 16 | inputs: 17 | versionSpec: '14.x' 18 | 19 | - script: | 20 | npm install --global node-gyp 21 | npm install --global lerna@^6.6.2 22 | npm install 23 | displayName: 'Install Dependencies' 24 | 25 | - script: | 26 | lerna bootstrap --hoist 27 | lerna run build 28 | displayName: 'Bootstrap & Build' 29 | 30 | - script: 'lerna run ci' 31 | displayName: 'Unit & Integration Tests' 32 | env: 33 | IOTHUB_CONNECTION_STRING: $(IOTHUB-CONNECTION-STRING) 34 | 35 | - script: 'lerna run e2e' 36 | displayName: 'E2E Tests' 37 | env: 38 | IOTHUB_CA_ROOT_CERT: $(IOTHUB-CA-ROOT-CERT) 39 | IOTHUB_CA_ROOT_CERT_KEY: $(IOTHUB-CA-ROOT-CERT-KEY) 40 | IOT_PROVISIONING_DEVICE_ENDPOINT: $(IOT-PROVISIONING-DEVICE-ENDPOINT) 41 | IOTHUB_CONNECTION_STRING: $(IOTHUB-CONNECTION-STRING) 42 | STORAGE_CONNECTION_STRING: $(STORAGE-CONNECTION-STRING) 43 | IOT_PROVISIONING_DEVICE_IDSCOPE: $(IOT-PROVISIONING-DEVICE-IDSCOPE) 44 | IOT_PROVISIONING_ROOT_CERT: $(IOT-PROVISIONING-ROOT-CERT) 45 | IOT_PROVISIONING_ROOT_CERT_KEY: $(IOT-PROVISIONING-ROOT-CERT-KEY) 46 | IOT_PROVISIONING_SERVICE_CONNECTION_STRING: $(IOT-PROVISIONING-SERVICE-CONNECTION-STRING) 47 | DPS_CONN_STRING_INVALID_CERT: $(DPS-CONN-STRING-INVALID-CERT) 48 | DPS_GLOBAL_DEVICE_ENDPOINT_INVALID_CERT: $(DPS-GLOBAL-DEVICE-ENDPOINT-INVALID-CERT) 49 | IOTHUB_CONN_STRING_INVALID_CERT: $(IOTHUB-CONN-STRING-INVALID-CERT) 50 | IOTHUB_DEVICE_CONN_STRING_INVALID_CERT: $(IOTHUB-DEVICE-CONN-STRING-INVALID-CERT) 51 | 52 | - task: PublishTestResults@2 53 | displayName: 'Publish Test Results | Mocha' 54 | inputs: 55 | testResultsFiles: '**/test-results.*.xml' 56 | mergeTestResults: true 57 | testRunTitle: 'E2E Tests - Linux' 58 | condition: succeededOrFailed() 59 | --------------------------------------------------------------------------------