初始提交卡包 USB 工程
纳入固件源码、屏幕组件、nand_xfer 工具和文档。忽略本机构建产物、sdkconfig,以及含本机路径的依赖锁。 Co-authored-by: Cursor <[email protected]>
This commit is contained in:
+1568
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,87 @@
|
||||
#ifndef _BLE_H_
|
||||
#define _BLE_H_
|
||||
|
||||
#include "esp_err.h"
|
||||
#include <stdbool.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* NimBLE 在 ble_hs.c 中实现,公开 host/ble_hs.h 未导出 */
|
||||
void ble_hs_lock(void);
|
||||
void ble_hs_unlock(void);
|
||||
|
||||
extern const char *BLE_TAG;
|
||||
extern bool notify_enabled;
|
||||
extern volatile bool sentinel_mode_is_active;
|
||||
extern char s_emoji_delete_target_pack;
|
||||
extern TaskHandle_t notification_task_handle;
|
||||
extern TaskHandle_t sentinel_task_handle;
|
||||
|
||||
// 设备名称
|
||||
#define DEVICE_NAME "咔宝"
|
||||
#define MAX_NOTIFY_LEN 256
|
||||
|
||||
// BLE 特征值
|
||||
#define BLE_SERVICE_UUID 0xFFFF
|
||||
#define BLE_CHAR_UUID_TX 0xFF01 // ESP32发送,APP接收
|
||||
#define BLE_CHAR_UUID_RX 0xFF02 // APP发送,ESP32接收
|
||||
#define BLE_CHAR_UUID_NOTIFY 0xFF03 // 通知特征
|
||||
|
||||
|
||||
#define SENTINEL_TASK_PRIORITY 5
|
||||
|
||||
#define SENTINEL_TURN_ON 0x01
|
||||
#define SENTINEL_TURN_OFF 0x02
|
||||
#define SENTINEL_LISTEN_START_PULSE 0x04
|
||||
#define SENTINEL_LISTEN_STOP_PULSE 0x08
|
||||
#define SENTINEL_PULSE_TIMEOUT_MS 3000
|
||||
#define SENTINEL_TOTAL_DURATION_MS (20 * 60 * 1000)
|
||||
|
||||
#define BLE_SEND_PROGRESS (1<<0)
|
||||
#define BLE_SEND_VERSION (1<<1)
|
||||
#define BLE_SEND_DL_EMOJI_FAILED (1<<2)
|
||||
#define BLE_SEND_DL_EMOJI_SUCCESS (1<<3)
|
||||
#define BLE_SEND_DOWNLOADED_PACKS (1<<4)
|
||||
#define BLE_SEND_WIFI_STATE (1<<5)
|
||||
#define BLE_SEND_EMOJI_USING (1<<6)
|
||||
#define BLE_SEND_EMOJI_EXCHANGE_RESULT (1<<7)
|
||||
#define BLE_SEND_OTA_RESULT (1<<8)
|
||||
#define BLE_SEND_EMOJI_DELETE_RESULT (1<<9)
|
||||
#define BLE_SEND_EMOJI_CLEAR_RESULT (1<<10)
|
||||
/** 仅发送 Feedback 2.2A brightness 单帧(如设置页亮度滑条松手),由 notification_task 发送 */
|
||||
#define BLE_SEND_BRIGHTNESS (1<<11)
|
||||
|
||||
/** 表情包下载成功后,等待首次切换指令做“收尾”(不重启,停留在目标包) */
|
||||
extern volatile bool g_emoji_upgrade_pending_finalize;
|
||||
/** 本次下载成功的 pack('A'/'B'/'C'/'D',或 '0') */
|
||||
extern volatile char g_emoji_upgrade_downloaded_pack;
|
||||
/** 最近一次收到的“切换表情包”目标 pack(供收尾逻辑判断) */
|
||||
extern volatile char g_emoji_upgrade_last_switch_target;
|
||||
|
||||
/** 请求通过 BLE 发送 OTA 升级进度 1.11_B(0~100),由 notification_task 实际发送 */
|
||||
void ble_send_ota_progress(uint8_t progress);
|
||||
/** 请求通过 BLE 发送 OTA 升级结果 1.11_A(0=失败,1=成功),由 notification_task 实际发送 */
|
||||
void ble_send_ota_result_request(uint8_t success);
|
||||
/** 设置本次「切换表情包」指令的目标 Pack_id,供 notification_task 发送切换结果前执行保存 */
|
||||
void set_emoji_exchange_target_pack(char pack_id);
|
||||
/** 开始 BLE 广播(GAP 回调等 NimBLE 上下文可直接调用) */
|
||||
void ble_app_advertise(void);
|
||||
/** 整机初始化完成后首次起广播:从 app_main 等任务调用,内部持 ble_hs_lock */
|
||||
void ble_app_advertise_after_system_init(void);
|
||||
/** 设置本次「删除表情包」指令的目标 Pack_id,供 notification_task 发送删除结果前执行删除 */
|
||||
void ble_set_emoji_delete_target(char pack_id);
|
||||
|
||||
void ble_main(void);
|
||||
void send_notification_to_app(const char *message);
|
||||
/** 请求通过 BLE 发送 WiFi 状态反馈(连接成功 0x01 / 断开 0x00),由 notification_task 实际发送 */
|
||||
void ble_send_wifi_state_request(uint8_t connected);
|
||||
|
||||
void send_protocol_frame(const uint8_t *data, size_t len);
|
||||
bool ble_is_connected(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _BLE_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
#ifndef __BLE_ANSY_H__
|
||||
#define __BLE_ANSY_H__
|
||||
|
||||
#include "config.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define play_sticker (uint16_t)0x0001
|
||||
#define sentinel_mode (uint16_t)0x0002
|
||||
#define exit_all_modes (uint16_t)0x0003
|
||||
#define set_brightness (uint16_t)0x0004
|
||||
#define date_info (uint16_t)0x0005
|
||||
#define time_info (uint16_t)0x0006
|
||||
#define city_info (uint16_t)0x0007
|
||||
#define w_t_info (uint16_t)0x0008
|
||||
#define wifi_config (uint16_t)0x0009
|
||||
#define ota_request (uint16_t)0x000A
|
||||
#define emoji_pack_download (uint16_t)0x000B
|
||||
#define ota_cancel (uint16_t)0x000C /* 1.13 OTA 升级取消 */
|
||||
#define speed_gear (uint16_t)0x000D /* V2 车机→设备:档位(1)+速度(2BE,KM/h),见 ble_data_ansy */
|
||||
#define get_sys_info (uint16_t)0x0010
|
||||
#define emojo_cmd (uint16_t)0x0020
|
||||
#define clear_emojo (uint16_t)0x0021
|
||||
#define reboot (uint16_t)0x0022 /* 重启设备 */
|
||||
|
||||
int ble_data_ansy(uint8_t *input, size_t length);
|
||||
int ble_wv_data_ansy2(uint8_t *input, size_t length);
|
||||
/** 1.12 表情包下载:获取本次要下载的目标系列 (A/B/C/D),由指令 0x000B 的 Target_pack 解析得到 */
|
||||
char ble_get_emoji_download_target_pack(void);
|
||||
|
||||
/**
|
||||
* UI 页面创建完成后调用:回放在 UI 未就绪阶段缓存的日期/时间。
|
||||
*/
|
||||
void ble_datetime_flush_cached_to_ui(void);
|
||||
|
||||
/**
|
||||
* UI 页面创建完成后调用:回放在 UI 未就绪阶段缓存的天气数据(当前/+2h/+4h)。
|
||||
*/
|
||||
void ble_weather_flush_cached_to_ui(void);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,588 @@
|
||||
#include "ble_send.h"
|
||||
#include "ble.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "esp_log.h"
|
||||
#include "ALGORITHM/crc.h"
|
||||
#include "EMOJI_STORAGE/emoji_storage.h"
|
||||
#include "event.h"
|
||||
|
||||
/* 统一亮度真源(定义在 main.c) */
|
||||
extern int get_system_brightness_percent(void);
|
||||
|
||||
volatile uint8_t s_ota_progress_to_send = 0;
|
||||
volatile bool g_emoji_upgrade_pending_finalize = false;
|
||||
volatile char g_emoji_upgrade_downloaded_pack = '0';
|
||||
volatile char g_emoji_upgrade_last_switch_target = '0';
|
||||
|
||||
static uint8_t s_wifi_state_to_send = 0;
|
||||
bool g_wifi_state = 0;
|
||||
|
||||
static uint8_t s_ota_result_to_send = 0;
|
||||
static char s_emoji_switch_target_pack = '0';
|
||||
|
||||
volatile uint8_t g_brightness = 85;
|
||||
void notification_task(void *arg)//上报任务
|
||||
{
|
||||
ESP_LOGI(BLE_TAG, "通知任务启动");
|
||||
uint32_t bits = 0;
|
||||
BaseType_t rec;
|
||||
|
||||
while (1)
|
||||
{
|
||||
rec = xTaskNotifyWait(0, ULONG_MAX, &bits, portMAX_DELAY);//永久等待通知
|
||||
ESP_LOGI("NOTIFICATION", "recv notify");
|
||||
if (rec != pdPASS)
|
||||
{
|
||||
ESP_LOGE("NOTIFICATION", "接受任务通知失败");
|
||||
continue;
|
||||
}
|
||||
if (bits & BLE_SEND_PROGRESS)//BLE 发送OTA 升级进度
|
||||
{
|
||||
ESP_LOGI("NOTIFICATION", "recv BLE_SEND_PROGRESS, 发送OTA进度(十进制)=%d%%", (int)s_ota_progress_to_send);
|
||||
notify_enabled = 1;
|
||||
send_ota_progress_frame(s_ota_progress_to_send);
|
||||
}
|
||||
else if (bits & BLE_SEND_OTA_RESULT)//返回OTA 升级结果
|
||||
{
|
||||
ESP_LOGI("NOTIFICATION", "recv BLE_SEND_OTA_RESULT, 发送OTA结果 %s", s_ota_result_to_send ? "成功" : "失败");
|
||||
notify_enabled = 1;
|
||||
send_ota_result_frame(s_ota_result_to_send);
|
||||
}
|
||||
else if (bits & BLE_SEND_VERSION) // 收到 get_system_info (0x0010) 请求后发送版本号、亮度和系统状态
|
||||
{
|
||||
ESP_LOGI("NOTIFICATION", "recv BLE_SEND_VERSION (get_system_info 请求)");
|
||||
int current_brightness_percent = get_system_brightness_percent();
|
||||
if (current_brightness_percent < 0)
|
||||
current_brightness_percent = 0;
|
||||
if (current_brightness_percent > 100)
|
||||
current_brightness_percent = 100;
|
||||
g_brightness = (uint8_t)current_brightness_percent; /* 保持兼容镜像 */
|
||||
notify_enabled = 1;
|
||||
|
||||
// 发送3个协议反馈帧
|
||||
// feedback2.1A: get_system_ok
|
||||
send_get_system_ok_frame();
|
||||
vTaskDelay(pdMS_TO_TICKS(10)); // 短暂延时,避免发送过快
|
||||
|
||||
// feedback2.2A: brightness
|
||||
send_brightness_frame((uint8_t)current_brightness_percent);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
|
||||
// feedback2.3A: version
|
||||
send_version_frame(DEVICE_FIRMWARE_VERSION);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
|
||||
// 1.10_A: 返回当前 WiFi 状态(配网成功为 0x01,未连为 0x00)
|
||||
send_wifi_state_frame(s_wifi_state_to_send);
|
||||
|
||||
ESP_LOGI(BLE_TAG, "已发送get_system_info反馈: version=%s, 亮度=%u, WiFi状态=%s", DEVICE_FIRMWARE_VERSION, (unsigned int)g_brightness, s_wifi_state_to_send ? "已连接" : "断开");
|
||||
}
|
||||
else if (bits & BLE_SEND_BRIGHTNESS)
|
||||
{
|
||||
ESP_LOGI("NOTIFICATION", "recv BLE_SEND_BRIGHTNESS");
|
||||
int current_brightness_percent = get_system_brightness_percent();
|
||||
if (current_brightness_percent < 0)
|
||||
current_brightness_percent = 0;
|
||||
if (current_brightness_percent > 100)
|
||||
current_brightness_percent = 100;
|
||||
g_brightness = (uint8_t)current_brightness_percent;
|
||||
notify_enabled = 1;
|
||||
send_brightness_frame((uint8_t)current_brightness_percent);
|
||||
}
|
||||
else if (bits & BLE_SEND_DL_EMOJI_FAILED)//返回下载表情失败
|
||||
{
|
||||
ESP_LOGI("NOTIFICATION", "BLE_SEND_DL_EMOJI_FAILED");
|
||||
notify_enabled = 1;
|
||||
send_emoji_download_result_frame(0);
|
||||
}
|
||||
else if (bits & BLE_SEND_DL_EMOJI_SUCCESS)//返回下载表情成功
|
||||
{
|
||||
ESP_LOGI("NOTIFICATION", "BLE_SEND_DL_EMOJI_SUCCESS");
|
||||
notify_enabled = 1;
|
||||
send_emoji_download_result_frame(1);
|
||||
}
|
||||
else if (bits & BLE_SEND_DOWNLOADED_PACKS)//返回已下载表情包列表
|
||||
{
|
||||
ESP_LOGI("NOTIFICATION", "BLE_SEND_DOWNLOADED_PACKS");
|
||||
notify_enabled = 1;
|
||||
send_downloaded_packs_frame();
|
||||
}
|
||||
else if (bits & BLE_SEND_WIFI_STATE)//返回WiFi状态
|
||||
{
|
||||
ESP_LOGI("NOTIFICATION", "BLE_SEND_WIFI_STATE, 主动发送 1.10_A WiFi状态=%s", s_wifi_state_to_send ? "已连接(0x01)" : "断开(0x00)");
|
||||
notify_enabled = 1;
|
||||
send_wifi_state_frame(s_wifi_state_to_send);
|
||||
}
|
||||
else if (bits & BLE_SEND_EMOJI_EXCHANGE_RESULT)//返回表情包切换结果
|
||||
{
|
||||
ESP_LOGI("NOTIFICATION", "BLE_SEND_EMOJI_EXCHANGE_RESULT");
|
||||
notify_enabled = 1;
|
||||
esp_err_t err = emoji_storage_save_using_pack(s_emoji_switch_target_pack);
|
||||
send_emoji_switch_result_frame(err == ESP_OK ? 1 : 0);
|
||||
ESP_LOGI("NOTIFICATION", "g_emoji_upgrade_pending_finalize = %d", (int)g_emoji_upgrade_pending_finalize);
|
||||
if (g_emoji_upgrade_pending_finalize)
|
||||
{
|
||||
/* 下载成功后第一次切换:收尾升级(不重启,不回到原来) */
|
||||
g_emoji_upgrade_pending_finalize = false;
|
||||
g_emoji_upgrade_last_switch_target = s_emoji_switch_target_pack;
|
||||
set_system_event(EMOJI_UPGRADE_FINALIZE_BIT);
|
||||
}
|
||||
}
|
||||
else if (bits & BLE_SEND_EMOJI_USING)//返回正在使用的表情包
|
||||
{
|
||||
ESP_LOGI("NOTIFICATION", "BLE_SEND_EMOJI_USING");
|
||||
notify_enabled = 1;
|
||||
send_emoji_using_frame(emoji_storage_get_using_pack());
|
||||
}
|
||||
else if (bits & BLE_SEND_EMOJI_DELETE_RESULT)//返回删除表情包结果
|
||||
{
|
||||
ESP_LOGI("NOTIFICATION", "BLE_SEND_EMOJI_DELETE_RESULT");
|
||||
notify_enabled = 1;
|
||||
emoji_storage_remove_pack_files(s_emoji_delete_target_pack);
|
||||
esp_err_t err = emoji_storage_remove_downloaded_pack(s_emoji_delete_target_pack);
|
||||
send_emoji_delete_result_frame(err == ESP_OK ? 1 : 0);
|
||||
}
|
||||
else if (bits & BLE_SEND_EMOJI_CLEAR_RESULT)
|
||||
{
|
||||
ESP_LOGI("NOTIFICATION", "BLE_SEND_EMOJI_CLEAR_RESULT");
|
||||
notify_enabled = 1;
|
||||
esp_err_t err = emoji_storage_clear_all_packs();
|
||||
send_emoji_clear_result_frame(err == ESP_OK ? 1 : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Feedback 3.4 返回删除表情包结果 0x0020 op=0x03:帧头(1)+类(2)+指令(2)+op(1)+Exchange_result(1)+CRC16(2)+帧尾(1)=10 */
|
||||
void send_emoji_delete_result_frame(uint8_t success)
|
||||
{
|
||||
uint8_t frame[10] = {0};
|
||||
uint16_t crc16;
|
||||
|
||||
frame[0] = 0xAA;
|
||||
frame[1] = 0xFF;
|
||||
frame[2] = 0xFF;
|
||||
frame[3] = 0x00;
|
||||
frame[4] = 0x20;
|
||||
frame[5] = 0x03; /* op=0x03 删除结果 */
|
||||
frame[6] = success ? 0x01 : 0x00;
|
||||
|
||||
crc16 = crc16_ccitt_calculate(frame, 7);
|
||||
frame[7] = (crc16 >> 8) & 0xFF;
|
||||
frame[8] = crc16 & 0xFF;
|
||||
frame[9] = 0x55;
|
||||
|
||||
send_protocol_frame(frame, sizeof(frame));
|
||||
ESP_LOGI(BLE_TAG, "发送Feedback3.4删除表情包结果: %s, 发送 CRC16=0x%04X", success ? "成功(0x01)" : "失败(0x00)", crc16);
|
||||
}
|
||||
|
||||
/* Feedback clear_emojo 返回清除所有表情包结果 0x0021:帧头(1)+类(2)+指令(2)+result(1)+CRC16(2)+帧尾(1)=9 */
|
||||
void send_emoji_clear_result_frame(uint8_t success)
|
||||
{
|
||||
uint8_t frame[9] = {0};
|
||||
uint16_t crc16;
|
||||
|
||||
frame[0] = 0xAA;
|
||||
frame[1] = 0xFF;
|
||||
frame[2] = 0xFF;
|
||||
frame[3] = 0x00;
|
||||
frame[4] = 0x21;
|
||||
frame[5] = success ? 0x01 : 0x00;
|
||||
|
||||
crc16 = crc16_ccitt_calculate(frame, 6);
|
||||
frame[6] = (crc16 >> 8) & 0xFF;
|
||||
frame[7] = crc16 & 0xFF;
|
||||
frame[8] = 0x55;
|
||||
|
||||
send_protocol_frame(frame, sizeof(frame));
|
||||
ESP_LOGI(BLE_TAG, "发送清除所有表情包结果: %s, CRC16=0x%04X", success ? "成功(0x01)" : "失败(0x00)", crc16);
|
||||
}
|
||||
|
||||
/* Feedback 表情包查询/切换 0x0020 op=0x02 切换结果:帧头(1)+类(2)+指令(2)+op(1)+result(1)+CRC16(2)+帧尾(1)=10 */
|
||||
void send_emoji_switch_result_frame(uint8_t success)
|
||||
{
|
||||
uint8_t frame[11] = {0};
|
||||
uint16_t crc16;
|
||||
|
||||
frame[0] = 0xAA;
|
||||
frame[1] = 0xFF;
|
||||
frame[2] = 0xFF;
|
||||
frame[3] = 0x00;
|
||||
frame[4] = 0x20;
|
||||
frame[5] = 0x02; /* op=0x02 切换结果 */
|
||||
frame[6] = success ? 0x01 : 0x00;
|
||||
frame[7] = s_emoji_switch_target_pack;//pack_id
|
||||
crc16 = crc16_ccitt_calculate(frame, 8);
|
||||
frame[8] = (crc16 >> 8) & 0xFF;
|
||||
frame[9] = crc16 & 0xFF;
|
||||
frame[10] = 0x55;
|
||||
|
||||
send_protocol_frame(frame, sizeof(frame));
|
||||
ESP_LOGI(BLE_TAG, "发送Feedback3.2切换结果: %s, 发送 CRC16=0x%04X", success ? "成功(0x01)" : "失败(0x00)", crc16);
|
||||
}
|
||||
|
||||
/* Feedback 表情包下载结果 0x0003:帧头(1)+类(2)+指令(2)+result(1)+CRC16(2)+帧尾(1)=9 */
|
||||
void send_emoji_download_result_frame(uint8_t success)
|
||||
{
|
||||
uint8_t frame[9] = {0};
|
||||
uint16_t crc16;
|
||||
|
||||
frame[0] = 0xAA;
|
||||
frame[1] = 0xFF;
|
||||
frame[2] = 0xFF;
|
||||
frame[3] = 0x00;
|
||||
frame[4] = 0x03; /* 表情包下载结果 */
|
||||
frame[5] = success ? 0x01 : 0x00;
|
||||
|
||||
crc16 = crc16_ccitt_calculate(frame, 6);
|
||||
frame[6] = (crc16 >> 8) & 0xFF;
|
||||
frame[7] = crc16 & 0xFF;
|
||||
frame[8] = 0x55;
|
||||
|
||||
send_protocol_frame(frame, sizeof(frame));
|
||||
ESP_LOGI(BLE_TAG, "发送表情包下载结果: %s, 发送 CRC16=0x%04X", success ? "成功(0x01)" : "失败(0x00)", crc16);
|
||||
}
|
||||
|
||||
/* Feedback 0x0020 op=0x00 返回已安装表情包列表:帧头(1)+类(2)+指令(2)+op(1)+count(1)+[id1..idN]+CRC16(2)+帧尾(1);默认系列 0 自带,无论如何都先发 */
|
||||
#define EMOJI_PACK_LIST_MAX 16
|
||||
void send_downloaded_packs_frame(void)
|
||||
{
|
||||
char list_buf[64];
|
||||
int len = emoji_storage_get_downloaded_packs(list_buf, sizeof(list_buf));
|
||||
uint8_t ids[EMOJI_PACK_LIST_MAX];
|
||||
int count = 0;
|
||||
/* 默认表情包系列 0 始终第一位 */
|
||||
ids[count++] = (uint8_t)'0';
|
||||
if (len > 0)
|
||||
{
|
||||
for (int i = 0; i < len && count < EMOJI_PACK_LIST_MAX; i++)
|
||||
{
|
||||
if (list_buf[i] != ',' && list_buf[i] != '0')
|
||||
{
|
||||
ids[count++] = (uint8_t)list_buf[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
size_t frame_len = 10 + count;
|
||||
uint8_t *frame = (uint8_t *)malloc(frame_len);
|
||||
if (!frame)
|
||||
{
|
||||
ESP_LOGE(BLE_TAG, "已安装列表帧分配失败");
|
||||
return;
|
||||
}
|
||||
frame[0] = 0xAA;
|
||||
frame[1] = 0xFF;
|
||||
frame[2] = 0xFF;
|
||||
frame[3] = 0x00;
|
||||
frame[4] = 0x20;
|
||||
frame[5] = 0x00; /* op=0x00 返回已安装列表 */
|
||||
frame[6] = (uint8_t)count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
frame[7 + i] = ids[i];
|
||||
}
|
||||
uint16_t crc16 = crc16_ccitt_calculate(frame, 7 + count);
|
||||
frame[7 + count] = (crc16 >> 8) & 0xFF;
|
||||
frame[8 + count] = crc16 & 0xFF;
|
||||
frame[9 + count] = 0x55;
|
||||
send_protocol_frame(frame, frame_len);
|
||||
ESP_LOGI(BLE_TAG, "发送已安装表情包列表: count=%d, 发送 CRC16=0x%04X", count, crc16);
|
||||
free(frame);
|
||||
}
|
||||
|
||||
|
||||
/* 发送get_system_info反馈帧2.3A: version */
|
||||
void send_version_frame(const char *version_str)
|
||||
{
|
||||
size_t version_len = strlen(version_str);
|
||||
size_t frame_len = 7 + version_len + 2 + 1; // 帧头(1) + 类(2) + 指令(2) + 长度(2) + 版本号 + CRC16(2) + 帧尾(1)
|
||||
uint8_t *frame = (uint8_t *)malloc(frame_len);
|
||||
if (!frame)
|
||||
{
|
||||
ESP_LOGE(BLE_TAG, "分配内存失败");
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t crc16;
|
||||
size_t pos = 0;
|
||||
|
||||
// 帧头
|
||||
frame[pos++] = 0xAA;
|
||||
// 类 (Feedback)
|
||||
frame[pos++] = 0xFF;
|
||||
frame[pos++] = 0xFF;
|
||||
// 指令 (version_cmd)
|
||||
frame[pos++] = 0x00;
|
||||
frame[pos++] = 0x06;
|
||||
// 长度 (2字节,大端序)
|
||||
frame[pos++] = (version_len >> 8) & 0xFF;
|
||||
frame[pos++] = version_len & 0xFF;
|
||||
// 版本号字符串
|
||||
memcpy(&frame[pos], version_str, version_len);
|
||||
pos += version_len;
|
||||
|
||||
// 计算CRC16 (不包括帧尾)
|
||||
crc16 = crc16_ccitt_calculate(frame, pos);
|
||||
frame[pos++] = (crc16 >> 8) & 0xFF;
|
||||
frame[pos++] = crc16 & 0xFF;
|
||||
|
||||
// 帧尾
|
||||
frame[pos++] = 0x55;
|
||||
|
||||
send_protocol_frame(frame, frame_len);
|
||||
ESP_LOGI(BLE_TAG, "发送version帧: %s (长度: %d), 发送 CRC16=0x%04X", version_str, frame_len, crc16);
|
||||
|
||||
free(frame);
|
||||
}
|
||||
|
||||
/* 1.11_B: 发送 OTA 升级进度 Feedback OTA_progress_cmd 0x0002,进度 0~100 */
|
||||
|
||||
void send_ota_progress_frame(uint8_t progress)
|
||||
{
|
||||
uint8_t frame[9] = {0};
|
||||
uint16_t crc16;
|
||||
frame[0] = 0xAA;
|
||||
frame[1] = 0xFF;
|
||||
frame[2] = 0xFF;
|
||||
frame[3] = 0x00;
|
||||
frame[4] = 0x02;
|
||||
frame[5] = progress > 100 ? 100 : progress;
|
||||
|
||||
crc16 = crc16_ccitt_calculate(frame, 6);
|
||||
frame[6] = (crc16 >> 8) & 0xFF;
|
||||
frame[7] = crc16 & 0xFF;
|
||||
frame[8] = 0x55;
|
||||
|
||||
send_protocol_frame(frame, sizeof(frame));
|
||||
ESP_LOGI(BLE_TAG, "发送OTA进度帧 1.11_B: 进度(十进制)=%d%%, 发送 CRC16=0x%04X", (int)frame[5], crc16);
|
||||
}
|
||||
|
||||
/* 1.11_A: 发送 OTA 升级结果 Feedback OTA_result_cmd 0x0001,0x01=成功 0x00=失败 */
|
||||
|
||||
void send_ota_result_frame(uint8_t result)
|
||||
{
|
||||
uint8_t frame[9] = {0};
|
||||
uint16_t crc16;
|
||||
|
||||
frame[0] = 0xAA;
|
||||
frame[1] = 0xFF;
|
||||
frame[2] = 0xFF;
|
||||
frame[3] = 0x00;
|
||||
frame[4] = 0x01;
|
||||
frame[5] = result ? 0x01 : 0x00;
|
||||
|
||||
crc16 = crc16_ccitt_calculate(frame, 6);
|
||||
frame[6] = (crc16 >> 8) & 0xFF;
|
||||
frame[7] = crc16 & 0xFF;
|
||||
frame[8] = 0x55;
|
||||
|
||||
send_protocol_frame(frame, sizeof(frame));
|
||||
ESP_LOGI(BLE_TAG, "发送OTA结果帧 1.11_A: %s, 发送 CRC16=0x%04X", result ? "成功(0x01)" : "失败(0x00)", crc16);
|
||||
}
|
||||
|
||||
void ble_send_ota_progress(uint8_t progress)
|
||||
{
|
||||
s_ota_progress_to_send = progress > 100 ? 100 : progress;
|
||||
if (notification_task_handle)
|
||||
{
|
||||
xTaskNotify(notification_task_handle, BLE_SEND_PROGRESS, eSetBits);
|
||||
}
|
||||
}
|
||||
|
||||
void ble_send_ota_result_request(uint8_t success)
|
||||
{
|
||||
s_ota_result_to_send = success ? 1 : 0;
|
||||
if (notification_task_handle)
|
||||
{
|
||||
xTaskNotify(notification_task_handle, BLE_SEND_OTA_RESULT, eSetBits);
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(BLE_TAG, "notification_task_handle 不存在");
|
||||
}
|
||||
}
|
||||
|
||||
/* 发送get_system_info反馈帧2.1A: get_system_ok */
|
||||
void send_get_system_ok_frame(void)
|
||||
{
|
||||
uint8_t frame[9] = {0};
|
||||
uint16_t crc16;
|
||||
|
||||
// 帧头
|
||||
frame[0] = 0xAA;
|
||||
// 类 (Feedback)
|
||||
frame[1] = 0xFF;
|
||||
frame[2] = 0xFF;
|
||||
// 指令 (get_sysinfo_feedback)
|
||||
frame[3] = 0x00;
|
||||
frame[4] = 0x04;
|
||||
// 指令返回 (get_system_ok = 0x01)
|
||||
frame[5] = 0x01;
|
||||
|
||||
// 计算CRC16 (不包括帧尾)
|
||||
crc16 = crc16_ccitt_calculate(frame, 6);
|
||||
frame[6] = (crc16 >> 8) & 0xFF;
|
||||
frame[7] = crc16 & 0xFF;
|
||||
|
||||
// 帧尾
|
||||
frame[8] = 0x55;
|
||||
|
||||
send_protocol_frame(frame, sizeof(frame));
|
||||
ESP_LOGI(BLE_TAG, "发送get_system_ok帧, 发送 CRC16=0x%04X", crc16);
|
||||
}
|
||||
|
||||
/* 发送get_system_info反馈帧2.2A: brightness */
|
||||
void send_brightness_frame(uint8_t brightness)
|
||||
{
|
||||
uint8_t frame[9] = {0};
|
||||
uint16_t crc16;
|
||||
|
||||
// 帧头
|
||||
frame[0] = 0xAA;
|
||||
// 类 (Feedback)
|
||||
frame[1] = 0xFF;
|
||||
frame[2] = 0xFF;
|
||||
// 指令 (Brightness_cmd)
|
||||
frame[3] = 0x00;
|
||||
frame[4] = 0x05;
|
||||
frame[5] = brightness > 100 ? 100 : brightness;
|
||||
|
||||
// 计算CRC16 (不包括帧尾)
|
||||
crc16 = crc16_ccitt_calculate(frame, 6);
|
||||
frame[6] = (crc16 >> 8) & 0xFF;
|
||||
frame[7] = crc16 & 0xFF;
|
||||
|
||||
// 帧尾
|
||||
frame[8] = 0x55;
|
||||
|
||||
send_protocol_frame(frame, sizeof(frame));
|
||||
ESP_LOGI(BLE_TAG, "发送brightness帧: 亮度(十进制)=%d, 发送 CRC16=0x%04X", (int)frame[5], crc16);
|
||||
}
|
||||
|
||||
/* Feedback 3.2: 返回正在使用的表情包 帧头(1)+类(2)+指令(2)+Check_using(1)+Pack_id(1)+CRC16(2)+帧尾(1)=10 */
|
||||
void send_emoji_using_frame(uint8_t pack_id)
|
||||
{
|
||||
uint8_t frame[10] = {0};
|
||||
uint16_t crc16;
|
||||
|
||||
frame[0] = 0xAA;
|
||||
frame[1] = 0xFF;
|
||||
frame[2] = 0xFF;
|
||||
frame[3] = 0x00;
|
||||
frame[4] = 0x20; /* Emoji_cmd 0x0020 */
|
||||
frame[5] = 0x01; /* Check_using 查询正在使用 */
|
||||
frame[6] = pack_id; /* Pack_id ASCII 1 byte */
|
||||
|
||||
crc16 = crc16_ccitt_calculate(frame, 7);
|
||||
frame[7] = (crc16 >> 8) & 0xFF;
|
||||
frame[8] = crc16 & 0xFF;
|
||||
frame[9] = 0x55;
|
||||
|
||||
send_protocol_frame(frame, sizeof(frame));
|
||||
ESP_LOGI(BLE_TAG, "发送Feedback3.2正在使用表情包: Pack_id=%c (0x%02X), 发送 CRC16=0x%04X", (char)pack_id, pack_id, crc16);
|
||||
}
|
||||
/* 发送 WiFi 状态反馈帧 1.10_A: Feedback Wifi_state_cmd 0x0010 */
|
||||
|
||||
void send_wifi_state_frame(uint8_t state)
|
||||
{
|
||||
uint8_t frame[9] = {0};
|
||||
uint16_t crc16;
|
||||
|
||||
frame[0] = 0xAA;
|
||||
frame[1] = 0xFF;
|
||||
frame[2] = 0xFF;
|
||||
frame[3] = 0x00;
|
||||
frame[4] = 0x10;
|
||||
frame[5] = state ? 0x01 : 0x00; /* 0x01=已连接, 0x00=断开 */
|
||||
|
||||
crc16 = crc16_ccitt_calculate(frame, 6);
|
||||
frame[6] = (crc16 >> 8) & 0xFF;
|
||||
frame[7] = crc16 & 0xFF;
|
||||
frame[8] = 0x55;
|
||||
|
||||
send_protocol_frame(frame, sizeof(frame));
|
||||
ESP_LOGI(BLE_TAG, "发送WiFi状态帧: %s, 发送 CRC16=0x%04X", state ? "已连接" : "断开", crc16);
|
||||
}
|
||||
|
||||
void ble_send_wifi_state_request(uint8_t connected)
|
||||
{
|
||||
s_wifi_state_to_send = connected ? 1 : 0;
|
||||
if (notification_task_handle)
|
||||
{
|
||||
xTaskNotify(notification_task_handle, BLE_SEND_WIFI_STATE, eSetBits);
|
||||
}
|
||||
}
|
||||
|
||||
void ble_request_send_brightness(void)
|
||||
{
|
||||
if (notification_task_handle)
|
||||
{
|
||||
xTaskNotify(notification_task_handle, BLE_SEND_BRIGHTNESS, eSetBits);
|
||||
}
|
||||
}
|
||||
|
||||
/* 切换表情包指令的目标 Pack_id,由 ble_data_ansy 在收到 op=0x02 时设置 */
|
||||
// static char s_emoji_switch_target_pack = '0';
|
||||
|
||||
void ble_set_emoji_switch_target(char pack_id)
|
||||
{
|
||||
s_emoji_switch_target_pack = pack_id;
|
||||
}
|
||||
|
||||
/* 删除表情包指令的目标 Pack_id,由 ble_data_ansy 在收到 op=0x03 时设置 */
|
||||
|
||||
|
||||
void ble_set_emoji_delete_target(char pack_id)
|
||||
{
|
||||
s_emoji_delete_target_pack = pack_id;
|
||||
}
|
||||
|
||||
void robot_sleep_frame(uint8_t state)
|
||||
{
|
||||
(void)state;
|
||||
uint8_t frame[8] = {0};
|
||||
uint16_t crc16;
|
||||
|
||||
frame[0] = 0xAA;
|
||||
frame[1] = 0xFF;
|
||||
frame[2] = 0xFF;
|
||||
frame[3] = 0x00;
|
||||
frame[4] = 0x07;
|
||||
|
||||
crc16 = crc16_ccitt_calculate(frame, 5);
|
||||
frame[5] = (crc16 >> 8) & 0xFF;
|
||||
frame[6] = crc16 & 0xFF;
|
||||
frame[7] = 0x55;
|
||||
|
||||
send_protocol_frame(frame, sizeof(frame));
|
||||
ESP_LOGI(BLE_TAG, "发送robot睡眠状态帧: 发送 CRC16=0x%04X", crc16);
|
||||
}
|
||||
|
||||
void robot_wake_frame(uint8_t state)
|
||||
{
|
||||
(void)state;
|
||||
uint8_t frame[8] = {0};
|
||||
uint16_t crc16;
|
||||
|
||||
frame[0] = 0xAA;
|
||||
frame[1] = 0xFF;
|
||||
frame[2] = 0xFF;
|
||||
frame[3] = 0x00;
|
||||
frame[4] = 0x08;
|
||||
|
||||
crc16 = crc16_ccitt_calculate(frame, 5);
|
||||
frame[5] = (crc16 >> 8) & 0xFF;
|
||||
frame[6] = crc16 & 0xFF;
|
||||
frame[7] = 0x55;
|
||||
|
||||
send_protocol_frame(frame, sizeof(frame));
|
||||
ESP_LOGI(BLE_TAG, "发送robot唤醒状态帧: 发送 CRC16=0x%04X", crc16);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef __BLE_SEND_H__
|
||||
#define __BLE_SEND_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern volatile uint8_t g_brightness;
|
||||
|
||||
void send_emoji_delete_result_frame(uint8_t success);
|
||||
void send_emoji_clear_result_frame(uint8_t success);
|
||||
void send_emoji_switch_result_frame(uint8_t success);
|
||||
void send_emoji_download_result_frame(uint8_t success);
|
||||
void send_downloaded_packs_frame(void);
|
||||
void send_version_frame(const char *version_str);
|
||||
void send_ota_progress_frame(uint8_t progress);
|
||||
void send_ota_result_frame(uint8_t result);
|
||||
void ble_send_ota_progress(uint8_t progress);
|
||||
void ble_send_ota_result_request(uint8_t success);
|
||||
void send_get_system_ok_frame(void);
|
||||
void send_brightness_frame(uint8_t brightness);
|
||||
void send_emoji_using_frame(uint8_t pack_id);
|
||||
|
||||
void send_wifi_state_frame(uint8_t state);
|
||||
void ble_send_wifi_state_request(uint8_t connected);
|
||||
/** 请求发送当前亮度单帧(0x0005),由 notification_task 调用 send_protocol_frame */
|
||||
void ble_request_send_brightness(void);
|
||||
void ble_set_emoji_switch_target(char pack_id);
|
||||
void ble_set_emoji_delete_target(char pack_id);
|
||||
void send_version_frame(const char *version_str);
|
||||
void send_ota_progress_frame(uint8_t progress);
|
||||
void send_ota_result_frame(uint8_t result);
|
||||
void robot_sleep_frame(uint8_t state);
|
||||
void robot_wake_frame(uint8_t state);
|
||||
|
||||
|
||||
void notification_task(void *arg);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user