• 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(IoTProfileKVT * kv)23 static cJSON *FormatProfileValue(IoTProfileKVT *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_FLOAT:
34             ret = cJSON_CreateNumber((double)(*(float *)kv->fvalue));
35             break;
36         case EN_IOT_DATATYPE_DOUBLE:
37             ret = cJSON_CreateNumber((*(double *)kv->dvalue));
38             break;
39         case EN_IOT_DATATYPE_STRING:
40             ret = cJSON_CreateString((const char *)kv->value);
41             break;
42         default:
43             break;
44     }
45     return ret;
46 }
47 
MakeKvs(IoTProfileKVT * kvlst)48 static cJSON *MakeKvs(IoTProfileKVT *kvlst)
49 {
50     cJSON *root;
51     cJSON *kv;
52     IoTProfileKVT *kvInfo;
53 
54     // build a root node
55     root = cJSON_CreateObject();
56     if (root == NULL) {
57         return root;
58     }
59 
60     // add all the property to the properties
61     kvInfo = kvlst;
62     while (kvInfo != NULL) {
63         kv = FormatProfileValue(kvInfo);
64         if (kv == NULL) {
65             if (root != NULL) {
66                 cJSON_Delete(root);
67                 root = NULL;
68             }
69             return root;
70         }
71 
72         cJSON_AddItemToObject(root, kvInfo->key, kv);
73         kvInfo = kvInfo->nxt;
74     }
75     // OK, now we return it
76     return root;
77 }
78 
79 #define CN_PROFILE_SERVICE_KEY_SERVICEID "service_id"
80 #define CN_PROFILE_SERVICE_KEY_PROPERTIIES "properties"
81 #define CN_PROFILE_SERVICE_KEY_EVENTTIME "event_time"
82 #define CN_PROFILE_KEY_SERVICES "services"
MakeService(IoTProfileServiceT * serviceInfo)83 static cJSON *MakeService(IoTProfileServiceT *serviceInfo)
84 {
85     cJSON *root;
86     cJSON *serviceID;
87     cJSON *properties;
88     cJSON *eventTime;
89 
90     // build a root node
91     root = cJSON_CreateObject();
92     if (root == NULL) {
93         return root;
94     }
95 
96     // add the serviceID node to the root node
97     serviceID = cJSON_CreateString(serviceInfo->serviceID);
98     if (serviceID == NULL) {
99         if (root != NULL) {
100             cJSON_Delete(root);
101             root = NULL;
102         }
103         return root;
104     }
105     cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_SERVICEID, serviceID);
106 
107     // add the properties node to the root
108     properties = MakeKvs(serviceInfo->serviceProperty);
109     if (properties == NULL) {
110         if (root != NULL) {
111             cJSON_Delete(root);
112             root = NULL;
113         }
114         return root;
115     }
116     cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_PROPERTIIES, properties);
117     // add the event time (optional) to the root
118     if (serviceInfo->eventTime != NULL) {
119         eventTime = cJSON_CreateString(serviceInfo->eventTime);
120         if (eventTime == NULL) {
121             if (root != NULL) {
122                 cJSON_Delete(root);
123                 root = NULL;
124             }
125             return root;
126         }
127         cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_EVENTTIME, eventTime);
128     }
129     // OK, now we return it
130     cJSON_Delete(properties);
131     return root;
132 }
133 
MakeServices(IoTProfileServiceT * serviceInfo)134 static cJSON *MakeServices(IoTProfileServiceT *serviceInfo)
135 {
136     cJSON *services = NULL;
137     cJSON *service;
138     IoTProfileServiceT *serviceTmp;
139 
140     // create the services array node
141     services = cJSON_CreateArray();
142     if (services == NULL) {
143         return services;
144     }
145 
146     serviceTmp = serviceInfo;
147     while (serviceTmp != NULL) {
148         service = MakeService(serviceTmp);
149         if (service == NULL) {
150             return services;
151         }
152         cJSON_AddItemToArray(services, service);
153         serviceTmp = serviceTmp->nxt;
154     }
155 
156     // now we return the services
157     return services;
158 }
159 
160 // use this function to make a topic to publish
161 // if request_id  is needed depends on the fmt
MakeTopic(const char * fmt,const char * deviceId,const char * requestID)162 static char *MakeTopic(const char *fmt, const char *deviceId, const char *requestID)
163 {
164     int len;
165     char *ret = NULL;
166 
167     len = strlen(fmt) + strlen(deviceId);
168     if (requestID != NULL) {
169         len += strlen(requestID);
170     }
171     ret = hi_malloc(0, len);
172     if (ret != NULL) {
173         if (requestID != NULL) {
174             (void)snprintf_s(ret, len, len, fmt, deviceId, requestID);
175         } else {
176             (void)snprintf_s(ret, len, len, fmt, deviceId);
177         }
178     }
179     return ret;
180 }
181 
182 #define CN_PROFILE_CMDRESP_KEY_RETCODE    "result_code"
183 #define CN_PROFILE_CMDRESP_KEY_RESPNAME    "response_name"
184 #define CN_PROFILE_CMDRESP_KEY_PARAS    "paras"
MakeProfileCmdResp(IoTCmdRespT * payload)185 static char *MakeProfileCmdResp(IoTCmdRespT *payload)
186 {
187     char *ret = NULL;
188     cJSON *root;
189     cJSON *retCode;
190     cJSON *respName;
191     cJSON *paras;
192 
193     // create the root node
194     root = cJSON_CreateObject();
195     if (root == NULL) {
196         return ret;
197     }
198 
199     // create retcode and retdesc and add it to the root
200     retCode = cJSON_CreateNumber(payload->retCode);
201     if (retCode == NULL) {
202         if (root != NULL) {
203             cJSON_Delete(root);
204         }
205         return ret;
206     }
207     cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_RETCODE, retCode);
208 
209     if (payload->respName != NULL) {
210         respName = cJSON_CreateString(payload->respName);
211         if (respName == NULL) {
212             if (root != NULL) {
213                 cJSON_Delete(root);
214             }
215             return ret;
216         }
217         cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_RESPNAME, respName);
218     }
219 
220     if (payload->paras != NULL) {
221         paras = MakeKvs(payload->paras);
222         if (paras == NULL) {
223             if (root != NULL) {
224                 cJSON_Delete(root);
225             }
226             return ret;
227         }
228         cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_PARAS, paras);
229     }
230 
231     // OK, now we make it to a buffer
232     ret = cJSON_PrintUnformatted(root);
233     cJSON_Delete(root);
234     return ret;
235 }
236 #define CN_PROFILE_TOPICFMT_CMDRESP    "$oc/devices/%s/sys/commands/response/request_id=%s"
IoTProfileCmdResp(const char * deviceID,IoTCmdRespT * payload)237 int IoTProfileCmdResp(const char *deviceID, IoTCmdRespT *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(IoTProfileServiceT * payload)261 static char *MakeProfilePropertyReport(IoTProfileServiceT *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,IoTProfileServiceT * payload)289 int IoTProfilePropertyReport(char *deviceID, IoTProfileServiceT *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 }