/**
 * @file      opc_ua_comm.h
 * @brief     description about opc_ua
 * @details  e.g. 485 port config, period polling
 * @author   wangleilei@zjdyiot.com
 * @date     2019.06.20
 * @version  A001
 * @par Copyright (c):
 *       DYIOT
 * @par History:
 *   version: draft\n
 */
#ifndef __OPC_UA_COMMON_H
#define __OPC_UA_COMMON_H

/***************HEADER FILES****************/
#include <string.h>
#include <syslog.h>
#include "ipc_session.h"
#include "lnxall_list.h"
#include "dy_utils/dy_common.h"
#include "dy_utils/dy_ds.h"
#include "dy_utils/kv_array.h"
#include "dy_utils/dy_ipc.h"

#include <open62541/client_config_default.h>
#include <open62541/client_highlevel.h>
#include <open62541/client_subscriptions.h>
#include <open62541/plugin/log_stdout.h>

#include "modbus/modbus.h"
/******************************************/

#define OPC_UA_NODE_STATUS_BAK_FILE "/app/opc_ua_status.bak"
#define OPC_UA_APP_KEY "qMcBdKcmZJBDbevd"
/******************************************/

/*************ENUM*************************/
typedef enum
{
    NODE_ID_INVALID = 0,  // 错误ID
    NODE_ID_USER_DEFINE,  // 从用户配置中获取
    NODE_ID_NEED_BROWSER, // 需要搜索
    NODE_ID_BROWSER,      // 通过browser匹配displayname获取
    NODE_ID_NOT_UA,       // 不是UA的点位，不需要去下面读取
} node_id_find_e;
/******************************************/

/*******************STRUCTURE**************/

typedef struct _opc_ua_var_t opc_ua_var_t;

typedef struct
{
    node_id_find_e type;
    UA_NodeId nodeId;
    object_property_cfg_t *perperty;
    char *display_name;
    UA_Variant val;
    UA_Boolean updated;
} opc_ua_tag_t;

typedef struct _connect_config_s
{
    struct list_head list;
    char *url;
    char *username;
    char *password;
    UA_Client *client;
    time_t last_send;
    time_t last_con;
    int connect_status;
    opc_ua_var_t *var;

    struct list_head node_list; // 节点
    struct list_head used_node_list; // 使用的节点
    UA_Boolean browsered;
    int report_timer;
    pthread_rwlock_t data_lock;
    int readable_tag_cnt;
    opc_ua_tag_t **tags;
} connect_config_t;

typedef struct
{
    struct list_head list;
    struct list_head list2;
    struct list_head used_list;
    opc_ua_var_t *var;
    char sn[SN_MAX_LEN]; ///<设备SN
    node_cfg_t *node_cfg;
    object_property_table_t *property_tab;
    connect_config_t *connect_config;
    int tag_cnt;
    opc_ua_tag_t *tag;
} dev_node_t;

typedef struct _opc_ua_var_t
{
    ipc_session_t *session;       //内部broker的MQTT client，用于进程间通信
    struct list_head connect_list; // 连接
    struct list_head node_list;    // 节点
    int conn_cnt;
    int node_cnt;

    nodes_cfg_table_t *nodes_cfg_table; //节点信息
    template_table_t *template_table;   //模板信息
    object_table_t *object_table;       //物模型信息

    char sn_str[SN_MAX_LEN];
    char proc_name[PROGRAM_NAME_LEN];
    int report_timer;

    dev_status_table_t *ds; //下挂节点的状态信息
    time_t nodes_status_sync_date;
    int node_status_timer;
} opc_ua_var_t;

/******************************************/

/******************FUNCTION****************/
extern int opc_ua_start_thread(opc_ua_var_t *var, connect_config_t *connect_cfg);
extern void inactivityCallback(UA_Client *client);

#endif /* __OPC_UA_COMMON_H */
