固件 0.1.14~0.1.16-c5:Hub 按需启停(hubctl)、开机长按统一 5 s
Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
+36
-1
@@ -16,6 +16,7 @@
|
||||
#include "dac63204.h"
|
||||
#include "evlog.h"
|
||||
#include "hal_i2c.h"
|
||||
#include "hubctl.h"
|
||||
#include "hal_lock.h"
|
||||
#include "hal_time.h"
|
||||
#include "i2cbus.h"
|
||||
@@ -189,7 +190,8 @@ static void test_cmd_numbers_are_frozen(void)
|
||||
TEST_ASSERT_EQUAL_INT(12, CMD_NET);
|
||||
TEST_ASSERT_EQUAL_INT(13, CMD_OTA); /* C2 */
|
||||
TEST_ASSERT_EQUAL_INT(14, CMD_FLASH_MODE); /* 0.1.5 刷机模式 */
|
||||
TEST_ASSERT_EQUAL_INT(15, CMD_COUNT);
|
||||
TEST_ASSERT_EQUAL_INT(15, CMD_HUB); /* 0.1.14 Hub 按需启停 */
|
||||
TEST_ASSERT_EQUAL_INT(16, CMD_COUNT);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(0, CMD_OK);
|
||||
TEST_ASSERT_EQUAL_INT(1, CMD_ERR_PARSE);
|
||||
@@ -590,6 +592,38 @@ static void test_fan_floor(void)
|
||||
TEST_ASSERT_EQUAL_UINT16(0, t_thermal_floor());
|
||||
}
|
||||
|
||||
/* 0.1.14 hub:改模式 / 保持窗口,两条链路都收;越界记事件、缺参数不记;
|
||||
USB 链路上的任何一行都算一次「有人在用 USB」。 */
|
||||
static void test_hub_command(void)
|
||||
{
|
||||
hubctl_init(HUB_MODE_AUTO, NULL, NULL, hal_time_now_ms());
|
||||
|
||||
const char *r = send_on(CMD_LINK_WIFI, "{\"seq\":1,\"cmd\":\"hub\",\"mode\":\"on\"}");
|
||||
ASSERT_HAS(r, "\"ok\":true");
|
||||
ASSERT_HAS(r, "\"hub\":{\"on\":true,\"mode\":\"on\"");
|
||||
TEST_ASSERT_EQUAL_INT(HUB_MODE_ON, hubctl_mode());
|
||||
|
||||
r = send("{\"seq\":2,\"cmd\":\"hub\",\"mode\":\"auto\",\"min\":30}");
|
||||
ASSERT_HAS(r, "\"mode\":\"auto\"");
|
||||
ASSERT_HAS(r, "\"hold\":1800");
|
||||
TEST_ASSERT_EQUAL_UINT32(1800, hubctl_hold_left_s(hal_time_now_ms()));
|
||||
|
||||
ASSERT_HAS(send("{\"seq\":3,\"cmd\":\"hub\",\"min\":241}"), "\"err\":\"range\"");
|
||||
TEST_ASSERT_EQUAL_INT(1, count_events(LOG_EV_CMD_REJECT));
|
||||
ASSERT_HAS(send("{\"seq\":4,\"cmd\":\"hub\",\"mode\":\"off\"}"), "\"err\":\"arg\"");
|
||||
ASSERT_HAS(send("{\"seq\":5,\"cmd\":\"hub\"}"), "\"err\":\"arg\"");
|
||||
TEST_ASSERT_EQUAL_INT(1, count_events(LOG_EV_CMD_REJECT));
|
||||
ASSERT_HAS(send("{\"seq\":5,\"cmd\":\"hub\"}"), "\"dup\":true"); /* 会动东西 ⇒ 进判重窗口 */
|
||||
|
||||
ASSERT_HAS(send("{\"seq\":7,\"cmd\":\"hub\",\"min\":0}"), "\"hold\":0");
|
||||
const hub_in_t idle = { .link_up = true };
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_OFF, hub_decide(&idle, hal_time_now_ms() + 1));
|
||||
|
||||
/* USB 上来一行(哪怕是 status)⇒ 重新给一个 idle 窗口。 */
|
||||
(void)send_on(CMD_LINK_USB, "{\"cmd\":\"status\"}");
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_IDLE, hub_decide(&idle, hal_time_now_ms() + 1));
|
||||
}
|
||||
|
||||
/* ---- 只读命令 ------------------------------------------------------------ */
|
||||
|
||||
/* events 分页:一次最多 CMD_EVENTS_MAX 条,逐条带序号,游标接得上;RAM 里的先落盘。 */
|
||||
@@ -858,6 +892,7 @@ int main(void)
|
||||
RUN_TEST(test_power_off_drops_vbus_and_always_drops_the_efuse);
|
||||
RUN_TEST(test_power_records_intent_only_when_it_took_effect);
|
||||
RUN_TEST(test_fan_floor);
|
||||
RUN_TEST(test_hub_command);
|
||||
RUN_TEST(test_events_pages_with_contiguous_seqs);
|
||||
RUN_TEST(test_status_fits_and_reports_unknowns_as_null);
|
||||
RUN_TEST(test_small_output_buffer);
|
||||
|
||||
@@ -89,7 +89,8 @@ static void test_flash_format_is_frozen(void)
|
||||
TEST_ASSERT_EQUAL_INT(19, LOG_EV_BOOT_CHECK); /* 0.1.2 开机校验 */
|
||||
TEST_ASSERT_EQUAL_INT(20, LOG_EV_BLADE_MUTE); /* 0.1.4 刀片不应答 */
|
||||
TEST_ASSERT_EQUAL_INT(21, LOG_EV_CHG_MODE); /* 0.1.5 刷机模式 */
|
||||
TEST_ASSERT_EQUAL_INT(22, LOG_EV_COUNT);
|
||||
TEST_ASSERT_EQUAL_INT(22, LOG_EV_HUB); /* 0.1.14 Hub 按需启停 */
|
||||
TEST_ASSERT_EQUAL_INT(23, LOG_EV_COUNT);
|
||||
}
|
||||
|
||||
/* §10.7 的「必记事件」有八类,A10 只产生其中两类。剩下的号先占住,
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
/* 0.1.14:Hub 按需启停(hubctl.h)。
|
||||
|
||||
口径同其它测试:判据用 `hub_decide()` 直接喂输入;引脚与事件用 `hubctl_tick()`
|
||||
打在假 GPIO / 事件缓冲上。R716 的上拉用 `sim_gpio_drive(HUB_RST#, 1)` 模拟 ——
|
||||
放成输入时读回 1 = Hub 在工作,配成输出拉低时读回 0 = 按住复位。 */
|
||||
#include <string.h>
|
||||
|
||||
#include "board_pins.h"
|
||||
#include "evlog.h"
|
||||
#include "hal_time.h"
|
||||
#include "hubctl.h"
|
||||
#include "netcfg.h"
|
||||
#include "sim_hal.h"
|
||||
#include "unity.h"
|
||||
|
||||
#define PIN BOARD_PIN_HUB_RST_N
|
||||
|
||||
static hub_mode_t s_saved;
|
||||
static int s_saves;
|
||||
|
||||
static void save(void *ctx, hub_mode_t m)
|
||||
{
|
||||
(void)ctx;
|
||||
s_saved = m;
|
||||
s_saves++;
|
||||
}
|
||||
|
||||
static void link(bool up)
|
||||
{
|
||||
net_status_t st;
|
||||
memset(&st, 0, sizeof(st));
|
||||
st.mqtt = up ? NET_UP : NET_CONNECTING;
|
||||
net_status_set(&st);
|
||||
}
|
||||
|
||||
static uint32_t now(void) { return hal_time_now_ms(); }
|
||||
|
||||
/* 每 100 ms 一拍(执行器空闲时的节奏),推 ms 毫秒。 */
|
||||
static void run_ms(uint32_t ms)
|
||||
{
|
||||
for (uint32_t t = 0; t < ms; t += 100) {
|
||||
sim_time_advance_ms(100);
|
||||
hubctl_tick(now());
|
||||
}
|
||||
}
|
||||
|
||||
static int hub_events(uint8_t arg)
|
||||
{
|
||||
(void)evlog_flush(0);
|
||||
evlog_rec_t r[16];
|
||||
const uint32_t n = evlog_read(0, r, 16);
|
||||
int k = 0;
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
k += (r[i].type == LOG_EV_HUB && r[i].arg == arg) ? 1 : 0;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
sim_hal_reset();
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, evlog_init());
|
||||
sim_gpio_drive(PIN, 1); /* R716 */
|
||||
s_saves = 0;
|
||||
link(true);
|
||||
hubctl_init(HUB_MODE_AUTO, save, NULL, now());
|
||||
}
|
||||
|
||||
void tearDown(void) {}
|
||||
|
||||
static const hub_in_t k_idle = { .link_up = true };
|
||||
|
||||
/* ---- 判据 ---------------------------------------------------------------- */
|
||||
|
||||
/* 启动算一次需要:HUB_IDLE_MS 之内开着(idle),到点就关。 */
|
||||
static void test_boot_window_then_off(void)
|
||||
{
|
||||
TEST_ASSERT_TRUE(hubctl_is_on());
|
||||
TEST_ASSERT_EQUAL_INT(1, sim_gpio_level(PIN));
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_IDLE, hub_decide(&k_idle, now() + HUB_IDLE_MS - 1));
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_OFF, hub_decide(&k_idle, now() + HUB_IDLE_MS));
|
||||
}
|
||||
|
||||
/* 优先级:mode > vbus > flash > act > hold > link。任一条都刷新「最后一次需要」。 */
|
||||
static void test_reasons_and_their_order(void)
|
||||
{
|
||||
hub_in_t in = k_idle;
|
||||
in.vbus_any = in.flash_any = in.act_any = true;
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_VBUS, hub_decide(&in, now()));
|
||||
in.vbus_any = false;
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_FLASH, hub_decide(&in, now()));
|
||||
in.flash_any = false;
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_ACT, hub_decide(&in, now()));
|
||||
in.act_any = false;
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_IDLE, hub_decide(&in, now()));
|
||||
|
||||
/* VBUS 一直开着 30 分钟,关掉之后还要再开 HUB_IDLE_MS。 */
|
||||
const uint32_t t0 = now() + 30u * 60000u;
|
||||
in.vbus_any = true;
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_VBUS, hub_decide(&in, t0));
|
||||
in.vbus_any = false;
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_IDLE, hub_decide(&in, t0 + HUB_IDLE_MS - 1));
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_OFF, hub_decide(&in, t0 + HUB_IDLE_MS));
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, hubctl_set_mode(HUB_MODE_ON));
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_MODE, hub_decide(&in, t0 + 10u * HUB_IDLE_MS));
|
||||
}
|
||||
|
||||
/* MQTT 断满 HUB_LINK_LOST_MS 才算(WiFi 抖一下不开);恢复后再给一个 idle 窗口。 */
|
||||
static void test_link_lost_forces_on(void)
|
||||
{
|
||||
const uint32_t t0 = now() + HUB_IDLE_MS; /* 启动窗口已过 */
|
||||
hub_in_t in = k_idle;
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_OFF, hub_decide(&in, t0));
|
||||
in.link_up = false;
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_OFF, hub_decide(&in, t0));
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_OFF, hub_decide(&in, t0 + HUB_LINK_LOST_MS - 1));
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_LINK, hub_decide(&in, t0 + HUB_LINK_LOST_MS));
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_LINK, hub_decide(&in, t0 + 5u * HUB_IDLE_MS));
|
||||
in.link_up = true;
|
||||
const uint32_t t1 = t0 + 5u * HUB_IDLE_MS + 1;
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_IDLE, hub_decide(&in, t1));
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_OFF, hub_decide(&in, t1 + HUB_IDLE_MS));
|
||||
|
||||
/* 断了不到一分钟又连上:计时重来,不累计。 */
|
||||
in.link_up = false;
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_OFF, hub_decide(&in, t1 + HUB_IDLE_MS + 1));
|
||||
in.link_up = true;
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_OFF, hub_decide(&in, t1 + HUB_IDLE_MS + 30000u));
|
||||
in.link_up = false;
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_OFF, hub_decide(&in, t1 + HUB_IDLE_MS + 30001u));
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_OFF,
|
||||
hub_decide(&in, t1 + HUB_IDLE_MS + 30001u + HUB_LINK_LOST_MS - 1));
|
||||
}
|
||||
|
||||
/* 电脑插上(UP_VBUS_DET 上升沿)与 USB 命令都算一次需要;电平一直高不算。 */
|
||||
static void test_host_edge_and_usb_touch(void)
|
||||
{
|
||||
const uint32_t t0 = now() + HUB_IDLE_MS;
|
||||
hub_in_t in = k_idle;
|
||||
in.host = true;
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_IDLE, hub_decide(&in, t0)); /* 上升沿 */
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_OFF, hub_decide(&in, t0 + HUB_IDLE_MS)); /* 电平不算 */
|
||||
|
||||
hubctl_touch(t0 + 2u * HUB_IDLE_MS);
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_IDLE, hub_decide(&in, t0 + 3u * HUB_IDLE_MS - 1));
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_OFF, hub_decide(&in, t0 + 3u * HUB_IDLE_MS));
|
||||
}
|
||||
|
||||
/* 保持窗口;min=0 取消保持并结束 idle 窗口(下一拍就关)。 */
|
||||
static void test_hold(void)
|
||||
{
|
||||
const uint32_t t0 = now();
|
||||
TEST_ASSERT_EQUAL_INT(HAL_ERR_ARG, hubctl_hold(HUB_HOLD_MAX_MIN + 1, t0));
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, hubctl_hold(30, t0));
|
||||
TEST_ASSERT_EQUAL_UINT32(1800, hubctl_hold_left_s(t0));
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_HOLD, hub_decide(&k_idle, t0 + 30u * 60000u - 1));
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_IDLE, hub_decide(&k_idle, t0 + 30u * 60000u));
|
||||
TEST_ASSERT_EQUAL_UINT32(0, hubctl_hold_left_s(t0 + 30u * 60000u));
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, hubctl_hold(0, t0 + 30u * 60000u));
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_OFF, hub_decide(&k_idle, t0 + 30u * 60000u + 1));
|
||||
}
|
||||
|
||||
/* 关着 49.7 天,32 位时钟回绕之后 idle 窗口不许「复活」。 */
|
||||
static void test_idle_window_does_not_revive_after_wrap(void)
|
||||
{
|
||||
const uint32_t t0 = now() + HUB_IDLE_MS;
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_OFF, hub_decide(&k_idle, t0));
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_OFF, hub_decide(&k_idle, t0 + 0x80000000u));
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_OFF, hub_decide(&k_idle, t0 + 0xFFFFFFF0u));
|
||||
}
|
||||
|
||||
/* ---- 引脚与事件 ---------------------------------------------------------- */
|
||||
|
||||
/* 关 = 配成输出拉低;开 = 放成输入(R716 拉高),**从不主动写 1**。每次翻转一条事件。 */
|
||||
static void test_tick_drives_the_pin_and_logs(void)
|
||||
{
|
||||
run_ms(HUB_IDLE_MS + 200);
|
||||
TEST_ASSERT_FALSE(hubctl_is_on());
|
||||
TEST_ASSERT_EQUAL_INT(0, sim_gpio_level(PIN));
|
||||
TEST_ASSERT_EQUAL_INT(1, hub_events(HUB_EV_OFF));
|
||||
TEST_ASSERT_EQUAL_UINT64(0, sim_gpio_rise_us(PIN)); /* 固件没写过 1 */
|
||||
|
||||
/* 断网一分钟 ⇒ 自己回来。 */
|
||||
link(false);
|
||||
run_ms(HUB_LINK_LOST_MS + 200);
|
||||
TEST_ASSERT_TRUE(hubctl_is_on());
|
||||
TEST_ASSERT_EQUAL_INT(HUB_WHY_LINK, hubctl_why());
|
||||
TEST_ASSERT_EQUAL_INT(1, sim_gpio_level(PIN));
|
||||
TEST_ASSERT_EQUAL_INT(1, hub_events(HUB_EV_ON));
|
||||
TEST_ASSERT_EQUAL_UINT64(0, sim_gpio_rise_us(PIN));
|
||||
|
||||
/* 一直开着不重复记。 */
|
||||
run_ms(5000);
|
||||
TEST_ASSERT_EQUAL_INT(1, hub_events(HUB_EV_ON));
|
||||
}
|
||||
|
||||
static void test_mode_is_saved_and_logged(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL_INT(HAL_ERR_ARG, hubctl_set_mode(HUB_MODE_COUNT));
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, hubctl_set_mode(HUB_MODE_ON));
|
||||
TEST_ASSERT_EQUAL_INT(1, s_saves);
|
||||
TEST_ASSERT_EQUAL_INT(HUB_MODE_ON, s_saved);
|
||||
TEST_ASSERT_EQUAL_INT(1, hub_events(HUB_EV_MODE | HUB_MODE_ON));
|
||||
run_ms(HUB_IDLE_MS + 200);
|
||||
TEST_ASSERT_TRUE(hubctl_is_on()); /* 常开 */
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, hubctl_set_mode(HUB_MODE_ON));
|
||||
TEST_ASSERT_EQUAL_INT(1, hub_events(HUB_EV_MODE | HUB_MODE_ON)); /* 没变不记 */
|
||||
|
||||
hub_mode_t m = HUB_MODE_ON;
|
||||
TEST_ASSERT_TRUE(hub_mode_parse("auto", &m));
|
||||
TEST_ASSERT_EQUAL_INT(HUB_MODE_AUTO, m);
|
||||
TEST_ASSERT_FALSE(hub_mode_parse("off", &m));
|
||||
}
|
||||
|
||||
/* 从 NVS 读到的是垃圾 ⇒ 按 AUTO。 */
|
||||
static void test_bad_mode_falls_back_to_auto(void)
|
||||
{
|
||||
hubctl_init((hub_mode_t)7, NULL, NULL, now());
|
||||
TEST_ASSERT_EQUAL_INT(HUB_MODE_AUTO, hubctl_mode());
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(test_boot_window_then_off);
|
||||
RUN_TEST(test_reasons_and_their_order);
|
||||
RUN_TEST(test_link_lost_forces_on);
|
||||
RUN_TEST(test_host_edge_and_usb_touch);
|
||||
RUN_TEST(test_hold);
|
||||
RUN_TEST(test_idle_window_does_not_revive_after_wrap);
|
||||
RUN_TEST(test_tick_drives_the_pin_and_logs);
|
||||
RUN_TEST(test_mode_is_saved_and_logged);
|
||||
RUN_TEST(test_bad_mode_falls_back_to_auto);
|
||||
return UNITY_END();
|
||||
}
|
||||
@@ -1020,7 +1020,7 @@ static void test_timings_match_the_documents(void)
|
||||
TEST_ASSERT_TRUE(ACT_HR_PG_POLL_MS > 0 && ACT_HR_PG_POLL_MS * 10 <= ACT_HR_PG_TIMEOUT_MS);
|
||||
|
||||
TEST_ASSERT_EQUAL_UINT32(100, ACT_KEY_MS_TAP); /* SW-5 三档 */
|
||||
TEST_ASSERT_EQUAL_UINT32(5000, ACT_KEY_MS_ON); /* 小米8 实测 2 s 不够(t_actuator.h) */
|
||||
TEST_ASSERT_EQUAL_UINT32(5000, ACT_KEY_MS_ON); /* 小米8 实测 2 s、3 s 都不够(t_actuator.h) */
|
||||
TEST_ASSERT_TRUE(ACT_KEY_MS_ON < ACT_KEY_MS_FORCE); /* 开机那一下不能按成强制重启 */
|
||||
TEST_ASSERT_EQUAL_UINT32(ACT_KEY_MS_ON, ACT_HR_BOOT_KEY_MS);
|
||||
TEST_ASSERT_EQUAL_UINT32(10000, ACT_KEY_MS_FORCE);
|
||||
@@ -1099,7 +1099,7 @@ static void test_format_prints_every_rail(void)
|
||||
/* ==== 0.1.2:硬重启的开机校验与重按 =======================================
|
||||
2026-09-28 板 B 第 1 路:电源键弹片压刀片铜盘接触不良,7 次硬重启只开起来 1 次,
|
||||
失败时电流一直 1~2 mA(屏都不亮)。假手机照实测建模:
|
||||
· 第 `boots_on` 次按满 5 s 松手后开机 ⇒ 电流 ~210 mA(logo 段);
|
||||
· 第 `boots_on` 次按满 ACT_KEY_MS_ON 松手后开机 ⇒ 电流 ~210 mA(logo 段);
|
||||
· 其余情况 1.5 mA(关机态);
|
||||
· `half_on`:第一次按下去 PMIC 醒了、SoC 没接住 —— 松手后 415 mA 撑 2.5 s 再掉回去
|
||||
(照「按 2 s」那次的实测形态),校验不能被它骗过去。 */
|
||||
@@ -1202,7 +1202,7 @@ static void run_phone_ms(int rail, uint32_t ms)
|
||||
}
|
||||
}
|
||||
|
||||
/* 一轮按键 + 校验最长多久:按 5 s + 松键后判到窗口末尾。 */
|
||||
/* 一轮按键 + 校验最长多久:按 ACT_KEY_MS_ON + 松键后判到窗口末尾。 */
|
||||
#define ONE_TRY_MS (ACT_HR_BOOT_KEY_MS + ACT_HR_VERIFY_DELAY_MS + ACT_HR_VERIFY_WINDOW_MS + 50)
|
||||
#define HR_TO_PRESS_MS (ACT_HR_OFF_MS + ACT_HR_RAMP_MS + ACT_HR_PG_POLL_MS)
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户