mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-05-31 07:26:28 +08:00
feat(smartconfig_ack): Add smartconfig_ack components
This commit is contained in:
121
components/esp8266/include/esp_smartconfig.h
Normal file
121
components/esp8266/include/esp_smartconfig.h
Normal file
@ -0,0 +1,121 @@
|
||||
// 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 __ESP_SMARTCONFIG_H__
|
||||
#define __ESP_SMARTCONFIG_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.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);
|
||||
|
||||
/**
|
||||
* @brief Get the version of SmartConfig.
|
||||
*
|
||||
* @return
|
||||
* - SmartConfig version const char.
|
||||
*/
|
||||
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 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.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: succeed
|
||||
* - others: fail
|
||||
*/
|
||||
esp_err_t esp_smartconfig_start(sc_callback_t cb, ...);
|
||||
|
||||
/**
|
||||
* @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_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Set timeout of SmartConfig process.
|
||||
*
|
||||
* @attention Timing starts from SC_STATUS_FIND_CHANNEL status. SmartConfig will restart if timeout.
|
||||
*
|
||||
* @param time_s range 15s~255s, offset:45s.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: succeed
|
||||
* - others: fail
|
||||
*/
|
||||
esp_err_t esptouch_set_timeout(uint8_t time_s);
|
||||
|
||||
/**
|
||||
* @brief Set protocol type of SmartConfig.
|
||||
*
|
||||
* @attention If users need to set the SmartConfig type, please set it before calling
|
||||
* esp_smartconfig_start.
|
||||
*
|
||||
* @param type Choose from the smartconfig_type_t.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: succeed
|
||||
* - others: fail
|
||||
*/
|
||||
esp_err_t esp_smartconfig_set_type(smartconfig_type_t type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,168 +0,0 @@
|
||||
/*
|
||||
* ESPRSSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2015 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
|
||||
* it is free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SMARTCONFIG_H__
|
||||
#define __SMARTCONFIG_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup WiFi_APIs WiFi Related APIs
|
||||
* @brief WiFi APIs
|
||||
*/
|
||||
|
||||
/** @addtogroup WiFi_APIs
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \defgroup Smartconfig_APIs Smartconfig APIs
|
||||
* @brief SmartConfig APIs
|
||||
*
|
||||
* SmartConfig can only be enabled in station only mode.
|
||||
* Please make sure the target AP is enabled before enable SmartConfig.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @addtogroup Smartconfig_APIs
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
SC_STATUS_WAIT = 0, /**< waiting, do not start connection in this phase */
|
||||
SC_STATUS_FIND_CHANNEL, /**< find target channel, start connection by APP in this phase */
|
||||
SC_STATUS_GETTING_SSID_PSWD, /**< getting SSID and password of target AP */
|
||||
SC_STATUS_LINK, /**< connecting to target AP */
|
||||
SC_STATUS_LINK_OVER, /**< got IP, connect to AP successfully */
|
||||
} sc_status;
|
||||
|
||||
typedef enum {
|
||||
SC_TYPE_ESPTOUCH = 0, /**< protocol: ESPTouch */
|
||||
SC_TYPE_AIRKISS, /**< protocol: AirKiss */
|
||||
SC_TYPE_ESPTOUCH_AIRKISS, /**< protocol: ESPTouch and AirKiss */
|
||||
} sc_type;
|
||||
|
||||
/**
|
||||
* @brief The callback of SmartConfig, executed when smart-config status changed.
|
||||
*
|
||||
* @param sc_status status : status of SmartConfig:
|
||||
* - if status == SC_STATUS_GETTING_SSID_PSWD, parameter void *pdata is a pointer
|
||||
of sc_type, means SmartConfig type: AirKiss or ESP-TOUCH.
|
||||
* - if status == SC_STATUS_LINK, parameter void *pdata is a pointer of struct station_config;
|
||||
* - if status == SC_STATUS_LINK_OVER, parameter void *pdata is a pointer of mobile
|
||||
* phone's IP address, 4 bytes. This is only available in ESPTOUCH, otherwise,
|
||||
* it is NULL.
|
||||
* - otherwise, parameter void *pdata is NULL.
|
||||
* @param void *pdata : data of SmartConfig
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
typedef void (*sc_callback_t)(sc_status status, void *pdata);
|
||||
|
||||
/**
|
||||
* @brief Get the version of SmartConfig.
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return SmartConfig version
|
||||
*/
|
||||
const char *smartconfig_get_version(void);
|
||||
|
||||
/**
|
||||
* @brief Start SmartConfig mode.
|
||||
*
|
||||
* Start SmartConfig mode, to connect ESP8266 station to AP, by sniffing
|
||||
* for special packets from the air, containing SSID and password of desired AP.
|
||||
* You need to broadcast the SSID and password (e.g. from mobile device or computer)
|
||||
* with the SSID and password encoded.
|
||||
*
|
||||
* @attention 1. This api can only be called in station mode.
|
||||
* @attention 2. During SmartConfig, ESP8266 station and soft-AP are disabled.
|
||||
* @attention 3. Can not call smartconfig_start twice before it finish, please call
|
||||
* smartconfig_stop first.
|
||||
* @attention 4. Don't call any other APIs during SmartConfig, please call smartconfig_stop first.
|
||||
*
|
||||
* @param sc_callback_t cb : SmartConfig callback; executed when SmartConfig status changed;
|
||||
* @param uint8 log : 1, UART output logs; otherwise, UART only outputs the result.
|
||||
*
|
||||
* @return true : succeed
|
||||
* @return false : fail
|
||||
*/
|
||||
bool smartconfig_start(sc_callback_t cb, ...);
|
||||
|
||||
/**
|
||||
* @brief Stop SmartConfig, free the buffer taken by smartconfig_start.
|
||||
*
|
||||
* @attention Whether connect to AP succeed or not, this API should be called to free
|
||||
* memory taken by smartconfig_start.
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return true : succeed
|
||||
* @return false : fail
|
||||
*/
|
||||
bool smartconfig_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Set timeout of SmartConfig.
|
||||
*
|
||||
* @attention SmartConfig timeout start at SC_STATUS_FIND_CHANNEL, SmartConfig will
|
||||
* restart if timeout.
|
||||
*
|
||||
* @param uint8 time_s : range 15s~255s, offset:45s.
|
||||
*
|
||||
* @return true : succeed
|
||||
* @return false : fail
|
||||
*/
|
||||
bool esptouch_set_timeout(uint8_t time_s);
|
||||
|
||||
/**
|
||||
* @brief Set protocol type of SmartConfig.
|
||||
*
|
||||
* @attention If users need to set the SmartConfig type, please set it before calling
|
||||
* smartconfig_start.
|
||||
*
|
||||
* @param sc_type type : AirKiss, ESP-TOUCH or both.
|
||||
*
|
||||
* @return true : succeed
|
||||
* @return false : fail
|
||||
*/
|
||||
bool smartconfig_set_type(sc_type type);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
2
components/smartconfig_ack/component.mk
Normal file
2
components/smartconfig_ack/component.mk
Normal file
@ -0,0 +1,2 @@
|
||||
#
|
||||
# Component Makefile
|
74
components/smartconfig_ack/include/smartconfig_ack.h
Normal file
74
components/smartconfig_ack/include/smartconfig_ack.h
Normal file
@ -0,0 +1,74 @@
|
||||
// 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_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
|
157
components/smartconfig_ack/smartconfig_ack.c
Normal file
157
components/smartconfig_ack/smartconfig_ack.c
Normal file
@ -0,0 +1,157 @@
|
||||
// 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.
|
||||
|
||||
/*
|
||||
* After station connects to AP and gets IP address by smartconfig,
|
||||
* it will use UDP to send 'ACK' to cellphone.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.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_ack.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 = -1;
|
||||
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 < LWIP_SOCKET_OFFSET) || (send_sock > (FD_SETSIZE - 1))) {
|
||||
ESP_LOGE(TAG, "Creat udp socket failed");
|
||||
goto _end;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
goto _end;
|
||||
}
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
_end:
|
||||
if ((send_sock >= LWIP_SOCKET_OFFSET) && (send_sock <= (FD_SETSIZE - 1))) {
|
||||
close(send_sock);
|
||||
}
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void sc_ack_send_stop(void)
|
||||
{
|
||||
s_sc_ack_send = false;
|
||||
}
|
Reference in New Issue
Block a user