diff --git a/components/esp8266/CMakeLists.txt b/components/esp8266/CMakeLists.txt index ff2f4269..22615a57 100644 --- a/components/esp8266/CMakeLists.txt +++ b/components/esp8266/CMakeLists.txt @@ -32,6 +32,8 @@ else() "source/crc.c" "source/phy_init.c" "source/reset_reason.c" + "source/smartconfig.c" + "source/smartconfig_ack.c" "source/startup.c" "source/system_api.c" "source/task_wdt.c" diff --git a/components/esp8266/include/esp_private/wifi.h b/components/esp8266/include/esp_private/wifi.h index 8c8042c6..170262df 100644 --- a/components/esp8266/include/esp_private/wifi.h +++ b/components/esp8266/include/esp_private/wifi.h @@ -18,6 +18,7 @@ #include "esp_wifi_types.h" #include "esp_event.h" #include "esp_wifi.h" +#include "esp_smartconfig.h" #ifdef __cplusplus extern "C" { @@ -39,7 +40,7 @@ typedef enum { WIFI_LOG_DEBUG, /*can be set in menuconfig*/ WIFI_LOG_VERBOSE, /*can be set in menuconfig*/ } wifi_log_level_t; - + /** * @brief WiFi log submodule definition * @@ -81,7 +82,7 @@ typedef enum { * - ESP_ERR_NO_MEM: out of memory * - others: refer to error code esp_err.h */ -esp_err_t esp_wifi_init_internal(const wifi_init_config_t *config); +esp_err_t esp_wifi_init_internal(const wifi_init_config_t* config); /** * @brief Deinitialize Wi-Fi Driver @@ -117,14 +118,14 @@ wifi_rx_pbuf_mem_type_t esp_wifi_get_rx_pbuf_mem_type(void); int8_t esp_wifi_get_ap_rssi(void); /** - * @brief The RX callback function when receive probe request packet. + * @brief The RX callback function when receive probe request packet. * When probe request packet is received, the callback function will be called. * * @param frame Data of received probe request. * @param len length of received probe request. * @param rssi rssi of received probe request. */ -typedef void (*wifi_sta_rx_probe_req_t)(const uint8_t *frame, int len, int rssi); +typedef void (*wifi_sta_rx_probe_req_t)(const uint8_t* frame, int len, int rssi); /** * @brief Register the RX callback function when receive probe request. @@ -159,14 +160,14 @@ void esp_wifi_internal_free_rx_buffer(void* buffer); * - ERR_IF : WiFi driver error * - ERR_ARG : Invalid argument */ -int esp_wifi_internal_tx(wifi_interface_t wifi_if, void *buffer, uint16_t len); +int esp_wifi_internal_tx(wifi_interface_t wifi_if, void* buffer, uint16_t len); /** * @brief The WiFi RX callback function * * Each time the WiFi need to forward the packets to high layer, the callback function will be called */ -typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void *eb); +typedef esp_err_t (*wifi_rxcb_t)(void* buffer, uint16_t len, void* eb); /** * @brief Set the WiFi RX callback @@ -183,7 +184,7 @@ typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void *eb); esp_err_t esp_wifi_internal_reg_rxcb(wifi_interface_t ifx, wifi_rxcb_t fn); /** - * @brief Set current WiFi log level + * @brief Set current WiFi log level * * @param level Log level. * @@ -207,7 +208,7 @@ esp_err_t esp_wifi_internal_set_log_level(wifi_log_level_t level); esp_err_t esp_wifi_internal_set_log_mod(uint32_t submodule); /** - * @brief Get current WiFi log info + * @brief Get current WiFi log info * * @param log_level the return log level. * @param log_mod the return log module and submodule @@ -215,21 +216,49 @@ esp_err_t esp_wifi_internal_set_log_mod(uint32_t submodule); * @return * - ESP_OK: succeed */ -esp_err_t esp_wifi_internal_get_log(wifi_log_level_t *log_level, uint32_t *log_mod); +esp_err_t esp_wifi_internal_get_log(wifi_log_level_t* log_level, uint32_t* log_mod); /** * @brief get wifi power management config. - * + * * @param ps_config power management config */ -void esp_wifi_set_pm_config(esp_pm_config_t *pm_config); +void esp_wifi_set_pm_config(esp_pm_config_t* pm_config); /** * @brief set wifi power management config. - * + * * @param ps_config power management config */ -void esp_wifi_get_pm_config(esp_pm_config_t *pm_config); +void esp_wifi_get_pm_config(esp_pm_config_t* pm_config); + +/** + * @brief Start SmartConfig, config ESP device to connect AP. You need to broadcast information by phone APP. + * Device sniffer special packets from the air that containing SSID and password of target AP. + * + * @attention 1. This API can be called in station or softAP-station mode. + * @attention 2. Can not call esp_smartconfig_start twice before it finish, please call + * esp_smartconfig_stop first. + * + * @param config pointer to smartconfig start configure structure + * + * @return + * - ESP_OK: succeed + * - others: fail + */ +esp_err_t esp_smartconfig_internal_start(const smartconfig_start_config_t* config); + +/** + * @brief Stop SmartConfig, free the buffer taken by esp_smartconfig_start. + * + * @attention Whether connect to AP succeed or not, this API should be called to free + * memory taken by smartconfig_start. + * + * @return + * - ESP_OK: succeed + * - others: fail + */ +esp_err_t esp_smartconfig_internal_stop(void); #ifdef __cplusplus } diff --git a/components/esp8266/include/esp_smartconfig.h b/components/esp8266/include/esp_smartconfig.h index f7b8e431..52be7899 100644 --- a/components/esp8266/include/esp_smartconfig.h +++ b/components/esp8266/include/esp_smartconfig.h @@ -18,37 +18,48 @@ #include #include #include "esp_err.h" +#include "esp_event_base.h" #ifdef __cplusplus extern "C" { #endif -typedef enum { - SC_STATUS_WAIT = 0, /**< Waiting to start connect */ - SC_STATUS_FIND_CHANNEL, /**< Finding target channel */ - SC_STATUS_GETTING_SSID_PSWD, /**< Getting SSID and password of target AP */ - SC_STATUS_LINK, /**< Connecting to target AP */ - SC_STATUS_LINK_OVER, /**< Connected to AP successfully */ -} smartconfig_status_t; - typedef enum { SC_TYPE_ESPTOUCH = 0, /**< protocol: ESPTouch */ SC_TYPE_AIRKISS, /**< protocol: AirKiss */ SC_TYPE_ESPTOUCH_AIRKISS, /**< protocol: ESPTouch and AirKiss */ } smartconfig_type_t; -/** - * @brief The callback of SmartConfig, executed when smart-config status changed. - * - * @param status Status of SmartConfig: - * - SC_STATUS_GETTING_SSID_PSWD : pdata is a pointer of smartconfig_type_t, means config type. - * - SC_STATUS_LINK : pdata is a pointer of struct station_config. - * - SC_STATUS_LINK_OVER : pdata is a pointer of phone's IP address(4 bytes) if pdata unequal NULL. - * - otherwise : parameter void *pdata is NULL. - * @param pdata According to the different status have different values. - * - */ -typedef void (*sc_callback_t)(smartconfig_status_t status, void *pdata); +/** Smartconfig event declarations */ +typedef enum { + SC_EVENT_SCAN_DONE, /*!< ESP32 station smartconfig has finished to scan for APs */ + SC_EVENT_FOUND_CHANNEL, /*!< ESP32 station smartconfig has found the channel of the target AP */ + SC_EVENT_GOT_SSID_PSWD, /*!< ESP32 station smartconfig got the SSID and password */ + SC_EVENT_SEND_ACK_DONE, /*!< ESP32 station smartconfig has sent ACK to cellphone */ +} smartconfig_event_t; + +/** @brief smartconfig event base declaration */ +ESP_EVENT_DECLARE_BASE(SC_EVENT); + +/** Argument structure for SC_EVENT_GOT_SSID_PSWD event */ +typedef struct { + uint8_t ssid[32]; /**< SSID of the AP. Null terminated string. */ + uint8_t password[64]; /**< Password of the AP. Null terminated string. */ + bool bssid_set; /**< whether set MAC address of target AP or not. */ + uint8_t bssid[6]; /**< MAC address of target AP. */ + smartconfig_type_t type; /**< Type of smartconfig(ESPTouch or AirKiss). */ + uint8_t token; /**< Token from cellphone which is used to send ACK to cellphone. */ + uint8_t cellphone_ip[4]; /**< IP address of cellphone. */ +} smartconfig_event_got_ssid_pswd_t; + +/** Configure structure for esp_smartconfig_start */ +typedef struct { + bool enable_log; /**< Enable smartconfig logs. */ +} smartconfig_start_config_t; + +#define SMARTCONFIG_START_CONFIG_DEFAULT() { \ + .enable_log = false \ + }; /** * @brief Get the version of SmartConfig. @@ -56,24 +67,23 @@ typedef void (*sc_callback_t)(smartconfig_status_t status, void *pdata); * @return * - SmartConfig version const char. */ -const char *esp_smartconfig_get_version(void); +const char* esp_smartconfig_get_version(void); /** * @brief Start SmartConfig, config ESP device to connect AP. You need to broadcast information by phone APP. * Device sniffer special packets from the air that containing SSID and password of target AP. * - * @attention 1. This API can be called in station or softAP-station mode. + * @attention 1. This API can be called in station mode. * @attention 2. Can not call esp_smartconfig_start twice before it finish, please call * esp_smartconfig_stop first. * - * @param cb SmartConfig callback function. - * @param ... log 1: UART output logs; 0: UART only outputs the result. + * @param config pointer to smartconfig start configure structure * * @return * - ESP_OK: succeed * - others: fail */ -esp_err_t esp_smartconfig_start(sc_callback_t cb, ...); +esp_err_t esp_smartconfig_start(const smartconfig_start_config_t* config); /** * @brief Stop SmartConfig, free the buffer taken by esp_smartconfig_start. diff --git a/components/esp8266/include/smartconfig_ack.h b/components/esp8266/include/smartconfig_ack.h new file mode 100644 index 00000000..2e3d2432 --- /dev/null +++ b/components/esp8266/include/smartconfig_ack.h @@ -0,0 +1,44 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SMARTCONFIG_ACK_H +#define SMARTCONFIG_ACK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Send smartconfig ACK to cellphone. + * + * @attention The API can only be used when receiving SC_EVENT_GOT_SSID_PSWD event. + * + * @param type: smartconfig type(ESPTouch or AirKiss); + * token: token from the cellphone; + * cellphone_ip: IP address of the cellphone; + * + * @retuen ESP_OK: succeed + * others: fail + */ +esp_err_t sc_send_ack_start(smartconfig_type_t type, uint8_t token, uint8_t* cellphone_ip); + +/** + * @brief Stop sending smartconfig ACK to cellphone. + */ +void sc_send_ack_stop(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/components/esp8266/lib/VERSION b/components/esp8266/lib/VERSION index 3655a18c..a4445363 100644 --- a/components/esp8266/lib/VERSION +++ b/components/esp8266/lib/VERSION @@ -4,5 +4,5 @@ gwen: pp: 4a1ab49 espnow: a4246a0 - smartconfig: 2.8.2 + smartconfig: 2.9.0 phy: 1163.0 diff --git a/components/esp8266/lib/libsmartconfig.a b/components/esp8266/lib/libsmartconfig.a index 039759dc..5f079f17 100644 Binary files a/components/esp8266/lib/libsmartconfig.a and b/components/esp8266/lib/libsmartconfig.a differ diff --git a/components/esp8266/source/smartconfig.c b/components/esp8266/source/smartconfig.c new file mode 100644 index 00000000..57486c55 --- /dev/null +++ b/components/esp8266/source/smartconfig.c @@ -0,0 +1,83 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include "esp_log.h" +#include "esp_event_base.h" +#include "esp_private/wifi.h" +#include "esp_smartconfig.h" +#include "smartconfig_ack.h" + +/* Smartconfig events definitions */ +ESP_EVENT_DEFINE_BASE(SC_EVENT); + +static const char* TAG = "smartconfig"; + +static void handler_got_ssid_passwd(void* arg, esp_event_base_t base, int32_t event_id, void* data) +{ + smartconfig_event_got_ssid_pswd_t* evt = (smartconfig_event_got_ssid_pswd_t*)data; + uint8_t ssid[33] = { 0 }; + uint8_t password[65] = { 0 }; + uint8_t cellphone_ip[4]; + esp_err_t err = ESP_OK; + + memcpy(ssid, evt->ssid, sizeof(evt->ssid)); + memcpy(password, evt->password, sizeof(evt->password)); + memcpy(cellphone_ip, evt->cellphone_ip, sizeof(evt->cellphone_ip)); + + ESP_LOGD(TAG, "SSID:%s", ssid); + ESP_LOGD(TAG, "PASSWORD:%s", password); + ESP_LOGD(TAG, "Phone ip: %d.%d.%d.%d\n", cellphone_ip[0], cellphone_ip[1], cellphone_ip[2], cellphone_ip[3]); + + err = sc_send_ack_start(evt->type, evt->token, evt->cellphone_ip); + + if (err != ESP_OK) { + ESP_LOGE(TAG, "Send smartconfig ACK error: %d", err); + } +} + +esp_err_t esp_smartconfig_start(const smartconfig_start_config_t* config) +{ + esp_err_t err = ESP_OK; + + err = esp_event_handler_register(SC_EVENT, SC_EVENT_GOT_SSID_PSWD, handler_got_ssid_passwd, NULL); + + if (err != ESP_OK) { + ESP_LOGE(TAG, "Register smartconfig default event handler fail!"); + return err; + } + + err = esp_smartconfig_internal_start(config); + + if (err != ESP_OK) { + esp_event_handler_unregister(SC_EVENT, SC_EVENT_GOT_SSID_PSWD, handler_got_ssid_passwd); + } + + return err; +} + +esp_err_t esp_smartconfig_stop(void) +{ + esp_err_t err = ESP_OK; + + err = esp_smartconfig_internal_stop(); + + if (err == ESP_OK) { + sc_send_ack_stop(); + esp_event_handler_unregister(SC_EVENT, SC_EVENT_GOT_SSID_PSWD, handler_got_ssid_passwd); + } + + return err; +} \ No newline at end of file diff --git a/components/smartconfig_ack/smartconfig_ack.c b/components/esp8266/source/smartconfig_ack.c similarity index 63% rename from components/smartconfig_ack/smartconfig_ack.c rename to components/esp8266/source/smartconfig_ack.c index 4a18fda6..b2f3aa19 100644 --- a/components/smartconfig_ack/smartconfig_ack.c +++ b/components/esp8266/source/smartconfig_ack.c @@ -32,12 +32,35 @@ #include "esp_smartconfig.h" #include "smartconfig_ack.h" -static const char *TAG = "smartconfig"; +#define SC_ACK_TASK_PRIORITY 2 /*!< Priority of sending smartconfig ACK task */ +#define SC_ACK_TASK_STACK_SIZE 2048 /*!< Stack size of sending smartconfig ACK task */ + +#define SC_ACK_TOUCH_SERVER_PORT 18266 /*!< ESP touch UDP port of server on cellphone */ +#define SC_ACK_AIRKISS_SERVER_PORT 10000 /*!< Airkiss UDP port of server on cellphone */ +#define SC_ACK_AIRKISS_DEVICE_PORT 10001 /*!< Airkiss UDP port of server on device */ +#define SC_ACK_AIRKISS_TIMEOUT 1500 /*!< Airkiss read data timout millisecond */ + +#define SC_ACK_TOUCH_LEN 11 /*!< Length of ESP touch ACK context */ +#define SC_ACK_AIRKISS_LEN 7 /*!< Length of Airkiss ACK context */ + +#define SC_ACK_MAX_COUNT 60 /*!< Maximum count of sending smartconfig ACK */ + +/** + * @brief Smartconfig parameters passed to sc_ack_send call. + */ +typedef struct sc_ack { + smartconfig_type_t type; /*!< Smartconfig type(ESPTouch or AirKiss) */ + struct { + uint8_t token; /*!< Smartconfig token from the cellphone */ + uint8_t mac[6]; /*!< MAC address of station */ + uint8_t ip[4]; /*!< IP address of cellphone */ + } ctx; +} sc_ack_t; + +static const char* TAG = "smartconfig"; /* Flag to indicate sending smartconfig ACK or not. */ static bool s_sc_ack_send = false; -static void *s_sc_ack_info = NULL; -static size_t s_sc_ack_info_size = 0; static int sc_ack_send_get_errno(int fd) { @@ -49,32 +72,26 @@ static int sc_ack_send_get_errno(int fd) return sock_errno; } -static void sc_ack_send_task(void *pvParameters) +static void sc_ack_send_task(void* pvParameters) { - sc_ack_t *ack = (sc_ack_t *)pvParameters; + sc_ack_t* ack = (sc_ack_t*)pvParameters; tcpip_adapter_ip_info_t local_ip; - sc_callback_data_t sc_callback_data; uint8_t remote_ip[4]; - memset(&sc_callback_data, 0x0, sizeof(sc_callback_data_t)); - if (ack->type == SC_ACK_TYPE_ESPTOUCH) { - memcpy(sc_callback_data.ip, ack->ctx.ip, sizeof(sc_callback_data.ip)); - } - memcpy(remote_ip, ack->ctx.ip, sizeof(remote_ip)); - sc_callback_data.type = ack->type; - int remote_port = (ack->type == SC_ACK_TYPE_ESPTOUCH) ? SC_ACK_TOUCH_SERVER_PORT : SC_ACK_AIRKISS_SERVER_PORT; + memset(remote_ip, 0xFF, sizeof(remote_ip)); + int remote_port = (ack->type == SC_TYPE_ESPTOUCH) ? SC_ACK_TOUCH_SERVER_PORT : SC_ACK_AIRKISS_SERVER_PORT; struct sockaddr_in server_addr; socklen_t sin_size = sizeof(server_addr); int send_sock = -1; int optval = 1; int sendlen; - int ack_len = (ack->type == SC_ACK_TYPE_ESPTOUCH) ? SC_ACK_TOUCH_LEN : SC_ACK_AIRKISS_LEN; + int ack_len = (ack->type == SC_TYPE_ESPTOUCH) ? SC_ACK_TOUCH_LEN : SC_ACK_AIRKISS_LEN; uint8_t packet_count = 1; int err; int ret; bzero(&server_addr, sizeof(struct sockaddr_in)); server_addr.sin_family = AF_INET; - server_addr.sin_addr.s_addr = inet_addr((const char*)remote_ip); + memcpy(&server_addr.sin_addr.s_addr, remote_ip, sizeof(remote_ip)); server_addr.sin_port = htons(remote_port); esp_wifi_get_mac(WIFI_IF_STA, ack->ctx.mac); @@ -84,22 +101,24 @@ static void sc_ack_send_task(void *pvParameters) while (s_sc_ack_send) { /* Get local IP address of station */ ret = tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &local_ip); + if ((ESP_OK == ret) && (local_ip.ip.addr != INADDR_ANY)) { /* If ESP touch, smartconfig ACK contains local IP address. */ - if (ack->type == SC_ACK_TYPE_ESPTOUCH) { + if (ack->type == SC_TYPE_ESPTOUCH) { memcpy(ack->ctx.ip, &local_ip.ip.addr, 4); } /* Create UDP socket. */ send_sock = socket(AF_INET, SOCK_DGRAM, 0); + if ((send_sock < LWIP_SOCKET_OFFSET) || (send_sock > (FD_SETSIZE - 1))) { ESP_LOGE(TAG, "Creat udp socket failed"); - goto _end; + goto _end; } setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, &optval, sizeof(int)); - if (ack->type == SC_ACK_TYPE_AIRKISS) { + if (ack->type == SC_TYPE_AIRKISS) { char data = 0; struct sockaddr_in local_addr, from; socklen_t sockadd_len = sizeof(struct sockaddr); @@ -114,18 +133,15 @@ static void sc_ack_send_task(void *pvParameters) local_addr.sin_addr.s_addr = INADDR_ANY; local_addr.sin_port = htons(SC_ACK_AIRKISS_DEVICE_PORT); - bind(send_sock, (struct sockaddr *)&local_addr, sockadd_len); + bind(send_sock, (struct sockaddr*)&local_addr, sockadd_len); setsockopt(send_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); - recvfrom(send_sock, &data, 1, 0, (struct sockaddr *)&from, &sockadd_len); + recvfrom(send_sock, &data, 1, 0, (struct sockaddr*)&from, &sockadd_len); + if (from.sin_addr.s_addr != INADDR_ANY) { memcpy(remote_ip, &from.sin_addr, 4); - memcpy(sc_callback_data.ip, &from.sin_addr, sizeof(sc_callback_data.ip)); server_addr.sin_addr.s_addr = from.sin_addr.s_addr; } else { - if (ack->cb) { - ack->cb(SC_STATUS_LINK_OVER, &sc_callback_data); - } goto _end; } } @@ -133,95 +149,73 @@ static void sc_ack_send_task(void *pvParameters) while (s_sc_ack_send) { /* Send smartconfig ACK every 100ms. */ vTaskDelay(100 / portTICK_RATE_MS); - - if (s_sc_ack_info) { - sendlen = sendto(send_sock, s_sc_ack_info, s_sc_ack_info_size, 0, (struct sockaddr*) &server_addr, sin_size); - } else { - sendlen = sendto(send_sock, &ack->ctx, ack_len, 0, (struct sockaddr*) &server_addr, sin_size); - } + sendlen = sendto(send_sock, &ack->ctx, ack_len, 0, (struct sockaddr*) &server_addr, sin_size); if (sendlen > 0) { /* Totally send 30 smartconfig ACKs. Then smartconfig is successful. */ if (packet_count++ >= SC_ACK_MAX_COUNT) { - if (ack->link_flag) { - *ack->link_flag = 1; - } - if (ack->cb) { - ack->cb(SC_STATUS_LINK_OVER, &sc_callback_data); - } + esp_event_post(SC_EVENT, SC_EVENT_SEND_ACK_DONE, NULL, 0, portMAX_DELAY); goto _end; } - } - else { + } else { err = sc_ack_send_get_errno(send_sock); + if (err == ENOMEM || err == EAGAIN) { ESP_LOGD(TAG, "send failed, errno %d", err); continue; } + ESP_LOGE(TAG, "send failed, errno %d", err); goto _end; } } - } - else { - vTaskDelay((portTickType)(100 / portTICK_RATE_MS)); + } else { + vTaskDelay((portTickType)(200 / portTICK_RATE_MS)); } } _end: + if ((send_sock >= LWIP_SOCKET_OFFSET) && (send_sock <= (FD_SETSIZE - 1))) { close(send_sock); } - if (s_sc_ack_info) { - free(s_sc_ack_info); - s_sc_ack_info = NULL; - s_sc_ack_info_size = 0; - } + free(ack); vTaskDelete(NULL); } -void sc_ack_send(sc_ack_t *param) +esp_err_t sc_send_ack_start(smartconfig_type_t type, uint8_t token, uint8_t* cellphone_ip) { - sc_ack_t *ack = NULL; + sc_ack_t* ack = NULL; - if (param == NULL) { - ESP_LOGE(TAG, "Smart config ack parameter error"); - return; + if (cellphone_ip == NULL) { + ESP_LOGE(TAG, "Cellphone IP address is NULL"); + return ESP_ERR_INVALID_ARG; } ack = malloc(sizeof(sc_ack_t)); + if (ack == NULL) { - ESP_LOGE(TAG, "Smart config ack parameter malloc fail"); - return; + ESP_LOGE(TAG, "ACK parameter malloc fail"); + return ESP_ERR_NO_MEM; } - memcpy(ack, param, sizeof(sc_ack_t)); + + ack->type = type; + ack->ctx.token = token; + memcpy(ack->ctx.ip, cellphone_ip, 4); s_sc_ack_send = true; if (xTaskCreate(sc_ack_send_task, "sc_ack_send_task", SC_ACK_TASK_STACK_SIZE, ack, SC_ACK_TASK_PRIORITY, NULL) != pdPASS) { ESP_LOGE(TAG, "Create sending smartconfig ACK task fail"); free(ack); + return ESP_ERR_NO_MEM; } + + return ESP_OK; } -void sc_ack_send_stop(void) +void sc_send_ack_stop(void) { s_sc_ack_send = false; } - -bool sc_ack_send_info(void *buffer, size_t size) -{ - if (!buffer || !size) - return false; - - s_sc_ack_info = s_sc_ack_info ? realloc(s_sc_ack_info, size + 1) : malloc(size + 1); - if (!s_sc_ack_info) - return false; - - s_sc_ack_info_size = size; - memset(s_sc_ack_info, 0, size + 1); - memcpy(s_sc_ack_info, buffer, size); - - return true; -} diff --git a/components/smartconfig_ack/CMakeLists.txt b/components/smartconfig_ack/CMakeLists.txt deleted file mode 100644 index 8b18007d..00000000 --- a/components/smartconfig_ack/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -set(COMPONENT_SRCDIRS ".") -set(COMPONENT_ADD_INCLUDEDIRS "include") - -set(COMPONENT_PRIV_REQUIRES lwip tcpip_adapter) - -register_component() diff --git a/components/smartconfig_ack/component.mk b/components/smartconfig_ack/component.mk deleted file mode 100644 index 58eac9a5..00000000 --- a/components/smartconfig_ack/component.mk +++ /dev/null @@ -1,2 +0,0 @@ -# -# Component Makefile diff --git a/components/smartconfig_ack/include/smartconfig_ack.h b/components/smartconfig_ack/include/smartconfig_ack.h deleted file mode 100644 index 1f037a57..00000000 --- a/components/smartconfig_ack/include/smartconfig_ack.h +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef SMARTCONFIG_ACK_H -#define SMARTCONFIG_ACK_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define SC_ACK_TASK_PRIORITY 2 /*!< Priority of sending smartconfig ACK task */ -#define SC_ACK_TASK_STACK_SIZE 2048 /*!< Stack size of sending smartconfig ACK task */ - -#define SC_ACK_TOUCH_SERVER_PORT 18266 /*!< ESP touch UDP port of server on cellphone */ -#define SC_ACK_AIRKISS_SERVER_PORT 10000 /*!< Airkiss UDP port of server on cellphone */ -#define SC_ACK_AIRKISS_DEVICE_PORT 10001 /*!< Airkiss UDP port of server on device */ -#define SC_ACK_AIRKISS_TIMEOUT 1500 /*!< Airkiss read data timeout millisecond */ - -#define SC_ACK_TOUCH_LEN 11 /*!< Length of ESP touch ACK context */ -#define SC_ACK_AIRKISS_LEN 7 /*!< Length of Airkiss ACK context */ - -#define SC_ACK_MAX_COUNT 30 /*!< Maximum count of sending smartconfig ACK */ - -/** - * @brief Smartconfig ACK type. - */ -typedef enum { - SC_ACK_TYPE_ESPTOUCH = 0, /*!< ESP touch ACK type */ - SC_ACK_TYPE_AIRKISS, /*!< Airkiss ACK type */ -} sc_ack_type_t; - -/** - * @brief Smartconfig parameters passed to sc_ack_send call. - */ -typedef struct sc_ack { - sc_ack_type_t type; /*!< Smartconfig ACK type */ - uint8_t *link_flag; /*!< Smartconfig link flag */ - sc_callback_t cb; /*!< Smartconfig callback function */ - struct { - uint8_t token; /*!< Smartconfig token to be sent */ - uint8_t mac[6]; /*!< MAC address of station */ - uint8_t ip[4]; /*!< IP address of cellphone */ - } ctx; -} sc_ack_t; - -/** - * @brief Smartconfig parameters passed sc_callback call. - */ -typedef struct sc_callback_ack { - uint8_t ip[4]; /*!< IP address of cellphone */ - sc_ack_type_t type; /*!< Smartconfig ACK type */ -} sc_callback_data_t; - -/** - * @brief Send smartconfig ACK to cellphone. - * - * @attention The API is only used in libsmartconfig.a. - * - * @param param: smartconfig parameters; - */ -void sc_ack_send(sc_ack_t *param); - -/** - * @brief Stop sending smartconfig ACK to cellphone. - * - * @attention The API is only used in libsmartconfig.a. - */ -void sc_ack_send_stop(void); - -/** - * @brief Fill smartconfig ACK information to cellphone. - * - * @attention The API is only used in libsmartconfig.a. - * - * @param buffer: Transmits the data in the buffer; - * @param size: The size argument specifies the number of bytes to be transmitted. - */ -bool sc_ack_send_info(void *buffer, size_t size); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/docs/Doxyfile b/docs/Doxyfile index 1516f915..40c1c94d 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -28,6 +28,11 @@ INPUT = \ ../../components/esp8266/include/esp_wifi_types.h \ ../../components/esp8266/include/esp_smartconfig.h \ ## + ## Event loop - API Reference + ../../components/esp_event/include/esp_event.h \ + ../../components/esp_event/include/esp_event_base.h \ + ../../components/esp_event/include/esp_event_legacy.h \ + ## ## TCP-IP - API Reference ## ../../components/tcpip_adapter/include/tcpip_adapter.h \ @@ -78,7 +83,8 @@ PREDEFINED = \ configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS=1 \ configNUM_THREAD_LOCAL_STORAGE_POINTERS=1 \ configUSE_APPLICATION_TASK_TAG=1 \ - configTASKLIST_INCLUDE_COREID=1 + configTASKLIST_INCLUDE_COREID=1 \ + "ESP_EVENT_DECLARE_BASE(x)=extern esp_event_base_t x" ## Do not complain about not having dot ## diff --git a/examples/wifi/smart_config/main/smartconfig_main.c b/examples/wifi/smart_config/main/smartconfig_main.c index bf9dc59f..fd1299a8 100644 --- a/examples/wifi/smart_config/main/smartconfig_main.c +++ b/examples/wifi/smart_config/main/smartconfig_main.c @@ -22,118 +22,95 @@ #include "smartconfig_ack.h" /* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; +static EventGroupHandle_t s_wifi_event_group; /* The event group allows multiple bits for each event, but we only care about one event - are we connected to the AP with an IP? */ static const int CONNECTED_BIT = BIT0; static const int ESPTOUCH_DONE_BIT = BIT1; -static const char *TAG = "sc"; +static const char* TAG = "smartconfig_example"; -static void smartconfig_example_task(void * parm); +static void smartconfig_example_task(void* parm); -static void on_wifi_start(void *arg, esp_event_base_t event_base, - int32_t event_id, void *event_data) +static void event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) { - xTaskCreate(smartconfig_example_task, "smartconfig_example_task", 4096, NULL, 3, NULL); -} + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { + xTaskCreate(smartconfig_example_task, "smartconfig_example_task", 4096, NULL, 3, NULL); + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { + esp_wifi_connect(); + xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT); + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT); + } else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE) { + ESP_LOGI(TAG, "Scan done"); + } else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL) { + ESP_LOGI(TAG, "Found channel"); + } else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD) { + ESP_LOGI(TAG, "Got SSID and password"); -static void on_wifi_disconnect(void *arg, esp_event_base_t event_base, - int32_t event_id, void *event_data) -{ - system_event_sta_disconnected_t *event = (system_event_sta_disconnected_t *)event_data; + smartconfig_event_got_ssid_pswd_t* evt = (smartconfig_event_got_ssid_pswd_t*)event_data; + wifi_config_t wifi_config; + uint8_t ssid[33] = { 0 }; + uint8_t password[65] = { 0 }; - ESP_LOGI(TAG, "Wi-Fi disconnected, trying to reconnect..."); - if (event->reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N); + bzero(&wifi_config, sizeof(wifi_config_t)); + memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid)); + memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password)); + wifi_config.sta.bssid_set = evt->bssid_set; + + if (wifi_config.sta.bssid_set == true) { + memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid)); + } + + memcpy(ssid, evt->ssid, sizeof(evt->ssid)); + memcpy(password, evt->password, sizeof(evt->password)); + ESP_LOGI(TAG, "SSID:%s", ssid); + ESP_LOGI(TAG, "PASSWORD:%s", password); + + ESP_ERROR_CHECK(esp_wifi_disconnect()); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_connect()); + } else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE) { + xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT); } - ESP_ERROR_CHECK(esp_wifi_connect()); -} - -static void on_got_ip(void *arg, esp_event_base_t event_base, - int32_t event_id, void *event_data) -{ - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); } static void initialise_wifi(void) { tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); + s_wifi_event_group = xEventGroupCreate(); ESP_ERROR_CHECK(esp_event_loop_create_default()); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); - ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_START, &on_wifi_start, NULL)); - ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect, NULL)); - ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip, NULL)); - - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_start() ); - ESP_ERROR_CHECK( esp_wifi_connect() ); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_start()); } -static void sc_callback(smartconfig_status_t status, void *pdata) -{ - switch (status) { - case SC_STATUS_WAIT: - ESP_LOGI(TAG, "SC_STATUS_WAIT"); - break; - case SC_STATUS_FIND_CHANNEL: - ESP_LOGI(TAG, "SC_STATUS_FINDING_CHANNEL"); - break; - case SC_STATUS_GETTING_SSID_PSWD: - ESP_LOGI(TAG, "SC_STATUS_GETTING_SSID_PSWD"); - break; - case SC_STATUS_LINK: - ESP_LOGI(TAG, "SC_STATUS_LINK"); - wifi_config_t *wifi_config = pdata; - ESP_LOGI(TAG, "SSID:%s", wifi_config->sta.ssid); - ESP_LOGI(TAG, "PASSWORD:%s", wifi_config->sta.password); - ESP_ERROR_CHECK( esp_wifi_disconnect() ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_connect() ); - break; - case SC_STATUS_LINK_OVER: - ESP_LOGI(TAG, "SC_STATUS_LINK_OVER"); - if (pdata != NULL) { - sc_callback_data_t *sc_callback_data = (sc_callback_data_t *)pdata; - switch (sc_callback_data->type) { - case SC_ACK_TYPE_ESPTOUCH: - ESP_LOGI(TAG, "Phone ip: %d.%d.%d.%d", sc_callback_data->ip[0], sc_callback_data->ip[1], sc_callback_data->ip[2], sc_callback_data->ip[3]); - ESP_LOGI(TAG, "TYPE: ESPTOUCH"); - break; - case SC_ACK_TYPE_AIRKISS: - ESP_LOGI(TAG, "TYPE: AIRKISS"); - break; - default: - ESP_LOGE(TAG, "TYPE: ERROR"); - break; - } - } - xEventGroupSetBits(wifi_event_group, ESPTOUCH_DONE_BIT); - break; - default: - break; - } -} - -static void smartconfig_example_task(void * parm) +static void smartconfig_example_task(void* parm) { EventBits_t uxBits; - ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS) ); - ESP_ERROR_CHECK( esp_smartconfig_start(sc_callback) ); + ESP_ERROR_CHECK(esp_smartconfig_set_type(SC_TYPE_ESPTOUCH)); + smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_smartconfig_start(&cfg)); + while (1) { - uxBits = xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY); - if(uxBits & CONNECTED_BIT) { + uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY); + + if (uxBits & CONNECTED_BIT) { ESP_LOGI(TAG, "WiFi Connected to ap"); } - if(uxBits & ESPTOUCH_DONE_BIT) { + + if (uxBits & ESPTOUCH_DONE_BIT) { ESP_LOGI(TAG, "smartconfig over"); esp_smartconfig_stop(); vTaskDelete(NULL); @@ -143,7 +120,7 @@ static void smartconfig_example_task(void * parm) void app_main() { - ESP_ERROR_CHECK( nvs_flash_init() ); + ESP_ERROR_CHECK(nvs_flash_init()); initialise_wifi(); }