[模块说明]
ems_redis的主要功能是订阅设备服务的数据，将其转化成北向点位和上报到emmsv2云平台的点位存入数据库
涉及的告警点位的告警编码、告警等级、告警原因编码等定义详见微盘 07产品研发资料 emmsv2资料->设计文档->EMS告警定义模板-导入.xlsx/EMS2.0告警管理系统需求规格书.docx

[配置文件]
ems_redis_cfg.json：进程配置文件
{   
    "snapshot_interval":60, //数据快照间隔
    "snapshot_enable":1,    //是否开启设备数据快照
    "devstatus_interval":60 //判断设备是否离线的间隔
}

devtype：设备类型配置文件，与ems_iec104中的定义一致，依次为 设备类型名称 设备类型别名 设备公共地址 遥测起始地址 遥测数量 遥信起始地址 遥信数量 modbus寄存器起始地址 modbus寄存器数量，以空格隔开
PCS PCS 2 16385 45 1 83 1 0

alarm_emms2.tag：告警映射表，将设备的告警点位转换为emms2云平台的告警，每一项依次为 设备TAG 告警编码 告警等级 告警原因编码
TAG_7149 35001 3 0
TAG_714A 35002 2 0
TAG_714B 35003 2 0
TAG_714D 35004 2 0

tag_emms2：目录。本地tag到emms2平台的tag的映射。目录下的文件以 设备类型_EMMS2.tag 命名。文件内容如下示例，每行为一组TAG映射，左边为本地tag，右边为到emms2平台的tag，以空格隔开
Online Online
TAG_2739 ActiveEnergy
TAG_2734 ReactiveEnergy
TAG_2716 AphaseVoltage

tag_modbus：目录。本地tag到redis数据库点位的映射，与ems_iec104中的定义一致。目录下的文件以 设备类型_MODBUS.tag 命名。文件内容如下示例，依次为 点位地址 点位TAG 数据类型 数据系数，以空格隔开
1 TAG_2716 2 0.1
2 TAG_2717 2 0.1
3 TAG_2718 2 0.1
4 TAG_2719 3 0.1
5 TAG_271A 3 0.1
6 TAG_271B 3 0.1

tag_smualarm：目录。本地tag到屏控告警tag的映射。目录下的文件以 设备类型_SMUALARM.tag 命名。文件内容如下示例，依次为 本地tag 屏控告警tag，以空格隔开
TAG_9C43 BmuHardwareFault
TAG_9C50 RackVolHighWarn1

[数据库定义]
devs：设备表。表名固定。使用redis的哈希表。以 设备SN 作为键，以 设备类型|设备公共地址内编号|设备公共地址 作为值。如218830000014_PCS1作为键,PCS|0|2作为值。
表用途：全局使用。mqtt收到topic为'ipc/[GW_SN]/[PORT]/device/[DEV_SN]/data_filtered/service/+'的设备数据后根据此表查找设备类型，进而存入设备数据表、告警表等。

realalarm：实时告警表。表名固定。使用redis的哈希表。以 告警编码|告警等级|实体列表 作为键, 以 告警原因编码|告警发生时间 作为值。如 35001|2|218830000014_PCS1 作为键， 0|1731060248 作为值。这样设计的原因是将 告警编码|告警等级|实体列表 视为实时告警的唯一标识，从而在告警发生和清除时执行实时告警表的插入和删除操作。
表用途：云平台及屏控使用。云平台及屏控需要获取当前仍未消除的所有告警。

alarm-20240913：历史告警表。表名为alarm-yyyymmdd(4位年份+2位月份+2位日期)。使用redis的有序集。以 告警发生时间 作为有序集中条目的分数，以 告警编码|告警原因编码|告警等级|告警发生时间|实体列表 作为有序集中条目的值。如 1731060248 作为分数， 35001|0|1|1731060248|218830000014_PCS1 作为值。
表用途：仅云平台使用。

218830000014_PCS1：设备实时数据表。表名为DEVSN。使用redis的有序集。以 上报到emms2平台的tag的分数 作为有序集中条目的分数，以 tag名|tag值 作为有序集中的值。 如 5 作为分数， AphaseVoltage|230.1 作为值。
表用途：云平台及屏控使用

218830000014_Rack1_1_CELL：电芯设备实时数据表。表名为簇SN_CELL。使用redis的有序集。以 上报到emms2平台的tag的分数 作为有序集中条目的分数，以 tag名|tag值 作为有序集中的值。如 5 作为分数， CV5|2307 作为值。
表用途：云平台及屏控使用

218830000014_PCS1_alarm：设备实时告警表。表名为DEVSN_alarm。使用redis的有序集。以 上报到屏控的告警tag的分数 作为有序集中条目的分数，以 上报到屏控的告警tag|告警值 作为有序集中的值。如 1 作为分数， BmuHardwareFault|1 作为值。
表用途：仅屏控使用

218830000014_Rack1_1_CELL_alarm：电芯设备实时告警表。表名为簇SN_CELL_alarm。使用redis的有序集。以 上报到屏控的告警tag的分数 作为有序集中条目的分数，以 上报到屏控的告警tag|告警值 作为有序集中的值。电芯数据一般无告警点位，此表暂不使用。
表用途：暂不使用

218830000014_PCS1-20240913：设备历史数据表。表名为DEVSN-yyyymmdd。使用redis的有序集。开启数据快照机制后按照数据快照间隔写入此表。以 快照时间 作为分数，以 tag1的值|tag2的值|...|tagN的值 作为有序集中的值，这里tag1到tagN是按照设备实时数据表中tag分数的顺序。如 130610 作为有序集中的分数，以 1|0.1|0.2|...|0|1作为有序集中的值。
表用途：暂未使用，按原定设计仅云平台使用

218830000014_Rack1_1_CELL-20240913：电芯历史数据表。表名为簇SN_CELL-yyyymmdd。使用redis的有序集。开启数据快照机制后按照数据快照间隔将电芯数据写入此表。以 快照时间 作为分数，以 tag1的值|tag2的值|...|tagN的值 作为有序集中的值，这里tag1到tagN是按照电芯设备实时数据表中tag分数的顺序。如 130610 作为有序集中的分数，以 2317|2315|2409|...|24.8|24.6作为有序集中的值。
表用途：暂未使用，按原定设计仅云平台使用

218830000014_gridmeter.AphaseVoltage-2024-09-13：电表单独点位历史数据表。表名为电表SN.点位tag-yyyy-mm-dd。使用redis的有序集。以 hhmmss 作为分数，表示2位小时2位分钟2位秒数，以 值|秒时间戳 作为有序集的值。如 130610 作为分数，以 230.1|1732100109 作为有序集的值。
表用途：仅屏控使用

2_modbus：北向设备数据表。表名为设备公共地址_modbus。使用redis的有序集。以 寄存器地址 作为分数，以 数据值|数据类型|tag|时间戳 作为有序集的值。如 29 作为地址，以 230.1|6|TAG_2739|1732100109 作为有序集的值。
表用途：仅北向使用

[整体设计]
此模块部分基于ems_iec104模块，同时为适配emms2平台及屏控对数据库定义及逻辑功能进行了较大的调整。按照原功能设计，适配了云平台、屏控及modbus北向。

程序启动后，加载所有配置文件，加载/app/node/nodes_cfg.json生成设备表，连接redis数据库，创建定时器处理定时任务，建立到内部mqtt broker的连接并订阅'ipc/+/+/device/+/data_filtered/service/+'的数据

MQTT订阅的回调函数：ems_redis_mqtt_handle_recv_msg。若topic为ipcalarm，按照和ems_ctrl定义的格式此为EMS告警信息，将其存入实时告警列表和历史告警列表；否则若topic为service，此为设备数据，遍历数据中每个tag，查找该tag的北向点位配置，若值发生变化则更新北向设备数据表。再查找该tag的屏控告警tag配置，若有则更新设备实时告警表。再查找该tag的emms2云平台tag配置，若有对应的云平台tag则更新设备实时数据表，若没有再查找该tag是否在全局告警表中，若是则生成告警信号到实时告警表和历史告警表。

定时任务：先检查设备在线状态。若开启设备数据快照机制，首先若在凌晨00：00则删除电表单独点位历史数据表两天前的数据(屏控只需要不超过两天的历史数据)，然后再遍历设备表，对于每个设备，遍历实时数据表，生成当前时间的设备数据记录并将其加入设备历史数据表，对于簇设备同步将电芯数据加入电芯历史数据表，对于电表设备将电表设备的每个点位加入电表单独点位历史数据表。