功率因数读取

能读取什么

功率因数是瞬时量,表示有功与视在之比。

业务含义OI类型倍率单位
功率因数200AInt16-3无

与功率对象一样,数组是 总量 + 三相,长度 = wiring == three_phase ? 4 : 2。

standard::phase_oad(standard::oi::power_factor, standard::Phase::total, layout); // 200A/2/1
standard::phase_oad(standard::oi::power_factor, standard::Phase::a, layout);     // 200A/2/2

数据地址表

属性名称类型倍率单位读写
1逻辑名OctetString——只读
2数值Array<Int16>-3无量纲只读
3换算及单位ScalerUnit——只读
功率因数是

Int16,符号有明确含义 线上值 894 是 0.894(倍率 -3),1000 就是 1.000。符号含义:

符号业务含义
正值感性(滞后),电流滞后于电压
负值容性(超前),电流超前于电压

没有符号的功率因数在工程上是无意义的,只取绝对值会丢失容性/感性判断。用 Int16 解析,不要用 UInt16。

单位枚举是 255(无单位),unit_symbol 会返回空字符串,这是正确行为,不是缺陷。输出时自己补 PF 或留空。

最小完整示例

#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::power_factor, 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 power factor, 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* kLabels[] = {"total", "A", "B", "C"};
    for (std::size_t i = 0; i < numbers.value().size(); ++i)
        std::cout << "power factor " << kLabels[i] << " = "
                  << standard::decimal_text(numbers.value()[i]) << '\n';
    // 输出:
    // power factor total = 0.894
    // power factor A = 0.880
    // power factor B = -0.880
    // power factor C = 0.891

    client.disconnect();
    return 0;
}

常用变体

只读总功率因数

auto oad = standard::phase_oad(oi::power_factor, standard::Phase::total, layout); // 200A/2/1
auto value = client.get(oad.value());

判断容性还是感性

ScaledNumber::raw 是 variant<int64_t, uint64_t>,功率因数落在有符号分支:

auto numbers = standard::engineering_values(oad.value(), data, layout);
if (numbers && !numbers.value().empty()) {
    const auto& pf = numbers.value()[0];
    // decimal_text 保留符号,直接看文本首字符最省事
    const std::string text = standard::decimal_text(pf);
    const bool capacitive = !text.empty() && text.front() == '-';
    std::cout << (capacitive ? "capacitive" : "inductive") << '\n';
}

与功率交叉校验

// 有功 2010.0 W、视在 6500.0 VA → 2010/6500 ≈ 0.309
// 设备读出的 200A 才是权威值

两者偏差超过几个百分点时,先确认功率的单位和倍率(W 还是 kW),再看设备是否配置了错误的互感器变比。

请求与响应报文

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

读取总功率因数

请求(200A/2/1):

68 17 00 43 05 00 00 00 00 00 00 00 72 79 05 01 00 20 0A 02 01 00 93 7B 16

响应(Int16 894,即 0.894):

68 1C 00 C3 05 00 00 00 00 00 00 00 BC FF 85 01 00 20 0A 02 01 01 10 03 7E 00 00 39 B5 16
字段字节含义
85服务:GET-Response
01GET-Normal
00PIID-ACD=0
20 0A 02 01回显 OAD:功率因数,属性 2,索引 1(总量)
01选择子:Data
10数据类型:Int16
03 7E原始值 894
00 / 00FollowReport / TimeTag 不存在

03 7E = 894,乘以 10^-3 得 0.894。数据类型 10 是 Int16,与功率的 05(Int32)不同。

读取功率因数数组

请求(200A/2/0):

68 17 00 43 05 00 00 00 00 00 00 00 72 79 05 01 00 20 0A 02 00 00 4B 62 16

响应(四项 Int16):

68 27 00 C3 05 00 00 00 00 00 00 00 6A 2E 85 01 00 20 0A 02 00 01 01 04 10 03 7E 10 03 70 10 FC 90 10 03 7B 00 00 82 96 16

解析:01(Data)→ 01(数组)→ 04(4 项):

索引原始字节原始值工程值性质
1 总量03 7E8940.894感性
2 A 相03 708800.880感性
3 B 相FC 90-880-0.880容性
4 C 相03 7B8910.891感性

B 相的 FC 90 是补码表示的 -880(0x10000 - 0x0390 = 0xFC90),这正是符号位生效的地方。decimal_text 会输出 -0.880。

读取 A 相功率因数

请求(200A/2/2,索引 2 = A 相):

68 17 00 43 05 00 00 00 00 00 00 00 72 79 05 01 00 20 0A 02 02 00 FB 51 16

相关配置

配置位置说明
DeviceLayout::wiring库本地配置三相为 4 项,单相为 2 项
互感器变比电表内部配置不在 698 点表里,是设备出厂参数;变比错会导致功率和功率因数都不对

常见失败

现象原因处理
负功率因数显示为正按 UInt16 解析Int16 补码,必须用有符号类型
值显示为 894 而非 0.894忘了倍率 -3走 engineering_values 或自己乘 10^-3
unit_symbol 返回空单位枚举是 255(无单位)功率因数无量纲,属正常
数组只有 2 项单相表Wiring::single_phase 下长度是 2
与 P/S 算出的值差几个百分点互感器变比或采样不同步以设备读数为准,检查设备配置