#ifndef __EMS_REDIS_H__
#define __EMS_REDIS_H__

#include <string.h>
#include <syslog.h>
#include <pthread.h>
#include "ipc_session.h"
#include "dy_utils/uthash/uthash.h"
#include "dy_utils/dy_common.h"
#include "dy_utils/dy_pp.h"
#include "dy_utils/dy_ipc.h"
#include "dy_utils/dy_ds.h"
#include "dy_utils/period_service.h"
#include "lnxall_ubuslog.h"
#include <hiredis/hiredis.h>

//确定北向通信的协议
#undef DB_IEC104 //支持IEC104北向通信
#define DB_MODBUS  //支持modbus北向通信

#undef FEATURE_MQTT //支持MQTT，redis数据库设备数据表定义与IEC104一致

#define MAX(a,b) (((a) > (b))? (a) : (b))

#define DEV_TAG "/app/config/ems_redis/tag/"
#define DEV_TAG_MODBUS "/app/config/ems_redis/tag_modbus/"
#define DEV_TAG_ALARM "/app/config/ems_redis/alarm_emms2.tag"
#define DEV_TAG_EMMS2 "/app/config/ems_redis/tag_emms2/"
#define DEV_TAG_SMUALARM "/app/config/ems_redis/tag_smualarm/"
#define DEV_TYPE_PATH "/app/config/ems_redis/devtype"
#define EMS_REDIS_CFG_PATH "/app/config/ems_redis/ems_redis_cfg.json"
#define NODE_CFG_PATH "/app/node/nodes_cfg.json"
#define ADDR_TAG_PATH_LEN 64

#define DEV_SN_LEN 32
#define DEV_GW_LEN 16
#define DEV_TYPE_LENGTH 12
#define DEV_TYPE_MODBUS_LENGTH 20
#define DEV_NAME_LENGTH 32
#define CMD_MAX_LENGTH 256
#define TAG_MAX_LENGTH 32
#define ADD_INFO_LENGTH 32
#define JSON_MAX_LENGTH 4096
#define REDIS_SERVER_IP "127.0.0.1"
#define REDIS_SERVER_PORT 6379
#define DEVDATA_MAX_LENGTH 8192
#define DEVDATA_CMD_LENGTH 8320

#define TOPIC_SETEMS "/setems"
#define TOPIC_SERVICE "/service"
#define TOPIC_IPCALARM "/ipcalarm"

#define CELL_VOLT "CellVol"
#define CELL_TEMP "CellTemp"

#define REDIS_DATA_U8 1
#define REDIS_DATA_U16 2
#define REDIS_DATA_I16 3
#define REDIS_DATA_U32 4
#define REDIS_DATA_I32 5
#define REDIS_DATA_F32 6
#define REDIS_REAL_ALARM_TABLE "realalarm"

#define MAX_DEV_NUM 128

//告警等级
typedef enum _alarm_severity
{
    alarm_clear = -1,   
    alram_warning,
    alarm_minor,
    alarm_major,
    alarm_critical,
} alarm_severity;

//告警tag配置，通过哈希表存储，以tag作为键
typedef struct _alarmtag_entry
{
    char tag[TAG_MAX_LENGTH];   //EMS1.0中该告警或故障的TAG
    int alarmcode;              //告警编码
    alarm_severity severity;    //告警等级
    int reasoncode;             //告警原因码
    UT_hash_handle hh;
}alarmtag_entry_t;

//设备tag配置，通过哈希表存储，以tag作为键
typedef struct _tagconf_entry
{
    char tag[TAG_MAX_LENGTH];   //EMS1.0中该设备数据的TAG
    int addr;                   //北向点位中该数据的地址
    ushort dtype;               //北向点位中该数据的类型，为REDIS_DATA_U8到REDIS_DATA_F32的值
    float k;                    //北向点位中该数据的系数
    char emmstag[TAG_MAX_LENGTH];   //该数据对应的到EMMS平台的TAG
    ushort emmsscore;               //该数据在设备实时数据表中的分数（用于有序集）
    char smualarmtag[TAG_MAX_LENGTH];   //该数据对应的到屏控的告警的tag
    ushort smualarmscore;           //该数据在设备实时告警表中的分数（用于有序集）
    UT_hash_handle hh;
} tagconf_entry_t;

//设备类型配置，通过哈希表存储，以dev_type作为键
typedef struct _devtype_entry
{
    char dev_type[DEV_TYPE_LENGTH];    //设备类型
    char dev_type_alias[DEV_TYPE_LENGTH]; //设备类型别名，来自平台
    int common_addr;                    //设备公共地址
    int num;                            //设备在公共地址中的编号
    int startaddr1;                     //遥测量起始地址
    int step1;                          //遥测量步长
    int startaddr2;                     //遥信量起始地址
    int step2;                          //遥信量步长
    int startModbus;                    //MobBus起始地址
    int stepModbus;                     //ModBus步长
    tagconf_entry_t *tagsconf;      //该devtype的tag配置
    ushort tagscore;                //tag存入有序集的最大分数
    ushort alarmscore;           //tag存入smu告警的最大分数
    int tagnum;
    UT_hash_handle hh;
} devtype_entry_t;

//存储单个设备
typedef struct _dev_entry
{
    char devsn[DEV_SN_LEN];         //设备SN
    char devtype[DEV_TYPE_LENGTH];  //设备类型
    int dev_no;                     //设备公共地址内编号
    int common_addr;                //设备公共地址
    time_t lastmsgtime;             //最近一次订阅到该设备数据的时间
    unsigned char online;           //设备在线状态
} dev_entry_t;

typedef struct _dev_table
{
    dev_entry_t devtab[MAX_DEV_NUM];    //设备表
    int devcount;                       //设备数量
} dev_table_t;

typedef struct _ems_redis_var_s
{
    ipc_session_t *session;
    int mi;
    char sn_str[SN_MAX_LEN];
    uint snapshot_score; //与数据快照功能相关的有序集中使用的分数
    int ems_status_timer;  
    int snapshot_interval; //数据快照间隔，单位秒
    int snapshot_enable;   //是否开启数据快照功能
    int devstatus_interval; //设备状态更新间隔，单位秒
    int dev_index;
    dev_table_t dev_table;  //设备表
    redisContext *context;
    redisContext *snapcontext;  
    devtype_entry_t *devtypes; //所有设备类型配置
    ushort dtypenum; //所有设备类型数量
    alarmtag_entry_t *alarmconf;    //所有告警类型配置
} ems_redis_var_t;

#endif //__EMS_REDIS_H__