diff --git a/application/ws63/user_main/spotlight/spotlight_main.c b/application/ws63/user_main/spotlight/spotlight_main.c index 55e4b76..037db02 100755 --- a/application/ws63/user_main/spotlight/spotlight_main.c +++ b/application/ws63/user_main/spotlight/spotlight_main.c @@ -40,6 +40,10 @@ static uint8_t calculate_checksum(const device_data_t* data); static bool write_device_data_to_addr(uint32_t addr, const device_data_t* data);; static void report_device_online_status(void); +// 工具:是否处于配网呼吸模式 +// 使用宏避免某些编译模式下 inline 函数被误判为未返回 +#define is_in_breath_mode() (g_net_breath_state == NET_CFG_BREATHING) + // 状态上报任务相关变量 #define REPORT_TASK_PRIO 80 @@ -254,14 +258,20 @@ static void *fade_task(const char *arg) fade_ctx.fade_completed = false; if (fade_ctx.is_closing_fade) { - // 关灯渐变完成:不更新g_device_control.brightness_local,保持原有目标亮度 - fade_ctx.is_closing_fade = false; - update_pwm_output(false, 0, 0); - g_device_control.duty_cw = 0; - g_device_control.duty_ww = 0; - // 注意:这里不更新 g_device_control.brightness_local,保持之前的亮度值 - e_printf("[fade_task] Close light fade completed, PWM turned off, brightness_local preserved: %d\r\n", - g_device_control.brightness_local); + // 若在收尾时外部已请求开灯且不处于配网呼吸模式,则不执行PWM关断,避免黑场 + if (g_device_control.on && !is_in_breath_mode()) { + e_printf("[fade_task] Close fade preempted by OPEN, skip turning off\r\n"); + fade_ctx.is_closing_fade = false; + } else { + // 关灯渐变完成:不更新g_device_control.brightness_local,保持原有目标亮度 + fade_ctx.is_closing_fade = false; + update_pwm_output(false, 0, 0); + g_device_control.duty_cw = 0; + g_device_control.duty_ww = 0; + // 注意:这里不更新 g_device_control.brightness_local,保持之前的亮度值 + e_printf("[fade_task] Close light fade completed, PWM turned off, brightness_local preserved: %d\r\n", + g_device_control.brightness_local); + } } else { // 正常渐变完成:正常更新所有值 g_device_control.duty_ww = device_control.duty_ww; @@ -667,10 +677,10 @@ static void cancel_current_light_fade(void) // 竞态保护:先拉低标志再停计时器,避免回调自重启 fade_ctx.timer_active = false; uapi_timer_stop(fade_ctx.timer_handle); - // 如果我打断了渐变,则将当前值更新到目标值不然下次计算会异常 - // g_device_control.cct_local = fade_ctx.current_cct; - // g_device_control.brightness_local = fade_ctx.current_brightness; - // memset(&fade_ctx, 0, FADE_CTRL_DATA_SIZE(fade_ctx)); + // 清理标志,防止过期回调触发收尾导致关断等副作用 + fade_ctx.is_fading = false; + fade_ctx.is_closing_fade = false; + fade_ctx.fade_completed = false; } // 计算校验和 @@ -939,6 +949,8 @@ int set_light(light_ctrl_source_e source, int32_t brightness_local_target, int32_t cct_local_target) { bool was_on = g_device_control.on; + bool breath_active = is_in_breath_mode(); + bool was_closing_fade = (fade_ctx.is_fading && fade_ctx.is_closing_fade); struct fade_ctx_t tmp_fade_ctx = {0}; if (fade_ctx.is_fading) { bool closing_fade_active = fade_ctx.is_closing_fade; @@ -949,7 +961,8 @@ int set_light(light_ctrl_source_e source, suppress_cancel = true; // 允许继续关灯渐变;再次关灯请求可复用或稍后重启 } } - if (!suppress_cancel) { + // 配网呼吸期间,不允许普通渐变取消/抢占,避免干扰呼吸效果 + if (!suppress_cancel && !breath_active) { cancel_current_light_fade(); } } @@ -957,12 +970,21 @@ int set_light(light_ctrl_source_e source, if (APP_OPEN_LIGHT == source || DEV_POWER_ON == source) { g_device_control.on = true; - if (DEV_POWER_ON == source || (APP_OPEN_LIGHT == source && !was_on)) { - // 开机或关灯→开灯:从0开始渐变 - fade_ctx.current_brightness = 0; - fade_ctx.current_cct = g_device_control.cct_local; // 色温保持目标值 - e_printf("[set_light] 开灯渐变设置: brightness=0->%d, cct=%d\n", - g_device_control.brightness_local, fade_ctx.current_cct); + if (!breath_active) { + if (was_closing_fade && APP_OPEN_LIGHT == source && !was_on) { + // 非配网场景:开灯打断关灯渐变,沿用即时亮度作为起点(无缝反向) + e_printf("[set_light] 开灯打断关灯渐变: curr=%d -> target=%d\n", + fade_ctx.current_brightness, g_device_control.brightness_local); + fade_ctx.is_closing_fade = false; + // 起点保持为当前渐变即时亮度 + fade_ctx.current_cct = g_device_control.cct_local; + } else if (DEV_POWER_ON == source || (APP_OPEN_LIGHT == source && !was_on)) { + // 真正关→开:从0开始渐变 + fade_ctx.current_brightness = 0; + fade_ctx.current_cct = g_device_control.cct_local; // 色温保持目标值 + e_printf("[set_light] 开灯渐变设置: brightness=0->%d, cct=%d\n", + g_device_control.brightness_local, fade_ctx.current_cct); + } } brightness_local_target = g_device_control.brightness_local; @@ -1009,7 +1031,7 @@ int set_light(light_ctrl_source_e source, tmp_fade_ctx.fade_time = NORMAL_FADE_TIME; // 使用默认渐变时长 tmp_fade_ctx.is_fading = true; tmp_fade_ctx.fade_completed = false; - if (tmp_fade_ctx.is_fading) { + if (tmp_fade_ctx.is_fading && !breath_active) { cancel_current_light_fade(); } calculate_fade_steps(&tmp_fade_ctx); // 复用原有计算流程 @@ -1026,7 +1048,16 @@ int set_light(light_ctrl_source_e source, tmp_fade_ctx.fade_time = NORMAL_FADE_TIME; // 上电时,直接设置为默认渐变时长 case APP_CHANGE_LIGHT_MODE: // 开灯场景或上电:执行渐变;关灯状态下仅更新目标不执行渐变 - if (was_on || source != APP_CHANGE_LIGHT_MODE) { + if (breath_active) { + // 配网期:只更新目标/上报,不启动普通渐变 + if (g_device_control.colourMode == COLOUR_MODE_DUAL) { + g_device_control.cct_local = tmp_fade_ctx.target_cct; + } + g_device_control.brightness_local = tmp_fade_ctx.target_brightness; + start_report_task(REPORT_SWITCH | REPORT_BRIGHTNESS | REPORT_CCT | REPORT_LIGHT_MODE | REPORT_COLOUR_MODE); + req_save_device_data(); + return -111; + } else if (was_on || source != APP_CHANGE_LIGHT_MODE) { if (g_device_control.colourMode == COLOUR_MODE_DUAL) { g_device_control.cct_local = tmp_fade_ctx.target_cct; } @@ -1062,7 +1093,17 @@ int set_light(light_ctrl_source_e source, } break; case APP_CHANGE_LIGHT_BRIGHTNESS_CCT: - if (!was_on) { + if (breath_active) { + // 配网期:只更新目标/上报 + 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; + } + start_report_task(REPORT_BRIGHTNESS | REPORT_CCT | REPORT_LIGHT_MODE | REPORT_COLOUR_MODE); + req_save_device_data(); + } else 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;