1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11 #include "nx_azure_iot_hub_client_properties.h"
12
13 extern UINT nx_azure_iot_hub_client_adjust_payload(NX_PACKET *packet_ptr);
14 VOID nx_azure_iot_hub_client_properties_component_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
15 NX_PACKET *packet_ptr, UINT message_type);
16
nx_azure_iot_hub_client_reported_properties_component_begin(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_AZURE_IOT_JSON_WRITER * writer_ptr,const UCHAR * component_name_ptr,USHORT component_name_length)17 UINT nx_azure_iot_hub_client_reported_properties_component_begin(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
18 NX_AZURE_IOT_JSON_WRITER *writer_ptr,
19 const UCHAR *component_name_ptr,
20 USHORT component_name_length)
21 {
22 az_result core_result;
23 az_span component_name;
24
25 if ((hub_client_ptr == NX_NULL) ||
26 (writer_ptr == NX_NULL) ||
27 (component_name_ptr == NX_NULL) ||
28 (component_name_length == 0))
29 {
30 LogError(LogLiteralArgs("IoT PnP reported property begin fail: INVALID POINTER"));
31 return(NX_AZURE_IOT_INVALID_PARAMETER);
32 }
33
34 component_name = az_span_create((UCHAR *)component_name_ptr, (INT)component_name_length);
35
36 core_result = az_iot_hub_client_properties_writer_begin_component(&(hub_client_ptr -> iot_hub_client_core),
37 &(writer_ptr -> json_writer), component_name);
38 if (az_result_failed(core_result))
39 {
40 LogError(LogLiteralArgs("IoT PnP failed to append component, core error : %d"), core_result);
41 return(NX_AZURE_IOT_SDK_CORE_ERROR);
42 }
43
44 return(NX_AZURE_IOT_SUCCESS);
45 }
46
nx_azure_iot_hub_client_reported_properties_component_end(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_AZURE_IOT_JSON_WRITER * writer_ptr)47 UINT nx_azure_iot_hub_client_reported_properties_component_end(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
48 NX_AZURE_IOT_JSON_WRITER *writer_ptr)
49 {
50 az_result core_result;
51
52 if ((hub_client_ptr == NX_NULL) ||
53 (writer_ptr == NX_NULL))
54 {
55 LogError(LogLiteralArgs("IoT PnP reported property end fail: INVALID POINTER"));
56 return(NX_AZURE_IOT_INVALID_PARAMETER);
57 }
58
59 core_result = az_iot_hub_client_properties_writer_end_component(&(hub_client_ptr -> iot_hub_client_core),
60 &(writer_ptr -> json_writer));
61 if (az_result_failed(core_result))
62 {
63 LogError(LogLiteralArgs("IoT PnP failed to append component, core error : %d"), core_result);
64 return(NX_AZURE_IOT_SDK_CORE_ERROR);
65 }
66
67 return(NX_AZURE_IOT_SUCCESS);
68 }
69
nx_azure_iot_hub_client_reported_properties_status_begin(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_AZURE_IOT_JSON_WRITER * writer_ptr,const UCHAR * property_name_ptr,UINT property_name_length,UINT status_code,ULONG version,const UCHAR * description_ptr,UINT description_length)70 UINT nx_azure_iot_hub_client_reported_properties_status_begin(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
71 NX_AZURE_IOT_JSON_WRITER *writer_ptr,
72 const UCHAR *property_name_ptr, UINT property_name_length,
73 UINT status_code, ULONG version,
74 const UCHAR *description_ptr, UINT description_length)
75 {
76 az_span property_name;
77 az_span description;
78 az_result core_result;
79
80 if ((hub_client_ptr == NX_NULL) ||
81 (writer_ptr == NX_NULL) ||
82 (property_name_ptr == NX_NULL) ||
83 (property_name_length == 0) )
84 {
85 LogError(LogLiteralArgs("IoT PnP client begin reported status failed: INVALID POINTER"));
86 return(NX_AZURE_IOT_INVALID_PARAMETER);
87 }
88
89 property_name = az_span_create((UCHAR *)property_name_ptr, (INT)property_name_length);
90 description = az_span_create((UCHAR *)description_ptr, (INT)description_length);
91
92 core_result = az_iot_hub_client_properties_writer_begin_response_status(&(hub_client_ptr -> iot_hub_client_core),
93 &(writer_ptr -> json_writer),
94 property_name, (int32_t)status_code,
95 (int32_t)version, description);
96 if (az_result_failed(core_result))
97 {
98 LogError(LogLiteralArgs("Failed to prefix data with core error : %d"), core_result);
99 return(NX_AZURE_IOT_SDK_CORE_ERROR);
100 }
101
102 return(NX_AZURE_IOT_SUCCESS);
103 }
104
nx_azure_iot_hub_client_reported_properties_status_end(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_AZURE_IOT_JSON_WRITER * writer_ptr)105 UINT nx_azure_iot_hub_client_reported_properties_status_end(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
106 NX_AZURE_IOT_JSON_WRITER *writer_ptr)
107 {
108 az_result core_result;
109
110 if ((hub_client_ptr == NX_NULL) ||
111 (writer_ptr == NX_NULL))
112 {
113 LogError(LogLiteralArgs("IoT PnP client end reported status failed: INVALID POINTER"));
114 return(NX_AZURE_IOT_INVALID_PARAMETER);
115 }
116
117 core_result = az_iot_hub_client_properties_writer_end_response_status(&(hub_client_ptr -> iot_hub_client_core),
118 &(writer_ptr -> json_writer));
119 if (az_result_failed(core_result))
120 {
121 LogError(LogLiteralArgs("Failed to suffix data with core error : %d"), core_result);
122 return(NX_AZURE_IOT_SDK_CORE_ERROR);
123 }
124
125 return(NX_AZURE_IOT_SUCCESS);
126 }
127
nx_azure_iot_hub_client_properties_version_get(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_AZURE_IOT_JSON_READER * reader_ptr,UINT message_type,ULONG * version_ptr)128 UINT nx_azure_iot_hub_client_properties_version_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
129 NX_AZURE_IOT_JSON_READER *reader_ptr,
130 UINT message_type, ULONG *version_ptr)
131 {
132 az_result core_result;
133 az_iot_hub_client_properties_message_type core_message_type;
134
135 if ((hub_client_ptr == NX_NULL) ||
136 (reader_ptr == NX_NULL) ||
137 (version_ptr == NX_NULL) ||
138 ((message_type != NX_AZURE_IOT_HUB_PROPERTIES) &&
139 (message_type != NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES)))
140 {
141 LogError(LogLiteralArgs("IoTHub client get properties version failed: INVALID POINTER"));
142 return(NX_AZURE_IOT_INVALID_PARAMETER);
143 }
144
145 core_message_type = (message_type == NX_AZURE_IOT_HUB_PROPERTIES) ? AZ_IOT_HUB_CLIENT_PROPERTIES_MESSAGE_TYPE_GET_RESPONSE :
146 AZ_IOT_HUB_CLIENT_PROPERTIES_MESSAGE_TYPE_WRITABLE_UPDATED;
147
148 core_result = az_iot_hub_client_properties_get_properties_version(&(hub_client_ptr -> iot_hub_client_core),
149 &(reader_ptr -> json_reader),
150 core_message_type,
151 (int32_t *)version_ptr);
152 if (az_result_failed(core_result))
153 {
154 LogError(LogLiteralArgs("IoTHub client get properties version failed : %d"), core_result);
155 return(NX_AZURE_IOT_SDK_CORE_ERROR);
156 }
157
158 return(NX_AZURE_IOT_SUCCESS);
159 }
160
nx_azure_iot_hub_client_properties_component_property_next_get_internal(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_AZURE_IOT_JSON_READER * reader_ptr,UINT message_type,UINT property_type,const UCHAR ** component_name_pptr,USHORT * component_name_length_ptr,UINT * component_index,UINT parse_system_component)161 static UINT nx_azure_iot_hub_client_properties_component_property_next_get_internal(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
162 NX_AZURE_IOT_JSON_READER *reader_ptr,
163 UINT message_type, UINT property_type,
164 const UCHAR **component_name_pptr,
165 USHORT *component_name_length_ptr,
166 UINT *component_index,
167 UINT parse_system_component)
168 {
169 az_span component_name;
170 az_iot_hub_client_properties_message_type core_message_type;
171 az_iot_hub_client_property_type core_property_type;
172 az_result core_result;
173 UINT index;
174 UINT system_component;
175
176 if (((message_type != NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES) &&
177 (message_type != NX_AZURE_IOT_HUB_PROPERTIES)) ||
178 ((property_type != NX_AZURE_IOT_HUB_CLIENT_PROPERTY_REPORTED_FROM_DEVICE) &&
179 (property_type != NX_AZURE_IOT_HUB_CLIENT_PROPERTY_WRITABLE)) ||
180 ((property_type == NX_AZURE_IOT_HUB_CLIENT_PROPERTY_REPORTED_FROM_DEVICE) &&
181 (message_type != NX_AZURE_IOT_HUB_PROPERTIES)))
182 {
183 LogError(LogLiteralArgs("Invalid response type or property type passed"));
184 return(NX_AZURE_IOT_INVALID_PARAMETER);
185 }
186
187 component_name = az_span_create((UCHAR *)*component_name_pptr, (INT)*component_name_length_ptr);
188 core_message_type = (message_type == NX_AZURE_IOT_HUB_PROPERTIES) ? AZ_IOT_HUB_CLIENT_PROPERTIES_MESSAGE_TYPE_GET_RESPONSE :
189 AZ_IOT_HUB_CLIENT_PROPERTIES_MESSAGE_TYPE_WRITABLE_UPDATED;
190 core_property_type = (property_type == NX_AZURE_IOT_HUB_CLIENT_PROPERTY_REPORTED_FROM_DEVICE) ? AZ_IOT_HUB_CLIENT_PROPERTY_REPORTED_FROM_DEVICE :
191 AZ_IOT_HUB_CLIENT_PROPERTY_WRITABLE;
192
193 do
194 {
195 core_result = az_iot_hub_client_properties_get_next_component_property(&(hub_client_ptr -> iot_hub_client_core),
196 &(reader_ptr -> json_reader),
197 core_message_type, core_property_type,
198 &component_name);
199 if (core_result == AZ_ERROR_IOT_END_OF_PROPERTIES)
200 {
201 return(NX_AZURE_IOT_NOT_FOUND);
202 }
203 else if (az_result_failed(core_result))
204 {
205 LogError(LogLiteralArgs("Failed to parse document with core error : %d"), core_result);
206 return(NX_AZURE_IOT_SDK_CORE_ERROR);
207 }
208
209 *component_name_pptr = az_span_ptr(component_name);
210 *component_name_length_ptr = (USHORT)az_span_size(component_name);
211
212 /* Check if it is system component. */
213 system_component = NX_FALSE;
214 for (index = 0; index < (UINT)hub_client_ptr -> iot_hub_client_core._internal.options.component_names_length; index++)
215 {
216 if ((az_span_is_content_equal(component_name, hub_client_ptr -> nx_azure_iot_hub_client_component_list[index]))&&
217 (hub_client_ptr -> nx_azure_iot_hub_client_component_callback[index] != NX_NULL))
218 {
219 system_component = NX_TRUE;
220 break;
221 }
222 }
223
224 /* System component. */
225 if ((parse_system_component == NX_TRUE) && (system_component == NX_TRUE))
226 {
227 *component_index = index;
228 return(NX_AZURE_IOT_SUCCESS);
229 }
230 else if ((parse_system_component == NX_FALSE) && (system_component == NX_FALSE))
231 {
232 return(NX_AZURE_IOT_SUCCESS);
233 }
234
235 /* Skip it and find the next one. */
236 nx_azure_iot_json_reader_next_token(reader_ptr);
237
238 /* Skip children in case the property value is an object. */
239 if (nx_azure_iot_json_reader_token_type(reader_ptr) == NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT)
240 {
241 nx_azure_iot_json_reader_skip_children(reader_ptr);
242 }
243 nx_azure_iot_json_reader_next_token(reader_ptr);
244
245 } while(1);
246 }
247
nx_azure_iot_hub_client_properties_component_property_next_get(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_AZURE_IOT_JSON_READER * reader_ptr,UINT message_type,UINT property_type,const UCHAR ** component_name_pptr,USHORT * component_name_length_ptr)248 UINT nx_azure_iot_hub_client_properties_component_property_next_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
249 NX_AZURE_IOT_JSON_READER *reader_ptr,
250 UINT message_type, UINT property_type,
251 const UCHAR **component_name_pptr,
252 USHORT *component_name_length_ptr)
253 {
254
255 UINT status;
256
257 if ((hub_client_ptr == NX_NULL) ||
258 (reader_ptr == NX_NULL) ||
259 (component_name_pptr == NX_NULL) ||
260 (component_name_length_ptr == NX_NULL))
261 {
262 LogError(LogLiteralArgs("IoTHub client component next property failed: INVALID POINTER"));
263 return(NX_AZURE_IOT_INVALID_PARAMETER);
264 }
265
266 status = nx_azure_iot_hub_client_properties_component_property_next_get_internal(hub_client_ptr, reader_ptr,
267 message_type, property_type,
268 component_name_pptr, component_name_length_ptr,
269 NX_NULL, NX_FALSE);
270
271 return(status);
272 }
273
nx_azure_iot_hub_client_properties_component_process(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_PACKET * packet_ptr,UINT message_type)274 VOID nx_azure_iot_hub_client_properties_component_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
275 NX_PACKET *packet_ptr, UINT message_type)
276 {
277
278 UINT status;
279 ULONG version;
280 NX_AZURE_IOT_JSON_READER reader_ptr;
281 const UCHAR *component_name_ptr = NX_NULL;
282 USHORT component_name_length = 0;
283 UINT component_index;
284 UCHAR *prepend_ptr = NX_NULL;
285
286
287 /* Check the message type. */
288 if ((message_type != NX_AZURE_IOT_HUB_PROPERTIES) &&
289 (message_type != NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES))
290 {
291 return;
292 }
293
294 /* Record the prepend pointer. */
295 prepend_ptr = packet_ptr -> nx_packet_prepend_ptr;
296
297 if (nx_azure_iot_hub_client_adjust_payload(packet_ptr))
298 {
299 return;
300 }
301
302 if (nx_azure_iot_json_reader_init(&reader_ptr, packet_ptr))
303 {
304
305 /* Recover the prepend pointer since other functions will retreive the topic again. */
306 packet_ptr -> nx_packet_length += (ULONG)(packet_ptr -> nx_packet_prepend_ptr - prepend_ptr);
307 packet_ptr -> nx_packet_prepend_ptr = prepend_ptr;
308 return;
309 }
310
311 /* Get the version. */
312 status = nx_azure_iot_hub_client_properties_version_get(hub_client_ptr, &reader_ptr,
313 message_type, &version);
314 if (status)
315 {
316
317 /* Recover the prepend pointer since other functions will retreive the topic again. */
318 packet_ptr -> nx_packet_length += (ULONG)(packet_ptr -> nx_packet_prepend_ptr - prepend_ptr);
319 packet_ptr -> nx_packet_prepend_ptr = prepend_ptr;
320 return;
321 }
322
323 /* Re-initialize the JSON reader state */
324 if (nx_azure_iot_json_reader_init(&reader_ptr, packet_ptr))
325 {
326
327 /* Recover the prepend pointer since other functions will retreive the topic again. */
328 packet_ptr -> nx_packet_length += (ULONG)(packet_ptr -> nx_packet_prepend_ptr - prepend_ptr);
329 packet_ptr -> nx_packet_prepend_ptr = prepend_ptr;
330 return;
331 }
332
333 /* Loop to process system component. */
334 while (nx_azure_iot_hub_client_properties_component_property_next_get_internal(hub_client_ptr,
335 &reader_ptr, message_type,
336 NX_AZURE_IOT_HUB_CLIENT_PROPERTY_WRITABLE,
337 &component_name_ptr, &component_name_length,
338 &component_index, NX_TRUE) == NX_AZURE_IOT_SUCCESS)
339 {
340
341 /* Check if it is system component. */
342 if ((component_name_ptr) && (component_name_length) &&
343 (hub_client_ptr -> nx_azure_iot_hub_client_component_callback[component_index]))
344 {
345 status = hub_client_ptr -> nx_azure_iot_hub_client_component_callback[component_index](&reader_ptr, version,
346 hub_client_ptr -> nx_azure_iot_hub_client_component_callback_args[component_index]);
347 if (status)
348 {
349
350 /* Recover the prepend pointer since other functions will retreive the topic again. */
351 packet_ptr -> nx_packet_length += (ULONG)(packet_ptr -> nx_packet_prepend_ptr - prepend_ptr);
352 packet_ptr -> nx_packet_prepend_ptr = prepend_ptr;
353 return;
354 }
355
356 }
357 else
358 {
359
360 /* The JSON reader must be advanced regardless of whether the property
361 is of interest or not. */
362 nx_azure_iot_json_reader_next_token(&reader_ptr);
363
364 /* Skip children in case the property value is an object. */
365 if (nx_azure_iot_json_reader_token_type(&reader_ptr) == NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT)
366 {
367 nx_azure_iot_json_reader_skip_children(&reader_ptr);
368 }
369 nx_azure_iot_json_reader_next_token(&reader_ptr);
370 }
371 }
372
373 /* Recover the prepend pointer since other functions will retreive the topic again. */
374 packet_ptr -> nx_packet_length += (ULONG)(packet_ptr -> nx_packet_prepend_ptr - prepend_ptr);
375 packet_ptr -> nx_packet_prepend_ptr = prepend_ptr;
376
377 return;
378 }
379