Skip to content

Commit

Permalink
Update Service Client Sample to Use Mqtt5 Client (#425)
Browse files Browse the repository at this point in the history
* update service client to use mqtt5

* update ci and identity sample

* improve logs

* setup client id for mqtt5 client

* setup connectProperties

* more service client notes

* update readme
  • Loading branch information
xiazhvera authored Sep 22, 2023
1 parent 24e2ab3 commit 14d1458
Show file tree
Hide file tree
Showing 11 changed files with 340 additions and 26 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,9 @@ jobs:
- name: run Shadow sample
run: |
python3 ./aws-iot-device-sdk-js-v2/utils/run_sample_ci.py --file ./aws-iot-device-sdk-js-v2/.github/workflows/ci_run_shadow_cfg.json
- name: run Mqtt5 Shadow sample
run: |
python3 ./aws-iot-device-sdk-js-v2/utils/run_sample_ci.py --file ./aws-iot-device-sdk-js-v2/.github/workflows/ci_run_shadow_mqtt5_cfg.json
- name: configure AWS credentials (Jobs)
uses: aws-actions/configure-aws-credentials@v1
with:
Expand All @@ -253,6 +256,9 @@ jobs:
- name: run Jobs sample
run: |
python3 ./aws-iot-device-sdk-js-v2/utils/run_sample_ci.py --file ./aws-iot-device-sdk-js-v2/.github/workflows/ci_run_jobs_cfg.json
- name: run Mqtt5 Jobs sample
run: |
python3 ./aws-iot-device-sdk-js-v2/utils/run_sample_ci.py --file ./aws-iot-device-sdk-js-v2/.github/workflows/ci_run_jobs_mqtt5_cfg.json
- name: configure AWS credentials (Fleet provisioning)
uses: aws-actions/configure-aws-credentials@v1
with:
Expand All @@ -264,6 +270,12 @@ jobs:
Sample_UUID=$(python3 -c "import uuid; print (uuid.uuid4())")
python3 ./aws-iot-device-sdk-js-v2/utils/run_sample_ci.py --file ./aws-iot-device-sdk-js-v2/.github/workflows/ci_run_fleet_provisioning_cfg.json --input_uuid ${Sample_UUID}
python3 ./aws-iot-device-sdk-js-v2/utils/delete_iot_thing_ci.py --thing_name "Fleet_Thing_${Sample_UUID}" --region "us-east-1"
- name: run Mqtt5 Fleet Provisioning sample
run: |
echo "Generating UUID for IoT thing"
Sample_UUID=$(python3 -c "import uuid; print (uuid.uuid4())")
python3 ./aws-iot-device-sdk-js-v2/utils/run_sample_ci.py --file ./aws-iot-device-sdk-js-v2/.github/workflows/ci_run_fleet_provisioning_mqtt5_cfg.json --input_uuid ${Sample_UUID}
python3 ./aws-iot-device-sdk-js-v2/utils/delete_iot_thing_ci.py --thing_name "Fleet_Thing_${Sample_UUID}" --region "us-east-1"
- name: configure AWS credentials (MQTT5 PubSub)
uses: aws-actions/configure-aws-credentials@v1
with:
Expand Down
34 changes: 34 additions & 0 deletions .github/workflows/ci_run_fleet_provisioning_mqtt5_cfg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"language": "Javascript",
"sample_file": "./aws-iot-device-sdk-js-v2/samples/node/fleet_provisioning",
"sample_region": "us-east-1",
"sample_main_class": "",
"arguments": [
{
"name": "--endpoint",
"secret": "ci/endpoint"
},
{
"name": "--cert",
"secret": "ci/FleetProvisioning/cert",
"filename": "tmp_certificate.pem"
},
{
"name": "--key",
"secret": "ci/FleetProvisioning/key",
"filename": "tmp_key.pem"
},
{
"name": "--template_name",
"data": "CI_FleetProvisioning_Template"
},
{
"name": "--template_parameters",
"data": "{\"SerialNumber\":\"$INPUT_UUID\"}"
},
{
"name": "--mqtt5",
"data": "true"
}
]
}
30 changes: 30 additions & 0 deletions .github/workflows/ci_run_jobs_mqtt5_cfg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"language": "Javascript",
"sample_file": "./aws-iot-device-sdk-js-v2/samples/node/jobs",
"sample_region": "us-east-1",
"sample_main_class": "",
"arguments": [
{
"name": "--endpoint",
"secret": "ci/endpoint"
},
{
"name": "--cert",
"secret": "ci/Jobs/cert",
"filename": "tmp_certificate.pem"
},
{
"name": "--key",
"secret": "ci/Jobs/key",
"filename": "tmp_key.pem"
},
{
"name": "--thing_name",
"data": "CI_Jobs_Thing"
},
{
"name": "--mqtt5",
"data": "true"
}
]
}
34 changes: 34 additions & 0 deletions .github/workflows/ci_run_shadow_mqtt5_cfg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"language": "Javascript",
"sample_file": "./aws-iot-device-sdk-js-v2/samples/node/shadow",
"sample_region": "us-east-1",
"sample_main_class": "",
"arguments": [
{
"name": "--endpoint",
"secret": "ci/endpoint"
},
{
"name": "--cert",
"secret": "ci/Shadow/cert",
"filename": "tmp_certificate.pem"
},
{
"name": "--key",
"secret": "ci/Shadow/key",
"filename": "tmp_key.pem"
},
{
"name": "--thing_name",
"data": "CI_Shadow_Thing"
},
{
"name": "--is_ci",
"data": "true"
},
{
"name": "--mqtt5",
"data": "true"
}
]
}
50 changes: 50 additions & 0 deletions samples/node/fleet_provisioning/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ npm install
node ./index.js --endpoint <endpoint> --cert <file> --key <file> --template_name <template name> --template_parameters <template parameters>
```

You can also run the sample with `--mqtt5` to run it with Mqtt5 Client
``` sh
# from the node/fleet_provisioning folder
npm install
node ./index.js --endpoint <endpoint> --cert <file> --key <file> --template_name <template name> --template_parameters <template parameters> --mqtt5
```

You can also pass a Certificate Authority file (CA) if your certificate and key combination requires it:

``` sh
Expand Down Expand Up @@ -314,3 +321,46 @@ npm install
node ./index.js --endpoint <endpoint> --cert <file> --key <file> --template_name <template name> --template_parameters '{\"SerialNumber\":\"1\",\"DeviceLocation\":\"Seattle\"}' --csr <path to csr file>
```

## Service Client Notes
### Differences between MQTT5 and MQTT311
The service client with Mqtt5 client is almost identical to Mqtt3 one. The only difference is that you would need setup up a Mqtt5 Client and pass it to the service client.
For how to setup a Mqtt5 Client, please refer to [MQTT5 User Guide](https://github.com/awslabs/aws-crt-nodejs/blob/main/MQTT5-UserGuide.md) and [MQTT5 PubSub Sample](../pub_sub_mqtt5/README.md)

<table>
<tr>
<th>Create a IoTIdentityClient with Mqtt5</th>
<th>Create a IoTIdentityClient with Mqtt311</th>
</tr>
<tr>
<td>

```js
// Create a Mqtt5 Client
config_builder = iot.AwsIotMqtt5ClientConfigBuilder.newDirectMqttBuilderWithMtlsFromPath(argv.endpoint, argv.cert, argv.key);
client = new mqtt5.Mqtt5Client(config_builder.build());

// Create the identity client from Mqtt5 Client
identity = iotidentity.IotIdentityClient.newFromMqtt5Client(client5);
```

</td>
<td>

```js
// Create a Mqtt311 Connection from the command line data
config_builder = iot.AwsIotMqttConnectionConfigBuilder.new_mtls_builder_from_path(argv.cert, argv.key);
config_builder.with_client_id(argv.client_id || "test-" + Math.floor(Math.random() * 100000000));
config_builder.with_endpoint(argv.endpoint);
client = new mqtt.MqttClient();
connection = client.new_connection(config);

// Create the shadow client from Mqtt311 Connection
identity = new iotidentity.IotIdentityClient(connection);
```

</td>
</tr>
</table>

### mqtt5.QoS v.s. mqtt.QoS
As the service client interface is unchanged for both Mqtt3 Connection and Mqtt5 Client,the service client will use mqtt.QoS instead of mqtt5.QoS even with a Mqtt5 Client.
41 changes: 35 additions & 6 deletions samples/node/fleet_provisioning/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

import { mqtt, iotidentity } from 'aws-iot-device-sdk-v2';
import { once } from "events"

type Args = { [index: string]: any };
const fs = require('fs')
Expand Down Expand Up @@ -229,14 +230,33 @@ async function execute_csr(identity: iotidentity.IotIdentityClient, argv: Args)
async function main(argv: Args) {
common_args.apply_sample_arguments(argv);

const connection = common_args.build_connection_from_cli_args(argv);
var connection;
var client5;
var identity;
var timer;

const identity = new iotidentity.IotIdentityClient(connection);
console.log("Connecting...");
if (argv.mqtt5) {
client5 = common_args.build_mqtt5_client_from_cli_args(argv);
identity = iotidentity.IotIdentityClient.newFromMqtt5Client(client5);

// force node to wait 60 seconds before killing itself, promises do not keep node alive
const timer = setTimeout(() => { }, 60 * 1000);
const connectionSuccess = once(client5, "connectionSuccess");
client5.start();

// force node to wait 60 seconds before killing itself, promises do not keep node alive
timer = setTimeout(() => { }, 60 * 1000);
await connectionSuccess;
console.log("Connected with Mqtt5 Client!");
} else {
connection = common_args.build_connection_from_cli_args(argv);
identity = new iotidentity.IotIdentityClient(connection);

// force node to wait 60 seconds before killing itself, promises do not keep node alive
timer = setTimeout(() => { }, 60 * 1000);
await connection.connect()
console.log("Connected with Mqtt3 Client!");
}

await connection.connect();

if (argv.csr_file) {
//Csr workflow
Expand All @@ -248,7 +268,16 @@ async function main(argv: Args) {
await execute_register_thing(identity, token as string, argv);
}

await connection.disconnect();
console.log("Disconnecting...");
if (connection) {
await connection.disconnect();
} else {
let stopped = once(client5, "stopped");
client5.stop();
await stopped;
client5.close();
}
console.log("Disconnected");
// Allow node to die if the promise above resolved
clearTimeout(timer);
}
50 changes: 50 additions & 0 deletions samples/node/jobs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,59 @@ npm install
node dist/index --endpoint <endpoint> --cert <path to certificate> --key <path to private key> --thing_name <thing name>
```

You can also pass `--mqtt5` to run the sample with Mqtt5 Client
```sh
npm install
node dist/index --endpoint <endpoint> --cert <path to certificate> --key <path to private key> --thing_name <thing name> --mqtt5
```

You can also pass a Certificate Authority file (CA) if your certificate and key combination requires it:

``` sh
npm install
node dist/index --endpoint <endpoint> --cert <path to certificate> --key <path to private key> --thing_name <thing name> --ca_file <path to root CA>
```

## Service Client Notes
### Differences between MQTT5 and MQTT311
The service client with Mqtt5 client is almost identical to Mqtt3 one. The only difference is that you would need setup up a Mqtt5 Client and pass it to the service client.
For how to setup a Mqtt5 Client, please refer to [MQTT5 User Guide](https://github.com/awslabs/aws-crt-nodejs/blob/main/MQTT5-UserGuide.md) and [MQTT5 PubSub Sample](../pub_sub_mqtt5/README.md)

<table>
<tr>
<th>Create a IotJobsClient with Mqtt5</th>
<th>Create a IotJobsClient with Mqtt311</th>
</tr>
<tr>
<td>

```js
// Create a Mqtt5 Client
config_builder = iot.AwsIotMqtt5ClientConfigBuilder.newDirectMqttBuilderWithMtlsFromPath(argv.endpoint, argv.cert, argv.key);
client = new mqtt5.Mqtt5Client(config_builder.build());

// Create the jobs client from Mqtt5 Client
jobs = iotjobs.IotJobsClient.newFromMqtt5Client(client5);
```

</td>
<td>

```js
// Create a Mqtt311 Connection from the command line data
config_builder = iot.AwsIotMqttConnectionConfigBuilder.new_mtls_builder_from_path(argv.cert, argv.key);
config_builder.with_client_id(argv.client_id || "test-" + Math.floor(Math.random() * 100000000));
config_builder.with_endpoint(argv.endpoint);
client = new mqtt.MqttClient();
connection = client.new_connection(config);

// Create the jobs client from Mqtt311 Connection
jobs = new iotjobs.IotJobsClient(connection);
```

</td>
</tr>
</table>

### mqtt5.QoS v.s. mqtt.QoS
As the service client interface is unchanged for both Mqtt3 Connection and Mqtt5 Client,the service client will use mqtt.QoS instead of mqtt5.QoS even with a Mqtt5 Client.
34 changes: 27 additions & 7 deletions samples/node/jobs/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { mqtt, iotjobs } from 'aws-iot-device-sdk-v2';
import {once} from "events";

const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

Expand Down Expand Up @@ -114,12 +115,26 @@ async function on_start_next_pending_job_execution_accepted(error? : iotjobs.Iot
async function main(argv: Args) {
common_args.apply_sample_arguments(argv);

const connection = common_args.build_connection_from_cli_args(argv);
const jobs = new iotjobs.IotJobsClient(connection);
var connection;
var client5;
var jobs;

console.log("Connecting...");
await connection.connect()
console.log("Connected!");
if (argv.mqtt5) {
client5 = common_args.build_mqtt5_client_from_cli_args(argv);
jobs = iotjobs.IotJobsClient.newFromMqtt5Client(client5);

const connectionSuccess = once(client5, "connectionSuccess");
client5.start();
await connectionSuccess;
console.log("Connected with Mqtt5 Client!");
} else {
connection = common_args.build_connection_from_cli_args(argv);
jobs = new iotjobs.IotJobsClient(connection);

await connection.connect()
console.log("Connected with Mqtt3 Client!");
}

// Subscribe to necessary topics and get pending jobs
try {
Expand Down Expand Up @@ -257,9 +272,14 @@ async function main(argv: Args) {
}

console.log("Disconnecting...");
await connection.disconnect();
// force node to wait a second before quitting to finish any promises
await sleep(1000);
if (connection) {
await connection.disconnect();
} else {
let stopped = once(client5, "stopped");
client5.stop();
await stopped;
client5.close();
}
console.log("Disconnected");
// Quit NodeJS
process.exit(0);
Expand Down
Loading

0 comments on commit 14d1458

Please sign in to comment.