Skip to content

Commit 9091363

Browse files
authored
Sync UI (tuya#115)
* Support T5AI EVB board * Synchronize the display under the app to esp32/common --------- Co-authored-by: YangJie <shiliu.yang@tuya.com>
1 parent 6ac1021 commit 9091363

4 files changed

Lines changed: 246 additions & 2 deletions

File tree

apps/tuya.ai/your_chat_bot/src/display/app_display.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,17 @@ static OPERATE_RET __get_ui_font(UI_FONT_T *ui_font)
103103
ui_font->emoji_list = sg_emo_list;
104104
#endif
105105
#elif defined(BOARD_CHOICE_TUYA_T5AI_EVB)
106+
#if defined(ENABLE_GUI_WECHAT)
107+
ui_font->text = &font_puhui_18_2;
108+
ui_font->icon = &font_awesome_16_4;
109+
ui_font->emoji = font_emoji_32_init();
110+
ui_font->emoji_list = sg_emo_list;
111+
#elif defined(ENABLE_GUI_CHATBOT)
112+
ui_font->text = &font_puhui_18_2;
113+
ui_font->icon = &font_awesome_16_4;
114+
ui_font->emoji = font_emoji_64_init();
115+
ui_font->emoji_list = sg_emo_list;
116+
#endif
106117
#elif defined(BOARD_CHOICE_BREAD_COMPACT_WIFI)
107118
ui_font->text = &font_puhui_14_1;
108119
ui_font->icon = &font_awesome_14_1;

boards/ESP32/common/display/app_display.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,17 @@ static OPERATE_RET __get_ui_font(UI_FONT_T *ui_font)
106106
ui_font->emoji_list = sg_emo_list;
107107
#endif
108108
#elif defined(BOARD_CHOICE_TUYA_T5AI_EVB)
109+
#if defined(ENABLE_GUI_WECHAT)
110+
ui_font->text = &font_puhui_18_2;
111+
ui_font->icon = &font_awesome_16_4;
112+
ui_font->emoji = font_emoji_32_init();
113+
ui_font->emoji_list = sg_emo_list;
114+
#elif defined(ENABLE_GUI_CHATBOT)
115+
ui_font->text = &font_puhui_18_2;
116+
ui_font->icon = &font_awesome_16_4;
117+
ui_font->emoji = font_emoji_64_init();
118+
ui_font->emoji_list = sg_emo_list;
119+
#endif
109120
#elif defined(BOARD_CHOICE_BREAD_COMPACT_WIFI)
110121
ui_font->text = &font_puhui_14_1;
111122
ui_font->icon = &font_awesome_14_1;

boards/ESP32/common/display/ui/ui_display.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ void ui_set_network(char *wifi_icon);
6767

6868
void ui_set_status_bar_pad(int32_t value);
6969

70+
#if defined(ENABLE_GUI_STREAM_AI_TEXT) && (ENABLE_GUI_STREAM_AI_TEXT == 1)
71+
void ui_set_assistant_msg_stream_start(void);
72+
73+
void ui_set_assistant_msg_stream_data(const char *text);
74+
75+
void ui_set_assistant_msg_stream_end(void);
76+
#endif
77+
7078
#ifdef __cplusplus
7179
}
7280
#endif

boards/ESP32/common/display/ui/ui_wechat.c

Lines changed: 216 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,16 @@
2121
#include "font_awesome_symbols.h"
2222
#include "lvgl.h"
2323

24+
#include "tuya_ringbuf.h"
25+
#include "tkl_mutex.h"
26+
2427
/***********************************************************
2528
************************macro define************************
2629
***********************************************************/
27-
#define MAX_MASSAGE_NUM 20
30+
#define MAX_MASSAGE_NUM 20
31+
#define STREAM_BUFF_MAX_LEN 1024
32+
#define STREAM_TEXT_SHOW_WORD_NUM 5
33+
#define ONE_WORD_MAX_LEN 4
2834

2935
/***********************************************************
3036
***********************typedef define***********************
@@ -45,10 +51,23 @@ typedef struct {
4551
lv_obj_t *mute_label;
4652
} APP_UI_T;
4753

54+
typedef struct {
55+
bool is_start;
56+
TKL_MUTEX_HANDLE rb_mutex;
57+
TUYA_RINGBUFF_T text_ringbuff;
58+
59+
lv_obj_t *msg_cont;
60+
lv_obj_t *bubble;
61+
lv_obj_t *label;
62+
63+
lv_timer_t *timer;
64+
} APP_UI_STREAM_T;
65+
4866
typedef struct {
4967
APP_UI_T ui;
5068

5169
UI_FONT_T font;
70+
APP_UI_STREAM_T stream;
5271

5372
lv_timer_t *notification_tm;
5473
} APP_CHATBOT_UI_T;
@@ -129,7 +148,7 @@ int ui_init(UI_FONT_T *ui_font)
129148
lv_obj_set_style_text_font(screen, sg_ui.font.text, 0);
130149
lv_obj_set_style_text_color(screen, lv_color_black(), 0);
131150
lv_obj_set_scrollbar_mode(screen, LV_SCROLLBAR_MODE_OFF);
132-
lv_obj_set_scroll_dir(screen, LV_DIR_NONE);
151+
lv_obj_set_scroll_dir(screen, LV_DIR_VER);
133152

134153
// Container
135154
sg_ui.ui.container = lv_obj_create(screen);
@@ -293,6 +312,201 @@ void ui_set_assistant_msg(const char *text)
293312
lv_obj_update_layout(sg_ui.ui.content);
294313
}
295314

315+
static uint8_t __get_one_word_from_stream_ringbuff(APP_UI_STREAM_T *stream, char *result)
316+
{
317+
uint32_t rb_used_size = 0, read_len = 0;
318+
uint8_t get_word_num = 0, word_len = 0;
319+
char tmp = 0;
320+
321+
tkl_mutex_lock(stream->rb_mutex);
322+
rb_used_size = tuya_ring_buff_used_size_get(stream->text_ringbuff);
323+
tkl_mutex_unlock(stream->rb_mutex);
324+
if (0 == rb_used_size) {
325+
return 0;
326+
}
327+
328+
// get word len
329+
do {
330+
tkl_mutex_lock(stream->rb_mutex);
331+
read_len = tuya_ring_buff_read(stream->text_ringbuff, &tmp, 1);
332+
tkl_mutex_unlock(stream->rb_mutex);
333+
334+
if ((tmp & 0xC0) != 0x80) {
335+
if ((tmp & 0xE0) == 0xC0) {
336+
word_len = 2;
337+
} else if ((tmp & 0xF0) == 0xE0) {
338+
word_len = 3;
339+
} else if ((tmp & 0xF8) == 0xF0) {
340+
word_len = 4;
341+
} else {
342+
word_len = 1;
343+
}
344+
break;
345+
}
346+
347+
tmp = 0;
348+
} while (read_len);
349+
350+
if (0 == word_len) {
351+
return 0;
352+
}
353+
354+
// get word
355+
result[0] = tmp;
356+
357+
if (word_len - 1) {
358+
tkl_mutex_lock(stream->rb_mutex);
359+
tuya_ring_buff_read(stream->text_ringbuff, &result[1], word_len - 1);
360+
tkl_mutex_unlock(stream->rb_mutex);
361+
}
362+
363+
return word_len;
364+
}
365+
366+
static uint8_t __get_words_from_stream_ringbuff(APP_UI_STREAM_T *stream, uint8_t word_num, char *result)
367+
{
368+
uint8_t word_len = 0, i = 0, get_num = 0;
369+
uint32_t result_len = 0;
370+
371+
for (i = 0; i < word_num; i++) {
372+
word_len = __get_one_word_from_stream_ringbuff(stream, &result[result_len]);
373+
if (0 == word_len) {
374+
break;
375+
}
376+
result_len += word_len;
377+
get_num++;
378+
}
379+
380+
result[result_len] = '\0';
381+
382+
return get_num;
383+
}
384+
385+
static void __stream_timer_cb(lv_timer_t *lv_timer)
386+
{
387+
uint8_t word_num = 0;
388+
char text[STREAM_TEXT_SHOW_WORD_NUM * ONE_WORD_MAX_LEN + 1] = {0};
389+
APP_UI_STREAM_T *stream = (APP_UI_STREAM_T *)lv_timer_get_user_data(lv_timer);
390+
391+
word_num = __get_words_from_stream_ringbuff(stream, STREAM_TEXT_SHOW_WORD_NUM, text);
392+
if (0 == word_num) {
393+
if (false == stream->is_start) {
394+
lv_timer_del(stream->timer);
395+
stream->timer = NULL;
396+
}
397+
return;
398+
}
399+
400+
lv_label_ins_text(stream->label, LV_LABEL_POS_LAST, text);
401+
402+
lv_coord_t content_height = lv_obj_get_height(stream->msg_cont);
403+
lv_coord_t height = lv_obj_get_height(sg_ui.ui.content);
404+
lv_coord_t y_position = content_height;
405+
406+
if (content_height > height) {
407+
lv_obj_scroll_to_y(sg_ui.ui.content, y_position, LV_ANIM_OFF);
408+
} else {
409+
lv_obj_scroll_to_view_recursive(stream->msg_cont, LV_ANIM_OFF);
410+
}
411+
412+
lv_obj_update_layout(sg_ui.ui.content);
413+
}
414+
415+
void ui_set_assistant_msg_stream_start(void)
416+
{
417+
if (sg_ui.ui.content == NULL) {
418+
return;
419+
}
420+
421+
if (sg_ui.stream.timer) {
422+
lv_timer_del(sg_ui.stream.timer);
423+
sg_ui.stream.timer = NULL;
424+
}
425+
426+
// Check if the number of messages exceeds the limit
427+
uint32_t child_count = lv_obj_get_child_cnt(sg_ui.ui.content);
428+
if (child_count >= MAX_MASSAGE_NUM) {
429+
lv_obj_t *first_child = lv_obj_get_child(sg_ui.ui.content, 0);
430+
if (first_child) {
431+
lv_obj_del(first_child);
432+
}
433+
}
434+
435+
sg_ui.stream.msg_cont = lv_obj_create(sg_ui.ui.content);
436+
lv_obj_remove_style_all(sg_ui.stream.msg_cont);
437+
lv_obj_set_size(sg_ui.stream.msg_cont, LV_PCT(100), LV_SIZE_CONTENT);
438+
lv_obj_set_style_pad_ver(sg_ui.stream.msg_cont, 6, 0);
439+
lv_obj_set_style_pad_column(sg_ui.stream.msg_cont, 10, 0);
440+
441+
lv_obj_t *avatar = lv_obj_create(sg_ui.stream.msg_cont);
442+
lv_obj_set_style_text_font(avatar, sg_ui.font.icon, 0);
443+
lv_obj_add_style(avatar, &sg_ui.ui.style_avatar, 0);
444+
lv_obj_set_size(avatar, 40, 40);
445+
lv_obj_align(avatar, LV_ALIGN_TOP_LEFT, 0, 0);
446+
447+
lv_obj_t *icon = lv_label_create(avatar);
448+
lv_label_set_text(icon, FONT_AWESOME_USER_ROBOT);
449+
lv_obj_center(icon);
450+
451+
sg_ui.stream.bubble = lv_obj_create(sg_ui.stream.msg_cont);
452+
lv_obj_set_width(sg_ui.stream.bubble, LV_PCT(75));
453+
lv_obj_set_height(sg_ui.stream.bubble, LV_SIZE_CONTENT);
454+
lv_obj_add_style(sg_ui.stream.bubble, &sg_ui.ui.style_ai_bubble, 0);
455+
lv_obj_align_to(sg_ui.stream.bubble, avatar, LV_ALIGN_OUT_RIGHT_TOP, 10, 0);
456+
457+
lv_obj_set_scrollbar_mode(sg_ui.stream.bubble, LV_SCROLLBAR_MODE_OFF);
458+
lv_obj_set_scroll_dir(sg_ui.stream.bubble, LV_DIR_VER);
459+
460+
lv_obj_t *text_cont = lv_obj_create(sg_ui.stream.bubble);
461+
lv_obj_remove_style_all(text_cont);
462+
lv_obj_set_size(text_cont, LV_PCT(100), LV_SIZE_CONTENT);
463+
lv_obj_set_flex_flow(text_cont, LV_FLEX_FLOW_COLUMN);
464+
465+
sg_ui.stream.label = lv_label_create(text_cont);
466+
lv_label_set_text(sg_ui.stream.label, "");
467+
lv_obj_set_width(sg_ui.stream.label, LV_PCT(100));
468+
lv_label_set_long_mode(sg_ui.stream.label, LV_LABEL_LONG_WRAP);
469+
470+
OPERATE_RET rt = OPRT_OK;
471+
if (NULL == sg_ui.stream.text_ringbuff) {
472+
rt = tuya_ring_buff_create(STREAM_BUFF_MAX_LEN, OVERFLOW_PSRAM_STOP_TYPE, &sg_ui.stream.text_ringbuff);
473+
if (rt != OPRT_OK) {
474+
return;
475+
}
476+
}
477+
478+
tuya_ring_buff_reset(sg_ui.stream.text_ringbuff);
479+
480+
if (sg_ui.stream.rb_mutex) {
481+
rt = tkl_mutex_create_init(&sg_ui.stream.rb_mutex);
482+
if (rt != OPRT_OK) {
483+
return;
484+
}
485+
}
486+
487+
sg_ui.stream.timer = lv_timer_create(__stream_timer_cb, 1000, &sg_ui.stream);
488+
if (NULL == sg_ui.stream.timer) {
489+
return;
490+
}
491+
492+
sg_ui.stream.is_start = true;
493+
}
494+
495+
void ui_set_assistant_msg_stream_data(const char *text)
496+
{
497+
if (false == sg_ui.stream.is_start) {
498+
return;
499+
}
500+
501+
tkl_mutex_lock(sg_ui.stream.rb_mutex);
502+
tuya_ring_buff_write(sg_ui.stream.text_ringbuff, text, strlen(text));
503+
tkl_mutex_unlock(sg_ui.stream.rb_mutex);
504+
}
505+
506+
void ui_set_assistant_msg_stream_end(void)
507+
{
508+
sg_ui.stream.is_start = false;
509+
}
296510
void ui_set_system_msg(const char *text)
297511
{
298512
if (sg_ui.ui.content == NULL) {

0 commit comments

Comments
 (0)