跳转至

MqttInfo接口说明

一、使用示例

1. 主站测试示例

连接MQTT服务器,订阅PD消息,推送MD消息

#include <iostream>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include "mqtt_info.h"

#define MQTT_URL        "tcp://mqtt.eclipse.org:1883"
#define CLIENT_ID       "ExampleClientHost"
#define USER_NAME       "user"
#define PASSWORD        "password"
#define TOPIC_PDINFO    "PDInfo"
#define TOPIC_MDINFO    "MDInfo"

// 收到PD消息回调函数(参数,主题,数据段,长度)
void CallbackRecvPdData(void *arg, const char* topic, const uint8_t* data, const int len)
{
    // 判定主题是否为PD消息
    if(strcmp(topic, TOPIC_PDINFO) != 0) {
        return;
    }

    // 解析数据段
    DatavSegment dsv;
    dsv.SetDataPacket(len, data);
    DatavSegment::AddrValue_T da[32];
    int num = dsv.GetDataPoint(32, da);

    // 打印收到的PD消息
    for(int i = 0; i < num; i++) {
        printf("addr: %d, value: %d\n", da[i].addr, da[i].value);
    }
}

uint64_t GetSysMs()     // 获取系统毫秒时间戳
{
    struct timeval tv;
    gettimeofday(&tv, NULL);    // 获取当前系统时间
    uint64_t sec = tv.tv_sec;
    uint64_t usec = tv.tv_usec;

    return sec*1000 + usec/1000;
}

void HostTest()
{
    // 创建MQTT客户端
    MqttInfo *pmqtt =
        new MqttInfo(MQTT_URL, CLIENT_ID, USER_NAME, PASSWORD);
    // 设置接收PD消息回调函数
    pmqtt->SetRecvPdDataCallback(CallbackRecvPdData, NULL);
    pmqtt->Subscribe(TOPIC_PDINFO, 0);

    // 循环推送MD写消息
    while(1) {
        // 数据段
        DatavSegment ds;
        ds.AddDataPoint(0x0000, 0x00);  // 添加数据点 - 地址0x0000,值0x00
        ds.AddDataPoint(0x0001, 0x01);  // 添加数据点 - 地址0x0001,值0x01
        ds.AddDataPoint(0x0002, 0x02);  // 添加数据点 - 地址0x0002,值0x02
        ds.AddDataPoint(0x0003, 0x03);  // 添加数据点 - 地址0x0003,值0x03
        ds.AddDataPoint(0x0004, 0x04);  // 添加数据点 - 地址0x0004,值0x04
        ds.AddDataPoint(0x1000, 0x05);  // 添加数据点 - 地址0x1000,值0x05
        ds.AddDataPoint(0x1001, 0x06);  // 添加数据点 - 地址0x1001,值0x06
        ds.AddDataPoint(0x1002, 0x07);  // 添加数据点 - 地址0x1002,值0x07
        ds.AddDataPoint(0x1003, 0x08);  // 添加数据点 - 地址0x1003,值0x08
        ds.AddDataPoint(0x1004, 0x09);  // 添加数据点 - 地址0x1004,值0x09
        ds.AddDataPoint(0x2000, 0x0A);  // 添加数据点 - 地址0x2000,值0x0A
        ds.AddDataPoint(0x2001, 0x0B);  // 添加数据点 - 地址0x2001,值0x0B
        ds.AddDataPoint(0x2002, 0x0C);  // 添加数据点 - 地址0x2002,值0x0C
        // 推送MD写消息
        pmqtt->PublishMdWrInfo(TOPIC_MDINFO, GetSysMs(), &ds, 0);
        sleep(10);
    }
    delete pmqtt;
}

int main()
{
    HostTest();

    return 0;
}

2. 从站测试示例

连接MQTT服务器,订阅MD消息,推送PD消息

#include <iostream>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include "mqtt_info.h"

#define MQTT_URL        "tcp://mqtt.eclipse.org:1883"
#define CLIENT_ID       "ExampleClientSlave"
#define USER_NAME       "user"
#define PASSWORD        "password"
#define TOPIC_PDINFO    "PDInfo"
#define TOPIC_MDINFO    "MDInfo"

// 收到MD消息回调函数指针(参数,主题,MD消息类别,,数据段,长度)
void CallbackRecvMdData(void *arg, const char* topic, const MDType_T type, const uint8_t* data, const int len)
{
    // 判定主题是否为MD消息
    if(strcmp(topic, TOPIC_MDINFO) != 0) {
        return;
    }

    // MD读消息
    if(type == MD_RE) {
        // 解析数据段
        DataSegment ds;
        ds.SetDataPacket(len, data);
        int addr[32];
        int num = ds.GetDataPoint(32, addr);

        // 打印收到的MD读消息
        for(int i = 0; i < num; i++) {
            printf("addr: %d\n", addr[i]);
        }
    }
    // MD写消息
    else if(type == MD_WR) {
        // 解析数据段
        DatavSegment dsv;
        dsv.SetDataPacket(len, data);
        DatavSegment::AddrValue_T da[32];
        int num = dsv.GetDataPoint(32, da);

        // 打印收到的MD写消息
        for(int i = 0; i < num; i++) {
            printf("addr: %d, value: %d\n", da[i].addr, da[i].value);
        }
    }
}

uint64_t GetSysMs()     // 获取系统毫秒时间戳
{
    struct timeval tv;
    gettimeofday(&tv, NULL);    // 获取当前系统时间
    uint64_t sec = tv.tv_sec;
    uint64_t usec = tv.tv_usec;

    return sec*1000 + usec/1000;
}

void SlaveTest()
{
    // 创建MQTT客户端
    MqttInfo *pmqtt =
        new MqttInfo(MQTT_URL, CLIENT_ID, USER_NAME, PASSWORD);
    // 设置接收MD消息回调函数
    pmqtt->SetRecvMdDataCallback(CallbackRecvMdData, NULL);
    // 订阅MD消息
    pmqtt->Subscribe(TOPIC_MDINFO, 0);

    // 循环推送PD消息
    while(1) {
        // 数据段
        DatavSegment ds;
        ds.AddDataPoint(0x0000, 0x00);  // 添加数据点 - 地址0x0000,值0x00
        ds.AddDataPoint(0x0001, 0x01);  // 添加数据点 - 地址0x0001,值0x01
        ds.AddDataPoint(0x0002, 0x02);  // 添加数据点 - 地址0x0002,值0x02
        ds.AddDataPoint(0x0003, 0x03);  // 添加数据点 - 地址0x0003,值0x03
        ds.AddDataPoint(0x0014, 0x04);  // 添加数据点 - 地址0x0014,值0x04
        ds.AddDataPoint(0x0015, 0x05);  // 添加数据点 - 地址0x0015,值0x05
        ds.AddDataPoint(0x0016, 0x06);  // 添加数据点 - 地址0x0016,值0x06
        ds.AddDataPoint(0x0027, 0x07);  // 添加数据点 - 地址0x0027,值0x07
        ds.AddDataPoint(0x0028, 0x08);  // 添加数据点 - 地址0x0028,值0x08
        ds.AddDataPoint(0x0039, 0x09);  // 添加数据点 - 地址0x0039,值0x09

        // 推送PD消息
        pmqtt->PublishPdInfo(TOPIC_PDINFO, GetSysMs(), &ds, 0);
        sleep(1);
    }

    delete pmqtt;
}

int main()
{
    SlaveTest();

    return 0;
}

二、DatavSegment类

带数据字节的数据段类,该类用于处理带数据字节的数据段(MD写消息、PD消息),包括组包和解包

1. 数据对象结构体

// 数据对象结构体
typedef struct DatavObj_ {
    int startaddr = 0;          // 起始地址
    int size = 0;               // 数据长度
    std::vector<uint16_t> data; // 数据
} DatavObj_T;

2. 地址值结构体

// 地址值结构体
typedef struct AddrValue_ {
    int addr = 0;               // 地址
    int value = 0;              // 值
} AddrValue_T;

3. 构造函数

构造函数,用于创建带有数据字节的数据段

/**
 * @brief 构造函数
 *
 */
DatavSegment(/* args */);
  • 参数

4. 析构函数

/**
 * @brief 析构函数
 */
~Dlt645Dev();

5. 组包时-清空数据区

/**
 * @brief 清空数据区(组包时使用)
 *
 * @return 无
 */
void Clear();
  • 参数
  • 无;
  • 返回值

6. 组包时-添加数据点

/**
 * @brief 添加数据点(组包时使用)
 *
 * @param addr  地址
 * @param value 数据
 * @param cover 是否覆盖(选择覆盖固定返回添加成功)
 *
 * @return 1添加成功;-1添加失败(数据点已存在)
 */
int AddDataPoint(const int addr, const uint16_t value, const bool cover = true);
  • 参数
  • addr 地址
  • value 数据
  • cover 是否覆盖(选择覆盖固定返回添加成功)
  • 返回值
  • 1添加成功;-1添加失败(数据点已存在)

7. 组包时-添加连续数据点

/**
 * @brief 添加连续数据点(组包时使用)
 *
 * @param startaddr 起始地址
 * @param num       数据点个数
 * @param *value    数据指针
 * @param cover     是否覆盖(选择覆盖固定返回添加成功)
 *
 * @return 1添加成功;-1添加失败(数据点已存在)
 */
int AddDataPoints(const int startaddr, const int num, const uint16_t *value, const bool cover = true);
  • 参数
  • startaddr 起始地址
  • num 数据点个数
  • *value 数据指针
  • cover 是否覆盖(选择覆盖固定返回添加成功)
  • 返回值
  • 1添加成功;-1添加失败(数据点已存在)

8. 组包时-将数据点生成数据包

/**
 * @brief 将数据点生成数据包(组包时使用)
 *
 * @param maxlen 允许的数据包最大长度
 * @param *buf   输出参数,数据包存放的指针
 *
 * @return 数据包实际长度,-1表示数据包长度超过maxlen
 */
int MakeDataPacket(const int maxlen, uint8_t *buf);
  • 参数
  • maxlen 允许的数据包最大长度
  • *buf 输出参数,数据包存放的指针
  • 返回值
  • 数据包实际长度,-1表示数据包长度超过maxlen

9. 解包时-设置数据包内容

/**
 * @brief 设置数据包内容(解包时使用)
 *
 * @param len 数据包长度
 * @param *buf 数据包指针
 *
 * @return -1设置失败包长度超范围;1设置成功
 */
int SetDataPacket(const int len, const uint8_t *buf);
  • 参数
  • len 数据包长度
  • *buf 数据包指针
  • 返回值
  • -1设置失败包长度超范围;1设置成功

10. 解包时-获取数据点

/**
 * @brief 获取数据点(解包时使用)
 *
 * @param maxnum     允许的最大数据点个数
 * @param *addrvalue 输出参数,数据点地址值存放的指针
 *
 * @return 数据点实际个数,-1表示数据点个数超过maxnum
 */
int GetDataPoint(const int maxnum, AddrValue_T *addrvalue);
  • 参数
  • maxnum 允许的最大数据点个数
  • *addrvalue 输出参数,数据点地址值存放的指针
  • 返回值
  • 数据点实际个数,-1表示数据点个数超过maxnum

11. 解包时-获取数据对象

/**
 * @brief 获取数据对象(解包时使用)
 *
 * @param maxnum   允许的最大数据对象个数
 * @param *dataobj 输出参数,数据对象存放的指针
 *
 * @return 数据对象实际个数,-1表示数据对象个数超过maxnum
 */
int GetDataObject(const int maxnum, DatavObj_T *dataobj);
  • 参数
  • maxnum 允许的最大数据对象个数
  • *dataobj 输出参数,数据对象存放的指针
  • 返回值
  • 数据对象实际个数,-1表示数据对象个数超过maxnum

三、DataSegment类

不带数据字节的数据段类,该类用于处理不带数据字节的数据段(MD读消息),包括组包和解包

1. 数据对象结构体

// 数据对象结构体
typedef struct DataObj_ {
    int startaddr = 0;      // 起始地址
    int size = 0;           // 数据长度
} DataObj_T;

2. 构造函数

构造函数,用于创建带有数据字节的数据段

/**
 * @brief 构造函数
 *
 */
DataSegment(/* args */);
  • 参数

3. 析构函数

/**
 * @brief 析构函数
 */
~DataSegment();

4. 组包时-清空数据区

/**
 * @brief 清空数据区(组包时使用)
 *
 * @return 无
 */
void Clear();
  • 参数
  • 无;
  • 返回值

5. 组包时-添加数据点

/**
 * @brief 添加数据点(组包时使用)
 *
 * @param addr  地址
 *
 * @return 无
 */
void AddDataPoint(const int addr);
  • 参数
  • addr 地址
  • 返回值

6. 组包时-添加连续数据点

/**
 * @brief 添加连续数据点(组包时使用)
 *
 * @param startaddr 起始地址
 * @param num       数据点个数
 *
 * @return 无
 */
void AddDataPoints(const int startaddr, const int num);
  • 参数
  • startaddr 起始地址
  • num 数据点个数
  • 返回值

7. 组包时-将数据点生成数据包

/**
 * @brief 将数据点生成数据包(组包时使用)
 *
 * @param maxlen 允许的数据包最大长度
 * @param *buf   输出参数,数据包存放的指针
 *
 * @return 数据包实际长度,-1表示数据包长度超过maxlen
 */
int MakeDataPacket(const int maxlen, uint8_t *buf);
  • 参数
  • maxlen 允许的数据包最大长度
  • *buf 输出参数,数据包存放的指针
  • 返回值
  • 数据包实际长度,-1表示数据包长度超过maxlen

8. 解包时-设置数据包内容

/**
 * @brief 设置数据包内容(解包时使用)
 *
 * @param len 数据包长度
 * @param *buf 数据包指针
 *
 * @return -1设置失败包长度超范围;1设置成功
 */
int SetDataPacket(const int len, const uint8_t *buf);
  • 参数
  • len 数据包长度
  • *buf 数据包指针
  • 返回值
  • -1设置失败包长度超范围;1设置成功

9. 解包时-获取数据点

/**
 * @brief 获取数据点(解包时使用)
 *
 * @param maxnum 允许的最大数据点个数
 * @param *addr  输出参数,数据点地址存放的指针
 *
 * @return 数据点实际个数,-1表示数据点个数超过maxnum
 */
int GetDataPoint(const int maxnum, int *addr);
  • 参数
  • maxnum 允许的最大数据点个数
  • *addr 输出参数,数据点地址存放的指针
  • 返回值
  • 数据点实际个数,-1表示数据点个数超过maxnum

10. 解包时-获取数据对象

/**
 * @brief 获取数据对象(解包时使用)
 *
 * @param maxnum   允许的最大数据对象个数
 * @param *dataobj 输出参数,数据对象存放的指针
 *
 * @return 数据对象实际个数,-1表示数据对象个数超过maxnum
 */
int GetDataObject(const int maxnum, DataObj_T *dataobj);
  • 参数
  • maxnum 允许的最大数据对象个数
  • *dataobj 输出参数,数据对象存放的指针
  • 返回值
  • 数据对象实际个数,-1表示数据对象个数超过maxnum

四、MqttInfo类

1. 构造函数

/**
 * @brief 构造函数
 *
 * @param server_url             MQTT服务器URL,例"tcp://123.456.789.123:1883";
 * @param client_id              客户端ID;
 * @param user_name              用户名;
 * @param password               密码;
 */
MqttInfo(const char* server_url, const char* client_id,
    const char* user_name, const char* password);
  • 参数
  • server_url MQTT服务器URL,例"tcp://123.456.789.123:1883";
  • client_id 客户端ID;
  • user_name 用户名;
  • password 密码;
  • 返回值

2. 析构函数

/**
 * @brief 析构函数
 */
~MqttInfo();

3. 自动重连时间间隔设置

/**
 * @brief 自动重连时间间隔设置
 *
 * @param ms 重连时间间隔(ms)
 *
 * @return 无
 */
void AutoConnectInterval(int ms);
  • 参数
  • ms 重连时间间隔(ms)
  • 返回值

4. 设置订阅接收数据回调函数

/**
 * @brief 设置订阅接收数据回调函数
 *
 * @param callback 回调函数指针
 * @param arg      回调函数参数
 *
 * @return 无
 */
void SetRecvPdDataCallback(fpRecvPdData callback, void *arg);
void SetRecvMdDataCallback(fpRecvMdData callback, void *arg);

// 收到PD消息回调函数指针(参数,主题,数据段,长度)
typedef void (*fpRecvPdData)
    (void *arg, const char* topic, const uint8_t* data, const int len);

// 收到MD消息回调函数指针(参数,主题,MD消息类别,数据段,长度)
typedef void (*fpRecvMdData)
    (void *arg, const char* topic, const MDType_T type, const uint8_t* data, const int len);
  • 参数
  • callback 回调函数指针
  • arg 回调函数参数
  • 返回值

5. 订阅函数

/**
 * @brief 订阅函数
 *
 * @param topic 订阅主题,可能包含通配符
 * @param qos   订阅所请求的服务质量
 *
 * @return 无
 */
void Subscribe(const char* topic, int qos = 0);
  • 参数
  • topic 订阅主题,可能包含通配符
  • qos 订阅所请求的服务质量
  • 返回值

6. 推送PD消息函数

/**
 * @brief 推送PD消息函数
 *
 * @param topic  推送主题
 * @param time   时间戳(自1970年1月1日以来的毫秒时间戳)
 * @param *datas 数据段
 * @param qos    推送消息的服务质量
 *
 * @return 无
 */
void PublishPdInfo(const char* topic, const uint64_t time, const DatavSegment *datas, int qos = 0);
  • 参数
  • topic 订阅主题,可能包含通配符
  • time 时间戳(自1970年1月1日以来的毫秒时间戳)
  • *datas 数据段
  • qos 推送消息的服务质量
  • 返回值

7. 推送MD写消息函数

/**
 * @brief 推送MD写消息函数
 *
 * @param topic  推送主题
 * @param time   时间戳(自1970年1月1日以来的毫秒时间戳)
 * @param *datas 数据段
 * @param qos    推送消息的服务质量
 *
 * @return 无
 */
void PublishMdWrInfo(const char* topic, const uint64_t time, const DatavSegment *datas, int qos = 0);
  • 参数
  • topic 订阅主题,可能包含通配符
  • time 时间戳(自1970年1月1日以来的毫秒时间戳)
  • *datas 数据段
  • qos 推送消息的服务质量
  • 返回值

8. 推送MD读消息函数

/**
 * @brief 推送MD读消息函数
 *
 * @param topic  推送主题
 * @param time   时间戳(自1970年1月1日以来的毫秒时间戳)
 * @param *datas 数据段
 * @param qos    推送消息的服务质量
 *
 * @return 无
 */
void PublishMdReInfo(const char* topic, const uint64_t time, const DataSegment *datas, int qos = 0);
  • 参数
  • topic 订阅主题,可能包含通配符
  • time 时间戳(自1970年1月1日以来的毫秒时间戳)
  • *datas 数据段
  • qos 推送消息的服务质量
  • 返回值

9. 获取当前MQTT连接状态

/**
 * @brief 获取当前MQTT连接状态
 *
 * @return 1已连接;-1未连接
 */
int GetConnectStatus();
  • 参数
  • 返回值
  • 1已连接;-1未连接