重构渐变控制(第一阶段):引入配网互斥与开关/属性抢占策略
- 增加 is_in_breath_mode() 工具,明确配网(BREATHING)期间禁止普通渐变的取消与启动,避免干扰配网呼吸。 - set_light: * 未指定字段保持不变的策略保留。 * 在关灯渐变期间,属性/模式变更不取消渐变,仅更新目标。 * 开灯(非配网)打断关灯渐变时,从当前即时亮度起步反向渐变,避免黑场;真正关→开或上电仍从0渐变。 * 配网期的开/关/改模式/改属性:仅更新目标与上报,不启动普通渐变。 - cancel_current_light_fade:补充清理 is_fading/is_closing_fade/fade_completed,杜绝过期回调收尾副作用。 - fade_task:关灯渐变完成时,如已被开灯抢占且非配网,跳过 PWM 关断收尾,避免‘先黑一下’。 覆盖场景:开关灯、场景模式、颜色模式、单独色温/亮度变更、各类中途打断;同时不影响配网呼吸。
This commit is contained in:
@@ -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 bool write_device_data_to_addr(uint32_t addr, const device_data_t* data);;
|
||||||
static void report_device_online_status(void);
|
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
|
#define REPORT_TASK_PRIO 80
|
||||||
@@ -254,14 +258,20 @@ static void *fade_task(const char *arg)
|
|||||||
fade_ctx.fade_completed = false;
|
fade_ctx.fade_completed = false;
|
||||||
|
|
||||||
if (fade_ctx.is_closing_fade) {
|
if (fade_ctx.is_closing_fade) {
|
||||||
// 关灯渐变完成:不更新g_device_control.brightness_local,保持原有目标亮度
|
// 若在收尾时外部已请求开灯且不处于配网呼吸模式,则不执行PWM关断,避免黑场
|
||||||
fade_ctx.is_closing_fade = false;
|
if (g_device_control.on && !is_in_breath_mode()) {
|
||||||
update_pwm_output(false, 0, 0);
|
e_printf("[fade_task] Close fade preempted by OPEN, skip turning off\r\n");
|
||||||
g_device_control.duty_cw = 0;
|
fade_ctx.is_closing_fade = false;
|
||||||
g_device_control.duty_ww = 0;
|
} else {
|
||||||
// 注意:这里不更新 g_device_control.brightness_local,保持之前的亮度值
|
// 关灯渐变完成:不更新g_device_control.brightness_local,保持原有目标亮度
|
||||||
e_printf("[fade_task] Close light fade completed, PWM turned off, brightness_local preserved: %d\r\n",
|
fade_ctx.is_closing_fade = false;
|
||||||
g_device_control.brightness_local);
|
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 {
|
} else {
|
||||||
// 正常渐变完成:正常更新所有值
|
// 正常渐变完成:正常更新所有值
|
||||||
g_device_control.duty_ww = device_control.duty_ww;
|
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;
|
fade_ctx.timer_active = false;
|
||||||
uapi_timer_stop(fade_ctx.timer_handle);
|
uapi_timer_stop(fade_ctx.timer_handle);
|
||||||
// 如果我打断了渐变,则将当前值更新到目标值不然下次计算会异常
|
// 清理标志,防止过期回调触发收尾导致关断等副作用
|
||||||
// g_device_control.cct_local = fade_ctx.current_cct;
|
fade_ctx.is_fading = false;
|
||||||
// g_device_control.brightness_local = fade_ctx.current_brightness;
|
fade_ctx.is_closing_fade = false;
|
||||||
// memset(&fade_ctx, 0, FADE_CTRL_DATA_SIZE(fade_ctx));
|
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)
|
int32_t brightness_local_target, int32_t cct_local_target)
|
||||||
{
|
{
|
||||||
bool was_on = g_device_control.on;
|
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};
|
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 closing_fade_active = fade_ctx.is_closing_fade;
|
||||||
@@ -949,7 +961,8 @@ int set_light(light_ctrl_source_e source,
|
|||||||
suppress_cancel = true; // 允许继续关灯渐变;再次关灯请求可复用或稍后重启
|
suppress_cancel = true; // 允许继续关灯渐变;再次关灯请求可复用或稍后重启
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!suppress_cancel) {
|
// 配网呼吸期间,不允许普通渐变取消/抢占,避免干扰呼吸效果
|
||||||
|
if (!suppress_cancel && !breath_active) {
|
||||||
cancel_current_light_fade();
|
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) {
|
if (APP_OPEN_LIGHT == source || DEV_POWER_ON == source) {
|
||||||
g_device_control.on = true;
|
g_device_control.on = true;
|
||||||
|
|
||||||
if (DEV_POWER_ON == source || (APP_OPEN_LIGHT == source && !was_on)) {
|
if (!breath_active) {
|
||||||
// 开机或关灯→开灯:从0开始渐变
|
if (was_closing_fade && APP_OPEN_LIGHT == source && !was_on) {
|
||||||
fade_ctx.current_brightness = 0;
|
// 非配网场景:开灯打断关灯渐变,沿用即时亮度作为起点(无缝反向)
|
||||||
fade_ctx.current_cct = g_device_control.cct_local; // 色温保持目标值
|
e_printf("[set_light] 开灯打断关灯渐变: curr=%d -> target=%d\n",
|
||||||
e_printf("[set_light] 开灯渐变设置: brightness=0->%d, cct=%d\n",
|
fade_ctx.current_brightness, g_device_control.brightness_local);
|
||||||
g_device_control.brightness_local, fade_ctx.current_cct);
|
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;
|
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.fade_time = NORMAL_FADE_TIME; // 使用默认渐变时长
|
||||||
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 && !breath_active) {
|
||||||
cancel_current_light_fade();
|
cancel_current_light_fade();
|
||||||
}
|
}
|
||||||
calculate_fade_steps(&tmp_fade_ctx); // 复用原有计算流程
|
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; // 上电时,直接设置为默认渐变时长
|
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 (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) {
|
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;
|
||||||
}
|
}
|
||||||
@@ -1062,7 +1093,17 @@ int set_light(light_ctrl_source_e source,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case APP_CHANGE_LIGHT_BRIGHTNESS_CCT:
|
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,避免开灯时跳变
|
// 关灯状态:仅更新目标,不执行渐变,保持 current_brightness=0,避免开灯时跳变
|
||||||
if (g_device_control.colourMode == COLOUR_MODE_DUAL && cct_local_target >= 0) {
|
if (g_device_control.colourMode == COLOUR_MODE_DUAL && cct_local_target >= 0) {
|
||||||
g_device_control.cct_local = tmp_fade_ctx.target_cct;
|
g_device_control.cct_local = tmp_fade_ctx.target_cct;
|
||||||
|
|||||||
Reference in New Issue
Block a user