• 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 <hi_mem.h>
17 #include <cJSON.h>
18 #include <string.h>
19 #include "iot_main.h"
20 #include "iot_log.h"
21 #include "iot_config.h"
22 #include "iot_profile.h"
23 
24 // < format the report data to json string mode
FormatProfileValue(IoTProfileKV_t * kv)25 static cJSON  *FormatProfileValue(IoTProfileKV_t  *kv)
26 {
27     cJSON  *ret = NULL;
28     switch (kv->type) {
29         case EN_IOT_DATATYPE_INT:
30             ret = cJSON_CreateNumber(kv->iValue);
31             break;
32         case EN_IOT_DATATYPE_LONG:
33             ret = cJSON_CreateNumber((double)(*(long *)kv->value));
34             break;
35         case EN_IOT_DATATYPE_STRING:
36             ret = cJSON_CreateString((const char *)kv->value);
37             break;
38         default:
39             break;
40     }
41     return ret;
42 }
43 
MakeKvs(IoTProfileKV_t * kvlst)44 static cJSON *MakeKvs(IoTProfileKV_t *kvlst)
45 {
46     cJSON *root;
47     cJSON *kv;
48     IoTProfileKV_t  *kvInfo;
49 
50     // < build a root node
51     root = cJSON_CreateObject();
52     if (root == NULL) {
53         cJSON_Delete(root);
54         root = NULL;
55         return root;
56     }
57     // < add all the property to the properties
58     kvInfo = kvlst;
59     while (kvInfo != NULL) {
60         kv = FormatProfileValue(kvInfo);
61         if (kv == NULL) {
62             if (root != NULL) {
63                 cJSON_Delete(root);
64                 root = NULL;
65             }
66             return root;
67         }
68         cJSON_AddItemToObject(root, kvInfo->key, kv);
69         kvInfo = kvInfo->nxt;
70     }
71     // < OK, now we return it
72     return root;
73 }
74 
75 #define CN_PROFILE_SERVICE_KEY_SERVICEID "service_id"
76 #define CN_PROFILE_SERVICE_KEY_PROPERTIIES "properties"
77 #define CN_PROFILE_SERVICE_KEY_EVENTTIME "event_time"
78 #define CN_PROFILE_KEY_SERVICES   "services"
MakeService(IoTProfileService_t * serviceInfo)79 static cJSON *MakeService(IoTProfileService_t *serviceInfo)
80 {
81     cJSON *root;
82     cJSON *serviceID;
83     cJSON *properties;
84     cJSON *eventTime;
85 
86     // < build a root node
87     root = cJSON_CreateObject();
88     if (root == NULL) {
89         cJSON_Delete(root);
90         root = NULL;
91         return root;
92     }
93     // < add the serviceID node to the root node
94     serviceID = cJSON_CreateString(serviceInfo->serviceID);
95     if (serviceID == NULL) {
96         if (root != NULL) {
97             cJSON_Delete(root);
98             root = NULL;
99         }
100         return root;
101     }
102     cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_SERVICEID, serviceID);
103     // < add the properties node to the root
104     properties = MakeKvs(serviceInfo->serviceProperty);
105     if (properties == NULL) {
106         if (root != NULL) {
107             cJSON_Delete(root);
108             root = NULL;
109         }
110         return root;
111     }
112     cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_PROPERTIIES, properties);
113     // < add the event time (optional) to the root
114     if (serviceInfo->eventTime != NULL) {
115         eventTime = cJSON_CreateString(serviceInfo->eventTime);
116         if (eventTime == NULL) {
117             if (root != NULL) {
118                 cJSON_Delete(root);
119                 root = NULL;
120             }
121             return root;
122         }
123         cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_EVENTTIME, eventTime);
124     }
125     // < OK, now we return it
126     cJSON_Delete(properties);
127     return root;
128 }
129 
MakeServices(IoTProfileService_t * serviceInfo)130 static cJSON *MakeServices(IoTProfileService_t *serviceInfo)
131 {
132     cJSON *services = NULL;
133     cJSON *service;
134     IoTProfileService_t  *serviceTmp;
135 
136     // < create the services array node
137     services = cJSON_CreateArray();
138     if (services == NULL) {
139         cJSON_Delete(services);
140         services = NULL;
141         return services;
142     }
143 
144     serviceTmp = serviceInfo;
145     while (serviceTmp != NULL) {
146         service = MakeService(serviceTmp);
147         if (service == NULL) {
148             if (services != NULL) {
149                 cJSON_Delete(services);
150                 services = NULL;
151             }
152             return services;
153         }
154         cJSON_AddItemToArray(services, service);
155         serviceTmp = serviceTmp->nxt;
156     }
157     // < now we return the services
158     return services;
159 }
160 
161 // < use this function to make a topic to publish
162 // < if request_id  is needed depends on the fmt
MakeTopic(const char * fmt,const char * deviceID,const char * requestID)163 static char *MakeTopic(const char *fmt, const char *deviceID, const char *requestID)
164 {
165     int len;
166     char *ret = NULL;
167 
168     len = strlen(fmt) + strlen(deviceID);
169     if (requestID != NULL) {
170         len += strlen(requestID);
171     }
172 
173     ret = hi_malloc(0, len);
174     if (ret != NULL) {
175         if (requestID != NULL) {
176             (void)snprintf_s(ret, len, len, fmt, deviceID, requestID);
177         } else {
178             (void)snprintf_s(ret, len, len, fmt, deviceID);
179         }
180     }
181     return ret;
182 }
183 
184 #define CN_PROFILE_CMDRESP_KEY_RETCODE        "result_code"
185 #define CN_PROFILE_CMDRESP_KEY_RESPNAME       "response_name"
186 #define CN_PROFILE_CMDRESP_KEY_PARAS          "paras"
MakeProfileCmdResp(IoTCmdResp_t * payload)187 static char *MakeProfileCmdResp(IoTCmdResp_t *payload)
188 {
189     char *ret = NULL;
190     cJSON *root;
191     cJSON *retCode;
192     cJSON *respName;
193     cJSON *paras;
194 
195     // < create the root node
196     root = cJSON_CreateObject();
197     if (root == NULL) {
198         cJSON_Delete(root);
199         return ret;
200     }
201     // < create retcode and retdesc and add it to the root
202     retCode = cJSON_CreateNumber(payload->retCode);
203     if (retCode == NULL) {
204         if (root != NULL) {
205             cJSON_Delete(root);
206         }
207         return ret;
208     }
209     cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_RETCODE, retCode);
210     if (payload->respName != NULL) {
211         respName = cJSON_CreateString(payload->respName);
212         if (respName == NULL) {
213             if (root != NULL) {
214                 cJSON_Delete(root);
215             }
216             return ret;
217         }
218         cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_RESPNAME, respName);
219     }
220 
221     if (payload->paras != NULL) {
222         paras = MakeKvs(payload->paras);
223         if (paras == NULL) {
224             if (root != NULL) {
225                 cJSON_Delete(root);
226             }
227             return ret;
228         }
229         cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_PARAS, paras);
230     }
231     // < OK, now we make it to a buffer
232     ret = cJSON_PrintUnformatted(root);
233     cJSON_Delete(root);
234     return ret;
235 }
236 
MakeProfilePropertyReport(IoTProfileService_t * payload)237 static char *MakeProfilePropertyReport(IoTProfileService_t *payload)
238 {
239     char *ret = NULL;
240     cJSON *root;
241     cJSON *services;
242 
243     // < create the root node
244     root = cJSON_CreateObject();
245     if (root == NULL) {
246         cJSON_Delete(root);
247         return ret;
248     }
249     // < create the services array node to the root
250     services = MakeServices(payload);
251     if (services == NULL) {
252         if (root != NULL) {
253             cJSON_Delete(root);
254         }
255         return ret;
256     }
257     cJSON_AddItemToObjectCS(root, CN_PROFILE_KEY_SERVICES, services);
258     // < OK, now we make it to a buffer
259     ret = cJSON_PrintUnformatted(root);
260     cJSON_Delete(root);
261     return ret;
262 }
263 
264 #define WECHAT_SUBSCRIBE_TYPE       "update"
265 #define WECHAT_SUBSCRIBE_VERSION    "1.0.0"
266 #define WECHAT_SUBSCRIBE_TOKEN      "DeviceSubscribe"
MakeProfileReport(WeChatProfile * payload)267 static char *MakeProfileReport(WeChatProfile *payload)
268 {
269     char *ret = NULL;
270     cJSON *root;
271     cJSON *state;
272     cJSON *reported;
273 
274     /* create json root node */
275     root = cJSON_CreateObject();
276     if (root == NULL) {
277         return;
278     }
279     /* state create */
280     state = cJSON_CreateObject();
281     if (state == NULL) {
282         return;
283     }
284     /* reported create */
285     reported = cJSON_CreateObject();
286     if (reported == NULL) {
287         return;
288     }
289     /* add root object */
290     cJSON_AddItemToObject(root, payload->subscribeType, cJSON_CreateString(WECHAT_SUBSCRIBE_TYPE));
291     cJSON_AddItemToObject(root, payload->status.subState, state);
292     cJSON_AddItemToObject(state, payload->status.subReport, reported);
293     cJSON_AddItemToObject(root, payload->status.reportVersion, cJSON_CreateString(WECHAT_SUBSCRIBE_VERSION));
294     cJSON_AddItemToObject(root, payload->status.Token, cJSON_CreateString(WECHAT_SUBSCRIBE_TOKEN));
295     /* add reported item */
296     cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionLight,
297                             payload->reportAction.lightActionStatus);
298     cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionMotor,
299                             payload->reportAction.motorActionStatus);
300     cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionTemperature,
301                             payload->reportAction.temperatureData);
302     cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionHumidity,
303                             payload->reportAction.humidityActionData);
304     cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionLightIntensity,
305                             payload->reportAction.lightIntensityActionData);
306     ret = cJSON_PrintUnformatted(root);
307     cJSON_Delete(state);
308     cJSON_Delete(reported);
309     cJSON_Delete(root);
310     return ret;
311 }
312 
313 #define CN_PROFILE_TOPICFMT_TOPIC            "$shadow/operation/19VUBHD786/mqtt"
IoTProfilePropertyReport(char * deviceID,WeChatProfile * payload)314 int IoTProfilePropertyReport(char *deviceID, WeChatProfile *payload)
315 {
316     int ret = -1;
317     char *topic;
318     char *msg;
319 
320     if ((deviceID == NULL) || (payload== NULL)) {
321         return ret;
322     }
323     topic = MakeTopic(CN_PROFILE_TOPICFMT_TOPIC, deviceID, NULL);
324     if (topic == NULL) {
325         return;
326     }
327     msg = MakeProfileReport(payload);
328     if ((topic != NULL) && (msg != NULL)) {
329         ret = IotSendMsg(0, topic, msg);
330     }
331 
332     hi_free(0, topic);
333     cJSON_free(msg);
334 
335     return ret;
336 }