• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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