├── Kconfig ├── README.md ├── adaptation ├── alink_network.c ├── alink_os.c ├── alink_product.c ├── alink_ssl.c ├── alink_upgrade.c ├── alink_wifi.c └── include │ ├── alink_platform.h │ └── alink_product.h ├── application ├── esp_alink_main.c ├── esp_data_transport.c ├── esp_info_store.c └── esp_json_parser.c ├── component.mk ├── include ├── alink_export.h ├── alink_json_parser.h ├── esp_alink.h ├── esp_alink_log.h ├── esp_info_store.h └── esp_json_parser.h └── lib ├── libalink_agent.a ├── libalink_agent_sds.a └── libtfspal.a /Kconfig: -------------------------------------------------------------------------------- 1 | menuconfig ALINK_ENABLE 2 | bool "Enable alink_embed function" 3 | default y 4 | help 5 | If the option is enabled, "ALINK_EMBED" works. 6 | 7 | choice ALINK_VERSION 8 | bool "Select the version of alink" 9 | default ALINK_VERSION_EMBED 10 | depends on ALINK_ENABLE 11 | help 12 | esp32 alink embed is the access Ali small wisdom, SDK, APP side are all 13 | used in the Ali. Free service provided by Ali. 14 | 15 | esp32 alink sds's APP and the server are allowed to customize, but need 16 | to pay the service fee 17 | 18 | config ALINK_VERSION_EMBED 19 | bool "esp32 alink embed" 20 | config ALINK_VERSION_SDS 21 | bool "esp32 alink sds" 22 | endchoice 23 | 24 | config ALINK_VERSION 25 | int 26 | default 0 if ALINK_VERSION_EMBED 27 | default 1 if ALINK_VERSION_SDS 28 | depends on ALINK_ENABLE 29 | 30 | config ALINK_WRITE_NOT_BUFFER 31 | bool "Remove the buffer space for reporting data" 32 | default 0 33 | depends on ALINK_ENABLE 34 | help 35 | Remove the buffer space for reporting data. 36 | 37 | config WIFI_WAIT_TIME 38 | int "the connection router maximum latency unit is seconds" 39 | default 60 40 | depends on ALINK_ENABLE 41 | help 42 | the connection router maximum latency unit is seconds 43 | 44 | config ALINK_TASK_PRIOTY 45 | int "Configure the priority of all alink tasks" 46 | default 6 47 | depends on ALINK_ENABLE 48 | help 49 | Configure the priority of all alink tasks 50 | 51 | config ALINK_EVENT_STACK_SIZE 52 | int "Event callback function stack space" 53 | default 4096 54 | depends on ALINK_ENABLE 55 | help 56 | Event callback function stack space 57 | 58 | config ALINK_POST_DATA_STACK_SIZE 59 | int "The size of the task of reporting data to Ali" 60 | default 4096 61 | depends on ALINK_ENABLE 62 | help 63 | The size of the task of reporting data to Ali 64 | 65 | config DOWN_CMD_QUEUE_NUM 66 | int "The number of buffered data received" 67 | default 3 68 | depends on ALINK_ENABLE 69 | help 70 | The number of buffered data received 71 | 72 | config UP_CMD_QUEUE_NUM 73 | int "The number of buffered data send" 74 | default 3 75 | depends on ALINK_ENABLE 76 | help 77 | The number of buffered data send 78 | 79 | config ALINK_DATA_LEN 80 | int "The maximum length of the transmitted data" 81 | default 1024 82 | depends on ALINK_ENABLE 83 | help 84 | The maximum length of this data is 1536B 85 | 86 | config ALINK_CHIPID 87 | string "The name of the chip" 88 | default "esp32" 89 | depends on ALINK_ENABLE 90 | help 91 | Before modifying this parameter, make sure that the device is 92 | unbinded with Ali cloud server 93 | 94 | config ALINK_MODULE_NAME 95 | string "The name of the module" 96 | default "ESP-WROOM-32" 97 | depends on ALINK_ENABLE 98 | help 99 | Before modifying this parameter, make sure that the device is 100 | unbinded with Ali cloud server 101 | 102 | config DEVICE_ID_ADRR 103 | int "Device id storage address" 104 | default 3211264 105 | depends on ALINK_ENABLE 106 | help 107 | Device id storage address 108 | 109 | choice LOG_ALINK_LEVEL 110 | bool "Configure the alink application layer's log" 111 | default LOG_ALINK_LEVEL_DEBUG 112 | depends on ALINK_ENABLE 113 | help 114 | Specify how much output to see in logs by default. 115 | Note that this setting limits which log statements 116 | are compiled into the program. So setting this to, say, 117 | "Warning" would mean that changing log level to "Debug" 118 | at runtime will not be possible. 119 | 120 | config LOG_ALINK_LEVEL_NONE 121 | bool "No output" 122 | config LOG_ALINK_LEVEL_ERROR 123 | bool "Error" 124 | config LOG_ALINK_LEVEL_WARN 125 | bool "Warning" 126 | config LOG_ALINK_LEVEL_INFO 127 | bool "Info" 128 | config LOG_ALINK_LEVEL_DEBUG 129 | bool "Debug" 130 | config LOG_ALINK_LEVEL_VERBOSE 131 | bool "Verbose" 132 | endchoice 133 | 134 | config LOG_ALINK_LEVEL 135 | int 136 | default 0 if LOG_ALINK_LEVEL_NONE 137 | default 1 if LOG_ALINK_LEVEL_ERROR 138 | default 2 if LOG_ALINK_LEVEL_WARN 139 | default 3 if LOG_ALINK_LEVEL_INFO 140 | default 4 if LOG_ALINK_LEVEL_DEBUG 141 | default 5 if LOG_ALINK_LEVEL_VERBOSE 142 | depends on ALINK_ENABLE 143 | 144 | choice LOG_ALINK_SDK_LEVEL 145 | bool "Configure the alink sdk's log" 146 | default LOG_ALINK_SDK_LEVEL_TRACE 147 | depends on ALINK_ENABLE 148 | help 149 | Specify how much output to see in logs by default. 150 | Note that this setting limits which log statements 151 | are compiled into the program. So setting this to, say, 152 | "Warning" would mean that changing log level to "Debug" 153 | at runtime will not be possible. 154 | 155 | config LOG_ALINK_SDK_LEVEL_NONE 156 | bool "No output" 157 | config LOG_ALINK_SDK_LEVEL_ERROR 158 | bool "Error" 159 | config LOG_ALINK_SDK_LEVEL_WARN 160 | bool "Warning" 161 | config LOG_ALINK_SDK_LEVEL_INFO 162 | bool "Info" 163 | config LOG_ALINK_SDK_LEVEL_DEBUG 164 | bool "Debug" 165 | config LOG_ALINK_SDK_LEVEL_TRACE 166 | bool "Trace" 167 | endchoice 168 | 169 | config LOG_ALINK_SDK_LEVEL 170 | int 171 | default 0 if LOG_ALINK_SDK_LEVEL_NONE 172 | default 1 if LOG_ALINK_SDK_LEVEL_FATAL 173 | default 2 if LOG_ALINK_SDK_LEVEL_ERROR 174 | default 3 if LOG_ALINK_SDK_LEVEL_WARN 175 | default 4 if LOG_ALINK_SDK_LEVEL_INFO 176 | default 5 if LOG_ALINK_SDK_LEVEL_DEBUG 177 | default 6 if LOG_ALINK_SDK_LEVEL_TRACE 178 | depends on ALINK_ENABLE 179 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | alink 是由阿里推出的智能硬件模组、阿里智能云、阿里智能 APP,阿里智能生活事业部为厂商提供一站式设备智能化解决方案。 2 | 本工程对接 alink embed 版本,并对阿里底层交互流程进行封装,你无需关心设备具体是如何进行交互的、升级的,对如果更改相关配置请使用 make menuconfig。 3 | 4 | # Feature: 5 | 1. 配网(一键配网、热点配网、零配网) 6 | 2. 绑定、解绑 7 | 3. OTA 升级 8 | 4. 数据传输非透传 9 | 10 | # 开发流程 11 | 1. 熟悉[esp32_idf的使用](http://esp-idf.readthedocs.io/en/latest/?badge=latest) 12 | 2. 了解[阿里智能](https://open.aliplus.com/docs/open)相关知识 13 | 3. 跑通[alink light demo](https://github.com/espressif/esp32-alink-demo),初步了解 alink 相关功能 14 | 4. [签约入驻](https://open.aliplus.com/docs/open/open/enter/index.html) 15 | 5. [产品注册](https://open.aliplus.com/docs/open/open/register/index.html) 16 | 6. 产品开发 17 | - **初始化**, 调用 alink_init() 传入产品注册的信息,注册事件回调函数 18 | - **配网**,设备配网过程中的所有动作,都会传入事件回调函数中 19 | - 当设备连上服务器时,需要主动上报设备状态 20 | - 设备配网过程,需要发送激活命令 21 | 22 | > 注:事件回调函数的 task 默认大小为 4k, 请避免在事件回调函数使用较大的栈空间 23 | - **数据通信** 24 | - 接收数据,接收到的数据由设置指令和请求指令组成 25 | - 发送数据,若发送的数据大于 512Byte,请修改配置文件,数据长度最大支持 1.5k 26 | - **底层驱动** 27 | - 设置 GPIO、串口等外围设备,参见:http://esp-idf.readthedocs.io/en/latest/api-reference/peripherals/index.html 28 | 29 | > 注: alink api 的使用参见:esp32-alink-demo:https://github.com/espressif/esp32-alink-demo 30 | 7. [发布上架](https://open.aliplus.com/docs/open/open/publish/index.html) 31 | 32 | # 配置与编译 33 | 2. **配置 idf**, 使用make menuconfig, 34 | - 禁用硬件 SHA: Component config->mbedTLS->SHA 35 | - 使能 SO_REUSEADDR: Component config->LWIP->Enable SO_REUSEADDR option 36 | - 提高 cpu 频率:Component config->ESP32-specific->CPU frequency (240 MHz) 37 | - 配置分区表:Partition Table->Factory app, two OTA definitions 38 | 3. **配置alink** 39 | - 使用 make menuconfig,配置日志等级,数据传输模式、任务优先级等,推荐使用默认值,make menuconfig->Component config->Enable alink_v2.0 function 40 | 41 | > 注:如果你想要详细了解esp32相关配置与编译详见esp-idf/README.md 42 | 43 | # Related links 44 | * ESP32 概览 : http://www.espressif.com/en/products/hardware/esp32/overview 45 | * ESP32 资料 : http://www.espressif.com/en/products/hardware/esp32/resources 46 | * 烧录工具 : http://espressif.com/en/support/download/other-tools 47 | * 串口驱动 : http://www.silabs.com/products/mcu/Pages/USBtoUARTBridgeVCPDrivers.aspx 48 | * 阿里智能开放平台:https://open.aliplus.com/docs/open/ 49 | -------------------------------------------------------------------------------- /adaptation/alink_network.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2017 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #include "esp_system.h" 26 | #include "lwip/err.h" 27 | #include "lwip/sockets.h" 28 | #include "lwip/netdb.h" 29 | #include "tcpip_adapter.h" 30 | 31 | #include "esp_alink.h" 32 | #include "alink_platform.h" 33 | #include "esp_alink_log.h" 34 | 35 | #define SOMAXCONN 5 36 | #define ALINK_SOCKET_TIMEOUT 20 37 | static const char *TAG = "alink_network"; 38 | 39 | static alink_err_t network_create_socket(pplatform_netaddr_t netaddr, int type, struct sockaddr_in *paddr, int *psock) 40 | { 41 | ALINK_PARAM_CHECK(netaddr); 42 | ALINK_PARAM_CHECK(paddr); 43 | ALINK_PARAM_CHECK(psock); 44 | 45 | struct hostent *hp; 46 | struct in_addr in; 47 | uint32_t ip; 48 | alink_err_t ret; 49 | 50 | if (NULL == netaddr->host) { 51 | ip = htonl(INADDR_ANY); 52 | } else { 53 | ALINK_LOGI("alink server host: %s", netaddr->host); 54 | 55 | if (inet_aton(netaddr->host, &in)) { 56 | ip = *(uint32_t *)∈ 57 | } else { 58 | hp = gethostbyname(netaddr->host); 59 | ALINK_ERROR_CHECK(hp == NULL, ALINK_ERR, "gethostbyname ret:%p", hp); 60 | ip = *(uint32_t *)(hp->h_addr); 61 | } 62 | } 63 | 64 | *psock = socket(AF_INET, type, 0); 65 | 66 | if (*psock < 0) { 67 | return ALINK_ERR; 68 | } 69 | 70 | memset(paddr, 0, sizeof(struct sockaddr_in)); 71 | 72 | int opt_val = 1; 73 | ret = setsockopt(*psock, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof(opt_val)); 74 | ALINK_ERROR_CHECK(ret != 0, ALINK_ERR, "setsockopt SO_REUSEADDR errno: %d", errno); 75 | 76 | if (type == SOCK_DGRAM) { 77 | ret = setsockopt(*psock, SOL_SOCKET, SO_BROADCAST, &opt_val, sizeof(opt_val)); 78 | 79 | if (ret != 0) { 80 | close(*psock); 81 | } 82 | 83 | ALINK_ERROR_CHECK(ret != 0, ALINK_ERR, "setsockopt SO_BROADCAST errno: %d", errno); 84 | } 85 | 86 | struct timeval timeout = {ALINK_SOCKET_TIMEOUT, 0}; 87 | 88 | ret = setsockopt((int) * psock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)); 89 | ALINK_ERROR_CHECK(ret != 0, ALINK_ERR, "setsockopt SO_RCVTIMEO errno: %d", errno); 90 | ALINK_LOGD("setsockopt: recv timeout %ds", ALINK_SOCKET_TIMEOUT); 91 | 92 | ret = setsockopt((int) * psock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)); 93 | ALINK_ERROR_CHECK(ret != 0, ALINK_ERR, "setsockopt SO_SNDTIMEO errno: %d", errno); 94 | ALINK_LOGD("setsockopt: send timeout %ds", ALINK_SOCKET_TIMEOUT); 95 | 96 | paddr->sin_addr.s_addr = ip; 97 | paddr->sin_family = AF_INET; 98 | paddr->sin_port = htons(netaddr->port); 99 | 100 | ALINK_LOGV("create sock: %d", *psock); 101 | 102 | return ALINK_OK; 103 | } 104 | 105 | void *platform_udp_server_create(_IN_ uint16_t port) 106 | { 107 | struct sockaddr_in addr; 108 | int server_socket; 109 | alink_err_t ret; 110 | platform_netaddr_t netaddr = {NULL, port}; 111 | 112 | ret = network_create_socket(&netaddr, SOCK_DGRAM, &addr, &server_socket); 113 | ALINK_ERROR_CHECK(ret != ALINK_OK, PLATFORM_INVALID_FD, "network_create_socket"); 114 | 115 | if (-1 == bind(server_socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))) { 116 | perror("socket bind"); 117 | platform_udp_close((void *)server_socket); 118 | return PLATFORM_INVALID_FD; 119 | } 120 | 121 | return (void *)server_socket; 122 | } 123 | 124 | void *platform_udp_client_create(void) 125 | { 126 | struct sockaddr_in addr; 127 | int sock; 128 | platform_netaddr_t netaddr = {NULL, 0}; 129 | alink_err_t ret; 130 | 131 | ret = network_create_socket(&netaddr, SOCK_DGRAM, &addr, &sock); 132 | ALINK_ERROR_CHECK(ret != ALINK_OK, PLATFORM_INVALID_FD, "network_create_socket"); 133 | 134 | return (void *)sock; 135 | } 136 | 137 | void *platform_udp_multicast_server_create(pplatform_netaddr_t netaddr) 138 | { 139 | ALINK_ASSERT(netaddr); 140 | 141 | int option = 1; 142 | struct sockaddr_in addr; 143 | int sock; 144 | struct ip_mreq mreq; 145 | alink_err_t ret = 0; 146 | 147 | platform_netaddr_t netaddr_client = {NULL, netaddr->port}; 148 | 149 | memset(&addr, 0, sizeof(addr)); 150 | memset(&mreq, 0, sizeof(mreq)); 151 | 152 | ret = network_create_socket(&netaddr_client, SOCK_DGRAM, &addr, &sock); 153 | ALINK_ERROR_CHECK(ret != ALINK_OK, PLATFORM_INVALID_FD, "network_create_socket"); 154 | 155 | /* allow multiple sockets to use the same PORT number */ 156 | if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option)) < 0) { 157 | ALINK_LOGE("setsockopt"); 158 | platform_udp_close((void *)sock); 159 | return PLATFORM_INVALID_FD; 160 | } 161 | 162 | if (-1 == bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))) { 163 | ALINK_LOGE("socket bind"); 164 | platform_udp_close((void *)sock); 165 | return PLATFORM_INVALID_FD; 166 | } 167 | 168 | mreq.imr_multiaddr.s_addr = inet_addr(netaddr->host); 169 | mreq.imr_interface.s_addr = htonl(INADDR_ANY); 170 | 171 | if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq)) < 0) { 172 | ALINK_LOGE("setsockopt IP_ADD_MEMBERSHIP"); 173 | platform_udp_close((void *)sock); 174 | return PLATFORM_INVALID_FD; 175 | } 176 | 177 | return (void *)sock; 178 | } 179 | 180 | void platform_udp_close(void *handle) 181 | { 182 | if ((int)handle >= 0) { 183 | close((int)handle); 184 | } 185 | } 186 | 187 | int platform_udp_sendto( 188 | _IN_ void *handle, 189 | _IN_ const char *buffer, 190 | _IN_ uint32_t length, 191 | _IN_ pplatform_netaddr_t netaddr) 192 | { 193 | ALINK_PARAM_CHECK((int)handle >= 0); 194 | ALINK_PARAM_CHECK(buffer); 195 | ALINK_PARAM_CHECK(netaddr); 196 | 197 | int ret; 198 | uint32_t ip; 199 | struct in_addr in; 200 | struct hostent *hp; 201 | struct sockaddr_in addr; 202 | 203 | if (inet_aton(netaddr->host, &in)) { 204 | ip = *(uint32_t *)∈ 205 | } else { 206 | hp = gethostbyname(netaddr->host); 207 | ALINK_ERROR_CHECK(!hp, ALINK_ERR, "gethostbyname Can't resolute the host address hp:%p", hp); 208 | ip = *(uint32_t *)(hp->h_addr); 209 | } 210 | 211 | addr.sin_addr.s_addr = ip; 212 | addr.sin_family = AF_INET; 213 | addr.sin_port = htons(netaddr->port); 214 | 215 | ret = sendto((int)handle, 216 | buffer, 217 | length, 218 | 0, 219 | (struct sockaddr *)&addr, 220 | sizeof(struct sockaddr_in)); 221 | ALINK_ERROR_CHECK(ret <= 0, ALINK_ERR, "sendto ret:%d, errno:%d", ret, errno); 222 | 223 | return ret; 224 | } 225 | 226 | int platform_udp_recvfrom( 227 | _IN_ void *handle, 228 | _OUT_ char *buffer, 229 | _IN_ uint32_t length, 230 | _OUT_OPT_ pplatform_netaddr_t netaddr) 231 | { 232 | ALINK_PARAM_CHECK((int)handle >= 0); 233 | ALINK_PARAM_CHECK(buffer); 234 | 235 | int ret; 236 | struct sockaddr_in addr; 237 | unsigned int addr_len = sizeof(addr); 238 | 239 | ret = recvfrom((int)handle, buffer, length, 0, (struct sockaddr *)&addr, &addr_len); 240 | ALINK_ERROR_CHECK(ret <= 0, ALINK_ERR, "recvfrom ret:%d, errno:%d", ret, errno); 241 | 242 | if (NULL != netaddr) { 243 | netaddr->port = ntohs(addr.sin_port); 244 | 245 | if (NULL != netaddr->host) { 246 | strcpy(netaddr->host, inet_ntoa(addr.sin_addr)); 247 | } 248 | } 249 | 250 | return ret; 251 | } 252 | 253 | 254 | void *platform_tcp_server_create(_IN_ uint16_t port) 255 | { 256 | struct sockaddr_in addr; 257 | int server_socket; 258 | alink_err_t ret = 0; 259 | platform_netaddr_t netaddr = {NULL, port}; 260 | 261 | ret = network_create_socket(&netaddr, SOCK_STREAM, &addr, &server_socket); 262 | ALINK_ERROR_CHECK(ret != ALINK_OK, PLATFORM_INVALID_FD, "network_create_socket"); 263 | 264 | if (-1 == bind(server_socket, (struct sockaddr *)&addr, sizeof(addr))) { 265 | ALINK_LOGE("bind"); 266 | platform_tcp_close((void *)server_socket); 267 | return PLATFORM_INVALID_FD; 268 | } 269 | 270 | if (0 != listen(server_socket, SOMAXCONN)) { 271 | ALINK_LOGE("listen"); 272 | platform_tcp_close((void *)server_socket); 273 | return PLATFORM_INVALID_FD; 274 | } 275 | 276 | return (void *)server_socket; 277 | } 278 | 279 | void *platform_tcp_server_accept(_IN_ void *server) 280 | { 281 | ALINK_ASSERT(server); 282 | 283 | struct sockaddr_in addr; 284 | unsigned int addr_length = sizeof(addr); 285 | int new_client; 286 | 287 | new_client = accept((int)server, (struct sockaddr *)&addr, &addr_length); 288 | ALINK_ERROR_CHECK(new_client <= 0, PLATFORM_INVALID_FD, "accept errno:%d", errno); 289 | 290 | return (void *)new_client; 291 | } 292 | 293 | void *platform_tcp_client_connect(_IN_ pplatform_netaddr_t netaddr) 294 | { 295 | ALINK_ASSERT(netaddr); 296 | 297 | struct sockaddr_in addr; 298 | int sock; 299 | alink_err_t ret = 0; 300 | 301 | ret = network_create_socket(netaddr, SOCK_STREAM, &addr, &sock); 302 | ALINK_ERROR_CHECK(ret != ALINK_OK, PLATFORM_INVALID_FD, "network_create_socket"); 303 | 304 | if (-1 == connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))) { 305 | ALINK_LOGE("connect errno: %d", errno); 306 | perror("connect"); 307 | platform_tcp_close((void *)sock); 308 | return PLATFORM_INVALID_FD; 309 | } 310 | 311 | return (void *)sock; 312 | } 313 | 314 | 315 | int platform_tcp_send(_IN_ void *handle, _IN_ const char *buffer, _IN_ uint32_t length) 316 | { 317 | ALINK_PARAM_CHECK((int)handle >= 0); 318 | ALINK_PARAM_CHECK(buffer); 319 | int bytes_sent; 320 | 321 | bytes_sent = send((int)handle, buffer, length, 0); 322 | ALINK_ERROR_CHECK(bytes_sent <= 0, ALINK_ERR, "send ret:%d", bytes_sent); 323 | return bytes_sent; 324 | } 325 | 326 | int platform_tcp_recv(_IN_ void *handle, _OUT_ char *buffer, _IN_ uint32_t length) 327 | { 328 | ALINK_PARAM_CHECK((int)handle >= 0); 329 | ALINK_PARAM_CHECK(buffer); 330 | 331 | int bytes_received = recv((int)handle, buffer, length, 0); 332 | ALINK_ERROR_CHECK(bytes_received <= 0, ALINK_ERR, "recv ret:%d", bytes_received); 333 | 334 | return bytes_received; 335 | } 336 | 337 | void platform_tcp_close(_IN_ void *handle) 338 | { 339 | if ((int)handle >= 0) { 340 | close((int)handle); 341 | } 342 | } 343 | 344 | int platform_select(void *read_fds[PLATFORM_SOCKET_MAXNUMS], 345 | void *write_fds[PLATFORM_SOCKET_MAXNUMS], 346 | int timeout_ms) 347 | { 348 | ALINK_PARAM_CHECK(read_fds || write_fds); 349 | 350 | int i, ret = -1; 351 | struct timeval timeout_value; 352 | struct timeval *ptimeval = &timeout_value; 353 | fd_set r_set, w_set; 354 | int max_fd = -1; 355 | 356 | if (PLATFORM_WAIT_INFINITE == timeout_ms) { 357 | ptimeval = NULL; 358 | } else { 359 | ptimeval->tv_sec = timeout_ms / 1000; 360 | ptimeval->tv_usec = (timeout_ms % 1000) * 1000; 361 | } 362 | 363 | FD_ZERO(&r_set); 364 | FD_ZERO(&w_set); 365 | 366 | if (read_fds) { 367 | for (i = 0; i < PLATFORM_SOCKET_MAXNUMS; ++i) { 368 | if (PLATFORM_INVALID_FD != read_fds[i]) { 369 | FD_SET((int)read_fds[i], &r_set); 370 | } 371 | 372 | if ((int)read_fds[i] > max_fd) { 373 | max_fd = (int)read_fds[i]; 374 | } 375 | } 376 | } 377 | 378 | if (write_fds) { 379 | for (i = 0; i < PLATFORM_SOCKET_MAXNUMS; ++i) { 380 | if (PLATFORM_INVALID_FD != write_fds[i]) { 381 | FD_SET((int)write_fds[i], &w_set); 382 | } 383 | 384 | if ((int)write_fds[i] > max_fd) { 385 | max_fd = (int)write_fds[i]; 386 | } 387 | } 388 | } 389 | 390 | ret = select(max_fd + 1, &r_set, &w_set, NULL, ptimeval); 391 | 392 | if (ret > 0) { 393 | if (read_fds) { 394 | for (i = 0; i < PLATFORM_SOCKET_MAXNUMS; ++i) { 395 | if (PLATFORM_INVALID_FD != read_fds[i] 396 | && !FD_ISSET((int)read_fds[i], &r_set)) { 397 | read_fds[i] = PLATFORM_INVALID_FD; 398 | } 399 | } 400 | } 401 | 402 | if (write_fds) { 403 | for (i = 0; i < PLATFORM_SOCKET_MAXNUMS; ++i) { 404 | if (PLATFORM_INVALID_FD != write_fds[i] 405 | && !FD_ISSET((int)write_fds[i], &w_set)) { 406 | write_fds[i] = PLATFORM_INVALID_FD; 407 | } 408 | } 409 | } 410 | } else {/* clear all fd */ 411 | if (read_fds) { 412 | for (i = 0; i < PLATFORM_SOCKET_MAXNUMS; ++i) { 413 | read_fds[i] = PLATFORM_INVALID_FD; 414 | } 415 | } 416 | 417 | if (write_fds) { 418 | for (i = 0; i < PLATFORM_SOCKET_MAXNUMS; ++i) { 419 | write_fds[i] = PLATFORM_INVALID_FD; 420 | } 421 | } 422 | } 423 | 424 | ALINK_ERROR_CHECK(ret < 0, ret, "select max_fd: %d, ret:%d, errno: %d", max_fd, ret, errno); 425 | return ret; 426 | } 427 | -------------------------------------------------------------------------------- /adaptation/alink_os.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2017 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #include "esp_system.h" 26 | #include "freertos/FreeRTOS.h" 27 | #include "freertos/task.h" 28 | #include "freertos/semphr.h" 29 | 30 | #include "lwip/sockets.h" 31 | 32 | #include "alink_platform.h" 33 | #include "esp_alink.h" 34 | #include "esp_alink_log.h" 35 | #include "esp_info_store.h" 36 | 37 | static const char *TAG = "alink_os"; 38 | 39 | typedef struct task_name_handler_content { 40 | const char *task_name; 41 | void *handler; 42 | } task_infor_t; 43 | 44 | static task_infor_t task_infor[] = { 45 | {"wsf_receive_worker", NULL}, 46 | {"alcs_thread", NULL}, 47 | {"work queue", NULL}, 48 | {NULL, NULL} 49 | }; 50 | 51 | void platform_printf(const char *fmt, ...) 52 | { 53 | /* Clear sniffer process information */ 54 | if (!strncmp(fmt, "[%d] ssid:%s, mac:", 18) || !strncmp(fmt, "channel %d", 10)) { 55 | return; 56 | } 57 | 58 | va_list args; 59 | va_start(args, fmt); 60 | vprintf(fmt, args); 61 | va_end(args); 62 | fflush(stdout); 63 | } 64 | 65 | 66 | /************************ memory manage ************************/ 67 | void *platform_malloc(_IN_ uint32_t size) 68 | { 69 | return alink_malloc(size); 70 | } 71 | 72 | void platform_free(_IN_ void *ptr) 73 | { 74 | alink_free(ptr); 75 | } 76 | 77 | 78 | /************************ mutex manage ************************/ 79 | void *platform_mutex_init(void) 80 | { 81 | return xSemaphoreCreateMutex(); 82 | } 83 | 84 | void platform_mutex_destroy(_IN_ void *mutex) 85 | { 86 | if (mutex) { 87 | vSemaphoreDelete(mutex); 88 | } 89 | } 90 | 91 | void platform_mutex_lock(_IN_ void *mutex) 92 | { 93 | if (mutex) { 94 | xSemaphoreTake(mutex, portMAX_DELAY); 95 | } 96 | } 97 | 98 | void platform_mutex_unlock(_IN_ void *mutex) 99 | { 100 | if (mutex) { 101 | xSemaphoreGive(mutex); 102 | } 103 | } 104 | 105 | 106 | /************************ semaphore manage ************************/ 107 | void *platform_semaphore_init(void) 108 | { 109 | return xSemaphoreCreateCounting(255, 0); 110 | } 111 | 112 | void platform_semaphore_destroy(_IN_ void *sem) 113 | { 114 | if (sem) { 115 | vSemaphoreDelete(sem); 116 | } 117 | } 118 | 119 | int platform_semaphore_wait(_IN_ void *sem, _IN_ uint32_t timeout_ms) 120 | { 121 | ALINK_PARAM_CHECK(sem); 122 | 123 | return xSemaphoreTake(sem, timeout_ms / portTICK_RATE_MS) ? ALINK_OK : ALINK_ERR; 124 | } 125 | 126 | void platform_semaphore_post(_IN_ void *sem) 127 | { 128 | if (sem) { 129 | xSemaphoreGive(sem); 130 | } 131 | } 132 | 133 | int platform_thread_get_stack_size(_IN_ const char *thread_name) 134 | { 135 | ALINK_PARAM_CHECK(thread_name); 136 | 137 | if (0 == strcmp(thread_name, "work queue")) { 138 | ALINK_LOGD("get work queue"); 139 | return 0xa00; 140 | } else if (0 == strcmp(thread_name, "wsf_receive_worker")) { 141 | ALINK_LOGD("get wsf_receive_worker"); 142 | return 0xa00; 143 | } else if (0 == strcmp(thread_name, "alcs_thread")) { 144 | ALINK_LOGD("get alcs_thread"); 145 | return 0xa00; 146 | } else { 147 | ALINK_LOGE("get othrer thread: %s", thread_name); 148 | return 0x800; 149 | } 150 | } 151 | 152 | 153 | /************************ task ************************/ 154 | static int get_task_name_location(_IN_ const char *name) 155 | { 156 | uint32_t i = 0; 157 | uint32_t len = 0; 158 | 159 | for (i = 0; task_infor[i].task_name != NULL; i++) { 160 | len = (strlen(task_infor[i].task_name) >= configMAX_TASK_NAME_LEN ? configMAX_TASK_NAME_LEN : strlen(task_infor[i].task_name)); 161 | 162 | if (!memcmp(task_infor[i].task_name, name, len)) { 163 | return i; 164 | } 165 | } 166 | 167 | return ALINK_ERR; 168 | } 169 | 170 | static bool set_task_name_handler(uint32_t pos, _IN_ void *handler) 171 | { 172 | ALINK_PARAM_CHECK(handler); 173 | 174 | task_infor[pos].handler = handler; 175 | return ALINK_OK; 176 | } 177 | 178 | int platform_thread_create(_OUT_ void **thread, 179 | _IN_ const char *name, 180 | _IN_ void *(*start_routine)(void *), 181 | _IN_ void *arg, 182 | _IN_ void *stack, 183 | _IN_ uint32_t stack_size, 184 | _OUT_ int *stack_used) 185 | { 186 | ALINK_PARAM_CHECK(name); 187 | ALINK_PARAM_CHECK(stack_size); 188 | 189 | alink_err_t ret; 190 | 191 | uint8_t task_priority = DEFAULU_TASK_PRIOTY; 192 | 193 | if (!strcmp(name, "work queue")) { 194 | task_priority++; 195 | } 196 | 197 | ret = xTaskCreate((TaskFunction_t)start_routine, name, (stack_size) * 2, arg, task_priority, thread); 198 | ALINK_ERROR_CHECK(ret != pdTRUE, ALINK_ERR, "thread_create name: %s, stack_size: %d, ret: %d", name, stack_size, ret); 199 | ALINK_LOGD("thread_create name: %s, stack_size: %d, priority:%d, thread_handle: %p", 200 | name, stack_size * 2, task_priority, *thread); 201 | 202 | int pos = get_task_name_location(name); 203 | 204 | if (pos == ALINK_ERR) { 205 | ALINK_LOGE("get_task_name_location name: %s", name); 206 | vTaskDelete(*thread); 207 | } 208 | 209 | set_task_name_handler(pos, *thread); 210 | return ALINK_OK; 211 | } 212 | 213 | void platform_thread_exit(_IN_ void *thread) 214 | { 215 | vTaskDelete(thread); 216 | } 217 | 218 | 219 | /************************ config ************************/ 220 | #define ALINK_CONFIG_KEY "alink_config" 221 | int platform_config_read(_OUT_ char *buffer, _IN_ int length) 222 | { 223 | ALINK_PARAM_CHECK(buffer); 224 | ALINK_PARAM_CHECK(length > 0); 225 | ALINK_LOGV("buffer: %p, length: %d", buffer, length); 226 | 227 | alink_err_t ret = esp_info_load(ALINK_CONFIG_KEY, buffer, length); 228 | 229 | return ret > 0 ? ALINK_OK : ALINK_ERR; 230 | } 231 | 232 | int platform_config_write(_IN_ const char *buffer, _IN_ int length) 233 | { 234 | ALINK_PARAM_CHECK(buffer); 235 | ALINK_PARAM_CHECK(length > 0); 236 | ALINK_LOGV("buffer: %p, length: %d", buffer, length); 237 | 238 | alink_err_t ret = esp_info_save(ALINK_CONFIG_KEY, buffer, length); 239 | 240 | return ret > 0 ? ALINK_OK : ALINK_ERR; 241 | } 242 | 243 | 244 | /*********************** system info ***********************/ 245 | char *platform_get_chipid(_OUT_ char cid_str[PLATFORM_CID_LEN]) 246 | { 247 | return strncpy(cid_str, ALINK_CHIPID, PLATFORM_CID_LEN); 248 | } 249 | 250 | char *platform_get_os_version(_OUT_ char version_str[STR_SHORT_LEN]) 251 | { 252 | return strncpy(version_str, esp_get_idf_version(), STR_SHORT_LEN); 253 | } 254 | 255 | char *platform_get_module_name(_OUT_ char name_str[STR_SHORT_LEN]) 256 | { 257 | return strncpy(name_str, ALINK_MODULE_NAME, STR_SHORT_LEN); 258 | } 259 | 260 | void platform_sys_reboot(void) 261 | { 262 | ALINK_LOGW("platform_sys_reboot"); 263 | esp_restart(); 264 | } 265 | 266 | void platform_msleep(_IN_ uint32_t ms) 267 | { 268 | vTaskDelay(ms / portTICK_RATE_MS); 269 | } 270 | 271 | uint32_t platform_get_time_ms(void) 272 | { 273 | return system_get_time() / 1000; 274 | } 275 | -------------------------------------------------------------------------------- /adaptation/alink_product.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2017 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #include 26 | 27 | #include "esp_wifi.h" 28 | 29 | #include "alink_product.h" 30 | #include "esp_alink_log.h" 31 | #include "esp_spi_flash.h" 32 | 33 | static const char *TAG = "alink_product"; 34 | static alink_product_t g_device_info; 35 | 36 | alink_err_t product_get(_OUT_ void *product_info) 37 | { 38 | ALINK_PARAM_CHECK(product_info); 39 | 40 | memcpy(product_info, &g_device_info, sizeof(alink_product_t)); 41 | return ALINK_OK; 42 | } 43 | 44 | alink_err_t product_set(_IN_ const void *product_info) 45 | { 46 | ALINK_PARAM_CHECK(product_info); 47 | 48 | memcpy(&g_device_info, product_info, sizeof(alink_product_t)); 49 | return ALINK_OK; 50 | } 51 | 52 | char *product_get_name(char name_str[PRODUCT_NAME_LEN]) 53 | { 54 | return strncpy(name_str, g_device_info.name, PRODUCT_NAME_LEN); 55 | } 56 | 57 | char *product_get_version(char ver_str[PRODUCT_VERSION_LEN]) 58 | { 59 | return strncpy(ver_str, g_device_info.version, PRODUCT_VERSION_LEN); 60 | } 61 | 62 | char *product_get_model(char model_str[PRODUCT_MODEL_LEN]) 63 | { 64 | return strncpy(model_str, g_device_info.model, PRODUCT_MODEL_LEN); 65 | } 66 | 67 | char *product_get_key(char key_str[PRODUCT_KEY_LEN]) 68 | { 69 | return strncpy(key_str, g_device_info.key, PRODUCT_KEY_LEN); 70 | } 71 | 72 | char *product_get_secret(char secret_str[PRODUCT_SECRET_LEN]) 73 | { 74 | return strncpy(secret_str, g_device_info.secret, PRODUCT_SECRET_LEN); 75 | } 76 | 77 | char *product_get_debug_key(char key_str[PRODUCT_KEY_LEN]) 78 | { 79 | if (!g_device_info.key_sandbox) { 80 | return NULL; 81 | } 82 | 83 | return strncpy(key_str, g_device_info.key_sandbox, PRODUCT_KEY_LEN); 84 | } 85 | 86 | char *product_get_debug_secret(char secret_str[PRODUCT_SECRET_LEN]) 87 | { 88 | if (!g_device_info.secret_sandbox) { 89 | return NULL; 90 | } 91 | 92 | return strncpy(secret_str, g_device_info.secret_sandbox, PRODUCT_SECRET_LEN); 93 | } 94 | 95 | 96 | char *product_get_device_key(char key_str[DEVICE_KEY_LEN]) 97 | { 98 | alink_err_t ret = ALINK_OK; 99 | 100 | if (g_device_info.key_device && strlen(g_device_info.key_device) == DEVICE_KEY_LEN - 1) { 101 | return strncpy(key_str, g_device_info.key_device, DEVICE_KEY_LEN); 102 | } 103 | 104 | ret = spi_flash_read(DEVICE_ID_ADRR, key_str, DEVICE_KEY_LEN - 1); 105 | ALINK_ERROR_CHECK(ret < 0, NULL, "spi_flash_read, key_str, ret: %d", ret); 106 | 107 | uint8_t invalid_device_key[DEVICE_KEY_LEN]; 108 | memset(invalid_device_key, 0xff, DEVICE_KEY_LEN); 109 | 110 | if (!memcmp(invalid_device_key, key_str, DEVICE_KEY_LEN - 1)) { 111 | ALINK_LOGE("the ID of the device is blank. write the ID of the device in flash"); 112 | vTaskDelay(portMAX_DELAY); 113 | } 114 | 115 | ALINK_LOGI("device_key: %s", key_str); 116 | 117 | return key_str; 118 | } 119 | 120 | char *product_get_device_secret(char secret_str[DEVICE_SECRET_LEN]) 121 | { 122 | alink_err_t ret = ALINK_OK; 123 | 124 | if (g_device_info.secret_device && strlen(g_device_info.secret_device) == DEVICE_SECRET_LEN - 1) { 125 | return strncpy(secret_str, g_device_info.secret_device, DEVICE_SECRET_LEN); 126 | } 127 | 128 | ret = spi_flash_read(DEVICE_ID_ADRR + DEVICE_KEY_LEN, secret_str, DEVICE_SECRET_LEN - 1); 129 | ALINK_ERROR_CHECK(ret < 0, NULL, "spi_flash_read, secret_str, ret: %d", ret); 130 | 131 | uint8_t invalid_device_secret[DEVICE_SECRET_LEN]; 132 | memset(invalid_device_secret, 0xff, DEVICE_SECRET_LEN); 133 | 134 | if (!memcmp(invalid_device_secret, secret_str, DEVICE_SECRET_LEN - 1)) { 135 | ALINK_LOGE("the ID of the device is blank. write the ID of the device in flash"); 136 | vTaskDelay(portMAX_DELAY); 137 | } 138 | 139 | ALINK_LOGI("device_secret: %s", secret_str); 140 | 141 | return secret_str; 142 | } 143 | 144 | char *product_get_sn(char sn_str[PRODUCT_SN_LEN]) 145 | { 146 | uint8_t mac[6] = {0}; 147 | ESP_ERROR_CHECK(esp_wifi_get_mac(ESP_IF_WIFI_STA, mac)); 148 | snprintf(sn_str, PRODUCT_SN_LEN, "%02x%02x%02x%02x%02x%02x", MAC2STR(mac)); 149 | return sn_str; 150 | } 151 | -------------------------------------------------------------------------------- /adaptation/alink_ssl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2017 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #include 26 | 27 | #include "openssl/ssl.h" 28 | #include "freertos/FreeRTOS.h" 29 | #include "freertos/task.h" 30 | #include "lwip/sockets.h" 31 | #include "lwip/netdb.h" 32 | 33 | #include "esp_alink.h" 34 | #include "esp_alink_log.h" 35 | #include "alink_platform.h" 36 | 37 | static SSL_CTX *ctx = NULL; 38 | static const char *TAG = "alink_ssl"; 39 | static void *alink_ssl_mutex = NULL; 40 | 41 | void *platform_ssl_connect(_IN_ void *tcp_fd, _IN_ const char *server_cert, _IN_ int server_cert_len) 42 | { 43 | ALINK_ASSERT(server_cert); 44 | 45 | if (platform_sys_net_is_ready() == ALINK_FALSE) { 46 | ALINK_LOGW("wifi disconnect"); 47 | return NULL; 48 | } 49 | 50 | SSL *ssl = NULL; 51 | int socket = (int)tcp_fd; 52 | int ret = -1; 53 | 54 | if (alink_ssl_mutex == NULL) { 55 | alink_ssl_mutex = platform_mutex_init(); 56 | } 57 | 58 | platform_mutex_lock(alink_ssl_mutex); 59 | 60 | ctx = SSL_CTX_new(TLSv1_1_client_method()); 61 | ALINK_ERROR_GOTO(!ctx, ERR_EXIT, "SSL_CTX_new, ctx: %p", ctx); 62 | 63 | ALINK_LOGD("set SSL new"); 64 | ssl = SSL_new(ctx); 65 | ALINK_ERROR_GOTO(!ssl, ERR_EXIT, "SSL_new, ssl: %p", ssl); 66 | 67 | ALINK_LOGV("set SSL_set_fd"); 68 | SSL_set_fd(ssl, socket); 69 | X509 *ca_cert = d2i_X509(NULL, (unsigned char *)server_cert, server_cert_len); 70 | ALINK_ERROR_GOTO(!ca_cert, ERR_EXIT, "d2i_X509, ca_cert: %p", ca_cert); 71 | 72 | ALINK_LOGV("set SSL_connect"); 73 | ret = SSL_add_client_CA(ssl, ca_cert); 74 | ALINK_ERROR_GOTO(ret == pdFALSE, ERR_EXIT, "SSL_add_client_CA, ret: %d", ret); 75 | 76 | ret = SSL_connect(ssl); 77 | ALINK_ERROR_GOTO(ret == pdFALSE, ERR_EXIT, "SSL_connect, ret: %d", ret); 78 | 79 | ALINK_LOGD("set SSL_connect is successed"); 80 | platform_mutex_unlock(alink_ssl_mutex); 81 | 82 | return ssl; 83 | 84 | ERR_EXIT: 85 | platform_mutex_unlock(alink_ssl_mutex); 86 | 87 | if (ctx) { 88 | SSL_CTX_free(ctx); 89 | ctx = NULL; 90 | } 91 | 92 | if (ssl) { 93 | platform_ssl_close(ssl); 94 | } 95 | 96 | return NULL; 97 | } 98 | 99 | int platform_ssl_send(_IN_ void *ssl, _IN_ const char *buffer, _IN_ int length) 100 | { 101 | ALINK_PARAM_CHECK(length > 0); 102 | ALINK_PARAM_CHECK(buffer); 103 | ALINK_PARAM_CHECK(ssl); 104 | 105 | alink_err_t ret; 106 | 107 | if (alink_ssl_mutex == NULL) { 108 | alink_ssl_mutex = platform_mutex_init(); 109 | } 110 | 111 | platform_mutex_lock(alink_ssl_mutex); 112 | ALINK_LOGV("SSL_write start"); 113 | ret = SSL_write((SSL *)ssl, buffer, length); 114 | ALINK_LOGV("SSL_write end"); 115 | platform_mutex_unlock(alink_ssl_mutex); 116 | ALINK_ERROR_CHECK(ret <= 0, ALINK_ERR, "SSL_write, ret:%d, errno:%d", ret, errno); 117 | return ret; 118 | } 119 | 120 | int platform_ssl_recv(_IN_ void *ssl, _OUT_ char *buffer, _IN_ int length) 121 | { 122 | ALINK_PARAM_CHECK(ssl); 123 | ALINK_PARAM_CHECK(buffer); 124 | 125 | int ret = -1; 126 | 127 | if (alink_ssl_mutex == NULL) { 128 | alink_ssl_mutex = platform_mutex_init(); 129 | } 130 | 131 | platform_mutex_lock(alink_ssl_mutex); 132 | ALINK_LOGV("SSL_read start"); 133 | ret = SSL_read((SSL *)ssl, buffer, length); 134 | ALINK_LOGV("SSL_read end"); 135 | platform_mutex_unlock(alink_ssl_mutex); 136 | 137 | if (ret <= 0) { 138 | perror("SSL_read"); 139 | } 140 | 141 | ALINK_ERROR_CHECK(ret <= 0, ALINK_ERR, "SSL_read, ret:%d, errno:%d", ret, errno); 142 | return ret; 143 | } 144 | 145 | int platform_ssl_close(_IN_ void *ssl) 146 | { 147 | ALINK_PARAM_CHECK(ssl); 148 | 149 | alink_err_t ret = -1; 150 | 151 | if (alink_ssl_mutex == NULL) { 152 | alink_ssl_mutex = platform_mutex_init(); 153 | } 154 | 155 | platform_mutex_lock(alink_ssl_mutex); 156 | ret = SSL_shutdown((SSL *)ssl); 157 | 158 | if (ret == pdFALSE) { 159 | ALINK_LOGW("SSL_shutdown: ret:%d, ssl: %p", ret, ssl); 160 | } 161 | 162 | int fd = SSL_get_fd((SSL *)ssl); 163 | 164 | if (ssl) { 165 | SSL_free(ssl); 166 | ssl = NULL; 167 | } 168 | 169 | if (ctx) { 170 | SSL_CTX_free(ctx); 171 | ctx = NULL; 172 | } 173 | 174 | if (fd >= 0) { 175 | close(fd); 176 | } else { 177 | ALINK_LOGE("SSL_get_fd:%d", fd); 178 | } 179 | 180 | platform_mutex_unlock(alink_ssl_mutex); 181 | 182 | return (ret == pdTRUE) ? ALINK_OK : ALINK_ERR; 183 | } 184 | -------------------------------------------------------------------------------- /adaptation/alink_upgrade.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2017 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #include 26 | 27 | #include "esp_system.h" 28 | #include "esp_ota_ops.h" 29 | #include "esp_partition.h" 30 | 31 | #include "esp_alink.h" 32 | #include "esp_alink_log.h" 33 | 34 | static const char *TAG = "alink_upgrade"; 35 | 36 | /* update handle : set by esp_ota_begin(), must be freed via esp_ota_end() */ 37 | static esp_ota_handle_t update_handle = 0 ; 38 | static const esp_partition_t *update_partition = NULL; 39 | static int binary_file_length = 0; 40 | 41 | void platform_flash_program_start(void) 42 | { 43 | alink_err_t ret = 0; 44 | const esp_partition_t *configured = esp_ota_get_boot_partition(); 45 | const esp_partition_t *running = esp_ota_get_running_partition(); 46 | 47 | assert(configured == running); /* fresh from reset, should be running from configured boot partition */ 48 | ALINK_LOGI("Running partition type %d subtype %d (offset 0x%08x)", 49 | configured->type, configured->subtype, configured->address); 50 | 51 | update_partition = esp_ota_get_next_update_partition(NULL); 52 | ALINK_LOGI("Writing to partition subtype %d at offset 0x%x", 53 | update_partition->subtype, update_partition->address); 54 | assert(update_partition != NULL); 55 | 56 | ret = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle); 57 | ALINK_ERROR_CHECK(ret != ESP_OK, ; , "esp_ota_begin failed, retor=%d", ret); 58 | 59 | ALINK_LOGI("esp_ota_begin succeeded"); 60 | } 61 | 62 | int platform_flash_program_write_block(_IN_ char *buffer, _IN_ uint32_t length) 63 | { 64 | ALINK_PARAM_CHECK(length); 65 | ALINK_PARAM_CHECK(buffer); 66 | 67 | alink_err_t ret = 0; 68 | 69 | ret = esp_ota_write(update_handle, (const void *)buffer, length); 70 | ALINK_ERROR_CHECK(ret != ESP_OK, ALINK_ERR, "Error: esp_ota_write failed! ret=0x%x", ret); 71 | 72 | binary_file_length += length; 73 | ALINK_LOGI("Have written image length %d", binary_file_length); 74 | 75 | return ALINK_OK; 76 | } 77 | 78 | int platform_flash_program_stop(void) 79 | { 80 | alink_err_t ret = 0; 81 | ALINK_LOGI("Total Write binary data length : %d", binary_file_length); 82 | 83 | ret = esp_ota_end(update_handle); 84 | ALINK_ERROR_CHECK(ret != ESP_OK, ALINK_ERR, "esp_ota_end failed!"); 85 | 86 | ret = esp_ota_set_boot_partition(update_partition); 87 | ALINK_ERROR_CHECK(ret != ESP_OK, ALINK_ERR, "esp_ota_set_boot_partition failed! ret=0x%x", ret); 88 | 89 | return ALINK_OK; 90 | } 91 | -------------------------------------------------------------------------------- /adaptation/alink_wifi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2017 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #include "esp_system.h" 26 | #include "esp_wifi.h" 27 | #include "esp_event_loop.h" 28 | #include "lwip/sockets.h" 29 | #include "freertos/timers.h" 30 | 31 | #include "alink_platform.h" 32 | #include "esp_alink.h" 33 | #include "esp_alink_log.h" 34 | #include "esp_info_store.h" 35 | 36 | static platform_awss_recv_80211_frame_cb_t g_sniffer_cb = NULL; 37 | static const char *TAG = "alink_wifi"; 38 | /** 39 | * @brief Get timeout interval, in millisecond, of per awss. 40 | * 41 | * @param None. 42 | * @return The timeout interval. 43 | * @see None. 44 | * @note The recommended value is 60,000ms. 45 | */ 46 | int platform_awss_get_timeout_interval_ms(void) 47 | { 48 | return 3 * 60 * 1000; 49 | } 50 | 51 | /** 52 | * @brief Get timeout interval in millisecond to connect the default SSID if awss timeout happens. 53 | * 54 | * @param None. 55 | * @return The timeout interval. 56 | * @see None. 57 | * @note The recommended value is 0ms, which mean forever. 58 | */ 59 | int platform_awss_get_connect_default_ssid_timeout_interval_ms(void) 60 | { 61 | return 0; 62 | } 63 | 64 | /** 65 | * @brief Get time length, in millisecond, of per channel scan. 66 | * 67 | * @param None. 68 | * @return The timeout interval. 69 | * @see None. 70 | * @note None. The recommended value is between 200ms and 400ms. 71 | */ 72 | int platform_awss_get_channelscan_interval_ms(void) 73 | { 74 | return 200; 75 | } 76 | 77 | /** 78 | * @brief Switch to specific wifi channel. 79 | * 80 | * @param[in] primary_channel @n Primary channel. 81 | * @param[in] secondary_channel @n Auxiliary channel if 40Mhz channel is supported, currently 82 | * this param is always 0. 83 | * @param[in] bssid @n A pointer to wifi BSSID on which awss lock the channel, most platform 84 | * may ignore it. 85 | */ 86 | void platform_awss_switch_channel(char primary_channel, 87 | char secondary_channel, uint8_t bssid[ETH_ALEN]) 88 | { 89 | ESP_ERROR_CHECK(esp_wifi_set_channel(primary_channel, secondary_channel)); 90 | } 91 | 92 | static void IRAM_ATTR wifi_sniffer_cb_(void *recv_buf, wifi_promiscuous_pkt_type_t type) 93 | { 94 | wifi_promiscuous_pkt_t *sniffer = (wifi_promiscuous_pkt_t *)recv_buf; 95 | g_sniffer_cb((char *)sniffer->payload, sniffer->rx_ctrl.sig_len, AWSS_LINK_TYPE_NONE, 1); 96 | } 97 | 98 | /** 99 | * @brief Set wifi running at monitor mode, 100 | and register a callback function which will be called when wifi receive a frame. 101 | * 102 | * @param[in] cb @n A function pointer, called back when wifi receive a frame. 103 | */ 104 | void platform_awss_open_monitor(_IN_ platform_awss_recv_80211_frame_cb_t cb) 105 | { 106 | ALINK_ASSERT(cb); 107 | 108 | g_sniffer_cb = cb; 109 | ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); 110 | ESP_ERROR_CHECK(esp_wifi_set_promiscuous(0)); 111 | ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(wifi_sniffer_cb_)); 112 | ESP_ERROR_CHECK(esp_wifi_set_promiscuous(1)); 113 | ESP_ERROR_CHECK(esp_wifi_set_channel(6, 0)); 114 | ESP_ERROR_CHECK(esp_wifi_start()); 115 | 116 | ALINK_LOGI("wifi running at monitor mode"); 117 | } 118 | 119 | /** 120 | * @brief Close wifi monitor mode, and set running at station mode. 121 | */ 122 | void platform_awss_close_monitor(void) 123 | { 124 | ESP_ERROR_CHECK(esp_wifi_set_promiscuous(0)); 125 | ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(NULL)); 126 | ESP_ERROR_CHECK(esp_wifi_stop()); 127 | 128 | ALINK_LOGI("close wifi monitor mode, and set running at station mode"); 129 | } 130 | 131 | 132 | int platform_wifi_get_rssi_dbm(void) 133 | { 134 | wifi_ap_record_t ap_infor; 135 | esp_wifi_sta_get_ap_info(&ap_infor); 136 | return ap_infor.rssi; 137 | } 138 | 139 | char *platform_wifi_get_mac(_OUT_ char mac_str[PLATFORM_MAC_LEN]) 140 | { 141 | ALINK_ASSERT(mac_str); 142 | 143 | uint8_t mac[6] = {0}; 144 | ESP_ERROR_CHECK(esp_wifi_get_mac(ESP_IF_WIFI_STA, mac)); 145 | snprintf(mac_str, PLATFORM_MAC_LEN, MACSTR, MAC2STR(mac)); 146 | return mac_str; 147 | } 148 | 149 | uint32_t platform_wifi_get_ip(_OUT_ char ip_str[PLATFORM_IP_LEN]) 150 | { 151 | ALINK_PARAM_CHECK(ip_str); 152 | 153 | tcpip_adapter_ip_info_t infor; 154 | tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &infor); 155 | memcpy(ip_str, inet_ntoa(infor.ip.addr), PLATFORM_IP_LEN); 156 | return infor.ip.addr; 157 | } 158 | 159 | static bool sys_net_is_ready = false; 160 | int platform_sys_net_is_ready(void) 161 | { 162 | return sys_net_is_ready; 163 | } 164 | 165 | static TimerHandle_t g_timer = NULL; 166 | static void wifi_connect_timer_cb(void *timer) 167 | { 168 | if (!platform_sys_net_is_ready()) { 169 | ESP_ERROR_CHECK(esp_wifi_disconnect()); 170 | } 171 | 172 | xTimerStop(g_timer, 0); 173 | xTimerDelete(g_timer, 0); 174 | g_timer = NULL; 175 | } 176 | 177 | static SemaphoreHandle_t xSemConnet = NULL; 178 | static alink_err_t event_handler(void *ctx, system_event_t *event) 179 | { 180 | switch (event->event_id) { 181 | case SYSTEM_EVENT_STA_CONNECTED: 182 | ALINK_LOGI("EVENT_STAMODE_CONNECTED"); 183 | 184 | /*!< compatible with xiaomi company's R1C router */ 185 | if (!g_timer) { 186 | g_timer = xTimerCreate("Timer", 4000 / portTICK_RATE_MS, false, 187 | NULL, wifi_connect_timer_cb); 188 | xTimerStart(g_timer, 0); 189 | } 190 | break; 191 | 192 | case SYSTEM_EVENT_STA_START: 193 | ALINK_LOGI("SYSTEM_EVENT_STA_START"); 194 | sys_net_is_ready = false; 195 | ESP_ERROR_CHECK(esp_wifi_connect()); 196 | break; 197 | 198 | case SYSTEM_EVENT_STA_GOT_IP: 199 | sys_net_is_ready = true; 200 | ALINK_LOGI("SYSTEM_EVENT_STA_GOT_IP"); 201 | xSemaphoreGive(xSemConnet); 202 | alink_event_send(ALINK_EVENT_WIFI_CONNECTED); 203 | break; 204 | 205 | case SYSTEM_EVENT_STA_DISCONNECTED: 206 | ALINK_LOGI("SYSTEM_EVENT_STA_DISCONNECTED, free_heap: %d", esp_get_free_heap_size()); 207 | sys_net_is_ready = false; 208 | alink_event_send(ALINK_EVENT_WIFI_DISCONNECTED); 209 | int ret = esp_wifi_connect(); 210 | 211 | if (ret != ESP_OK) { 212 | ALINK_LOGE("esp_wifi_connect, ret: %d", ret); 213 | } 214 | 215 | break; 216 | 217 | default: 218 | break; 219 | } 220 | 221 | return ALINK_OK; 222 | } 223 | 224 | int platform_awss_connect_ap( 225 | _IN_ uint32_t connection_timeout_ms, 226 | _IN_ char ssid[PLATFORM_MAX_SSID_LEN], 227 | _IN_ char passwd[PLATFORM_MAX_PASSWD_LEN], 228 | _IN_OPT_ enum AWSS_AUTH_TYPE auth, 229 | _IN_OPT_ enum AWSS_ENC_TYPE encry, 230 | _IN_OPT_ uint8_t bssid[ETH_ALEN], 231 | _IN_OPT_ uint8_t channel) 232 | { 233 | wifi_config_t wifi_config; 234 | alink_err_t ret = 0; 235 | 236 | if (xSemConnet == NULL) { 237 | xSemConnet = xSemaphoreCreateBinary(); 238 | esp_event_loop_set_cb(event_handler, NULL); 239 | } 240 | 241 | ESP_ERROR_CHECK(esp_wifi_stop()); 242 | ESP_ERROR_CHECK(esp_wifi_get_config(WIFI_IF_STA, &wifi_config)); 243 | ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); 244 | 245 | memcpy(wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid)); 246 | memcpy(wifi_config.sta.password, passwd, sizeof(wifi_config.sta.password)); 247 | ALINK_LOGI("ap ssid: %s, password: %s", wifi_config.sta.ssid, wifi_config.sta.password); 248 | ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); 249 | 250 | ESP_ERROR_CHECK(esp_wifi_start()); 251 | 252 | ret = xSemaphoreTake(xSemConnet, connection_timeout_ms / portTICK_RATE_MS); 253 | ALINK_ERROR_CHECK(ret == pdFALSE, ALINK_ERR, "xSemaphoreTake, wait: %d", connection_timeout_ms); 254 | 255 | if (!strcmp(ssid, "aha")) { 256 | return ALINK_OK; 257 | } 258 | 259 | ret = esp_info_save(NVS_KEY_WIFI_CONFIG, &wifi_config, sizeof(wifi_config_t)); 260 | ALINK_ERROR_CHECK(ret < 0, ALINK_ERR, "alink information save failed"); 261 | 262 | return ALINK_OK; 263 | } 264 | 265 | /** 266 | * @brief send 80211 raw frame in current channel with basic rate(1Mbps) 267 | * 268 | * @param[in] type @n see enum platform_awss_frame_type, currently only FRAME_BEACON 269 | * FRAME_PROBE_REQ is used 270 | * @param[in] buffer @n 80211 raw frame, include complete mac header & FCS field 271 | * @param[in] len @n 80211 raw frame length 272 | * @return 273 | @verbatim 274 | = 0, send success. 275 | = -1, send failure. 276 | = -2, unsupported. 277 | @endverbatim 278 | * @see None. 279 | * @note awss use this API send raw frame in wifi monitor mode & station mode 280 | */ 281 | int platform_wifi_send_80211_raw_frame(_IN_ enum platform_awss_frame_type type, 282 | _IN_ uint8_t *buffer, _IN_ int len) 283 | { 284 | ALINK_PARAM_CHECK(buffer); 285 | 286 | extern esp_err_t esp_wifi_80211_tx(wifi_interface_t ifx, const void *buffer, int len); 287 | int ret = esp_wifi_80211_tx(ESP_IF_WIFI_STA, buffer, len); 288 | ALINK_ERROR_CHECK(ret != ALINK_OK, ALINK_ERR, "esp_wifi_80211_tx, ret: 0x%x", ret); 289 | 290 | return ALINK_OK; 291 | } 292 | 293 | /** 294 | * @brief enable/disable filter specific management frame in wifi station mode 295 | * 296 | * @param[in] filter_mask @n see mask macro in enum platform_awss_frame_type, 297 | * currently only FRAME_PROBE_REQ_MASK & FRAME_BEACON_MASK is used 298 | * @param[in] vendor_oui @n oui can be used for precise frame match, optional 299 | * @param[in] callback @n see platform_wifi_mgnt_frame_cb_t, passing 80211 300 | * frame or ie to callback. when callback is NULL 301 | * disable sniffer feature, otherwise enable it. 302 | * @return 303 | @verbatim 304 | = 0, success 305 | = -1, fail 306 | = -2, unsupported. 307 | @endverbatim 308 | * @see None. 309 | * @note awss use this API to filter specific mgnt frame in wifi station mode 310 | */ 311 | typedef void (*wifi_sta_rx_probe_req_t)(const uint8_t *frame, int len, int rssi); 312 | extern esp_err_t esp_wifi_set_sta_rx_probe_req(wifi_sta_rx_probe_req_t cb); 313 | 314 | static platform_wifi_mgnt_frame_cb_t g_callback = NULL; 315 | static uint8_t g_vendor_oui[3] = {0}; 316 | 317 | static void wifi_sta_rx_probe_req(const uint8_t *frame, int len, int rssi) 318 | { 319 | vendor_ie_data_t *alink_ie_info = (vendor_ie_data_t *)(frame + 60); 320 | 321 | if (alink_ie_info->element_id == WIFI_VENDOR_IE_ELEMENT_ID && alink_ie_info->length != 67 322 | && !memcmp(alink_ie_info->vendor_oui, g_vendor_oui, 3)) { 323 | 324 | if (alink_ie_info->vendor_oui_type == 171) { 325 | ALINK_LOGV("frame is no support, alink_ie_info->type: %d", alink_ie_info->vendor_oui_type); 326 | return; 327 | } 328 | 329 | g_callback((uint8_t *)alink_ie_info, alink_ie_info->length + 2, rssi, 1); 330 | } 331 | } 332 | 333 | int platform_wifi_enable_mgnt_frame_filter(_IN_ uint32_t filter_mask, 334 | _IN_OPT_ uint8_t vendor_oui[3], _IN_ 335 | platform_wifi_mgnt_frame_cb_t callback) 336 | { 337 | ALINK_PARAM_CHECK(vendor_oui); 338 | ALINK_PARAM_CHECK(callback); 339 | ALINK_ERROR_CHECK(filter_mask != (FRAME_PROBE_REQ_MASK | FRAME_BEACON_MASK), 340 | -2, "frame is no support, frame: 0x%x", filter_mask); 341 | 342 | alink_err_t ret = 0; 343 | g_callback = callback; 344 | 345 | memcpy(g_vendor_oui, vendor_oui, sizeof(g_vendor_oui)); 346 | 347 | ret = esp_wifi_set_sta_rx_probe_req(wifi_sta_rx_probe_req); 348 | ALINK_ERROR_CHECK(ret != ALINK_OK, ALINK_ERR, "esp_wifi_set_sta_rx_probe_req, ret: %d", ret); 349 | 350 | return ALINK_OK; 351 | } 352 | 353 | /** 354 | * @brief launch a wifi scan operation 355 | * 356 | * @param[in] cb @n pass ssid info(scan result) to this callback one by one 357 | * @return 0 for wifi scan is done, otherwise return -1 358 | * @see None. 359 | * @note 360 | * This API should NOT exit before the invoking for cb is finished. 361 | * This rule is something like the following : 362 | * platform_wifi_scan() is invoked... 363 | * ... 364 | * for (ap = first_ap; ap <= last_ap; ap = next_ap){ 365 | * cb(ap) 366 | * } 367 | * ... 368 | * platform_wifi_scan() exit... 369 | */ 370 | int platform_wifi_scan(platform_wifi_scan_result_cb_t cb) 371 | { 372 | uint16_t wifi_ap_num = 0; 373 | wifi_ap_record_t *ap_info = NULL; 374 | wifi_scan_config_t scan_config; 375 | 376 | memset(&scan_config, 0, sizeof(scan_config)); 377 | ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, true)); 378 | ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&wifi_ap_num)); 379 | 380 | ALINK_LOGI("ap number: %d", wifi_ap_num); 381 | ap_info = (wifi_ap_record_t *)alink_malloc(sizeof(wifi_ap_record_t) * wifi_ap_num); 382 | ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&wifi_ap_num, ap_info)); 383 | 384 | for (int i = 0; i < wifi_ap_num; ++i) { 385 | cb((char *)ap_info[i].ssid, (uint8_t *)ap_info[i].bssid, ap_info[i].authmode, AWSS_ENC_TYPE_INVALID, 386 | ap_info[i].primary, ap_info[i].rssi, 1); 387 | } 388 | 389 | ESP_ERROR_CHECK(esp_wifi_scan_stop()); 390 | 391 | alink_free(ap_info); 392 | return ALINK_OK; 393 | } 394 | 395 | /** 396 | * @brief initialize AES struct. 397 | * 398 | * @param[in] key: 399 | * @param[in] iv: 400 | * @param[in] dir: AES_ENCRYPTION or AES_DECRYPTION 401 | * @return AES128_t 402 | */ 403 | #include "mbedtls/aes.h" 404 | #define AES_BLOCK_SIZE 16 405 | 406 | typedef struct { 407 | mbedtls_aes_context ctx; 408 | uint8_t iv[16]; 409 | } platform_aes_t; 410 | 411 | p_aes128_t platform_aes128_init( 412 | _IN_ const uint8_t *key, 413 | _IN_ const uint8_t *iv, 414 | _IN_ AES_DIR_t dir) 415 | { 416 | ALINK_ASSERT(key); 417 | ALINK_ASSERT(iv); 418 | 419 | alink_err_t ret = 0; 420 | platform_aes_t *p_aes128 = NULL; 421 | p_aes128 = (platform_aes_t *)alink_calloc(1, sizeof(platform_aes_t)); 422 | ALINK_ERROR_CHECK(!p_aes128, NULL, "calloc"); 423 | 424 | mbedtls_aes_init(&p_aes128->ctx); 425 | 426 | if (dir == PLATFORM_AES_ENCRYPTION) { 427 | ret = mbedtls_aes_setkey_enc(&p_aes128->ctx, key, 128); 428 | } else { 429 | ret = mbedtls_aes_setkey_dec(&p_aes128->ctx, key, 128); 430 | } 431 | 432 | if (ret != ALINK_OK) { 433 | alink_free(p_aes128); 434 | } 435 | 436 | ALINK_ERROR_CHECK(ret != ALINK_OK, NULL, "mbedtls_aes_setkey_enc"); 437 | 438 | memcpy(p_aes128->iv, iv, 16); 439 | return (p_aes128_t *)p_aes128; 440 | } 441 | 442 | /** 443 | * @brief release AES struct. 444 | * 445 | * @param[in] aes: 446 | * @return 447 | @verbatim 448 | = 0: succeeded 449 | = -1: failed 450 | @endverbatim 451 | * @see None. 452 | * @note None. 453 | */ 454 | int platform_aes128_destroy(_IN_ p_aes128_t aes) 455 | { 456 | ALINK_PARAM_CHECK(aes); 457 | 458 | mbedtls_aes_free(&((platform_aes_t *)aes)->ctx); 459 | alink_free(aes); 460 | 461 | return ALINK_OK; 462 | } 463 | 464 | /** 465 | * @brief encrypt data with aes (cbc/128bit key). 466 | * 467 | * @param[in] aes: AES handler 468 | * @param[in] src: plain data 469 | * @param[in] blockNum: plain data number of 16 bytes size 470 | * @param[out] dst: cipher data 471 | * @return 472 | @verbatim 473 | = 0: succeeded 474 | = -1: failed 475 | @endverbatim 476 | * @see None. 477 | * @note None. 478 | */ 479 | int platform_aes128_cbc_encrypt( 480 | _IN_ p_aes128_t aes, 481 | _IN_ const void *src, 482 | _IN_ size_t blockNum, 483 | _OUT_ void *dst) 484 | { 485 | ALINK_PARAM_CHECK(aes); 486 | ALINK_PARAM_CHECK(src); 487 | ALINK_PARAM_CHECK(dst); 488 | 489 | alink_err_t ret = 0; 490 | platform_aes_t *p_aes128 = (platform_aes_t *)aes; 491 | 492 | for (int i = 0; i < blockNum; ++i) { 493 | ret = mbedtls_aes_crypt_cbc(&p_aes128->ctx, MBEDTLS_AES_ENCRYPT, AES_BLOCK_SIZE, 494 | p_aes128->iv, src, dst); 495 | src += 16; 496 | dst += 16; 497 | } 498 | 499 | ALINK_ERROR_CHECK(ret != ALINK_OK, ALINK_ERR, "mbedtls_aes_crypt_cbc, ret: %d", ret); 500 | return ALINK_OK; 501 | } 502 | 503 | /** 504 | * @brief decrypt data with aes (cbc/128bit key). 505 | * 506 | * @param[in] aes: AES handler 507 | * @param[in] src: cipher data 508 | * @param[in] blockNum: plain data number of 16 bytes size 509 | * @param[out] dst: plain data 510 | * @return 511 | @verbatim 512 | = 0: succeeded 513 | = -1: failed 514 | @endverbatim 515 | * @see None. 516 | * @note None. 517 | */ 518 | int platform_aes128_cbc_decrypt( 519 | _IN_ p_aes128_t aes, 520 | _IN_ const void *src, 521 | _IN_ size_t blockNum, 522 | _OUT_ void *dst) 523 | { 524 | ALINK_PARAM_CHECK(aes); 525 | ALINK_PARAM_CHECK(src); 526 | ALINK_PARAM_CHECK(dst); 527 | 528 | alink_err_t ret = 0; 529 | platform_aes_t *p_aes128 = (platform_aes_t *)aes; 530 | 531 | for (int i = 0; i < blockNum; ++i) { 532 | ret = mbedtls_aes_crypt_cbc(&p_aes128->ctx, MBEDTLS_AES_DECRYPT, AES_BLOCK_SIZE, 533 | p_aes128->iv, src, dst); 534 | src += 16; 535 | dst += 16; 536 | } 537 | 538 | ALINK_ERROR_CHECK(ret != ALINK_OK, ALINK_ERR, 539 | "mbedtls_aes_crypt_cbc, ret: %d, blockNum: %d", ret, blockNum); 540 | return ALINK_OK; 541 | } 542 | 543 | /** 544 | * @brief get the information of the connected AP. 545 | * 546 | * @param[out] ssid: array to store ap ssid. It will be null if ssid is not required. 547 | * @param[out] passwd: array to store ap password. It will be null if ap password is not required. 548 | * @param[out] bssid: array to store ap bssid. It will be null if bssid is not required. 549 | * @return 550 | @verbatim 551 | = 0: succeeded 552 | = -1: failed 553 | @endverbatim 554 | * @see None. 555 | * @note None. 556 | */ 557 | 558 | int platform_wifi_get_ap_info( 559 | _OUT_ char ssid[PLATFORM_MAX_SSID_LEN], 560 | _OUT_ char passwd[PLATFORM_MAX_PASSWD_LEN], 561 | _OUT_ uint8_t bssid[ETH_ALEN]) 562 | { 563 | alink_err_t ret = 0; 564 | wifi_ap_record_t ap_info; 565 | wifi_config_t wifi_config; 566 | 567 | memset(&ap_info, 0, sizeof(wifi_ap_record_t)); 568 | ESP_ERROR_CHECK(esp_wifi_sta_get_ap_info(&ap_info)); 569 | 570 | if (ssid) { 571 | memcpy(ssid, ap_info.ssid, PLATFORM_MAX_SSID_LEN); 572 | } 573 | 574 | if (bssid) { 575 | memcpy(bssid, ap_info.bssid, ETH_ALEN); 576 | } 577 | 578 | if (!passwd) { 579 | return ALINK_OK; 580 | } 581 | 582 | ret = esp_info_load(NVS_KEY_WIFI_CONFIG, &wifi_config, sizeof(wifi_config_t)); 583 | 584 | if (ret > 0 && !memcmp(ap_info.ssid, wifi_config.sta.ssid, strlen((char *)ap_info.ssid))) { 585 | memcpy(passwd, wifi_config.sta.password, PLATFORM_MAX_PASSWD_LEN); 586 | ALINK_LOGV("wifi passwd: %s", passwd); 587 | } else { 588 | memset(passwd, 0, PLATFORM_MAX_PASSWD_LEN); 589 | } 590 | 591 | return ALINK_OK; 592 | } 593 | -------------------------------------------------------------------------------- /adaptation/include/alink_platform.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. 3 | * 4 | * Alibaba Group retains all right, title and interest (including all 5 | * intellectual property rights) in and to this computer program, which is 6 | * protected by applicable intellectual property laws. Unless you have 7 | * obtained a separate written license from Alibaba Group., you are not 8 | * authorized to utilize all or a part of this computer program for any 9 | * purpose (including reproduction, distribution, modification, and 10 | * compilation into object code), and you must immediately destroy or 11 | * return to Alibaba Group all copies of this computer program. If you 12 | * are licensed by Alibaba Group, your rights to utilize this computer 13 | * program are limited by the terms of that license. To obtain a license, 14 | * please contact Alibaba Group. 15 | * 16 | * This computer program contains trade secrets owned by Alibaba Group. 17 | * and, unless unauthorized by Alibaba Group in writing, you agree to 18 | * maintain the confidentiality of this computer program and related 19 | * information and to not disclose this computer program and related 20 | * information to any other person or entity. 21 | * 22 | * THIS COMPUTER PROGRAM IS PROVIDED AS IS WITHOUT ANY WARRANTIES, AND 23 | * Alibaba Group EXPRESSLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, 24 | * INCLUDING THE WARRANTIES OF MERCHANTIBILITY, FITNESS FOR A PARTICULAR 25 | * PURPOSE, TITLE, AND NONINFRINGEMENT. 26 | */ 27 | #ifndef __ALINK_PLATFORM_H__ 28 | #define __ALINK_PLATFORM_H__ 29 | 30 | #ifdef __cplusplus 31 | extern "C" 32 | { 33 | #endif 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | /* mask this line, if stdint.h is not defined */ 40 | #define USE_STDINT_H 41 | 42 | #ifdef USE_STDINT_H 43 | #include 44 | #else 45 | typedef signed char int8_t; 46 | typedef signed short int16_t; 47 | typedef signed int int32_t; 48 | typedef unsigned char uint8_t; 49 | typedef unsigned short uint16_t; 50 | typedef unsigned int uint32_t; 51 | typedef unsigned long long uint64_t; 52 | #endif 53 | 54 | /** @defgroup group_platform platform 55 | * @{ 56 | */ 57 | 58 | 59 | #define _IN_ /**< indicate that this is a input parameter. */ 60 | #define _OUT_ /**< indicate that this is a output parameter. */ 61 | #define _INOUT_ /**< indicate that this is a io parameter. */ 62 | #define _IN_OPT_ /**< indicate that this is a optional input parameter. */ 63 | #define _OUT_OPT_ /**< indicate that this is a optional output parameter. */ 64 | #define _INOUT_OPT_ /**< indicate that this is a optional io parameter. */ 65 | 66 | 67 | #define PLATFORM_SOCKET_MAXNUMS (10) 68 | #define PLATFORM_WAIT_INFINITE (~0) 69 | #define PLATFORM_INVALID_FD ((void *)-1) 70 | 71 | #define STR_SHORT_LEN (32) 72 | #define STR_LONG_LEN (128) 73 | 74 | #ifndef ETH_ALEN 75 | #define ETH_ALEN (6) 76 | #endif 77 | 78 | /* ssid: 32 octets at most, include the NULL-terminated */ 79 | #define PLATFORM_MAX_SSID_LEN (32 + 1) 80 | /* password: 8-63 ascii */ 81 | #define PLATFORM_MAX_PASSWD_LEN (64 + 1) 82 | 83 | /*********************************** thread interface ***********************************/ 84 | 85 | /** @defgroup group_platform_thread thread 86 | * @{ 87 | */ 88 | 89 | /** 90 | * @brief create a thread. 91 | * 92 | * @param[out] thread @n The new thread handle. 93 | * @param[in] name @n thread name. 94 | * @param[in] start_routine @n A pointer to the application-defined function to be executed by the thread. 95 | This pointer represents the starting address of the thread. 96 | * @param[in] arg @n A pointer to a variable to be passed to the start_routine. 97 | * @param[in] stack @n A pointer to stack buffer malloced by caller, if platform used this buffer, set stack_used to non-zero value, otherwise set it to 0. 98 | * @param[in] stack_size @n The initial size of the stack, in bytes. see platform_get_thread_stack_size(). 99 | * @param[out] stack_used @n if platform used stack buffer, set stack_used to 1, otherwise set it to 0. 100 | * @return 101 | @verbatim 102 | = 0: on success. 103 | = -1: error occur. 104 | @endverbatim 105 | * @see None. 106 | * @note None. 107 | */ 108 | int platform_thread_create( 109 | _OUT_ void **thread, 110 | _IN_ const char *name, 111 | _IN_ void *(*start_routine)(void *), 112 | _IN_ void *arg, 113 | _IN_ void *stack, 114 | _IN_ uint32_t stack_size, 115 | _OUT_ int *stack_used); 116 | 117 | /** 118 | * @brief exit the thread itself. 119 | * 120 | * @param[in] thread: itself thread handle. 121 | * @return None. 122 | * @see None. 123 | * @note None. 124 | */ 125 | void platform_thread_exit(_IN_ void *thread); 126 | 127 | /** 128 | * @brief get thread stack size in this platform. 129 | * 130 | * @param[in] thread_name: specify the thread by uniform thread name. 131 | * @return thread name. 132 | * @see None. 133 | * @note there are 6 threads included: 134 | * 1) wsf_receive_worker; 135 | * 2) wsf_send_worker; 136 | * 3) wsf_callback_worker; 137 | * 4) fota_thread; 138 | * 5) alcs_thread; 139 | */ 140 | int platform_thread_get_stack_size(_IN_ const char *thread_name); 141 | 142 | /** 143 | * @brief sleep thread itself. 144 | * 145 | * @param[in] ms @n the time interval for which execution is to be suspended, in milliseconds. 146 | * @return None. 147 | * @see None. 148 | * @note None. 149 | */ 150 | void platform_msleep(_IN_ uint32_t ms); 151 | 152 | 153 | /** @} */ //end of platform_thread 154 | 155 | 156 | /*********************************** mutex interface ***********************************/ 157 | 158 | /** @defgroup group_platform_mutex mutex 159 | * @{ 160 | */ 161 | 162 | /** 163 | * @brief Create a mutex. 164 | * 165 | * @return Mutex handle. 166 | * @see None. 167 | * @note None. 168 | */ 169 | void *platform_mutex_init(void); 170 | 171 | 172 | 173 | /** 174 | * @brief Destroy the specified mutex object, it will free related resource. 175 | * 176 | * @param[in] mutex @n The specified mutex. 177 | * @return None. 178 | * @see None. 179 | * @note None. 180 | */ 181 | void platform_mutex_destroy(_IN_ void *mutex); 182 | 183 | 184 | 185 | /** 186 | * @brief Waits until the specified mutex is in the signaled state. 187 | * 188 | * @param[in] mutex @n the specified mutex. 189 | * @return None. 190 | * @see None. 191 | * @note None. 192 | */ 193 | void platform_mutex_lock(_IN_ void *mutex); 194 | 195 | 196 | 197 | /** 198 | * @brief Releases ownership of the specified mutex object.. 199 | * 200 | * @param[in] mutex @n the specified mutex. 201 | * @return None. 202 | * @see None. 203 | * @note None. 204 | */ 205 | void platform_mutex_unlock(_IN_ void *mutex); 206 | 207 | 208 | /** @} */ //end of platform_mutex 209 | 210 | 211 | /********************************* semaphore interface *********************************/ 212 | 213 | 214 | /** @defgroup group_platform_semaphore semaphore 215 | * @{ 216 | */ 217 | 218 | /** 219 | * @brief Create a semaphore. 220 | * 221 | * @return semaphore handle. 222 | * @see None. 223 | * @note The recommended value of maximum count of the semaphore is 255. 224 | */ 225 | void *platform_semaphore_init(void); 226 | 227 | 228 | 229 | /** 230 | * @brief Destroy the specified semaphore object, it will free related resource. 231 | * 232 | * @param[in] sem @n the specified sem. 233 | * @return None. 234 | * @see None. 235 | * @note None. 236 | */ 237 | void platform_semaphore_destroy(_IN_ void *sem); 238 | 239 | 240 | 241 | /** 242 | * @brief Wait until the specified mutex is in the signaled state or the time-out interval elapses. 243 | * 244 | * @param[in] sem @n the specified semaphore. 245 | * @param[in] timeout_ms @n timeout interval in millisecond. 246 | If timeout_ms is PLATFORM_WAIT_INFINITE, the function will return only when the semaphore is signaled. 247 | * @return 248 | @verbatim 249 | = 0: The state of the specified object is signaled. 250 | = -1: The time-out interval elapsed, and the object's state is nonsignaled. 251 | @endverbatim 252 | * @see None. 253 | * @note None. 254 | */ 255 | int platform_semaphore_wait(_IN_ void *sem, _IN_ uint32_t timeout_ms); 256 | 257 | 258 | 259 | /** 260 | * @brief Increases the count of the specified semaphore object by 1. 261 | * 262 | * @param[in] sem @n the specified semaphore. 263 | * @return None. 264 | * @see None. 265 | * @note None. 266 | */ 267 | void platform_semaphore_post(_IN_ void *sem); 268 | 269 | 270 | 271 | 272 | /** @} */ //end of platform_semaphore 273 | 274 | /********************************** memory interface **********************************/ 275 | 276 | 277 | /** @defgroup group_platform_memory_manage memory 278 | * @{ 279 | */ 280 | 281 | 282 | /** 283 | * @brief Allocates a block of size bytes of memory, returning a pointer to the beginning of the block. 284 | * 285 | * @param[in] size @n specify block size in bytes. 286 | * @return A pointer to the beginning of the block. 287 | * @see None. 288 | * @note Block value is indeterminate. 289 | */ 290 | void *platform_malloc(_IN_ uint32_t size); 291 | 292 | 293 | /** 294 | * @brief Deallocate memory block 295 | * 296 | * @param[in] ptr @n Pointer to a memory block previously allocated with platform_malloc. 297 | * @return None. 298 | * @see None. 299 | * @note None. 300 | */ 301 | void platform_free(_IN_ void *ptr); 302 | 303 | 304 | /** @} */ //end of platform_memory_manage 305 | 306 | 307 | /********************************** network interface **********************************/ 308 | 309 | /** @defgroup group_network network 310 | * @{ 311 | */ 312 | 313 | /** 314 | * @brief this is a network address structure, including host(ip or host name) and port. 315 | */ 316 | typedef struct { 317 | char *host; /**< host ip(dotted-decimal notation) or host name(string) */ 318 | uint16_t port; /**< udp port or tcp port */ 319 | } platform_netaddr_t, *pplatform_netaddr_t; 320 | 321 | 322 | 323 | /** 324 | * @brief Create a udp server with the specified port. 325 | * 326 | * @param[in] port @n The specified udp sever listen port. 327 | * @return Server handle. 328 | @verbatim 329 | = NULL: fail. 330 | != NULL: success. 331 | @endverbatim 332 | * @see None. 333 | * @note It is recommended to add handle value by 1, if 0(NULL) is a valid handle value in your platform. 334 | */ 335 | void *platform_udp_server_create(_IN_ uint16_t port); 336 | 337 | 338 | 339 | /** 340 | * @brief Create a udp client. 341 | * 342 | * @param None 343 | * @return Client handle. 344 | @verbatim 345 | = NULL: fail. 346 | != NULL: success. 347 | @endverbatim 348 | * @see None. 349 | * @note None. 350 | */ 351 | void *platform_udp_client_create(void); 352 | 353 | 354 | 355 | /** 356 | * @brief Add this host to the specified udp multicast group. 357 | * 358 | * @param[in] netaddr @n Specify multicast address. 359 | * @return Multicast handle. 360 | @verbatim 361 | = NULL: fail. 362 | != NULL: success. 363 | @endverbatim 364 | * @see None. 365 | * @note None. 366 | * 367 | */ 368 | void *platform_udp_multicast_server_create(platform_netaddr_t *netaddr); 369 | 370 | /** 371 | * @brief Closes an existing udp connection. 372 | * 373 | * @param[in] handle @n the specified connection. 374 | * @return None. 375 | * @see None. 376 | * @note None. 377 | */ 378 | void platform_udp_close(void *handle); 379 | 380 | 381 | 382 | /** 383 | * @brief Sends data to a specific destination. 384 | * 385 | * @param[in] handle @n A descriptor identifying a connection. 386 | * @param[in] buffer @n A pointer to a buffer containing the data to be transmitted. 387 | * @param[in] length @n The length, in bytes, of the data pointed to by the buffer parameter. 388 | * @param[in] netaddr @n A pointer to a netaddr structure that contains the address of the target. 389 | * 390 | * @return 391 | @verbatim 392 | > 0: the total number of bytes sent, which can be less than the number indicated by length. 393 | = -1: error occur. 394 | @endverbatim 395 | * @see None. 396 | * @note blocking API. 397 | */ 398 | int platform_udp_sendto( 399 | _IN_ void *handle, 400 | _IN_ const char *buffer, 401 | _IN_ uint32_t length, 402 | _IN_ platform_netaddr_t *netaddr); 403 | 404 | 405 | /** 406 | * @brief Receives data from a udp connection. 407 | * 408 | * @param[in] handle @n A descriptor identifying a connection. 409 | * @param[out] buffer @n A pointer to a buffer to receive incoming data. 410 | * @param[in] length @n The length, in bytes, of the data pointed to by the buffer parameter. 411 | * @param[out] netaddr @n A pointer to a netaddr structure that contains the address of the source. 412 | * @return 413 | @verbatim 414 | > 0: The total number of bytes received, which can be less than the number indicated by length. 415 | < 0: Error occur. 416 | @endverbatim 417 | * 418 | * @see None. 419 | * @note blocking API. 420 | */ 421 | int platform_udp_recvfrom( 422 | _IN_ void *handle, 423 | _OUT_ char *buffer, 424 | _IN_ uint32_t length, 425 | _OUT_OPT_ platform_netaddr_t *netaddr); 426 | 427 | 428 | 429 | /** 430 | * @brief Create a tcp server with the specified port. 431 | * 432 | * @param[in] port @n The specified tcp sever listen port. 433 | * @return Server handle. 434 | @verbatim 435 | = NULL: fail. 436 | != NULL: success. 437 | @endverbatim 438 | * @see None. 439 | * @note None. 440 | */ 441 | void *platform_tcp_server_create(_IN_ uint16_t port); 442 | 443 | 444 | 445 | /** 446 | * @brief Permits an incoming connection attempt on a tcp server. 447 | * 448 | * @param[in] server @n The specified tcp sever. 449 | * @return Connection handle. 450 | * @see None. 451 | * @note None. 452 | */ 453 | void *platform_tcp_server_accept(_IN_ void *server); 454 | 455 | 456 | 457 | /** 458 | * @brief Establish a connection. 459 | * 460 | * @param[in] netaddr @n The destination address. 461 | * @return Connection handle 462 | @verbatim 463 | = NULL: fail. 464 | != NULL: success. 465 | @endverbatim 466 | * @see None. 467 | * @note the func will block until tcp connect success or fail. 468 | */ 469 | void *platform_tcp_client_connect(_IN_ platform_netaddr_t *netaddr); 470 | 471 | 472 | 473 | 474 | /** 475 | * @brief Sends data on a connection. 476 | * 477 | * @param[in] handle @n A descriptor identifying a connection. 478 | * @param[in] buffer @n A pointer to a buffer containing the data to be transmitted. 479 | * @param[in] length @n The length, in bytes, of the data pointed to by the buffer parameter. 480 | * @return 481 | @verbatim 482 | > 0: The total number of bytes sent, which can be less than the number indicated by length. 483 | < 0: Error occur. 484 | @endverbatim 485 | * @see None. 486 | * @note Blocking API. 487 | */ 488 | int platform_tcp_send(_IN_ void *handle, _IN_ const char *buffer, _IN_ uint32_t length); 489 | 490 | 491 | 492 | /** 493 | * @brief Receives data from a tcp connection. 494 | * 495 | * @param[in] handle @n A descriptor identifying a connection. 496 | * @param[out] buffer @n A pointer to a buffer to receive incoming data. 497 | * @param[in] length @n The length, in bytes, of the data pointed to by the buffer parameter. 498 | * @return 499 | @verbatim 500 | > 0: The total number of bytes received, which can be less than the number indicated by length. 501 | < 0: Error occur. 502 | @endverbatim 503 | * 504 | * @see None. 505 | * @note Blocking API. 506 | */ 507 | int platform_tcp_recv(_IN_ void *handle, _OUT_ char *buffer, _IN_ uint32_t length); 508 | 509 | 510 | 511 | /** 512 | * @brief Closes an existing tcp connection. 513 | * 514 | * @param[in] handle @n the specified connection. 515 | * @return None. 516 | * @see None. 517 | * @note None. 518 | */ 519 | void platform_tcp_close(_IN_ void *handle); 520 | 521 | 522 | 523 | 524 | /** 525 | * @brief Determines the status of one or more connection, waiting if necessary, to perform synchronous I/O. 526 | * 527 | * @param[in,out] handle_read @n 528 | @verbatim 529 | [in]: An optional pointer to a set of connection to be checked for readability. 530 | handle_read[n] > 0, care the connection, and the value is handle of the careful connection. 531 | handle_read[n] = NULL, uncare. 532 | [out]: handle_read[n] = NULL, the connection unreadable; != NULL, the connection readable. 533 | @endverbatim 534 | * @param[in,out] handle_write: @n 535 | @verbatim 536 | [in]: An optional pointer to a set of connection to be checked for writability. 537 | handle_write[n] > 0, care the connection, and the value is handle of the careful connection. 538 | handle_write[n] = NULL, uncare. 539 | [out]: handle_write[n] = NULL, the connection unwritable; != NULL, the connection wirteable. 540 | @endverbatim 541 | * @param[in] timeout_ms: @n Timeout interval in millisecond. 542 | * @return 543 | @verbatim 544 | = 0: The timeout interval elapsed. 545 | > 0: The total number of connection handles that are ready. 546 | < 0: A connection error occur. 547 | @endverbatim 548 | * @see None. 549 | * @note None. 550 | */ 551 | int platform_select( 552 | _INOUT_OPT_ void *read_fds[PLATFORM_SOCKET_MAXNUMS], 553 | _INOUT_OPT_ void *write_fds[PLATFORM_SOCKET_MAXNUMS], 554 | _IN_ int timeout_ms); 555 | 556 | 557 | /** @} */ //end of platform_network 558 | 559 | 560 | 561 | /************************************ SSL interface ************************************/ 562 | 563 | /** @defgroup group_platform_ssl ssl 564 | * @{ 565 | */ 566 | 567 | /** 568 | * @brief Establish a ssl connection. 569 | * 570 | * @param[in] tcp_fd @n The network connection handle. 571 | * @param[in] server_cert @n Specify the sever certificate which is PEM format, and 572 | * both root cert(CA) and user cert should be supported 573 | * @param[in] server_cert_len @n Length of sever certificate, in bytes. 574 | * @return SSL handle. 575 | * @see None. 576 | * @note None. 577 | */ 578 | void *platform_ssl_connect(_IN_ void *tcp_fd, _IN_ const char *server_cert, _IN_ int server_cert_len); 579 | 580 | 581 | 582 | /** 583 | * @brief Sends data on a ssl connection. 584 | * 585 | * @param[in] ssl @n A descriptor identifying a ssl connection. 586 | * @param[in] buffer @n A pointer to a buffer containing the data to be transmitted. 587 | * @param[in] length @n The length, in bytes, of the data pointed to by the buffer parameter. 588 | * @return 589 | @verbatim 590 | > 0: The total number of bytes sent, which can be less than the number indicated by length. 591 | < 0: Error occur. 592 | @endverbatim 593 | * @see None. 594 | * @note Blocking API. 595 | */ 596 | int platform_ssl_send(_IN_ void *ssl, _IN_ const char *buffer, _IN_ int length); 597 | 598 | 599 | /** 600 | * @brief Receives data from a ssl connection. 601 | * 602 | * @param[in] ssl @n A descriptor identifying a ssl connection. 603 | * @param[out] buffer @n A pointer to a buffer to receive incoming data. 604 | * @param[in] length @n The length, in bytes, of the data pointed to by the buffer parameter. 605 | * @return 606 | @verbatim 607 | > 0: The total number of bytes received, which can be less than the number indicated by length. 608 | < 0: Error occur. 609 | @endverbatim 610 | * 611 | * @see None. 612 | * @note blocking API. 613 | */ 614 | int platform_ssl_recv(_IN_ void *ssl, _IN_ char *buffer, _IN_ int length); 615 | 616 | 617 | /** 618 | * @brief Closes an existing ssl connection. 619 | * 620 | * @param[in] ssl: @n the specified connection. 621 | * @return None. 622 | * @see None. 623 | * @note None. 624 | */ 625 | int platform_ssl_close(_IN_ void *ssl); 626 | 627 | 628 | /** @} */ //end of platform_ssl 629 | 630 | /********************************** system interface **********************************/ 631 | 632 | /** @defgroup group_platform_system system 633 | * @{ 634 | */ 635 | 636 | 637 | /** 638 | * @brief check system network is ready(get ip address) or not. 639 | * 640 | * @param None. 641 | * @return 0, net is not ready; 1, net is ready. 642 | * @see None. 643 | * @note None. 644 | */ 645 | int platform_sys_net_is_ready(void); 646 | 647 | 648 | 649 | /** 650 | * @brief reboot system immediately. 651 | * 652 | * @param None. 653 | * @return None. 654 | * @see None. 655 | * @note None. 656 | */ 657 | void platform_sys_reboot(void); 658 | 659 | 660 | 661 | /** 662 | * @brief Retrieves the number of milliseconds that have elapsed since the system was boot. 663 | * 664 | * @param None. 665 | * @return the number of milliseconds. 666 | * @see None. 667 | * @note None. 668 | */ 669 | uint32_t platform_get_time_ms(void); 670 | 671 | typedef struct { 672 | int tm_sec; /* seconds */ 673 | int tm_min; /* minutes */ 674 | int tm_hour; /* hours */ 675 | int tm_mday; /* day of the month */ 676 | int tm_mon; /* month */ 677 | int tm_year; /* year */ 678 | int tm_wday; /* day of the week */ 679 | int tm_yday; /* day in the year */ 680 | int tm_isdst; /* daylight saving time */ 681 | } os_time_struct; 682 | 683 | uint64_t platform_get_utc_time(_INOUT_ uint64_t *p_utc); 684 | 685 | os_time_struct *platform_local_time_r(const _IN_ uint64_t *p_utc, _OUT_ os_time_struct *p_result); 686 | 687 | /** 688 | * @brief get the available memroy size in bytes 689 | * 690 | * @param None. 691 | * @return free memory size in bytes 692 | * @see None. 693 | * @note None. 694 | */ 695 | int platform_get_free_memory_size(void); 696 | 697 | 698 | /** @} */ //end of platform_system 699 | 700 | /***************************** firmware upgrade interface *****************************/ 701 | 702 | /** @defgroup group_platform_ota ota 703 | * @{ 704 | */ 705 | 706 | 707 | /** 708 | * @brief initialize a firmware upgrade. 709 | * 710 | * @param None 711 | * @return None. 712 | * @see None. 713 | * @note None. 714 | */ 715 | void platform_flash_program_start(void); 716 | 717 | 718 | /** 719 | * @brief save firmware upgrade data to flash. 720 | * 721 | * @param[in] buffer: @n A pointer to a buffer to save data. 722 | * @param[in] length: @n The length, in bytes, of the data pointed to by the buffer parameter. 723 | * @return 0, Save success; -1, Save failure. 724 | * @see None. 725 | * @note None. 726 | */ 727 | int platform_flash_program_write_block(_IN_ char *buffer, _IN_ uint32_t length); 728 | 729 | 730 | /** 731 | * @brief indicate firmware upgrade data complete, and trigger data integrity checking, 732 | and then reboot the system. 733 | * 734 | * @param None. 735 | * @return 0: Success; -1: Failure. 736 | * @see None. 737 | * @note None. 738 | */ 739 | int platform_flash_program_stop(void); 740 | 741 | 742 | /** @} */ //end of platform_firmware_upgrade 743 | 744 | /************************************ io interface ************************************/ 745 | 746 | /** @defgroup group_platform_io io 747 | * @{ 748 | */ 749 | 750 | 751 | /** 752 | * @brief Writes formatted data to stream. 753 | * 754 | * @param[in] fmt: @n String that contains the text to be written, it can optionally contain embedded format specifiers 755 | that specifies how subsequent arguments are converted for output. 756 | * @param[in] ...: @n the variable argument list, for formatted and inserted in the resulting string replacing their respective specifiers. 757 | * @return None. 758 | * @see None. 759 | * @note None. 760 | */ 761 | void platform_printf(_IN_ const char *fmt, ...); 762 | 763 | 764 | /** @} */ //end of group_io 765 | 766 | /********************************** config interface **********************************/ 767 | 768 | /** @defgroup group_platform_config config 769 | * @{ 770 | */ 771 | 772 | /** 773 | * @brief Get flash(R/W) storage directory path. 774 | * alink SDK use this path to store data profile 775 | * 776 | * @param None. 777 | * @return return storage path. 778 | * @see None. 779 | * @note None. 780 | */ 781 | const char *platform_get_storage_directory(void); 782 | 783 | #define PLATFORM_CONFIG_SIZE (2048) 784 | 785 | /** 786 | * @brief Read configure data from the start of configure zone. 787 | * 788 | * @param[in] buffer @n A pointer to a buffer to receive incoming data. 789 | * @param[in] length @n Specify read length, in bytes. 790 | * @return 791 | @verbatim 792 | = 0, read success. 793 | = -1, read failure. 794 | @endverbatim 795 | * @see None. 796 | * @note None. 797 | */ 798 | int platform_config_read(char *buffer, int length); 799 | 800 | 801 | /** 802 | * @brief Write configure data from the start of configure zone. 803 | * 804 | * @param[in] buffer @n A pointer to a buffer to receive incoming data. 805 | * @param[in] length @n Specify write length, in bytes. 806 | * @return 807 | @verbatim 808 | = 0, write success. 809 | = -1, write failure. 810 | @endverbatim 811 | * @see None. 812 | * @note None. 813 | */ 814 | int platform_config_write(const char *buffer, int length); 815 | 816 | 817 | /** @} */ //end of platform_config 818 | 819 | /******************************** wifi module interface ********************************/ 820 | 821 | /** @defgroup group_platform_wifi_module wifi related 822 | * @{ 823 | */ 824 | 825 | /** 826 | * @brief Get model of the wifi module. 827 | * 828 | * @param[in] model_str @n Buffer for using to store model string. 829 | * @return A pointer to the start address of model_str. 830 | * @see None. 831 | * @note None. 832 | */ 833 | char *platform_get_module_name(char name_str[STR_SHORT_LEN]); 834 | 835 | 836 | /** 837 | * @brief Get WIFI received signal strength indication(rssi). 838 | * 839 | * @param None. 840 | * @return The level number, in dBm. 841 | * @see None. 842 | * @note None. 843 | */ 844 | int platform_wifi_get_rssi_dbm(void); 845 | 846 | /** 847 | * @brief wifi module enter power saving mode for a period 848 | * 849 | * @param[in] timeout_ms @n during this period, wifi module enter power saving 850 | * mode 851 | * @return 0 for success, -1 otherwise 852 | * @see None. 853 | * @note sample code 854 | * int platform_wifi_low_power(int timeout_ms) 855 | * { 856 | * wifi_enter_power_saving_mode(); 857 | * msleep(timeout_ms); 858 | * wifi_exit_power_saving_mode(); 859 | * 860 | * return 0; 861 | * } 862 | */ 863 | int platform_wifi_low_power(int timeout_ms); 864 | 865 | /** 866 | * @brief Get WIFI received signal strength indication(rssi). 867 | * 868 | * @param None. 869 | * @return The level number, in dBm. 870 | * @see None. 871 | * @note None. 872 | */ 873 | int platform_rf433_get_rssi_dbm(void); 874 | 875 | 876 | #define PLATFORM_MAC_LEN (17 + 1) 877 | /** 878 | * @brief Get WIFI MAC string, format should be XX:XX:XX:XX:XX:XX 879 | * 880 | * @param[out] mac_str @n Buffer for using to store wifi MAC string. 881 | * @return A pointer to the start address of mac_str. 882 | * @see None. 883 | * @note None. 884 | */ 885 | char *platform_wifi_get_mac(char mac_str[PLATFORM_MAC_LEN]); 886 | 887 | 888 | #define PLATFORM_IP_LEN (15 + 1) 889 | /** 890 | * @brief Get WIFI IP string with format like: xx:xx:xx:xx:xx:xx, 891 | and return IP with binary form, in network byte order. 892 | * 893 | * @param[out] ip_str @n Buffer for using to store IP string, in numbers-and-dots notation form. 894 | * @return IP with binary form, in network byte order. 895 | * @see None. 896 | * @note None. 897 | */ 898 | uint32_t platform_wifi_get_ip(char ip_str[PLATFORM_IP_LEN]); 899 | 900 | 901 | #define PLATFORM_CID_LEN (64 + 1) 902 | /** 903 | * @brief Get unique chip id string. 904 | * 905 | * @param[out] cid_str @n Buffer for using to store chip id string. 906 | * @return A pointer to the start address of cid_str. 907 | * @see None. 908 | * @note None. 909 | */ 910 | char *platform_get_chipid(char cid_str[PLATFORM_CID_LEN]); 911 | 912 | 913 | /** 914 | * @brief Get the os version of wifi module firmware. 915 | * 916 | * @param[in] version_str @n Buffer for using to store version string. 917 | * @return A pointer to the start address of version_str. 918 | * @see None. 919 | * @note None. 920 | */ 921 | char *platform_get_os_version(char version_str[STR_SHORT_LEN]); 922 | 923 | 924 | /** @} */ //end of platform_wifi_module 925 | 926 | 927 | /************************* awss(alink wireless setup service) interface ***************************/ 928 | 929 | /** @defgroup group_platform_awss alink wireless setup service(awss) 930 | * @{ 931 | */ 932 | 933 | 934 | /** 935 | * @brief Get timeout interval, in millisecond, of per awss. 936 | * 937 | * @param None. 938 | * @return The timeout interval. 939 | * @see None. 940 | * @note The recommended value is 60,000ms. 941 | */ 942 | int platform_awss_get_timeout_interval_ms(void); 943 | 944 | /** 945 | * @brief Get timeout interval in millisecond to connect the default SSID if awss timeout happens. 946 | * 947 | * @param None. 948 | * @return The timeout interval. 949 | * @see None. 950 | * @note The recommended value is 0ms, which mean forever. 951 | */ 952 | int platform_awss_get_connect_default_ssid_timeout_interval_ms(void); 953 | 954 | /** 955 | * @brief Get time length, in millisecond, of per channel scan. 956 | * 957 | * @param None. 958 | * @return The timeout interval. 959 | * @see None. 960 | * @note None. The recommended value is between 200ms and 400ms. 961 | */ 962 | int platform_awss_get_channelscan_interval_ms(void); 963 | 964 | 965 | /* link type */ 966 | enum AWSS_LINK_TYPE { 967 | /*< rtos platform choose this type */ 968 | AWSS_LINK_TYPE_NONE, 969 | 970 | /*< linux platform may choose the following type */ 971 | AWSS_LINK_TYPE_PRISM, 972 | AWSS_LINK_TYPE_80211_RADIO, 973 | AWSS_LINK_TYPE_80211_RADIO_AVS 974 | }; 975 | /** 976 | * @brief 80211 frame handler, passing 80211 frame to this func 977 | * 978 | * @param[in] buf @n 80211 frame buffer 979 | * @param[in] length @n 80211 frame buffer length 980 | * @param[in] link_type @n AWSS_LINK_TYPE_NONE for most rtos platform, 981 | * and for linux platform, do the following step to check 982 | * which header type the driver supported. 983 | @verbatim 984 | a) iwconfig wlan0 mode monitor #open monitor mode 985 | b) iwconfig wlan0 channel 6 #switch channel 6 986 | c) tcpdump -i wlan0 -s0 -w file.pacp #capture 80211 frame & save 987 | d) open file.pacp with wireshark or omnipeek 988 | check the link header type and fcs included or not 989 | @endverbatim 990 | * @param[in] with_fcs @n 80211 frame buffer include fcs(4 byte) or not 991 | */ 992 | typedef int (*platform_awss_recv_80211_frame_cb_t)(char *buf, int length, 993 | enum AWSS_LINK_TYPE link_type, int with_fcs); 994 | 995 | /** 996 | * @brief Set wifi running at monitor mode, 997 | and register a callback function which will be called when wifi receive a frame. 998 | * 999 | * @param[in] cb @n A function pointer, called back when wifi receive a frame. 1000 | * @return None. 1001 | * @see None. 1002 | * @note None. 1003 | */ 1004 | void platform_awss_open_monitor(platform_awss_recv_80211_frame_cb_t cb); 1005 | 1006 | 1007 | 1008 | /** 1009 | * @brief Close wifi monitor mode, and set running at station mode. 1010 | * 1011 | * @param None. 1012 | * @return None. 1013 | * @see None. 1014 | * @note None. 1015 | */ 1016 | void platform_awss_close_monitor(void); 1017 | 1018 | 1019 | 1020 | /** 1021 | * @brief Switch to specific wifi channel. 1022 | * 1023 | * @param[in] primary_channel @n Primary channel. 1024 | * @param[in] secondary_channel @n Auxiliary channel if 40Mhz channel is supported, currently 1025 | * this param is always 0. 1026 | * @param[in] bssid @n A pointer to wifi BSSID on which awss lock the channel, most platform 1027 | * may ignore it. 1028 | * @return None. 1029 | * @see None. 1030 | * @note None. 1031 | */ 1032 | void platform_awss_switch_channel( 1033 | _IN_ char primary_channel, 1034 | _IN_OPT_ char secondary_channel, 1035 | _IN_OPT_ uint8_t bssid[ETH_ALEN]); 1036 | 1037 | /* auth type */ 1038 | enum AWSS_AUTH_TYPE { 1039 | AWSS_AUTH_TYPE_OPEN, 1040 | AWSS_AUTH_TYPE_SHARED, 1041 | AWSS_AUTH_TYPE_WPAPSK, 1042 | AWSS_AUTH_TYPE_WPA8021X, 1043 | AWSS_AUTH_TYPE_WPA2PSK, 1044 | AWSS_AUTH_TYPE_WPA28021X, 1045 | AWSS_AUTH_TYPE_WPAPSKWPA2PSK, 1046 | AWSS_AUTH_TYPE_MAX = AWSS_AUTH_TYPE_WPAPSKWPA2PSK, 1047 | AWSS_AUTH_TYPE_INVALID = 0xff, 1048 | }; 1049 | 1050 | /* encry type */ 1051 | enum AWSS_ENC_TYPE { 1052 | AWSS_ENC_TYPE_NONE, 1053 | AWSS_ENC_TYPE_WEP, 1054 | AWSS_ENC_TYPE_TKIP, 1055 | AWSS_ENC_TYPE_AES, 1056 | AWSS_ENC_TYPE_TKIPAES, 1057 | AWSS_ENC_TYPE_MAX = AWSS_ENC_TYPE_TKIPAES, 1058 | AWSS_ENC_TYPE_INVALID = 0xff, 1059 | }; 1060 | 1061 | /** 1062 | * @brief Wifi AP connect function 1063 | * 1064 | * @param[in] connection_timeout_ms @n AP connection timeout in ms or PLATFORM_WAIT_INFINITE 1065 | * @param[in] ssid @n AP ssid 1066 | * @param[in] passwd @n AP passwd 1067 | * @param[in] auth @n optional(AWSS_AUTH_TYPE_INVALID), AP auth info 1068 | * @param[in] encry @n optional(AWSS_ENC_TYPE_INVALID), AP encry info 1069 | * @param[in] bssid @n optional(NULL or zero mac address), AP bssid info 1070 | * @param[in] channel @n optional, AP channel info 1071 | * @return 1072 | @verbatim 1073 | = 0: connect AP & DHCP success 1074 | = -1: connect AP or DHCP fail/timeout 1075 | @endverbatim 1076 | * @see None. 1077 | * @note None. 1078 | */ 1079 | int platform_awss_connect_ap( 1080 | _IN_ uint32_t connection_timeout_ms, 1081 | _IN_ char ssid[PLATFORM_MAX_SSID_LEN], 1082 | _IN_ char passwd[PLATFORM_MAX_PASSWD_LEN], 1083 | _IN_OPT_ enum AWSS_AUTH_TYPE auth, 1084 | _IN_OPT_ enum AWSS_ENC_TYPE encry, 1085 | _IN_OPT_ uint8_t bssid[ETH_ALEN], 1086 | _IN_OPT_ uint8_t channel); 1087 | 1088 | /* 80211 frame type */ 1089 | enum platform_awss_frame_type { 1090 | FRAME_ACTION, 1091 | FRAME_BEACON, 1092 | FRAME_PROBE_REQ, 1093 | FRAME_PROBE_RESPONSE, 1094 | FRAME_DATA 1095 | }; 1096 | 1097 | #define FRAME_ACTION_MASK (1 << FRAME_ACTION) 1098 | #define FRAME_BEACON_MASK (1 << FRAME_BEACON) 1099 | #define FRAME_PROBE_REQ_MASK (1 << FRAME_PROBE_REQ) 1100 | #define FRAME_PROBE_RESP_MASK (1 << FRAME_PROBE_RESPONSE) 1101 | #define FRAME_DATA_MASK (1 << FRAME_DATA) 1102 | 1103 | /** 1104 | * @brief send 80211 raw frame in current channel with basic rate(1Mbps) 1105 | * 1106 | * @param[in] type @n see enum platform_awss_frame_type, currently only FRAME_BEACON 1107 | * FRAME_PROBE_REQ is used 1108 | * @param[in] buffer @n 80211 raw frame, include complete mac header & FCS field 1109 | * @param[in] len @n 80211 raw frame length 1110 | * @return 1111 | @verbatim 1112 | = 0, send success. 1113 | = -1, send failure. 1114 | = -2, unsupported. 1115 | @endverbatim 1116 | * @see None. 1117 | * @note awss use this API send raw frame in wifi monitor mode & station mode 1118 | */ 1119 | int platform_wifi_send_80211_raw_frame(_IN_ enum platform_awss_frame_type type, 1120 | _IN_ uint8_t *buffer, _IN_ int len); 1121 | 1122 | /** 1123 | * @brief management frame handler 1124 | * 1125 | * @param[in] buffer @n 80211 raw frame or ie(information element) buffer 1126 | * @param[in] len @n buffer length 1127 | * @param[in] rssi_dbm @n rssi in dbm, set it to 0 if not supported 1128 | * @param[in] buffer_type @n 0 when buffer is a 80211 frame, 1129 | * 1 when buffer only contain IE info 1130 | * @return None. 1131 | * @see None. 1132 | * @note None. 1133 | */ 1134 | typedef void (*platform_wifi_mgnt_frame_cb_t)(_IN_ uint8_t *buffer, 1135 | _IN_ int len, _IN_ char rssi_dbm, _IN_ int buffer_type); 1136 | 1137 | /** 1138 | * @brief enable/disable filter specific management frame in wifi station mode 1139 | * 1140 | * @param[in] filter_mask @n see mask macro in enum platform_awss_frame_type, 1141 | * currently only FRAME_PROBE_REQ_MASK & FRAME_BEACON_MASK is used 1142 | * @param[in] vendor_oui @n oui can be used for precise frame match, optional 1143 | * @param[in] callback @n see platform_wifi_mgnt_frame_cb_t, passing 80211 1144 | * frame or ie to callback. when callback is NULL 1145 | * disable sniffer feature, otherwise enable it. 1146 | * @return 1147 | @verbatim 1148 | = 0, success 1149 | = -1, fail 1150 | = -2, unsupported. 1151 | @endverbatim 1152 | * @see None. 1153 | * @note awss use this API to filter specific mgnt frame in wifi station mode 1154 | */ 1155 | int platform_wifi_enable_mgnt_frame_filter( 1156 | _IN_ uint32_t filter_mask, 1157 | _IN_OPT_ uint8_t vendor_oui[3], 1158 | _IN_ platform_wifi_mgnt_frame_cb_t callback); 1159 | 1160 | /** @} */ //end of platform__awss 1161 | 1162 | typedef struct { 1163 | enum AWSS_AUTH_TYPE auth; 1164 | enum AWSS_ENC_TYPE encry; 1165 | uint8_t channel; 1166 | char rssi_dbm; 1167 | char ssid[PLATFORM_MAX_SSID_LEN]; 1168 | uint8_t mac[ETH_ALEN]; 1169 | } ap_info_t; 1170 | 1171 | /** 1172 | * @brief handle one piece of AP information from wifi scan result 1173 | * 1174 | * @param[in] ssid @n name of AP 1175 | * @param[in] bssid @n mac address of AP 1176 | * @param[in] channel @n AP channel 1177 | * @param[in] rssi @n rssi range[-100, 0]. 1178 | * the higher the RSSI number, the stronger the signal. 1179 | * @param[in] is_last_ap @n this AP information is the last one if is_last_ap > 0. 1180 | * this AP information is not the last one if is_last_ap == 0. 1181 | * @return 0 for wifi scan is done, otherwise return -1 1182 | * @see None. 1183 | * @note None. 1184 | */ 1185 | typedef int (*platform_wifi_scan_result_cb_t)( 1186 | const char ssid[PLATFORM_MAX_SSID_LEN], 1187 | const uint8_t bssid[ETH_ALEN], 1188 | enum AWSS_AUTH_TYPE auth, 1189 | enum AWSS_ENC_TYPE encry, 1190 | uint8_t channel, char rssi, 1191 | int is_last_ap); 1192 | 1193 | /** 1194 | * @brief launch a wifi scan operation 1195 | * 1196 | * @param[in] cb @n pass ssid info(scan result) to this callback one by one 1197 | * @return 0 for wifi scan is done, otherwise return -1 1198 | * @see None. 1199 | * @note 1200 | * This API should NOT exit before the invoking for cb is finished. 1201 | * This rule is something like the following : 1202 | * platform_wifi_scan() is invoked... 1203 | * ... 1204 | * for (ap = first_ap; ap <= last_ap; ap = next_ap){ 1205 | * cb(ap) 1206 | * } 1207 | * ... 1208 | * platform_wifi_scan() exit... 1209 | */ 1210 | int platform_wifi_scan(platform_wifi_scan_result_cb_t cb); 1211 | 1212 | typedef enum { 1213 | PLATFORM_AES_ENCRYPTION = 0, 1214 | PLATFORM_AES_DECRYPTION = 1, 1215 | } AES_DIR_t; 1216 | 1217 | typedef void *p_aes128_t; 1218 | 1219 | /** 1220 | * @brief initialize AES struct. 1221 | * 1222 | * @param[in] key: 1223 | * @param[in] iv: 1224 | * @param[in] dir: AES_ENCRYPTION or AES_DECRYPTION 1225 | * @return AES128_t 1226 | @verbatim None 1227 | @endverbatim 1228 | * @see None. 1229 | * @note None. 1230 | */ 1231 | p_aes128_t platform_aes128_init( 1232 | _IN_ const uint8_t *key, 1233 | _IN_ const uint8_t *iv, 1234 | _IN_ AES_DIR_t dir); 1235 | 1236 | /** 1237 | * @brief release AES struct. 1238 | * 1239 | * @param[in] aes: 1240 | * @return 1241 | @verbatim 1242 | = 0: succeeded 1243 | = -1: failed 1244 | @endverbatim 1245 | * @see None. 1246 | * @note None. 1247 | */ 1248 | int platform_aes128_destroy(_IN_ p_aes128_t aes); 1249 | 1250 | /** 1251 | * @brief encrypt data with aes (cbc/128bit key). 1252 | * 1253 | * @param[in] aes: AES handler 1254 | * @param[in] src: plain data 1255 | * @param[in] blockNum: plain data number of 16 bytes size 1256 | * @param[out] dst: cipher data 1257 | * @return 1258 | @verbatim 1259 | = 0: succeeded 1260 | = -1: failed 1261 | @endverbatim 1262 | * @see None. 1263 | * @note None. 1264 | */ 1265 | int platform_aes128_cbc_encrypt( 1266 | _IN_ p_aes128_t aes, 1267 | _IN_ const void *src, 1268 | _IN_ size_t blockNum, 1269 | _OUT_ void *dst); 1270 | 1271 | /** 1272 | * @brief decrypt data with aes (cbc/128bit key). 1273 | * 1274 | * @param[in] aes: AES handler 1275 | * @param[in] src: cipher data 1276 | * @param[in] blockNum: plain data number of 16 bytes size 1277 | * @param[out] dst: plain data 1278 | * @return 1279 | @verbatim 1280 | = 0: succeeded 1281 | = -1: failed 1282 | @endverbatim 1283 | * @see None. 1284 | * @note None. 1285 | */ 1286 | int platform_aes128_cbc_decrypt( 1287 | _IN_ p_aes128_t aes, 1288 | _IN_ const void *src, 1289 | _IN_ size_t blockNum, 1290 | _OUT_ void *dst); 1291 | 1292 | /** 1293 | * @brief get the information of the connected AP. 1294 | * 1295 | * @param[out] ssid: array to store ap ssid. It will be null if ssid is not required. 1296 | * @param[out] passwd: array to store ap password. It will be null if ap password is not required. 1297 | * @param[out] bssid: array to store ap bssid. It will be null if bssid is not required. 1298 | * @return 1299 | @verbatim 1300 | = 0: succeeded 1301 | = -1: failed 1302 | @endverbatim 1303 | * @see None. 1304 | * @note None. 1305 | */ 1306 | int platform_wifi_get_ap_info( 1307 | _OUT_ char ssid[PLATFORM_MAX_SSID_LEN], 1308 | _OUT_ char passwd[PLATFORM_MAX_PASSWD_LEN], 1309 | _OUT_ uint8_t bssid[ETH_ALEN]); 1310 | 1311 | 1312 | /** @} */ //end of platform__awss 1313 | 1314 | /** @} */ //end of group_platform 1315 | 1316 | #ifdef __cplusplus 1317 | } 1318 | #endif 1319 | 1320 | #endif 1321 | 1322 | -------------------------------------------------------------------------------- /adaptation/include/alink_product.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. 3 | * 4 | * Alibaba Group retains all right, title and interest (including all 5 | * intellectual property rights) in and to this computer program, which is 6 | * protected by applicable intellectual property laws. Unless you have 7 | * obtained a separate written license from Alibaba Group., you are not 8 | * authorized to utilize all or a part of this computer program for any 9 | * purpose (including reproduction, distribution, modification, and 10 | * compilation into object code), and you must immediately destroy or 11 | * return to Alibaba Group all copies of this computer program. If you 12 | * are licensed by Alibaba Group, your rights to utilize this computer 13 | * program are limited by the terms of that license. To obtain a license, 14 | * please contact Alibaba Group. 15 | * 16 | * This computer program contains trade secrets owned by Alibaba Group. 17 | * and, unless unauthorized by Alibaba Group in writing, you agree to 18 | * maintain the confidentiality of this computer program and related 19 | * information and to not disclose this computer program and related 20 | * information to any other person or entity. 21 | * 22 | * THIS COMPUTER PROGRAM IS PROVIDED AS IS WITHOUT ANY WARRANTIES, AND 23 | * Alibaba Group EXPRESSLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, 24 | * INCLUDING THE WARRANTIES OF MERCHANTIBILITY, FITNESS FOR A PARTICULAR 25 | * PURPOSE, TITLE, AND NONINFRINGEMENT. 26 | */ 27 | 28 | #ifndef __ALINK_PRODUCT_H__ 29 | #define __ALINK_PRODUCT_H__ 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | #include "alink_platform.h" 36 | #include "esp_alink.h" 37 | 38 | /** @defgroup group_product product 39 | * @{ 40 | */ 41 | 42 | #ifndef CONFIG_DEVICE_ID_ADRR 43 | #define CONFIG_DEVICE_ID_ADRR 0x310000 44 | #endif 45 | #define DEVICE_ID_ADRR CONFIG_DEVICE_ID_ADRR 46 | #define DEVICE_KEY_LEN (20 + 1) 47 | #define DEVICE_SECRET_LEN (32 + 1) 48 | 49 | #define PRODUCT_SN_LEN (64 + 1) 50 | #define PRODUCT_MODEL_LEN (80 + 1) 51 | #define PRODUCT_KEY_LEN (20 + 1) 52 | #define PRODUCT_SECRET_LEN (40 + 1) 53 | #define PRODUCT_UUID_LEN (32 + 1) 54 | #define PRODUCT_VERSION_LEN (16 + 1) 55 | #define PRODUCT_NAME_LEN (32 + 1) 56 | 57 | /** 58 | * @brief Get the product version string. 59 | * 60 | * @param[in] version_str @n Buffer for using to store version string. 61 | * @return The version string. 62 | * @see None. 63 | * @note 64 | */ 65 | alink_err_t product_get(_OUT_ void *product_info); 66 | 67 | /** 68 | * @brief Get the product version string. 69 | * 70 | * @param[in] version_str @n Buffer for using to store version string. 71 | * @return The version string. 72 | * @see None. 73 | * @note 74 | */ 75 | alink_err_t product_set(_IN_ const void *product_info); 76 | 77 | /** 78 | * @brief Get the product version string. 79 | * 80 | * @param[in] version_str @n Buffer for using to store version string. 81 | * @return The version string. 82 | * @see None. 83 | * @note 84 | */ 85 | char *product_get_version(char version_str[PRODUCT_VERSION_LEN]); 86 | 87 | /** 88 | * @brief Get product name string. 89 | * 90 | * @param[out] name_str @n Buffer for using to store name string. 91 | * @return A pointer to the start address of name_str. 92 | * @see None. 93 | * @note None. 94 | */ 95 | char *product_get_name(char name_str[PRODUCT_NAME_LEN]); 96 | 97 | /** 98 | * @brief Get product SN string. 99 | * 100 | * @param[out] sn_str @n Buffer for using to store SN string. 101 | * @return A pointer to the start address of sn_str. 102 | * @see None. 103 | * @note None. 104 | */ 105 | char *product_get_sn(char sn_str[PRODUCT_SN_LEN]); 106 | 107 | /** 108 | * @brief Get product model string. 109 | * 110 | * @param[out] model_str @n Buffer for using to store model string. 111 | * @return A pointer to the start address of model_str. 112 | * @see None. 113 | * @note None. 114 | */ 115 | char *product_get_model(char model_str[PRODUCT_MODEL_LEN]); 116 | 117 | /** 118 | * @brief Get product key string. 119 | * 120 | * @param[out] key_str @n Buffer for using to store key string. 121 | * @return A pointer to the start address of key_str. 122 | * @see None. 123 | * @note None. 124 | */ 125 | char *product_get_key(char key_str[PRODUCT_KEY_LEN]); 126 | 127 | /** 128 | * @brief Get product secret string. 129 | * 130 | * @param[out] secret_str @n Buffer for using to store secret string. 131 | * @return A pointer to the start address of secret_str. 132 | * @see None. 133 | * @note None. 134 | */ 135 | char *product_get_secret(char secret_str[PRODUCT_SECRET_LEN]); 136 | 137 | /** 138 | * @brief Get product debug key string. 139 | * 140 | * @param[out] key_str @n Buffer for using to store debug key string. 141 | * @return A pointer to the start address of key_str. 142 | * @see None. 143 | * @note None. 144 | */ 145 | char *product_get_debug_key(char key_str[PRODUCT_KEY_LEN]); 146 | 147 | /** 148 | * @brief Get product debug secret string. 149 | * 150 | * @param[out] secret_str @n Buffer for using to store debug secret string. 151 | * @return A pointer to the start address of secret_str. 152 | * @see None. 153 | * @note None. 154 | */ 155 | char *product_get_debug_secret(char secret_str[PRODUCT_SECRET_LEN]); 156 | 157 | /** @} */// end of group_product 158 | 159 | #ifdef __cplusplus 160 | } 161 | #endif 162 | #endif 163 | -------------------------------------------------------------------------------- /application/esp_alink_main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2017 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #include 26 | #include 27 | 28 | #include "esp_system.h" 29 | #include "freertos/FreeRTOS.h" 30 | #include "freertos/task.h" 31 | #include "nvs.h" 32 | #include "nvs_flash.h" 33 | #include "esp_partition.h" 34 | #include "esp_wifi.h" 35 | 36 | #include "alink_platform.h" 37 | #include "alink_product.h" 38 | #include "alink_export.h" 39 | #include "alink_json_parser.h" 40 | 41 | #include "esp_alink.h" 42 | #include "esp_alink_log.h" 43 | #include "esp_info_store.h" 44 | #include "esp_json_parser.h" 45 | 46 | static const char *TAG = "alink_main"; 47 | /** 48 | * @brief Clear wifi information, restart the device into the config network mode 49 | */ 50 | alink_err_t alink_update_router() 51 | { 52 | int ret = 0; 53 | ALINK_LOGI("clear wifi config"); 54 | ret = esp_info_erase(NVS_KEY_WIFI_CONFIG); 55 | 56 | if (ret != ALINK_OK) { 57 | ALINK_LOGD("esp_info_erase, ret: %d", ret); 58 | } 59 | 60 | ALINK_LOGW("The system is about to be restarted"); 61 | esp_restart(); 62 | 63 | return ALINK_OK; 64 | } 65 | 66 | static alink_err_t alink_connect_ap() 67 | { 68 | alink_err_t ret = ALINK_ERR; 69 | wifi_config_t wifi_config; 70 | 71 | ret = esp_info_load(NVS_KEY_WIFI_CONFIG, &wifi_config, sizeof(wifi_config_t)); 72 | 73 | if (ret > 0) { 74 | if (platform_awss_connect_ap(WIFI_WAIT_TIME, (char *)wifi_config.sta.ssid, (char *)wifi_config.sta.password, 75 | 0, 0, wifi_config.sta.bssid, 0) == ALINK_OK) { 76 | return ALINK_OK; 77 | } 78 | } 79 | 80 | alink_event_send(ALINK_EVENT_CONFIG_NETWORK); 81 | ALINK_LOGI("*********************************"); 82 | ALINK_LOGI("* ENTER SAMARTCONFIG MODE *"); 83 | ALINK_LOGI("*********************************"); 84 | ret = awss_start(); 85 | 86 | if (ret != ALINK_OK) { 87 | ALINK_LOGW("awss_start is err"); 88 | ALINK_LOGW("The system is about to be restarted"); 89 | esp_restart(); 90 | } 91 | 92 | return ALINK_OK; 93 | } 94 | 95 | /** 96 | * @brief Clear all the information of the device and return to the factory status 97 | */ 98 | alink_err_t alink_factory_setting() 99 | { 100 | /* clear ota data */ 101 | ALINK_LOGI("*********************************"); 102 | ALINK_LOGI("* FACTORY RESET *"); 103 | ALINK_LOGI("*********************************"); 104 | ALINK_LOGI("clear wifi config"); 105 | alink_err_t err; 106 | err = esp_info_erase(ALINK_SPACE_NAME); 107 | ALINK_ERROR_CHECK(err != 0, ALINK_ERR, "alink_erase_wifi_config"); 108 | 109 | esp_partition_t find_partition; 110 | memset(&find_partition, 0, sizeof(esp_partition_t)); 111 | find_partition.type = ESP_PARTITION_TYPE_DATA; 112 | find_partition.subtype = ESP_PARTITION_SUBTYPE_DATA_OTA; 113 | 114 | const esp_partition_t *partition = esp_partition_find_first(find_partition.type, find_partition.subtype, NULL); 115 | ALINK_ERROR_CHECK(partition == NULL, ALINK_ERR, "nvs_erase_key partition:%p", partition); 116 | 117 | err = esp_partition_erase_range(partition, 0, partition->size); 118 | ALINK_ERROR_CHECK(partition == NULL, ALINK_ERR, "esp_partition_erase_range ret:%d", err); 119 | 120 | if (err != ALINK_OK) { 121 | ALINK_LOGE("esp_partition_erase_range ret:%d", err); 122 | vTaskDelete(NULL); 123 | } 124 | 125 | ALINK_LOGI("reset user account binding"); 126 | alink_factory_reset(); 127 | 128 | ALINK_LOGW("The system is about to be restarted"); 129 | esp_restart(); 130 | } 131 | 132 | /** 133 | * @brief Get time from alink service 134 | */ 135 | #define TIME_STR_LEN (32) 136 | alink_err_t alink_get_time(unsigned int *utc_time) 137 | { 138 | ALINK_PARAM_CHECK(utc_time); 139 | 140 | char buf[TIME_STR_LEN] = { 0 }, *attr_str; 141 | int size = TIME_STR_LEN, attr_len = 0; 142 | 143 | if (!alink_query("getAlinkTime", "{}", buf, &size)) { 144 | return ALINK_ERR; 145 | } 146 | 147 | attr_str = json_get_value_by_name(buf, size, "time", &attr_len, NULL); 148 | ALINK_ERROR_CHECK(!attr_str, ALINK_ERR, "json_get_value_by_name, ret: %p", attr_str); 149 | 150 | *utc_time = atoi(attr_str); 151 | 152 | return ALINK_OK; 153 | } 154 | 155 | /** 156 | * @brief Event management 157 | */ 158 | #define EVENT_QUEUE_NUM 3 159 | static xQueueHandle xQueueEvent = NULL; 160 | static void alink_event_loop_task(void *pvParameters) 161 | { 162 | alink_event_cb_t s_event_handler_cb = (alink_event_cb_t)pvParameters; 163 | 164 | for (;;) { 165 | alink_event_t event; 166 | 167 | if (xQueueReceive(xQueueEvent, &event, portMAX_DELAY) != pdPASS) { 168 | continue; 169 | } 170 | 171 | if (!s_event_handler_cb) { 172 | continue; 173 | } 174 | 175 | if ((*s_event_handler_cb)(event) < 0) { 176 | ALINK_LOGW("Event handling failed"); 177 | } 178 | } 179 | 180 | vTaskDelete(NULL); 181 | } 182 | 183 | alink_err_t alink_event_send(alink_event_t event) 184 | { 185 | if (!xQueueEvent) { 186 | xQueueEvent = xQueueCreate(EVENT_QUEUE_NUM, sizeof(alink_event_t)); 187 | } 188 | 189 | alink_err_t ret = xQueueSend(xQueueEvent, &event, 0); 190 | ALINK_ERROR_CHECK(ret != pdTRUE, ALINK_ERR, "xQueueSendToBack fail!"); 191 | 192 | return ALINK_OK; 193 | } 194 | 195 | /** 196 | * @brief Initialize alink config and start alink task 197 | */ 198 | extern alink_err_t alink_trans_init(); 199 | extern void alink_trans_destroy(); 200 | alink_err_t alink_init(_IN_ const void *product_info, 201 | _IN_ const alink_event_cb_t event_handler_cb) 202 | { 203 | ALINK_PARAM_CHECK(product_info); 204 | ALINK_PARAM_CHECK(event_handler_cb); 205 | 206 | alink_err_t ret = ALINK_OK; 207 | 208 | if (!xQueueEvent) { 209 | xQueueEvent = xQueueCreate(EVENT_QUEUE_NUM, sizeof(alink_event_t)); 210 | } 211 | 212 | xTaskCreate(alink_event_loop_task, "alink_event_loop_task", ALINK_EVENT_STACK_SIZE, 213 | event_handler_cb, DEFAULU_TASK_PRIOTY, NULL); 214 | 215 | ret = product_set(product_info); 216 | ALINK_ERROR_CHECK(ret != ALINK_OK, ALINK_ERR, "product_set :%d", ret); 217 | 218 | ret = alink_connect_ap(); 219 | ALINK_ERROR_CHECK(ret != ALINK_OK, ALINK_ERR, "alink_connect_ap :%d", ret); 220 | 221 | ret = alink_trans_init(); 222 | 223 | if (ret != ALINK_OK) { 224 | alink_trans_destroy(); 225 | } 226 | 227 | ALINK_ERROR_CHECK(ret != ALINK_OK, ALINK_ERR, "alink_trans_init :%d", ret); 228 | 229 | return ALINK_OK; 230 | } 231 | -------------------------------------------------------------------------------- /application/esp_data_transport.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2017 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #include "esp_system.h" 26 | #include "freertos/FreeRTOS.h" 27 | #include "freertos/task.h" 28 | #include "freertos/queue.h" 29 | #include "lwip/sockets.h" 30 | 31 | #include "alink_platform.h" 32 | #include "alink_product.h" 33 | #include "alink_export.h" 34 | 35 | #include "esp_alink.h" 36 | #include "esp_alink_log.h" 37 | #include "esp_json_parser.h" 38 | 39 | #define Method_PostData "postDeviceData" 40 | #define Method_PostRawData "postDeviceRawData" 41 | #define Method_GetStatus "getDeviceStatus" 42 | #define Method_SetStatus "setDeviceStatus" 43 | #define Method_GetAlinkTime "getAlinkTime" 44 | 45 | #define ALINK_METHOD_POST Method_PostData 46 | #define ALINK_GET_DEVICE_DATA ALINK_GET_DEVICE_STATUS 47 | #define ALINK_SET_DEVICE_DATA ALINK_SET_DEVICE_STATUS 48 | 49 | static const char *TAG = "esp_data_transport.c"; 50 | static alink_err_t post_data_enable = ALINK_TRUE; 51 | static xQueueHandle xQueueDownCmd = NULL; 52 | static xQueueHandle xQueueUpCmd = NULL; 53 | 54 | static alink_err_t cloud_get_device_data(_IN_ char *json_buffer) 55 | { 56 | ALINK_PARAM_CHECK(json_buffer); 57 | 58 | alink_err_t ret = ALINK_OK; 59 | 60 | alink_event_send(ALINK_EVENT_GET_DEVICE_DATA); 61 | 62 | ret = esp_json_pack(json_buffer, "method", Method_GetStatus); 63 | ALINK_ERROR_CHECK(ret < 0, ALINK_ERR, "esp_json_pack, ret:%d", ret); 64 | 65 | int size = ret + 1; 66 | char *q_data = (char *)alink_malloc(size); 67 | 68 | if (size > ALINK_DATA_LEN) { 69 | ALINK_LOGW("json_buffer len:%d", size); 70 | } 71 | 72 | memcpy(q_data, json_buffer, size); 73 | 74 | if (xQueueSend(xQueueDownCmd, &q_data, 0) != pdTRUE) { 75 | ALINK_LOGW("xQueueSend xQueueDownCmd is err"); 76 | ret = ALINK_ERR; 77 | alink_free(q_data); 78 | } 79 | 80 | return ret; 81 | } 82 | 83 | static alink_err_t cloud_set_device_data(_IN_ char *json_buffer) 84 | { 85 | ALINK_PARAM_CHECK(json_buffer); 86 | 87 | alink_err_t ret = ALINK_OK; 88 | 89 | alink_event_send(ALINK_EVENT_SET_DEVICE_DATA); 90 | 91 | ret = esp_json_pack(json_buffer, "method", Method_SetStatus); 92 | ALINK_ERROR_CHECK(ret < 0, ALINK_ERR, "esp_json_pack, ret:%d", ret); 93 | 94 | int size = ret + 1; 95 | char *q_data = (char *)alink_malloc(size); 96 | 97 | if (size > ALINK_DATA_LEN) { 98 | ALINK_LOGW("json_buffer len:%d, json_buffer: %s", size, json_buffer); 99 | } 100 | 101 | memcpy(q_data, json_buffer, size); 102 | 103 | if (xQueueSend(xQueueDownCmd, &q_data, 0) != pdTRUE) { 104 | ALINK_LOGW("xQueueSend xQueueDownCmd is err"); 105 | ret = ALINK_ERR; 106 | alink_free(q_data); 107 | } 108 | 109 | return ret; 110 | } 111 | 112 | #ifndef ALINK_WRITE_NOT_BUFFER 113 | static void alink_post_data(void *arg) 114 | { 115 | alink_err_t ret; 116 | char *up_cmd = NULL; 117 | 118 | for (; post_data_enable;) { 119 | ret = xQueueReceive(xQueueUpCmd, &up_cmd, portMAX_DELAY); 120 | 121 | if (ret != pdTRUE) { 122 | ALINK_LOGW("There is no data to report"); 123 | continue; 124 | } 125 | 126 | ALINK_LOGV("up_cmd: %s", up_cmd); 127 | ret = alink_report(ALINK_METHOD_POST, up_cmd); 128 | 129 | if (ret != ALINK_OK) { 130 | ALINK_LOGW("post failed!"); 131 | alink_event_send(ALINK_EVENT_POST_CLOUD_DATA_FAIL); 132 | platform_msleep(3000); 133 | } else { 134 | alink_event_send(ALINK_EVENT_POST_CLOUD_DATA); 135 | } 136 | 137 | alink_free(up_cmd); 138 | } 139 | 140 | vTaskDelete(NULL); 141 | } 142 | #endif /*!< ALINK_WRITE_NOT_BUFFER */ 143 | 144 | static void cloud_connected(void) 145 | { 146 | alink_event_send(ALINK_EVENT_CLOUD_CONNECTED); 147 | } 148 | 149 | static void cloud_disconnected(void) 150 | { 151 | alink_event_send(ALINK_EVENT_CLOUD_DISCONNECTED); 152 | } 153 | 154 | alink_err_t alink_trans_init() 155 | { 156 | alink_err_t ret = ALINK_OK; 157 | post_data_enable = ALINK_TRUE; 158 | xQueueUpCmd = xQueueCreate(DOWN_CMD_QUEUE_NUM, sizeof(char *)); 159 | xQueueDownCmd = xQueueCreate(UP_CMD_QUEUE_NUM, sizeof(char *)); 160 | alink_set_loglevel(ALINK_SDK_LOG_LEVEL); 161 | 162 | alink_register_callback(ALINK_CLOUD_CONNECTED, &cloud_connected); 163 | alink_register_callback(ALINK_CLOUD_DISCONNECTED, &cloud_disconnected); 164 | alink_register_callback(ALINK_GET_DEVICE_DATA, &cloud_get_device_data); 165 | alink_register_callback(ALINK_SET_DEVICE_DATA, &cloud_set_device_data); 166 | 167 | ret = alink_start(); 168 | ALINK_ERROR_CHECK(ret != ALINK_OK, ALINK_ERR, "alink_start :%d", ret); 169 | ALINK_LOGI("wait main device login"); 170 | /*wait main device login, -1 means wait forever */ 171 | ret = alink_wait_connect(ALINK_WAIT_FOREVER); 172 | ALINK_ERROR_CHECK(ret != ALINK_OK, ALINK_ERR, "alink_start : %d", ret); 173 | 174 | #ifndef ALINK_WRITE_NOT_BUFFER 175 | ret = xTaskCreate(alink_post_data, "alink_post_data", ALINK_POST_DATA_STACK_SIZE, NULL, DEFAULU_TASK_PRIOTY, NULL); 176 | ALINK_ERROR_CHECK(ret != pdTRUE, ALINK_ERR, "thread_create name: %s, stack_size: %d, ret: %d", "alink_post_data", 2048, ret); 177 | #endif /*!< ALINK_WRITE_NOT_BUFFER */ 178 | 179 | return ALINK_OK; 180 | } 181 | 182 | void alink_trans_destroy() 183 | { 184 | post_data_enable = ALINK_FALSE; 185 | alink_end(); 186 | vQueueDelete(xQueueUpCmd); 187 | vQueueDelete(xQueueDownCmd); 188 | } 189 | 190 | #ifdef ALINK_WRITE_NOT_BUFFER 191 | ssize_t alink_write(_IN_ const void *up_cmd, size_t size, int micro_seconds) 192 | { 193 | ALINK_PARAM_CHECK(up_cmd); 194 | ALINK_PARAM_CHECK(size && size <= ALINK_DATA_LEN); 195 | alink_err_t ret = 0; 196 | 197 | ALINK_LOGV("up_cmd: %s", (char *)up_cmd); 198 | ret = alink_report(ALINK_METHOD_POST, up_cmd); 199 | 200 | if (ret != ALINK_OK) { 201 | ALINK_LOGW("post failed!"); 202 | platform_msleep(1000); 203 | } else { 204 | alink_event_send(ALINK_EVENT_POST_CLOUD_DATA); 205 | } 206 | return size; 207 | } 208 | #endif 209 | 210 | #ifndef ALINK_WRITE_NOT_BUFFER 211 | ssize_t alink_write(_IN_ const void *up_cmd, size_t size, int micro_seconds) 212 | { 213 | ALINK_PARAM_CHECK(up_cmd); 214 | ALINK_PARAM_CHECK(size && size <= ALINK_DATA_LEN); 215 | 216 | if (!xQueueUpCmd) { 217 | return ALINK_ERR; 218 | } 219 | 220 | alink_err_t ret = ALINK_OK; 221 | char *q_data = (char *)alink_malloc(size); 222 | memcpy(q_data, up_cmd, size); 223 | 224 | ret = xQueueSend(xQueueUpCmd, &q_data, micro_seconds / portTICK_RATE_MS); 225 | 226 | if (ret == pdFALSE) { 227 | ALINK_LOGD("xQueueSend xQueueUpCmd, wait_time: %d", micro_seconds); 228 | alink_free(q_data); 229 | return ALINK_ERR; 230 | } 231 | 232 | return size; 233 | } 234 | #endif 235 | 236 | ssize_t alink_read(_OUT_ void *down_cmd, size_t size, int micro_seconds) 237 | { 238 | ALINK_PARAM_CHECK(down_cmd); 239 | ALINK_PARAM_CHECK(xQueueDownCmd); 240 | ALINK_PARAM_CHECK(size && size <= ALINK_DATA_LEN); 241 | 242 | alink_err_t ret = ALINK_OK; 243 | char *q_data = NULL; 244 | 245 | ret = xQueueReceive(xQueueDownCmd, &q_data, micro_seconds / portTICK_RATE_MS); 246 | 247 | if (ret == pdFALSE) { 248 | ALINK_LOGD("xQueueReceive xQueueDownCmd, ret:%d, wait_time: %d", ret, micro_seconds); 249 | alink_free(q_data); 250 | return ALINK_ERR; 251 | } 252 | 253 | int size_tmp = strlen(q_data) + 1; 254 | size = (size_tmp > size) ? size : size_tmp; 255 | 256 | if (size > ALINK_DATA_LEN) { 257 | ALINK_LOGD("read len > ALINK_DATA_LEN, len: %d", size); 258 | size = ALINK_DATA_LEN; 259 | q_data[size - 1] = '\0'; 260 | } 261 | 262 | memcpy(down_cmd, q_data, size); 263 | 264 | alink_free(q_data); 265 | return size; 266 | } 267 | -------------------------------------------------------------------------------- /application/esp_info_store.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2017 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #include 26 | #include 27 | 28 | #include "nvs.h" 29 | #include "nvs_flash.h" 30 | 31 | #include "esp_info_store.h" 32 | #include "esp_alink_log.h" 33 | 34 | static const char *TAG = "esp_info_store"; 35 | 36 | int esp_info_erase(const char *key) 37 | { 38 | ALINK_PARAM_CHECK(key); 39 | 40 | alink_err_t ret = -1; 41 | nvs_handle handle = 0; 42 | 43 | ret = nvs_open(ALINK_SPACE_NAME, NVS_READWRITE, &handle); 44 | ALINK_ERROR_CHECK(ret != ESP_OK, ALINK_ERR, "nvs_open ret:%x", ret); 45 | 46 | if (!strcmp(key, ALINK_SPACE_NAME)) { 47 | ret = nvs_erase_all(handle); 48 | } else { 49 | ret = nvs_erase_key(handle, key); 50 | } 51 | 52 | nvs_commit(handle); 53 | ALINK_ERROR_CHECK(ret != ESP_OK, ALINK_ERR, "nvs_erase_key ret:%x", ret); 54 | return ALINK_OK; 55 | } 56 | 57 | ssize_t esp_info_save(const char *key, const void *value, size_t length) 58 | { 59 | ALINK_PARAM_CHECK(key); 60 | ALINK_PARAM_CHECK(value); 61 | ALINK_PARAM_CHECK(length > 0); 62 | 63 | alink_err_t ret = -1; 64 | nvs_handle handle = 0; 65 | 66 | ret = nvs_open(ALINK_SPACE_NAME, NVS_READWRITE, &handle); 67 | ALINK_ERROR_CHECK(ret != ESP_OK, ALINK_ERR, "nvs_open ret:%x", ret); 68 | 69 | /** 70 | * Reduce the number of flash writes 71 | */ 72 | char *tmp = (char *)alink_malloc(length); 73 | ret = nvs_get_blob(handle, key, tmp, &length); 74 | 75 | if ((ret == ESP_OK) && !memcmp(tmp, value, length)) { 76 | alink_free(tmp); 77 | nvs_close(handle); 78 | return length; 79 | } 80 | 81 | alink_free(tmp); 82 | 83 | ret = nvs_set_blob(handle, key, value, length); 84 | nvs_commit(handle); 85 | nvs_close(handle); 86 | ALINK_ERROR_CHECK(ret != ESP_OK, ALINK_ERR, "nvs_set_blob ret:%x", ret); 87 | 88 | return length; 89 | } 90 | 91 | ssize_t esp_info_load(const char *key, void *value, size_t length) 92 | { 93 | ALINK_PARAM_CHECK(key); 94 | ALINK_PARAM_CHECK(value); 95 | ALINK_PARAM_CHECK(length > 0); 96 | 97 | alink_err_t ret = -1; 98 | nvs_handle handle = 0; 99 | 100 | ret = nvs_open(ALINK_SPACE_NAME, NVS_READWRITE, &handle); 101 | ALINK_ERROR_CHECK(ret != ESP_OK, ALINK_ERR, "nvs_open ret:%x", ret); 102 | ret = nvs_get_blob(handle, key, value, &length); 103 | nvs_close(handle); 104 | 105 | if (ret == ESP_ERR_NVS_NOT_FOUND) { 106 | ALINK_LOGW("No data storage,the load data is empty"); 107 | return ALINK_ERR; 108 | } 109 | 110 | ALINK_ERROR_CHECK(ret != ESP_OK, ALINK_ERR, "nvs_get_blob ret:%x", ret); 111 | return length; 112 | } 113 | -------------------------------------------------------------------------------- /application/esp_json_parser.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2017 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #include 26 | #include 27 | 28 | #include "cJSON.h" 29 | 30 | #include "esp_alink.h" 31 | #include "esp_alink_log.h" 32 | 33 | static const char *TAG = "esp_json_parser"; 34 | 35 | alink_err_t __esp_json_parse(const char *json_str, const char *key, void *value, int value_type) 36 | { 37 | ALINK_PARAM_CHECK(json_str); 38 | ALINK_PARAM_CHECK(key); 39 | ALINK_PARAM_CHECK(value); 40 | 41 | cJSON *pJson = cJSON_Parse(json_str); 42 | ALINK_ERROR_CHECK(!pJson, ALINK_ERR, "cJSON_Parse"); 43 | 44 | cJSON *pSub = cJSON_GetObjectItem(pJson, key); 45 | 46 | if (!pSub) { 47 | cJSON_Delete(pJson); 48 | return -EINVAL; 49 | } 50 | 51 | char *p = NULL; 52 | int array_size = 0; 53 | char **q = NULL; 54 | 55 | switch (value_type) { 56 | case 1: 57 | *((int *)value) = pSub->valueint; 58 | break; 59 | 60 | case 2: 61 | *((float *)value) = (float)(pSub->valuedouble); 62 | break; 63 | 64 | case 3: 65 | *((double *)value) = pSub->valuedouble; 66 | break; 67 | 68 | default: 69 | switch (pSub->type) { 70 | case cJSON_False: 71 | *((char *)value) = cJSON_False; 72 | break; 73 | 74 | case cJSON_True: 75 | *((char *)value) = cJSON_True; 76 | break; 77 | 78 | case cJSON_Number: 79 | *((char *)value) = pSub->valueint; 80 | break; 81 | 82 | case cJSON_String: 83 | memcpy(value, pSub->valuestring, strlen(pSub->valuestring) + 1); 84 | break; 85 | 86 | case cJSON_Object: 87 | p = cJSON_PrintUnformatted(pSub); 88 | 89 | if (!p) { 90 | cJSON_Delete(pJson); 91 | } 92 | 93 | ALINK_ERROR_CHECK(!p, -ENOMEM, "cJSON_Print"); 94 | memcpy(value, p, strlen(p) + 1); 95 | free(p); 96 | break; 97 | 98 | case cJSON_Array: 99 | array_size = cJSON_GetArraySize(pSub); 100 | q = (char **)value; 101 | 102 | for (int i = 0; i < array_size; ++i) { 103 | cJSON *item = cJSON_GetArrayItem(pSub, i); 104 | 105 | if (item->type == cJSON_Number) { 106 | *((int *)value + i) = cJSON_GetArrayItem(pSub, i)->valueint; 107 | continue; 108 | } 109 | 110 | if (item->type == cJSON_String) { 111 | cJSON_Minify(item->valuestring); 112 | *q++ = strstr(json_str, item->valuestring); 113 | continue; 114 | } 115 | 116 | if (item->type == cJSON_Object) { 117 | p = cJSON_PrintUnformatted(item); 118 | 119 | if (!p) { 120 | cJSON_Delete(pJson); 121 | } 122 | 123 | ALINK_ERROR_CHECK(!p, -ENOMEM, "cJSON_Print"); 124 | ALINK_ASSERT(*q++ = strstr(json_str, p)); 125 | free(p); 126 | } 127 | } 128 | 129 | 130 | cJSON_Delete(pJson); 131 | return array_size; 132 | break; 133 | 134 | default: 135 | ALINK_LOGE("does not support this type(%d) of data parsing", pSub->type); 136 | break; 137 | } 138 | } 139 | 140 | cJSON_Delete(pJson); 141 | return ALINK_OK; 142 | } 143 | 144 | ssize_t esp_json_pack_double(char *json_str, const char *key, double value) 145 | { 146 | ALINK_PARAM_CHECK(json_str); 147 | ALINK_PARAM_CHECK(key); 148 | 149 | int ret = 0; 150 | 151 | if (*json_str != '{') { 152 | *json_str = '{'; 153 | } else { 154 | ret = (strlen(json_str) - 1); 155 | json_str += ret; 156 | ALINK_ERROR_CHECK(*(json_str) != '}', -EINVAL, "json_str Not initialized to empty"); 157 | *json_str = ','; 158 | } 159 | 160 | json_str++; 161 | ret++; 162 | 163 | ret += sprintf(json_str, "\"%s\": %lf}", key, (double)value); 164 | return ret; 165 | } 166 | 167 | ssize_t __esp_json_pack(char *json_str, const char *key, int value, int value_type) 168 | { 169 | ALINK_PARAM_CHECK(json_str); 170 | ALINK_PARAM_CHECK(key); 171 | 172 | char identifier = '{'; 173 | 174 | if (*key == '[') { 175 | identifier = '['; 176 | key = NULL; 177 | } 178 | 179 | int ret = 0; 180 | 181 | if (*json_str != identifier) { 182 | *json_str = identifier; 183 | } else { 184 | ret = (strlen(json_str) - 1); 185 | json_str += ret; 186 | *json_str = ','; 187 | } 188 | 189 | json_str++; 190 | ret++; 191 | 192 | /* 193 | * drom0_0_seg (R) : org = 0x3F400010, len = 0x800000 194 | * "abc……" type can not be determined 195 | */ 196 | if ((!value_type) && ((value & 0x3f000000) == 0x3f000000)) { 197 | value_type = 3; 198 | } 199 | 200 | int tmp = 0; 201 | 202 | if (key) { 203 | tmp = sprintf(json_str, "\"%s\": ", key); 204 | json_str += tmp; 205 | ret += tmp; 206 | } 207 | 208 | switch (value_type) { 209 | case 1: 210 | tmp = sprintf(json_str, "%d", (int)value); 211 | break; 212 | 213 | case 2: 214 | tmp = sprintf(json_str, "%lf", (double)value); 215 | break; 216 | 217 | case 3: 218 | if (*((char *)value) == '{' || *((char *)value) == '[') { 219 | tmp = sprintf(json_str, "%s", (char *)value); 220 | } else { 221 | tmp = sprintf(json_str, "\"%s\"", (char *)value); 222 | } 223 | 224 | break; 225 | 226 | default: 227 | ALINK_LOGE("invalid type: %d, value_add: %x", value_type, value); 228 | ret = ALINK_ERR; 229 | return ret; 230 | } 231 | 232 | *(json_str + tmp) = '}'; 233 | *(json_str + tmp + 1) = '\0'; 234 | 235 | if (identifier == '[') { 236 | *(json_str + tmp) = ']'; 237 | } 238 | 239 | ret += tmp + 1; 240 | return ret; 241 | } 242 | -------------------------------------------------------------------------------- /component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Component Makefile 3 | # 4 | 5 | ifdef CONFIG_ALINK_ENABLE 6 | 7 | COMPONENT_ADD_INCLUDEDIRS := include adaptation/include 8 | COMPONENT_SRCDIRS := adaptation application 9 | 10 | ifdef CONFIG_ALINK_VERSION_EMBED 11 | LIBS := $(dirname $(COMPONENT_PATH)) alink_agent tfspal 12 | endif 13 | 14 | ifdef CONFIG_ALINK_VERSION_SDS 15 | LIBS := $(dirname $(COMPONENT_PATH)) alink_agent_sds tfspal 16 | endif 17 | 18 | COMPONENT_ADD_LDFLAGS += -L $(COMPONENT_PATH)/lib \ 19 | $(addprefix -l,$(LIBS)) 20 | 21 | endif 22 | -------------------------------------------------------------------------------- /include/alink_export.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. 3 | * 4 | * Alibaba Group retains all right, title and interest (including all 5 | * intellectual property rights) in and to this computer program, which is 6 | * protected by applicable intellectual property laws. Unless you have 7 | * obtained a separate written license from Alibaba Group., you are not 8 | * authorized to utilize all or a part of this computer program for any 9 | * purpose (including reproduction, distribution, modification, and 10 | * compilation into object code), and you must immediately destroy or 11 | * return to Alibaba Group all copies of this computer program. If you 12 | * are licensed by Alibaba Group, your rights to utilize this computer 13 | * program are limited by the terms of that license. To obtain a license, 14 | * please contact Alibaba Group. 15 | * 16 | * This computer program contains trade secrets owned by Alibaba Group. 17 | * and, unless unauthorized by Alibaba Group in writing, you agree to 18 | * maintain the confidentiality of this computer program and related 19 | * information and to not disclose this computer program and related 20 | * information to any other person or entity. 21 | * 22 | * THIS COMPUTER PROGRAM IS PROVIDED AS IS WITHOUT ANY WARRANTIES, AND 23 | * Alibaba Group EXPRESSLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, 24 | * INCLUDING THE WARRANTIES OF MERCHANTIBILITY, FITNESS FOR A PARTICULAR 25 | * PURPOSE, TITLE, AND NONINFRINGEMENT. 26 | */ 27 | 28 | #ifndef _ALINK_EXPORT_H_ 29 | #define _ALINK_EXPORT_H_ 30 | 31 | #if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ 32 | extern "C" 33 | { 34 | #endif 35 | 36 | /** @defgroup wifi_device wifi device API 37 | * @{ 38 | */ 39 | 40 | 41 | /** @defgroup wifi_debug debug 42 | * @{ 43 | */ 44 | 45 | /** 46 | * log level def. 47 | */ 48 | enum ALINK_LOG_LEVEL { 49 | ALINK_LL_NONE, /**< disable log */ 50 | ALINK_LL_FATAL, /**< fatal error log will output */ 51 | ALINK_LL_ERROR, /**< error + fatal log will output */ 52 | ALINK_LL_WARN, /**< warn + error + fatal log will output(default level) */ 53 | ALINK_LL_INFO, /**< info + warn + error + fatal log will output */ 54 | ALINK_LL_DEBUG, /**< debug + info + warn + error + fatal log will output */ 55 | ALINK_LL_TRACE, /**< trace + debug + info + warn + error + fatal will output */ 56 | }; 57 | 58 | /** 59 | * @brief log level control 60 | * 61 | * @param[in] loglevel 62 | * @return None. 63 | * @see enum ALINK_LOG_LEVEL. 64 | * @note None. 65 | */ 66 | void alink_set_loglevel(enum ALINK_LOG_LEVEL loglevel); 67 | 68 | /** 69 | * @brief enable sandbox mode, for debug 70 | * 71 | * @param None. 72 | * @retval 0 on success, otherwise -1 will return 73 | * @see None. 74 | * @note None. 75 | */ 76 | int alink_enable_sandbox_mode(void); 77 | 78 | /** 79 | * @brief enable daily mode, for debug 80 | * 81 | * @param None. 82 | * @retval 0 on success, otherwise -1 will return 83 | * @see None. 84 | * @note None. 85 | */ 86 | int alink_enable_daily_mode(const char *server_ip, int port); 87 | 88 | /** @} */ //end of debug 89 | 90 | 91 | 92 | /** @defgroup wifi_entry main 93 | * @{ 94 | */ 95 | 96 | /** 97 | * @brief entry function. start alink gateway service. 98 | * 99 | * @param None. 100 | * @retval 0 on success, otherwise -1 will return 101 | * @see None. 102 | * @note None. 103 | */ 104 | int alink_start(void); 105 | 106 | #define ALINK_WAIT_FOREVER (0) 107 | /** 108 | * @brief waiting alink connect to aliyun server 109 | * 110 | * @param[in] timeout_ms: time in milliseconds, 111 | * use ALINK_WAIT_FOREVER to wait until aliyun server is connected 112 | * @retval 0 when connect to server successfully, otherwise -1 will return 113 | * @see None. 114 | * @note None. 115 | */ 116 | int alink_wait_connect(int timeout_ms); 117 | 118 | /** 119 | * @brief destroy alink service and free resources 120 | * 121 | * @param None. 122 | * @retval 0 on success, otherwise -1 will return 123 | * @see None. 124 | * @note this func will block at most 15 seconds to 125 | * stop all alink related process(thread) 126 | */ 127 | int alink_end(void); 128 | 129 | /** 130 | * @brief reset user account binding. 131 | * 132 | * @retval 0 on success, -1 when params invalid 133 | * @see None. 134 | * @note None. 135 | */ 136 | int alink_factory_reset(void); 137 | 138 | /** @} */ //end of entry 139 | 140 | /** @defgroup wifi_report report status 141 | * @{ 142 | */ 143 | 144 | /** 145 | * @brief report alink message, it is a fundamental func. 146 | * 147 | * @param[in] method: alink protocol method, 148 | * i.e. "postDeviceRawData", "postDeviceData". 149 | * @param[in] json_buffer: json format buffer, like 150 | * {"OnOff":"1", "Light":"80"} for ""postDeviceData", 151 | * or {"rawData":"F5F5F5F50100041501","length":"20"} for "postDeviceRawData" 152 | * @retval 0 when successfully got response from cloud, 153 | * otherwise this func will block until timeout and -1 will return 154 | * @see None. 155 | * @note when connection with server is unstable, this func will block 156 | * until got response from server or timeout. 157 | */ 158 | int alink_report(const char *method, const char *json_buffer); 159 | 160 | /** 161 | * @brief query alink cloud service, like getAlinkTime... 162 | * 163 | * @param[in] method: alink protocol method, 164 | * i.e. "getAlinkTime", "retrieveDeviceData". 165 | * @param[in] json_buffer: json format buffer, like {} for "getAlinkTime", 166 | * or {"dataKey":"param_probe_num"} for "retrieveDeviceData" 167 | * @param[in] result_buf: to hold json string return from cloud 168 | * @param[in/out] buf_len: [in] size of result_buf, [out] strlen of json string 169 | * return from cloud 170 | * @retval 0 when successfully got response from cloud, 171 | * otherwise this func will block until timeout and -1 will return 172 | * @see None. 173 | * @note when connection with server is unstable, this func will block 174 | * until got response from server or timeout. 175 | */ 176 | int alink_query(const char *method, const char *json_buffer, 177 | char *result_buf, int *buf_len); 178 | 179 | /** @} */ //end of report 180 | 181 | /** @defgroup wifi_callback callback 182 | * @{ 183 | */ 184 | 185 | /** 186 | * alink callback event 187 | */ 188 | enum ALINK_WIFI_CALLBACK { 189 | /** 190 | * void callback_cloud_connected(void) 191 | * @n@n called each time when gateway successfully connect(or reconnect) 192 | * to aliyun server 193 | */ 194 | ALINK_CLOUD_CONNECTED = 0, 195 | 196 | /** 197 | * void callback_cloud_disconnected(void) 198 | * @n@n called each time when gateway lose connection with aliyun server 199 | */ 200 | ALINK_CLOUD_DISCONNECTED, 201 | /** 202 | * int callback_read_device_status(const char *params) 203 | * @n@nuccessfully 204 | */ 205 | ALINK_GET_DEVICE_STATUS, 206 | 207 | /** 208 | * void callback_write_device_status(const char *params) 209 | */ 210 | ALINK_SET_DEVICE_STATUS, 211 | /** 212 | * int callback_read_device_rawdata(const char *params) 213 | * @n@nuccessfully 214 | */ 215 | ALINK_GET_DEVICE_RAWDATA, 216 | 217 | /** 218 | * void callback_write_device_rawdata(const char *params) 219 | */ 220 | ALINK_SET_DEVICE_RAWDATA, 221 | }; 222 | 223 | /** 224 | * @brief register misc callback 225 | * 226 | * @param[in] cb_type: callback type. 227 | * @param[in] cb_func: callback func pointer, func declaration see related comments. 228 | * 229 | * @retval 0 on success, otherwise -1 will return 230 | * @see enum ALINK_WIFI_CALLBACK. 231 | * @note None. 232 | */ 233 | int alink_register_callback(unsigned char cb_type, void *cb_func); 234 | /** @} */ //end of callback 235 | 236 | /** @defgroup wifi_awss awss 237 | * @{ 238 | */ 239 | 240 | /** 241 | * @brief start awss service, block method, 242 | * block until awss succeed, or timeout(see Note). 243 | * 244 | * @return 0 on success, otherwise non-zero value will return 245 | @verbatim 246 | = 0: connect AP & DHCP success 247 | = -1: get ssid & passwd fail 248 | = -2: connect AP / DHCP fail 249 | @endverbatim 250 | * @see None. 251 | * @note platform_awss_get_timeout_interval_ms() return monitor timeout interval, 252 | * AP connection timeout is 30s. 253 | */ 254 | int awss_start(void); 255 | 256 | /** 257 | * @brief calling this func force awss_start exit. 258 | * 259 | * @param None. 260 | * @retval 0 on success, otherwise -1 will return 261 | * @see None. 262 | * @note None. 263 | */ 264 | int awss_stop(void); 265 | 266 | /** @} */ //end of awss 267 | 268 | #endif 269 | -------------------------------------------------------------------------------- /include/alink_json_parser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015 Alibaba Group. All rights reserved. 3 | * 4 | * Alibaba Group retains all right, title and interest (including all 5 | * intellectual property rights) in and to this computer program, which is 6 | * protected by applicable intellectual property laws. Unless you have 7 | * obtained a separate written license from Alibaba Group., you are not 8 | * authorized to utilize all or a part of this computer program for any 9 | * purpose (including reproduction, distribution, modification, and 10 | * compilation into object code), and you must immediately destroy or 11 | * return to Alibaba Group all copies of this computer program. If you 12 | * are licensed by Alibaba Group, your rights to utilize this computer 13 | * program are limited by the terms of that license. To obtain a license, 14 | * please contact Alibaba Group. 15 | * 16 | * This computer program contains trade secrets owned by Alibaba Group. 17 | * and, unless unauthorized by Alibaba Group in writing, you agree to 18 | * maintain the confidentiality of this computer program and related 19 | * information and to not disclose this computer program and related 20 | * information to any other person or entity. 21 | * 22 | * THIS COMPUTER PROGRAM IS PROVIDED AS IS WITHOUT ANY WARRANTIES, AND 23 | * Alibaba Group EXPRESSLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, 24 | * INCLUDING THE WARRANTIES OF MERCHANTIBILITY, FITNESS FOR A PARTICULAR 25 | * PURPOSE, TITLE, AND NONINFRINGEMENT. 26 | */ 27 | 28 | #ifndef __ALINK_JSON_PARSER_H__ 29 | #define __ALINK_JSON_PARSER_H__ 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | /** 36 | The descriptions of the json value node type 37 | **/ 38 | enum JSONTYPE { 39 | JNONE = -1, 40 | JSTRING = 0, 41 | JOBJECT, 42 | JARRAY, 43 | JNUMBER, 44 | JTYPEMAX 45 | }; 46 | 47 | /** 48 | The error codes produced by the JSON parsers 49 | **/ 50 | enum JSON_PARSE_CODE { 51 | JSON_PARSE_ERR, 52 | JSON_PARSE_OK, 53 | JSON_PARSE_FINISH 54 | }; 55 | 56 | /** 57 | The return codes produced by the JSON parsers 58 | **/ 59 | enum JSON_PARSE_RESULT { 60 | JSON_RESULT_ERR = -1, 61 | JSON_RESULT_OK 62 | }; 63 | 64 | #define JSON_DEBUG 0 65 | typedef int (*json_parse_cb)(char *p_cName, int iNameLen, char *p_cValue, int iValueLen, int iValueType, void *p_Result); 66 | 67 | /** 68 | * @brief Parse the JSON string, and iterate through all keys and values, 69 | * then handle the keys and values by callback function. 70 | * 71 | * @param[in] p_cJsonStr @n The JSON string 72 | * @param[in] iStrLen @n The JSON string length 73 | * @param[in] pfnCB @n Callback function 74 | * @param[out] p_CBData @n User data 75 | * @return JSON_RESULT_OK success, JSON_RESULT_ERR failed 76 | * @see None. 77 | * @note None. 78 | **/ 79 | int json_parse_name_value(char *p_cJsonStr, int iStrLen, json_parse_cb pfnCB, void *p_CBData); 80 | 81 | /** 82 | * @brief Get the value by a specified key from a json string 83 | * 84 | * @param[in] p_cJsonStr @n the JSON string 85 | * @param[in] iStrLen @n the JSON string length 86 | * @param[in] p_cName @n the specified key string 87 | * @param[out] p_iValueLen @n the value length 88 | * @param[out] p_iValueType @n the value type 89 | * @return A pointer to the value 90 | * @see None. 91 | * @note None. 92 | **/ 93 | char *json_get_value_by_name(char *p_cJsonStr, int iStrLen, char *p_cName, int *p_iValueLen, int *p_iValueType); 94 | 95 | /** 96 | * @brief Get the length of a json string 97 | * 98 | * @param[in] json_str @n The JSON string 99 | * @param[in] str_len @n The JSON string length 100 | * @returns Array size 101 | * @see None. 102 | * @note None. 103 | **/ 104 | int json_get_array_size(char *json_str, int str_len); 105 | 106 | /** 107 | * @brief Get the JSON object point associate with a given type. 108 | * 109 | * @param[in] type @n The object type 110 | * @param[in] str @n The JSON string 111 | * @returns The json object point with the given field type. 112 | * @see None. 113 | * @note None. 114 | */ 115 | char *json_get_object(int type, char *str); 116 | char *json_get_next_object(int type, char *str, char **key, int *key_len, char **val, int *val_len, int *val_type); 117 | /** 118 | * @brief retrieve each key&value pair from the json string 119 | * 120 | * @param[in] str @n Json string to revolve 121 | * @param[in] pos @n cursor 122 | * @param[out] key @n pointer to the next Key object 123 | * @param[out] klen @n Key object length 124 | * @param[out] val @n pointer to the next Value object 125 | * @param[out] vlen @n Value object length 126 | * @param[out] vtype @n Value object type(digital, string, object, array) 127 | * @see None. 128 | * @note None. 129 | */ 130 | #define json_object_for_each_kv(str, pos, key, klen, val, vlen, vtype) \ 131 | for (pos = json_get_object(JOBJECT, str); \ 132 | pos!=0 && *pos!=0 && (pos=json_get_next_object(JOBJECT, pos, &key, &klen, &val, &vlen, &vtype))!=0; ) 133 | 134 | /** 135 | * @brief retrieve each entry from the json array 136 | * 137 | * @param[in] str @n Json array to revolve 138 | * @param[in] pos @n cursor 139 | * @param[out] entry @n pointer to the next entry from the array 140 | * @param[out] len @n entry length 141 | * @param[out] type @n entry type(digital, string, object, array) 142 | * @see None. 143 | * @note None. 144 | */ 145 | #define json_array_for_each_entry(str, pos, entry, len, type) \ 146 | for (pos = json_get_object(JARRAY, str); \ 147 | pos!=0 && *pos!=0 && (pos=json_get_next_object(JARRAY, ++pos, 0, 0, &entry, &len, &type))!=0; ) 148 | 149 | #ifdef __cplusplus 150 | } 151 | #endif 152 | 153 | #endif 154 | -------------------------------------------------------------------------------- /include/esp_alink.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2017 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #ifndef __ESP_ALINK_H__ 26 | #define __ESP_ALINK_H__ 27 | 28 | #include "esp_system.h" 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | typedef int32_t alink_err_t; 35 | 36 | #ifndef ALINK_TRUE 37 | #define ALINK_TRUE 1 38 | #endif 39 | #ifndef ALINK_FALSE 40 | #define ALINK_FALSE 0 41 | #endif 42 | #ifndef ALINK_OK 43 | #define ALINK_OK 0 44 | #endif 45 | #ifndef ALINK_ERR 46 | #define ALINK_ERR -1 47 | #endif 48 | 49 | #ifndef _IN_ 50 | #define _IN_ /*!< indicate that this is a input parameter. */ 51 | #endif 52 | #ifndef _OUT_ 53 | #define _OUT_ /*!< indicate that this is a output parameter. */ 54 | #endif 55 | #ifndef _INOUT_ 56 | #define _INOUT_ /*!< indicate that this is a io parameter. */ 57 | #endif 58 | #ifndef _IN_OPT_ 59 | #define _IN_OPT_ /*!< indicate that this is a optional input parameter. */ 60 | #endif 61 | #ifndef _OUT_OPT_ 62 | #define _OUT_OPT_ /*!< indicate that this is a optional output parameter. */ 63 | #endif 64 | #ifndef _INOUT_OPT_ 65 | #define _INOUT_OPT_ /*!< indicate that this is a optional io parameter. */ 66 | #endif 67 | 68 | #ifndef CONFIG_WIFI_WAIT_TIME 69 | #define CONFIG_WIFI_WAIT_TIME 60 70 | #endif 71 | 72 | #ifndef CONFIG_ALINK_DATA_LEN 73 | #define CONFIG_ALINK_DATA_LEN 1024 74 | #endif 75 | 76 | #ifndef CONFIG_ALINK_TASK_PRIOTY 77 | #define CONFIG_ALINK_TASK_PRIOTY 6 78 | #endif 79 | 80 | #ifndef CONFIG_DOWN_CMD_QUEUE_NUM 81 | #define CONFIG_DOWN_CMD_QUEUE_NUM 3 82 | #endif 83 | 84 | #ifndef CONFIG_UP_CMD_QUEUE_NUM 85 | #define CONFIG_UP_CMD_QUEUE_NUM 3 86 | #endif 87 | 88 | #ifndef CONFIG_EVENT_STACK_SIZE 89 | #define CONFIG_EVENT_STACK_SIZE 4096 90 | #endif 91 | 92 | #ifndef CONFIG_ALINK_POST_DATA_STACK_SIZE 93 | #define CONFIG_ALINK_POST_DATA_STACK_SIZE 4096 94 | #endif 95 | 96 | #ifndef CONFIG_ALINK_CHIPID 97 | #define CONFIG_ALINK_CHIPID "esp32" 98 | #endif 99 | 100 | #ifndef CONFIG_ALINK_MODULE_NAME 101 | #define CONFIG_ALINK_MODULE_NAME "ESP-WROOM-32" 102 | #endif 103 | 104 | #define ALINK_CHIPID CONFIG_ALINK_CHIPID 105 | #define ALINK_MODULE_NAME CONFIG_ALINK_MODULE_NAME 106 | 107 | #define WIFI_WAIT_TIME (CONFIG_WIFI_WAIT_TIME * 1000) 108 | #define ALINK_DATA_LEN CONFIG_ALINK_DATA_LEN 109 | #define DEFAULU_TASK_PRIOTY CONFIG_ALINK_TASK_PRIOTY 110 | #define ALINK_EVENT_STACK_SIZE CONFIG_ALINK_EVENT_STACK_SIZE 111 | #define ALINK_POST_DATA_STACK_SIZE CONFIG_ALINK_POST_DATA_STACK_SIZE 112 | 113 | #define DOWN_CMD_QUEUE_NUM CONFIG_DOWN_CMD_QUEUE_NUM 114 | #define UP_CMD_QUEUE_NUM CONFIG_UP_CMD_QUEUE_NUM 115 | 116 | #ifdef CONFIG_ALINK_WRITE_NOT_BUFFER 117 | #define ALINK_WRITE_NOT_BUFFER 118 | #endif 119 | 120 | typedef enum { 121 | ALINK_EVENT_CLOUD_CONNECTED = 0,/*!< ESP32 connected from alink cloude */ 122 | ALINK_EVENT_CLOUD_DISCONNECTED, /*!< ESP32 disconnected from alink cloude */ 123 | ALINK_EVENT_GET_DEVICE_DATA, /*!< Alink cloud requests data from the device */ 124 | ALINK_EVENT_SET_DEVICE_DATA, /*!< Alink cloud to send data to the device */ 125 | ALINK_EVENT_POST_CLOUD_DATA, /*!< The device sends data to alink cloud */ 126 | ALINK_EVENT_POST_CLOUD_DATA_FAIL, /*!< The device sends data to alink cloud fialed */ 127 | ALINK_EVENT_WIFI_CONNECTED, /*!< ESP32 station got IP from connected AP */ 128 | ALINK_EVENT_WIFI_DISCONNECTED, /*!< ESP32 station disconnected from AP */ 129 | ALINK_EVENT_CONFIG_NETWORK, /*!< The equipment enters the distribution mode */ 130 | ALINK_EVENT_UPDATE_ROUTER, /*!< Request to configure the router */ 131 | ALINK_EVENT_FACTORY_RESET, /*!< Request to restore factory settings */ 132 | ALINK_EVENT_ACTIVATE_DEVICE, /*!< Request activation device */ 133 | } alink_event_t; 134 | 135 | typedef struct alink_product { 136 | const char *name; 137 | const char *model; 138 | const char *version; 139 | const char *key; 140 | const char *secret; 141 | const char *key_sandbox; 142 | const char *secret_sandbox; 143 | const char *key_device; 144 | const char *secret_device; 145 | } alink_product_t; 146 | 147 | #define alink_malloc(num_bytes) ({void *ptr = malloc(num_bytes); \ 148 | ALINK_LOGV("malloc size: %d, ptr: %p, heap free: %d", num_bytes, ptr, esp_get_free_heap_size()); ptr;}) 149 | 150 | #define alink_calloc(n, size) ({void *ptr = calloc(n, size); \ 151 | ALINK_LOGV("calloc size: %d, ptr: %p, heap free: %d", n * size, ptr, esp_get_free_heap_size()); ptr;}) 152 | 153 | #define alink_free(arg) {if(arg){ free(arg); \ 154 | ALINK_LOGV("free ptr: %p, heap free: %d", arg, esp_get_free_heap_size()); arg = NULL;}}while(0) 155 | 156 | /** 157 | * @brief Application specified event callback function 158 | * 159 | * @param event event type defined in this file 160 | * 161 | * @note The memory space for the event callback function defaults to 4kBety 162 | * 163 | * @return 164 | * - ALINK_OK : Succeed 165 | * - others : fail 166 | */ 167 | typedef alink_err_t (*alink_event_cb_t)(alink_event_t event); 168 | 169 | /** 170 | * @brief Send the event to the event handler 171 | * 172 | * @param event Generated events 173 | * 174 | * @return 175 | * - ALINK_OK : Succeed 176 | * - ALINK_ERR : Fail 177 | */ 178 | alink_err_t alink_event_send(alink_event_t event); 179 | 180 | /** 181 | * @brief Initialize alink config and start alink task 182 | * Initialize event loop Create the event handler and task 183 | * 184 | * @param product_info config provice alink init configuration 185 | * event_handler_cb application specified event callback 186 | * 187 | * @return 188 | * - ALINK_OK : Succeed 189 | * - ALINK_ERR : Fail 190 | */ 191 | alink_err_t alink_init(_IN_ const void *product_info, 192 | _IN_ const alink_event_cb_t event_handler_cb); 193 | 194 | /** 195 | * @brief attempts to read up to count bytes from file descriptor fd into the 196 | * buffer starting at buf. 197 | * 198 | * @param up_cmd Store the read data 199 | * @param size Write the size of the data 200 | * @param micro_seconds seconds before the function timeout, set to -1 if wait forever 201 | * 202 | * @return 203 | * - ALINK_ERR : Error, errno is set appropriately 204 | * - Others : Write the size of the data 205 | */ 206 | ssize_t alink_write(_IN_ const void *up_cmd, size_t size, int micro_seconds); 207 | 208 | /** 209 | * @brief attempts to read up to count bytes from file descriptor fd into the 210 | * buffer starting at buf. 211 | * 212 | * @param down_cmd Store the read data 213 | * @param size Read the size of the data 214 | * @param micro_seconds seconds before the function timeout, set to -1 if wait forever 215 | * 216 | * @return 217 | * - ALINK_ERR : Error, errno is set appropriately 218 | * - Others : Read the size of the data 219 | */ 220 | ssize_t alink_read(_OUT_ void *down_cmd, size_t size, int micro_seconds); 221 | 222 | /** 223 | * @brief Clear wifi information, restart the device into the config network mode 224 | * 225 | * @return 226 | * - ALINK_OK : Succeed 227 | * - ALINK_ERR : Fail 228 | */ 229 | alink_err_t alink_update_router(); 230 | 231 | /** 232 | * @brief Clear all the information of the device and return to the factory status 233 | * 234 | * @return 235 | * - ALINK_OK : Succeed 236 | * - ALINK_ERR : Fail 237 | */ 238 | alink_err_t alink_factory_setting(); 239 | 240 | #ifdef __cplusplus 241 | } 242 | #endif 243 | 244 | #endif 245 | -------------------------------------------------------------------------------- /include/esp_alink_log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2017 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #ifndef __ESP_ALINK_LOG_H__ 26 | #define __ESP_ALINK_LOG_H__ 27 | 28 | #include "esp_log.h" 29 | #include "errno.h" 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | #ifndef CONFIG_LOG_ALINK_LEVEL 36 | #define CONFIG_LOG_ALINK_LEVEL CONFIG_LOG_DEFAULT_LEVEL 37 | #endif 38 | #ifndef CONFIG_LOG_ALINK_SDK_LEVEL 39 | #define CONFIG_LOG_ALINK_SDK_LEVEL ALINK_LL_DEBUG 40 | #endif 41 | 42 | #undef LOG_LOCAL_LEVEL 43 | #define LOG_LOCAL_LEVEL CONFIG_LOG_ALINK_LEVEL 44 | #define ALINK_SDK_LOG_LEVEL CONFIG_LOG_ALINK_SDK_LEVEL 45 | 46 | #define ALINK_LOGE( format, ... ) ESP_LOGE(TAG, "[%s, %d]:" format, __func__, __LINE__, ##__VA_ARGS__) 47 | #define ALINK_LOGW( format, ... ) ESP_LOGW(TAG, "[%s, %d]:" format, __func__, __LINE__, ##__VA_ARGS__) 48 | #define ALINK_LOGI( format, ... ) ESP_LOGI(TAG, format, ##__VA_ARGS__) 49 | #define ALINK_LOGD( format, ... ) ESP_LOGD(TAG, "[%s, %d]:" format, __func__, __LINE__, ##__VA_ARGS__) 50 | #define ALINK_LOGV( format, ... ) ESP_LOGV(TAG, "[%s, %d]:" format, __func__, __LINE__, ##__VA_ARGS__) 51 | 52 | /** 53 | * @brief Check the return value 54 | */ 55 | #define ALINK_ERROR_CHECK(con, err, format, ...) do { \ 56 | if (con) { \ 57 | ALINK_LOGE(format , ##__VA_ARGS__); \ 58 | if(errno) ALINK_LOGE("errno: %d, errno_str: %s\n", errno, strerror(errno)); \ 59 | return err; \ 60 | } \ 61 | }while (0) 62 | 63 | #define ALINK_ERROR_GOTO(con, lable, format, ...) do { \ 64 | if (con) { \ 65 | ALINK_LOGE(format , ##__VA_ARGS__); \ 66 | if(errno) ALINK_LOGE("errno: %d, errno_str: %s\n", errno, strerror(errno)); \ 67 | goto lable; \ 68 | } \ 69 | }while (0) 70 | 71 | /** 72 | * @brief check param 73 | */ 74 | #define ALINK_PARAM_CHECK(con) do { \ 75 | if (!(con)) { ALINK_LOGE("parameter error: %s", #con); return ALINK_ERR; } \ 76 | } while (0) 77 | 78 | /** 79 | * @brief Set breakpoint 80 | */ 81 | #define ALINK_ASSERT(con) do { \ 82 | if (!(con)) { ALINK_LOGE("errno:%d:%s\n", errno, strerror(errno)); assert(0 && #con); } \ 83 | } while (0) 84 | 85 | #ifdef __cplusplus 86 | } 87 | #endif 88 | 89 | #endif/*!< __ESP_ALINK_LOG_H__ */ 90 | 91 | -------------------------------------------------------------------------------- /include/esp_info_store.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2017 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #ifndef __ESP_INFO_STORE_H__ 26 | #define __ESP_INFO_STORE_H__ 27 | 28 | #include 29 | #include "esp_alink.h" 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | #define ALINK_SPACE_NAME "ALINK_APP" 36 | #define NVS_KEY_WIFI_CONFIG "wifi_config" 37 | 38 | /** 39 | * @brief Erase the alink's information 40 | * 41 | * @param key the corresponding key, it will find the target type by the key 42 | * 43 | * @return 44 | * - alink_ERR : Error, errno is set appropriately 45 | * - alink_OK : Success 46 | */ 47 | alink_err_t esp_info_erase(const char *key); 48 | 49 | /** 50 | * @brief Save the alink's information 51 | * 52 | * @param key the corresponding key, it will find the target type by the key 53 | * @param value the value to be saved in the target information 54 | * @param length the length of the value 55 | * 56 | * - alink_ERR : Error, errno is set appropriately 57 | * - others : The length of the stored information 58 | */ 59 | ssize_t esp_info_save(const char *key, const void *value, size_t length); 60 | 61 | /** 62 | * @brief Load the alink's information 63 | * 64 | * @param key the corresponding key, it will find the target type by the key 65 | * @param value the value to be saved in the target information 66 | * @param length the length of the value 67 | * 68 | * - alink_ERR : Error, errno is set appropriately 69 | * - others : The length of the stored information 70 | */ 71 | ssize_t esp_info_load(const char *key, void *value, size_t length); 72 | 73 | /****************************** example ******************************/ 74 | /* 75 | void info_store() 76 | { 77 | esp_info_init(); 78 | char buf[16] = "12345678910"; 79 | 80 | esp_info_save("test_buf", buf, sizeof(buf)); 81 | memset(buf, 0, sizeof(buf)); 82 | int ret = esp_info_load("test_buf", buf, sizeof(buf)); 83 | printf("ret: %d, buf: %s\n", ret, buf); 84 | 85 | esp_info_erase("test_buf"); 86 | memset(buf, 0, sizeof(buf)); 87 | ret = esp_info_load("test_buf", buf, sizeof(buf)); 88 | printf("ret: %d, buf: %s\n", ret, buf); 89 | } 90 | */ 91 | 92 | #ifdef __cplusplus 93 | } 94 | #endif 95 | 96 | #endif /* __ESP_INFO_STORE_H__ */ 97 | -------------------------------------------------------------------------------- /include/esp_json_parser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2017 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #ifndef __ESP_JOSN_PARSER_H__ 26 | #define __ESP_JOSN_PARSER_H__ 27 | 28 | #include "esp_system.h" 29 | #include "esp_alink_log.h" 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif /*!< _cplusplus */ 34 | 35 | /** 36 | * @brief This api is used only for alink json internal use 37 | */ 38 | alink_err_t __esp_json_parse(const char *json_str, const char *key, void *value, int value_type); 39 | alink_err_t __esp_json_pack(char *json_str, const char *key, int value, int value_type); 40 | 41 | /** 42 | * @brief alink_err_t esp_json_parse(const char *json_str, const char *key, void *value) 43 | * Parse the json formatted string 44 | * 45 | * @param json_str The string pointer to be parsed 46 | * @param key Nuild value pairs 47 | * @param value You must ensure that the incoming type is consistent with the 48 | * post-resolution type 49 | * 50 | * @note Does not support the analysis of array types 51 | * 52 | * @return 53 | * - ALINK_OK Success 54 | * - ALINK_ERR Parameter error 55 | */ 56 | #define esp_json_parse(json_str, key, value) \ 57 | __esp_json_parse((const char *)(json_str), (const char *)(key), value, \ 58 | __builtin_types_compatible_p(typeof(value), short *) * 1\ 59 | + __builtin_types_compatible_p(typeof(value), int *) * 1\ 60 | + __builtin_types_compatible_p(typeof(value), uint16_t *) * 1\ 61 | + __builtin_types_compatible_p(typeof(value), uint32_t *) * 1\ 62 | + __builtin_types_compatible_p(typeof(value), float *) * 2\ 63 | + __builtin_types_compatible_p(typeof(value), double *) * 3) 64 | 65 | /** 66 | * @brief esp_json_pack(char *json_str, const char *key, int/double/char value); 67 | * Create a json string 68 | * 69 | * @param json_str Save the generated json string 70 | * @param key Build value pairs 71 | * @param value This is a generic, support int/double/char/char * 72 | * 73 | * @note If the value is double or float type only retains the integer part, 74 | * requires complete data calling esp_json_pack_double() 75 | * 76 | * @return 77 | * - generates the length of the json string Success 78 | * - ALINK_ERR Parameter error 79 | */ 80 | #define esp_json_pack(json_str, key, value) \ 81 | __esp_json_pack((char *)(json_str), (const char *)(key), (int)(value), \ 82 | __builtin_types_compatible_p(typeof(value), char) * 1\ 83 | + __builtin_types_compatible_p(typeof(value), short) * 1\ 84 | + __builtin_types_compatible_p(typeof(value), int) * 1\ 85 | + __builtin_types_compatible_p(typeof(value), uint8_t) * 1\ 86 | + __builtin_types_compatible_p(typeof(value), uint16_t) * 1\ 87 | + __builtin_types_compatible_p(typeof(value), uint32_t) * 1\ 88 | + __builtin_types_compatible_p(typeof(value), float) * 2\ 89 | + __builtin_types_compatible_p(typeof(value), double) * 2\ 90 | + __builtin_types_compatible_p(typeof(value), char *) * 3\ 91 | + __builtin_types_compatible_p(typeof(value), const char *) * 3\ 92 | + __builtin_types_compatible_p(typeof(value), unsigned char *) * 3\ 93 | + __builtin_types_compatible_p(typeof(value), const unsigned char *) * 3) 94 | 95 | /** 96 | * @brief Create a double type json string, Make up for the lack of esp_json_pack() 97 | * 98 | * @param json_str Save the generated json string 99 | * @param key Build value pairs 100 | * @param value The value to be stored 101 | * 102 | * @return 103 | * - generates the length of the json string Success 104 | * - ALINK_ERR Parameter error 105 | */ 106 | alink_err_t esp_json_pack_double(char *json_str, const char *key, double value); 107 | 108 | /****************************** example ******************************/ 109 | /* 110 | static void esp_json_test() 111 | { 112 | int ret = 0; 113 | char *json_root = (char *)alink_calloc(1, 512); 114 | char *json_sub = (char *)alink_calloc(1, 64); 115 | int valueint = 0; 116 | char valuestring[20]; 117 | double valuedouble = 0; 118 | 119 | // { 120 | // "key0": 0, 121 | // "key1": "tmp1", 122 | // "key4": { 123 | // "key2": { 124 | // "name": "json test" 125 | // }, 126 | // "key3": 1 127 | // }, 128 | // "key5": 99.00000, 129 | // "key6": 99.23456 130 | // } 131 | ret = esp_json_pack(json_root, "key0", valueint++); 132 | ret = esp_json_pack(json_root, "key1", "tmp1"); 133 | ret = esp_json_pack(json_sub, "key2", "{\"name\":\"json test\"}"); 134 | ret = esp_json_pack(json_sub, "key3", valueint++); 135 | ret = esp_json_pack(json_root, "key4", json_sub); 136 | ret = esp_json_pack(json_root, "key5", 99.23456); 137 | ret = esp_json_pack_double(json_root, "key6", 99.23456); 138 | printf("json_len: %d, json: %s\n", ret, json_root); 139 | 140 | printf("------------- json parse -----------\n"); 141 | 142 | esp_json_parse(json_root, "key0", &valueint); 143 | printf("key0: %d\n", valueint); 144 | esp_json_parse(json_root, "key1", valuestring); 145 | printf("key1: %s\n", valuestring); 146 | esp_json_parse(json_root, "key4", json_sub); 147 | printf("key4: %s\n", json_sub); 148 | 149 | esp_json_parse(json_sub, "key2", valuestring); 150 | printf("key2: %s\n", valuestring); 151 | esp_json_parse(json_sub, "key3", &valueint); 152 | printf("key3: %d\n", valueint); 153 | esp_json_parse(json_root, "key5", &valueint); 154 | printf("key5: %d\n", valueint); 155 | // CJson floating point type handling problems, later will be fixed 156 | esp_json_parse(json_root, "key6", &valuedouble); 157 | 158 | // printf can not output double type 159 | char double_char[16] = {0}; 160 | sprintf(double_char, "%lf", valuedouble); 161 | printf("key6: %s\n", double_char); 162 | 163 | alink_free(json_root); 164 | alink_free(json_sub); 165 | } 166 | */ 167 | 168 | #ifdef __cplusplus 169 | } 170 | #endif /*!< _cplusplus */ 171 | 172 | #endif /*!< __ESP_JOSN_PARSER_H__ */ 173 | -------------------------------------------------------------------------------- /lib/libalink_agent.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espressif/esp32-alink/c1284d48b2ea9b8cc92926e5e3fe9708ae80c61a/lib/libalink_agent.a -------------------------------------------------------------------------------- /lib/libalink_agent_sds.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espressif/esp32-alink/c1284d48b2ea9b8cc92926e5e3fe9708ae80c61a/lib/libalink_agent_sds.a -------------------------------------------------------------------------------- /lib/libtfspal.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espressif/esp32-alink/c1284d48b2ea9b8cc92926e5e3fe9708ae80c61a/lib/libtfspal.a --------------------------------------------------------------------------------