Skip to content

Commit da6be6f

Browse files
committed
Support remote emotion
1 parent 3df2cff commit da6be6f

12 files changed

+274
-2
lines changed

main/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,12 @@ if(CONFIG_USE_AUDIO_CODEC_ENCODE_OPUS OR CONFIG_USE_AUDIO_CODEC_DECODE_OPUS)
195195
"audio_codecs/es8388_audio_codec.cc")
196196
endif()
197197

198+
if(CONFIG_USE_EMOTION_REMOTE)
199+
list(APPEND SOURCES "remote/emotion_remote.cc"
200+
"remote/gapRemote.cc")
201+
list(APPEND INCLUDE_DIRS "remote")
202+
endif()
203+
198204
idf_component_register(SRCS ${SOURCES}
199205
EMBED_FILES ${LANG_SOUNDS} ${COMMON_SOUNDS}
200206
INCLUDE_DIRS ${INCLUDE_DIRS}

main/Kconfig.projbuild

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,13 @@ config USE_REALTIME_CHAT
235235
help
236236
需要 ESP32 S3 与 AEC 开启,因为性能不够,不建议和微信聊天界面风格同时开启
237237

238+
config USE_EMOTION_REMOTE
239+
bool "启用远程表情控制(doit_ai_two_eye眼部表情)"
240+
default y
241+
depends on !IDF_TARGET_ESP32C2
242+
help
243+
可用于控制 doit_ai_two_eye 做出对应的表情
244+
238245
config USE_AUDIO_CODEC_ENCODE_OPUS
239246
depends on BOARD_TYPE_DOIT_AI_01_KIT || BOARD_TYPE_DOIT_AI_01_KIT_LCD
240247
bool "use audio codec encode opus"

main/display/display.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
#include "audio_codec.h"
1212
#include "settings.h"
1313
#include "assets/lang_config.h"
14+
#ifdef CONFIG_USE_EMOTION_REMOTE
15+
#include "emotion_remote.h"
16+
#endif
1417

1518
#define TAG "Display"
1619

@@ -194,6 +197,11 @@ void Display::Update() {
194197

195198

196199
void Display::SetEmotion(const char* emotion) {
200+
201+
#ifdef CONFIG_USE_EMOTION_REMOTE
202+
EmotionRemote::GetInstance().SetEmotion(emotion);
203+
#endif
204+
197205
struct Emotion {
198206
const char* icon;
199207
const char* text;

main/display/lcd_display.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111

1212
#include "board.h"
1313

14+
#ifdef CONFIG_USE_EMOTION_REMOTE
15+
#include "emotion_remote.h"
16+
#endif
17+
1418
#define TAG "LcdDisplay"
1519

1620
// Color definitions for dark theme
@@ -638,6 +642,11 @@ void LcdDisplay::SetupUI() {
638642
#endif
639643

640644
void LcdDisplay::SetEmotion(const char* emotion) {
645+
646+
#ifdef CONFIG_USE_EMOTION_REMOTE
647+
EmotionRemote::GetInstance().SetEmotion(emotion);
648+
#endif
649+
641650
struct Emotion {
642651
const char* icon;
643652
const char* text;

main/remote/emotion_remote.cc

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include "emotion_remote.h"
2+
3+
#include "esp_log.h"
4+
5+
#include "font_awesome_symbols.h"
6+
7+
#define TAG "emzy"
8+
9+
void EmotionRemote::SetEmotion(const char* emotion){
10+
struct Emotion {
11+
uint8_t em_id;
12+
const char* text;
13+
};
14+
static const std::vector<Emotion> emotions = {
15+
{0x01, "neutral"},
16+
{0x02, "happy"},
17+
{0x03, "laughing"},
18+
{0x04, "funny"},
19+
{0x05, "sad"},
20+
{0x06, "angry"},
21+
{0x07, "crying"},
22+
{0x08, "loving"},
23+
{0x09, "embarrassed"},
24+
{0x0a, "surprised"},
25+
{0x0b, "shocked"},
26+
{0x0c, "thinking"},
27+
{0x0d, "winking"},
28+
{0x0e, "cool"},
29+
{0x0f, "relaxed"},
30+
{0x10, "delicious"},
31+
{0x11, "kissy"},
32+
{0x12, "confident"},
33+
{0x13, "sleepy"},
34+
{0x14, "silly"},
35+
{0x15, "confused"}
36+
};
37+
std::string_view emotion_view(emotion);
38+
auto it = std::find_if(emotions.begin(), emotions.end(),
39+
[&emotion_view](const Emotion& e) { return e.text == emotion_view; });
40+
if (it != emotions.end()) {
41+
sendGapData(it->em_id);
42+
} else {
43+
sendGapData(0x01);
44+
}
45+
}
46+
47+
void EmotionRemote::sendGapData(uint8_t code){
48+
gapData[9]++;
49+
gapData[11] = code;
50+
remote.start_adv(gapData, gapDateLen, 20000);
51+
}
52+
53+
EmotionRemote::EmotionRemote(){
54+
55+
}

main/remote/emotion_remote.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#ifndef _EMOTION_REMOTE_H_
2+
#define _EMOTION_REMOTE_H_
3+
4+
#include "gapRemote.h"
5+
#include <functional>
6+
#include <string>
7+
8+
class EmotionRemote {
9+
private:
10+
struct RemotFun
11+
{
12+
std::string funName;
13+
uint8_t code;
14+
std::function<void(uint8_t)> func; // 使用 std::function 存储函数
15+
};
16+
17+
const uint8_t gapDateLen = 12;
18+
uint8_t gapData[12] = {
19+
0x0B, // 数据长度
20+
0xFF, // 厂商自定义类型
21+
0x77, 0x66, // 厂商 ID
22+
0x01, // 协议
23+
0xFF, // 标志
24+
0x95, 0x03, // 设备 ID
25+
0xFF, // 组 ID
26+
0x00, // 序列号
27+
0x01, // 命令
28+
0x01 // 参数
29+
};
30+
31+
32+
GapRemote& remote = GapRemote::GetInstance();
33+
void sendGapData(uint8_t code);
34+
public:
35+
static EmotionRemote& GetInstance() {
36+
static EmotionRemote instance;
37+
return instance;
38+
}
39+
// 删除拷贝构造函数和赋值运算符
40+
EmotionRemote(const EmotionRemote&) = delete;
41+
EmotionRemote& operator=(const EmotionRemote&) = delete;
42+
explicit EmotionRemote();
43+
void SetEmotion(const char* emotion);
44+
};
45+
46+
#endif

main/remote/gapRemote.cc

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#include "gapRemote.h"
2+
#include "esp_event.h"
3+
#include "esp_log.h"
4+
#include "esp_system.h"
5+
#include "nvs_flash.h"
6+
#include "nimble/nimble_port.h"
7+
#include "nimble/nimble_port_freertos.h"
8+
#include "host/ble_hs.h"
9+
#include "host/ble_gap.h"
10+
#include "freertos/FreeRTOS.h"
11+
#include "freertos/task.h"
12+
13+
#define TAG "gap_remote"
14+
static uint32_t start_time = 0;
15+
void GapRemote::ble_sync_callback(void)
16+
{
17+
auto &remote = GapRemote::GetInstance();
18+
/* 获取设备地址类型 */
19+
int rc = ble_hs_id_infer_auto(0, &remote.ble_addr_type);
20+
if (rc != 0)
21+
{
22+
ESP_LOGE(TAG, "无法推断设备地址类型");
23+
return;
24+
}
25+
26+
uint8_t addr[6];
27+
ble_hs_id_copy_addr(remote.ble_addr_type, addr, NULL);
28+
ESP_LOGI(TAG, "device gap mac: %02X:%02X:%02X:%02X:%02X:%02X",
29+
addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
30+
31+
struct ble_gap_adv_params adv_params;
32+
// 设置广播参数
33+
memset(&adv_params, 0, sizeof(adv_params));
34+
adv_params.conn_mode = BLE_GAP_CONN_MODE_NON;
35+
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
36+
adv_params.itvl_min = 0x20; // 默认最小间隔
37+
adv_params.itvl_max = 0x40; // 默认最大间隔
38+
adv_params.channel_map = 0x07; // 37信道
39+
}
40+
41+
int GapRemote::ble_gap_event(struct ble_gap_event *event, void *arg) {
42+
auto& remote = GapRemote::GetInstance();
43+
switch (event->type) {
44+
case BLE_GAP_EVENT_ADV_COMPLETE: // 广播完成事件
45+
ESP_LOGW(TAG, "broadcast finish, %ld", pdMS_TO_TICKS(xTaskGetTickCount()-start_time));
46+
remote.is_broadcast = false;
47+
break;
48+
default:
49+
break;
50+
}
51+
return 1;
52+
}
53+
54+
int GapRemote::start_adv(uint8_t *adv_data, uint8_t len, uint32_t duration_ms, bool force){
55+
if (is_broadcast && force==false)
56+
{
57+
ESP_LOGW(TAG, "The last broadcast is not over yet");
58+
return -1;
59+
}else if (is_broadcast && force)
60+
{
61+
ble_gap_adv_stop();
62+
is_broadcast=false;
63+
}
64+
65+
int rc = ble_gap_adv_set_data((unsigned char *)adv_data, len);
66+
if (rc != 0) {
67+
ESP_LOGE(TAG, "fail set adv data, err: %d", rc);
68+
return -2;
69+
}
70+
71+
/* 广播参数 */
72+
struct ble_gap_adv_params adv_params = {
73+
.conn_mode = BLE_GAP_CONN_MODE_NON, // 不允许连接
74+
.disc_mode = BLE_GAP_DISC_MODE_GEN, // 一般可发现模式
75+
.itvl_min = 0x20, // 最小间隔
76+
.itvl_max = 0x40 , // 最大间隔
77+
.channel_map = 0x07 , // 使用信道 37
78+
};
79+
80+
rc = ble_gap_adv_start(ble_addr_type, NULL, duration_ms, &adv_params, ble_gap_event, NULL);
81+
if (rc != 0) {
82+
ESP_LOGE(TAG, "ble_gap_adv_start fail, err: %d", rc);
83+
return -2;
84+
}
85+
start_time = xTaskGetTickCount();
86+
is_broadcast = true;
87+
return 1;
88+
}
89+
90+
GapRemote::GapRemote() {
91+
/* 初始化 NimBLE 核心 */
92+
nimble_port_init();
93+
/* 配置 Host */
94+
ble_hs_cfg.sync_cb = ble_sync_callback;
95+
nimble_port_freertos_init([](void *param)
96+
{ nimble_port_run(); });
97+
ESP_LOGI(TAG, "NimBLE init Finsh");
98+
}

main/remote/gapRemote.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#ifndef _GAP_REMOTE_H_
2+
#define _GAP_REMOTE_H_
3+
4+
#include <cstdint>
5+
6+
class GapRemote{
7+
public:
8+
static GapRemote& GetInstance() {
9+
static GapRemote instance;
10+
return instance;
11+
}
12+
// 删除拷贝构造函数和赋值运算符
13+
GapRemote(const GapRemote&) = delete;
14+
GapRemote& operator=(const GapRemote&) = delete;
15+
int start_adv(uint8_t *adv_data, uint8_t len, uint32_t duration_ms=1000, bool force=true);
16+
private:
17+
GapRemote();
18+
bool is_broadcast = false;
19+
uint8_t broadcast_count;
20+
uint8_t ble_addr_type;
21+
static void ble_sync_callback(void);
22+
static int ble_gap_event(struct ble_gap_event *event, void *arg);
23+
24+
};
25+
26+
#endif

sdkconfig.defaults

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,14 @@ CONFIG_LV_USE_WIN=n
6363

6464
CONFIG_LV_BUILD_EXAMPLES=n
6565

66+
CONFIG_ESP_MAIN_TASK_STACK_SIZE=6144
67+
68+
CONFIG_MQTT_USE_CUSTOM_CONFIG=y
69+
CONFIG_MQTT_TASK_STACK_SIZE=4096
70+
71+
CONFIG_TACKGROUND_TASK_STACK_SIZE=28672
72+
73+
CONFIG_BT_ENABLED=y
74+
CONFIG_BT_NIMBLE_ENABLED=y
75+
CONFIG_BT_NIMBLE_LOG_LEVEL_ERROR=y
76+
CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY=y

sdkconfig.defaults.esp32c2

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,6 @@ CONFIG_UART_ISR_IN_IRAM=y
2222
CONFIG_ESP_MAIN_TASK_STACK_SIZE=4096
2323

2424
CONFIG_MQTT_USE_CUSTOM_CONFIG=y
25-
CONFIG_MQTT_TASK_STACK_SIZE=3584
25+
CONFIG_MQTT_TASK_STACK_SIZE=3584
26+
27+
CONFIG_BT_ENABLED=n

sdkconfig.defaults.esp32s3

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
77
CONFIG_SPIRAM=y
88
CONFIG_SPIRAM_MODE_OCT=y
99
CONFIG_SPIRAM_SPEED_80M=y
10-
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=4096
10+
# CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=4096
1111
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=49152
1212
CONFIG_SPIRAM_MEMTEST=n
1313
CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
@@ -19,3 +19,5 @@ CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y
1919
CONFIG_SR_WN_WN9_NIHAOXIAOZHI_TTS=y
2020

2121
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096
22+
23+
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=32

sdkconfig.defaults.mem_opt.esp32c2

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,5 @@ CONFIG_AUDIO_LOOP_TASK_STACK_SIZE=1280
3131
CONFIG_VB6824_UART_TASK_STACK_SIZE=2560
3232
CONFIG_VB6824_SEND_USE_TASK=n
3333
# CONFIG_VB6824_SEND_TASK_STACK_SIZE=1280
34+
35+
CONFIG_BT_ENABLED=n

0 commit comments

Comments
 (0)