Files
AC7911BB_JL-AIBT-SoundBox/radar/radar_report_service.c
T

308 lines
5.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "system/includes.h"
#include "app_log.h"
#include "radar_report_service.h"
#include <string.h>
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,
&current
);
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,
&current,
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,
&current
);
if (ret != 0) {
return ret;
}
if (radar_report_business_equal(
&pending_snapshot,
&current
)) {
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;
}