| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566 |
- /*
- * Work Control Module - v2.3 (修复版)
- *
- * 修复:工作结束后必须等待天亮才能再次工作
- * 优化:保护逻辑简化版
- *
- * Version: 2.3.1
- */
- /*********************↓ include ↓************************/
- #define DBG_TAG "WORK"
- #define DBG_LVL DBG_INFO
- #include <rtdbg.h>
- #include <rtthread.h>
- #include <rtdevice.h>
- #include <board.h>
- #include <string.h>
- #include <stdio.h>
- #include "ecode.h"
- #include "ym310_protecl.h"
- /*********************↑ include ↑************************/
- /*********************↓ define ↓************************/
- /* 工作线程基础时间片(毫秒)*/
- #define WORK_BASE_MS 100
- /* ========== 光控阈值定义 ========== */
- // #define LIGHT_VAL_NIGHT_THRESHOLD 50 /* 夜晚阈值:≤5%亮度 */
- // #define LIGHT_VAL_DAY_THRESHOLD 150 /* 白天阈值:≥15%亮度 */
- #define LIGHT_VAL_NIGHT_THRESHOLD 20 /* 夜晚阈值:≤2%亮度 */
- #define LIGHT_VAL_DAY_THRESHOLD 150 /* 白天阈值:≥15%亮度 */
- #define PV_VOLTAGE_NIGHT_THRESHOLD limit.vsunset /* 夜晚阈值:太阳能板电压≤1.5V */
- #define PV_VOLTAGE_DAY_THRESHOLD limit.vsunrise /* 白天阈值:太阳能板电压≥3.3V */
- /* ========== 状态转换延迟参数 ========== */
- #define LIGHT_DEBOUNCE_SEC 10 /* 光控状态防抖10秒 */
- #define WORK_COOLDOWN_SEC 300 /* 工作结束后冷却5分钟 */
- #define PROTECT_RELEASE_DELAY_SEC 5 /* 保护解除后延迟5秒再恢复工作能力 */
- #define LIGHT_BREAK_WORK_SEC 300 /* 持续光控保护 到达后 退出本次工作 */
- /* ========== 工作状态定义 ========== */
- typedef enum
- {
- WORK_STATE_IDLE = 0,
- WORK_STATE_WORKING,
- WORK_STATE_LIGHT_PRT,
- WORK_STATE_COOLDOWN,
- WORK_STATE_WAIT_DAY,
- WORK_STATE_OTHER_PRT
- } Work_status;
- /* 保护激活标志值 */
- #define PROTECT_ACTIVE 0x9D
- /* ========== RTC备份寄存器地址定义 ========== */
- #define RTC_BKP_WORK_A RTC_BKP_DR1 /* DR1: 工作开始时间戳 */
- #define RTC_BKP_WORK_B RTC_BKP_DR2 /* DR2: 工作持续时间秒数 */
- #define RTC_BKP_WORK_C RTC_BKP_DR3 /* DR3: 打包状态寄存器 */
- #define RTC_BKP_WORK_D RTC_BKP_DR4 /* DR4: 打包状态寄存器 */
- #define RTC_BKP_WORK_E RTC_BKP_DR5 /* DR5: 打包状态寄存器 */
- /* 打包状态寄存器格式 */
- #define RTC_WORK_VALID_MAGIC 0xA5U /* 魔数,用于校验数据有效性 */
- /*********************↑ define ↑************************/
- /*********************↓ 外部变量声明 ↓***********************/
- extern SYS_STATUS sys_sta;
- extern DEV_INFO dev_info;
- extern struct rtc_time time_now;
- extern void gpio_lamp_ctrl(rt_bool_t on);
- extern void gpio_hv_ctrl(rt_bool_t on);
- extern char ef_cfged;
- extern RTC_HandleTypeDef hrtc;
- extern char start_ftp;
- /*********************↑ 外部变量声明 ↑***********************/
- /*********************↓ 全局变量(供MQTT上报) ↓***********************/
- extern uint8_t g_work_state;
- extern uint8_t g_work_mode;
- extern uint32_t g_work_elapsed_sec;
- extern uint32_t g_work_total_sec;
- extern uint8_t g_work_progress;
- extern uint32_t g_cooldown_sec;
- extern uint8_t g_work_start_hour;
- extern uint8_t g_work_start_minute;
- extern char KEY_IN_TEST_TIME;
- /*********************↑ 全局变量 ↑***********************/
- /*********************↓ 静态变量 ↓***********************/
- static rt_thread_t s_thread = RT_NULL; /* 工作线程句柄 */
- static rt_bool_t s_running = RT_FALSE; /* 线程运行标志 */
- /* ========== 工作状态核心变量 ========== */
- /**
- * @brief 以下这些放rtc里面
- *
- */
- static uint8_t s_state = WORK_STATE_IDLE; /* 当前工作状态 */
- static uint8_t s_light_protect = 0; /* 光控保护状态 */
- static uint8_t s_start_hour = 0; /* 工作开始小时 */
- static uint8_t s_start_minute = 0; /* 工作开始分钟 */ // 寄存器1
- static uint32_t s_start_time = 0; /* 工作开始时间戳(秒)*/ // 开启时间 // 寄存器2
- static uint32_t s_duration_sec = 0; /* 工作持续时长(秒)*/ // 需要工作时长 // 寄存器3
- static uint32_t s_cooldown_until = 0; /* 冷却结束时间戳(秒)*/ // 寄存器4
- /**
- * 先不放rtc里面 这个可以根据参数还原
- */
- static uint8_t s_auto_mode = 0; /* 自动模式标志 */
- /* ========== 光控保护状态(带防抖)========== */
- /* ========== 保护相关变量(简化版)========== */
- static uint32_t s_protect_release_time = 0; /* 保护解除后可以恢复工作的时间戳 */
- static uint32_t light_prt_start_time = 0; // 光控触发后的时间计算
- /* ========== GPIO状态缓存 ========== */
- /*********************↑ 静态变量 ↑***********************/
- /*********************↓ 函数声明 ↓***********************/
- static uint32_t get_timestamp(void);
- static void sync_mqtt_vars(void);
- static void safe_start(char type);
- static int in_time_range(void);
- static uint32_t get_elapsed_sec(void);
- static void work_start(void);
- static void work_stop(const char *reason, uint8_t start_cooldown);
- static uint8_t is_duration_expired(void);
- static uint8_t other_protect_active(void);
- static const char *other_protect_name(void);
- uint8_t calculate_hours_diff(uint8_t start, uint8_t ent);
- /*********************↑ 函数声明 ↑***********************/
- /*********************↓ RTC备份寄存器存储方案 ↓***********************/
- uint32_t crc32_update(uint32_t data, uint32_t *crc)
- {
- if (crc == NULL)
- return 0;
- if (*crc == 0)
- {
- *crc = 0xFFFFFFFFUL;
- }
- for (int byte_idx = 3; byte_idx >= 0; byte_idx--)
- {
- uint8_t byte = (data >> (byte_idx * 8)) & 0xFF;
- *crc ^= byte;
- for (int bit = 0; bit < 8; bit++)
- {
- if (*crc & 1)
- {
- *crc = (*crc >> 1) ^ 0xEDB88320UL;
- }
- else
- {
- *crc >>= 1;
- }
- }
- }
- return *crc ^ 0xFFFFFFFFUL;
- }
- // /**
- // * 计算两个时间点之间的小时差,支持跨天(24小时制)
- // * @param start 开始时间(小时,0-23)
- // * @param end 结束时间(小时,0-23)
- // * @return 从 start 到 end 经过的小时数(0-23)
- // */
- // uint8_t calculate_hours_diff(uint8_t start, uint8_t end)
- // {
- // // 参数合法性检查(可根据需要选择是否启用)
- // if (start < 0 || start > 23 || end < 0 || end > 23)
- // {
- // return -1; // 返回错误码
- // }
- // if (start <= end)
- // {
- // // 同一天内:直接相减
- // return end - start;
- // }
- // else
- // {
- // // 跨天:(到当天结束的小时数) + (第二天开始到 end 的小时数)
- // return (24 - start) + end;
- // }
- // }
- /**
- * 计算两个时间点之间的小时差,支持跨天(24小时制)
- * @param start 开始时间(小时,0-23)
- * @param end 结束时间(小时,0-23)
- * @return 从 start 到 end 经过的小时数(0-24)
- */
- uint8_t calculate_hours_diff(uint8_t start, uint8_t end)
- {
- if (start == 0 && end == 23)
- {
- return 24;
- }
- if (start <= end)
- {
- return end - start;
- }
- else
- {
- return (24 - start) + end;
- }
- }
- /**
- * @brief 将工作状态打包到单个32位寄存器
- */
- static uint32_t pack_work_state(void)
- {
- return ((uint32_t)s_state << 24) |
- ((uint32_t)s_light_protect << 16) |
- ((uint32_t)s_start_hour << 8) |
- ((uint32_t)s_start_minute);
- }
- /**
- * @brief 从32位寄存器解包工作状态
- */
- static int unpack_work_state(uint32_t packed)
- {
- s_state = (packed >> 24) & 0xFF;
- s_light_protect = (packed >> 16) & 0xFF;
- s_start_hour = (packed >> 8) & 0xFF;
- s_start_minute = packed & 0xFF;
- return 1;
- }
- /**
- * @brief 保存工作状态到RTC备份寄存器
- */
- static void save_work_state(void)
- {
- uint32_t crc = 0, final_crc = 0, packeg = 0;
- static uint32_t e = 0;
- packeg = pack_work_state();
- final_crc = crc32_update(packeg, &crc);
- final_crc = crc32_update(s_start_time, &crc);
- final_crc = crc32_update(s_duration_sec, &crc);
- final_crc = crc32_update(s_cooldown_until, &crc);
- e = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_WORK_E);
- if (e != final_crc)
- {
- HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_WORK_A, pack_work_state());
- HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_WORK_B, s_start_time);
- HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_WORK_C, s_duration_sec);
- HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_WORK_D, s_cooldown_until);
- HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_WORK_E, final_crc);
- LOG_I("工作状态已更新到RTC: time=%u, dur=%lu, CRC = 0x%08X",
- s_start_time, s_duration_sec, final_crc);
- e = final_crc;
- }
- }
- /**
- * @brief 清除RTC备份寄存器中的工作状态
- */
- static void clear_work_state(void)
- {
- HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_WORK_A, 0);
- HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_WORK_B, 0);
- HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_WORK_C, 0);
- HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_WORK_D, 0);
- HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_WORK_E, 0);
- LOG_D("工作状态已清除");
- }
- /**
- * @brief 从RTC备份寄存器恢复工作状态
- */
- static int restore_work_state(void)
- {
- uint32_t crc = 0, final_crc = 0, a = 0, b = 0, c = 0, d = 0, e = 0;
- a = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_WORK_A);
- b = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_WORK_B);
- c = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_WORK_C);
- d = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_WORK_D);
- e = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_WORK_E);
- final_crc = crc32_update(a, &crc);
- final_crc = crc32_update(b, &crc);
- final_crc = crc32_update(c, &crc);
- final_crc = crc32_update(d, &crc);
- LOG_I("读取RTC: time=%u, dur=%lu, CRC = 0x%08X",
- b, c, e);
- if (final_crc != e)
- {
- LOG_I("无有效工作状态数据(CRC FAIL) %d", (final_crc != e));
- return 0;
- }
- if (!unpack_work_state(a))
- {
- LOG_W("工作状态数据校验失败");
- return 0;
- }
- if (s_auto_mode > 1)
- {
- LOG_W("自动模式标志无效");
- return 0;
- }
- s_start_time = b;
- s_duration_sec = c;
- s_cooldown_until = d;
- LOG_I("成功恢复工作状态: 开始时间=%u, 持续=%lu秒, 自动模式=%d",
- s_start_time, s_duration_sec, s_auto_mode);
- return 1;
- }
- /*********************↑ RTC备份寄存器存储方案 ↑***********************/
- /*********************↓ 辅助函数 ↓***********************/
- /**
- * @brief 获取当前Unix时间戳
- */
- static uint32_t get_timestamp(void)
- {
- uint32_t ts = 0;
- for (uint16_t y = 2000; y < time_now.year; y++)
- {
- ts += ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0)) ? 366 : 365;
- }
- ts *= 86400;
- static const uint16_t md[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
- ts += (md[time_now.month - 1] + time_now.date - 1) * 86400;
- if ((time_now.year % 4 == 0 && time_now.year % 100 != 0) && time_now.month > 2)
- {
- ts += 86400;
- }
- ts += time_now.hour * 3600 + time_now.minute * 60 + time_now.second;
- return ts;
- }
- /**
- * @brief 同步MQTT上报变量
- */
- static void sync_mqtt_vars(void)
- {
- g_work_state = s_state;
- g_work_mode = (s_state == WORK_STATE_WORKING) ? 1 : 0;
- if (s_state == WORK_STATE_WORKING && s_start_time > 0)
- {
- uint32_t now = get_timestamp();
- g_work_elapsed_sec = (now > s_start_time) ? now - s_start_time : 0;
- }
- else
- {
- g_work_elapsed_sec = 0;
- }
- g_work_total_sec = s_duration_sec;
- if (s_duration_sec > 0 && !s_auto_mode && g_work_elapsed_sec <= s_duration_sec)
- {
- g_work_progress = (g_work_elapsed_sec * 100) / s_duration_sec;
- }
- else
- {
- g_work_progress = 0;
- }
- g_work_start_hour = s_start_hour;
- g_work_start_minute = s_start_minute;
- if (sys_sta.light_protect)
- {
- sys_sta.light_protect = 0x9D;
- }
- else
- {
- sys_sta.light_protect = 0;
- }
- save_work_state();
- }
- extern rt_bool_t gpio_hv_get_status(void);
- extern rt_bool_t gpio_lamp_get_status(void);
- /**
- * @brief 安全控制灯管
- */
- static char safe_lamp(rt_bool_t on)
- {
- if (gpio_lamp_get_status() != on)
- {
- gpio_lamp_ctrl(on);
- return 1;
- }
- return 0;
- }
- /**
- * @brief 安全控制高压
- */
- static char safe_hv(rt_bool_t on)
- {
- if (gpio_hv_get_status() != on)
- {
- gpio_hv_ctrl(on);
- return 1;
- }
- return 0;
- }
- /**
- * @brief 安全停止所有输出
- */
- static void safe_stop(char type)
- {
- if (KEY_IN_TEST_TIME == VALID)
- {
- LOG_D("safe_stop %c skipped (test mode)", type);
- return;
- }
- char res = safe_lamp(RT_FALSE) + safe_hv(RT_FALSE);
- if (res)
- {
- LOG_I(" safe_stop %c \n\n", type);
- }
- }
- /**
- * @brief 安全启动所有输出
- */
- static void safe_start(char type)
- {
- char res = safe_lamp(RT_TRUE) + safe_hv(RT_TRUE);
- if (res)
- {
- safe_lamp(1);
- safe_hv(1);
- LOG_I(" safe_start %c \n\n", type);
- }
- }
- /**
- * @brief 判断当前时间是否在时控时段内
- */
- static int in_time_range(void)
- {
- uint8_t s = dev_info.time_start;
- uint8_t e = dev_info.time_end;
- uint8_t h = time_now.hour;
- // 全天工作
- if ((s == 0 && e == 23) || (s == e))
- {
- return 1;
- }
- if (s <= e)
- {
- return (h >= s && h < e);
- }
- else
- {
- return (h >= s || h < e);
- }
- }
- /**
- * @brief 检查是否有其他保护激活
- */
- static uint8_t other_protect_active(void)
- {
- #define PROTECT_LOW_TEMP 0x7A
- #define PROTECT_HIGH_TEMP 0x9D
- uint8_t res = (sys_sta.undervolt_protect == PROTECT_ACTIVE ||
- sys_sta.temp_protect == PROTECT_HIGH_TEMP ||
- sys_sta.temp_protect == PROTECT_LOW_TEMP ||
- sys_sta.tilt_protect == PROTECT_ACTIVE ||
- sys_sta.rain_protect == PROTECT_ACTIVE);
- if (res && KEY_IN_TEST_TIME != VALID)
- {
- char power_off = safe_lamp(RT_FALSE) + safe_hv(RT_FALSE);
- if (power_off)
- {
- char buf[50] = {0};
- sprintf(buf, "停止工作:%s", other_protect_name());
- Recode_e_code(e_protect_stopwork, res + power_off, buf);
- }
- }
- return res;
- }
- /**
- * @brief 获取当前激活的保护名称
- */
- static const char *other_protect_name(void)
- {
- if (sys_sta.undervolt_protect == PROTECT_ACTIVE)
- return "欠压保护";
- if (sys_sta.temp_protect == PROTECT_HIGH_TEMP)
- return "高温保护";
- if (sys_sta.temp_protect == PROTECT_LOW_TEMP)
- return "低温保护";
- if (sys_sta.tilt_protect == PROTECT_ACTIVE)
- return "倾倒保护";
- if (sys_sta.rain_protect == PROTECT_ACTIVE)
- return "雨控保护";
- return "";
- }
- /*********************↑ 辅助函数 ↑***********************/
- /*********************↓ 光控保护(带防抖) ↓***********************/
- /**
- * @brief 获取当前光控条件
- */
- static uint8_t get_light_condition(void)
- {
- if (dev_info.light_flag == 0)
- {
- if (sys_sta.charge_voltage >= PV_VOLTAGE_DAY_THRESHOLD)
- {
- return 1;
- }
- else if (sys_sta.charge_voltage <= PV_VOLTAGE_NIGHT_THRESHOLD)
- {
- return 0;
- }
- else
- {
- return 2;
- }
- }
- else
- {
- if (sys_sta.light_percent >= LIGHT_VAL_DAY_THRESHOLD)
- {
- return 1;
- }
- else if (sys_sta.light_percent <= LIGHT_VAL_NIGHT_THRESHOLD)
- {
- return 0;
- }
- else
- {
- return 2;
- }
- }
- }
- /**
- * @brief 更新光控保护状态(带防抖机制) <带防抖的确认当前是否光控以及是否解除>
- */
- static char check_light_protect(void)
- {
- uint8_t is_protect = get_light_condition();
- uint32_t now = get_timestamp();
- static uint32_t start_change_time = 0;
- static char ready_change = 0x9D;
- static uint32_t count_bak = 0;
- static work_state_DEF old_work_state = work_state_IDLE;
- static uint8_t next_status;
- if (next_status != 0)
- {
- next_status = 0;
- }
- if (is_protect == 2) // 光控水平介于
- {
- if (ready_change != 0x9D) // 本次切换取消
- {
- rt_kprintf("本次光控切换放弃(光控中间态) 当前:%d\n", s_light_protect);
- start_change_time = 0;
- ready_change = 0x9D;
- count_bak = 0;
- }
- return s_light_protect;
- }
- if (s_light_protect != is_protect && ready_change == 0x9D) // 本次切换开始
- {
- rt_kprintf("开启光控切换 :%d -> %d [%d]\n", s_light_protect, is_protect, sys_sta.light_percent);
- start_change_time = now;
- ready_change = 1;
- count_bak = 0;
- next_status = is_protect;
- }
- else if (s_light_protect != is_protect) // 本次切换结果确认
- {
- count_bak++;
- if ((now - start_change_time) > LIGHT_DEBOUNCE_SEC) // 检查是否光控触发或解除
- {
- s_light_protect = is_protect;
- rt_kprintf("(time)本次光控切换完成 当前:%d\n", s_light_protect);
- start_change_time = 0;
- ready_change = 0x9D;
- count_bak = 0;
- }
- else if (count_bak > ((1000 / WORK_BASE_MS * LIGHT_DEBOUNCE_SEC) + 5)) // 备用方案 给时间戳逻辑补漏
- {
- s_light_protect = is_protect;
- rt_kprintf("(count)本次光控切换完成 当前:%d\n", s_light_protect);
- start_change_time = 0;
- ready_change = 0x9D;
- count_bak = 0;
- }
- if (ready_change == 0x9D)
- {
- if (s_light_protect && (dev_info.light_flag == 0) && (sys_sta.work_state != work_state_CHG)) // 太阳能板光控 进入充电状态
- {
- old_work_state = sys_sta.work_state;
- sys_sta.work_state = work_state_CHG;
- }
- if ((s_light_protect == 0) && (sys_sta.work_state == work_state_CHG)) // 光控解除了 一起解除充电状态
- {
- if (old_work_state < work_state_CHG)
- {
- sys_sta.work_state = old_work_state;
- }
- else
- {
- sys_sta.work_state = work_state_IDLE;
- }
- }
- }
- }
- else if (ready_change != 0x9D) // 本次切换取消
- {
- rt_kprintf("本次光控切换放弃 当前:%d\n", s_light_protect);
- start_change_time = 0;
- ready_change = 0x9D;
- count_bak = 0;
- }
- if (s_light_protect && (dev_info.light_flag == 0) && (sys_sta.work_state != work_state_CHG))
- {
- old_work_state = sys_sta.work_state;
- sys_sta.work_state = work_state_CHG;
- }
- return s_light_protect;
- }
- /*********************↑ 光控保护 ↑***********************/
- /*********************↓ 工作时长管理 ↓***********************/
- /**
- * @brief 检查工作时间是否已到
- */
- static uint8_t is_duration_expired(void)
- {
- if (s_auto_mode)
- return 0;
- if (s_start_time == 0)
- return 0;
- uint32_t elapsed = get_timestamp() - s_start_time;
- return elapsed >= s_duration_sec;
- }
- /**
- * @brief 获取已工作时长(秒)
- */
- static uint32_t get_elapsed_sec(void)
- {
- if (s_start_time == 0)
- return 0;
- uint32_t elapsed = get_timestamp() - s_start_time;
- return (elapsed < s_duration_sec) ? elapsed : s_duration_sec;
- }
- /*********************↑ 工作时长管理 ↑***********************/
- /*********************↓ 工作控制 ↓***********************/
- /**
- * @brief 开始工作
- */
- static void work_start(void)
- {
- char log_buf[52];
- if (s_state == WORK_STATE_WORKING)
- {
- return;
- }
- s_start_time = get_timestamp();
- if (dev_info.time_ctrl_enable == 0) // 光控模式
- {
- s_duration_sec = dev_info.light_work_duration * 3600; /* 分钟转秒 */
- s_auto_mode = (dev_info.light_work_duration == 0);
- }
- else if (in_time_range()) // 时控模式 && 在时段内(中途进入)
- {
- uint8_t start = dev_info.time_start;
- uint8_t end = dev_info.time_end;
- uint8_t cur_hour = time_now.hour;
- uint8_t cur_min = time_now.minute;
- uint8_t cur_sec = time_now.second;
- uint32_t elapsed_sec = 0;
- /* 计算从时段开始到当前已过的时间 */
- if (start < end)
- {
- /* 同天:17-20,当前18点 -> 已过1小时 */
- elapsed_sec = (cur_hour - start) * 3600 + cur_min * 60 + cur_sec;
- }
- else
- {
- /* 跨天:22-6,当前1点 -> 已过 (24-22) + 1 = 3小时 */
- if (cur_hour >= start)
- {
- /* 第一天:22-23点 */
- elapsed_sec = (cur_hour - start) * 3600 + cur_min * 60 + cur_sec;
- }
- else
- {
- /* 第二天:0-5点 */
- elapsed_sec = (24 - start + cur_hour) * 3600 + cur_min * 60 + cur_sec;
- }
- }
- uint32_t full_sec = calculate_hours_diff(start, end) * 3600;
- s_duration_sec = (elapsed_sec < full_sec) ? (full_sec - elapsed_sec) : 0;
- s_auto_mode = 0;
- LOG_I("时控中途进入: 完整=%lu秒, 已过=%lu秒, 剩余=%lu秒", full_sec, elapsed_sec, s_duration_sec);
- }
- else // 时控模式 && 不在时段内(正常进入,等进入时段)
- {
- s_duration_sec = calculate_hours_diff(dev_info.time_start, dev_info.time_end) * 3600;
- s_auto_mode = 0;
- }
- s_start_hour = time_now.hour;
- s_start_minute = time_now.minute;
- safe_start('A');
- sys_sta.work_state = work_state_WORK;
- sys_sta.hv_count++;
- if (dev_info.time_ctrl_enable == 0)
- {
- if (s_auto_mode)
- {
- rt_snprintf(log_buf, sizeof(log_buf), "工作开始:自动模式(天亮结束)");
- LOG_I("%s", log_buf);
- Recode_e_code(e_work_start, 1, log_buf);
- }
- else
- {
- rt_snprintf(log_buf, sizeof(log_buf), "工作开始:光控模式 %d小时", dev_info.light_work_duration);
- LOG_I("%s", log_buf);
- Recode_e_code(e_work_start, 2, log_buf);
- }
- }
- else
- {
- uint8_t start = dev_info.time_start;
- uint8_t end = dev_info.time_end;
- uint8_t hour_diff = calculate_hours_diff(start, end);
- rt_snprintf(log_buf, sizeof(log_buf), "工作开始:时控模式 %d小时(%02d-%02d)", hour_diff, start, end);
- LOG_I("%s", log_buf);
- Recode_e_code(e_work_start, 3, log_buf);
- }
- }
- /**
- * @brief 停止工作
- */
- static void work_stop(const char *reason, uint8_t start_cooldown)
- {
- char log_buf[52];
- clear_work_state();
- safe_stop('A');
- s_state = WORK_STATE_IDLE;
- s_start_time = 0;
- s_start_hour = 0;
- s_start_minute = 0;
- sys_sta.work_state = work_state_IDLE;
- rt_snprintf(log_buf, sizeof(log_buf), "工作停止:%s", reason);
- LOG_I("%s", log_buf);
- Recode_e_code(e_work_stop, 0, log_buf);
- if (start_cooldown)
- {
- s_state = WORK_STATE_COOLDOWN;
- s_cooldown_until = get_timestamp() + WORK_COOLDOWN_SEC;
- LOG_I("冷却开始: %d秒内不能工作", WORK_COOLDOWN_SEC);
- }
- }
- /**
- * @brief 检查是否还在工作时间
- *
- * @return char 0-不在 1-在
- */
- static char check_time_vaild(void)
- {
- char res = 0;
- if (dev_info.time_ctrl_enable) // 时控模式
- {
- res = in_time_range();
- if (res)
- {
- return 1;
- }
- }
- else if (!is_duration_expired())
- {
- return 1;
- }
- return 0;
- }
- /*********************↑ 工作控制 ↑***********************/
- /*********************↓ 主线程 ↓***********************/
- /**
- * @brief 判断NTP时间是否已同步成功
- * @return 1=已同步, 0=未同步
- *
- * 判断逻辑:当前系统时间若为2026年5月及以前,认为未同步
- * 因为设备实际运行时间在2026年6月之后
- */
- static uint8_t is_ntp_synced(void)
- {
- /* 计算当前时间的 (年*12 + 月) 值 */
- uint32_t current_value = (uint32_t)(time_now.year - 2000) * 12 + time_now.month;
- /* 2026年5月的参考值:26*12 + 5 = 317 */
- uint32_t threshold = 26 * 12 + 5;
- // rt_kprintf("current_value %d threshold %d res = %d" , current_value ,threshold, (current_value > threshold));
- /* 如果当前时间 <= 2026年5月,认为NTP未同步 */
- if (current_value <= threshold)
- {
- return 0; /* 未同步 */
- }
- return 1; /* 已同步 */
- }
- /**
- * @brief 工作控制主线程
- */
- static void work_thread_entry(void *param)
- {
- uint16_t ftp_wait_cnt = 0;
- uint32_t last_sync_time = 0;
- uint32_t last_log_time = 0;
- char log_process = 0;
- uint8_t s_state_last = WORK_STATE_IDLE; // 备用状态
- int8_t last_sta = WORK_STATE_IDLE; // 打印日志用
- /* 等待配置加载完成 */
- int wait_cnt = 0;
- while (ef_cfged != 1 && wait_cnt < 100)
- {
- rt_thread_mdelay(100);
- wait_cnt++;
- }
- rt_thread_mdelay(3000);
- /* ===== 新增:等待时间同步完成(最多2分钟)===== */
- {
- uint32_t time_wait_cnt = 0;
- const uint32_t TIME_WAIT_MAX = 120; /* 最多等待120秒 */
- const uint8_t TIME_CHECK_INTERVAL = 1; /* 每秒检查一次 */
- /* 检查RTC时间是否有效(非默认值2026-01-01) */
- while (time_wait_cnt < TIME_WAIT_MAX)
- {
- /* 检查RTC是否已从默认值更新 */
- if (is_ntp_synced())
- {
- LOG_I("时间同步已完成: %04d-%02d-%02d %02d:%02d:%02d",
- time_now.year, time_now.month, time_now.date,
- time_now.hour, time_now.minute, time_now.second);
- break;
- }
- time_wait_cnt++;
- if (time_wait_cnt % 10 == 0)
- {
- LOG_I("等待时间同步中... (%d/%d秒)", time_wait_cnt, TIME_WAIT_MAX);
- }
- rt_thread_mdelay(TIME_CHECK_INTERVAL * 1000);
- }
- if (time_wait_cnt >= TIME_WAIT_MAX)
- {
- Recode_e_code(e_work_without_ntp, 0, "工作开启时未同步时间");
- LOG_W("时间同步等待超时(2分钟),使用默认时间继续工作");
- }
- }
- /* ============================================= */
- /* 从RTC恢复之前的工作状态 */
- if (restore_work_state())
- {
- uint32_t now = get_timestamp();
- uint32_t elapsed = (now > s_start_time) ? (now - s_start_time) : 0;
- if (elapsed < s_duration_sec)
- {
- safe_start('B');
- sys_sta.work_state = work_state_WORK;
- uint32_t remain = s_duration_sec - elapsed;
- LOG_I("工作恢复: (已工作%lu时%lu分, 剩余%lu时%lu分)", elapsed / 3600, elapsed % 3600 / 60, remain / 3600, remain % 3600 / 60);
- Recode_e_code(e_work_resume, 0, "工作恢复:重启后恢复(RTC)");
- while (other_protect_active())
- {
- LOG_I("等待工作恢复: %s", other_protect_name());
- rt_thread_mdelay(10000);
- sync_mqtt_vars();
- }
- }
- else
- {
- clear_work_state();
- s_state = WORK_STATE_IDLE;
- s_start_time = 0;
- LOG_I("保存的工作已过期,不恢复");
- }
- }
- /* 主循环 */
- while (1)
- {
- uint32_t now = get_timestamp();
- uint8_t protect_active = other_protect_active(); // 刷新其他保护
- check_light_protect(); // 刷新光控保护
- sync_mqtt_vars();
- /* 3.1 关机检查 */
- if (dev_info.power_state == 0)
- {
- if (s_state == WORK_STATE_WORKING)
- {
- work_stop("设备关机", 0);
- s_state = WORK_STATE_IDLE;
- safe_stop('G');
- }
- rt_thread_mdelay(WORK_BASE_MS);
- continue;
- }
- /* 3.3 保护处理(简化版)*/
- if (protect_active && (s_state != WORK_STATE_OTHER_PRT))
- {
- LOG_I("保护触发: %s", other_protect_name());
- s_state_last = s_state;
- // if (s_state == WORK_STATE_WORKING)
- // {
- // s_state_last = WORK_STATE_WORKING;
- // }
- // else
- // {
- // s_state_last = WORK_STATE_IDLE;
- // }
- s_state = WORK_STATE_OTHER_PRT;
- }
- if (last_sta != s_state)
- {
- LOG_I("Detect sta chang %d -> %d", last_sta, s_state);
- last_sta = s_state;
- }
- if (light_prt_start_time != 0 && s_state != WORK_STATE_LIGHT_PRT) // 异常状态切换保护 WORK_STATE_LIGHT_PRT 专用
- {
- light_prt_start_time = 0;
- rt_kprintf("light_prt_start_time CLEAR\n");
- }
- if (s_protect_release_time != 0 && s_state != WORK_STATE_OTHER_PRT) // 异常状态切换保护 WORK_STATE_OTHER_PRT 专用
- {
- s_protect_release_time = 0;
- // rt_kprintf("s_protect_release_time CLEAR\n");
- }
- if ((start_ftp == VALID) && (ftp_wait_cnt * WORK_BASE_MS < (600000))) // 检查是否在升级
- {
- ftp_wait_cnt++;
- if (ftp_wait_cnt > 0 && (ftp_wait_cnt % (10000 / WORK_BASE_MS) == 0))
- {
- rt_kprintf("work_thread_entry continue %d/%d\n", ftp_wait_cnt * WORK_BASE_MS / 1000, 600);
- }
- rt_thread_mdelay(WORK_BASE_MS);
- safe_stop('H');
- continue;
- }
- else if (ftp_wait_cnt != 0)
- {
- ftp_wait_cnt = 0;
- }
- /* ========== 3.5 状态机处理 ========== */
- switch (s_state)
- {
- case WORK_STATE_IDLE: /* 空闲状态 */
- {
- uint8_t can_work = 0;
- if (dev_info.time_ctrl_enable) // 时控模式
- {
- can_work = in_time_range();
- if (can_work)
- {
- LOG_I("时控条件满足,开始工作");
- }
- }
- else if (!s_light_protect && !get_light_condition())
- {
- can_work = 1;
- LOG_I("光控条件满足(夜晚),开始工作");
- }
- if (can_work)
- {
- work_start();
- s_state = WORK_STATE_WORKING;
- continue;
- }
- safe_stop('B');
- break;
- }
- case WORK_STATE_WORKING: /* 工作中状态 */
- {
- uint8_t should_stop = 0;
- const char *stop_reason = "";
- if (is_duration_expired())
- {
- should_stop = 1;
- stop_reason = "时长到";
- }
- else if ((s_auto_mode && s_light_protect) && (dev_info.time_ctrl_enable == 0))
- {
- should_stop = 1;
- stop_reason = "天亮";
- }
- if (should_stop)
- {
- work_stop(stop_reason, 1);
- s_state = WORK_STATE_COOLDOWN;
- continue;
- }
- else if (s_light_protect && (dev_info.time_ctrl_enable == 0)) // 检查光控
- {
- s_state = WORK_STATE_LIGHT_PRT;
- continue;
- }
- else
- {
- if (now - last_sync_time >= 1)
- {
- last_sync_time = now;
- }
- if (!s_auto_mode && s_duration_sec > 0)
- {
- uint32_t elapsed = get_elapsed_sec();
- uint32_t progress = (elapsed * 100) / s_duration_sec;
- uint32_t remain = s_duration_sec - elapsed;
- if (log_process != progress)
- {
- log_process = progress;
- LOG_I("工作进度: %u%% (已工作%lu时%lu分, 剩余%lu时%lu分)", progress, elapsed / 3600, elapsed % 3600 / 60, remain / 3600, remain % 3600 / 60);
- }
- }
- }
- safe_start('C');
- break;
- }
- case WORK_STATE_LIGHT_PRT: // 光控保护
- {
- if ((dev_info.time_ctrl_enable == 1))
- {
- s_state = WORK_STATE_IDLE;
- LOG_W("时控模式 禁用光控保护\n");
- continue;
- }
- if (light_prt_start_time == 0)
- {
- light_prt_start_time = get_timestamp();
- }
- if (s_light_protect) // 光控着吗?
- {
- // rt_kprintf("WORK_STATE_LIGHT_PRT A\n");
- if (is_duration_expired()) // 工作时间到没?
- {
- work_stop("光控至工作时间结束", 1);
- light_prt_start_time = 0;
- s_state = WORK_STATE_COOLDOWN;
- continue;
- }
- else if ((now - light_prt_start_time) >= LIGHT_BREAK_WORK_SEC) // 光控超时没
- {
- work_stop("长时间光控退出", 1);
- light_prt_start_time = 0;
- s_state = WORK_STATE_COOLDOWN;
- }
- }
- else // 保护解除
- {
- s_state = WORK_STATE_WORKING;
- light_prt_start_time = 0;
- continue;
- }
- safe_stop('C');
- break;
- }
- case WORK_STATE_COOLDOWN: /* 冷却状态 */
- {
- if ((dev_info.time_ctrl_enable == 1))
- {
- s_state = WORK_STATE_IDLE;
- LOG_W("时控模式 禁用光控状态\n");
- continue;
- }
- if (s_cooldown_until > 0 && now >= s_cooldown_until)
- {
- s_cooldown_until = 0;
- if (dev_info.time_ctrl_enable == 0)
- {
- s_state = WORK_STATE_WAIT_DAY;
- LOG_I("冷却结束,等待天亮后才能再次工作");
- }
- else
- {
- s_state = WORK_STATE_IDLE;
- LOG_I("冷却结束,随时可以工作(时控)");
- }
- continue;
- }
- else if (s_cooldown_until == 0)
- {
- s_cooldown_until = get_timestamp() + WORK_COOLDOWN_SEC;
- LOG_I("异常进入冷却开始");
- }
- safe_stop('D');
- break;
- }
- case WORK_STATE_WAIT_DAY: /* 等待天亮状态 */
- {
- if ((dev_info.time_ctrl_enable == 1))
- {
- s_state = WORK_STATE_IDLE;
- LOG_W("时控模式 禁用光控状态\n");
- continue;
- }
- if (now - last_log_time >= 60)
- {
- last_log_time = now;
- LOG_D("等待天亮中... 光控保护=%s", s_light_protect ? "白天" : "夜晚");
- }
- if (s_light_protect) // 天亮了
- {
- s_state = WORK_STATE_IDLE;
- continue;
- }
- safe_stop('E');
- break;
- }
- case WORK_STATE_OTHER_PRT:
- {
- if (!protect_active && s_protect_release_time == 0) // 保护解除了
- {
- s_protect_release_time = now + PROTECT_RELEASE_DELAY_SEC;
- LOG_I("保护已解除,延迟%d秒后恢复", PROTECT_RELEASE_DELAY_SEC);
- }
- else if (!protect_active)
- {
- if (now >= s_protect_release_time)
- {
- s_state = s_state_last;
- LOG_I("退出保护:恢复工作状态=%d\n", s_state_last);
- continue;
- }
- }
- // else if (!check_time_vaild())
- // {
- // s_state = WORK_STATE_IDLE;
- // LOG_I("失效保护:(已不在工作时间)恢复至空闲状态\n");
- // continue;
- // }
- safe_stop('F');
- break;
- }
- default:
- {
- LOG_W("未知状态: %d, 重置为空闲", s_state);
- s_state = WORK_STATE_IDLE;
- break;
- }
- }
- rt_thread_mdelay(WORK_BASE_MS);
- }
- }
- /*********************↑ 主线程 ↑***********************/
- /*********************↓ 初始化 ↓***********************/
- /**
- * @brief 启动工作控制模块
- */
- static void work_startup(void)
- {
- if (s_thread)
- return;
- s_running = RT_TRUE;
- s_thread = rt_thread_create("work", work_thread_entry, NULL, 2048, 13, 10);
- if (s_thread)
- {
- rt_thread_startup(s_thread);
- // LOG_I("工作控制模块已启动");
- }
- else
- {
- LOG_E("创建工作线程失败");
- }
- }
- /**
- * @brief 工作模块自动初始化
- */
- static int work_init(void)
- {
- work_startup();
- return 0;
- }
- INIT_APP_EXPORT(work_init);
- /*********************↑ 初始化 ↑***********************/
- /*********************↓ MSH命令 ↓***********************/
- /**
- * @brief MSH命令:查看工作状态
- */
- static void cmd_work_status(int argc, char **argv)
- {
- uint32_t now = get_timestamp();
- uint32_t elapsed = 0;
- uint32_t remain = 0;
- uint32_t progress = 0;
- uint32_t cooldown_remain = 0;
- if (s_state == WORK_STATE_WORKING && s_start_time > 0)
- {
- elapsed = (now > s_start_time) ? now - s_start_time : 0;
- if (elapsed > s_duration_sec)
- elapsed = s_duration_sec;
- if (s_duration_sec > 0 && !s_auto_mode)
- {
- progress = (elapsed * 100) / s_duration_sec;
- remain = s_duration_sec - elapsed;
- }
- }
- if (s_state == WORK_STATE_COOLDOWN && s_cooldown_until > now)
- {
- cooldown_remain = s_cooldown_until - now;
- }
- rt_kprintf("\n");
- rt_kprintf("╔══════════════════════════════════════════════════════════════╗\n");
- rt_kprintf("║ WORK STATUS REPORT ║\n");
- rt_kprintf("╠══════════════════════════════════════════════════════════════╣\n");
- rt_kprintf("║ 开关机状态 : %-46s ║\n", dev_info.power_state ? "开机" : "关机");
- char buf[16] = {0};
- switch (s_state)
- {
- case WORK_STATE_IDLE:
- sprintf(buf, "空闲");
- break;
- case WORK_STATE_WORKING:
- sprintf(buf, "工作中");
- break;
- case WORK_STATE_LIGHT_PRT:
- sprintf(buf, "光控中");
- break;
- case WORK_STATE_COOLDOWN:
- sprintf(buf, "冷却中");
- break;
- case WORK_STATE_WAIT_DAY:
- sprintf(buf, "等天亮");
- break;
- case WORK_STATE_OTHER_PRT:
- sprintf(buf, "保护中");
- break;
- default:
- sprintf(buf, "未知?");
- break;
- }
- rt_kprintf("║ 工作状态 : %s ║\n", buf);
- if (s_state == WORK_STATE_WORKING)
- {
- if (dev_info.time_ctrl_enable == 0)
- rt_kprintf("║ 光控模式 : %-46s ║\n", s_auto_mode ? "自动模式" : "光控模式");
- rt_kprintf("║ 开始时间 : %02d:%02d%-44s ║\n", s_start_hour, s_start_minute, "");
- if (elapsed >= 60)
- {
- uint32_t min = elapsed / 60;
- uint32_t sec = elapsed % 60;
- rt_kprintf("║ 已工作时长 : %u分%u秒%-42s ║\n", min, sec, "");
- }
- else
- {
- rt_kprintf("║ 已工作时长 : %u秒%-45s ║\n", elapsed, "");
- }
- if (!s_auto_mode)
- {
- if (remain >= 60)
- {
- uint32_t min = remain / 60;
- uint32_t sec = remain % 60;
- rt_kprintf("║ 剩余时长 : %u分%u秒%-42s ║\n", min, sec, "");
- }
- else
- {
- rt_kprintf("║ 剩余时长 : %u秒%-45s ║\n", remain, "");
- }
- rt_kprintf("║ 进度 : %3d%% %-46s ║\n", progress, "");
- rt_kprintf("║ [");
- uint8_t bar_len = progress / 2;
- for (uint8_t i = 0; i < 50; i++)
- {
- if (i < bar_len)
- rt_kprintf("=");
- else if (i == bar_len)
- rt_kprintf(">");
- else
- rt_kprintf(" ");
- }
- rt_kprintf("] %3d%%%27s ║\n", progress, "");
- }
- else
- {
- rt_kprintf("║ 工作模式 : 自动(天亮结束)%-35s ║\n", "");
- }
- if (dev_info.light_work_duration > 0)
- {
- rt_kprintf("║ 配置工作时长 : %d小时 ║\n", dev_info.light_work_duration);
- }
- else
- {
- rt_kprintf("║ 配置工作时长 : 自动模式%-43s ║\n", "");
- }
- }
- if (s_state == WORK_STATE_COOLDOWN && cooldown_remain > 0)
- {
- if (cooldown_remain >= 60)
- {
- uint32_t min = cooldown_remain / 60;
- uint32_t sec = cooldown_remain % 60;
- rt_kprintf("║ 冷却剩余时间 : %u分%u秒%-42s ║\n", min, sec, "");
- }
- else
- {
- rt_kprintf("║ 冷却剩余时间 : %u秒%-45s ║\n", cooldown_remain, "");
- }
- }
- if (s_state == WORK_STATE_WAIT_DAY)
- {
- rt_kprintf("║ 状态说明 : 等待天亮后才能再次工作%-26s ║\n", "");
- }
- if (s_state == WORK_STATE_LIGHT_PRT && s_protect_release_time > 0)
- {
- uint32_t remain = (s_protect_release_time > now) ? s_protect_release_time - now : 0;
- rt_kprintf("║ 保护延迟剩余 : %lu秒%-44s ║\n", remain, "");
- }
- rt_kprintf("╠══════════════════════════════════════════════════════════════╣\n");
- rt_kprintf("║ 控制模式 : %-46s ║\n", dev_info.time_ctrl_enable ? "时控模式" : "光控模式");
- if (dev_info.time_ctrl_enable == 0)
- {
- rt_kprintf("║ 光控来源 : %-46s ║\n", dev_info.light_flag == 0 ? "太阳能板" : "光敏二极管");
- rt_kprintf("║ 当前亮度 : %d.%d%%%-44s ║\n",
- sys_sta.light_percent / 10, sys_sta.light_percent % 10, "");
- rt_kprintf("║ 充电电压 : %dmV%-45s ║\n", sys_sta.charge_voltage, "");
- rt_kprintf("║ 光控保护 : %-46s ║\n", s_light_protect ? "激活(白天)" : "未激活(夜晚)");
- }
- else
- {
- char range[32];
- rt_snprintf(range, sizeof(range), "%02d:00 - %02d:00", dev_info.time_start, dev_info.time_end);
- rt_kprintf("║ 时控时段 : %-46s ║\n", range);
- rt_kprintf("║ 当前小时 : %d点%-46s ║\n", time_now.hour, "");
- rt_kprintf("║ 是否在时段内 : %-46s ║\n", in_time_range() ? "是" : "否");
- }
- rt_kprintf("╠══════════════════════════════════════════════════════════════╣\n");
- rt_kprintf("║ 保护状态 : ║\n");
- rt_kprintf("║ 光控保护 : %-46s ║\n", s_light_protect ? "激活" : "正常");
- rt_kprintf("║ 欠压保护 : %-46s ║\n",
- sys_sta.undervolt_protect == PROTECT_ACTIVE ? "激活" : "正常");
- rt_kprintf("║ 高温保护 : %-46s ║\n",
- sys_sta.temp_protect == PROTECT_HIGH_TEMP ? "激活" : "正常");
- rt_kprintf("║ 低温保护 : %-46s ║\n",
- sys_sta.temp_protect == PROTECT_LOW_TEMP ? "激活" : "正常");
- rt_kprintf("║ 倾倒保护 : %-46s ║\n",
- sys_sta.tilt_protect == PROTECT_ACTIVE ? "激活" : "正常");
- rt_kprintf("║ 雨控保护 : %-46s ║\n",
- sys_sta.rain_protect == PROTECT_ACTIVE ? "激活" : "正常");
- rt_kprintf("╠══════════════════════════════════════════════════════════════╣\n");
- rt_kprintf("║ 电气参数 : ║\n");
- rt_kprintf("║ 电池电压 : %dmV%-45s ║\n", sys_sta.battery_voltage, "");
- rt_kprintf("║ 主板温度 : %d.%d°C%-44s ║\n",
- sys_sta.board_temp / 10, sys_sta.board_temp % 10, "");
- rt_kprintf("║ 灯管电流 : %u%-47s ║\n", sys_sta.lamp_current, "");
- rt_kprintf("║ 高压次数 : %u%-47s ║\n", sys_sta.hv_count, "");
- rt_kprintf("║ 灯管开关 : %u%-47s ║\n", gpio_lamp_get_status(), "");
- rt_kprintf("║ 高压开关 : %u%-47s ║\n", gpio_hv_get_status(), "");
- rt_kprintf("╚══════════════════════════════════════════════════════════════╝\n");
- }
- MSH_CMD_EXPORT(cmd_work_status, 查看工作状态);
- /**
- * @brief MSH命令:手动控制工作
- */
- static void cmd_work_ctrl(int argc, char **argv)
- {
- if (argc < 2)
- {
- rt_kprintf("用法: work [start|stop|set <分钟>]\n");
- rt_kprintf(" start - 手动开始工作\n");
- rt_kprintf(" stop - 手动停止工作\n");
- rt_kprintf(" set 5 - 设置工作时长为5分钟\n");
- return;
- }
- if (strcmp(argv[1], "start") == 0)
- {
- if (dev_info.power_state == 0)
- {
- rt_kprintf("错误: 设备已关机\n");
- return;
- }
- s_cooldown_until = 0;
- s_protect_release_time = 0;
- s_state = WORK_STATE_IDLE;
- work_start();
- rt_kprintf("已手动开始工作\n");
- }
- else if (strcmp(argv[1], "stop") == 0)
- {
- work_stop("手动停止", 0);
- rt_kprintf("已手动停止工作\n");
- }
- else if (strcmp(argv[1], "set") == 0 && argc >= 3)
- {
- uint16_t minutes = atoi(argv[2]);
- dev_info.light_work_duration = minutes;
- save_dev_info();
- if (minutes >= 60)
- {
- uint32_t hours = minutes / 60;
- uint32_t mins = minutes % 60;
- if (mins > 0)
- {
- rt_kprintf("工作时长已设置为 %u小时%u分钟\n", hours, mins);
- }
- else
- {
- rt_kprintf("工作时长已设置为 %u小时\n", hours);
- }
- }
- else
- {
- rt_kprintf("工作时长已设置为 %d分钟\n", minutes);
- }
- }
- else
- {
- rt_kprintf("未知命令: %s\n", argv[1]);
- }
- }
- MSH_CMD_EXPORT(cmd_work_ctrl, 手动控制工作);
- /**
- * @brief MSH命令:调试信息
- */
- static void cmd_work_debug(int argc, char **argv)
- {
- rt_kprintf("\n========== WORK DEBUG ==========\n");
- rt_kprintf("s_state: %d\n", s_state);
- rt_kprintf("s_start_time: %u\n", s_start_time);
- rt_kprintf("s_duration_sec: %lu\n", s_duration_sec);
- rt_kprintf("s_auto_mode: %d\n", s_auto_mode);
- rt_kprintf("s_cooldown_until: %u\n", s_cooldown_until);
- rt_kprintf("s_light_protect: %d\n", s_light_protect);
- rt_kprintf("s_protect_release_time: %u\n", s_protect_release_time);
- rt_kprintf("light_percent: %d.%d%%\n",
- sys_sta.light_percent / 10, sys_sta.light_percent % 10);
- rt_kprintf("charge_voltage: %dmV\n", sys_sta.charge_voltage);
- rt_kprintf("===============================\n");
- }
- MSH_CMD_EXPORT(cmd_work_debug, 调试信息);
- /*********************↑ MSH命令 ↑***********************/
|