电流读取

能读取什么

电流是瞬时量,按相别分为 A、B、C 三相。属性 2 是数值组:

  • 索引 0:整个数组(三相全部)
  • 索引 1/2/3:分别是 A/B/C 相

电流没有"总"这一项,三相电流求和没有业务含义。

业务含义OI类型倍率单位
电流2001Int32-3A
零线电流属性 4Int32-3A

电流相关的另外两个对象:

业务含义OI说明
电流波形失真度200C见谐波与波形失真度
电流谐波含有量200E见谐波与波形失真度

数据地址表

属性名称类型倍率单位读写说明
1逻辑名OctetString——只读通常不读
2数值Array<Int32>-3A只读索引 0 整体,1/2/3 = A/B/C
3换算及单位ScalerUnit——只读设备声明的倍率和单位
4零线电流Int32-3A只读三相四线才有意义

数组长度 = wiring == three_phase ? 3 : 1。

电流是

Int32,不是 UInt32 电流有符号:反向流动时读数为负。线上 Int32 5000 是 +5.000 A,Int32 -5000 是 -5.000 A。用无符号类型解析会把负电流显示成巨大的正数。

单位是 A,倍率 -3 是毫安级分辨率,线上 5000 是 5.000 A。

最小完整示例

#include <dlt698/app.hpp>
#include <dlt698/standard/catalog.hpp>
#include <iostream>

int main() {
    using namespace dlt698;
    namespace oi = standard::oi;

    const standard::DeviceLayout layout{standard::Wiring::three_phase, 4, 21};

    app::ClientOptions options;
    options.protocol.server.bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    app::Client client(options);
    auto connected = client.connect_tcp("127.0.0.1", 6980);
    if (!connected) {
        std::cerr << connected.error().context << '\n';
        return 1;
    }

    auto oad = standard::make_oad(oi::current, 2, 0, layout);
    if (!oad) {
        std::cerr << oad.error().context << '\n';
        client.disconnect();
        return 1;
    }

    auto value = client.get(oad.value());
    if (!value) {
        std::cerr << value.error().context << '\n';
        client.disconnect();
        return 1;
    }
    if (const auto dar = std::get_if<std::uint8_t>(&value.value())) {
        std::cerr << "meter does not provide current, DAR=" << unsigned(*dar) << '\n';
        client.disconnect();
        return 1;
    }

    const auto& data = std::get<model::Data>(value.value());
    auto numbers = standard::engineering_values(oad.value(), data, layout);
    if (!numbers) {
        std::cerr << numbers.error().context << '\n';
        client.disconnect();
        return 1;
    }
    static const char* kPhases[] = {"A", "B", "C"};
    for (std::size_t i = 0; i < numbers.value().size(); ++i)
        std::cout << "current " << kPhases[i] << " = "
                  << standard::decimal_text(numbers.value()[i]) << ' '
                  << standard::unit_symbol(numbers.value()[i].scaling.unit) << '\n';
    // 输出:
    // current A = 5.000 A
    // current B = 4.980 A
    // current C = 5.010 A

    client.disconnect();
    return 0;
}

常用变体

读单相电流

auto a = standard::phase_oad(oi::current, standard::Phase::a, layout); // 2001/2/1
auto b = standard::phase_oad(oi::current, standard::Phase::b, layout); // 2001/2/2
auto c = standard::phase_oad(oi::current, standard::Phase::c, layout); // 2001/2/3

auto result = client.get_list({a.value(), b.value(), c.value()});

读零线电流

零线电流是独立属性,不是数组元素,索引固定 0:

auto oad = standard::make_oad(oi::current, 4, 0, layout); // 2001/4/0
auto value = client.get(oad.value());
if (value && !std::get_if<std::uint8_t>(&value.value())) {
    const auto& data = std::get<model::Data>(value.value());
    auto numbers = standard::engineering_values(oad.value(), data, layout);
    if (numbers && !numbers.value().empty())
        std::cout << "neutral = "
                  << standard::decimal_text(numbers.value()[0]) << ' '
                  << standard::unit_symbol(numbers.value()[0].scaling.unit) << '\n';
    // Int32 1200 → 1.200 A
}
三相不平衡度检测

把三相电流和零线电流一起读,就能算不平衡度:

auto phases = standard::make_oad(oi::current, 2, 0, layout);
auto neutral = standard::make_oad(oi::current, 4, 0, layout);
// 正常三相四线:零线电流接近 0 A
// 零线电流明显不为 0:可能存在接线错误或单相负荷

不是所有设备都提供属性 4,不支持时返回 DAR=4,属正常。

请求与响应报文

以下示例固定:SA 六个 00 字节、逻辑地址 0、CA=0、PIID=0、控制域请求 43/响应 C3。

读取 A 相电流

请求(2001/2/1):

68 17 00 43 05 00 00 00 00 00 00 00 72 79 05 01 00 20 01 02 01 00 86 BB 16

响应(Int32 5000,即 5.000 A):

68 1E 00 C3 05 00 00 00 00 00 00 00 9E 54 85 01 00 20 01 02 01 01 05 00 00 13 88 00 00 DC DF 16
字段字节含义
85服务:GET-Response
01GET-Normal
00PIID-ACD=0
20 01 02 01回显 OAD:电流,属性 2,索引 1(A 相)
01选择子:Data
05数据类型:Int32
00 00 13 88原始值 5000
00 / 00FollowReport / TimeTag 不存在

注意数据类型是 05(Int32),不是电压用的 12(UInt16)。

读取三相电流数组

请求(2001/2/0):

68 17 00 43 05 00 00 00 00 00 00 00 72 79 05 01 00 20 01 02 00 00 5E A2 16

响应(三项 Int32):

68 2A 00 C3 05 00 00 00 00 00 00 00 04 99 85 01 00 20 01 02 00 01 01 03 05 00 00 13 88 05 00 00 13 74 05 00 00 13 92 00 00 DE 7C 16

解析:01(Data)→ 01(数组)→ 03(3 项)→ 3 个 05(Int32):

索引原始字节原始值工程值
1 A 相00 00 13 8850005.000 A
2 B 相00 00 13 7449804.980 A
3 C 相00 00 13 9250105.010 A

读取零线电流

请求(2001/4/0):

68 17 00 43 05 00 00 00 00 00 00 00 72 79 05 01 00 20 01 04 00 00 87 74 16

响应(Int32 1200,即 1.200 A):

68 1E 00 C3 05 00 00 00 00 00 00 00 9E 54 85 01 00 20 01 04 00 01 05 00 00 04 B0 00 00 1F AE 16

相关配置

配置位置说明
DeviceLayout::wiring库本地配置三相为 3 项,单相为 1 项
SessionOptions::request_timeout库连接参数单次 GET 超时,默认 5 秒

常见失败

现象原因处理
DAR=4 读属性 4设备没有零线电流测量三相三线设备通常不提供,属正常
负电流显示成大正数按 UInt32 解析电流是 Int32,engineering_values 会保留符号
数组长度校验失败wiring 配错单相表按三相校验会失败
三相电流都是 0设备只累计不测量,或未接入互感器纯计量型终端可能不提供实时量
值比预期大 1000 倍把原始整数当成了工程值线上 5000 是 5.000 A,倍率 -3