Commit 32b8cc13 authored by 梁百峰's avatar 梁百峰

🎉 init:上传esp32程序,ble检测

parent cdd3bf39
build/
sdkconfig.old
/.vscode
*.o
*.s
*.log
*.lst
*.d
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
set(EXTRA_COMPONENT_DIRS "./source/wifi")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(TianYing100)
zs_rt2 esp32程序
\ No newline at end of file
sddadadadad
as
\ No newline at end of file
# Embed the server root certificate into the final binary
idf_build_get_property(project_dir PROJECT_DIR)
idf_component_register(SRCS "gatts_table_creat_demo.c"
"Protocol_CRC16.c"
"Protocol_Lib.c"
"Protocol_User.c"
"MCU_Core_Protocol.c"
"app_Ble_User.c"
"main_user.c"
INCLUDE_DIRS ".")
#include "Protocol_Lib.h"
#include "MCU_Core_Protocol.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "Protocol_User.h"
#include "gatts_table_creat_demo.h"
#include "app_Ble_User.h"
#ifndef _MCU_CORE_PROTOCOL_H_
#define _MCU_CORE_PROTOCOL_H_
#include "Protocol_Lib.h"
#endif
/**
* @file Protocol_CRC16.c
* @brief CRC16计算
* @details CRC16计算
* @author myliu
* @date 2022.05.09
* @version V1.0
* @copyright myiu
*/
#include "Protocol_CRC16.h"
static const Protocol_uint8_t CRC16_TAB_H [ 256 ] = {0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x01u, 0xC0u, 0x80u, 0x41u, 0x00u, 0xC1u, 0x81u, 0x40u};
static const Protocol_uint8_t CRC16_TAB_L [ 256 ] = {0x00u, 0xC0u, 0xC1u, 0x01u, 0xC3u, 0x03u, 0x02u, 0xC2u, 0xC6u, 0x06u, 0x07u, 0xC7u, 0x05u, 0xC5u, 0xC4u, 0x04u, 0xCCu, 0x0Cu, 0x0Du, 0xCDu, 0x0Fu, 0xCFu, 0xCEu, 0x0Eu, 0x0Au, 0xCAu, 0xCBu, 0x0Bu, 0xC9u, 0x09u, 0x08u, 0xC8u, 0xD8u, 0x18u, 0x19u, 0xD9u, 0x1Bu, 0xDBu, 0xDAu, 0x1Au, 0x1Eu, 0xDEu, 0xDFu, 0x1Fu, 0xDDu, 0x1Du, 0x1Cu, 0xDCu, 0x14u, 0xD4u, 0xD5u, 0x15u, 0xD7u, 0x17u, 0x16u, 0xD6u, 0xD2u, 0x12u, 0x13u, 0xD3u, 0x11u, 0xD1u, 0xD0u, 0x10u, 0xF0u, 0x30u, 0x31u, 0xF1u, 0x33u, 0xF3u, 0xF2u, 0x32u, 0x36u, 0xF6u, 0xF7u, 0x37u, 0xF5u, 0x35u, 0x34u, 0xF4u, 0x3Cu, 0xFCu, 0xFDu, 0x3Du, 0xFFu, 0x3Fu, 0x3Eu, 0xFEu, 0xFAu, 0x3Au, 0x3Bu, 0xFBu, 0x39u, 0xF9u, 0xF8u, 0x38u, 0x28u, 0xE8u, 0xE9u, 0x29u, 0xEBu, 0x2Bu, 0x2Au, 0xEAu, 0xEEu, 0x2Eu, 0x2Fu, 0xEFu, 0x2Du, 0xEDu, 0xECu, 0x2Cu, 0xE4u, 0x24u, 0x25u, 0xE5u, 0x27u, 0xE7u, 0xE6u, 0x26u, 0x22u, 0xE2u, 0xE3u, 0x23u, 0xE1u, 0x21u, 0x20u, 0xE0u, 0xA0u, 0x60u, 0x61u, 0xA1u, 0x63u, 0xA3u, 0xA2u, 0x62u, 0x66u, 0xA6u, 0xA7u, 0x67u, 0xA5u, 0x65u, 0x64u, 0xA4u, 0x6Cu, 0xACu, 0xADu, 0x6Du, 0xAFu, 0x6Fu, 0x6Eu, 0xAEu, 0xAAu, 0x6Au, 0x6Bu, 0xABu, 0x69u, 0xA9u, 0xA8u, 0x68u, 0x78u, 0xB8u, 0xB9u, 0x79u, 0xBBu, 0x7Bu, 0x7Au, 0xBAu, 0xBEu, 0x7Eu, 0x7Fu, 0xBFu, 0x7Du, 0xBDu, 0xBCu, 0x7Cu, 0xB4u, 0x74u, 0x75u, 0xB5u, 0x77u, 0xB7u, 0xB6u, 0x76u, 0x72u, 0xB2u, 0xB3u, 0x73u, 0xB1u, 0x71u, 0x70u, 0xB0u, 0x50u, 0x90u, 0x91u, 0x51u, 0x93u, 0x53u, 0x52u, 0x92u, 0x96u, 0x56u, 0x57u, 0x97u, 0x55u, 0x95u, 0x94u, 0x54u, 0x9Cu, 0x5Cu, 0x5Du, 0x9Du, 0x5Fu, 0x9Fu, 0x9Eu, 0x5Eu, 0x5Au, 0x9Au, 0x9Bu, 0x5Bu, 0x99u, 0x59u, 0x58u, 0x98u, 0x88u, 0x48u, 0x49u, 0x89u, 0x4Bu, 0x8Bu, 0x8Au, 0x4Au, 0x4Eu, 0x8Eu, 0x8Fu, 0x4Fu, 0x8Du, 0x4Du, 0x4Cu, 0x8Cu, 0x44u, 0x84u, 0x85u, 0x45u, 0x87u, 0x47u, 0x46u, 0x86u, 0x82u, 0x42u, 0x43u, 0x83u, 0x41u, 0x81u, 0x80u, 0x40u};
/**
* 获取CRC16校验和
*/
/**
* @brief 计算传入数据的CRC16
* @param[in] pData 计算的数据内容
* @param[in] len 计算的数据长度
*
* @return 校验和
*
* @since 1.0.0
*/
Protocol_uint16_t getCheckSum(const Protocol_uint8_t *pData, int len)
{
Protocol_uint8_t u8_crc_h = 0xFFu;
Protocol_uint8_t u8_crc_l = 0xFFu;
Protocol_uint8_t u8_index = 0u;
Protocol_uint8_t i = 0u;
Protocol_uint16_t re_value;
while ( len-- )
{
u8_index = u8_crc_h ^ (pData [ i++ ]);
u8_crc_h = u8_crc_l ^ CRC16_TAB_H [ u8_index ];
u8_crc_l = CRC16_TAB_L [ u8_index ];
}
re_value = ( Protocol_uint16_t )u8_crc_h << 8u;
re_value |= u8_crc_l;
return re_value;
}
#ifndef PROTOCOL_CRC16_H
#define PROTOCOL_CRC16_H
#include "Protocol_Lib.h"
Protocol_uint16_t getCheckSum(const Protocol_uint8_t *pData, int len);
#endif
/**
* @file Protocol_Lib.c
* @brief 串口协议解析
* @details 串口协议解析
* @author myliu
* @date 2022.05.09
* @version V1.0
* @copyright myiu
*/
#include <stdio.h>
#include <string.h>
#include "Protocol_CRC16.h"
#include "gatts_table_creat_demo.h"
static UARTOpen UARTOpen_Cbk;
static UARTSend UARTSend_Cbk;
static UARTRead UARTRead_Cbk;
static ProcParse ProcParseCbk;
static UARTClose UARTClose_Cbk;
static ProtocolSetData ProtocolSetData_Cbk;
static Protocol_uint8_t *mDataBufPtr = Protocol_NULL;
static Protocol_uint16_t mDataBufLen = 0;
static Protocol_uint32_t DataBufMaxLen = 0;
//#define DEBUG_PRO_DATA 0
/**
* @brief 初始化函数
* @param[in] pMemSpace 分配给协议库的内存空间,用来缓存串口数据
* @param[in] MemLen 分配的内存空间大小
* @param[in] pFunc 回调函数,包括串口打开、发送、读取、关闭,也包括解析后数据回传
* @param[in] ProcParseCbk 此回调函数,返回数据从FrameNo开始到CRC16之前,和ProtocolSetData_Cbk二选一
* @param[in] ProtocolSetData_Cbk 此回调函数,返回数据区分命令字、电源状态等,和ProcParseCbk二选一,详见结构体Protocol_Data_t
*
* @warning 此函数KL30和Wakeup都要调用,否则未分配内存,功能不好使,也有可能造成野指针复位
*
* @since 1.0.0
*/
void Protocol_Init(Protocol_uint8_t *pMemSpace, Protocol_uint32_t MemLen, Protocol_Func_t *pFunc)
{
mDataBufPtr = pMemSpace;
DataBufMaxLen = MemLen;
UARTOpen_Cbk = pFunc->UARTOpen_Cbk;
UARTSend_Cbk = pFunc->UARTSend_Cbk;
UARTRead_Cbk = pFunc->UARTRead_Cbk;
ProcParseCbk = pFunc->ProcParseCbk;
UARTClose_Cbk = pFunc->UARTClose_Cbk;
ProtocolSetData_Cbk = pFunc->ProtocolSetData_Cbk;
if ( UARTOpen_Cbk != Protocol_NULL )
{
UARTOpen_Cbk( );
}
return;
}
/**
* @brief 串口协议服务函数,包括读取数据,解析数据,如在外部读取数据,可不调用此函数
*
* @warning 此函数可自定义周期调用,建议20ms周期调用,最大不可超过协议的最小发送周期
*
* @since 1.0.0
*/
void Protocol_Service(void)
{
int len = 0;
int num =0;
Protocol_uint32_t readNum = 0;
if ( UARTRead_Cbk != Protocol_NULL )
{
readNum = UARTRead_Cbk(mDataBufPtr + mDataBufLen, 256 - mDataBufLen);
if ( readNum > 0 )
{
mDataBufLen += readNum;
// 解析协议
len = Protocol_Parse(mDataBufPtr, mDataBufLen);
len = 7;
if ( (len > 0) && (len < mDataBufLen) )
{
// 将未解析的数据移到头部
// Move unparsed data to the head
memcpy(mDataBufPtr, mDataBufPtr + len, mDataBufLen - len);
}
printf("get num~~~~~~~~~~~~~~%x\n",mDataBufPtr[0 ]);
printf("get num~~~~~~~~~~~~~~%x\n",mDataBufPtr[1]);
printf("get num~~~~~~~~~~~~~~%x\n",mDataBufPtr[2]);
printf("get num~~~~~~~~~~~~~~%x\n",mDataBufPtr[3]);
printf("get num~~~~~~~~~~~~~~%x\n",mDataBufPtr[4]);
printf("get num~~~~~~~~~~~~~~%x\n",mDataBufPtr[5]);
printf("get num~~~~~~~~~~~~~~%x\n",mDataBufPtr[6]);
mDataBufLen -= len;
}
}
}
/**
* @brief 协议解析函数,如外部获取数据(例如中断),可直接调用此函数解析数据
* @param[in] pData 协议数据内容
* @param[in] len 需要处理的协议数据长度
*
* @return 剩余已处理的数据长度
*
* @since 1.0.0
*/
Protocol_uint32_t Protocol_Parse(const Protocol_uint8_t *pData, Protocol_uint32_t len)
{
Protocol_uint32_t remainLen = len; // 剩余数据长度 Remaining data length
Protocol_uint32_t dataLen; // 数据包长度 Packet length
Protocol_uint32_t frameLen; // 帧长度 Frame length
Protocol_uint32_t frameSum;
Protocol_Data_t ProcData;
// int i = 0;
// int dataBuf [ 256 ];
/**
* 以下部分需要根据协议格式进行相应的修改,解析出每一帧的数据
*/
while ( remainLen >= DATA_PACKAGE_MIN_LEN )
{
// 找到一帧数据的数据头
// Find the data header of a frame of data
while ( (remainLen >= 2) && ((pData [ 0 ] != CMD_HEAD1) || (pData [ 1 ] != CMD_HEAD2)) )
{
pData++;
remainLen--;
continue;
}
if ( remainLen < DATA_PACKAGE_MIN_LEN )
{
#ifdef DEBUG_PRO_DATA
d_printf("too short!!!!!!\n");
#endif
break;
}
dataLen = pData [ 2 ];
frameLen = dataLen + DATA_PACKAGE_FIXED_LEN;
if ( frameLen > remainLen )
{
// 数据内容不全
#ifdef DEBUG_PRO_DATA
d_printf("Incomplete data packet!!!!!!\n");
#endif
break;
}
// 打印一帧数据,需要时在CommDef.h文件中打开DEBUG_PRO_DATA宏
#ifdef DEBUG_PRO_DATA
for ( i = 0; i < frameLen; ++i )
{
d_printf("%x ", pData [ i ]);
}
d_printf("\n");
#endif
// 检测校验码 Checksum
frameSum = (pData [ frameLen - 2 ] << 8) | (pData [ frameLen - 1 ]);
if ( frameLen > 4 )
{
if ( getCheckSum(pData + 2, frameLen - 4) == frameSum )
{
// 解析一帧数据
if ( ProcParseCbk != Protocol_NULL )
{
ProcParseCbk(pData + 3, dataLen - 2);
}
if ( ProtocolSetData_Cbk != Protocol_NULL )
{
ProcData.FrameNo = pData [ 3 ];
ProcData.PowerSts = (pData [ 4 ] >> 6) & 0x03;
ProcData.CmdID = pData [ 4 ] & 0x3F;
if ( ProcData.CmdID == 0x10 )
{
#ifdef DEBUG_PRO_DATA
for ( i = 0; i < frameLen; ++i )
{
d_printf("%x ", pData [ i ]);
}
d_printf("\n");
#endif
}
if ( ProcData.CmdID == 0x12 )
{
#ifdef DEBUG_PRO_DATA
for ( i = 0; i < frameLen; ++i )
{
d_printf("%x ", pData [ i ]);
}
d_printf("\n");
#endif
}
ProcData.DataLen = dataLen - 4;
memcpy(ProcData.Data, pData + 5, ProcData.DataLen);
ProtocolSetData_Cbk(&ProcData);
}
}
else
{
// for ( i = 0; i < frameLen; ++i )
// {
// dataBuf [ i ] = pData [ i ];
// }
// i = 0;
#ifdef DEBUG_PRO_DATA
d_printf("CheckSum error: new = %x, old = %x!!!!!!\n", getCheckSum(pData + 2, frameLen - 4), frameSum);
#endif
}
}
pData += frameLen;
remainLen -= frameLen;
}
return len - remainLen;
}
/**
* 根据协议格式进行拼接
*/
/**
* @brief 串口协议数据拼接,如初始化发送函数,调用此函数后,数据已通过串口发送
* @param[in] cmdID 命令字
* @param[in] pData 协议数据内容(不包括协议头、长度、帧序号、命令字、校验和,从数据域算起)
* @param[in] len 数据域长度
*
* @return 已发送的数据长度
*
* @since 1.0.0
*/
Protocol_uint32_t Protocol_Send(const Protocol_uint16_t cmdID, const Protocol_uint8_t *pData, Protocol_uint8_t len)
{
int i = 0;
Protocol_uint16_t checksum = 0;
Protocol_uint8_t dataBuf [ 256 ];
Protocol_uint32_t frameLen;
if ( len + DATA_PACKAGE_MIN_LEN > 256 )
{
// printf("sendProtocol data is too len !!!\n");
return 0;
}
dataBuf [ 0 ] = CMD_HEAD1;
dataBuf [ 1 ] = CMD_HEAD2; // 同步帧头 Sync frame header
dataBuf [ 2 ] = len + 4;
dataBuf [ 3 ] = len; // 命令字节 Command byte
dataBuf [ 4 ] = ( Protocol_uint8_t )cmdID;
frameLen = 5;
// 数据 Data
for ( i = 0; i < len; ++i )
{
dataBuf [ frameLen ] = pData [ i ];
frameLen++;
}
// 校验码 Checksum
checksum = getCheckSum(dataBuf + 2, frameLen - 2);
dataBuf [ frameLen ] = (checksum >> 8) & 0x00FF;
frameLen++;
dataBuf [ frameLen ] = checksum & 0x00FF;
frameLen++;
if ( UARTSend_Cbk != Protocol_NULL )
{
return UARTSend_Cbk(dataBuf, frameLen);
}
else
{
return 0;
}
}
#ifndef PROTOCOL_LIB_H
#define PROTOCOL_LIB_H
/*
Platform_32Bit
Platform_16Bit
*/
#ifdef Platform_16Bit
#define Protocol_uint8_t unsigned char
#define Protocol_uint16_t unsigned int
#define Protocol_uint32_t unsigned long
#else
#define Protocol_uint8_t unsigned char
#define Protocol_uint16_t unsigned short
#define Protocol_uint32_t unsigned int
#define Protocol_uint64_t unsigned long long
#endif
#ifndef Protocol_NULL
#define Protocol_NULL ( void * )0u
#endif /* NULL */
/**<0xEB 0x90 长度 帧序号 命令字 DATA0-DATAN CRC16_1 CRC16_2*/
#define DATA_PACKAGE_MIN_LEN 7 /**< 0xEB 0x90 + 长度 + 数据包序号 + CMDID + CRC16_1 + CRC16_2 */
#define DATA_PACKAGE_FIXED_LEN 3 /**< 未计算在长度内的数据 0xEB 0x90 + 长度位 */
#define CMD_HEAD1 0xEB
#define CMD_HEAD2 0x90
/**@struct Protocol_Data_t
* @brief 解析后的协议数据
*/
typedef struct
{
Protocol_uint8_t FrameNo; /**< 帧序号 */
Protocol_uint8_t PowerSts; /**< 电源状态 */
Protocol_uint8_t CmdID; /**< 命令字 */
Protocol_uint8_t DataLen; /**< 有效数据长度 DATA0-DATAN*/
Protocol_uint8_t Data [ 256 ]; /**< 有效数据内容 DATA0-DATAN*/
} Protocol_Data_t;
typedef Protocol_uint8_t (*UARTOpen)(void);
typedef Protocol_uint32_t (*UARTSend)(const Protocol_uint8_t *pData, Protocol_uint32_t u32Len);
typedef Protocol_uint32_t (*UARTRead)(Protocol_uint8_t *pData, Protocol_uint32_t u32Len);
typedef void (*ProtocolSetData)(const Protocol_Data_t *pData);
typedef void (*ProcParse)(const Protocol_uint8_t *pData, Protocol_uint32_t u32Len);
typedef void (*UARTClose)(void);
/**@struct Protocol_Func_t
* @brief 协议解析回调函数
*/
typedef struct
{
UARTOpen UARTOpen_Cbk; /**< 串口打开回调 */
UARTSend UARTSend_Cbk; /**< 串口发送回调 */
UARTRead UARTRead_Cbk; /**< 串口读取回调 */
UARTClose UARTClose_Cbk; /**< 串口关闭回调 */
ProcParse ProcParseCbk; /**< 解析后的数据, 处理了数据包序号,命令字和电源状态,和ProcParse二选一 */
ProtocolSetData ProtocolSetData_Cbk; /**< 不包含 0xEB 0x90 + 长度 + CRC16_1 + CRC16_2,和ProtocolSetData二选一 */
} Protocol_Func_t;
void Protocol_Init(Protocol_uint8_t *pMemSpace, Protocol_uint32_t MemLen, Protocol_Func_t *pFunc);
void Protocol_Service(void);
Protocol_uint32_t Protocol_Parse(const Protocol_uint8_t *pData, Protocol_uint32_t len);
Protocol_uint32_t Protocol_Send(const Protocol_uint16_t cmdID, const Protocol_uint8_t *pData, Protocol_uint8_t len);
#endif
This diff is collapsed.
#ifndef PROTOCOL_USER_H
#define PROTOCOL_USER_H
#include "Protocol_Lib.h"
#define BLE_START_STA 0x10
#define MCU_REPLY 0x20
#define BLE_NAVIGATION 0x01
#define BLE_WEATHER 0x02
#define BLE_LOCATION 0x03
#define BLE_STA 0x12
#define MCU_TO_BLE_INFO 0x21
void Protocol_KL30_Wakeup_Init(void);
void Protocol_Send_Service(void); // 10ms任务调用
void UART_Put(Protocol_uint16_t Data);
typedef enum
{
Prot_Idle = 0,
Prot_Starting,
Prot_Start,
Prot_Normal,
}Prot_User_State_Enum;
typedef struct
{
uint8_t State;
uint16_t TimeDelay;
}Protocol_User_Ctrl_Struct;
extern Protocol_User_Ctrl_Struct Prot_User;
void Protocol_User_Ctrl_Init(void );
void Prot_Send_Msg_Process(void );
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#ifndef GATTS_TABLE_CREAT_DEMO_H
#define GATTS_TABLE_CREAT_DEMO_H
/* Attributes State Machine */
enum
{
IDX_SVC,
IDX_CHAR_2A29,
IDX_CHAR_VAL_2A29,
IDX_CHAR_CFG_2A29,
IDX_CHAR_2A24,
IDX_CHAR_VAL_2A24,
IDX_CHAR_CFG_2A24,
IDX_CHAR_2A25,
IDX_CHAR_VAL_2A25,
IDX_CHAR_CFG_2A25,
IDX_CHAR_2A27,
IDX_CHAR_VAL_2A27,
IDX_CHAR_CFG_2A27,
IDX_CHAR_2A26,
IDX_CHAR_VAL_2A26,
IDX_CHAR_CFG_2A26,
IDX_CHAR_2A28,
IDX_CHAR_VAL_2A28,
IDX_CHAR_CFG_2A28,
IDX_CHAR_2A23,
IDX_CHAR_VAL_2A23,
IDX_CHAR_CFG_2A23,
IDX_CHAR_2A2A,
IDX_CHAR_VAL_2A2A,
IDX_CHAR_CFG_2A2A,
IDX_CHAR_2A50,
IDX_CHAR_VAL_2A50,
IDX_CHAR_CFG_2A50,
HRS_IDX_NB,
};
enum
{
IDX_SVC2,
IDX_CHAR_A2,
IDX_CHAR_VAL_A2,
IDX_CHAR_CFG_A2,
HRS_IDX_NB2,
};
void bsp_Ble_Init(void);
void bsp_Uart_Init(void );
int bsp_Ble_Gatts_Send_Indicate(uint8_t len, uint8_t *data);
void simple_ota_service(void);
extern uint8_t BT_Device_Name[13];
void Get_Mac_Init(void );
extern int bsp_Uart_Send_Data(uint8_t * data , unsigned int len);
extern void ble_send(void);
#endif
#include "app_Ble_User.h"
#include "gatts_table_creat_demo.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "string.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "gatts_table_creat_demo.h"
#include "main_user.h"
#include "Protocol_CRC16.h"
#include "Protocol_User.h"
// #include "bt_app_main.h"
// #include "app_BT_User.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "string.h"
#include "driver/gpio.h"
#include "MCU_Core_Protocol.h"
#include "Protocol_Lib.h"
#include "app_Ble_User.h"
// #include "app_BT_User.h"
// #include "bt_app_hf.h"
#include "wifi_service.h"
#define TAG "MAIN_USER"
// extern esp_bd_addr_t peer_addr;
uint32_t Sys_1ms_Cnt;
TaskHandle_t wifi_service_hdl;
#define SYS_RUN_TASK_1MS (1)
#define SYS_RUN_TASK_10MS (Sys_1ms_Cnt % 10 == 1)
#define SYS_RUN_TASK_20MS (Sys_1ms_Cnt % 20 == 2)
#define SYS_RUN_TASK_50MS (Sys_1ms_Cnt % 50 == 3)
#define SYS_RUN_TASK_100MS (Sys_1ms_Cnt % 100 == 4)
#define SYS_RUN_TASK_1000MS (Sys_1ms_Cnt % 1000 == 5)
uint32_t testcnt;
static void Sys_Run_Tasks(void *arg)
{
// uint8_t i = 0;
while(1)
{
if(Sys_1ms_Cnt < 499)
{
Sys_1ms_Cnt ++ ;
}
else
{
Sys_1ms_Cnt = 0;
}
if(SYS_RUN_TASK_10MS)
{
Protocol_Send_Service();
Protocol_Service();
// BT_User_Process();
}
if(SYS_RUN_TASK_20MS)
{
}
if(SYS_RUN_TASK_50MS)
{
Prot_Send_Msg_Process();
}
if(SYS_RUN_TASK_100MS)
{
Ble_MsgRec_Navi_Timeout();
}
if(SYS_RUN_TASK_1000MS)
{
ble_send();
simple_ota_service();
testcnt++;
if(testcnt >= 10)
{
testcnt = 0;
// printf("BT_User.BT_Sts = %d\r\n", BT_User.BT_Sts);
// printf("Ble_User.Ble_Sts = %d\r\n", Ble_User.Ble_Sts);
// esp_log_buffer_hex(TAG, peer_addr, 6);
// printf("Ble_User.Navi_Updat = %d\r\n", Ble_User.Navi_Updat);
// printf("RecCtrl.Sts = %d\r\n", RecCtrl.Sts);
// Ble_Msg_RequestNavi_RLY();
// if(Prot_User.State < Prot_Normal)
// {
// Prot_User.State = Prot_Normal;
// printf("Prot_Normal \r\n");
// }
}
}
vTaskDelay(1);
}
vTaskDelete(NULL);
}
static void wifi_service_task(void *arg)
{
while (1)
{
wifi_service_timer();
wifi_service();
vTaskDelay(pdMS_TO_TICKS(100));
}
}
void app_main(void)
{
Protocol_User_Ctrl_Init();
// BT_User_Init();
Ble_User_Init();
bsp_Ble_Init();
// Get_Mac_Init();
// bsp_BT_Init();
// bsp_Ble_Init();
bsp_Uart_Init();
//printf("KL30 INIT OVER~~~~~~\r\n");
xTaskCreatePinnedToCore(Sys_Run_Tasks, "Sys_Run_Tasks", 4096, NULL, 3, NULL, 1);
// xTaskCreatePinnedToCore(wifi_service_task, "wifi_service_task", 4096, NULL, 5, &wifi_service_hdl, 1);
}
#ifndef _MAIN_USER_H_
#define _MAIN_USER_H_
#endif
\ No newline at end of file
# Name, Type, SubType, Offset, Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
nvs, data, nvs, , 0x4000,
otadata, data, ota, , 0x2000,
phy_init, data, phy, , 0x1000,
ota_0, app, ota_0, , 2M,
ota_1, app, ota_1, , 2M,
\ No newline at end of file
This diff is collapsed.
idf_component_register(SRCS "wifi_service.c" "softap.c" "http_server.c"
INCLUDE_DIRS "."
PRIV_REQUIRES nvs_flash esp_netif esp_wifi esp_http_server app_update driver
EMBED_FILES "html/favicon.ico" "html/index.html" "html/ota.html")
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="utf-8">
<title>ESP32</title>
</head>
<body>
<h2>ESP32</h2>
<hr><br>
<button id="ota" type="button" onclick="ota()">ESP32 固件升级</button>
<script>
function ota() {
window.location.href = "http://192.168.4.1/ota";
}
</script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="utf-8">
<title>固件升级</title>
</head>
<body>
<h2>固件升级</h2>
<hr>
<a href="http://192.168.4.1" style="font-size: smaller;">[返回首页]</a><br><br>
<!-- 选择文本按钮 -->
<label for="newFile">加载文件:</label>
<input id="newFile" type="file" accept=".bin" onchange="checkFile()">
<br><br>
<!-- 上传操作 -->
<label for="otaStart">执行操作:</label>
<button id="otaStart" type="button" onclick="otaStart()">开始升级</button>
<button id="reload" type="button" onclick="reload()">刷新界面</button>
<br><br>
<!-- 进度显示 -->
<label for="otaPercent">进度显示:</label>
<input id="otaPercent" type="text" value="0.00%" style="width: 75px;border: none;font-size:large;">
<progress id="otaProgress" value="0" max="100"></progress>
<br><br><hr>
<p id="viewName"></p>
<p id="viewSize"></p>
<p id="viewFlashStart"></p>
<p id="viewFlashResult"></p>
<script>
function reload() {
location.reload();
}
function getFileSize(size) {
if (!size) return "";
var num = 1024.00;
if (size < num) {
return size + "B";
}
if (size < Math.pow(num, 2)) {
return (size / num).toFixed(2) + "KB";
}
if (size < Math.pow(num, 3)) {
return (size / Math.pow(num, 2)).toFixed(2) + "MB";
}
}
function checkFile() {
var newFile = document.getElementById("newFile").files[0];
var newFileName = newFile.name;
var newFileSize = newFile.size;
if (newFileSize > 2 * 1024 * 1024) {
alert('所选文件超出最大限制\n点击确定后将自动刷新页面');
location.reload();
}
else {
document.getElementById("viewName").innerHTML = "文件名称:" + newFileName;
document.getElementById("viewSize").innerHTML = "文件大小:" + getFileSize(newFileSize);
}
}
function otaStart() {
var res = document.getElementById("newFile").files[0];
if (typeof (res) == "undefined") {
alert('未选择文件!');
}
else {
var filepath = document.getElementById("newFile").files[0].name;
var upload_path = "/ota/" + filepath;
document.getElementById("viewFlashStart").innerHTML = "锁定页面,请务必保持WiFi在线,正在上传...";
document.getElementById("newFile").disabled = true;
document.getElementById("otaStart").disabled = true;
var file = document.getElementById("newFile").files[0];
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (xhttp.readyState == 4) {
if (xhttp.status == 200) {
document.getElementById("viewFlashResult").innerHTML = "上传成功!";
} else if (xhttp.status == 0) {
document.getElementById("viewFlashResult").innerHTML = "服务器断开!<br><br>请检查服务器是否在线,刷新页面后重新上传...";
} else {
alert(xhttp.status + " Error!\n" + xhttp.responseText);
}
}
};
let progressBar = document.getElementById("otaProgress");
xhttp.upload.onprogress = function (e) {
var percentage = (event.loaded * 100.00) / (event.total * 1.00);
percentage = percentage.toFixed(2);
progressBar.value = Math.round(percentage);
document.getElementById("otaPercent").value = percentage + "%";
}
xhttp.open("POST", upload_path, true);
xhttp.send(file);
}
}
</script>
</body>
</html>
\ No newline at end of file
#include <string.h>
#include <esp_log.h>
#include <nvs_flash.h>
#include <sys/param.h>
#include <sys/stat.h>
#include "esp_netif.h"
#include <esp_wifi.h>
#include <esp_system.h>
#include "nvs_flash.h"
#include "esp_ota_ops.h"
#include "http_server.h"
static const char *TAG = "http_server";
char buf[MAX_OTA_BUFF]; // 接收服务端传来的文件缓存, 必须使用全局变量, 否则会触发看门狗复位, 原理未知
httpd_handle_t http_server = NULL;
static esp_err_t http_resp_index_html(httpd_req_t *req)
{
extern const unsigned char index_html_start[] asm("_binary_index_html_start");
extern const unsigned char index_html_end[] asm("_binary_index_html_end");
const size_t index_html_size = (index_html_end - index_html_start);
ESP_LOGI(TAG, "---- DevKit首页");
httpd_resp_set_type(req, "text/HTML");
httpd_resp_send(req, (const char *)index_html_start, index_html_size);
return ESP_OK;
}
static esp_err_t http_resp_favicon_ico(httpd_req_t *req)
{
extern const unsigned char favicon_ico_start[] asm("_binary_favicon_ico_start");
extern const unsigned char favicon_ico_end[] asm("_binary_favicon_ico_end");
const size_t favicon_ico_size = (favicon_ico_end - favicon_ico_start);
ESP_LOGI(TAG, "---- 下载网站图标");
httpd_resp_set_type(req, "image/x-icon");
httpd_resp_send(req, (const char *)favicon_ico_start, favicon_ico_size);
return ESP_OK;
}
static esp_err_t http_resp_ota_html(httpd_req_t *req)
{
extern const unsigned char ota_html_start[] asm("_binary_ota_html_start");
extern const unsigned char ota_html_end[] asm("_binary_ota_html_end");
const size_t ota_html_size = (ota_html_end - ota_html_start);
ESP_LOGI(TAG, "---- 进入固件升级页面");
httpd_resp_set_type(req, "text/HTML");
httpd_resp_send(req, (const char *)ota_html_start, ota_html_size);
return ESP_OK;
}
static esp_err_t http_resp_handler(httpd_req_t *req)
{
const char *uri_get = req->uri;
ESP_LOGI(TAG, "---- request uri: 192.168.4.1%s", req->uri);
if (strcmp(uri_get, "/") == 0)
{
return http_resp_index_html(req);
}
else if (strcmp(uri_get, "/favicon.ico") == 0)
{
return http_resp_favicon_ico(req);
}
else if (strcmp(uri_get, "/ota") == 0)
{
return http_resp_ota_html(req);
}
else
{
ESP_LOGI(TAG, "---- 未知链接, 不处理, 直接回到起始页");
return http_resp_index_html(req);
}
return ESP_OK;
}
static esp_err_t http_ota_handler(httpd_req_t *req)
{
int ret = 0;
int recv_block = 0;
int remaining = req->content_len;
int total = remaining;
double percent = 0.0;
ESP_LOGI(TAG, "---- 应用程序更新, 需接收数据长度(bytes): %d", remaining);
esp_ota_handle_t app_update_handle = 0;
const esp_partition_t *app_update_partition = esp_ota_get_next_update_partition(NULL);
esp_err_t err = esp_ota_begin(app_update_partition, OTA_WITH_SEQUENTIAL_WRITES, &app_update_handle);
while (remaining > 0)
{
/* Read the data for the request */
if ((ret = httpd_req_recv(req, buf, MIN(remaining, sizeof(buf)))) <= 0)
{
if (ret == HTTPD_SOCK_ERR_TIMEOUT)
{
/* Retry receiving if timeout occurred */
continue;
}
return ESP_FAIL;
}
err = esp_ota_write(app_update_handle, buf, ret);
if (err != ESP_OK)
{
ESP_LOGI(TAG, "---- 写入数据失败, 错误信息:%s", esp_err_to_name(err));
}
else
{
remaining -= ret;
recv_block++;
if ((recv_block % 20) == 0)
{
percent = 100.0 - (double)(remaining * 100) / (double)total;
ESP_LOGI(TAG, "---- 写入OTA升级数据: %.2f%%", percent);
}
}
// 增加20ms延时, 解决CPU0看门狗超时的问题
vTaskDelay(pdMS_TO_TICKS(20));
}
err = esp_ota_end(app_update_handle);
if (err == ESP_OK)
{
esp_err_t err = esp_ota_set_boot_partition(app_update_partition);
if (err != ESP_OK)
{
ESP_LOGI(TAG, "---- 设备启动分区失败, 错误信息:%s", esp_err_to_name(err));
}
else
{
ESP_LOGI(TAG, "---- 应用程序更新完成, 3秒后自动重启.");
httpd_resp_send_chunk(req, NULL, 0);
// httpd_resp_sendstr(req, "<p>应用程序更新完成,3秒后自动重启.</p>");
vTaskDelay(pdMS_TO_TICKS(3000));
esp_restart();
}
}
// End response
ESP_LOGI(TAG, "---- 数据接收完成, OTA失败, 1秒后自动重启.");
// httpd_resp_sendstr(req, "<p>数据上传完成,但应用更新不成功,请重试.</p>");
httpd_resp_send_chunk(req, NULL, 0);
vTaskDelay(pdMS_TO_TICKS(1000));
esp_restart();
return ESP_OK;
}
httpd_handle_t start_webserver(void)
{
httpd_handle_t server = NULL;
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.lru_purge_enable = true;
config.uri_match_fn = httpd_uri_match_wildcard;
// Start the httpd server
ESP_LOGI(TAG, "---- 服务器端口号: '%d'", config.server_port);
if (httpd_start(&server, &config) == ESP_OK)
{
// Set URI handlers
ESP_LOGI(TAG, "---- 注册URI管理程序");
// 注册客户端请求行为
httpd_uri_t http_resp = {
.uri = "/*",
.method = HTTP_GET,
.handler = http_resp_handler,
.user_ctx = NULL};
httpd_register_uri_handler(server, &http_resp);
// 注册客户端OTA行为
httpd_uri_t http_ota = {
.uri = "/ota/*",
.method = HTTP_POST,
.handler = http_ota_handler,
.user_ctx = NULL};
httpd_register_uri_handler(server, &http_ota);
return server;
}
ESP_LOGI(TAG, "---- 服务器启动时发生错误.");
return NULL;
}
esp_err_t stop_webserver(httpd_handle_t server)
{
return httpd_stop(server);
}
void connect_handler(void *arg)
{
httpd_handle_t *server = (httpd_handle_t *)arg;
if (*server == NULL)
{
ESP_LOGI(TAG, "---- 开启HTTP服务器");
*server = start_webserver();
}
}
void disconnect_handler(void *arg)
{
httpd_handle_t *server = (httpd_handle_t *)arg;
if (*server)
{
ESP_LOGI(TAG, "---- 关闭HTTP服务器");
if (stop_webserver(*server) == ESP_OK)
{
*server = NULL;
}
else
{
ESP_LOGE(TAG, "Failed to stop http server");
}
}
}
httpd_handle_t http_service(void)
{
static httpd_handle_t server = NULL;
// 首次启动http_server
server = start_webserver();
if (server)
{
ESP_LOGI(TAG, "---- HTTP服务器开启成功.");
}
else
{
ESP_LOGI(TAG, "---- HTTP服务器开启失败.");
}
return server;
}
#ifndef _GTTP_SERVER_H_
#define _GTTP_SERVER_H_
#include "esp_event.h"
#include "esp_http_server.h"
#define HTTP_SERVER_STOP 0
#define HTTP_SERVER_INIT 1
#define HTTP_SERVER_START 2
#define HTTP_SERVER_DEINIT 3
#define MAX_OTA_BUFF 4096u
extern char buf[MAX_OTA_BUFF];
extern httpd_handle_t http_server;
/**
* 根据某种状态自动开关webserver的监听处理,
* 任意STA连接AP,自动开启webserver.
*/
void connect_handler(void *arg);
/**
* 根据某种状态自动开关webserver的监听处理,
* 没有任何STA连接AP,自动关闭webserver,
*/
void disconnect_handler(void *arg);
/**
* 开启HTTP服务器
* @return httpd_handle_t 结构体
*/
httpd_handle_t http_service(void);
#endif
#include <stdio.h>
#include <string.h>
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_mac.h"
#include "esp_netif.h"
#include "esp_log.h"
#include "softap.h"
#include "wifi_service.h"
static const char *TAG = "softAP";
esp_netif_t *softap_netif = NULL;
wifi_sta_list_t softap_sta_list;
unsigned char softap_sta_connect = STA_CONNECTED_NEVER;
static void softap_event_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STACONNECTED)
{
wifi_event_ap_staconnected_t *event = (wifi_event_ap_staconnected_t *)event_data;
ESP_LOGI(TAG, "---- 设备加入网络, MAC地址 :" MACSTR ", 编号(AID) = %d.", MAC2STR(event->mac), event->aid);
softap_sta_connect = STA_CONNECTED_ONCE;
connect_handler(event_handler_arg);
wifi_service_stop_timer_clear();
}
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STADISCONNECTED)
{
wifi_event_ap_stadisconnected_t *event = (wifi_event_ap_stadisconnected_t *)event_data;
ESP_LOGI(TAG, "---- 设备退出网络, MAC地址 :" MACSTR ", 编号(AID) = %d.", MAC2STR(event->mac), event->aid);
disconnect_handler(event_handler_arg);
wifi_service_stop_timer_clear();
}
}
void softap_service_start(void)
{
// NVS分区初始化
ESP_LOGI(TAG, "---- nvs分区初始化...");
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
{
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
// 创建系统事件循环
ESP_LOGI(TAG, "---- 创建系统事件循环...");
ESP_ERROR_CHECK(esp_event_loop_create_default());
// 将WiFi的所有事件作为实例注册进系统事件循环中
ESP_LOGI(TAG, "---- 注册WiFi事件实例...");
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, softap_event_handler, &http_server));
// 初始化网卡相关的底层配置
ESP_LOGI(TAG, "---- 网卡初始化...");
ESP_ERROR_CHECK(esp_netif_init());
// 以默认的方式创建一个ap类型的网卡
ESP_LOGI(TAG, "---- 创建AP类型网卡...");
softap_netif = esp_netif_create_default_wifi_ap();
// 初始化WiFi底层配置
ESP_LOGI(TAG, "---- WiFi初始化...");
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
// 将WiFi设置成AP模式
ESP_LOGI(TAG, "---- 配置WiFi为AP模式...");
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
// 创建AP配置
ESP_LOGI(TAG, "---- 创建AP配置...");
wifi_config_t wifi_config = {
.ap = {
.ssid = ESP_WIFI_SSID,
.ssid_len = strlen(ESP_WIFI_SSID),
.password = ESP_WIFI_PASSWD,
.max_connection = 1,
.authmode = WIFI_AUTH_WPA_WPA2_PSK}};
// 获取当前AP的MAC地址
unsigned char softap_mac[6];
esp_wifi_get_mac(WIFI_IF_AP, softap_mac);
// 将MAC地址后两个字节转为字符串
char softap_temp[5];
sprintf(softap_temp, "%02X%02X", softap_mac[4], softap_mac[5]);
// 将MAC地址拼接到 ESP_WIFI_SSID 后面
char softap_ssid[32] = ESP_WIFI_SSID;
strcat(softap_ssid, softap_temp);
// 重新配置 ssid 和 ssid_len
memcpy(wifi_config.ap.ssid, softap_ssid, sizeof(softap_ssid));
wifi_config.ap.ssid_len = strlen(softap_ssid);
// 配置AP的属性
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
// 开启WiFi
ESP_LOGI(TAG, "---- 开启WiFi, 名称 : %s 密码 : %s", wifi_config.ap.ssid, wifi_config.ap.password);
ESP_ERROR_CHECK(esp_wifi_start());
// 首次开启http_server
ESP_LOGI(TAG, "---- 首次开启HTTP服务器...");
http_server = http_service();
// 启动服务关闭计时器
ESP_LOGI(TAG, "---- 启动服务关闭计时器...");
wifi_service_stop_timer_clear();
}
void softap_service_stop(void)
{
// 关闭http_server
ESP_LOGI(TAG, "---- 关闭HTTP服务器...");
disconnect_handler(&http_server);
// 关闭WiFi
ESP_LOGI(TAG, "---- 关闭WiFi...");
ESP_ERROR_CHECK(esp_wifi_stop());
// WiFi反初始化
ESP_LOGI(TAG, "---- WiFi反初始化...");
ESP_ERROR_CHECK(esp_wifi_deinit());
// 销毁网卡实例
ESP_LOGI(TAG, "---- 销毁网卡实例...");
esp_netif_destroy_default_wifi(softap_netif);
// 网卡反初始化 - 官方未实现的功能
// ESP_LOGI(TAG, "---- 网卡反初始化...");
// ESP_ERROR_CHECK(esp_netif_deinit());
// 注销WiFi事件实例
ESP_LOGI(TAG, "---- 注销WiFi事件实例...");
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, softap_event_handler));
// 删除系统事件循环
ESP_LOGI(TAG, "---- 删除系统事件循环...");
ESP_ERROR_CHECK(esp_event_loop_delete_default());
// NVS分区反初始化
ESP_LOGI(TAG, "---- NVS分区反初始化...");
ESP_ERROR_CHECK(nvs_flash_deinit());
ESP_LOGI(TAG, "---- WiFi服务已关闭, 重置WiFi参数");
wifi_service_init();
}
#ifndef _SOFTAP_H_
#define _SOFTAP_H_
#include "esp_wifi.h"
#include "http_server.h"
#define SOFTAP_STOP 0
#define SOFTAP_INIT 1
#define SOFTAP_START 2
#define SOFTAP_DEINIT 3
#define STA_CONNECTED_NEVER 0
#define STA_CONNECTED_ONCE 1
#define ESP_WIFI_SSID "ESP32S3_AP_"
#define ESP_WIFI_PASSWD "12345677"
extern wifi_sta_list_t softap_sta_list;
extern unsigned char softap_sta_connect;
/**
* 开启 WiFi 服务
*/
void softap_service_start(void);
/**
* 关闭 WiFi 服务
*/
void softap_service_stop(void);
#endif
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "esp_wifi.h"
#include "wifi_service.h"
static const char *TAG = "wifi_service";
/*****************************************************
* 首次启动HTTP服务器后, 如果一直没有STA设备加入
* 就不能触发STA disconnect事件,也就不会自动关闭HTTP服务器
* 所以需要额外判断这种情况, 当30秒关闭的定时器触发2次后直接关闭
******************************************************/
static unsigned char http_server_stop_counter = 0;
static unsigned char softap_service_stop_flag = 0;
static unsigned short wifi_service_start_timer = 0;
static unsigned short wifi_service_stop_timer = 0;
wifi_service_t wifi_service_info;
void wifi_service_init(void)
{
wifi_service_stop_timer = 0;
softap_service_stop_flag = 0;
http_server_stop_counter = 0;
wifi_service_info.status = WIFI_SERVICE_STOP;
wifi_service_info.softap_status = SOFTAP_STOP;
wifi_service_info.http_server_status = HTTP_SERVER_STOP;
wifi_service_info.ota_partition = 0;
}
void wifi_service_timer(void)
{
if (wifi_service_info.status == WIFI_SERVICE_STOP)
{
if (wifi_service_start_timer < 60)
{
++wifi_service_start_timer;
}
// 上电5秒自动开启WiFi服务
if (wifi_service_start_timer == 50)
{
wifi_service_info.status = WIFI_SERVICE_INIT;
}
}
if (wifi_service_info.status == WIFI_SERVICE_START)
{
if (wifi_service_stop_timer < 300)
{
++wifi_service_stop_timer;
}
// 每30秒尝试关闭WiFi服务
if (wifi_service_stop_timer == 300)
{
wifi_service_info.status = WIFI_SERVICE_DEINIT;
}
}
}
void wifi_service_stop_timer_clear(void)
{
wifi_service_stop_timer = 0;
}
void wifi_service(void)
{
if (wifi_service_info.status == WIFI_SERVICE_INIT) // 收到指令: WiFi服务初始化
{
wifi_service_info.status = WIFI_SERVICE_START;
ESP_LOGI(TAG, "---- 关闭CAN总线, 卸载LIN driver, 开启WiFi服务...");
softap_service_start();
}
else
{
if (wifi_service_info.status == WIFI_SERVICE_DEINIT) // 收到指令: WiFi服务反初始化, 先读取当前连接的STA数量
{
esp_err_t ret = esp_wifi_ap_get_sta_list(&softap_sta_list);
if (ret == ESP_OK)
{
if (softap_sta_list.num == 0) // 当前没有STA连接
{
if (softap_sta_connect == STA_CONNECTED_NEVER) // 从未有STA接入过
{
if (http_server_stop_counter == 1)
{
softap_service_stop_flag = 1;
}
else
{
ESP_LOGI(TAG, "首次启动HTTP服务器, 1分钟内不会关闭WiFi");
++http_server_stop_counter; // 服务器开启状态且没有设备接入过, 延后30秒再关闭
}
}
else
{
softap_service_stop_flag = 1; // 关闭WiFi服务
}
}
else
{
ESP_LOGI(TAG, "---- 有STA设备在线, 拒绝关闭WiFi");
}
}
else
{
ESP_LOGI(TAG, "---- 读取当前连接的STA数量失败, 打印错误信息");
esp_err_to_name(ret);
}
if (softap_service_stop_flag == 1)
{
wifi_service_info.status = WIFI_SERVICE_STOP;
ESP_LOGI(TAG, "---- 关闭WiFi服务, 开启CAN总线, 重装LIN driver...");
softap_service_stop();
}
else
{
wifi_service_info.status = WIFI_SERVICE_START;
wifi_service_stop_timer = 0; // 重置HTTP服务器关闭的定时器
}
}
}
}
#ifndef _WIFI_SERVICE_H_
#define _WIFI_SERVICE_H_
#include "softap.h"
#define WIFI_SERVICE_STOP 0
#define WIFI_SERVICE_INIT 1
#define WIFI_SERVICE_START 2
#define WIFI_SERVICE_DEINIT 3
typedef struct
{
unsigned char status;
unsigned char softap_status; // 暂时用不上 2024.05.08
unsigned char http_server_status; // 暂时用不上 2024.05.08
unsigned char ota_partition; // 暂时用不上 2024.05.08
} wifi_service_t;
extern wifi_service_t wifi_service_info;
/**
* 初始化 WiFi 服务状态
*/
void wifi_service_init(void);
/**
* WiFi 服务计时器
*/
void wifi_service_timer(void);
/**
* WiFi 服务自动关闭计时器的重置函数
*/
void wifi_service_stop_timer_clear(void);
/**
* WiFi 服务启停控制
*/
void wifi_service(void);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment