DLT645接口说明
一、使用示例
创建1条DLT645通讯通道,在这条通道上创建2个DLT645电表,循环获取2个电表的数据
#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. 表地址结构体
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. 析构函数
3. 启动
- 参数
- 无
- 返回值
- 无
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站点
- 参数
- *addr DLT645电表地址,长度为6的数组
3. 构造函数3
构造函数,用于创建DLT645站点
- 参数
- addr DLT645电表地址结构
4. 析构函数
5. 获取电表站点的地址(表号)
- 参数
- 无;
- 返回值
- 表地址的结构体
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. 获取通讯超时状态
- 参数
- 无;
- 返回值
- 通讯状态,0-未超时;1-超时;