#ifndef __CLOUD_MQTT_COMMON_H
#define __CLOUD_MQTT_COMMON_H

/***************HEADER FILES****************/
#include <string.h>
#include <syslog.h>
#include <stdlib.h>
#include <limits.h>
#include <stdio.h>
#include <errno.h>
#include <math.h>

#include "dy_utils/dy_mqtt.h"
#include "dy_utils/dy_list.h"
#include "dy_utils/dy_common.h"
#include "dy_utils/dy_db.h"
#include "dy_utils/dy_ipc.h"

#define YUZHI_CFG_FILE "/app/config/yuzhi_cfg.json"
#define YUZHI_DATA_CFG "/app/config/yuzhi_data_"
#define YUZHI_DEV_CFG "/app/config/yuzhi_dev_cfg.json"

#define YUZHI_CHANGEALL "com.ss.iot.changeall."
#define YUZHI_EDITALL "com.ss.iot.editall."
#define YUZHI_HB "com.ss.iot.heartbeat"
#define YUZHI_REPORTALL "com.ss.iot.reportall"
#define YUZHI_PLCSTATUS "com.ss.iot.plcstatus"

#define msleep(n) usleep(n * 1000)

/* --- PRINTF_BYTE_TO_BINARY macro's --- */
#define PRINTF_BINARY_PATTERN_INT8 "%c%c%c%c%c%c%c%c"
#define PRINTF_BYTE_TO_BINARY_INT8(i) \
    (((i)&0x80ll) ? '1' : '0'),       \
        (((i)&0x40ll) ? '1' : '0'),   \
        (((i)&0x20ll) ? '1' : '0'),   \
        (((i)&0x10ll) ? '1' : '0'),   \
        (((i)&0x08ll) ? '1' : '0'),   \
        (((i)&0x04ll) ? '1' : '0'),   \
        (((i)&0x02ll) ? '1' : '0'),   \
        (((i)&0x01ll) ? '1' : '0')

#define PRINTF_BINARY_PATTERN_INT16 \
    PRINTF_BINARY_PATTERN_INT8 PRINTF_BINARY_PATTERN_INT8
#define PRINTF_BYTE_TO_BINARY_INT16(i) \
    PRINTF_BYTE_TO_BINARY_INT8((i) >> 8), PRINTF_BYTE_TO_BINARY_INT8(i)
#define PRINTF_BINARY_PATTERN_INT32 \
    PRINTF_BINARY_PATTERN_INT16 PRINTF_BINARY_PATTERN_INT16
#define PRINTF_BYTE_TO_BINARY_INT32(i) \
    PRINTF_BYTE_TO_BINARY_INT16((i) >> 16), PRINTF_BYTE_TO_BINARY_INT16(i)
#define PRINTF_BINARY_PATTERN_INT64 \
    PRINTF_BINARY_PATTERN_INT32 PRINTF_BINARY_PATTERN_INT32
#define PRINTF_BYTE_TO_BINARY_INT64(i) \
    PRINTF_BYTE_TO_BINARY_INT32((i) >> 32), PRINTF_BYTE_TO_BINARY_INT32(i)
/* --- end macros --- */



typedef struct _yuzhi_var_t yuzhi_var_t;
typedef struct _yuzhi_prod_t yuzhi_prod_t;
typedef uintptr_t S7Object;

typedef struct _s7_plc_client_s
{
    char *ip_addr;
    int rack;
    int slot;
    S7Object Client;
    yuzhi_prod_t *prod;
} s7_plc_client_t;

typedef struct _s7_plc_data_s
{
    int pk;
    int pt;
    int Area;
    int WordLen;
    int Result;
    int DBNumber;
    int Start;
    int Amount;
    int type;
    int threshold;
    int decimal_cnt;
    int rw;
    void *pdata;
    int len;
    union
    {
        unsigned char bit;
        unsigned short uv16;
        short v16;
        unsigned int uv32;
        int v32;
        float f;
        short bcd16;
        int bcd32;
        unsigned short bin16;
        unsigned int bin32;
        unsigned short hex16;
        unsigned int hex32;
        double d;
        char *text;
        unsigned short dog;
    } val;
    int update;
    int reported;
} s7_plc_data_t;

typedef struct _yuzhi_prod_t
{
    int connecttype;
    char plcmodel[64];
    int plctype;
    char ip[32];
    char mac[32];
    int port;
    int netaddr;
    char devicekey[32];
    s7_plc_client_t *s7_plc_client;
    int data_cnt;
    s7_plc_data_t *data;
    yuzhi_var_t *var;
    int cpuStatus;
} yuzhi_prod_t;

typedef struct _yuzhi_var_t
{
    mqtt_session_t *session;
    mqtt_session_t *session_internal; //
    char sn_str[SN_MAX_LEN];
    char *login_url;
    char *login_member;
    char *login_password;
    char *prod_login_url;
    int status_poll_timer;
    int report_timer;
    int prod_cnt;
    yuzhi_prod_t *prods;
} yuzhi_var_t;

extern int s7_plc_create_conn(s7_plc_client_t *client);
extern void *s7_run_loop(void *param);
extern int yuzhi_load_s7_data_cfg(yuzhi_var_t *var, yuzhi_prod_t *prod);
extern int s7_create_data_report(yuzhi_var_t *var, yuzhi_prod_t *prod, cJSON *items);
extern int yuzhi_edit_s7_data(yuzhi_var_t *var, yuzhi_prod_t *prod, cJSON *watches);

#endif /* __CLOUD_MQTT_COMMON_H */
