【实战分享】智慧养老系统核心模块设计 —— 健康监测与自动紧急呼叫

最近刚完成了我的智慧养老系统的一个核心功能模块:个性化健康阈值配置 + 自动紧急呼叫。这是我养老系统的其中一个功能,项目刚做完,当前还未在社区应用。本篇把设计思路、关键数据表和实现要点整理成一篇实战笔记,便于在 CSDN 分享与复用。


目录

一、为什么要做这个模块

二、架构概览

三、设计要点一:个性化健康阈值

[3.1 设计原则](#3.1 设计原则)

[3.2 数据库表(核心)](#3.2 数据库表(核心))

[3.3 默认值参考(可直接采用)](#3.3 默认值参考(可直接采用))

[四、判断逻辑(后端核心实现 ------ Spring Boot)](#四、判断逻辑(后端核心实现 —— Spring Boot))

小细节:阈值变更要通知

[五、设计要点二:自动紧急呼叫(Auto Call)](#五、设计要点二:自动紧急呼叫(Auto Call))

[5.1 触发方式](#5.1 触发方式)

[5.2 流程要点](#5.2 流程要点)

[5.3 呼叫记录表(示例)](#5.3 呼叫记录表(示例))

[5.4 后端自动呼叫实现要点(核心代码节选)](#5.4 后端自动呼叫实现要点(核心代码节选))

六、前端接听

七、我在实现中学到的实战经验

八、后续优化方向

九、结语


一、为什么要做这个模块

很多独居或行动不便的老人,日常体征(心率、血压、血氧、血糖)会有个体差异。统一医学标准会导致大量误报或漏报,影响家庭和护理团队的信任。

我的目标:

  • 支持个性化阈值(老人/家属/医生可调整)

  • 异常自动分级(预警 / 紧急)

  • 紧急情况下能自动发起呼叫并通知家属/社区人员

  • 保证系统稳定:异步、并发安全、状态一致性


二、架构概览

流程简要:

复制代码
数据采集(手环/MQTT/蓝牙) → 阈值判断(个性化) → 预警/紧急判定 → 告警记录 → 自动/手动呼叫 → 实时通知(WebSocket) → 视频/电话接入

三、设计要点一:个性化健康阈值

3.1 设计原则

  • 医学参考值作为默认值

  • 支持用户/家属/医生覆盖默认值(有记录与审计)

  • 修改阈值须触发通知(避免纠纷)

3.2 数据库表(核心)

user_health_config(每人一条)

复制代码
CREATE TABLE `user_health_config` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `user_id` bigint NOT NULL COMMENT '用户ID',
  `hr_min` int DEFAULT 60 COMMENT '心率下限',
  `hr_max` int DEFAULT 100 COMMENT '心率上限',
  `bo_min` int DEFAULT 95 COMMENT '血氧下限',
  `bo_warning` int DEFAULT 98 COMMENT '血氧预警值',
  `bp_sys_min` int DEFAULT 90 COMMENT '收缩压下限',
  `bp_sys_max` int DEFAULT 140 COMMENT '收缩压上限',
  `bp_sys_emergency` int DEFAULT 180 COMMENT '收缩压紧急值',
  `bp_dia_min` int DEFAULT 60 COMMENT '舒张压下限',
  `bp_dia_max` int DEFAULT 90 COMMENT '舒张压上限',
  `bp_dia_emergency` int DEFAULT 120 COMMENT '舒张压紧急值',
  `bg_fasting_min` float DEFAULT 3.9 COMMENT '空腹血糖下限',
  `bg_fasting_max` float DEFAULT 6.1 COMMENT '空腹血糖上限',
  `step_target` int DEFAULT 6000 COMMENT '步数目标',
  `sleep_target` float DEFAULT 7.5 COMMENT '睡眠(小时)',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_user_id` (`user_id`)
);

3.3 默认值参考(可直接采用)

  • 心率:60--100 次/分(静息)

  • 血氧:95%(低于 95% 预警,<90% 紧急)

  • 收缩压:90--140 mmHg(>180 紧急)

  • 舒张压:60--90 mmHg(>120 紧急)

  • 空腹血糖:3.9--6.1 mmol/L


四、判断逻辑(后端核心实现 ------ Spring Boot)

我把阈值判断封装到 HealthMonitoringService,返回等级:0-正常, 1-异常(预警), 2-紧急(需呼叫)

关键代码(节选):

复制代码
@Service
public class HealthMonitoringServiceImpl implements HealthMonitoringService {

    @Autowired
    private UserHealthConfigMapper userHealthConfigMapper;

    private int checkVitalSignStatus(Long userId, String type, Float value1, Float value2) {
        UserHealthConfig config = userHealthConfigMapper.selectByUserId(userId);
        if (config == null) {
            config = createDefaultHealthConfig(userId);
        }
        switch (type) {
            case "BP":
                return checkBloodPressureStatus(config, value1, value2);
            case "HR":
                return checkHeartRateStatus(config, value1);
            case "BO":
                return checkBloodOxygenStatus(config, value1);
            case "BG":
                return checkBloodGlucoseStatus(config, value1);
            default:
                return 0;
        }
    }

    // 血压判定示例
    private int checkBloodPressureStatus(UserHealthConfig config, Float systolic, Float diastolic) {
        if (systolic > config.getBpSysEmergency() || diastolic > config.getBpDiaEmergency()) {
            return 2;
        }
        if (systolic > config.getBpSysMax() || diastolic > config.getBpDiaMax()
                || systolic < config.getBpSysMin() || diastolic < config.getBpDiaMin()) {
            return 1;
        }
        return 0;
    }
    // 其他判定略...
}
小细节:阈值变更要通知

当阈值由家属或老人修改时,会发送消息通知对方并写入 health_config_log 做审计。


五、设计要点二:自动紧急呼叫(Auto Call)

5.1 触发方式

  • 手动:老人点击"一键求助"

  • 自动:来自健康监测模块判定为紧急(alertLevel=2)

5.2 流程要点

  1. 生成呼叫记录(emergency_call_record)并落库

  2. 拉取紧急联系人(优先家属,再社区工作人员)

  3. 顺序依次发起通知(避免多人同时骚扰老人)------每位等待一定超时时间(示例:30s)

  4. 使用并发安全结构(ConcurrentHashMap)维护正在进行的呼叫上下文

  5. 使用异步线程池执行呼叫流程,避免阻塞主线程

  6. 状态在内存与数据库同时更新,保证一致性

5.3 呼叫记录表(示例)

复制代码
CREATE TABLE `emergency_call_record` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `elder_user_id` bigint NOT NULL,
  `call_type` varchar(20),
  `alert_type` varchar(20),
  `alert_level` int,
  `alert_value` varchar(50),
  `status` varchar(20),
  `answered_by_user_id` bigint,
  `start_time` datetime,
  `end_time` datetime,
  PRIMARY KEY (`id`)
);

5.4 后端自动呼叫实现要点(核心代码节选)

复制代码
@Service
public class AutoEmergencyCallServiceImpl implements AutoEmergencyCallService {
    private final Map<Long, AutoCallContext> autoCallContexts = new ConcurrentHashMap<>();
    private final ExecutorService executorService = Executors.newCachedThreadPool();

    @Override
    public Map<String, Object> triggerAutoEmergencyCall(Long userId, String alertType, Float value1, Integer alertLevel) {
        EmergencyCallRecord record = new EmergencyCallRecord();
        record.setElderUserId(userId);
        record.setCallType("auto");
        record.setAlertType(alertType);
        record.setAlertLevel(alertLevel);
        record.setAlertValue(String.valueOf(value1));
        record.setStatus("calling");
        record.setStartTime(new Date());
        emergencyCallRecordMapper.insert(record);

        List<EmergencyContact> contacts = emergencyContactMapper.selectByUserId(userId);
        // family first -> staff next
        List<EmergencyContact> allContacts = mergeContacts(contacts);

        AutoCallContext context = new AutoCallContext();
        context.userId = userId;
        context.callRecord = record;
        context.contacts = allContacts;
        autoCallContexts.put(userId, context);

        executorService.submit(() -> performAutoCall(context));
        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("msg", "自动紧急呼叫已触发");
        result.put("callRecordId", record.getId());
        return result;
    }
    // performAutoCall / answerAutoCall / sendCallNotification 等方法见上文逻辑
}

六、前端接听

前端通过 WebSocket 接收 EMERGENCY_CALL_NOTIFICATION 通知,弹出呼叫窗口,用户点击"接听"后调用后端 /api/auto-emergency/answer 接口并跳转到视频通话页(示例代码如下)。

复制代码
websocket.onmessage = function(event) {
    const data = JSON.parse(event.data);
    if (data.msgType === 'EMERGENCY_CALL_NOTIFICATION') {
        showCallUI(data);
    }
};

async function acceptCall(data) {
    await axios.post('/api/auto-emergency/answer', {
        callRecordId: data.callRecordId,
        answeredByUserId: currentUser.id
    });
    window.location.href = `./video-call.html?callRecordId=${data.callRecordId}&elderUserId=${data.elderUserId}`;
}

七、我在实现中学到的实战经验

  • 默认配置 + 个性化覆盖 是减少误报的关键

  • 并发控制(ConcurrentHashMap)避免重复通知与状态竞态

  • 异步执行(线程池)确保接口响应及时

  • 数据库+内存双写 保证呼叫状态的一致性与可审计性

  • 阈值修改要记录日志并通知相关人员,避免责任不明


八、后续优化方向

  • 接入跌倒检测器、智能药盒,扩展触发场景

  • 引入 AI 语音助手,支持老人语音求助

  • 对接社区医院,实现医生端直连推送

  • 增强多模态报警(短信 + 电话 + APP 推送 + 语音)


九、结语

完成这个从 0 到 1 的项目,对我而言既是一次技术练习,也是一次把业务场景落地的实践:在实现功能的过程中我遇到了并发、异步、实时通信等真实问题,也通过查阅资料与反复调试逐步解决。

相关推荐
骄马之死15 小时前
SpringMVC + SpringBoot 核心知识点总结
java·spring boot·后端
AOwhisky16 小时前
MySQL 学习笔记(第四期):SQL 语言之多表查询
linux·运维·网络·数据库·笔记·学习·mysql
GoGeekBaird16 小时前
Anthropic技能"(Skills)的经验分享
后端
小红卒16 小时前
mysql之udf提权
数据库·mysql·网络安全
王码码203516 小时前
多台服务器怎么统一看状态?Beszel 轻量监控,搭起来不费事
运维·服务器·后端·安全·阿里云·接口·web
郑洁文17 小时前
基于Spring Boot的流浪动物救助网站
java·spring boot·后端·毕设·流浪动物救助
螺丝钉code17 小时前
JAVA项目 Claude code CLAUDE.md 到底应该怎么写
java·人工智能·claude code
指令集梦境18 小时前
Cursor + Spring Boot实战:从零写一个RESTful API
spring boot·后端·restful
南极企鹅18 小时前
MySQL的两大支柱:undo Log&redo log
数据库·mysql·oracle
摇滚侠18 小时前
Maven 入门+高深 单一架构案例 54-59
java·架构·maven·intellij-idea