1 /*----------------------------------------------------------------------------
2 * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
3 * All rights reserved.
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 * 1. Redistributions of source code must retain the above copyright notice, this list of
7 * conditions and the following disclaimer.
8 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
9 * of conditions and the following disclaimer in the documentation and/or other materials
10 * provided with the distribution.
11 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
12 * to endorse or promote products derived from this software without specific prior written
13 * permission.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *---------------------------------------------------------------------------*/
26 /*----------------------------------------------------------------------------
27 * Notice of Export Control Law
28 * ===============================================
29 * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
30 * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
31 * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
32 * applicable export control laws and regulations.
33 *---------------------------------------------------------------------------*/
34 /**
35 * DATE AUTHOR INSTRUCTION
36 * 2020-02-05 17:00 zhangqianfu The first version
37 *
38 */
39
40
41 #include <stdio.h>
42 #include <string.h>
43 #include <unistd.h>
44
45 #include "cJSON.h"
46 #include "cmsis_os2.h"
47 #include "MQTTClient.h"
48
49 #include <oc_mqtt.h>
50 #include <oc_mqtt_profile_package.h>
51
52
53 #define OC_MQTT_CONSTANT_1 6
54 #define OC_MQTT_BUF_SIZE 2048
55 #define OS_MQTT_CMD_TIMEOUT 1000
56 #define OS_MQTT_KEEP_ALIVE 30
57 #define OS_MQTT_VERSION 3
58
59 typedef struct {
60 char *device_id;
61 fn_oc_mqtt_profile_rcvdeal rcvfunc;
62 } oc_mqtt_profile_cb_t;
63
64 static oc_mqtt_profile_cb_t s_oc_mqtt_profile_cb;
65
66 static char init_ok = FALSE;
67 static MQTTClient mq_client;
68 struct bp_oc_info oc_info;
69 struct oc_device {
70 struct bp_oc_info *oc_info;
71
72 void (*cmd_rsp_cb)(uint8_t *recv_data, size_t recv_size, uint8_t **resp_data, size_t *resp_size);
73 } oc_mqtt;
74
mqtt_callback(MessageData * msg_data)75 void mqtt_callback(MessageData *msg_data)
76 {
77 size_t res_len = 0;
78 uint8_t *response_buf = NULL;
79 char topicname[45] = { "$crsp/" };
80
81 LOS_ASSERT(msg_data);
82
83 if (oc_mqtt.cmd_rsp_cb != NULL) {
84 oc_mqtt.cmd_rsp_cb((uint8_t *)msg_data->message->payload, msg_data->message->payloadlen, &response_buf,
85 &res_len);
86
87 if (response_buf != NULL || res_len != 0) {
88 strncat_s(topicname, sizeof(topicname), &(msg_data->topicName->lenstring.data[OC_MQTT_CONSTANT_1]),
89 msg_data->topicName->lenstring.len - OC_MQTT_CONSTANT_1);
90
91 oc_mqtt_publish(topicname, response_buf, strlen((const char *)response_buf), (int)en_mqtt_al_qos_1);
92
93 free(response_buf);
94 }
95 }
96 }
97 unsigned char *oc_mqtt_buf;
98 unsigned char *oc_mqtt_readbuf;
99 int buf_size;
100
101 Network n;
102 MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
103
oc_mqtt_entry(void)104 static int oc_mqtt_entry(void)
105 {
106 int rc = 0;
107
108 NetworkInit(&n);
109 NetworkConnect(&n, OC_SERVER_IP, OC_SERVER_PORT);
110
111 buf_size = OC_MQTT_BUF_SIZE;
112 oc_mqtt_buf = (unsigned char *)malloc(buf_size);
113 oc_mqtt_readbuf = (unsigned char *)malloc(buf_size);
114 if (!(oc_mqtt_buf && oc_mqtt_readbuf)) {
115 printf("No memory for MQTT client buffer!");
116 return -1;
117 }
118
119 MQTTClientInit(&mq_client, &n, OS_MQTT_CMD_TIMEOUT, oc_mqtt_buf, buf_size, oc_mqtt_readbuf, buf_size);
120
121 MQTTStartTask(&mq_client);
122
123 data.keepAliveInterval = OS_MQTT_KEEP_ALIVE;
124 data.cleansession = 1;
125 data.clientID.cstring = oc_info.client_id;
126 data.username.cstring = oc_info.username;
127 data.password.cstring = oc_info.password;
128 data.MQTTVersion = OS_MQTT_VERSION;
129
130 mq_client.defaultMessageHandler = mqtt_callback;
131
132 rc = MQTTConnect(&mq_client, &data);
133
134 return rc;
135 }
136
device_info_init(char * client_id,char * username,char * password)137 void device_info_init(char *client_id, char *username, char *password)
138 {
139 oc_info.user_device_id_flg = 1;
140 strncpy_s(oc_info.client_id, strlen(client_id)+1, client_id, strlen(client_id));
141 strncpy_s(oc_info.username, strlen(username)+1, username, strlen(username));
142 strncpy_s(oc_info.password, strlen(password)+1, password, strlen(password));
143 }
144
145 /**
146 * oc mqtt client init.
147 *
148 * @param NULL
149 *
150 * @return 0 : init success
151 * -1 : init fail
152 */
oc_mqtt_init(void)153 int oc_mqtt_init(void)
154 {
155 int result = 0;
156
157 if (init_ok) {
158 return 0;
159 }
160 if (oc_mqtt_entry() < 0) {
161 result = -1;
162 if (!result) {
163 init_ok = 0;
164 }
165 return result;
166 }
167
168 return result;
169 }
170 /**
171 * set the command responses call back function
172 *
173 * @param cmd_rsp_cb command responses call back function
174 *
175 * @return 0 : set success
176 * -1 : function is null
177 */
oc_set_cmd_rsp_cb(void (* cmd_rsp_cb)(uint8_t * recv_data,uint32_t recv_size,uint8_t ** resp_data,uint32_t * resp_size))178 void oc_set_cmd_rsp_cb(
179 void (*cmd_rsp_cb)(uint8_t *recv_data, uint32_t recv_size, uint8_t **resp_data, uint32_t *resp_size))
180 {
181 oc_mqtt.cmd_rsp_cb = cmd_rsp_cb;
182 }
183
184 /**
185 * mqtt publish msg to topic
186 *
187 * @param topic target topic
188 * @param msg message to be sent
189 * @param len message length
190 *
191 * @return 0 : publish success
192 * -1 : publish fail
193 */
oc_mqtt_publish(char * topic,uint8_t * msg,int msg_len,int qos)194 int oc_mqtt_publish(char *topic, uint8_t *msg, int msg_len, int qos)
195 {
196 MQTTMessage message;
197
198 LOS_ASSERT(topic);
199 LOS_ASSERT(msg);
200
201 message.qos = qos;
202 message.retained = 0;
203 message.payload = (void *)msg;
204 message.payloadlen = msg_len;
205
206 if (MQTTPublish(&mq_client, topic, &message) < 0) {
207 return -1;
208 }
209
210 return 0;
211 }
212 ///< use this function to make a topic to publish
213 ///< if request_id is needed depends on the fmt
topic_make(char * fmt,char * device_id,char * request_id)214 static char *topic_make(char *fmt, char *device_id, char *request_id)
215 {
216 int len;
217 char *ret = NULL;
218
219 if (device_id == NULL) {
220 return ret;
221 }
222 len = strlen(fmt) + strlen(device_id);
223 if (request_id != NULL) {
224 len += strlen(request_id);
225 }
226
227 ret = malloc(len);
228 if (ret != NULL) {
229 (void)snprintf_s(ret, len, len, fmt, device_id, request_id);
230 }
231 return ret;
232 }
233
234 ///< use this function to report the messsage
235 #define CN_OC_MQTT_PROFILE_MSGUP_TOPICFMT "$oc/devices/%s/sys/messages/up"
oc_mqtt_profile_msgup(char * deviceid,oc_mqtt_profile_msgup_t * payload)236 int oc_mqtt_profile_msgup(char *deviceid, oc_mqtt_profile_msgup_t *payload)
237 {
238 int ret = (int)en_oc_mqtt_err_parafmt;
239 char *topic;
240 char *msg;
241 char *device_id = deviceid;
242
243 if (device_id == NULL) {
244 if (s_oc_mqtt_profile_cb.device_id == NULL) {
245 return ret;
246 } else {
247 device_id = s_oc_mqtt_profile_cb.device_id;
248 }
249 }
250
251 if ((payload == NULL) || (payload->msg == NULL)) {
252 return ret;
253 }
254
255 topic = topic_make(CN_OC_MQTT_PROFILE_MSGUP_TOPICFMT, device_id, NULL);
256 msg = oc_mqtt_profile_package_msgup(payload);
257 if ((topic != NULL) && (msg != NULL)) {
258 ret = oc_mqtt_publish(topic, (uint8_t *)msg, strlen(msg), (int)en_mqtt_al_qos_1);
259 } else {
260 ret = (int)en_oc_mqtt_err_sysmem;
261 }
262
263 free(topic);
264 free(msg);
265
266 return ret;
267 }
268
269 #define CN_OC_MQTT_PROFILE_PROPERTYREPORT_TOPICFMT "$oc/devices/%s/sys/properties/report"
oc_mqtt_profile_propertyreport(char * deviceid,oc_mqtt_profile_service_t * payload)270 int oc_mqtt_profile_propertyreport(char *deviceid, oc_mqtt_profile_service_t *payload)
271 {
272 int ret = (int)en_oc_mqtt_err_parafmt;
273 char *topic;
274 char *msg;
275 char *device_id = deviceid;
276
277 if (device_id == NULL) {
278 if (s_oc_mqtt_profile_cb.device_id == NULL) {
279 return ret;
280 } else {
281 device_id = s_oc_mqtt_profile_cb.device_id;
282 }
283 }
284
285 if ((payload == NULL) || (payload->service_id == NULL) || (payload->service_property == NULL)) {
286 return ret;
287 }
288
289 topic = topic_make(CN_OC_MQTT_PROFILE_PROPERTYREPORT_TOPICFMT, device_id, NULL);
290 msg = oc_mqtt_profile_package_propertyreport(payload);
291 if ((topic != NULL) && (msg != NULL)) {
292 ret = oc_mqtt_publish(topic, (uint8_t *)msg, strlen(msg), (int)en_mqtt_al_qos_1);
293 } else {
294 ret = (int)en_oc_mqtt_err_sysmem;
295 }
296
297 free(topic);
298 free(msg);
299
300 return ret;
301 }
302
303 #define CN_OC_MQTT_PROFILE_GWPROPERTYREPORT_TOPICFMT "$oc/devices/%s/sys/gateway/sub_devices/properties/report"
oc_mqtt_profile_gwpropertyreport(char * deviceid,oc_mqtt_profile_device_t * payload)304 int oc_mqtt_profile_gwpropertyreport(char *deviceid, oc_mqtt_profile_device_t *payload)
305 {
306 int ret = (int)en_oc_mqtt_err_parafmt;
307 char *topic;
308 char *msg;
309 char *device_id = deviceid;
310
311 if (device_id == NULL) {
312 if (s_oc_mqtt_profile_cb.device_id == NULL) {
313 return ret;
314 } else {
315 device_id = s_oc_mqtt_profile_cb.device_id;
316 }
317 }
318
319 if ((payload == NULL) || (payload->subdevice_id == NULL) || (payload->subdevice_property == NULL) ||
320 (payload->subdevice_property->service_id == NULL) || (payload->subdevice_property->service_property == NULL)) {
321 return ret;
322 }
323
324 topic = topic_make(CN_OC_MQTT_PROFILE_GWPROPERTYREPORT_TOPICFMT, device_id, NULL);
325 msg = oc_mqtt_profile_package_gwpropertyreport(payload);
326 if ((topic != NULL) && (msg != NULL)) {
327 ret = oc_mqtt_publish(topic, (uint8_t *)msg, strlen(msg), (int)en_mqtt_al_qos_1);
328 } else {
329 ret = (int)en_oc_mqtt_err_sysmem;
330 }
331
332 free(topic);
333 free(msg);
334
335 return ret;
336 }
337
338 #define CN_OC_MQTT_PROFILE_ROPERTYSETRESP_TOPICFMT "$oc/devices/%s/sys/properties/set/response/request_id=%s"
oc_mqtt_profile_propertysetresp(char * deviceid,oc_mqtt_profile_propertysetresp_t * payload)339 int oc_mqtt_profile_propertysetresp(char *deviceid, oc_mqtt_profile_propertysetresp_t *payload)
340 {
341 int ret = (int)en_oc_mqtt_err_parafmt;
342 char *topic;
343 char *msg;
344 char *device_id = deviceid;
345
346 if (device_id == NULL) {
347 if (s_oc_mqtt_profile_cb.device_id == NULL) {
348 return ret;
349 } else {
350 device_id = s_oc_mqtt_profile_cb.device_id;
351 }
352 }
353
354 if ((payload == NULL) || (payload->request_id == NULL)) {
355 return ret;
356 }
357 topic = topic_make(CN_OC_MQTT_PROFILE_ROPERTYSETRESP_TOPICFMT, device_id, payload->request_id);
358 msg = oc_mqtt_profile_package_propertysetresp(payload);
359 if ((topic != NULL) && (msg != NULL)) {
360 ret = oc_mqtt_publish(topic, (uint8_t *)msg, strlen(msg), (int)en_mqtt_al_qos_1);
361 } else {
362 ret = (int)en_oc_mqtt_err_sysmem;
363 }
364
365 free(topic);
366 free(msg);
367
368 return ret;
369 }
370
371 #define CN_OC_MQTT_PROFILE_ROPERTYGETRESP_TOPICFMT "$oc/devices/%s/sys/properties/get/response/request_id=%s"
oc_mqtt_profile_propertygetresp(char * deviceid,oc_mqtt_profile_propertygetresp_t * payload)372 int oc_mqtt_profile_propertygetresp(char *deviceid, oc_mqtt_profile_propertygetresp_t *payload)
373 {
374 int ret = (int)en_oc_mqtt_err_parafmt;
375 char *topic;
376 char *msg;
377 char *device_id = deviceid;
378
379 if (device_id == NULL) {
380 if (s_oc_mqtt_profile_cb.device_id == NULL) {
381 return ret;
382 } else {
383 device_id = s_oc_mqtt_profile_cb.device_id;
384 }
385 }
386
387 if ((payload == NULL) || (payload->request_id == NULL) || (payload->services->service_id == NULL) ||
388 (payload->services->service_property == NULL)) {
389 return ret;
390 }
391
392 topic = topic_make(CN_OC_MQTT_PROFILE_ROPERTYGETRESP_TOPICFMT, device_id, payload->request_id);
393 msg = oc_mqtt_profile_package_propertygetresp(payload);
394 if ((topic != NULL) && (msg != NULL)) {
395 ret = oc_mqtt_publish(topic, (uint8_t *)msg, strlen(msg), (int)en_mqtt_al_qos_1);
396 } else {
397 ret = (int)en_oc_mqtt_err_sysmem;
398 }
399
400 free(topic);
401 free(msg);
402
403 return ret;
404 }
405
406 #define CN_OC_MQTT_PROFILE_CMDRESP_TOPICFMT "$oc/devices/%s/sys/commands/response/request_id=%s"
oc_mqtt_profile_cmdresp(char * deviceid,oc_mqtt_profile_cmdresp_t * payload)407 int oc_mqtt_profile_cmdresp(char *deviceid, oc_mqtt_profile_cmdresp_t *payload)
408 {
409 int ret = (int)en_oc_mqtt_err_parafmt;
410 char *topic;
411 char *msg;
412 char *device_id = deviceid;
413
414 if (device_id == NULL) {
415 if (s_oc_mqtt_profile_cb.device_id == NULL) {
416 return ret;
417 } else {
418 device_id = s_oc_mqtt_profile_cb.device_id;
419 }
420 }
421
422 if ((payload == NULL) || (payload->request_id == NULL)) {
423 return ret;
424 }
425
426 topic = topic_make(CN_OC_MQTT_PROFILE_CMDRESP_TOPICFMT, device_id, payload->request_id);
427 msg = oc_mqtt_profile_package_cmdresp(payload);
428 if ((topic != NULL) && (msg != NULL)) {
429 ret = oc_mqtt_publish(topic, (uint8_t *)msg, strlen(msg), (int)en_mqtt_al_qos_1);
430 } else {
431 ret = (int)en_oc_mqtt_err_sysmem;
432 }
433
434 free(topic);
435 free(msg);
436
437 return ret;
438 }
439