Initial commit of akmon project

This commit is contained in:
2026-01-20 08:04:15 +08:00
commit 77a2bab985
1309 changed files with 343305 additions and 0 deletions

View File

@@ -0,0 +1,184 @@
// 告警消息解析工具
// 参考 doc_eldercare/alert.md 设计
export type AlertParseResult {
type : string; // 解析后的类型,如 'SOS', '健康数据', '定位', '通知', '计步', '围栏', '语音', '睡眠', '手表', '未知'
title : string; // 简要标题
content : string; // 展示内容
time ?: string; // 时间
raw : any; // 原始数据
level ?: 'normal' | 'warn' | 'danger'; // 可选,紧急等级
mid ?: string; // 设备ID
smid ?: string; // 消息ID
extra ?: UTSJSONObject; // 其它解析字段
}
/**
* 解析推送消息主入口
* @param msg 传入ps_push_msg_raw的raw_data对象或完整record
*/
export const parseAlertMessage = (msg : UTSJSONObject) : AlertParseResult => {
// 兼容 record/raw_data
let data : UTSJSONObject = msg.getJSON('raw_data') ?? {};
const pushType = data.getNumber('pushType') ?? 0;
const action = data.getNumber('actionRaw') ?? 0;
const time = data.getString('Time') ?? data.getString('time') ?? data.getString('created_at') ?? '';
// 1. SOS
if (pushType === 1) {
return {
type: 'SOS',
title: 'SOS求救',
content: `${data.getString('Name') ?? ''}(${data.getString('MID') ?? ''}) 向您发出求救`,
time,
raw: msg,
level: 'danger',
mid: data.getString('MID') ?? data.getString('mid'),
smid: data.getString('SMID') ?? data.getString('smid'),
extra: { lon: data.getNumber('Lon'), lat: data.getNumber('Lat'), address: data.getString('Str') }
};
}
// 2. 健康数据
if (pushType === 2) {
let arr : string[] = [];
const h = data.getNumber('H');
const o = data.getNumber('O');
const w = data.getNumber('W');
const x = data.getNumber('X');
const y = data.getNumber('Y');
if (h != null) arr.push(`心率:${h}`);
if (o != null) arr.push(`血氧:${o}`);
if (w != null) arr.push(`体温:${w}`);
if (x != null) arr.push(`高压:${x}`);
if (y != null) arr.push(`低压:${y}`);
return {
type: '健康数据',
title: '健康数据推送',
content: arr.length > 0 ? arr.join('') : JSON.stringify(data),
time,
raw: msg,
level: 'normal',
mid: data.getString('MID') ?? data.getString('mid'),
smid: data.getString('SMID') ?? data.getString('smid'),
extra: { mid: data.getString('MID') ?? data.getString('mid') }
};
}
// 3. 定位
if (pushType === 3) {
return {
type: '定位',
title: '定位推送',
content: `${data.getString('Pro') ?? ''}${data.getString('City') ?? ''}${data.getString('Dist') ?? ''}${data.getString('Str') ?? ''} (${data.getNumber('Lon')},${data.getNumber('Lat')})`,
time: data.getString('CT') ?? data.getString('UT') ?? time,
raw: msg,
level: 'normal',
mid: data.getString('MID') ?? data.getString('mid'),
smid: data.getString('SMID') ?? data.getString('smid'),
extra: { lon: data.getNumber('Lon'), lat: data.getNumber('Lat') }
};
}
// 4. 通知
if (pushType === 4) {
const actionMapObj = {
'-1': '设备在线离线', '4': '围栏内停留', '5': '离开围栏', '6': '进入围栏', '9': '低电报警', '11': '跌倒报警', '23': '高温报警',
'26': '断开wifi', '28': 'wifi离线', '36': '防盗报警', '42': '布防告警', '44': '在家布防告警', '7': 'SOS报警', '10': '摘除报警',
'22': '低温报警', '24': '更换SIM卡', '27': '连接wifi', '35': '社区养老报警', '37': '状态通知', '43': '撤防告警', '45': '八件套报警',
'47': 'wifi不一致报警', '49': '红外报警', '50': 'NB按键报警', '51': 'NB防拆报警', '52': 'NB报警复位', '61': 'NB设备报警',
'63': '人体存在报警', '67': 'NB测试报警', '85': '网关上线', '87': '删除子设备', '114': '烟感/气感/门磁事件', '116': 'SCA事件',
'118': '防跌倒雷达', '121': '智能胸牌告警', '84': '网关离线', '86': '添加子设备', '113': '门磁事件', '115': '拉绳SOS',
'117': '4G视频门磁', '119': 'd5网关子设备报警', '122': 'NB温湿度报警', '123': '气感报警', '125': '水浸报警', '127': '跌倒报警',
'129': '燃气报警', '131': '对讲SOS', '134': 'AI智能报警', '124': '烟感报警', '126': '摄像头报警', '128': '井盖报警',
'130': '红外报警', '132': 'ZML_SOS报警', '200': '设备信息变更'
};
let actionStr:string = actionMapObj.getString(action.toString()) ?? `通知类型:${action}`;
return {
type: '通知',
title: actionStr,
content: `${data.getString('Name') ?? ''} ${data.getString('Content') ?? ''}`.trim() ?? JSON.stringify(data),
time,
raw: msg,
level: (action === 9 || action === 11 || action === 23 || action === 7) ? 'danger' : 'warn',
mid: data.getString('MID') ?? data.getString('mid'),
smid: data.getString('SMID') ?? data.getString('smid'),
extra: { action }
};
}
// 5. 计步/翻转pushType=5 或有 Step/Roll 字段)
if (pushType === 6) {
return {
type: '计步',
title: '计步/翻转',
content: `步数:${data.getNumber('Step') ?? '-'} 翻转:${data.getNumber('Roll') ?? '-'}`,
time,
raw: msg,
level: 'normal',
mid: data.getString('MID') ?? data.getString('mid'),
smid: data.getString('SMID') ?? data.getString('smid'),
extra: { step: data.getNumber('Step'), roll: data.getNumber('Roll'), mid: data.getString('MID') ?? data.getString('mid'), smid: data.getString('SMID') ?? data.getString('smid') }
};
}
// 6. 围栏(进出围栏、进入围栏、离开围栏等)
if (pushType === 7 || (pushType === 4 && (action === 6 || action === 5))) {
let actionStr = '';
if (pushType === 4) {
if (action === 6) actionStr = '进入围栏';
else if (action === 5) actionStr = '离开围栏';
else actionStr = '围栏事件';
} else {
actionStr = '进出围栏';
}
return {
type: '围栏',
title: actionStr,
content: data.getString('Content') ?? JSON.stringify(data),
time,
raw: msg,
level: 'warn',
mid: data.getString('MID') ?? data.getString('mid'),
smid: data.getString('SMID') ?? data.getString('smid'),
extra: { lon: data.getNumber('Lon'), lat: data.getNumber('Lat'), action }
};
}
// 7. 微聊语音
if (pushType === 8) {
let msgType = data.getNumber('msgType') ?? data.getNumber('MType') ?? 0;
let typeStr = msgType === 2 ? '语音' : '文字';
return {
type: '微聊',
title: `微聊${typeStr}消息`,
content: data.getString('content') ?? JSON.stringify(data),
time,
raw: msg,
level: 'normal',
mid: data.getString('MID') ?? data.getString('mid'),
smid: data.getString('SMID') ?? data.getString('smid'),
extra: { msgType }
};
}
// 8. 睡眠带报警
if (pushType === 9) {
return {
type: '睡眠报警',
title: '睡眠带报警',
content: data.getString('Content') ?? JSON.stringify(data),
time,
raw: msg,
level: 'warn',
mid: data.getString('MID') ?? data.getString('mid'),
smid: data.getString('SMID') ?? data.getString('smid'),
extra: { action }
};
}
// 9. 其它类型可继续补充...
// 默认
return {
type: '未知',
title: '未知推送',
content: JSON.stringify(data),
time,
raw: msg,
mid: data.getString('MID') ?? data.getString('mid'),
smid: data.getString('SMID') ?? data.getString('smid')
};
};