forked from espressif/esp-idf
Refractor smartconfig
Move code of receiving smartconfig packets and getting password to wifi lib. Open source code of sending smartconfig ACK to cellphone in IDF.
This commit is contained in:
154
components/esp32/smartconfig.c
Normal file
154
components/esp32/smartconfig.c
Normal file
@@ -0,0 +1,154 @@
|
||||
// Copyright 2010-2017 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.
|
||||
|
||||
/*
|
||||
* After station connects to AP and gets IP address by smartconfig,
|
||||
* it will use UDP to send 'ACK' to cellphone.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "tcpip_adapter.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_smartconfig.h"
|
||||
#include "smartconfig.h"
|
||||
|
||||
static const char *TAG = "smartconfig";
|
||||
|
||||
/* Flag to indicate sending smartconfig ACK or not. */
|
||||
static bool s_sc_ack_send = false;
|
||||
|
||||
static int sc_ack_send_get_errno(int fd)
|
||||
{
|
||||
int sock_errno = 0;
|
||||
u32_t optlen = sizeof(sock_errno);
|
||||
|
||||
getsockopt(fd, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen);
|
||||
|
||||
return sock_errno;
|
||||
}
|
||||
|
||||
static void sc_ack_send_task(void *pvParameters)
|
||||
{
|
||||
sc_ack_t *ack = (sc_ack_t *)pvParameters;
|
||||
tcpip_adapter_ip_info_t local_ip;
|
||||
uint8_t *remote_ip = ack->ctx.ip;
|
||||
int remote_port = (ack->type == SC_ACK_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 = 0;
|
||||
int optval = 1;
|
||||
int sendlen;
|
||||
int ack_len = (ack->type == SC_ACK_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);
|
||||
server_addr.sin_port = htons(remote_port);
|
||||
|
||||
esp_wifi_get_mac(WIFI_IF_STA, ack->ctx.mac);
|
||||
|
||||
vTaskDelay(200 / portTICK_RATE_MS);
|
||||
|
||||
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) {
|
||||
memcpy(ack->ctx.ip, &local_ip.ip.addr, 4);
|
||||
}
|
||||
|
||||
/* Create UDP socket. */
|
||||
send_sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (send_sock < 0) {
|
||||
ESP_LOGE(TAG, "Creat udp socket failed");
|
||||
free(ack);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, &optval, sizeof(int));
|
||||
|
||||
while (s_sc_ack_send) {
|
||||
/* Send smartconfig ACK every 100ms. */
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
|
||||
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, remote_ip);
|
||||
}
|
||||
close(send_sock);
|
||||
free(ack);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
}
|
||||
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);
|
||||
close(send_sock);
|
||||
free(ack);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
vTaskDelay((portTickType)(100 / portTICK_RATE_MS));
|
||||
}
|
||||
}
|
||||
|
||||
free(ack);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void sc_ack_send(sc_ack_t *param)
|
||||
{
|
||||
sc_ack_t *ack = NULL;
|
||||
|
||||
if (param == NULL) {
|
||||
ESP_LOGE(TAG, "Smart config ack parameter error");
|
||||
return;
|
||||
}
|
||||
|
||||
ack = malloc(sizeof(sc_ack_t));
|
||||
if (ack == NULL) {
|
||||
ESP_LOGE(TAG, "Smart config ack parameter malloc fail");
|
||||
return;
|
||||
}
|
||||
memcpy(ack, param, sizeof(sc_ack_t));
|
||||
|
||||
s_sc_ack_send = true;
|
||||
|
||||
xTaskCreate(sc_ack_send_task, "sc_ack_send_task", SC_ACK_TASK_STACK_SIZE, ack, SC_ACK_TASK_PRIORITY, NULL);
|
||||
}
|
||||
|
||||
void sc_ack_send_stop(void)
|
||||
{
|
||||
s_sc_ack_send = false;
|
||||
}
|
74
components/esp32/smartconfig.h
Normal file
74
components/esp32/smartconfig.h
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright 2010-2017 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_H
|
||||
#define SMARTCONFIG_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_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 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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
Reference in New Issue
Block a user