Files
P4-USB-transfer/main/BLE/ble_send.c
T

588 lines
18 KiB
C
Raw Normal View History

2026-10-13 21:54:50 +08:00
#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);
}