source: azure_iot_hub_f767zi/trunk/azure_iot_sdk/provisioning_client/src/prov_device_client.c@ 457

Last change on this file since 457 was 457, 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: 12.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 <stdlib.h>
5
6#include <signal.h>
7#include "azure_c_shared_utility/gballoc.h"
8#include "azure_c_shared_utility/threadapi.h"
9#include "azure_c_shared_utility/lock.h"
10#include "azure_c_shared_utility/xlogging.h"
11
12#include "azure_prov_client/prov_device_ll_client.h"
13#include "azure_prov_client/prov_device_client.h"
14#include "azure_c_shared_utility/vector.h"
15
16#define DO_WORK_FREQ_DEFAULT 1
17
18static const char* const OPTION_DO_WORK_FREQUENCY_IN_MS = "do_work_freq_ms";
19
20typedef struct PROV_DEVICE_INSTANCE_TAG
21{
22 PROV_DEVICE_LL_HANDLE ProvDeviceLLHandle;
23 THREAD_HANDLE ThreadHandle;
24 LOCK_HANDLE LockHandle;
25 sig_atomic_t StopThread;
26 uint16_t do_work_freq_ms;
27} PROV_DEVICE_INSTANCE;
28
29static int ScheduleWork_Thread(void* threadArgument)
30{
31 PROV_DEVICE_INSTANCE* prov_device_instance = (PROV_DEVICE_INSTANCE*)threadArgument;
32 uint16_t sleeptime_in_ms = DO_WORK_FREQ_DEFAULT;
33
34 srand((unsigned int)get_time(NULL));
35
36 while (1)
37 {
38 if (Lock(prov_device_instance->LockHandle) == LOCK_OK)
39 {
40 if (prov_device_instance->StopThread)
41 {
42 (void)Unlock(prov_device_instance->LockHandle);
43 break; /*gets out of the thread*/
44 }
45 else
46 {
47 Prov_Device_LL_DoWork(prov_device_instance->ProvDeviceLLHandle);
48 sleeptime_in_ms = prov_device_instance->do_work_freq_ms; // Update the sleepval within the locked thread.
49 (void)Unlock(prov_device_instance->LockHandle);
50 }
51 }
52 else
53 {
54 LogError("Lock failed, shall retry");
55 }
56 (void)ThreadAPI_Sleep(sleeptime_in_ms);
57 }
58
59 ThreadAPI_Exit(0);
60 return 0;
61}
62
63static PROV_DEVICE_RESULT StartWorkerThreadIfNeeded(PROV_DEVICE_INSTANCE* prov_device_instance)
64{
65 PROV_DEVICE_RESULT result;
66 if (prov_device_instance->ThreadHandle == NULL)
67 {
68 prov_device_instance->StopThread = 0;
69 if (ThreadAPI_Create(&prov_device_instance->ThreadHandle, ScheduleWork_Thread, prov_device_instance) != THREADAPI_OK)
70 {
71 LogError("ThreadAPI_Create failed");
72 result = PROV_DEVICE_RESULT_ERROR;
73 }
74 else
75 {
76 result = PROV_DEVICE_RESULT_OK;
77 }
78 }
79 else
80 {
81 result = PROV_DEVICE_RESULT_OK;
82 }
83 return result;
84}
85
86PROV_DEVICE_HANDLE Prov_Device_Create(const char* uri, const char* id_scope, PROV_DEVICE_TRANSPORT_PROVIDER_FUNCTION protocol)
87{
88 PROV_DEVICE_INSTANCE* result;
89
90 /* Codes_SRS_PROV_DEVICE_CLIENT_12_001: [ If any of the input parameter is NULL `Prov_Device_Create` shall return NULL.] */
91 if (uri == NULL || id_scope == NULL || protocol == NULL)
92 {
93 LogError("Invalid parameter specified uri: %p, id_scope: %p, protocol: %p", uri, id_scope, protocol);
94 result = NULL;
95 }
96 else
97 {
98 /* Codes_SRS_PROV_DEVICE_CLIENT_12_002: [ The function shall allocate memory for PROV_DEVICE_INSTANCE data structure. ] */
99 result = (PROV_DEVICE_INSTANCE*)malloc(sizeof(PROV_DEVICE_INSTANCE));
100 if (result == NULL)
101 {
102 /* Codes_SRS_PROV_DEVICE_CLIENT_12_003: [ If the memory allocation failed the function shall return NULL. ] */
103 LogError("Unable to allocate Instance Info");
104 }
105 else
106 {
107 memset(result, 0, sizeof(PROV_DEVICE_INSTANCE) );
108 /* Codes_SRS_PROV_DEVICE_CLIENT_12_004: [ The function shall initialize the Lock. ] */
109 result->LockHandle = Lock_Init();
110 if (result->LockHandle == NULL)
111 {
112 /* Codes_SRS_PROV_DEVICE_CLIENT_12_005: [ If the Lock initialization failed the function shall clean up the all resources and return NULL. ] */
113 LogError("Lock_Init failed");
114 free(result);
115 result = NULL;
116 }
117 else
118 {
119 /* Codes_SRS_PROV_DEVICE_CLIENT_12_006: [ The function shall call the LL layer Prov_Device_LL_Create function and return with it's result. ] */
120 result->ProvDeviceLLHandle = Prov_Device_LL_Create(uri, id_scope, protocol);
121 if (result->ProvDeviceLLHandle == NULL)
122 {
123 /* Codes_SRS_PROV_DEVICE_CLIENT_12_025: [ If the Client initialization failed the function shall clean up the all resources and return NULL. ] */
124 LogError("Prov_Device_LL_Create failed");
125 free(result);
126 result = NULL;
127 }
128 else
129 {
130 /* Codes_SRS_PROV_DEVICE_CLIENT_12_007: [ The function shall initialize the result datastructure. ] */
131 result->ThreadHandle = NULL;
132 result->StopThread = 0;
133 result->do_work_freq_ms = DO_WORK_FREQ_DEFAULT;
134 }
135 }
136 }
137 }
138
139 return result;
140}
141
142void Prov_Device_Destroy(PROV_DEVICE_HANDLE prov_device_handle)
143{
144 /* Codes_SRS_PROV_DEVICE_CLIENT_12_008: [ If the input parameter is NULL `Prov_Device_Destroy` shall return. ] */
145 if (prov_device_handle == NULL)
146 {
147 LogError("NULL prov_device_handle");
148 }
149 else
150 {
151 PROV_DEVICE_INSTANCE* prov_device_instance = (PROV_DEVICE_INSTANCE*)prov_device_handle;
152
153 if (Lock(prov_device_handle->LockHandle) != LOCK_OK)
154 {
155 /* Codes_SRS_PROV_DEVICE_CLIENT_12_009: [ The function shall check the Lock status and if it is not OK set the thread signal to stop. ] */
156 LogError("Could not acquire lock");
157 prov_device_handle->StopThread = 1; /*setting it even when Lock fails*/
158 }
159 else
160 {
161 /* Codes_SRS_PROV_DEVICE_CLIENT_12_010: [ The function shall check the Lock status and if it is OK set the thread signal to stop and unlock the Lock. ] */
162 prov_device_handle->StopThread = 1;
163
164 (void)Unlock(prov_device_handle->LockHandle);
165 }
166
167 /* Codes_SRS_PROV_DEVICE_CLIENT_12_011: [ If there is a running worker thread the function shall call join to finish. ] */
168 if (prov_device_handle->ThreadHandle != NULL)
169 {
170 int res;
171 if (ThreadAPI_Join(prov_device_handle->ThreadHandle, &res) != THREADAPI_OK)
172 {
173 LogError("ThreadAPI_Join failed");
174 }
175 }
176
177 /* Codes_SRS_PROV_DEVICE_CLIENT_12_012: [ The function shall call the LL layer Prov_Device_LL_Destroy with the given handle. ] */
178 Prov_Device_LL_Destroy(prov_device_instance->ProvDeviceLLHandle);
179
180 /* Codes_SRS_PROV_DEVICE_CLIENT_12_013: [ The function shall free the Lock resource with de-init. ] */
181 Lock_Deinit(prov_device_instance->LockHandle);
182
183 /* Codes_SRS_PROV_DEVICE_CLIENT_12_014: [ The function shall free the device handle resource. ] */
184 free(prov_device_instance);
185 }
186}
187
188PROV_DEVICE_RESULT Prov_Device_Register_Device(PROV_DEVICE_HANDLE prov_device_handle, PROV_DEVICE_CLIENT_REGISTER_DEVICE_CALLBACK register_callback, void* user_context, PROV_DEVICE_CLIENT_REGISTER_STATUS_CALLBACK register_status_callback, void* status_user_context)
189{
190 PROV_DEVICE_RESULT result;
191
192 /* Codes_SRS_PROV_DEVICE_CLIENT_12_015: [ If the prov_device_handle or register_callback input parameter is NULL `Prov_Device_Register_Device` shall return with invalid argument error. ] */
193 if (prov_device_handle == NULL || register_callback == NULL)
194 {
195 LogError("Invalid parameter specified prov_device_handle: %p, register_callback: %p", prov_device_handle, register_callback);
196 result = PROV_DEVICE_RESULT_INVALID_ARG;
197 }
198 else
199 {
200 PROV_DEVICE_INSTANCE* prov_device_instance = (PROV_DEVICE_INSTANCE*)prov_device_handle;
201
202 /* Codes_SRS_PROV_DEVICE_CLIENT_12_018: [ The function shall try to lock the Lock. ] */
203 if (Lock(prov_device_instance->LockHandle) != LOCK_OK)
204 {
205 /* Codes_SRS_PROV_DEVICE_CLIENT_12_019: [ If the locking failed the function shall return with error. ] */
206 LogError("Could not acquire lock");
207 result = PROV_DEVICE_RESULT_ERROR;
208 }
209 else
210 {
211 /* Codes_SRS_PROV_DEVICE_CLIENT_12_020: [ The function shall call the LL layer Prov_Device_LL_Register_Device with the given parameters and return with the result. ] */
212 result = Prov_Device_LL_Register_Device(prov_device_instance->ProvDeviceLLHandle, register_callback, user_context, register_status_callback, status_user_context);
213
214 /* Codes_SRS_PROV_DEVICE_CLIENT_12_021: [ The function shall unlock the Lock. ] */
215 (void)Unlock(prov_device_instance->LockHandle);
216
217 if (result == PROV_DEVICE_RESULT_OK)
218 {
219 /* Codes_SRS_PROV_DEVICE_CLIENT_12_016: [ The function shall start a worker thread with the device instance. ] */
220 if ((result = StartWorkerThreadIfNeeded(prov_device_instance)) != PROV_DEVICE_RESULT_OK)
221 {
222 /* Codes_SRS_PROV_DEVICE_CLIENT_12_017: [ If the thread initialization failed the function shall return error. ] */
223 LogError("Could not start worker thread");
224 result = PROV_DEVICE_RESULT_ERROR;
225 }
226 }
227 }
228 }
229
230 return result;
231}
232
233PROV_DEVICE_RESULT Prov_Device_SetOption(PROV_DEVICE_HANDLE prov_device_handle, const char* optionName, const void* value)
234{
235 PROV_DEVICE_RESULT result;
236
237 /* Codes_SRS_PROV_DEVICE_CLIENT_12_022: [ If any of the input parameter is NULL `Prov_Device_SetOption` shall return with invalid argument error. ] */
238 if (
239 (prov_device_handle == NULL) ||
240 (optionName == NULL) ||
241 (value == NULL)
242 )
243 {
244 result = PROV_DEVICE_RESULT_INVALID_ARG;
245 LogError("Invalid parameter specified prov_device_handle: %p, optionName: %p, value: %p", prov_device_handle, optionName, value);
246 }
247 else
248 {
249 /* Codes_SRS_PROV_DEVICE_CLIENT_12_023: [ The function shall call the LL layer Prov_Device_LL_SetOption with the given parameters and return with the result. ] */
250 PROV_DEVICE_INSTANCE* prov_device_instance = (PROV_DEVICE_INSTANCE*)prov_device_handle;
251
252 /* Codes_SRS_PROV_DEVICE_CLIENT_41_002: [ `Prov_Device_SetOption` shall be made thread-safe by using the lock created in `Prov_Device_Create`. ] */
253 if (Lock(prov_device_instance->LockHandle) != LOCK_OK)
254 {
255 /* Codes_SRS_PROV_DEVICE_CLIENT_41_003: [ If acquiring the lock fails, `Prov_Device_SetOption` shall return `IOTHUB_CLIENT_ERROR`. ] */
256 result = PROV_DEVICE_RESULT_ERROR;
257 LogError("Could not acquire lock");
258 }
259 else
260 {
261 /* Codes_SRS_PROV_DEVICE_CLIENT_41_001: [ If parameter `optionName` is `OPTION_DO_WORK_FREQUENCY_IN_MS` then `IoTHubClientCore_SetOption` shall set `do_work_freq_ms` parameter of `prov_device_instance` ] */
262 if (strcmp(OPTION_DO_WORK_FREQUENCY_IN_MS, optionName) == 0)
263 {
264 prov_device_instance->do_work_freq_ms = *((uint16_t *)value);
265 result = PROV_DEVICE_RESULT_OK;
266 }
267 else
268 {
269 result = Prov_Device_LL_SetOption(prov_device_instance->ProvDeviceLLHandle, optionName, value);
270 if (result != PROV_DEVICE_RESULT_OK)
271 {
272 LogError("Prov_Device_LL_SetOption failed");
273 }
274 }
275 (void)Unlock(prov_device_instance->LockHandle);
276 }
277 }
278 return result;
279}
280
281const char* Prov_Device_GetVersionString(void)
282{
283 /* Codes_SRS_PROV_DEVICE_CLIENT_12_024: [ The function shall call the LL layer Prov_Device_LL_GetVersionString and return with the result. ] */
284 return Prov_Device_LL_GetVersionString();
285}
286
287PROV_DEVICE_RESULT Prov_Device_Set_Provisioning_Payload(PROV_DEVICE_HANDLE handle, const char* json)
288{
289 PROV_DEVICE_RESULT result;
290 if (handle == NULL)
291 {
292 LogError("Invalid parameter specified handle: %p", handle);
293 result = PROV_DEVICE_RESULT_INVALID_ARG;
294 }
295 else
296 {
297 result = Prov_Device_LL_Set_Provisioning_Payload(handle->ProvDeviceLLHandle, json);
298 }
299 return result;
300}
301
302const char* Prov_Device_Get_Provisioning_Payload(PROV_DEVICE_HANDLE handle)
303{
304 const char* result;
305 if (handle == NULL)
306 {
307 LogError("Invalid parameter specified handle: %p", handle);
308 result = NULL;
309 }
310 else
311 {
312 result = Prov_Device_LL_Get_Provisioning_Payload(handle->ProvDeviceLLHandle);
313 }
314 return result;
315}
316
Note: See TracBrowser for help on using the repository browser.