1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4
5 #ifndef __OTA_COAP_C_H__
6 #define __OTA_COAP_C_H__
7 #if (OTA_SIGNAL_CHANNEL) == 2
8
9 #include "iotx_ota_internal.h"
10
11 /* OSC, OTA signal channel */
12
13 /* Specify the maximum characters of version */
14 #define OSC_COAP_URI_MAX_LEN (135) /* IoTx CoAP uri maximal length */
15
16 typedef struct {
17 void *coap;
18 const char *product_key;
19 const char *device_name;
20 ota_cb_fpt cb;
21 void *context;
22 } otacoap_Struct_t, *otacoap_Struct_pt;
23
24 static otacoap_Struct_pt h_osc_coap = NULL;
25
otacoap_response_handler(void * arg,void * p_response)26 static void otacoap_response_handler(void *arg, void *p_response)
27 {
28 int len = 0;
29 unsigned char *p_payload = NULL;
30 iotx_coap_resp_code_t resp_code;
31 IOT_CoAP_GetMessageCode(p_response, &resp_code);
32 IOT_CoAP_GetMessagePayload(p_response, &p_payload, &len);
33 OTA_LOG_DEBUG("CoAP response code = %d", resp_code);
34 OTA_LOG_DEBUG("[CoAP msg_len=%d, msg=%s\r\n", len, p_payload);
35
36 if ((NULL != h_osc_coap) && (NULL != p_payload)) {
37 h_osc_coap->cb(h_osc_coap->context, (const char *)p_payload,
38 (uint32_t)len);
39 }
40 }
41
42 /* Generate topic name according to @ota_topic_type, @product_key, @device_name
43 */
44 /* and then copy to @buf. */
45 /* 0, successful; -1, failed */
otacoap_GenTopicName(char * buf,size_t buf_len,const char * ota_topic_type,const char * product_key,const char * device_name)46 static int otacoap_GenTopicName(char *buf, size_t buf_len,
47 const char *ota_topic_type,
48 const char *product_key,
49 const char *device_name)
50 {
51 int ret;
52
53 ret = OTA_SNPRINTF(buf, buf_len, "/topic/ota/device/%s/%s/%s",
54 ota_topic_type, product_key, device_name);
55
56 if (ret >= buf_len) {
57 return -1;
58 }
59
60 if (ret < 0) {
61 OTA_LOG_ERROR("snprintf failed");
62 return -1;
63 }
64
65 return 0;
66 }
67
68 /* report progress of OTA */
otacoap_Publish(otacoap_Struct_pt handle,const char * topic_type,const char * msg)69 static int otacoap_Publish(otacoap_Struct_pt handle, const char *topic_type,
70 const char *msg)
71 {
72 int ret;
73 char uri[IOTX_URI_MAX_LEN + 1] = { 0 };
74 iotx_message_t message;
75 message.p_payload = (unsigned char *)msg;
76 message.payload_len = (unsigned short)strlen(msg);
77 message.resp_callback = otacoap_response_handler;
78 message.msg_type = IOTX_MESSAGE_CON;
79 message.content_type = IOTX_CONTENT_TYPE_JSON;
80
81 /* topic name: /topic/ota/device/${topic_type}/${productKey}/${deviceName}
82 */
83 ret = otacoap_GenTopicName(uri, OSC_COAP_URI_MAX_LEN, topic_type,
84 handle->product_key, handle->device_name);
85 if (ret < 0) {
86 OTA_LOG_ERROR("generate topic name failed");
87 return -1;
88 }
89
90 ret = IOT_CoAP_SendMessage(handle->coap, (char *)uri, &message);
91 if (ret != IOTX_SUCCESS) {
92 OTA_LOG_ERROR("send CoAP msg failed%d", ret);
93 return -1;
94 }
95
96 return 0;
97 }
98
osc_Init(const char * product_key,const char * device_name,void * ch_signal,ota_cb_fpt cb,void * context)99 void *osc_Init(const char *product_key, const char *device_name,
100 void *ch_signal, ota_cb_fpt cb, void *context)
101 {
102 otacoap_Struct_pt h_osc = NULL;
103
104 h_osc = OTA_MALLOC(sizeof(otacoap_Struct_t));
105 if (h_osc == NULL) {
106 OTA_LOG_ERROR("allocate for h_osc failed");
107 return NULL;
108 }
109
110 memset(h_osc, 0, sizeof(otacoap_Struct_t));
111
112 h_osc->coap = ch_signal;
113 h_osc->product_key = product_key;
114 h_osc->device_name = device_name;
115 h_osc->cb = cb;
116 h_osc->context = context;
117
118 h_osc_coap = h_osc;
119
120 return h_osc;
121 }
122
osc_Deinit(void * handle)123 int osc_Deinit(void *handle)
124 {
125 if (NULL != handle) {
126 OTA_FREE(handle);
127 }
128
129 return 0;
130 }
131
132 /* report progress of OTA */
osc_ReportProgress(void * handle,const char * msg)133 int osc_ReportProgress(void *handle, const char *msg)
134 {
135 return otacoap_Publish(handle, "progress", msg);
136 }
137
138 /* report version of OTA firmware */
osc_ReportVersion(void * handle,const char * msg)139 int osc_ReportVersion(void *handle, const char *msg)
140 {
141 static int state = 0;
142 int ret;
143
144 if (0 == state) { /* report version in initial state */
145 ret = otacoap_Publish(handle, "inform", msg);
146 if (0 != ret) {
147 return ret;
148 }
149 state = 1;
150 }
151
152 /* request new firmware after initial state */
153 return otacoap_Publish(handle, "request", msg);
154 }
155
156 #endif /* #if (OTA_SIGNAL_CHANNEL) == 2 */
157 #endif
158