
#ifndef MQTT_EMMS2_CLOUD_NORTTH__
#define MQTT_EMMS2_CLOUD_NORTTH__


#include "mqtt_session.h"
#include "../tag.h"
#include "sqlite3.h"
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <dy_utils/lnxall_buffer.h>
#include "../mqtt_dp/mqtt_dp.h"

#define EMMS2_ALARM_BY_CB 0 //使用回调函数检擦告警
#define EMMS2_MAX_BASE_LEN 256
#define EMMS2_MAX_BASE_SHORT_LEN 64
#define EMMS2_KEEP_ALIVE_MAX  10
#define EMMS2_DEFAULT_IPC_QOS 0

#define EMMS2_BROKER_ADDR "emsmqtt.lnxall.com"
#define EMMS2_BROKER_PORT 60007
#define EMMS2_BROKER_USER "localuser"
#define EMMS2_BROKER_PASS "dywl@galaxy"

#define EMMS2_TLS_CAFILE   "/app/cert/mqtt_server_cacert.pem"
#define EMMS2_TLS_CERTFILE "/app/cert/mqtt_client_cert.pem"
#define EMMS2_TLS_KEYFILE  "/app/cert/mqtt_client_key.pem"

#define PATH_NET_STATUS "/opt/lnxall_app/lib/dyiot/bin/fetch_port_status.sh"

#define EMMS2_TAGBLE_NAME    "emms2_history"
#define EMMS2_HISTORY_DB_PRE "/app/database/emms2_history"

#define SECONDS_IN_DAY 86400
#define HISTORY_DATA_HOLD_DAYS 30

#define MAX_MQTT_EMMS2_DEV_NUM   CHANNEL_DEVS_MAX
#define MAX_MQTT_EMMS2_BLOCK_NUM CHANNEL_DEVS_MAX
#define MAX_MQTT_EMMS2_SUB_NUM   512

#define MAX_PUB_TAG_NUM 512

#define EMMS2_TAG_EX_PR_INDEX       1 //tag中扩展指针数组的索引
#define EMMS2_TAG_ALARM_EX_PR_INDEX 2 //告警指针位置

#define DEVICE_MAX_TAG_NUM 1024

#define LZ4_DEFAULT_BUFFER_MULTIPLIER 10   // 默认缓冲区倍数
#define LZ4_MAX_BUFFER_MULTIPLIER 1000      // 最大缓冲区倍数

#define MQTT_EMMS2_MAX_THREAD_NUM 4                                // 最大MQTT并发线程数
#define MQTT_EMMS2_CONFIG_PATH    "/app/config/emms2_mqtt.json"    // MQTT_EMMS2配置文件路径
#define MQTT_EMMS2_STATION_ID     "mqtt_emms2"                     // MQTT配置文件中的 key, 云平台
#define MQTT_STACTRL_CONFIG_PATH  "/app/config/stactrl_mqtt.json" // MQTT_STACTRL配置文件路径
#define MQTT_STACTRL_STATION_ID   "mqtt_stactrl"                   // MQTT配置文件中的 key, 站控

#define MQTT_PUB_DEV_LIST_CONFIG "/app/config/mqtt_pub_dev_list.json" // MQTT_PUB_DEV_LIST配置文件路径
#define MQTT_CHANGE_REPORT_LIST "/app/config/change_report_tag_list.json"  //MQTT变化上报点位列表

/***
 * - 控制器数据上报
- 告警上报
- 心跳
-登录
*/
#define TYPE_POST       "LcPost"// ↑
/*
上报回应*/
#define TYPE_POST_RESP  "LcPostResp"//↓

/**
 * 
 * ### 平台召测,设备响应
- 设备配置表查询
- 控制器参数查询
- 告警同步
*/
#define TYPE_GET       "Get" //↓

/**
 * 
 *  平台设置,设备应答
*/
#define TYPE_GET_RESP      "GetResp" // ↑

/**
 * 
控制指令下发
*/
#define TYPE_SET       "Set" //↓

#define TYPE_SET_RESP   "SetResp" // ↑

// Set 功能设置BMS上下高压，这个点不在write_reg里，做特殊处理
// function FUNCTION_SUBTELECONTROL
#define TAG_BMS_SET_CONNECT "BmsSetConnect"

#define FUNCTION_ID_LOGIN       "Login"
#define FUNCTION_HEARTBEAT      "HeartBeat"
#define FUNCTION_DEVINFO        "DeviceInfo"
#define FUNCTION_SCHEDULE       "Schedule"
#define FUNCTION_TELEMETRY      "Telemetry"
#define FUNCTION_TELECONTROL    "Telecontrol"
#define FUNCTION_SUBTELEMETRY   "SubTelemetry"
#define FUNCTION_SUBTELECONTROL "SubTelecontrol"
#define FUNCTION_CONTINUE_DATA  "ContinueData"
#define FUNCTION_ALARM          "Alarm"
#define FUNCTION_ALL_ALARM      "AllAlarm"
#define FUNCTION_ALARM_DISABLE  "AlarmDisable"
#define FUNCTION_HISTORY        "History"
#define FUNCTION_LOG            "Log"
#define FUNCTION_TEMPLATE       "Template"
#define FUNCTION_ALARMFILE      "Alarmfile"
#define FUNCTION_ACCIDENT_CFG   "AccidentConfig"
#define FUNCTION_ACCIDENT_CREATE           "AccidentCreateUpload"
#define FUNCTION_ACCIDENT_UPLOAD_INFO      "AccidentUploadInfo"
#define FUNCTION_ACCIDENT_FINISH_UPLOAD    "AccidentFinishUpload"
#define FUNCTION_ACCIDENT_CLEAR            "AccidentClear"
#define FUNCTION_GRID_GROUP            "GridGroup"

#define FUNCTION_RATE_SET            "SetRate"
#define FUNCTION_RATE_GET            "GetMultiRate"

#define FUNCTION_PORXYFRPC      "ProxyFrpc"
#define FUNCTION_OTAUPDATE      "OtaUpdate"
#define FUNCTION_CONFIG         "Config"
#define FUNCTION_MONITOR        "Monitor"
#define FUNCTION_LC_INFO        "LcInfo"
#define FUNCTION_UPGRADE        "Upgrade"
#define FUNCTION_PROGRESS       "Progress"
#define FUNCTION_CABINETINFO    "CabinetInfo"
#define HEARTBEAT_INTERVAL  60
#define REPORT_ALARM_INTERVAL  3600

#define DEFAULT_PUB_INTERVAL_TIME  5
#define DEFAULT_PUB_TIME_OUT  60

#define FUNCTION_SUB_DATA       "DashboardData"
#define FUNCTION_SUB_CTRL       "DashboardCtrl"

#define FUNCTION_RATE_SET            "SetRate"
#define FUNCTION_RATE_GET            "GetMultiRate"

#define MQTT_OFFLINE_DB_MAX_COUNT 5000 // 断点续传最大缓存5000条

typedef enum
{
    EMMS2_SUCCESS = 0,
    EMMS2_ERROR
} RESPONSE_RESULT;

typedef enum
{
    EMMS2_CONNECTING = 0,
    EMMS2_LOGINING,
    EMMS2_DEVREPORTING,
    EMMS2_HEARTBEAT
} EMMS2_STATUS;

typedef enum
{
    EMMS2_TAG_TYPE_R = 0,
    EMMS2_TAG_TYPE_RW,
    EMMS2_TAG_TYPE_ALARM
} EMMS2_TAG_TYPE;

typedef struct
{
    char* host;
    int   port;
    char* user;
    char* passwd;
    char* file;
    char* no;
    char* date;
    char* httpurl;
    int   seq;
    char* function_id;
    void* var;
} QUEUE_MSG_S;

typedef struct
{
    char* dev_no;
    int   seq;
    void* var;
} RATE_MSG_S;

typedef struct mqtt_emms2_param_s
{
    char* addr;
    char* user;
    char* pass;
    char* config_url;
    int   port;
    int   reportInterval;
    int   changeReportInterval; //写0不会变化上报。
    int   saveDisconnectData;
    int   tls;
    int   disable_lz4;
    int   operation;
    int   change_deadband;      //状态变化死区
} mqtt_emms2_param;

typedef struct
{
    list_head_t list;
    tag_t *change_tag;
} change_list_t;

typedef struct 
{
    int       pub_tag_num;
    device_t* device;
    tag_t**   tag_pub_list; //发布数据的tag列表
} pub_dev_list_t;

typedef struct offline_db_s
{
    char* database;
    sqlite3* db;
    pthread_cond_t  history_cond;  // 断点续传锁
    pthread_mutex_t history_mutex; //
} offline_db_s;

// 告警上报队列
typedef struct alarm_report_list_s
{
    list_head_t     alarm_report_queue; // 告警上报队列
    pthread_mutex_t alarm_report_queue_mutex;
    int             alarm_report_queue_size;
    int             alarm_report_queue_max_size;
} alarm_report_list_s;

typedef struct pub_dev_t
{
    time_t end;
    time_t period;
    pub_dev_list_t* pub_dev_list;
    int pub_dev_list_num;
} pub_dev_t;

typedef struct std_enum_tag_list // 具体读取哪些在.c的23,24行定义
{
    char** pcs_std_list;
    int    pcs_std_list_num;
    char** bms_std_list;
    int    bms_std_list_num;
} std_enum_tag_list_t;

// 存储监控设备的状态
typedef struct device_status_s {
    char dev_no[32];           // 设备编号
    char tag_name[64];         // 点位名称
    int last_status;           // 上一次的状态值
    int func;                  // 是否使用适配器 0:否;1:是
} device_status_t;

// 点位配置管理
typedef struct tag_config_s {
    char dev_name[32];         // 设备名称
    char type_name[32];        // 设备类型
    char tag_name[64];         // 点位名称
    int func;                  // 是否使用适配器 0:否;1:是
} tag_config_t;

typedef struct mqtt_emms2_var_s
{
    char* station_id;
    mqtt_emms2_param base_param;
    mqtt_session_t *session;
    char topic_sn[EMMS2_MAX_BASE_SHORT_LEN];
    pthread_t mqtt_cycle_tid;
    unsigned int seq;
    EMMS2_STATUS emms2_status;
    pthread_rwlock_t dev_list_rwlock;
    hash_intptr_t *dev_hash;
    int log_fd;

    int offlinecount;
    int cond_wait_sec;
    int backoff_count;
    pthread_cond_t cond;//
    pthread_mutex_t mutex; //
    key_t key;
    int snapshoot_thread_state; //0空闲1正在运行
    offline_db_s* offline_db;
    alarm_report_list_s* alarm_report_list;
    pub_dev_t* pub_dev;
    mqtt_dp_var_t*        dp;
    
    time_t last_check_time;      // 上一次检查的时间
    device_status_t *device_status_list;  // 设备状态列表
    int device_status_count;              // 设备状态数量
    tag_config_t *tag_config_list;        // 点位配置列表
    int tag_config_count;                 // 点位配置数量
}mqtt_emms2_var_t;

typedef struct alarm_real_t alarm_real_t;
typedef struct alarm_real_t alarm_report_t;

mqtt_emms2_var_t *mqtt_emms2_client_init(char* station_id);
char * get_net_string(char *data_info);
void mqtt_emms2_start(mqtt_emms2_var_t *var);
int mqtt_add_alarm_report_s(alarm_real_t* real);
mqtt_emms2_var_t* get_mqtt_emms2_var_by_id(char* id);
int upload_template_by_dev_no(const mqtt_emms2_var_t* var, const char* dev_no, const char* languages, char* topic_post);
int upload_alarminfo_by_language(const mqtt_emms2_var_t* var, const char* lang, char* topic_post);
int mqtt_publish_message(const mqtt_emms2_var_t* var, char* pub_topic, char* data, int data_len);


int mqtt_set_cabinet_info(mqtt_emms2_var_t* var, cJSON* message,int seq);
int  set_cabinet_info(cJSON* info, char* source, time_t set_time);
void read_cabinet_info(struct lnxall_buff* lbuf);
int  sync_cabinet_info_all();
int  sync_cabinet_info_response(mqtt_emms2_var_t* var, cJSON* root);
void init_sync_cabinet_info_record();
void send_sync_cabinet_info(mqtt_emms2_var_t* var);
int  set_lc_cabname_info(cJSON* info);

#endif
