feat(smartconfig): refactor smartconfig callback to use esp event

Consistent with esp-idf(branch: release/v4.2, commit id: c5bb6c4)
This commit is contained in:
chenwen
2020-10-20 16:57:54 +08:00
parent dda5062c80
commit d3a974f6f2
13 changed files with 339 additions and 296 deletions

View File

@ -32,6 +32,8 @@ else()
"source/crc.c" "source/crc.c"
"source/phy_init.c" "source/phy_init.c"
"source/reset_reason.c" "source/reset_reason.c"
"source/smartconfig.c"
"source/smartconfig_ack.c"
"source/startup.c" "source/startup.c"
"source/system_api.c" "source/system_api.c"
"source/task_wdt.c" "source/task_wdt.c"

View File

@ -18,6 +18,7 @@
#include "esp_wifi_types.h" #include "esp_wifi_types.h"
#include "esp_event.h" #include "esp_event.h"
#include "esp_wifi.h" #include "esp_wifi.h"
#include "esp_smartconfig.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -81,7 +82,7 @@ typedef enum {
* - ESP_ERR_NO_MEM: out of memory * - ESP_ERR_NO_MEM: out of memory
* - others: refer to error code esp_err.h * - 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 * @brief Deinitialize Wi-Fi Driver
@ -124,7 +125,7 @@ int8_t esp_wifi_get_ap_rssi(void);
* @param len length of received probe request. * @param len length of received probe request.
* @param rssi rssi 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. * @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_IF : WiFi driver error
* - ERR_ARG : Invalid argument * - 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 * @brief The WiFi RX callback function
* *
* Each time the WiFi need to forward the packets to high layer, the callback function will be called * 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 * @brief Set the WiFi RX callback
@ -215,21 +216,49 @@ esp_err_t esp_wifi_internal_set_log_mod(uint32_t submodule);
* @return * @return
* - ESP_OK: succeed * - 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. * @brief get wifi power management config.
* *
* @param ps_config 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. * @brief set wifi power management config.
* *
* @param ps_config 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 #ifdef __cplusplus
} }

View File

@ -18,37 +18,48 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "esp_err.h" #include "esp_err.h"
#include "esp_event_base.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #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 { typedef enum {
SC_TYPE_ESPTOUCH = 0, /**< protocol: ESPTouch */ SC_TYPE_ESPTOUCH = 0, /**< protocol: ESPTouch */
SC_TYPE_AIRKISS, /**< protocol: AirKiss */ SC_TYPE_AIRKISS, /**< protocol: AirKiss */
SC_TYPE_ESPTOUCH_AIRKISS, /**< protocol: ESPTouch and AirKiss */ SC_TYPE_ESPTOUCH_AIRKISS, /**< protocol: ESPTouch and AirKiss */
} smartconfig_type_t; } smartconfig_type_t;
/** /** Smartconfig event declarations */
* @brief The callback of SmartConfig, executed when smart-config status changed. typedef enum {
* SC_EVENT_SCAN_DONE, /*!< ESP32 station smartconfig has finished to scan for APs */
* @param status Status of SmartConfig: SC_EVENT_FOUND_CHANNEL, /*!< ESP32 station smartconfig has found the channel of the target AP */
* - SC_STATUS_GETTING_SSID_PSWD : pdata is a pointer of smartconfig_type_t, means config type. SC_EVENT_GOT_SSID_PSWD, /*!< ESP32 station smartconfig got the SSID and password */
* - SC_STATUS_LINK : pdata is a pointer of struct station_config. SC_EVENT_SEND_ACK_DONE, /*!< ESP32 station smartconfig has sent ACK to cellphone */
* - SC_STATUS_LINK_OVER : pdata is a pointer of phone's IP address(4 bytes) if pdata unequal NULL. } smartconfig_event_t;
* - otherwise : parameter void *pdata is NULL.
* @param pdata According to the different status have different values. /** @brief smartconfig event base declaration */
* ESP_EVENT_DECLARE_BASE(SC_EVENT);
*/
typedef void (*sc_callback_t)(smartconfig_status_t status, void *pdata); /** 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. * @brief Get the version of SmartConfig.
@ -56,24 +67,23 @@ typedef void (*sc_callback_t)(smartconfig_status_t status, void *pdata);
* @return * @return
* - SmartConfig version const char. * - 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. * @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. * 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 * @attention 2. Can not call esp_smartconfig_start twice before it finish, please call
* esp_smartconfig_stop first. * esp_smartconfig_stop first.
* *
* @param cb SmartConfig callback function. * @param config pointer to smartconfig start configure structure
* @param ... log 1: UART output logs; 0: UART only outputs the result.
* *
* @return * @return
* - ESP_OK: succeed * - ESP_OK: succeed
* - others: fail * - 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. * @brief Stop SmartConfig, free the buffer taken by esp_smartconfig_start.

View File

@ -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

View File

@ -4,5 +4,5 @@ gwen:
pp: 4a1ab49 pp: 4a1ab49
espnow: a4246a0 espnow: a4246a0
smartconfig: 2.8.2 smartconfig: 2.9.0
phy: 1163.0 phy: 1163.0

View File

@ -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 <stdint.h>
#include <string.h>
#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;
}

View File

@ -32,12 +32,35 @@
#include "esp_smartconfig.h" #include "esp_smartconfig.h"
#include "smartconfig_ack.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. */ /* Flag to indicate sending smartconfig ACK or not. */
static bool s_sc_ack_send = false; 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) 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; 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; tcpip_adapter_ip_info_t local_ip;
sc_callback_data_t sc_callback_data;
uint8_t remote_ip[4]; uint8_t remote_ip[4];
memset(&sc_callback_data, 0x0, sizeof(sc_callback_data_t)); memset(remote_ip, 0xFF, sizeof(remote_ip));
if (ack->type == SC_ACK_TYPE_ESPTOUCH) { int remote_port = (ack->type == SC_TYPE_ESPTOUCH) ? SC_ACK_TOUCH_SERVER_PORT : SC_ACK_AIRKISS_SERVER_PORT;
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;
struct sockaddr_in server_addr; struct sockaddr_in server_addr;
socklen_t sin_size = sizeof(server_addr); socklen_t sin_size = sizeof(server_addr);
int send_sock = -1; int send_sock = -1;
int optval = 1; int optval = 1;
int sendlen; 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; uint8_t packet_count = 1;
int err; int err;
int ret; int ret;
bzero(&server_addr, sizeof(struct sockaddr_in)); bzero(&server_addr, sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET; 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); server_addr.sin_port = htons(remote_port);
esp_wifi_get_mac(WIFI_IF_STA, ack->ctx.mac); esp_wifi_get_mac(WIFI_IF_STA, ack->ctx.mac);
@ -84,14 +101,16 @@ static void sc_ack_send_task(void *pvParameters)
while (s_sc_ack_send) { while (s_sc_ack_send) {
/* Get local IP address of station */ /* Get local IP address of station */
ret = tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &local_ip); ret = tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &local_ip);
if ((ESP_OK == ret) && (local_ip.ip.addr != INADDR_ANY)) { if ((ESP_OK == ret) && (local_ip.ip.addr != INADDR_ANY)) {
/* If ESP touch, smartconfig ACK contains local IP address. */ /* 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); memcpy(ack->ctx.ip, &local_ip.ip.addr, 4);
} }
/* Create UDP socket. */ /* Create UDP socket. */
send_sock = socket(AF_INET, SOCK_DGRAM, 0); send_sock = socket(AF_INET, SOCK_DGRAM, 0);
if ((send_sock < LWIP_SOCKET_OFFSET) || (send_sock > (FD_SETSIZE - 1))) { if ((send_sock < LWIP_SOCKET_OFFSET) || (send_sock > (FD_SETSIZE - 1))) {
ESP_LOGE(TAG, "Creat udp socket failed"); ESP_LOGE(TAG, "Creat udp socket failed");
goto _end; goto _end;
@ -99,7 +118,7 @@ static void sc_ack_send_task(void *pvParameters)
setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, &optval, sizeof(int)); 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; char data = 0;
struct sockaddr_in local_addr, from; struct sockaddr_in local_addr, from;
socklen_t sockadd_len = sizeof(struct sockaddr); 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_addr.s_addr = INADDR_ANY;
local_addr.sin_port = htons(SC_ACK_AIRKISS_DEVICE_PORT); 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)); 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) { if (from.sin_addr.s_addr != INADDR_ANY) {
memcpy(remote_ip, &from.sin_addr, 4); 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; server_addr.sin_addr.s_addr = from.sin_addr.s_addr;
} else { } else {
if (ack->cb) {
ack->cb(SC_STATUS_LINK_OVER, &sc_callback_data);
}
goto _end; goto _end;
} }
} }
@ -133,95 +149,73 @@ static void sc_ack_send_task(void *pvParameters)
while (s_sc_ack_send) { while (s_sc_ack_send) {
/* Send smartconfig ACK every 100ms. */ /* Send smartconfig ACK every 100ms. */
vTaskDelay(100 / portTICK_RATE_MS); 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) { if (sendlen > 0) {
/* Totally send 30 smartconfig ACKs. Then smartconfig is successful. */ /* Totally send 30 smartconfig ACKs. Then smartconfig is successful. */
if (packet_count++ >= SC_ACK_MAX_COUNT) { if (packet_count++ >= SC_ACK_MAX_COUNT) {
if (ack->link_flag) { esp_event_post(SC_EVENT, SC_EVENT_SEND_ACK_DONE, NULL, 0, portMAX_DELAY);
*ack->link_flag = 1;
}
if (ack->cb) {
ack->cb(SC_STATUS_LINK_OVER, &sc_callback_data);
}
goto _end; goto _end;
} }
} } else {
else {
err = sc_ack_send_get_errno(send_sock); err = sc_ack_send_get_errno(send_sock);
if (err == ENOMEM || err == EAGAIN) { if (err == ENOMEM || err == EAGAIN) {
ESP_LOGD(TAG, "send failed, errno %d", err); ESP_LOGD(TAG, "send failed, errno %d", err);
continue; continue;
} }
ESP_LOGE(TAG, "send failed, errno %d", err); ESP_LOGE(TAG, "send failed, errno %d", err);
goto _end; goto _end;
} }
} }
} } else {
else { vTaskDelay((portTickType)(200 / portTICK_RATE_MS));
vTaskDelay((portTickType)(100 / portTICK_RATE_MS));
} }
} }
_end: _end:
if ((send_sock >= LWIP_SOCKET_OFFSET) && (send_sock <= (FD_SETSIZE - 1))) { if ((send_sock >= LWIP_SOCKET_OFFSET) && (send_sock <= (FD_SETSIZE - 1))) {
close(send_sock); 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); free(ack);
vTaskDelete(NULL); 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) { if (cellphone_ip == NULL) {
ESP_LOGE(TAG, "Smart config ack parameter error"); ESP_LOGE(TAG, "Cellphone IP address is NULL");
return; return ESP_ERR_INVALID_ARG;
} }
ack = malloc(sizeof(sc_ack_t)); ack = malloc(sizeof(sc_ack_t));
if (ack == NULL) { if (ack == NULL) {
ESP_LOGE(TAG, "Smart config ack parameter malloc fail"); ESP_LOGE(TAG, "ACK parameter malloc fail");
return; 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; 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) { 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"); ESP_LOGE(TAG, "Create sending smartconfig ACK task fail");
free(ack); 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; 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;
}

View File

@ -1,6 +0,0 @@
set(COMPONENT_SRCDIRS ".")
set(COMPONENT_ADD_INCLUDEDIRS "include")
set(COMPONENT_PRIV_REQUIRES lwip tcpip_adapter)
register_component()

View File

@ -1,2 +0,0 @@
#
# Component Makefile

View File

@ -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

View File

@ -28,6 +28,11 @@ INPUT = \
../../components/esp8266/include/esp_wifi_types.h \ ../../components/esp8266/include/esp_wifi_types.h \
../../components/esp8266/include/esp_smartconfig.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 ## TCP-IP - API Reference
## ##
../../components/tcpip_adapter/include/tcpip_adapter.h \ ../../components/tcpip_adapter/include/tcpip_adapter.h \
@ -78,7 +83,8 @@ PREDEFINED = \
configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS=1 \ configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS=1 \
configNUM_THREAD_LOCAL_STORAGE_POINTERS=1 \ configNUM_THREAD_LOCAL_STORAGE_POINTERS=1 \
configUSE_APPLICATION_TASK_TAG=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 ## Do not complain about not having dot
## ##

View File

@ -22,118 +22,95 @@
#include "smartconfig_ack.h" #include "smartconfig_ack.h"
/* FreeRTOS event group to signal when we are connected & ready to make a request */ /* 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, /* The event group allows multiple bits for each event,
but we only care about one event - are we connected but we only care about one event - are we connected
to the AP with an IP? */ to the AP with an IP? */
static const int CONNECTED_BIT = BIT0; static const int CONNECTED_BIT = BIT0;
static const int ESPTOUCH_DONE_BIT = BIT1; 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, static void event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void *event_data) int32_t event_id, void* event_data)
{ {
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
xTaskCreate(smartconfig_example_task, "smartconfig_example_task", 4096, NULL, 3, NULL); 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, smartconfig_event_got_ssid_pswd_t* evt = (smartconfig_event_got_ssid_pswd_t*)event_data;
int32_t event_id, void *event_data) wifi_config_t wifi_config;
{ uint8_t ssid[33] = { 0 };
system_event_sta_disconnected_t *event = (system_event_sta_disconnected_t *)event_data; uint8_t password[65] = { 0 };
ESP_LOGI(TAG, "Wi-Fi disconnected, trying to reconnect..."); bzero(&wifi_config, sizeof(wifi_config_t));
if (event->reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));
/*Switch to 802.11 bgn mode */ memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));
esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N); 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));
} }
ESP_ERROR_CHECK(esp_wifi_connect());
}
static void on_got_ip(void *arg, esp_event_base_t event_base, memcpy(ssid, evt->ssid, sizeof(evt->ssid));
int32_t event_id, void *event_data) memcpy(password, evt->password, sizeof(evt->password));
{ ESP_LOGI(TAG, "SSID:%s", ssid);
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); 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);
}
} }
static void initialise_wifi(void) static void initialise_wifi(void)
{ {
tcpip_adapter_init(); tcpip_adapter_init();
wifi_event_group = xEventGroupCreate(); s_wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(esp_event_loop_create_default());
wifi_init_config_t cfg = WIFI_INIT_CONFIG_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_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect, NULL)); ESP_ERROR_CHECK(esp_wifi_start());
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() );
} }
static void sc_callback(smartconfig_status_t status, void *pdata) static void smartconfig_example_task(void* parm)
{
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)
{ {
EventBits_t uxBits; EventBits_t uxBits;
ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS) ); ESP_ERROR_CHECK(esp_smartconfig_set_type(SC_TYPE_ESPTOUCH));
ESP_ERROR_CHECK( esp_smartconfig_start(sc_callback) ); smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_smartconfig_start(&cfg));
while (1) { while (1) {
uxBits = xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY); uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);
if(uxBits & CONNECTED_BIT) {
if (uxBits & CONNECTED_BIT) {
ESP_LOGI(TAG, "WiFi Connected to ap"); ESP_LOGI(TAG, "WiFi Connected to ap");
} }
if(uxBits & ESPTOUCH_DONE_BIT) {
if (uxBits & ESPTOUCH_DONE_BIT) {
ESP_LOGI(TAG, "smartconfig over"); ESP_LOGI(TAG, "smartconfig over");
esp_smartconfig_stop(); esp_smartconfig_stop();
vTaskDelete(NULL); vTaskDelete(NULL);
@ -143,7 +120,7 @@ static void smartconfig_example_task(void * parm)
void app_main() void app_main()
{ {
ESP_ERROR_CHECK( nvs_flash_init() ); ESP_ERROR_CHECK(nvs_flash_init());
initialise_wifi(); initialise_wifi();
} }