From 220e4fab27b7f419b3e89e2f2d28ae789aac09d7 Mon Sep 17 00:00:00 2001
From: wangzhibo <wangzhibo@shsening.com>
Date: 星期四, 08 十月 2026 16:29:55 +0800
Subject: [PATCH] 5种场景模式家长端ok

---
 xiaozhi-esp32-2.2.6/main/boards/sening-xiaozhi-s3/system.c |  144 +++++++++++++++++++++++++++++++++--------------
 1 files changed, 101 insertions(+), 43 deletions(-)

diff --git a/xiaozhi-esp32-2.2.6/main/boards/sening-xiaozhi-s3/system.c b/xiaozhi-esp32-2.2.6/main/boards/sening-xiaozhi-s3/system.c
index d1c2a1f..c892541 100644
--- a/xiaozhi-esp32-2.2.6/main/boards/sening-xiaozhi-s3/system.c
+++ b/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);
     }
 }
 

--
Gitblit v1.9.1