From 28aaa9a6a571b56189adbbb0695c4a15349dfc7d Mon Sep 17 00:00:00 2001 From: maidang Date: Mon, 6 Jul 2026 14:29:26 +0800 Subject: [PATCH 1/2] feat: update Gitee sync workflow and add app_ui_action registration for AI display --- .github/workflows/sync-to-gitee.yml | 4 +- src/app_ui_action.c | 204 ++++++++++++++++++++++++++++ src/tuyaopen_claw_chat.c | 14 ++ 3 files changed, 220 insertions(+), 2 deletions(-) create mode 100644 src/app_ui_action.c diff --git a/.github/workflows/sync-to-gitee.yml b/.github/workflows/sync-to-gitee.yml index 4edcbba..2a5151d 100644 --- a/.github/workflows/sync-to-gitee.yml +++ b/.github/workflows/sync-to-gitee.yml @@ -5,7 +5,7 @@ on: jobs: sync: - if: github.repository == 'tuya/DuckyClaw' + if: github.repository == 'tuya/TuyaOpenClaw' runs-on: ubuntu-latest name: Git Repo Sync steps: @@ -14,6 +14,6 @@ jobs: fetch-depth: 0 - uses: tuya/TuyaOpen@master with: - target-url: 'https://gitee.com/tuya-open/DuckyClaw.git' + target-url: 'https://gitee.com/tuya-open/TuyaOpenClaw.git' target-username: 'flyingcys' target-token: ${{ secrets.GITEE_TOKEN }} diff --git a/src/app_ui_action.c b/src/app_ui_action.c new file mode 100644 index 0000000..9a51daf --- /dev/null +++ b/src/app_ui_action.c @@ -0,0 +1,204 @@ +/** + * @file app_ui_action.c + * @brief app_ui_action module is used to + * @version 0.1 + * @copyright Copyright (c) 2021-2026 Tuya Inc. All Rights Reserved. + */ +#include "tal_api.h" +#include + +#if defined(ENABLE_COMP_AI_DISPLAY) && (ENABLE_COMP_AI_DISPLAY == 1) +#include "ai_ui_manage.h" + +#if defined(ENABLE_COMP_AI_PICTURE) && (ENABLE_COMP_AI_PICTURE == 1) +#include "image_album.h" +#include "ai_picture.h" +#include "ai_picture_input.h" +#endif + +#if defined(ENABLE_COMP_AI_VIDEO) && (ENABLE_COMP_AI_VIDEO == 1) +#include "ai_video_input.h" +#endif + +#if defined(ENABLE_PRINTER) && (ENABLE_PRINTER == 1) +#include "app_printer.h" +#endif + +/*********************************************************** +************************macro define************************ +***********************************************************/ + + +/*********************************************************** +***********************typedef define*********************** +***********************************************************/ +#if defined(ENABLE_COMP_AI_VIDEO) && (ENABLE_COMP_AI_VIDEO == 1) +static bool sg_ai_vision_enabled = false; +#endif + +/*********************************************************** +***********************function define********************** +***********************************************************/ +#if defined(ENABLE_COMP_AI_VIDEO) && (ENABLE_COMP_AI_VIDEO == 1) +static void __display_camera_yuv_fram(TDL_CAMERA_FRAME_T *frame) +{ + AI_UI_VIDEO_T video = {0}; + + if (NULL == frame) { + return; + } + + video.width = frame->width; + video.height = frame->height; + video.yuv422 = frame->data; + video.len = frame->data_len; + + ai_ui_disp_msg_sync(AI_UI_DISP_CAMERA_FLUSH, (uint8_t*)&video, sizeof(AI_UI_VIDEO_T)); +} +#endif /* ENABLE_COMP_AI_VIDEO */ + + +static void __app_ui_action_handle(AI_UI_ACTION_E action, uint8_t *data, uint32_t len) +{ + switch (action) { +#if defined(ENABLE_COMP_AI_VIDEO) && (ENABLE_COMP_AI_VIDEO == 1) + case AI_UI_ACT_OPEN_CAMERA: + sg_ai_vision_enabled = false; + ai_video_set_yuv_frame_flush_cb(__display_camera_yuv_fram); + ai_video_start(); + ai_ui_disp_msg_sync(AI_UI_DISP_CAMERA_OPEN, NULL, 0); + break; + + case AI_UI_ACT_TAKE_PHOTO: { + uint8_t *jpeg = NULL; + uint32_t jpeg_len = 0; + ai_video_get_jpeg_frame(&jpeg, &jpeg_len); + + if (jpeg && jpeg_len) { +#if defined(ENABLE_COMP_AI_PICTURE) && (ENABLE_COMP_AI_PICTURE == 1) + char name[AI_PICTURE_NAME_MAX_LEN + 1] = {0}; + ai_picture_save_to_album(jpeg, jpeg_len, NULL, name); + ai_ui_disp_msg_sync(AI_UI_DISP_CAMERA_THUMB, jpeg, jpeg_len); +#endif + if (sg_ai_vision_enabled) { + /* Close camera so the user sees the AI response in chat */ + ai_video_stop(); + ai_video_set_yuv_frame_flush_cb(NULL); + ai_ui_disp_msg_sync(AI_UI_DISP_CAMERA_CLOSE, NULL, 0); +#if defined(ENABLE_COMP_AI_PICTURE) && (ENABLE_COMP_AI_PICTURE == 1) + ai_ui_disp_msg(AI_UI_DISP_USER_IMAGE_LINK, (uint8_t *)name, strlen(name)); + + ai_picture_input_recognize(jpeg, jpeg_len); +#endif + } else { + ai_ui_disp_msg_sync(AI_UI_DISP_CAMERA_THUMB, jpeg, jpeg_len); + } + + ai_video_jpeg_image_free(&jpeg); + } + } break; + + case AI_UI_ACT_CLOSE_CAMER: + ai_video_stop(); + ai_video_set_yuv_frame_flush_cb(NULL); + ai_ui_disp_msg_sync(AI_UI_DISP_CAMERA_CLOSE, NULL, 0); + break; + + case AI_UI_ACT_CAMERA_AI_ON: + sg_ai_vision_enabled = true; + break; + + case AI_UI_ACT_CAMERA_AI_OFF: + sg_ai_vision_enabled = false; + break; +#endif /* ENABLE_COMP_AI_VIDEO */ + +#if defined(ENABLE_COMP_AI_PICTURE) && (ENABLE_COMP_AI_PICTURE == 1) + case AI_UI_ACT_OPEN_ALBUM: { + char *album_name = ai_picture_get_album_name(); + if (album_name) { + ai_ui_disp_msg_sync(AI_UI_DISP_ALBUM_OPEN, (uint8_t*)album_name, strlen(album_name)); + } + } break; + + case AI_UI_ACT_VIEW_PREV_IMG: + ai_ui_disp_msg_sync(AI_UI_DISP_ALBUM_VIEW_PREV, NULL, 0); + break; + + case AI_UI_ACT_VIEW_NEXT_IMG: + ai_ui_disp_msg_sync(AI_UI_DISP_ALBUM_VIEW_NEXT, NULL, 0); + break; + + case AI_UI_ACT_VIEW_ALL_IMG: + ai_ui_disp_msg_sync(AI_UI_DISP_ALBUM_VIEW_ALL, NULL, 0); + break; + + case AI_UI_ACT_DELETE_IMG: { + char *name = (char *)data; + if (NULL == name) { + PR_ERR("image name is null"); + break; + } + IMAGE_ALBUM_HANDLE hdl = image_album_find_by_name(ai_picture_get_album_name()); + image_album_delete(hdl, name); + ai_ui_disp_msg_sync(AI_UI_DISP_ALBUM_RELOAD, NULL, 0); + } break; + + case AI_UI_ACT_BATCH_DELETE_IMG: { + if (NULL == data || len < sizeof(AI_UI_BATCH_DELETE_T)) { + break; + } + IMAGE_ALBUM_HANDLE hdl = image_album_find_by_name(ai_picture_get_album_name()); + if (NULL == hdl) { + PR_ERR("album not found for batch delete"); + break; + } + AI_UI_BATCH_DELETE_T *batch = (AI_UI_BATCH_DELETE_T *)data; + uint32_t i; + for (i = 0; i < batch->count && i < AI_UI_BATCH_DELETE_MAX; i++) { + image_album_delete(hdl, batch->names[i]); + } + } break; + + case AI_UI_ACT_CLOSE_ALBUM: + ai_ui_disp_msg_sync(AI_UI_DISP_ALBUM_CLOSE, NULL, 0); + break; + + case AI_UI_ACT_OPEN_IMG_ATTACH_LIST: + ai_ui_disp_msg_sync(AI_UI_DISP_ALBUM_SELECT_IMG, NULL, 0); + break; + + case AI_UI_ACT_ADD_IMG_ATTACH: { + ai_ui_disp_msg_sync(AI_UI_DISP_ADD_CHAT_ATTACH_IMG, data, strlen((char *)data)); + ai_picture_input_add_from_album((char *)data, NULL); + } break; + + case AI_UI_ACT_DEL_IMG_ATTACH: { + ai_picture_input_del_from_album((char *)data); + } break; + +#if defined(ENABLE_PRINTER) && (ENABLE_PRINTER == 1) + case AI_UI_ACT_PRINT_IMG: { + if (NULL == data || 0 == len) { + PR_ERR("print: filename is null"); + break; + } + OPERATE_RET print_rt = app_print_img_from_album((const char *)data); + int32_t result = (int32_t)print_rt; + ai_ui_disp_msg(AI_UI_DISP_PRINT_RESULT, (uint8_t *)&result, sizeof(result)); + } break; +#endif /* ENABLE_PRINTER */ + +#endif /* ENABLE_IMAGE_ALBUM */ + default: + break; + } +} + + +void app_ui_action_register(void) +{ + ai_ui_action_cb_register(__app_ui_action_handle); +} + +#endif diff --git a/src/tuyaopen_claw_chat.c b/src/tuyaopen_claw_chat.c index 4fc1631..a5baf5a 100755 --- a/src/tuyaopen_claw_chat.c +++ b/src/tuyaopen_claw_chat.c @@ -222,6 +222,10 @@ static void __ai_chat_handle_event(AI_NOTIFY_EVENT_T *event) } } +#if defined(ENABLE_COMP_AI_DISPLAY) && (ENABLE_COMP_AI_DISPLAY == 1) +extern void app_ui_action_register(void); +#endif + OPERATE_RET tuyaopen_claw_chat_init(void) { OPERATE_RET rt = OPRT_OK; @@ -233,6 +237,11 @@ OPERATE_RET tuyaopen_claw_chat_init(void) }; TUYA_CALL_ERR_RETURN(ai_chat_init(&ai_chat_cfg)); +#if defined(ENABLE_COMP_AI_DISPLAY) && (ENABLE_COMP_AI_DISPLAY == 1) + /* Register popup (+ button) action handler: camera / album / add-image attach */ + app_ui_action_register(); +#endif + #if defined(ENABLE_COMP_AI_VIDEO) && (ENABLE_COMP_AI_VIDEO == 1) TUYA_CALL_ERR_LOG(ai_video_init()); TUYA_CALL_ERR_LOG(ai_video_set_yuv_frame_flush_cb(__ai_video_display_flush)); @@ -242,6 +251,11 @@ OPERATE_RET tuyaopen_claw_chat_init(void) TUYA_CALL_ERR_RETURN(ai_mcp_init()); #endif +#if defined(ENABLE_COMP_AI_PICTURE) && (ENABLE_COMP_AI_PICTURE == 1) + /* Create/register the "ai_picture" album so album + add-image popup actions resolve */ + TUYA_CALL_ERR_RETURN(ai_picture_init()); +#endif + // Free heap size tal_sw_timer_create(__printf_free_heap_tm_cb, NULL, &sg_printf_heap_tm); tal_sw_timer_start(sg_printf_heap_tm, PRINTF_FREE_HEAP_TTIME, TAL_TIMER_CYCLE); From 4dffef3c360adbea29b87bdb5f6b22d019479c76 Mon Sep 17 00:00:00 2001 From: maidang Date: Mon, 6 Jul 2026 14:30:11 +0800 Subject: [PATCH 2/2] chore: update subproject commit reference for TuyaOpen --- TuyaOpen | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TuyaOpen b/TuyaOpen index 2d1b79b..4e6d0e7 160000 --- a/TuyaOpen +++ b/TuyaOpen @@ -1 +1 @@ -Subproject commit 2d1b79b249614318dca74e2328f4a525c9851ed5 +Subproject commit 4e6d0e7e6f8766a1668998bc7f5634e11165acfc