1515#include < mutex>
1616#include < thread>
1717
18- #include " ../../utils/CommandLineUtils.h"
19-
2018using namespace Aws ::Crt;
2119using namespace Aws ::Discovery;
2220
21+ struct CmdArgs
22+ {
23+ String endpoint;
24+ String cert;
25+ String key;
26+ String clientId;
27+ String caFile;
28+ String thingName;
29+ String topic = " test/topic" ;
30+ String message;
31+ String mode = " both" ;
32+ String signingRegion = " us-east-1" ;
33+ String proxyHost;
34+ uint32_t proxyPort = 0 ;
35+ bool printDiscoverRespOnly = false ;
36+ };
37+
2338static std::shared_ptr<Mqtt::MqttConnection> getMqttConnection (
2439 Aws::Iot::MqttClient &mqttClient,
2540 const Aws::Crt::Vector<GGGroup> &ggGroups,
26- Utils::cmdData &cmdData,
41+ CmdArgs &cmdData,
2742 std::promise<void > &shutdownCompletedPromise)
2843{
2944 std::shared_ptr<Mqtt::MqttConnection> connection;
@@ -41,7 +56,7 @@ static std::shared_ptr<Mqtt::MqttConnection> getMqttConnection(
4156 (int )connectivityInfo.Port .value ());
4257
4358 connection = mqttClient.NewConnection (
44- Aws::Iot::MqttClientConnectionConfigBuilder (cmdData.input_cert .c_str (), cmdData.input_key .c_str ())
59+ Aws::Iot::MqttClientConnectionConfigBuilder (cmdData.cert .c_str (), cmdData.key .c_str ())
4560 .WithCertificateAuthority (ByteCursorFromCString (groupToUse.CAs ->at (0 ).c_str ()))
4661 .WithPortOverride (connectivityInfo.Port .value ())
4762 .WithEndpoint (connectivityInfo.HostAddress .value ())
@@ -98,7 +113,7 @@ static std::shared_ptr<Mqtt::MqttConnection> getMqttConnection(
98113 shutdownCompletedPromise.set_value ();
99114 };
100115
101- if (!connection->Connect (cmdData.input_thingName .c_str (), false ))
116+ if (!connection->Connect (cmdData.thingName .c_str (), false ))
102117 {
103118 fprintf (stderr, " Connect failed with error %s\n " , aws_error_debug_str (aws_last_error ()));
104119 continue ;
@@ -132,33 +147,131 @@ static void printGreengrassResponse(const Aws::Crt::Vector<GGGroup> &ggGroups)
132147 }
133148}
134149
150+ void printHelp ()
151+ {
152+ printf (" Greengrass Discovery Sample\n " );
153+ printf (" options:\n " );
154+ printf (" --help show this help message and exit\n " );
155+ printf (" required arguments:\n " );
156+ printf (" --cert Path to the certificate file\n " );
157+ printf (" --key Path to the private key file\n " );
158+ printf (" --thing_name Thing name\n " );
159+ printf (" optional arguments:\n " );
160+ printf (" --client_id Client ID (default: test-<uuid>)\n " );
161+ printf (" --ca_file Path to optional CA bundle (PEM)\n " );
162+ printf (" --topic Topic (default: test/topic)\n " );
163+ printf (" --message Message to publish\n " );
164+ printf (" --mode Mode: publish, subscribe, both (default: both)\n " );
165+ printf (" --signing_region Signing region (default: us-east-1)\n " );
166+ printf (" --proxy_host HTTP proxy host\n " );
167+ printf (" --proxy_port HTTP proxy port\n " );
168+ printf (" --print_discover_resp_only Print discovery response only\n " );
169+ }
170+
171+ CmdArgs parseArgs (int argc, char *argv[])
172+ {
173+ CmdArgs args;
174+ for (int i = 1 ; i < argc; i++)
175+ {
176+ if (strcmp (argv[i], " --help" ) == 0 )
177+ {
178+ printHelp ();
179+ exit (0 );
180+ }
181+ else if (i < argc - 1 )
182+ {
183+ if (strcmp (argv[i], " --cert" ) == 0 )
184+ {
185+ args.cert = argv[++i];
186+ }
187+ else if (strcmp (argv[i], " --key" ) == 0 )
188+ {
189+ args.key = argv[++i];
190+ }
191+ else if (strcmp (argv[i], " --thing_name" ) == 0 )
192+ {
193+ args.thingName = argv[++i];
194+ }
195+ else if (strcmp (argv[i], " --client_id" ) == 0 )
196+ {
197+ args.clientId = argv[++i];
198+ }
199+ else if (strcmp (argv[i], " --ca_file" ) == 0 )
200+ {
201+ args.caFile = argv[++i];
202+ }
203+ else if (strcmp (argv[i], " --topic" ) == 0 )
204+ {
205+ args.topic = argv[++i];
206+ }
207+ else if (strcmp (argv[i], " --message" ) == 0 )
208+ {
209+ args.message = argv[++i];
210+ }
211+ else if (strcmp (argv[i], " --mode" ) == 0 )
212+ {
213+ args.mode = argv[++i];
214+ }
215+ else if (strcmp (argv[i], " --signing_region" ) == 0 )
216+ {
217+ args.signingRegion = argv[++i];
218+ }
219+ else if (strcmp (argv[i], " --proxy_host" ) == 0 )
220+ {
221+ args.proxyHost = argv[++i];
222+ }
223+ else if (strcmp (argv[i], " --proxy_port" ) == 0 )
224+ {
225+ args.proxyPort = atoi (argv[++i]);
226+ }
227+ else
228+ {
229+ fprintf (stderr, " Unknown argument: %s\n " , argv[i]);
230+ printHelp ();
231+ exit (1 );
232+ }
233+ }
234+ else if (strcmp (argv[i], " --print_discover_resp_only" ) == 0 )
235+ {
236+ args.printDiscoverRespOnly = true ;
237+ }
238+ }
239+ if (args.cert .empty () || args.key .empty () || args.thingName .empty ())
240+ {
241+ fprintf (stderr, " Error: --cert, --key, and --thing_name are required\n " );
242+ printHelp ();
243+ exit (1 );
244+ }
245+ if (args.clientId .empty ())
246+ {
247+ args.clientId = String (" test-" ) + UUID ().ToString ();
248+ }
249+ return args;
250+ }
251+
135252int main (int argc, char *argv[])
136253{
137254 /* *********************** Setup ****************************/
138255
256+ // Parse command line arguments
257+ CmdArgs cmdData = parseArgs (argc, argv);
258+
139259 // Do the global initialization for the API.
140260 ApiHandle apiHandle;
141261
142- /* *
143- * cmdData is the arguments/input from the command line placed into a single struct for
144- * use in this sample. This handles all of the command line parsing, validating, etc.
145- * See the Utils/CommandLineUtils for more information.
146- */
147- Utils::cmdData cmdData = Utils::parseSampleInputGreengrassDiscovery (argc, argv, &apiHandle);
148-
149262 // We're using Mutual TLS for MQTT, so we need to load our client certificates
150263 Io::TlsContextOptions tlsCtxOptions =
151- Io::TlsContextOptions::InitClientWithMtls (cmdData.input_cert .c_str (), cmdData.input_key .c_str ());
264+ Io::TlsContextOptions::InitClientWithMtls (cmdData.cert .c_str (), cmdData.key .c_str ());
152265
153266 if (!tlsCtxOptions)
154267 {
155268 fprintf (stderr, " TLS Context Options creation failed with error %s\n " , ErrorDebugString (Aws::Crt::LastError ()));
156269 exit (-1 );
157270 }
158271
159- if (!cmdData.input_ca .empty ())
272+ if (!cmdData.caFile .empty ())
160273 {
161- tlsCtxOptions.OverrideDefaultTrustStore (nullptr , cmdData.input_ca .c_str ());
274+ tlsCtxOptions.OverrideDefaultTrustStore (nullptr , cmdData.caFile .c_str ());
162275 }
163276
164277 Io::TlsContext tlsCtx (tlsCtxOptions, Io::TlsMode::CLIENT);
@@ -189,13 +302,13 @@ int main(int argc, char *argv[])
189302 DiscoveryClientConfig clientConfig;
190303 clientConfig.SocketOptions = socketOptions;
191304 clientConfig.TlsContext = tlsCtx;
192- clientConfig.Region = cmdData.input_signingRegion ;
305+ clientConfig.Region = cmdData.signingRegion ;
193306
194307 Aws::Crt::Http::HttpClientConnectionProxyOptions proxyOptions;
195- if (cmdData.input_proxyHost .length () > 0 && cmdData.input_proxyPort != 0 )
308+ if (cmdData.proxyHost .length () > 0 && cmdData.proxyPort != 0 )
196309 {
197- proxyOptions.HostName = cmdData.input_proxyHost ;
198- proxyOptions.Port = static_cast < uint32_t >( cmdData.input_proxyPort ) ;
310+ proxyOptions.HostName = cmdData.proxyHost ;
311+ proxyOptions.Port = cmdData.proxyPort ;
199312 clientConfig.ProxyOptions = proxyOptions;
200313 }
201314
@@ -217,7 +330,7 @@ int main(int argc, char *argv[])
217330 // NOTE: This is an asynchronous operation, so it completes before the results are actually ready. You need to use
218331 // synchronization techniques to obtain its results. For simplicity, we use promise/future in this sample.
219332 discoveryClient->Discover (
220- cmdData.input_thingName ,
333+ cmdData.thingName ,
221334 [&discoverResponse, &discoveryStatusPromise](DiscoverResponse *response, int error, int httpResponseCode) {
222335 fprintf (stdout, " Discovery completed with error code %d; http code %d\n " , error, httpResponseCode);
223336
@@ -245,7 +358,7 @@ int main(int argc, char *argv[])
245358 }
246359
247360 // Print the discovery response information and then exit. Does not use the discovery info.
248- if (cmdData.input_PrintDiscoverRespOnly )
361+ if (cmdData.printDiscoverRespOnly )
249362 {
250363 printGreengrassResponse (*discoverResponse.GGGroups );
251364 return 0 ;
@@ -260,7 +373,7 @@ int main(int argc, char *argv[])
260373 }
261374
262375 // Now, with the established connection to a Greengrass core, we can perform MQTT-related actions.
263- if (cmdData.input_mode == " both" || cmdData.input_mode == " subscribe" )
376+ if (cmdData.mode == " both" || cmdData.mode == " subscribe" )
264377 {
265378 auto onMessage = [&](Mqtt::MqttConnection & /* connection*/ ,
266379 const String &receivedOnTopic,
@@ -294,30 +407,30 @@ int main(int argc, char *argv[])
294407 }
295408 };
296409
297- connection->Subscribe (cmdData.input_topic .c_str (), AWS_MQTT_QOS_AT_MOST_ONCE, onMessage, onSubAck);
410+ connection->Subscribe (cmdData.topic .c_str (), AWS_MQTT_QOS_AT_MOST_ONCE, onMessage, onSubAck);
298411 }
299412
300413 bool first_input = true ;
301414 while (true )
302415 {
303416 String input;
304- if (cmdData.input_mode == " both" || cmdData.input_mode == " publish" )
417+ if (cmdData.mode == " both" || cmdData.mode == " publish" )
305418 {
306- if (cmdData.input_message .empty ())
419+ if (cmdData.message .empty ())
307420 {
308421 fprintf (
309422 stdout,
310423 " Enter the message you want to publish to topic %s and press enter. Enter 'exit' to exit this "
311424 " program.\n " ,
312- cmdData.input_topic .c_str ());
425+ cmdData.topic .c_str ());
313426 std::getline (std::cin, input);
314- cmdData.input_message = input;
427+ cmdData.message = input;
315428 }
316429 else if (!first_input)
317430 {
318431 fprintf (stdout, " Enter a new message or enter 'exit' or 'quit' to exit the program.\n " );
319432 std::getline (std::cin, input);
320- cmdData.input_message = input;
433+ cmdData.message = input;
321434 }
322435 first_input = false ;
323436 }
@@ -333,7 +446,7 @@ int main(int argc, char *argv[])
333446 break ;
334447 }
335448
336- if (cmdData.input_mode == " both" || cmdData.input_mode == " publish" )
449+ if (cmdData.mode == " both" || cmdData.mode == " publish" )
337450 {
338451 ByteBuf payload = ByteBufNewCopy (DefaultAllocator (), (const uint8_t *)input.data (), input.length ());
339452 ByteBuf *payloadPtr = &payload;
@@ -351,7 +464,7 @@ int main(int argc, char *argv[])
351464 }
352465 };
353466 connection->Publish (
354- cmdData.input_topic .c_str (), AWS_MQTT_QOS_AT_LEAST_ONCE, false , payload, onPublishComplete);
467+ cmdData.topic .c_str (), AWS_MQTT_QOS_AT_LEAST_ONCE, false , payload, onPublishComplete);
355468 }
356469 }
357470
0 commit comments