跳转至

DLT645接口说明

一、使用示例

创建1条DLT645通讯通道,在这条通道上创建2个DLT645电表,循环获取2个电表的数据

DLT645

#include "dlt645_host/dlt645_host_ch.h"
#include "dlt645_host/dlt645_host_dev.h"
#include "dlt645_host/dlt645_host.h"
#include <stdio.h>
#include <unistd.h>

Dlt645Host::DataId07_E g_en_id[] = {
    Dlt645Host::kDataId07_00010000,   // (当前)正向有功总电能
    Dlt645Host::kDataId07_00020000,   // (当前)反向有功总电能
    Dlt645Host::kDataId07_01010000,   // (当前)正向有功总最大需量及发生时间
    Dlt645Host::kDataId07_01020000,   // (当前)反向有功总最大需量及发生时间
    Dlt645Host::kDataId07_02010100,   // 电压数A相
    Dlt645Host::kDataId07_02010200,   // 电压数B相
    Dlt645Host::kDataId07_02010300,   // 电压数C相
    Dlt645Host::kDataId07_02020100,   // 电流数A相
    Dlt645Host::kDataId07_02020200,   // 电流数B相
    Dlt645Host::kDataId07_02020300,   // 电流数C相
    Dlt645Host::kDataId07_02030000,   // 瞬时有功功率总
    //Dlt645Host::kDataId07_02030100,   // 瞬时有功功率A相
    //Dlt645Host::kDataId07_02030200,   // 瞬时有功功率B相
    //Dlt645Host::kDataId07_02030300,   // 瞬时有功功率C相
    Dlt645Host::kDataId07_02040000,   // 瞬时无功功率总
    //Dlt645Host::kDataId07_02040100,   // 瞬时无功功率A相
    //Dlt645Host::kDataId07_02040200,   // 瞬时无功功率B相
    //Dlt645Host::kDataId07_02040300,   // 瞬时无功功率C相
    Dlt645Host::kDataId07_02050000,   // 瞬时视在功率总
    //Dlt645Host::kDataId07_02050100,   // 瞬时视在功率A相
    //Dlt645Host::kDataId07_02050200,   // 瞬时视在功率B相
    //Dlt645Host::kDataId07_02050300,   // 瞬时视在功率C相
    Dlt645Host::kDataId07_02060000,   // 功率因数数总
    //Dlt645Host::kDataId07_02060100,   // 功率因数A相
    //Dlt645Host::kDataId07_02060200,   // 功率因数B相
    //Dlt645Host::kDataId07_02060300,   // 功率因数C相
    Dlt645Host::kDataId07_02800002,   // 电网频率
    Dlt645Host::kDataId07_02800004,   // 当前有功需量
    //Dlt645Host::kDataId07_02800005    // 当前无功需量
};

void GetDev(Dlt645HostDev *pdev, Dlt645Host::DataId07_E *en_id, int count)
{
    Dlt645Host::Addr_T addr = pdev->GetAddr();
    int timeout = pdev->GetCommTimeOutFlag();
    printf("MeterAddr:[%02X%02X%02X%02X%02X%02X] timeout=%d\r\n",
        addr.addr[0], addr.addr[1], addr.addr[2], addr.addr[3], addr.addr[4], addr.addr[5], timeout);
    int ret = 0;
    float value = 0;
    uint64_t time_ms = 0;
    uint8_t arg[5] = { 0 };
    uint64_t curr_time_ms = Dlt645Host::GetSysTimestampMs();
    uint64_t ditt_tims_ms = 0;
    // 循环遍历使能的数据标识
    for(int i = 0; i < count; i++) {
        printf("DataId:[%08X] ", en_id[i]);
        // 判断数据标识是否为“最大需量及发生时间”的标识
        if(Dlt645Host::IsMaxDemandId(en_id[i])) {
            // 获取数据
            ret = pdev->GetData(en_id[i], &value, &time_ms, arg);
            if(ret == 1) {
                ditt_tims_ms = curr_time_ms - time_ms;
                printf("value=%9.04f, %2ld.%03ld, %02d-%02d-%02d %02d:%02d ",
                    value, ditt_tims_ms/1000, ditt_tims_ms%1000, arg[0], arg[1], arg[2], arg[3], arg[4]);
            }
            else {
                printf("error ");
            }
        }
        // 其他数据标识
        else {
            ret = pdev->GetData(en_id[i], &value, &time_ms);
            if(ret == 1) {
                ditt_tims_ms = curr_time_ms - time_ms;
                printf("value=%9.04f, %2ld.%03ld ", value, ditt_tims_ms/1000, ditt_tims_ms%1000);
            }
            else {
                printf("error ");
            }
        }
        Dlt645Host::DataInfo_T datainfo;
        ret = Dlt645Host::GetId07Info(en_id[i], &datainfo);
        if(ret == 1) {
            printf("\"%s\", \"%s\"", datainfo.name, datainfo.unit);
        }
        printf("\r\n");
    }
}

int main(int argc, char *argv[])
{
    // 使能数据标识的数量
    int en_id_count = sizeof(g_en_id) / sizeof(g_en_id[0]);

    // 创建通道
    Dlt645HostCh *pch = new Dlt645HostCh("/dev/ttysWK2", 115200, 'N', 8, 1);
    //pch->SetDebug(1);
    printf("创建通讯通道 [%08X]\r\n", pch);
    // 创建设备1
    Dlt645HostDev *pdev1 = new Dlt645HostDev(pch, 0x1111, 0x2222, 0x3333);
    // 使能设备1的数据标识
    for(int i = 0; i < en_id_count; i++) {
        pdev1->SetDataId07En(g_en_id[i]);
    }
    printf("创建设备1 [%08X]\r\n", pdev1);
    // 创建设备2
    Dlt645HostDev *pdev2 = new Dlt645HostDev(pch, 0x4444, 0x5555, 0x6666);
    // 使能设备2的数据标识
    for(int i = 0; i < en_id_count; i++) {
        pdev2->SetDataId07En(g_en_id[i]);
    }
    printf("创建设备2 [%08X]\r\n", pdev2);
    // 启动通道
    pch->Run();
    printf("启动通讯通道\r\n");

    // 循环
    for(int i = 0; i < 1000; i++) {
        sleep(5);
        printf("\033[31m-----------------------------------------------------------------------------------\033[0m\r\n");
        printf("\033[31m---------------------------------------[%05d]---------------------------------------\033[0m\r\n", i);
        GetDev(pdev1, g_en_id, en_id_count);
        printf("\033[31m---------------------------------------[%05d]---------------------------------------\033[0m\r\n", i);
        GetDev(pdev2, g_en_id, en_id_count);
        printf("\033[31m---------------------------------------[%05d]---------------------------------------\033[0m\r\n", i);
        printf("\033[31m-----------------------------------------------------------------------------------\033[0m\r\n\r\n\r\n");
    }

    return 1;
}

二、Dlt645Host类

Dlt645Host基础类,包含一些基础的数据结构

1. 数据标识

DLT645通讯的数据标识,下列枚举中为该模块支持的数据标识

// DLT645 07数据标识
typedef enum DLT645_07_DataIdentification_ {
    kDataId07_00000000 = 0x00000000,    // (当前)组合有功总电能
    kDataId07_00000100 = 0x00000100,    // (当前)组合有功费率 1 电能
    kDataId07_00000200 = 0x00000200,    // (当前)组合有功费率 2 电能
    kDataId07_00000300 = 0x00000300,    // (当前)组合有功费率 3 电能
    kDataId07_00000400 = 0x00000400,    // (当前)组合有功费率 4 电能
    kDataId07_00000500 = 0x00000500,    // (当前)组合有功费率 5 电能
    kDataId07_00000600 = 0x00000600,    // (当前)组合有功费率 6 电能
    kDataId07_00000700 = 0x00000700,    // (当前)组合有功费率 7 电能
    kDataId07_00000800 = 0x00000800,    // (当前)组合有功费率 8 电能
    //kDataId07_0000FF00 = 0x0000FF00,    // (当前)组合有功电能数据块
    kDataId07_00010000 = 0x00010000,    // (当前)正向有功总电能
    kDataId07_00010100 = 0x00010100,    // (当前)正向有功费率 1 电能
    kDataId07_00010200 = 0x00010200,    // (当前)正向有功费率 2 电能
    kDataId07_00010300 = 0x00010300,    // (当前)正向有功费率 3 电能
    kDataId07_00010400 = 0x00010400,    // (当前)正向有功费率 4 电能
    kDataId07_00010500 = 0x00010500,    // (当前)正向有功费率 5 电能
    kDataId07_00010600 = 0x00010600,    // (当前)正向有功费率 6 电能
    kDataId07_00010700 = 0x00010700,    // (当前)正向有功费率 7 电能
    kDataId07_00010800 = 0x00010800,    // (当前)正向有功费率 8 电能
    //kDataId07_0001FF00 = 0x0001FF00,    // (当前)正向有功电能数据块
    kDataId07_00020000 = 0x00020000,    // (当前)反向有功总电能
    kDataId07_00020100 = 0x00020100,    // (当前)反向有功费率 1 电能
    kDataId07_00020200 = 0x00020200,    // (当前)反向有功费率 2 电能
    kDataId07_00020300 = 0x00020300,    // (当前)反向有功费率 3 电能
    kDataId07_00020400 = 0x00020400,    // (当前)反向有功费率 4 电能
    kDataId07_00020500 = 0x00020500,    // (当前)反向有功费率 5 电能
    kDataId07_00020600 = 0x00020600,    // (当前)反向有功费率 6 电能
    kDataId07_00020700 = 0x00020700,    // (当前)反向有功费率 7 电能
    kDataId07_00020800 = 0x00020800,    // (当前)反向有功费率 8 电能
    //kDataId07_0002FF00 = 0x0002FF00,    // (当前)反向有功电能数据块
    kDataId07_01010000 = 0x01010000,    // (当前)正向有功总最大需量及发生时间
    kDataId07_01010100 = 0x01010100,    // (当前)正向有功费率 1 最大需量及发生时间
    kDataId07_01010200 = 0x01010200,    // (当前)正向有功费率 2 最大需量及发生时间
    kDataId07_01010300 = 0x01010300,    // (当前)正向有功费率 3 最大需量及发生时间
    kDataId07_01010400 = 0x01010400,    // (当前)正向有功费率 4 最大需量及发生时间
    kDataId07_01010500 = 0x01010500,    // (当前)正向有功费率 5 最大需量及发生时间
    kDataId07_01010600 = 0x01010600,    // (当前)正向有功费率 6 最大需量及发生时间
    kDataId07_01010700 = 0x01010700,    // (当前)正向有功费率 7 最大需量及发生时间
    kDataId07_01010800 = 0x01010800,    // (当前)正向有功费率 8 最大需量及发生时间
    //kDataId07_0101FF00 = 0x0101FF00,    // (当前)正向有功最大需量及发生时间数据块
    kDataId07_01020000 = 0x01020000,    // (当前)反向有功总最大需量及发生时间
    kDataId07_01020100 = 0x01020100,    // (当前)反向有功费率 1 最大需量及发生时间
    kDataId07_01020200 = 0x01020200,    // (当前)反向有功费率 2 最大需量及发生时间
    kDataId07_01020300 = 0x01020300,    // (当前)反向有功费率 3 最大需量及发生时间
    kDataId07_01020400 = 0x01020400,    // (当前)反向有功费率 4 最大需量及发生时间
    kDataId07_01020500 = 0x01020500,    // (当前)反向有功费率 5 最大需量及发生时间
    kDataId07_01020600 = 0x01020600,    // (当前)反向有功费率 6 最大需量及发生时间
    kDataId07_01020700 = 0x01020700,    // (当前)反向有功费率 7 最大需量及发生时间
    kDataId07_01020800 = 0x01020800,    // (当前)反向有功费率 8 最大需量及发生时间
    //kDataId07_0102FF00 = 0x0102FF00,    // (当前)反向有功最大需量及发生时间数据块
    kDataId07_02010100 = 0x02010100,    // A 相电压
    kDataId07_02010200 = 0x02010200,    // B 相电压
    kDataId07_02010300 = 0x02010300,    // C 相电压
    //kDataId07_0201FF00 = 0x0201FF00,    // 电压数据块(三相电压1帧读回)
    kDataId07_02020100 = 0x02020100,    // A 相电流
    kDataId07_02020200 = 0x02020200,    // B 相电流
    kDataId07_02020300 = 0x02020300,    // C 相电流
    //kDataId07_0202FF00 = 0x0202FF00,    // 电流数据块(三相电流1帧读回)
    kDataId07_02030000 = 0x02030000,    // 瞬时总有功功率
    kDataId07_02030100 = 0x02030100,    // 瞬时A相有功功率
    kDataId07_02030200 = 0x02030200,    // 瞬时B相有功功率
    kDataId07_02030300 = 0x02030300,    // 瞬时C相有功功率
    //kDataId07_0203FF00 = 0x0203FF00,    // 瞬时有功功率数据块(三相有功及总有功1帧读回)
    kDataId07_02040000 = 0x02040000,    // 瞬时总无功功率
    kDataId07_02040100 = 0x02040100,    // 瞬时A相无功功率
    kDataId07_02040200 = 0x02040200,    // 瞬时B相无功功率
    kDataId07_02040300 = 0x02040300,    // 瞬时C相无功功率
    //kDataId07_0204FF00 = 0x0204FF00,    // 瞬时无功功率数据块(三相无功及总无功1帧读回)
    kDataId07_02050000 = 0x02050000,    // 瞬时总视在功率
    kDataId07_02050100 = 0x02050100,    // 瞬时A相视在功率
    kDataId07_02050200 = 0x02050200,    // 瞬时B相视在功率
    kDataId07_02050300 = 0x02050300,    // 瞬时C相视在功率
    //kDataId07_0205FF00 = 0x0205FF00,    // 瞬时视在功率数据块(三相视在及总视在1帧读回)
    kDataId07_02060000 = 0x02060000,    // 总功率因数
    kDataId07_02060100 = 0x02060100,    // A相功率因数
    kDataId07_02060200 = 0x02060200,    // B相功率因数
    kDataId07_02060300 = 0x02060300,    // C相功率因数
    //kDataId07_0206FF00 = 0x0206FF00,    // 功率因数数据块(三相功率因数及总功率因数1帧读回)
    kDataId07_02800002 = 0x02800002,    // 电网频率
    kDataId07_02800004 = 0x02800004,    // 当前有功需量
    kDataId07_02800005 = 0x02800005,    // 当前无功需量
} DataId07_E;

2. 表地址结构体

// 表地址结构体
typedef struct {
    uint8_t addr[6];
} Addr_T;

3. 数据点信息结构体

typedef struct DataInfo_ {
    DataId07_E id;          // 数据标识
    char fotmat[32] = { 0 };// 数据格式
    int len;                // 数据长度
    char unit[32] = { 0 };  // 数据单位
    char name[128] = { 0 }; // 数据名称
} DataInfo_T;

三、Dlt645HostCh类

DLT645模式下创建通讯通道的类

1. 构造函数

构造函数,用于创建DLT645通讯通道

/**
 * @brief 构造函数
 *
 * @param *device  串口的文件描述符;
 * @param baud     波特率;
 * @param parity   校验位,可选'N'(无校验)、'O'(奇校验)、'E'(偶校验);
 * @param data_bit 数据位,可选5、6、7、8;
 * @param stop_bit 停止位,可选1、2;
 */
Dlt645HostCh(const char *device, int baud = 115200,
            char parity = 'N', int data_bit = 8, int stop_bit = 1);
  • 参数
  • *device 串口的文件描述符;
  • baud 波特率;
  • parity 校验位,可选'N'(无校验)、'O'(奇校验)、'E'(偶校验);
  • data_bit 数据位,可选5、6、7、8;
  • stop_bit 停止位,可选1、2;

2. 析构函数

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

3. 启动

/**
 * @brief 启动函数
 *
 * 启动DLT645读取读取数据
 *
 * @param 无
 *
 * @return 无
 */
void Run();
  • 参数
  • 返回值

4. 设置通讯超时时间

/**
 * @brief 设置通讯超时时间
 * 
 * @param sec  超时时间的秒数;
 * @param usec 超时时间的微秒数;
 * 
 * @return 无
 */
void SetResponseTimeout(long sec, long usec);
  • 参数
  • sec:超时时间的秒数;
  • usec:超时时间的微秒数;
  • 返回值

5. 设置Dlt645Host通讯异常的判定次数

dlt645帧通讯超时次数超过此值时,认为dlt645通讯异常

/**
 * @brief 设置dlt645通讯异常的判定次数
 *
 * dlt645帧通讯超时次数超过此值时,认为dlt645通讯异常
 *
 * @param count 次数;
 * 
 * @return 无
 */
void SetTimeoutMaxCount(uint32_t count);
  • 参数
  • count:次数;
  • 返回值

6. 轮询帧时间间隔 毫秒

/**
 * @brief 轮询帧时间间隔
 *
 * 每2帧通讯报文的之间的间隔时间
 *
 * @param ms 间隔时间,毫秒;
 * 
 * @return 无
 */
void SetPollFrameIntervalMs(uint32_t ms);
  • 参数
  • ms:每2帧通讯报文的间隔时间,毫秒;
  • 返回值

7. 轮询总时间间隔 毫秒

/**
 * @brief 轮询总时间间隔
 *
 * 所有帧通讯报文之间的间隔时间,即所有报文轮训一遍后等待一定时间后再进行下次轮训
 *
 * @param ms 所有帧通讯报文的间隔时间,毫秒;
 * 
 * @return 无
 */
void SetPollTotalIntervalMs(uint32_t ms);
  • 参数
  • ms:所有帧通讯报文的间隔时间,毫秒;
  • 返回值

8. 设置是否打印报文

/**
 * @brief 设置是否打印报文(通过printf输出到命令行中)
 * 
 * @param debug 是否开启,0-关闭;1-开启;
 * 
 * @return 无
 */
void SetDebug(int debug);
  • 参数
  • debug :是否开启,0-关闭;1-开启;
  • 返回值

9. 设置收发报文内容回调函数

/**
 * @brief 设置收发报文内容回调函数
 *
 * @param *s_callback 发送报文回调函数(参数,报文内容,报文长度);
 * @param *r_callback 接收报文回调函数(参数,报文内容,报文长度);
 * @param arg         回调参数;
 * 
 * @return 无
 */
void set_MessageCallback(
        void (*s_callback)(void *, const uint8_t *, int),
        void (*r_callback)(void *, const uint8_t *, int),
        void *arg = NULL);
  • 参数
  • *s_callback:发送报文回调函数(参数,报文内容,报文长度);
  • *r_callback:接收报文回调函数(参数,报文内容,报文长度);
  • arg:回调参数;
  • 返回值

10. 设置收发报文内容回调使能

/**
 * @brief 设置收发报文内容回调使能
 *
 * @param en 是否使能:0-未使能;1-使能;
 * 
 * @return 无
 */
void set_MessagrCallbackEn(int en);
  • 参数
  • en:是否使能:0-未使能;1-使能;
  • 返回值

四、Dlt645HostDev类

1. 构造函数1

构造函数,用于创建DLT645站点

/**
 * @brief 构造函数
 *
 * @param addrh  DLT645电表地址,高4字节
 * @param addrm  DLT645电表地址,中4字节
 * @param addrl  DLT645电表地址,低4字节
 */
Dlt645Dev(uint16_t addrh, uint16_t addrm, uint16_t addrl);
  • 参数
  • addrh DLT645电表地址,高4字节
  • addrm DLT645电表地址,中4字节
  • addrl DLT645电表地址,低4字节

2. 构造函数2

构造函数,用于创建DLT645站点

/**
 * @brief 构造函数
 *
 * @param *addr  DLT645电表地址,长度为6的数组
 */
Dlt645Dev(uint8_t *addr);
  • 参数
  • *addr DLT645电表地址,长度为6的数组

3. 构造函数3

构造函数,用于创建DLT645站点

/**
 * @brief 构造函数
 *
 * @param addr  DLT645电表地址结构
 */
Dlt645Dev(Dlt645Host::Addr_T addr);
  • 参数
  • addr DLT645电表地址结构

4. 析构函数

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

5. 获取电表站点的地址(表号)

/**
 * @brief 获取电表的地址
 *
 * @return 电表的地址
 */
Dlt645Host::Addr_T get_Addr();
  • 参数
  • 无;
  • 返回值
  • 表地址的结构体

6. 设置数据标识使能

默认情况下所有支持的数据标识都是未使能的,需要使能后才能使用

/**
 * @brief 设置使能指定的数据标识
 *
 * 默认情况下所有支持的数据标识都是未使能的,需要使能后才能使用
 *
 * @param id       枚举值,数据标识;
 * @param cycle_ms 该数据标识的通讯周期,毫秒;
 *
 * @return 无
 */
void SetDataId07En(DataId07_E id, int cycle_ms = 1000);
  • 参数
  • id 枚举值,数据标识;
  • cycle_ms 该数据标识的通讯周期,毫秒;
  • 返回值
  • 表地址的结构体

7. 获取指定数据

/**
 * @brief 获取指定数据
 *
 * @param id            枚举值,数据标识;
 * @param *value        返回参数,数据;
 * @param *refresh_time 回读成功数据刷新时间,自1970年1月1日以来的毫秒数
 * @param *arg          目前仅“最大需量及发生时间”的时间部分使用此参数,需要传输一个uint8_t tmp[5]的数组
 *
 * @return 是否获取成功:1-获取成功;-1-未使能该数据标识;-2-不支持此数据标识;
 */
int GetData(Dlt645Host::DataId07_E id, float *value,
    uint64_t *refresh_time = nullptr, uint8_t *arg = nullptr);
  • 参数
  • id 枚举值,数据标识;
  • value:返回参数,数据;
  • refresh_time:回读成功数据刷新时间,自1970年1月1日以来的毫秒数;
  • arg:目前仅“最大需量及发生时间”的时间部分使用此参数,需要传输一个uint8_t tmp[5]的数组
  • 返回值
  • 是否获取成功:1-获取成功;-1-未使能该数据标识;-2-不支持此数据标识;

8. 获取通讯超时状态

/**
 * @brief 获取通讯超时状态
 *
 * @return 通讯状态,0-未超时;1-超时;
 */
int GetCommTimeOutFlag();
  • 参数
  • 无;
  • 返回值
  • 通讯状态,0-未超时;1-超时;