修复灯光渐变与状态保持逻辑

主要变更:
- set_light 默认目标值改为取设备当前状态(未指定字段保持不变),避免关灯后切换模式把亮度误写为0。
- 仅对明确修改的字段回写设备状态,防止无意覆盖。
- 关灯状态下的模式/属性变更:只更新目标,不推进渐变;开灯(关→开)从0平滑渐变到目标。
- 关灯渐变进行中不再取消渐变(不被属性/模式变更打断),避免停留在低亮不灭的情况。
- 增加若干调试日志(keep brightness/cct、开灯渐变设置、off-state 变更提示)。

影响范围:application/ws63/user_main/spotlight/spotlight_main.c 的 set_light 与渐变控制流程。

回归清单(详细):
1) 基础渐变与开关
- ON→OFF:观察3s(NORMAL_FADE_TIME)内亮度平滑降为0,最终PWM关断;日志含“start close light fade/Close light fade completed”。
- OFF→ON:从0平滑拉升至目标亮度(保持当前色温),日志含“开灯渐变设置: brightness=0->X”。
- 单色/双色两种 colourMode 下分别验证上述两条。

2) 关灯状态下属性/模式变更(不推进渐变)
- OFF 且非渐变中:修改亮度/色温/模式,仅更新目标,不改变当前亮度(保持0);再次开灯从0平滑到目标。
- OFF 且正在“关灯渐变”中:
  a. 切换 单色→双色、双色→单色;
  b. 修改色温(2700/中间值/最大6000);
  c. 修改亮度(1%、10%、80%、100%);
  期望:关灯渐变不中断直至0;日志出现“off-state mode/attr change … keep/preserve …”,无新的 cancel/stop;开灯后从0渐变到变更后的目标。

3) 渐变过程中的变更
- 开灯渐变过程中修改亮度/色温/场景:应重新计算步长并继续渐变到新目标,无闪断;日志有“start fade”“fade brightness:A->B”。
- 关灯渐变过程中(is_closing_fade=true)修改模式/属性:不取消当前渐变,继续降至0(本修复重点)。

4) 场景模式
- 亮灯状态切换各场景(自定义/休闲/观影/用餐/回家/冬天/夏天):亮度、色温按预设渐变到位。
- 离家模式:切到离家立即触发关灯渐变;开灯时恢复基础模式并从0渐变到目标。
- 关灯状态切换场景:仅更新目标,不推进渐变;开灯后生效。

5) 单色↔双色互转
- 亮灯:单色→双色、双色→单色均应平滑到新目标。
- 关灯:单色→双色、双色→单色只更新目标,关灯渐变不中断;开灯后从0渐变到新目标(复现用例修复验证)。

6) 持久化与上电
- 设定亮度/色温/模式后断电重启:读取到的持久化状态与上电行为正确(若on=true,上电从0渐变到目标;若on=false,保持熄灭)。

7) 上报一致性
- 每次变更后,APP数值与进度条一致,且与设备上报一致;避免出现“进度条位置旧、数值为0”的分离。

8) 边界值与映射
- 亮度:1%/10%/11%/100% 验证 BRIGHTNESS_REMOTE2LOCAL/LOCAL2REMOTE 映射正确,无跳变。
- 色温:2700/中间值/6000,双色下比例分配正确;单色下固定 SINGLE_COLOUR_CCT。

9) 竞态与稳定性
- 快速连点:关/开/改模式/改色温混合快速操作,确保无死锁、无抖动、无残留亮度;fade 定时器单实例运行(无重复自重启)。

10) 日志关键点(用于对齐期望)
- “[set_light] keep brightness/cct …”、“[set_light] 开灯渐变设置 …”、“off-state mode/attr change …”。
- “start close light fade / Fade completed”、“fade brightness: x->y … time:3s”。
- 上报触发:REPORT_SWITCH/BRIGHTNESS/CCT/LIGHT_MODE/COLOUR_MODE 顺序与次数合理。
This commit is contained in:
2025-11-16 19:18:57 +08:00
parent 8270708ef2
commit cb1ef39108
3 changed files with 99 additions and 44 deletions

View File

@@ -938,19 +938,30 @@ static void stop_save_task(void)
int set_light(light_ctrl_source_e source, int set_light(light_ctrl_source_e source,
int32_t brightness_local_target, int32_t cct_local_target) int32_t brightness_local_target, int32_t cct_local_target)
{ {
bool was_on = g_device_control.on;
struct fade_ctx_t tmp_fade_ctx = {0}; struct fade_ctx_t tmp_fade_ctx = {0};
if (fade_ctx.is_fading) { if (fade_ctx.is_fading) {
bool closing_fade_active = fade_ctx.is_closing_fade;
bool suppress_cancel = false;
// 在关灯渐变过程中,属性/模式变更不应打断关灯过程
if (closing_fade_active) {
if (source == APP_CHANGE_LIGHT_BRIGHTNESS_CCT || source == APP_CHANGE_LIGHT_MODE || source == APP_CLOSE_LIGHT) {
suppress_cancel = true; // 允许继续关灯渐变;再次关灯请求可复用或稍后重启
}
}
if (!suppress_cancel) {
cancel_current_light_fade(); cancel_current_light_fade();
} }
}
// 如果打开灯,则需要手动将前置状态设置为关闭的样子,这样子后面计算渐变才能正常计算 // 如果打开灯,则需要手动将前置状态设置为关闭的样子,这样子后面计算渐变才能正常计算
if (APP_OPEN_LIGHT == source || DEV_POWER_ON == source) { if (APP_OPEN_LIGHT == source || DEV_POWER_ON == source) {
g_device_control.on = true; g_device_control.on = true;
if (DEV_POWER_ON == source) { if (DEV_POWER_ON == source || (APP_OPEN_LIGHT == source && !was_on)) {
// 🔧 开机渐变:明确设置从0开始 // 开机或关灯→开灯:从0开始渐变
fade_ctx.current_brightness = 0; // 从0开始渐变 fade_ctx.current_brightness = 0;
fade_ctx.current_cct = g_device_control.cct_local; // 色温保持目标值 fade_ctx.current_cct = g_device_control.cct_local; // 色温保持目标值
e_printf("[set_light] 开渐变设置: brightness=0->%d, cct=%d\n", e_printf("[set_light] 开渐变设置: brightness=0->%d, cct=%d\n",
g_device_control.brightness_local, fade_ctx.current_cct); g_device_control.brightness_local, fade_ctx.current_cct);
} }
@@ -964,15 +975,24 @@ int set_light(light_ctrl_source_e source,
} }
} }
memcpy(&tmp_fade_ctx, &fade_ctx, FADE_CTRL_DATA_SIZE(fade_ctx)); memcpy(&tmp_fade_ctx, &fade_ctx, FADE_CTRL_DATA_SIZE(fade_ctx));
// tmp_fade_ctx.target_brightness = tmp_fade_ctx.current_brightness; // 默认目标应为“当前设备状态”避免在未指定字段时误用上一次渐变的目标可能为0
tmp_fade_ctx.target_brightness = g_device_control.brightness_local;
tmp_fade_ctx.target_cct = g_device_control.cct_local;
if (brightness_local_target >= 0) { if (brightness_local_target >= 0) {
BRIGHTNESS_LITME_RANGE(brightness_local_target); BRIGHTNESS_LITME_RANGE(brightness_local_target);
tmp_fade_ctx.target_brightness = brightness_local_target; tmp_fade_ctx.target_brightness = brightness_local_target;
} else {
e_printf("[set_light] keep brightness:%d (source:%d)\r\n",
tmp_fade_ctx.target_brightness, source);
} }
// tmp_fade_ctx.target_cct = tmp_fade_ctx.current_cct;
if (cct_local_target >= 0) { if (cct_local_target >= 0) {
CCT_LITME_RANGE(cct_local_target); CCT_LITME_RANGE(cct_local_target);
tmp_fade_ctx.target_cct = cct_local_target; tmp_fade_ctx.target_cct = cct_local_target;
} else {
e_printf("[set_light] keep cct:%d (source:%d)\r\n",
tmp_fade_ctx.target_cct, source);
} }
e_printf("source:%d, lightMode:%d, local brightness: base:%d, target:%d, local cct: base:%d, target:%d\r\n", e_printf("source:%d, lightMode:%d, local brightness: base:%d, target:%d, local cct: base:%d, target:%d\r\n",
source, g_device_control.elightMode, tmp_fade_ctx.current_brightness, source, g_device_control.elightMode, tmp_fade_ctx.current_brightness,
@@ -1005,12 +1025,12 @@ int set_light(light_ctrl_source_e source,
case APP_OPEN_LIGHT: case APP_OPEN_LIGHT:
tmp_fade_ctx.fade_time = NORMAL_FADE_TIME; // 上电时,直接设置为默认渐变时长 tmp_fade_ctx.fade_time = NORMAL_FADE_TIME; // 上电时,直接设置为默认渐变时长
case APP_CHANGE_LIGHT_MODE: case APP_CHANGE_LIGHT_MODE:
// 直接将信息更新目标 // 开灯场景或上电:执行渐变;关灯状态下仅更新目标不执行渐变
if (was_on || source != APP_CHANGE_LIGHT_MODE) {
if (g_device_control.colourMode == COLOUR_MODE_DUAL) { if (g_device_control.colourMode == COLOUR_MODE_DUAL) {
g_device_control.cct_local = tmp_fade_ctx.target_cct; g_device_control.cct_local = tmp_fade_ctx.target_cct;
} }
g_device_control.brightness_local = tmp_fade_ctx.target_brightness; g_device_control.brightness_local = tmp_fade_ctx.target_brightness;
//情景模式或者上电时直接切换到对应的色温和亮度
tmp_fade_ctx.is_fading = true; tmp_fade_ctx.is_fading = true;
tmp_fade_ctx.fade_completed = false; tmp_fade_ctx.fade_completed = false;
if (tmp_fade_ctx.is_fading) { if (tmp_fade_ctx.is_fading) {
@@ -1024,13 +1044,47 @@ int set_light(light_ctrl_source_e source,
start_report_task(REPORT_SWITCH | REPORT_BRIGHTNESS | REPORT_CCT | REPORT_LIGHT_MODE | REPORT_COLOUR_MODE); start_report_task(REPORT_SWITCH | REPORT_BRIGHTNESS | REPORT_CCT | REPORT_LIGHT_MODE | REPORT_COLOUR_MODE);
req_save_device_data(); req_save_device_data();
return 0; // 异步上报 return 0; // 异步上报
break; } else {
case APP_CHANGE_LIGHT_BRIGHTNESS_CCT: // 灯处于关闭仅更新目标值保持当前亮度为0不触发渐变
// 直接将信息更新到目标值 if (g_device_control.colourMode == COLOUR_MODE_DUAL) {
if (g_device_control.colourMode == COLOUR_MODE_DUAL) { //只有双色温模式下,色温才会变化
g_device_control.cct_local = tmp_fade_ctx.target_cct; g_device_control.cct_local = tmp_fade_ctx.target_cct;
// 关灯渐变进行中不改动 fade_ctx避免打断渐变过程的内部状态
if (!fade_ctx.is_closing_fade) {
fade_ctx.current_cct = tmp_fade_ctx.target_cct; // 预设色温,开灯后按新色温渐变
}
} }
g_device_control.brightness_local = tmp_fade_ctx.target_brightness; g_device_control.brightness_local = tmp_fade_ctx.target_brightness;
e_printf("[set_light] off-state mode change, preserve current_brightness:%d, target_brightness:%d\r\n",
fade_ctx.current_brightness, g_device_control.brightness_local);
start_report_task(REPORT_BRIGHTNESS | REPORT_CCT | REPORT_LIGHT_MODE | REPORT_COLOUR_MODE);
req_save_device_data();
return -111;
}
break;
case APP_CHANGE_LIGHT_BRIGHTNESS_CCT:
if (!was_on) {
// 关灯状态:仅更新目标,不执行渐变,保持 current_brightness=0避免开灯时跳变
if (g_device_control.colourMode == COLOUR_MODE_DUAL && cct_local_target >= 0) {
g_device_control.cct_local = tmp_fade_ctx.target_cct;
if (!fade_ctx.is_closing_fade) {
fade_ctx.current_cct = tmp_fade_ctx.target_cct; // 预设色温
}
}
if (brightness_local_target >= 0) {
g_device_control.brightness_local = tmp_fade_ctx.target_brightness;
}
e_printf("[set_light] off-state attr change, keep current_brightness:%d, target_brightness:%d\r\n",
fade_ctx.current_brightness, g_device_control.brightness_local);
start_report_task(REPORT_BRIGHTNESS | REPORT_CCT | REPORT_LIGHT_MODE | REPORT_COLOUR_MODE);
req_save_device_data();
} else {
// 开灯状态:执行正常渐变
if (g_device_control.colourMode == COLOUR_MODE_DUAL && cct_local_target >= 0) { // 双色温且明确修改时才更新色温
g_device_control.cct_local = tmp_fade_ctx.target_cct;
}
if (brightness_local_target >= 0) { // 明确修改亮度时才更新亮度
g_device_control.brightness_local = tmp_fade_ctx.target_brightness;
}
tmp_fade_ctx.is_fading = true; tmp_fade_ctx.is_fading = true;
tmp_fade_ctx.fade_completed = false; tmp_fade_ctx.fade_completed = false;
if (tmp_fade_ctx.is_fading) { if (tmp_fade_ctx.is_fading) {
@@ -1043,6 +1097,7 @@ int set_light(light_ctrl_source_e source,
uapi_timer_start(fade_ctx.timer_handle, fade_ctx.update_interval, fade_timer_callback, 0); uapi_timer_start(fade_ctx.timer_handle, fade_ctx.update_interval, fade_timer_callback, 0);
start_report_task(REPORT_BRIGHTNESS | REPORT_CCT | REPORT_LIGHT_MODE | REPORT_COLOUR_MODE); start_report_task(REPORT_BRIGHTNESS | REPORT_CCT | REPORT_LIGHT_MODE | REPORT_COLOUR_MODE);
req_save_device_data(); req_save_device_data();
}
#if 0 #if 0
等待渐变完成 等待渐变完成
while (!fade_ctx.fade_completed) { while (!fade_ctx.fade_completed) {

Binary file not shown.