66import { mqtt , io , iot , greengrass } from 'aws-iot-device-sdk-v2' ;
77import { TextDecoder } from 'util' ;
88
9- type Args = { [ index : string ] : any } ;
9+ // --------------------------------- ARGUMENT PARSING -----------------------------------------
10+ const args = require ( 'yargs' )
11+ . option ( 'ca_file' , {
12+ alias : 'r' ,
13+ description : '<path>: path to a Root CA certificate file in PEM format (optional, system trust store used by default)' ,
14+ type : 'string' ,
15+ required : false
16+ } )
17+ . option ( 'cert' , {
18+ alias : 'c' ,
19+ description : '<path>: path to a PEM encoded certificate to use with mTLS' ,
20+ type : 'string' ,
21+ required : true
22+ } )
23+ . option ( 'key' , {
24+ alias : 'k' ,
25+ description : '<path>: Path to a PEM encoded private key that matches cert' ,
26+ type : 'string' ,
27+ required : true
28+ } )
29+ . option ( 'thing_name' , {
30+ alias : 'T' ,
31+ description : 'Targeted Thing name' ,
32+ type : 'string' ,
33+ required : true
34+ } )
35+ . option ( 'topic' , {
36+ alias : 't' ,
37+ description : 'Topic to publish/subscribe to' ,
38+ type : 'string' ,
39+ default : 'test/topic'
40+ } )
41+ . option ( 'message' , {
42+ alias : 'M' ,
43+ description : 'Message to publish' ,
44+ type : 'string' ,
45+ default : 'Hello World!'
46+ } )
47+ . option ( 'count' , {
48+ alias : 'n' ,
49+ description : 'Number of messages to publish' ,
50+ type : 'number' ,
51+ default : 10
52+ } )
53+ . option ( 'mode' , {
54+ alias : 'm' ,
55+ description : 'Mode options: [publish, subscribe, both] (optional)' ,
56+ type : 'string' ,
57+ default : 'both' ,
58+ choices : [ 'publish' , 'subscribe' , 'both' ]
59+ } )
60+ . option ( 'region' , {
61+ description : 'AWS Region' ,
62+ type : 'string' ,
63+ required : true
64+ } )
65+ . option ( 'print_discover_resp_only' , {
66+ description : 'Only print the response from Greengrass discovery (optional)' ,
67+ type : 'boolean' ,
68+ default : false
69+ } )
70+ . option ( 'is_ci' , {
71+ description : 'Adjusts sample to output/run in CI mode (optional)' ,
72+ type : 'boolean' ,
73+ default : false
74+ } )
75+ . option ( 'verbose' , {
76+ alias : 'v' ,
77+ description : 'Verbose logging level' ,
78+ type : 'string' ,
79+ default : 'none'
80+ } )
81+ . help ( )
82+ . argv ;
1083
11- const common_args = require ( 'aws-iot-samples-util/cli_args' ) ;
12-
13- const yargs = require ( 'yargs' ) ;
14- yargs . command ( '*' , false , ( yargs : any ) => {
15- common_args . add_universal_arguments ( yargs ) ;
16- common_args . add_topic_message_arguments ( yargs ) ;
17-
18- yargs
19- . option ( 'ca_file' , {
20- alias : 'r' ,
21- description : '<path>: path to a Root CA certificate file in PEM format (optional, system trust store used by default).' ,
22- type : 'string' ,
23- required : false
24- } )
25- . option ( 'cert' , {
26- alias : 'c' ,
27- description : '<path>: path to a PEM encoded certificate to use with mTLS.' ,
28- type : 'string' ,
29- required : true
30- } )
31- . option ( 'key' , {
32- alias : 'k' ,
33- description : '<path>: Path to a PEM encoded private key that matches cert.' ,
34- type : 'string' ,
35- required : true
36- } )
37- . option ( 'thing_name' , {
38- alias : 'T' ,
39- description : 'Targeted Thing name.' ,
40- type : 'string' ,
41- required : true
42- } )
43- . option ( 'mode' , {
44- alias : 'm' ,
45- description : 'Mode options: [publish, subscribe, both] (optional).' ,
46- type : 'string' ,
47- default : 'both' ,
48- choices : [ 'publish' , 'subscribe' , 'both' ]
49- } )
50- . option ( 'region' , {
51- description : 'AWS Region.' ,
52- type : 'string' ,
53- required : true
54- } )
55- . option ( 'print_discover_resp_only' , {
56- description : 'Only print the response from Greengrass discovery (optional).' ,
57- type : 'boolean' ,
58- default : false
59- } )
60- . option ( 'is_ci' , {
61- description : 'Adjusts sample to output/run in CI mode (optional).' ,
62- type : 'boolean' ,
63- default : false
64- } )
65- } , main ) . parse ( ) ;
84+ // --------------------------------- ARGUMENT PARSING END -----------------------------------------
6685
6786function firstResolved < T > ( promises : Promise < T > [ ] ) {
6887 let rejects : Error [ ] = [ ] ;
@@ -82,7 +101,7 @@ function firstResolved<T>(promises: Promise<T>[]) {
82101 } ) ;
83102}
84103
85- async function connect_to_iot ( mqtt_client : mqtt . MqttClient , argv : Args , discovery_response : greengrass . model . DiscoverResponse ) {
104+ async function connect_to_iot ( mqtt_client : mqtt . MqttClient , discovery_response : greengrass . model . DiscoverResponse ) {
86105 return new Promise < mqtt . MqttClientConnection > ( ( resolve , reject ) => {
87106 const start_connections = ( ) => {
88107 let attempted_cores : string [ ] = [ ] ;
@@ -91,9 +110,9 @@ async function connect_to_iot(mqtt_client: mqtt.MqttClient, argv: Args, discover
91110 for ( const core of gg_group . cores ) {
92111 attempted_cores . push ( core . thing_arn . toString ( ) ) ;
93112 for ( const endpoint of core . connectivity ) {
94- const mqtt_config = iot . AwsIotMqttConnectionConfigBuilder . new_mtls_builder_from_path ( argv . cert , argv . key )
113+ const mqtt_config = iot . AwsIotMqttConnectionConfigBuilder . new_mtls_builder_from_path ( args . cert , args . key )
95114 . with_certificate_authority ( gg_group . certificate_authorities [ 0 ] )
96- . with_client_id ( argv . thing_name )
115+ . with_client_id ( args . thing_name )
97116 . with_clean_session ( false )
98117 . with_socket_options ( new io . SocketOptions ( io . SocketType . STREAM , io . SocketDomain . IPV4 , 3000 ) )
99118 . build ( ) ;
@@ -126,45 +145,45 @@ async function connect_to_iot(mqtt_client: mqtt.MqttClient, argv: Args, discover
126145 } ) ;
127146}
128147
129- async function execute_session ( connection : mqtt . MqttClientConnection , argv : Args ) {
130- console . log ( "execute_session: topic is " + argv . topic ) ;
148+ async function execute_session ( connection : mqtt . MqttClientConnection ) {
149+ console . log ( "execute_session: topic is " + args . topic ) ;
131150 return new Promise < void > ( async ( resolve , reject ) => {
132151 try {
133152 let published = false ;
134153 let subscribed = false ;
135154 const decoder = new TextDecoder ( 'utf8' ) ;
136- if ( argv . mode == 'both' || argv . mode == 'subscribe' ) {
155+ if ( args . mode == 'both' || args . mode == 'subscribe' ) {
137156 const on_publish = ( topic : string , payload : ArrayBuffer , dup : boolean , qos : mqtt . QoS , retain : boolean ) => {
138157 const json = decoder . decode ( payload ) ;
139158 console . log ( `Publish received. topic:"${ topic } " dup:${ dup } qos:${ qos } retain:${ retain } ` ) ;
140159 console . log ( json ) ;
141160 const message = JSON . parse ( json ) ;
142- if ( message . sequence == argv . count ) {
161+ if ( message . sequence == args . count ) {
143162 subscribed = true ;
144163 if ( subscribed && published ) {
145164 resolve ( ) ;
146165 }
147166 }
148167 }
149- await connection . subscribe ( argv . topic , mqtt . QoS . AtLeastOnce , on_publish ) ;
168+ await connection . subscribe ( args . topic , mqtt . QoS . AtLeastOnce , on_publish ) ;
150169 }
151170 else {
152171 subscribed = true ;
153172 }
154173
155- if ( argv . mode == 'both' || argv . mode == 'publish' ) {
174+ if ( args . mode == 'both' || args . mode == 'publish' ) {
156175 let published_counts = 0 ;
157- for ( let op_idx = 0 ; op_idx < argv . count ; ++ op_idx ) {
176+ for ( let op_idx = 0 ; op_idx < args . count ; ++ op_idx ) {
158177 const publish = async ( ) => {
159178 const msg = {
160- message : argv . message ,
179+ message : args . message ,
161180 sequence : op_idx + 1 ,
162181 } ;
163182 const json = JSON . stringify ( msg ) ;
164183 console . log ( "execute_session: publishing..." ) ;
165- connection . publish ( argv . topic , json , mqtt . QoS . AtLeastOnce ) . then ( ( ) => {
184+ connection . publish ( args . topic , json , mqtt . QoS . AtLeastOnce ) . then ( ( ) => {
166185 ++ published_counts ;
167- if ( published_counts == argv . count ) {
186+ if ( published_counts == args . count ) {
168187 published = true ;
169188 if ( subscribed && published ) {
170189 resolve ( ) ;
@@ -185,49 +204,49 @@ async function execute_session(connection: mqtt.MqttClientConnection, argv: Args
185204 } ) ;
186205}
187206
188- async function main ( argv : Args ) {
189- if ( argv . verbose && argv . verbose != 'none' ) {
190- const level : io . LogLevel = parseInt ( io . LogLevel [ argv . verbose . toUpperCase ( ) ] ) ;
207+ async function main ( ) {
208+ if ( args . verbose && args . verbose != 'none' ) {
209+ const level : io . LogLevel = parseInt ( io . LogLevel [ args . verbose . toUpperCase ( ) ] ) ;
191210 io . enable_logging ( level ) ;
192211 }
193212
194213 const client_bootstrap = new io . ClientBootstrap ( ) ;
195214 const socket_options = new io . SocketOptions ( io . SocketType . STREAM , io . SocketDomain . IPV4 , 3000 ) ;
196215 const tls_options = new io . TlsContextOptions ( ) ;
197- if ( argv . ca_file ) {
198- tls_options . override_default_trust_store_from_path ( undefined , argv . ca_file ) ;
216+ if ( args . ca_file ) {
217+ tls_options . override_default_trust_store_from_path ( undefined , args . ca_file ) ;
199218 }
200- tls_options . certificate_filepath = argv . cert ;
201- tls_options . private_key_filepath = argv . key ;
219+ tls_options . certificate_filepath = args . cert ;
220+ tls_options . private_key_filepath = args . key ;
202221 if ( io . is_alpn_available ( ) ) {
203222 tls_options . alpn_list . push ( 'x-amzn-http-ca' ) ;
204223 }
205224 const tls_ctx = new io . ClientTlsContext ( tls_options ) ;
206- const discovery = new greengrass . DiscoveryClient ( client_bootstrap , socket_options , tls_ctx , argv . region ) ;
225+ const discovery = new greengrass . DiscoveryClient ( client_bootstrap , socket_options , tls_ctx , args . region ) ;
207226
208227 // force node to wait 60 seconds before killing itself, promises do not keep node alive
209228 const timer = setTimeout ( ( ) => { } , 60 * 1000 ) ;
210229
211- console . log ( "Starting discovery for thing " + argv . thing_name ) ;
230+ console . log ( "Starting discovery for thing " + args . thing_name ) ;
212231
213- await discovery . discover ( argv . thing_name )
232+ await discovery . discover ( args . thing_name )
214233 . then ( async ( discovery_response : greengrass . model . DiscoverResponse ) => {
215234 console . log ( "Discovery Response:" ) ;
216235
217- if ( argv . is_ci != true ) {
236+ if ( args . is_ci != true ) {
218237 console . log ( JSON . stringify ( discovery_response ) ) ;
219238 } else {
220239 console . log ( "Received a greengrass discovery result! Not showing result in CI for possible data sensitivity." ) ;
221240 }
222241
223- if ( argv . print_discover_resp_only ) {
242+ if ( args . print_discover_resp_only ) {
224243 process . exit ( 0 ) ;
225244 }
226245
227246 const mqtt_client = new mqtt . MqttClient ( client_bootstrap ) ;
228- return connect_to_iot ( mqtt_client , argv , discovery_response ) ;
247+ return connect_to_iot ( mqtt_client , discovery_response ) ;
229248 } ) . then ( async ( connection ) => {
230- await execute_session ( connection , argv ) ;
249+ await execute_session ( connection ) ;
231250 console . log ( "Disconnecting..." ) ;
232251 return connection . disconnect ( ) ;
233252 } ) . then ( ( ) => {
@@ -242,3 +261,8 @@ async function main(argv: Args) {
242261 clearTimeout ( timer ) ;
243262 process . exit ( 0 ) ;
244263}
264+
265+ main ( ) . catch ( ( error ) => {
266+ console . error ( error ) ;
267+ process . exit ( 1 ) ;
268+ } ) ;
0 commit comments