#include "system/includes.h" #include "app_log.h" #include "radar_report_service.h" #include static struct radar_report_service_config report_config; static struct radar_report_snapshot pending_snapshot; static u8 report_service_initialized; static u8 report_pending; static u8 pending_reason; static u32 last_report_ms; /* * 判断两个快照在“manager meaningful-change 关注的字段”上 * 是否仍然一致。 * * 不比较 position: * 当前 manager 的 meaningful-change 本来就不以 XYZ 作为 * 上报变化条件,位置的持续抖动不应阻止 consumed baseline 推进。 * * 不比较 last_update_ms/sample_age_ms: * 它们是时间信息,不是业务状态本身。 */ static u8 radar_report_business_equal( const struct radar_report_snapshot *a, const struct radar_report_snapshot *b ) { if (!a || !b) { return 0; } if (a->sensor.presence != b->sensor.presence) { return 0; } if (a->sensor.motion != b->sensor.motion) { return 0; } if (a->sensor.sleep_state != b->sensor.sleep_state) { return 0; } if (a->sensor.body_movement != b->sensor.body_movement) { return 0; } if (a->sensor.distance_cm != b->sensor.distance_cm) { return 0; } if (a->sensor.heart_rate_x10 != b->sensor.heart_rate_x10) { return 0; } if (a->sensor.breath_rate_x10 != b->sensor.breath_rate_x10) { return 0; } if (a->sensor.abnormal_state != b->sensor.abnormal_state) { return 0; } return 1; } int radar_report_service_init( const struct radar_report_service_config *config ) { if (!config) { return -1; } if (config->max_age_ms == 0) { return -2; } memset( &pending_snapshot, 0, sizeof(pending_snapshot) ); report_config = *config; report_pending = 0; pending_reason = RADAR_REPORT_REASON_NONE; last_report_ms = 0; report_service_initialized = 1; APP_LOG( "[RADAR_REPORT] init success max_age=%u periodic=%u\n", report_config.max_age_ms, report_config.periodic_interval_ms ); return 0; } int radar_report_service_check( u32 now_ms, struct radar_report_snapshot *out, u8 *reason ) { int ret; u8 due_reason; struct radar_report_snapshot current; if (!out || !reason) { return -1; } if (!report_service_initialized) { return -2; } /* * 已经有一份等待真正发送成功的快照: * 始终返回同一份,避免发送失败重试时内容漂移。 */ if (report_pending) { memcpy( out, &pending_snapshot, sizeof(*out) ); *reason = pending_reason; return 1; } ret = radar_manager_get_report_snapshot( now_ms, report_config.max_age_ms, ¤t ); if (ret != 0) { return ret; } /* * 没有真正业务样本,或者样本已经过期: * 不把旧数据交给上层发送。 */ if (current.sensor.last_update_ms == 0 || !current.has_fresh_sample) { *reason = RADAR_REPORT_REASON_NONE; return 0; } due_reason = RADAR_REPORT_REASON_NONE; /* * 第一次成功上报之前, * 只要已经有 fresh sample 就先产生一份初始快照。 */ if (last_report_ms == 0) { due_reason = RADAR_REPORT_REASON_INITIAL; } else if (current.has_meaningful_change) { due_reason = RADAR_REPORT_REASON_CHANGE; } else if ( report_config.periodic_interval_ms != 0 && (u32)(now_ms - last_report_ms) >= report_config.periodic_interval_ms ) { due_reason = RADAR_REPORT_REASON_PERIODIC; } if (due_reason == RADAR_REPORT_REASON_NONE) { *reason = RADAR_REPORT_REASON_NONE; return 0; } memcpy( &pending_snapshot, ¤t, sizeof(pending_snapshot) ); report_pending = 1; pending_reason = due_reason; memcpy( out, &pending_snapshot, sizeof(*out) ); *reason = pending_reason; return 1; } int radar_report_service_mark_reported( u32 now_ms ) { int ret; struct radar_report_snapshot current; if (!report_service_initialized) { return -1; } if (!report_pending) { return 0; } /* * 发送成功后重新看一次 manager 当前状态。 * * 如果从生成 pending 到发送成功之间, * meaningful-change 相关业务字段没有变化, * 才安全推进 manager consumed baseline。 * * 如果已经变化,则不消费: * 下一次 check 会继续看到 CHANGE, * 防止“发送旧快照却把新状态标记为已消费”。 */ ret = radar_manager_get_report_snapshot( now_ms, report_config.max_age_ms, ¤t ); if (ret != 0) { return ret; } if (radar_report_business_equal( &pending_snapshot, ¤t )) { ret = radar_manager_mark_snapshot_consumed(); if (ret != 0) { return ret; } } else { APP_LOG( "[RADAR_REPORT] state changed while pending, " "keep manager change for next report\n" ); } last_report_ms = now_ms; report_pending = 0; pending_reason = RADAR_REPORT_REASON_NONE; memset( &pending_snapshot, 0, sizeof(pending_snapshot) ); return 0; }