283 lines
8.4 KiB
C
283 lines
8.4 KiB
C
#include "FreeRTOS.h"
|
||
#include "task.h"
|
||
#include "project_version.h"
|
||
|
||
#define TAG "main"
|
||
|
||
#include "lisa_log.h"
|
||
#include "lisa_time.h"
|
||
#include "alarm_aiui.h"
|
||
|
||
#include "service_led.h"
|
||
#include "service_volume.h"
|
||
#include "service_brightness.h"
|
||
#include "service_button.h"
|
||
#include "service_camera.h"
|
||
#include "service_alarm.h"
|
||
#include "service_image.h"
|
||
|
||
#include "voice_msg.h"
|
||
#include "lisa_kv.h"
|
||
#include "wifi_manager/wifi_manager.h"
|
||
#include "app_datas.h"
|
||
#include "tone.h"
|
||
#include "player_mgr.h"
|
||
#include "power/power_manager.h"
|
||
#include "pa_manager.h"
|
||
#include "lisa_display.h"
|
||
#include "battery/battery.h"
|
||
#include "lisa_ui_nav_scr.h"
|
||
#include "apps/llm/models/model_voice.h"
|
||
#include "voice_cloud.h"
|
||
#ifdef CONFIG_VOICE_LINK_LINGXIN
|
||
#include "lingxin_server_config.h"
|
||
#endif
|
||
|
||
#ifdef CONFIG_VOICE_LINK_LINGXIN
|
||
#define LINGXIN_BUTTON_WAKEUP_DEBOUNCE_MS 800U
|
||
|
||
static bool lingxin_button_wakeup_debounce(void)
|
||
{
|
||
static uint32_t s_last_wakeup_ms;
|
||
uint32_t now_ms = (uint32_t)lisa_os_get_tick_ms();
|
||
|
||
if (s_last_wakeup_ms != 0 && (uint32_t)(now_ms - s_last_wakeup_ms) < LINGXIN_BUTTON_WAKEUP_DEBOUNCE_MS) {
|
||
LISA_LOGI(TAG, "[Lingxin] single click ignored by debounce");
|
||
return false;
|
||
}
|
||
|
||
s_last_wakeup_ms = now_ms;
|
||
return true;
|
||
}
|
||
|
||
static void lingxin_publish_button_wakeup(void)
|
||
{
|
||
struct app_datas *app_datas = get_app_datas();
|
||
|
||
if (app_datas && (app_datas->voice_work_mode & VOICE_WORK_MODE_BUTTON_WAKEUP)) {
|
||
voice_msg_pub(VOICE_MSG_WAKEUP_BUTTON_START, NULL, 0);
|
||
} else {
|
||
const char keyword[] = "xiao ling xiao ling";
|
||
voice_msg_pub(VOICE_MSG_WAKEUP_KEYWORD, (void *)keyword, sizeof(keyword));
|
||
}
|
||
}
|
||
#endif
|
||
|
||
extern uint8_t app_ble_adv_start(uint8_t adv_id, uint8_t adv_type);
|
||
void network_reset(void)
|
||
{
|
||
LOGI("network reset running...");
|
||
#if CONFIG_WIFI_MANAGER
|
||
wifi_mgr_sta_disconnect(true);
|
||
wifi_mgr_sta_config_t list[16] = {0};
|
||
int count = 0;
|
||
do {
|
||
count = wifi_mgr_storage_search_ap(list, (int)(sizeof(list) / sizeof(list[0])), SEARCH_ALL, NULL);
|
||
if (count > 0) {
|
||
int del_count = count;
|
||
if (del_count > (int)(sizeof(list) / sizeof(list[0]))) {
|
||
del_count = (int)(sizeof(list) / sizeof(list[0]));
|
||
}
|
||
for (int i = 0; i < del_count; i++) {
|
||
wifi_mgr_storage_delete_ap(&list[i]);
|
||
}
|
||
}
|
||
} while (count > (int)(sizeof(list) / sizeof(list[0])));
|
||
#endif
|
||
}
|
||
|
||
|
||
void factory_reset(void)
|
||
{
|
||
LOGI("factory reset running...");
|
||
lisa_kv_clear();
|
||
network_reset();
|
||
LOGI("factory reset dwone.");
|
||
LOGI("The system will restart after 300ms.");
|
||
player_mgr_play(LOCAL, app_tone_get_url(TONE_ID_103), 0);
|
||
vTaskDelay(2000);
|
||
extern void sys_platform_sw_full_reset(void);
|
||
sys_platform_sw_full_reset();
|
||
}
|
||
|
||
static void voice_system_network_probe_success(void *unused, uint32_t msg_id, void *data, uint32_t len, void *user_data)
|
||
{
|
||
#ifdef CONFIG_VOICE_LINK_LINGXIN
|
||
if (lingxin_server_config_fetch() != 0) {
|
||
LOGE("[Lingxin] failed to load runtime config");
|
||
}
|
||
#endif
|
||
service_alarm_init();
|
||
}
|
||
|
||
static void button_changed(void *unused, uint32_t msg_id, void *data, uint32_t len, void *user_data)
|
||
{
|
||
voice_msg_button_evt_t *evt = (voice_msg_button_evt_t *)data;
|
||
|
||
service_image_waiting_cancel();
|
||
|
||
if (evt->button_id != 0) {
|
||
return;
|
||
}
|
||
|
||
switch (evt->action) {
|
||
case VOICE_MSG_BUTTON_ACTION_CLICK:
|
||
{
|
||
/* 单击:非主页先回主页;主页则触发按键唤醒 */
|
||
if (lisa_ui_nav_scr_get_top_id() != 0) {
|
||
LISA_LOGI(TAG, "Single click: not on home page, navigating home");
|
||
lisa_ui_nav_scr_nav_to(0);
|
||
break;
|
||
} else {
|
||
LISA_LOGI(TAG, "Single click: wakeup trigger");
|
||
#ifdef CONFIG_VOICE_LINK_LINGXIN
|
||
if (!lingxin_button_wakeup_debounce()) {
|
||
break;
|
||
}
|
||
|
||
LISA_LOGI(TAG, "[Lingxin] single click: wakeup/barge-in trigger");
|
||
lingxin_publish_button_wakeup();
|
||
#else
|
||
if (model_voice_tts_is_playing()) {
|
||
LISA_LOGI(TAG, "Single click: TTS playing, stop it");
|
||
player_mgr_stop(TTS);
|
||
break;
|
||
}
|
||
#ifdef CONFIG_VOICE_LINK_LSCHAT
|
||
if (model_voice_cloud_is_running()) {
|
||
voice_msg_pub(VOICE_MSG_CLOUD_MCP_CHAT_EXIT, NULL, 0);
|
||
} else {
|
||
const char keyword[] = "xiao ling xiao ling";
|
||
voice_msg_pub(VOICE_MSG_WAKEUP_KEYWORD, (void *)keyword, sizeof(keyword));
|
||
}
|
||
#else
|
||
LISA_LOGI(TAG, "LSChat link inactive, ignore LSChat wakeup trigger");
|
||
#endif
|
||
#endif
|
||
}
|
||
break;
|
||
}
|
||
case VOICE_MSG_BUTTON_ACTION_DOUBLE_CLICK:
|
||
{
|
||
/* 双击:留给 LiveKit 设备呼叫,避免同时触发拍照识图 */
|
||
LISA_LOGI(TAG, "power button double click, reserved for livekit call");
|
||
break;
|
||
}
|
||
case VOICE_MSG_BUTTON_ACTION_TRIPLE_CLICK:
|
||
{
|
||
/* 三击:留给 LiveKit 来电拒接,不再打开二维码/信息页 */
|
||
LISA_LOGI(TAG, "power button triple click, reserved for livekit reject");
|
||
break;
|
||
}
|
||
case VOICE_MSG_BUTTON_ACTION_QUADRUPLE_CLICK:
|
||
{
|
||
/* 四击:拍照识图 */
|
||
LISA_LOGI(TAG, "power button quadruple click, image recognition");
|
||
voice_msg_pub(VOICE_MSG_BUTTON_IMAGE_RECOGNITION, NULL, 0);
|
||
break;
|
||
}
|
||
case VOICE_MSG_BUTTON_ACTION_QUINTUPLE_CLICK:
|
||
case VOICE_MSG_BUTTON_ACTION_SEXTUPLE_CLICK:
|
||
case VOICE_MSG_BUTTON_ACTION_SEPTUPLE_CLICK:
|
||
{
|
||
struct app_datas *app_datas = get_app_datas();
|
||
/* 连击 >=5:进入 BLE 配网并打开信息页 */
|
||
LISA_LOGI(TAG, "power button multi click, enter BLE config");
|
||
if (app_datas != NULL && !app_datas->wifi_connected) {
|
||
player_mgr_play(LOCAL, app_tone_get_url(TONE_ID_70), 0);
|
||
}
|
||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||
network_reset();
|
||
app_ble_adv_start(0, 1);
|
||
voice_msg_pub(VOICE_MSG_CLOUD_OPEN_INFO, NULL, 0);
|
||
break;
|
||
}
|
||
case VOICE_MSG_BUTTON_ACTION_REPEAT_CLICK:
|
||
{
|
||
/* 连击 >=8:恢复出厂 */
|
||
LISA_LOGI(TAG, "power button repeat click, factory reset");
|
||
factory_reset();
|
||
break;
|
||
}
|
||
case VOICE_MSG_BUTTON_ACTION_LONG_HOLD:
|
||
{
|
||
/* 长按:关机(USB 供电时忽略)*/
|
||
if (power_is_usb_plugged()) {
|
||
LISA_LOGI(TAG, "USB connected, ignore long press shutdown");
|
||
} else {
|
||
LISA_LOGI(TAG, "power button long press hold, shutting down...");
|
||
power_shutdown();
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
static void shutdown(void)
|
||
{
|
||
LISA_LOGI(TAG, "System shutting down...");
|
||
|
||
pa_manager_onoff(0);
|
||
|
||
lisa_device_t *disp = lisa_device_get("display");
|
||
lisa_display_blanking_on(disp);
|
||
lisa_display_set_brightness(disp, 0);
|
||
|
||
vTaskDelay(pdMS_TO_TICKS(500));
|
||
}
|
||
|
||
int main(int argc, char **argv)
|
||
{
|
||
LOGI("Application version: %s-%s", PROJECT_VERSION_STR, PROJECT_VERSION_COMMIT);
|
||
|
||
boot_watchdog_feed();
|
||
|
||
power_config_t power_cfg = {
|
||
.on_shutdown = shutdown,
|
||
};
|
||
power_init(&power_cfg);
|
||
|
||
if (!power_wait_settle()) {
|
||
power_shutdown();
|
||
return 0;
|
||
}
|
||
|
||
battery_init();
|
||
|
||
voice_msg_sub(VOICE_MSG_SYSTEM_NETWORK_PROBE_SUCCESS, voice_system_network_probe_success, NULL);
|
||
voice_msg_sub(VOICE_MSG_BUTTON_CHANGE, button_changed, NULL);
|
||
|
||
service_led_init();
|
||
service_volume_init();
|
||
service_brightness_init();
|
||
service_button_init();
|
||
service_image_init();
|
||
#if !CONFIG_4G_MODULE
|
||
service_camera_init();
|
||
#endif
|
||
|
||
|
||
#if CONFIG_APPLICATION_UI
|
||
extern int lisa_ui_init(void);
|
||
lisa_ui_init();
|
||
#endif
|
||
|
||
|
||
#if CONFIG_WIFI_MANAGER
|
||
wifi_mgr_sta_config_t list[8] = {0};
|
||
int count = wifi_mgr_storage_search_ap(list, (int)(sizeof(list) / sizeof(list[0])), SEARCH_ALL, NULL);
|
||
if (count == 0) {
|
||
voice_msg_pub(VOICE_MSG_CLOUD_OPEN_INFO, NULL, 0);
|
||
player_mgr_play(LOCAL, app_tone_get_url(TONE_ID_70), 0);
|
||
}
|
||
#endif
|
||
|
||
vTaskDelay(pdMS_TO_TICKS(3000));
|
||
while (1) {
|
||
boot_watchdog_feed();
|
||
vTaskDelay(pdMS_TO_TICKS(100));
|
||
}
|
||
|
||
return 0;
|
||
}
|