source: azure_iot_hub_riscv/trunk/app_iothub_client/src/client.c@ 453

Last change on this file since 453 was 453, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 16.5 KB
Line 
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#include <stdio.h>
5#include <stdlib.h>
6
7/* This sample uses the _LL APIs of iothub_client for example purposes.
8That does not mean that HTTP only works with the _LL APIs.
9Simply changing the using the convenience layer (functions not having _LL)
10and removing calls to _DoWork will yield the same results. */
11
12#include "azure_c_shared_utility/threadapi.h"
13#include "azure_c_shared_utility/crt_abstractions.h"
14#include "azure_c_shared_utility/platform.h"
15#include "azure_c_shared_utility/shared_util_options.h"
16#include "iothub_client_ll.h"
17#include "iothub_message.h"
18#include "iothubtransporthttp.h"
19#include "iothubtransportmqtt.h"
20#include "iothubtransportmqtt_websockets.h"
21#include "iothub_client_options.h"
22#include "serializer.h"
23#include "serializer_devicetwin.h"
24#include "client.h"
25
26#ifdef _MSC_VER
27extern int sprintf_s(char* dst, size_t dstSizeInBytes, const char* format, ...);
28#endif // _MSC_VER
29
30#define SET_TRUSTED_CERT_IN_SAMPLES
31
32#ifdef SET_TRUSTED_CERT_IN_SAMPLES
33#include "certs.h"
34#endif // SET_TRUSTED_CERT_IN_SAMPLES
35
36/*String containing Hostname, Device Id & Device Key in the format: */
37/* "HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>" */
38/* "HostName=<host_name>;DeviceId=<device_id>;SharedAccessSignature=<device_sas_token>" */
39char* connectionString = NULL;
40
41bool g_use_proxy;
42HTTP_PROXY_OPTIONS g_proxy_options;
43int ledOn;
44
45static int callbackCounter;
46static bool g_continueRunning;
47static bool g_twinReport;
48static char propText[1024];
49#define MESSAGE_COUNT 5
50#define DOWORK_LOOP_NUM 3
51
52typedef struct EVENT_INSTANCE_TAG
53{
54 IOTHUB_MESSAGE_HANDLE messageHandle;
55 size_t messageTrackingId; // For tracking the messages within the user callback.
56} EVENT_INSTANCE;
57
58static IOTHUBMESSAGE_DISPOSITION_RESULT ReceiveMessageCallback(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback)
59{
60 int* counter = (int*)userContextCallback;
61 const char* buffer;
62 size_t size;
63 MAP_HANDLE mapProperties;
64 const char* messageId;
65 const char* correlationId;
66 const char* contentType;
67 const char* contentEncoding;
68
69 // Message properties
70 if ((messageId = IoTHubMessage_GetMessageId(message)) == NULL)
71 {
72 messageId = "<null>";
73 }
74
75 if ((correlationId = IoTHubMessage_GetCorrelationId(message)) == NULL)
76 {
77 correlationId = "<null>";
78 }
79
80 if ((contentType = IoTHubMessage_GetContentTypeSystemProperty(message)) == NULL)
81 {
82 contentType = "<null>";
83 }
84
85 if ((contentEncoding = IoTHubMessage_GetContentEncodingSystemProperty(message)) == NULL)
86 {
87 contentEncoding = "<null>";
88 }
89
90 // Message content
91 if (IoTHubMessage_GetByteArray(message, (const unsigned char**)&buffer, &size) != IOTHUB_MESSAGE_OK)
92 {
93 printf("unable to retrieve the message data\r\n");
94 }
95 else
96 {
97 (void)printf("Received Message [%d]\r\n Message ID: %s\r\n Correlation ID: %s\r\n Content-Type: %s\r\n Content-Encoding: %s\r\n Data: <<<%.*s>>> & Size=%d\r\n",
98 *counter, messageId, correlationId, contentType, contentEncoding, (int)size, buffer, (int)size);
99 // If we receive the work 'quit' then we stop running
100 if (size == (strlen("quit") * sizeof(char)) && memcmp(buffer, "quit", size) == 0)
101 {
102 g_continueRunning = false;
103 }
104 }
105
106 // Retrieve properties from the message
107 mapProperties = IoTHubMessage_Properties(message);
108 if (mapProperties != NULL)
109 {
110 const char*const* keys;
111 const char*const* values;
112 size_t propertyCount = 0;
113 if (Map_GetInternals(mapProperties, &keys, &values, &propertyCount) == MAP_OK)
114 {
115 if (propertyCount > 0)
116 {
117 size_t index;
118
119 printf(" Message Properties:\r\n");
120 for (index = 0; index < propertyCount; index++)
121 {
122 (void)printf("\tKey: %s Value: %s\r\n", keys[index], values[index]);
123 }
124 (void)printf("\r\n");
125 }
126 }
127 }
128
129 /* Some device specific action code goes here... */
130 (*counter)++;
131 return IOTHUBMESSAGE_ACCEPTED;
132}
133
134// Define the Model
135BEGIN_NAMESPACE(WeatherStation);
136
137DECLARE_MODEL(ContosoAnemometer,
138WITH_DATA(double, windSpeed),
139WITH_DATA(double, temperature),
140WITH_DATA(double, humidity),
141WITH_METHOD(quit),
142WITH_METHOD(turnLedOn),
143WITH_METHOD(turnLedOff)
144);
145
146DECLARE_STRUCT(ThresholdD,
147 double, value
148);
149
150DECLARE_STRUCT(ThresholdR,
151 double, value,
152 ascii_char_ptr, status
153);
154
155DECLARE_DEVICETWIN_MODEL(AnemometerState,
156WITH_REPORTED_PROPERTY(ThresholdR, threshold)
157);
158
159DECLARE_DEVICETWIN_MODEL(AnemometerSettings,
160WITH_DESIRED_PROPERTY(ThresholdD, threshold, onDesiredThreshold)
161);
162
163END_NAMESPACE(WeatherStation);
164
165void anemometerReportedStateCallback(int status_code, void* userContextCallback)
166{
167 AnemometerState *anemometer = (AnemometerState *)userContextCallback;
168
169 printf("received states \033[43m%d\033[49m, reported threshold = %.1f\n", status_code, anemometer->threshold.value);
170}
171
172void onDesiredThreshold(void* argument)
173{
174 // Note: The argument is NOT a pointer to threshold, but instead a pointer to the MODEL
175 // that contains threshold as one of its arguments. In this case, it
176 // is AnemometerSettings*.
177
178 AnemometerSettings *anemometer = (AnemometerSettings *)argument;
179 printf("received a new desired.threshold = \033[42m%.1f\033[49m\n", anemometer->threshold.value);
180
181 g_twinReport = true;
182}
183
184METHODRETURN_HANDLE quit(ContosoAnemometer* device)
185{
186 (void)device;
187 (void)printf("quit with Method.\r\n");
188
189 g_continueRunning = false;
190
191 METHODRETURN_HANDLE result = MethodReturn_Create(0, "{\"Message\":\"quit with Method\"}");
192 return result;
193}
194
195METHODRETURN_HANDLE turnLedOn(ContosoAnemometer* device)
196{
197 (void)device;
198 (void)printf("\033[41mTurning LED on with Method.\033[49m\r\n");
199
200 ledOn = 1;
201
202 METHODRETURN_HANDLE result = MethodReturn_Create(1, "{\"Message\":\"Turning fan on with Method\"}");
203 return result;
204}
205
206METHODRETURN_HANDLE turnLedOff(ContosoAnemometer* device)
207{
208 (void)device;
209 (void)printf("\033[44mTurning LED off with Method.\033[49m\r\n");
210
211 ledOn = 0;
212
213 METHODRETURN_HANDLE result = MethodReturn_Create(0, "{\"Message\":\"Turning fan off with Method\"}");
214 return result;
215}
216
217static int ReceiveDeviceMethodCallback(const char* method_name, const unsigned char* payload, size_t size, unsigned char** response, size_t* resp_size, void* userContextCallback)
218{
219 int result;
220
221 /*this is step 3: receive the method and push that payload into serializer (from below)*/
222 char* payloadZeroTerminated = (char*)malloc(size + 1);
223 if (payloadZeroTerminated == 0)
224 {
225 printf("failed to malloc\r\n");
226 *resp_size = 0;
227 *response = NULL;
228 result = -1;
229 }
230 else
231 {
232 (void)memcpy(payloadZeroTerminated, payload, size);
233 payloadZeroTerminated[size] = '\0';
234
235 /*execute method - userContextCallback is of type deviceModel*/
236 METHODRETURN_HANDLE methodResult = EXECUTE_METHOD(userContextCallback, method_name, payloadZeroTerminated);
237 free(payloadZeroTerminated);
238
239 if (methodResult == NULL)
240 {
241 printf("failed to EXECUTE_METHOD\r\n");
242 *resp_size = 0;
243 *response = NULL;
244 result = -1;
245 }
246 else
247 {
248 /* get the serializer answer and push it in the networking stack*/
249 const METHODRETURN_DATA* data = MethodReturn_GetReturn(methodResult);
250 if (data == NULL)
251 {
252 printf("failed to MethodReturn_GetReturn\r\n");
253 *resp_size = 0;
254 *response = NULL;
255 result = -1;
256 }
257 else
258 {
259 result = data->statusCode;
260 if (data->jsonValue == NULL)
261 {
262 char* resp = "{}";
263 *resp_size = strlen(resp);
264 *response = (unsigned char*)malloc(*resp_size);
265 (void)memcpy(*response, resp, *resp_size);
266 }
267 else
268 {
269 *resp_size = strlen(data->jsonValue);
270 *response = (unsigned char*)malloc(*resp_size);
271 (void)memcpy(*response, data->jsonValue, *resp_size);
272 }
273 }
274 MethodReturn_Destroy(methodResult);
275 }
276 }
277 return result;
278}
279
280static void SendConfirmationCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* userContextCallback)
281{
282 EVENT_INSTANCE* eventInstance = (EVENT_INSTANCE*)userContextCallback;
283
284 (void)printf("Confirmation[%d] received for message tracking id = %u with result = %s\r\n", callbackCounter, eventInstance->messageTrackingId, MU_ENUM_TO_STRING(IOTHUB_CLIENT_CONFIRMATION_RESULT, result));
285
286 /* Some device specific action code goes here... */
287 callbackCounter++;
288 IoTHubMessage_Destroy(eventInstance->messageHandle);
289}
290
291void iothub_client_run(int proto)
292{
293 IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle;
294
295 EVENT_INSTANCE messages[MESSAGE_COUNT];
296 int msg_id = 0;
297 double avgWindSpeed = 10.0;
298 double minTemperature = 20.0;
299 double minHumidity = 60.0;
300 int receiveContext = 0;
301
302 g_continueRunning = true;
303
304 srand((unsigned int)time(NULL));
305
306 callbackCounter = 0;
307
308 if (platform_init() != 0)
309 {
310 (void)printf("Failed to initialize the platform.\r\n");
311 }
312 else {
313 if (serializer_init(NULL) != SERIALIZER_OK)
314 {
315 (void)printf("Failed in serializer_init.");
316 }
317 else if (SERIALIZER_REGISTER_NAMESPACE(WeatherStation) == NULL)
318 {
319 LogError("unable to SERIALIZER_REGISTER_NAMESPACE");
320 }
321 else
322 {
323 IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol;
324 switch (proto) {
325 case 0:
326 (void)printf("Starting the IoTHub client sample HTTP...\r\n");
327 protocol = HTTP_Protocol;
328 break;
329 case 1:
330 (void)printf("Starting the IoTHub client sample MQTT...\r\n");
331 protocol = MQTT_Protocol;
332 break;
333 case 2:
334 (void)printf("Starting the IoTHub client sample MQTT over WebSocket...\r\n");
335 protocol = MQTT_WebSocket_Protocol;
336 break;
337 default:
338 platform_deinit();
339 return;
340 }
341
342 if ((iotHubClientHandle = IoTHubClient_LL_CreateFromConnectionString(connectionString, protocol)) == NULL)
343 {
344 (void)printf("ERROR: iotHubClientHandle is NULL!\r\n");
345 }
346 else
347 {
348 if (g_use_proxy)
349 {
350 if (IoTHubClient_LL_SetOption(iotHubClientHandle, OPTION_HTTP_PROXY, &g_proxy_options) != IOTHUB_CLIENT_OK)
351 {
352 printf("failure to set option \"HTTP Proxy\"\r\n");
353 }
354 }
355#if 0
356 long curl_verbose = 1;
357 if (IoTHubClient_LL_SetOption(iotHubClientHandle, OPTION_CURL_VERBOSE, &curl_verbose) != IOTHUB_CLIENT_OK)
358 {
359 printf("failure to set option \"CURL Verbose\"\r\n");
360 }
361
362 unsigned int timeout = 241000;
363 // Because it can poll "after 9 seconds" polls will happen effectively // at ~10 seconds.
364 // Note that for scalabilty, the default value of minimumPollingTime
365 // is 25 minutes. For more information, see:
366 // https://azure.microsoft.com/documentation/articles/iot-hub-devguide/#messaging
367 unsigned int minimumPollingTime = 9;
368 if (IoTHubClient_LL_SetOption(iotHubClientHandle, "timeout", &timeout) != IOTHUB_CLIENT_OK)
369 {
370 printf("failure to set option \"timeout\"\r\n");
371 }
372
373 if (IoTHubClient_LL_SetOption(iotHubClientHandle, "MinimumPollingTime", &minimumPollingTime) != IOTHUB_CLIENT_OK)
374 {
375 printf("failure to set option \"MinimumPollingTime\"\r\n");
376 }
377
378 bool traceOn = 1;
379 if (IoTHubClient_LL_SetOption(iotHubClientHandle, OPTION_LOG_TRACE, &traceOn) != IOTHUB_CLIENT_OK)
380 {
381 printf("failure to set option \"log trace on\"\r\n");
382 }
383#endif
384#ifdef SET_TRUSTED_CERT_IN_SAMPLES
385 // For mbed add the certificate information
386 if (IoTHubClient_LL_SetOption(iotHubClientHandle, OPTION_TRUSTED_CERT, certificates) != IOTHUB_CLIENT_OK)
387 {
388 printf("failure to set option \"TrustedCerts\"\r\n");
389 }
390#endif // SET_TRUSTED_CERT_IN_SAMPLES
391 AnemometerState *anemometerState = IoTHubDeviceTwin_LL_CreateAnemometerState(iotHubClientHandle);
392 if (anemometerState == NULL)
393 {
394 printf("Failure in IoTHubDeviceTwin_LL_CreateAnemometerState");
395 }
396 else
397 {
398 (void)printf("IoTHubDeviceTwin_LL_CreateAnemometerState...successful.\r\n");
399 }
400 AnemometerSettings *anemometerSettings = IoTHubDeviceTwin_LL_CreateAnemometerSettings(iotHubClientHandle);
401 if (anemometerSettings == NULL)
402 {
403 printf("Failure in IoTHubDeviceTwin_LL_CreateAnemometerSettings");
404 }
405 else
406 {
407 (void)printf("IoTHubDeviceTwin_LL_CreateAnemometerSettings...successful.\r\n");
408 }
409 ContosoAnemometer* myWeather = CREATE_MODEL_INSTANCE(WeatherStation, ContosoAnemometer);
410 if (myWeather == NULL)
411 {
412 (void)printf("Failed on CREATE_MODEL_INSTANCE\r\n");
413 }
414 else if (IoTHubClient_LL_SetDeviceMethodCallback(iotHubClientHandle, ReceiveDeviceMethodCallback, myWeather) != IOTHUB_CLIENT_OK)
415 {
416 (void)printf("ERROR: IoTHubClient_LL_SetDeviceMethodCallback..........FAILED!\r\n");
417 }
418 else
419 {
420 (void)printf("IoTHubClient_LL_SetDeviceMethodCallback...successful.\r\n");
421 }
422 /* Setting Message call back, so we can receive Commands. */
423 if (IoTHubClient_LL_SetMessageCallback(iotHubClientHandle, ReceiveMessageCallback, &receiveContext) != IOTHUB_CLIENT_OK)
424 {
425 (void)printf("ERROR: IoTHubClient_LL_SetMessageCallback..........FAILED!\r\n");
426 }
427 else
428 {
429 (void)printf("IoTHubClient_LL_SetMessageCallback...successful.\r\n");
430 }
431
432 /* Now that we are ready to receive commands, let's send some messages */
433 int iterator = 4000;
434 do
435 {
436 if (iterator >= 5000)
437 {
438 iterator = 0;
439 int msgPos = msg_id % MESSAGE_COUNT;
440 unsigned char *msgText;
441 size_t msgSize;
442 myWeather->windSpeed = avgWindSpeed + (rand() % 4 + 2);
443 myWeather->temperature = minTemperature + (rand() % 10);
444 myWeather->humidity = minHumidity + (rand() % 20);
445 if (SERIALIZE(&msgText, &msgSize, myWeather->windSpeed, myWeather->temperature, myWeather->humidity) != CODEFIRST_OK)
446 {
447 (void)printf("Failed to serialize\r\n");
448 }
449 else if ((messages[msgPos].messageHandle = IoTHubMessage_CreateFromByteArray((const unsigned char*)msgText, msgSize)) == NULL)
450 {
451 (void)printf("ERROR: iotHubMessageHandle is NULL!\r\n");
452 free(msgText);
453 }
454 else
455 {
456 MAP_HANDLE propMap;
457
458 messages[msgPos].messageTrackingId = msg_id;
459
460 propMap = IoTHubMessage_Properties(messages[msgPos].messageHandle);
461 (void)sprintf_s(propText, sizeof(propText), myWeather->temperature > anemometerSettings->threshold.value ? "true" : "false");
462 if (Map_AddOrUpdate(propMap, "temperatureAlert", propText) != MAP_OK)
463 {
464 (void)printf("ERROR: Map_AddOrUpdate Failed!\r\n");
465 }
466
467 if (proto == 0) {
468 (void)IoTHubMessage_SetContentTypeSystemProperty(messages[msgPos].messageHandle, "application/json");
469 (void)IoTHubMessage_SetContentEncodingSystemProperty(messages[msgPos].messageHandle, "utf-8");
470 }
471
472 if (IoTHubClient_LL_SendEventAsync(iotHubClientHandle, messages[msgPos].messageHandle, SendConfirmationCallback, &messages[msgPos]) != IOTHUB_CLIENT_OK)
473 {
474 (void)printf("ERROR: IoTHubClient_LL_SendEventAsync..........FAILED!\r\n");
475 }
476 else
477 {
478 (void)printf("IoTHubClient_LL_SendEventAsync accepted message [%d] for transmission to IoT Hub.\r\n", msg_id);
479 }
480
481 free(msgText);
482 msg_id++;
483 }
484 }
485 else if (g_twinReport) {
486 g_twinReport = false;
487 anemometerState->threshold.value = anemometerSettings->threshold.value;
488 anemometerState->threshold.status = "success";
489 IoTHubDeviceTwin_LL_SendReportedStateAnemometerState(anemometerState, anemometerReportedStateCallback, anemometerState);
490 }
491 iterator++;
492
493 IoTHubClient_LL_DoWork(iotHubClientHandle);
494 ThreadAPI_Sleep(1);
495
496 } while (g_continueRunning);
497
498 (void)printf("iothub_client_run has gotten quit message, call DoWork %d more time to complete final sending...\r\n", DOWORK_LOOP_NUM);
499 for (size_t index = 0; index < DOWORK_LOOP_NUM; index++)
500 {
501 IoTHubClient_LL_DoWork(iotHubClientHandle);
502 ThreadAPI_Sleep(1);
503 }
504
505 if (anemometerSettings != NULL)
506 IoTHubDeviceTwin_LL_DestroyAnemometerSettings(anemometerSettings);
507 if (anemometerState != NULL)
508 IoTHubDeviceTwin_LL_DestroyAnemometerState(anemometerState);
509 if (myWeather != NULL)
510 DESTROY_MODEL_INSTANCE(myWeather);
511 IoTHubClient_LL_Destroy(iotHubClientHandle);
512 }
513 serializer_deinit();
514 }
515 platform_deinit();
516 }
517}
518
519void iothub_client_init()
520{
521#if 0
522 char *set_cs_argv[2] = {
523 "set_cs",
524 "[device connection string]"
525 };
526 set_cs_main(2, set_cs_argv);
527
528 char *set_proxy_argv[2] = {
529 "set_proxy",
530 "example.com:8080"
531 };
532 set_proxy_main(2, set_proxy_argv);
533#endif
534}
535
536int iothub_client_main(int argc, char **argv)
537{
538 if (connectionString == NULL) {
539 printf("Not set connection string, use 'device csgen' or 'device setcs'.\n");
540 return 0;
541 }
542
543 if (argc < 2) {
544 iothub_client_run(1);
545 return 0;
546 }
547
548 if (strcmp(argv[1], "http") == 0) {
549 iothub_client_run(0);
550 return 0;
551 }
552 else if (strcmp(argv[1], "mqtt") == 0) {
553 iothub_client_run(1);
554 return 0;
555 }
556 else if (strcmp(argv[1], "mqttows") == 0) {
557 iothub_client_run(2);
558 return 0;
559 }
560
561 printf("%s [http|mqtt|mqttows] \n", argv[0]);
562 return 0;
563}
Note: See TracBrowser for help on using the repository browser.