• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <string.h>
17 #include <hi_mem.h>
18 #include <cJSON.h>
19 #include "iot_log.h"
20 #include "iot_profile.h"
21 
22 // format the report data to json string mode
FormatProfileValue(IoTProfileKV * kv)23 static cJSON *FormatProfileValue(IoTProfileKV *kv)
24 {
25     cJSON  *ret = NULL;
26     switch (kv->type) {
27         case EN_IOT_DATATYPE_INT:
28             ret = cJSON_CreateNumber(kv->iValue);
29             break;
30         case EN_IOT_DATATYPE_LONG:
31             ret = cJSON_CreateNumber((double)(*(long *)kv->value));
32             break;
33         case EN_IOT_DATATYPE_STRING:
34             ret = cJSON_CreateString((const char *)kv->value);
35             break;
36         default:
37             break;
38     }
39     return ret;
40 }
41 
MakeKvs(IoTProfileKV * kvlst)42 static cJSON *MakeKvs(IoTProfileKV *kvlst)
43 {
44     cJSON *root;
45     cJSON *kv;
46     IoTProfileKV *kvInfo;
47 
48     // build a root node
49     root = cJSON_CreateObject();
50     if (root == NULL) {
51         return root;
52     }
53 
54     // add all the property to the properties
55     kvInfo = kvlst;
56     while (kvInfo != NULL) {
57         kv = FormatProfileValue(kvInfo);
58         if (kv == NULL) {
59             if (root != NULL) {
60                 cJSON_Delete(root);
61                 root = NULL;
62             }
63             return root;
64         }
65 
66         cJSON_AddItemToObject(root, kvInfo->key, kv);
67         kvInfo = kvInfo->nxt;
68     }
69     // OK, now we return it
70     return root;
71 }
72 
73 #define CN_PROFILE_SERVICE_KEY_SERVICEID "service_id"
74 #define CN_PROFILE_SERVICE_KEY_PROPERTIIES "properties"
75 #define CN_PROFILE_SERVICE_KEY_EVENTTIME "event_time"
76 #define CN_PROFILE_KEY_SERVICES "services"
MakeService(IoTProfileService * serviceInfo)77 static cJSON *MakeService(IoTProfileService *serviceInfo)
78 {
79     cJSON *root;
80     cJSON *serviceID;
81     cJSON *properties;
82     cJSON *eventTime;
83 
84     // build a root node
85     root = cJSON_CreateObject();
86     if (root == NULL) {
87         return root;
88     }
89 
90     // add the serviceID node to the root node
91     serviceID = cJSON_CreateString(serviceInfo->serviceID);
92     if (serviceID == NULL) {
93         if (root != NULL) {
94             cJSON_Delete(root);
95             root = NULL;
96         }
97         return root;
98     }
99     cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_SERVICEID, serviceID);
100 
101     // add the properties node to the root
102     properties = MakeKvs(serviceInfo->serviceProperty);
103     if (properties == NULL) {
104         if (root != NULL) {
105             cJSON_Delete(root);
106             cJSON_Delete(properties);
107             root = NULL;
108         }
109         return root;
110     }
111     cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_PROPERTIIES, properties);
112     // add the event time (optional) to the root
113     if (serviceInfo->eventTime != NULL) {
114         eventTime = cJSON_CreateString(serviceInfo->eventTime);
115         if (eventTime == NULL) {
116             if (root != NULL) {
117                 cJSON_Delete(root);
118                 root = NULL;
119             }
120             return root;
121         }
122         cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_EVENTTIME, eventTime);
123     }
124     // OK, now we return it
125     return root;
126 }
127 
MakeServices(IoTProfileService * serviceInfo)128 static cJSON *MakeServices(IoTProfileService *serviceInfo)
129 {
130     cJSON *services = NULL;
131     cJSON *service;
132     IoTProfileService  *serviceTmp;
133 
134     // create the services array node
135     services = cJSON_CreateArray();
136     if (services == NULL) {
137         return services;
138     }
139 
140     serviceTmp = serviceInfo;
141     while (serviceTmp != NULL) {
142         service = MakeService(serviceTmp);
143         if (service == NULL) {
144             return services;
145         }
146         cJSON_AddItemToArray(services, service);
147         serviceTmp = serviceTmp->nxt;
148     }
149 
150     // now we return the services
151     return services;
152 }
153 
154 // use this function to make a topic to publish
155 // if request_id  is needed depends on the fmt
MakeTopic(const char * fmt,const char * deviceId,const char * requestID)156 static char *MakeTopic(const char *fmt, const char *deviceId, const char *requestID)
157 {
158     int len;
159     char *ret = NULL;
160 
161     len = strlen(fmt) + strlen(deviceId);
162     if (requestID != NULL) {
163         len += strlen(requestID);
164     }
165 
166     ret = hi_malloc(0, len);
167     if (ret != NULL) {
168         if (requestID != NULL) {
169             if (snprintf_s(ret, len + 1, len, fmt, deviceId, requestID) < 0) {
170                 printf("string is null\r\n");
171             }
172         } else {
173             if (snprintf_s(ret, len + 1, len, fmt, deviceId) < 0) {
174                 printf("string is null\r\n");
175             }
176         }
177     }
178     return ret;
179 }
180 
181 #define CN_PROFILE_CMDRESP_KEY_RETCODE    "result_code"
182 #define CN_PROFILE_CMDRESP_KEY_RESPNAME    "response_name"
183 #define CN_PROFILE_CMDRESP_KEY_PARAS    "paras"
MakeProfileCmdResp(IoTCmdResp * payload)184 static char *MakeProfileCmdResp(IoTCmdResp *payload)
185 {
186     char *ret = NULL;
187     cJSON *root;
188     cJSON *retCode;
189     cJSON *respName;
190     cJSON *paras;
191 
192     // create the root node
193     root = cJSON_CreateObject();
194     if (root == NULL) {
195         return ret;
196     }
197 
198     // create retcode and retdesc and add it to the root
199     retCode = cJSON_CreateNumber(payload->retCode);
200     if (retCode == NULL) {
201         if (root != NULL) {
202             cJSON_Delete(root);
203         }
204         return ret;
205     }
206     cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_RETCODE, retCode);
207 
208     if (payload->respName != NULL) {
209         respName = cJSON_CreateString(payload->respName);
210         if (respName == NULL) {
211             if (root != NULL) {
212                 cJSON_Delete(root);
213             }
214             return ret;
215         }
216         cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_RESPNAME, respName);
217     }
218 
219     if (payload->paras != NULL) {
220         paras = MakeKvs(payload->paras);
221         if (paras == NULL) {
222             if (root != NULL) {
223                 cJSON_Delete(root);
224             }
225             return ret;
226         }
227         cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_PARAS, paras);
228     }
229 
230     // OK, now we make it to a buffer
231     ret = cJSON_PrintUnformatted(root);
232     cJSON_Delete(root);
233     return ret;
234 }
235 
236 #define CN_PROFILE_TOPICFMT_CMDRESP    "$oc/devices/%s/sys/commands/response/request_id=%s"
IoTProfileCmdResp(char * deviceID,IoTCmdResp * payload)237 int IoTProfileCmdResp(char *deviceID, IoTCmdResp *payload)
238 {
239     int ret = -1;
240     const char *topic;
241     const char *msg;
242 
243     if ((deviceID == NULL) || (payload == NULL) || (payload->requestID == NULL)) {
244         return ret;
245     }
246 
247     topic = MakeTopic(CN_PROFILE_TOPICFMT_CMDRESP, deviceID, payload->requestID);
248     if (topic == NULL) {
249         return;
250     }
251     msg = MakeProfileCmdResp(payload);
252     if ((topic != NULL) && (msg != NULL)) {
253         ret = IotSendMsg(0, topic, msg);
254     }
255 
256     hi_free(0, topic);
257     cJSON_free(msg);
258     return ret;
259 }
260 
MakeProfilePropertyReport(IoTProfileService * payload)261 static char *MakeProfilePropertyReport(IoTProfileService *payload)
262 {
263     char *ret = NULL;
264     cJSON *root;
265     cJSON *services;
266 
267     // create the root node
268     root = cJSON_CreateObject();
269     if (root == NULL) {
270         return ret;
271     }
272 
273     // create the services array node to the root
274     services = MakeServices(payload);
275     if (services == NULL) {
276         if (root != NULL) {
277             cJSON_Delete(root);
278         }
279         return ret;
280     }
281     cJSON_AddItemToObjectCS(root, CN_PROFILE_KEY_SERVICES, services);
282 
283     // OK, now we make it to a buffer
284     ret = cJSON_PrintUnformatted(root);
285     cJSON_Delete(root);
286     return ret;
287 }
288 #define CN_PROFILE_TOPICFMT_PROPERTYREPORT    "$oc/devices/%s/sys/properties/report"
IoTProfilePropertyReport(char * deviceID,IoTProfileService * payload)289 int IoTProfilePropertyReport(char *deviceID, IoTProfileService *payload)
290 {
291     int ret = -1;
292     char *topic;
293     char *msg;
294 
295     if ((deviceID == NULL) || (payload == NULL) || (payload->serviceID == NULL) || (payload->serviceProperty == NULL)) {
296         return ret;
297     }
298     topic = MakeTopic(CN_PROFILE_TOPICFMT_PROPERTYREPORT, deviceID, NULL);
299     if (topic == NULL) {
300         return;
301     }
302     msg = MakeProfilePropertyReport(payload);
303     if ((topic != NULL) && (msg != NULL)) {
304         ret = IotSendMsg(0, topic, msg);
305     }
306 
307     hi_free(0, topic);
308     cJSON_free(msg);
309     return ret;
310 }