#ifndef __BMSER_H__
#define __BMSER_H__
#include <stdint.h>
#include "mqtt_session.h"

#define BMSER_KEEP_ALIVE_MAX 10
#define BMSER_DEFAULT_IPC_QOS 0

#define BMSER_ONLINE_ADDR (0x0137)
#define BMSER_ONLINE_POINT_COUNT (2)
#define BMSER_CHECK_ONLINE_TIME (10 * 1000)


typedef enum bmser_data_t
{
    BMSER_DATA_U16 = 0,
    BMSER_DATA_S16,
    BMSER_DATA_U32,
    BMSER_DATA_S32,
    BMSER_DATA_FLOAT,
    BMSER_DATA_BIT16,
    BMSER_DATA_MAX
} bmser_data_t;

#pragma pack(1)
typedef struct block_data
{
    uint32_t block_id;
    uint16_t start_sub_id;
    uint16_t sub_num;
    uint16_t bytes;
    uint8_t content[0];
} block_data;

typedef struct bmser_payload
{
    uint8_t block_num;
    block_data block[0];
} bmser_payload;
#pragma pack()

typedef struct bmser_bin_pack
{
    uint32_t trans_id;
    uint8_t dev_len;
    uint8_t dev[16]; // 没有使用
    uint8_t cmd_len;
    uint8_t cmd[16]; // 没有使用
    uint16_t payload_len;
    bmser_payload *payload;
} bmser_bin_pack;

typedef struct cb_s
{
    const block_data *proto_data;
    void *top; // 上层使用的数据
} bmser_cb_par;

typedef struct bmser_protocol
{
    char ip[16];
    uint16_t port;
    int (*data_report)(const bmser_cb_par *p);
    mqtt_session_t *mqtt;
    bmser_cb_par cb_par; // 上层使用的数据
} bmser_protocol;

//
#define TOGGLE_ENDIAN_32(data) (((data >> 24) & 0xff) | ((data >> 8) & 0xff00) | ((data << 8) & 0xff0000) | ((data << 24) & 0xff000000))
#define TOGGLE_ENDIAN_16(data) (((data >> 8) & 0xff) | ((data << 8) & 0xff00))
#define BMSER_BLOCK_NEXT(p_cur_block) ((block_data *)(&((p_cur_block)->content[TOGGLE_ENDIAN_16(p_cur_block->bytes)])))
// mqtt
bmser_protocol *new_bmser_protocol(char *ip, uint16_t port, int (*data_report)(const bmser_cb_par *p), void *top);
int delete_bmser_protocol(bmser_protocol *bmser);
int new_bmser_proto_pack(bmser_bin_pack *pack_info, block_data *block_arr[], uint8_t block_num, void *ret_pack);
block_data *new_block_data(uint32_t block_id, uint16_t start_sub_id, void *content, uint16_t sub_num, uint16_t bytes);
int bmser_protocol_start(bmser_protocol *bmser);
bmser_data_t bmser_protocol_to_type(char *t);
int bmser_protocol_send_pack(bmser_protocol *this_p, char *dev_no, void *pack, int len);
bmser_protocol *new_bmser_protocol(char *ip, uint16_t port, int (*data_report)(const bmser_cb_par *p), void *top);
int bmser_protocol_add_dev(bmser_protocol *bmser, char *dev_no);
int bmser_protocol_start(bmser_protocol *bmser);

#ifdef EN_BMSER_DB_CTROL_LIB // 直接读共享内存
int bmser_init(void);
int bmser_read(void *buff, void *valid_flag, uint16_t max, uint32_t bank_rack, uint16_t start_sub_id, uint16_t reg_count);
int bmser_write(void *buff, uint32_t bank_rack, uint16_t start_sub_id, uint16_t reg_count);
#endif
#endif
