wangzhibo
10 天以前 220e4fab27b7f419b3e89e2f2d28ae789aac09d7
xiaozhi-esp32-2.2.6/main/boards/sening-xiaozhi-s3/system.c
@@ -1,6 +1,7 @@
#include "system.h"
#include "config.h"
#include "app_task.h"
#include "parent_schedule.h"
#include "display/lvgl_display/jpg/jpeg_to_image.h"
#include <esp_heap_caps.h>
@@ -71,6 +72,8 @@
static bool battery_charging_gpio_initialized;
static alarm_entry_t current_alarm1_entry;
static bool current_alarm1_valid;
static alarm_entry_t schedule_wake_entry;
static bool schedule_wake_valid;
static TaskHandle_t alarm_monitor_task_handle;
static TaskHandle_t alarm_power_off_restore_task_handle;
@@ -89,6 +92,8 @@
static bool get_current_time(i2c_dev_t *i2c_dev, struct tm *timeinfo);
static int select_next_alarm_index(const alarm_store_t *store, const struct tm *now);
static int alarm_delta_seconds(const alarm_entry_t *entry, const struct tm *now);
static const alarm_entry_t *select_soonest_alarm(const alarm_store_t *store, const struct tm *now);
static void program_soonest_alarm(i2c_dev_t *i2c_dev, const struct tm *now);
static int mqtt_weekday_to_tm_wday(int day);
static uint8_t tm_wday_to_repeat_bit(int tm_wday);
static bool alarm_entry_equals(const alarm_entry_t *left, const alarm_entry_t *right);
@@ -159,10 +164,13 @@
    if (!command || command[0] == '\0') {
        return false;
    }
    if (Board_Is_Chat_Return_Command(command)) {
        return false;
    }
    return strcmp(command, OFFLINE_REPEATER_WORD) == 0 ||
           strcmp(command, OFFLINE_START_REPEATER_WORD) == 0 ||
           strstr(command, OFFLINE_REPEATER_WORD) ||
           strstr(command, OFFLINE_START_REPEATER_WORD);
           strstr(command, OFFLINE_START_REPEATER_WORD) ||
           strstr(command, "打开泛听");
}
bool Board_Handle_Offline_Command(const char *command)
@@ -198,20 +206,52 @@
    esp_sntp_init();
}
void DS2312_Update_Alarm(i2c_dev_t *i2c_dev, struct tm *time)
static const alarm_entry_t *select_soonest_alarm(const alarm_store_t *store, const struct tm *now)
{
    const alarm_entry_t *best = NULL;
    int best_delta = SECONDS_PER_DAY * 8 + 1;
    if (store && store->count > 0) {
        int index = select_next_alarm_index(store, now);
        if (index >= 0) {
            best = &store->entries[index];
            best_delta = alarm_delta_seconds(best, now);
        }
    }
    if (schedule_wake_valid) {
        int delta = alarm_delta_seconds(&schedule_wake_entry, now);
        if (delta < best_delta) {
            best = &schedule_wake_entry;
        }
    }
    return best;
}
static void program_soonest_alarm(i2c_dev_t *i2c_dev, const struct tm *now)
{
    alarm_store_t store;
    if (load_alarm_store(&store) != ESP_OK) {
        disable_alarm1(i2c_dev);
        memset(&store, 0, sizeof(store));
    }
    const alarm_entry_t *best = select_soonest_alarm(&store, now);
    if (!best) {
        if (current_alarm1_valid && !Board_Is_Power_Off()) {
            disable_alarm1(i2c_dev);
        }
        return;
    }
    if (store.count == 0) {
        disable_alarm1(i2c_dev);
        ESP_LOGI(TAG, "alarm list is empty");
    if (!current_alarm1_valid) {
        program_alarm1(i2c_dev, best);
        return;
    }
    int next_delta = alarm_delta_seconds(best, now);
    int current_delta = alarm_delta_seconds(&current_alarm1_entry, now);
    if (next_delta < current_delta || !alarm_entry_equals(best, &current_alarm1_entry)) {
        program_alarm1(i2c_dev, best);
    }
}
void DS2312_Update_Alarm(i2c_dev_t *i2c_dev, struct tm *time)
{
    struct tm now;
    if (time) {
        now = *time;
@@ -219,14 +259,7 @@
        ESP_LOGW(TAG, "current time unavailable, skip alarm update");
        return;
    }
    int index = select_next_alarm_index(&store, &now);
    if (index < 0) {
        disable_alarm1(i2c_dev);
        return;
    }
    program_alarm1(i2c_dev, &store.entries[index]);
    program_soonest_alarm(i2c_dev, &now);
}
void DS2312_Start_Alarm_Monitor(i2c_dev_t *i2c_dev)
@@ -241,6 +274,43 @@
        alarm_monitor_task_handle = NULL;
        ESP_LOGE(TAG, "create alarm monitor task failed");
    }
}
bool Board_Get_Wall_Clock(struct tm *out)
{
    if (!out) {
        return false;
    }
    return get_current_time(ds2321_dev, out);
}
esp_err_t DS2312_Set_Schedule_Wake(int hour, int min, int sec, uint8_t weekday_bit)
{
    if (hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 59 ||
        (weekday_bit & ALARM_REPEAT_ALL) == 0) {
        return ESP_ERR_INVALID_ARG;
    }
    memset(&schedule_wake_entry, 0, sizeof(schedule_wake_entry));
    strlcpy(schedule_wake_entry.id, "_sched", sizeof(schedule_wake_entry.id));
    schedule_wake_entry.hour = (uint8_t)hour;
    schedule_wake_entry.min = (uint8_t)min;
    schedule_wake_entry.sec = (uint8_t)sec;
    schedule_wake_entry.flags = ALARM_ENTRY_ENABLED;
    schedule_wake_entry.repeat_mask = (uint8_t)(weekday_bit & ALARM_REPEAT_ALL);
    schedule_wake_valid = true;
    DS2312_Update_Alarm(ds2321_dev, NULL);
    ESP_LOGI(TAG, "schedule wake %02d:%02d:%02d mask=0x%02x", hour, min, sec, schedule_wake_entry.repeat_mask);
    return ESP_OK;
}
void DS2312_Clear_Schedule_Wake(void)
{
    if (!schedule_wake_valid) {
        return;
    }
    schedule_wake_valid = false;
    memset(&schedule_wake_entry, 0, sizeof(schedule_wake_entry));
    DS2312_Update_Alarm(ds2321_dev, NULL);
}
void DS2312_Add_Alarm_Time(i2c_dev_t *i2c_dev, int hour, int min, int sec)
@@ -1623,14 +1693,6 @@
    while (true) {
        vTaskDelay(pdMS_TO_TICKS(1000));
        alarm_store_t store;
        if (load_alarm_store(&store) != ESP_OK || store.count == 0) {
            if (current_alarm1_valid) {
                disable_alarm1(i2c_dev);
            }
            continue;
        }
        struct tm now;
        if (!get_current_time(i2c_dev, &now)) {
            continue;
@@ -1641,28 +1703,24 @@
            ESP_LOGI(TAG, "DS3231 alarm1 triggered");
            ds3231_clear_alarm_flags(i2c_dev, DS3231_ALARM_1);
            current_alarm1_valid = false;
            schedule_power_off_restore_from_alarm();
        }
        int next_index = select_next_alarm_index(&store, &now);
        if (next_index < 0) {
            if (current_alarm1_valid && !Board_Is_Power_Off()) {
                disable_alarm1(i2c_dev);
            if (Board_Schedule_ClaimDue()) {
                if (Board_Is_Power_Off()) {
                    schedule_power_off_restore_from_alarm();
                } else {
                    Board_Schedule_OnAlarmFired();
                }
            }
            continue;
        } else if (Board_Schedule_ClaimDue()) {
            ESP_LOGI(TAG, "schedule wall clock due");
            if (Board_Is_Power_Off()) {
                schedule_power_off_restore_from_alarm();
            } else {
                Board_Schedule_OnAlarmFired();
            }
        }
        alarm_entry_t *next_alarm = &store.entries[next_index];
        if (!current_alarm1_valid) {
            program_alarm1(i2c_dev, next_alarm);
            continue;
        }
        int next_delta = alarm_delta_seconds(next_alarm, &now);
        int current_delta = alarm_delta_seconds(&current_alarm1_entry, &now);
        if (next_delta < current_delta || !alarm_entry_equals(next_alarm, &current_alarm1_entry)) {
            program_alarm1(i2c_dev, next_alarm);
        }
        Board_Schedule_OnLessonFilesUpdated();
        program_soonest_alarm(i2c_dev, &now);
    }
}