Skip to content

23108-DLT64507-1P 对接文档

传感器简介

DL/T645-2007 单相电能表,余三码BCD采集单相电量(电压/电流/功率/功率因数/电能/频率),通过 KC11 市电版 DTU 接入,支持 subDevice 表地址识别

项目
项目名称MT-23108-DLT64507-1P
厂商门思科技 (ManThink)
型号DLT64507-1P
业务代码23108
对接模式edgebus-dtu
协议dlt645

模型清单

可使用下列名称或 ID 在 ThinkLink 中搜索对应模型。

模型类型名称id_name平台模型 ID
RPC[DLT64507-1P GET] paradlt64507_1p_get_23108101062552481435653
RPC[DLT64507-1P SET] paradlt64507_1p_set_23108101062392342908933
TemplateDLT64507-1P101062927179583493
Thing Model[DLT64507-1P]dlt64507_1p_23108101059204525068293
Thing Model[MT-23108-DLT64507-1P资产] 区域聚合dlt64507_1p_asset_23108119677189950959622
Parameter Thing Model[DLT64507-1P-PARA]dlt64507_1p_para_23108101058843898810373

产品特点与适用范围

本项目面向“DL/T645-2007 单相电能表”场景。能力边界、字段和可部署模型均以当前 descriptor、requirements 与模型源文件为准。

部署与采集信息

| DTU | KC11 | | 供电 | ac | | LoRaWAN Class | C | | 接口 | RS-485 | | 波特率 | 9600 |

遥测与寄存器定义

字段名称类型单位地址/来源说明
energy_import_total正向有功总电能bcdLE4kWhDLT645 DI3正向有功总电能
energy_export_total反向有功总电能bcdLE4kWhDLT645 DI3反向有功总电能
voltage电压bcdLE2VDLT645 DI3单相电压
current电流bcdLE3ADLT645 DI3单相电流
active_power有功功率bcdLE3kWDLT645 DI3单相有功功率
reactive_power无功功率bcdLE3kvarDLT645 DI3单相无功功率
power_factor功率因数bcdLE2DLT645 DI3单相功率因数
frequency电网频率bcdLE2HzDLT645 DI3电网频率

参数定义

参数名称类型默认值范围单位说明
app_38pwron_delayuint16LE0-65535ms
app_70period_upuint32LE0-4294967295s
app_74period_readuint32LE0-4294967295s
app_150addr_modbusuint811-247

Requirements 证据

以下关键事实由 requirements 源文件提取;原始行号用于复核。

类别来源事实来源
协议/数据> 补抓的 input/单相电表协议对接.md 手册(协议细节)+ descriptor.yaml(机型/模式)回填。requirement/requirements.md:4
部署| DTU Power Mode | AC 85–270V(市电,KC11 恒为常供电,无需确认) |requirement/requirements.md:22
部署| LoRaWAN Class | Class C(eb/23108-DLT64507-1P.ts otaConfig 注释「非电池供电,Class C模式」,Battery:false) |requirement/requirements.md:23
部署> KC11 恒为市电供电(Class C),供电方式无歧义,不适用 KB-37 的「电池/常电」确认门。requirement/requirements.md:26
部署- 场景2:配电室/箱式变电站单相支路计量 — 民用/商业配电室内的单相照明或辅助支路计量点,KC11 市电供电与配电柜本身供电一致,免电池维护。requirement/requirements.md:33
协议/数据- 遵循国标 DL/T645-2007 通信协议 — 兼容绝大多数国产单相电能表,行业互通性好。requirement/requirements.md:39
部署- 常电供电(KC11 市电版)— 与电表本身取电一致,无需额外电池维护。requirement/requirements.md:40
协议/数据- 支持 RS-485 长距离总线 — 可多表共享一条总线(本项目通过表地址实现 subDevice 区分)。requirement/requirements.md:41
未确认事项| Voltage | 电表本身取电网供电(AC,具体额定值手册未标注);DTU 为 KC11 市电版 AC 85–270V | descriptor.yaml / TODO(电表自身额定电压手册未给出,需用户/厂商手册补充) |requirement/requirements.md:56
未确认事项| Power Consumption | TODO — 手册未标注 | TODO |requirement/requirements.md:57
部署| Power-on to Stable Working | 1s(默认) | 说明书未标注,默认为 1 秒。如实际设备需要更长时间请修改。 |requirement/requirements.md:63
协议/数据| Interface Type | RS-485(另提供 UART 调试口,仅用于工厂/现场调试,不用于正常上行) |requirement/requirements.md:69
部署| Baud Rate | 手册标注 2400bps;⚠️ 实际部署的 eb/23108-DLT64507-1P.ts otaConfig 配置为 9600bps(见 §11 决策记录,需用户现场确认真实波特率) |requirement/requirements.md:70
部署电表 UART(GND/RX/TX/12V) ── 仅调试用,不接入正常部署requirement/requirements.md:79
部署KC11 AC L/N ──────── 市电 85–270V 供电(KC11 自身取电)requirement/requirements.md:80
部署| AC L/N | 市电供电 | KC11 电源输入(DTU 自身取电,市电版无需再给电表供电——电表由电网自身供电) |requirement/requirements.md:88
部署DTU-specific wiring notes:requirement/requirements.md:90
部署- KC11:AC L/N 供电 DTU 本身(85–270V)。RS-485A/485B 接电表。总线较长时可用 120Ω 端接电阻(短接到 485A)。requirement/requirements.md:92
协议/数据| Protocol Type | dlt645(DL/T645-2007) |requirement/requirements.md:100
协议/数据| Device Default Address | 无固定默认地址;每台电表出厂地址不同,通过「读电表地址」命令(控制码 0x13)获取 6 字节 BCD 地址,用作 subDevice 地址 |requirement/requirements.md:101
协议/数据| Frame Format | 68 <地址域 6B, BCD小端> 68 <控制码 1B> <数据长度 1B> <数据域(余三码)> <校验和 1B> 16;总线唤醒时可在帧首加前导 FE FE FE FE |requirement/requirements.md:102
协议/数据> 标准协议帧结构为 DL/T645-2007 通用格式(国网《多功能电能表通信协议》),逐项字段以下方 §5.2/§9 已生成的 EB/物模型解析逻辑为准。requirement/requirements.md:105
部署来源:eb/23108-DLT64507-1P.ts quInfo 注释 + thinklink/thingModel/dlt64507_1p_23108.js payload_parser(权威,已部署)。requirement/requirements.md:109
协议/数据| 正向有功总电能 (energy_import_total) | 00010000 | bcdle4 | 4 | 0.01 | R | EPI_T |requirement/requirements.md:113

EdgeBus 代码

以下为当前使用的 EdgeBus 业务代码。

typescript
import { Buffer } from "buffer";
import { buildOtaFile } from "@EBSDK/run";
import {
    ActionAfertExpr, CalcData,
    CrcMode,
    CvtRule,
    EBBuffer,
    EBModel,
    ExprCondition,
    LoraUpEvent,
    QueryEvent, SetUpCovDataType,UserConfUPItem,EventInfoItem
} from "@EBSDK/EBCompiler/all_variable";
import { CheckbitEnum, getOtaConfig, HwTypeEnum, UpgrdTypeEnum } from "@EBSDK/otaConfig";
////////////////////////////////////////////////////////////////////////////////////////
const eventInfo: UserConfUPItem[] = [
    {
        name: "DLT64507_1P", port: 22, version: "0x87", dataType: "0x08",
        upPeriodIndex: 70, indexAddr: 5, addrSize: 6,
        quInfo: [
            // 正向有功总电能,listVal[0] = EPI_T,DI: 00010000
            {
                protocol: "DLT64507", periodIndex: 74,
                indexAPP: 150, indexCMD: 1, copySize: 6, preamble: 4,
                cmd: "0x68 22 01 13 07 11 25 68 11 04 33 33 34 33 25 16",
                ack: "0x68 22 01 13 07 11 25 68 91 08 33 33 34 33 33 33 33 33 75 16",
                listVal: [{ start: "14", end: "17" }]
            },
            // 反向有功总电能,listVal[0] = EPO_T,DI: 00020000
            {
                protocol: "DLT64507", periodIndex: 74,
                indexAPP: 150, indexCMD: 1, copySize: 6, preamble: 4,
                cmd: "0x68 22 01 13 07 11 25 68 11 04 33 33 35 33 26 16",
                ack: "0x68 22 01 13 07 11 25 68 91 08 33 33 35 33 33 33 33 33 76 16",
                listVal: [
                    { start: "14", end: "17" }
                ]
            },
            // 电压,listVal[0] = U,DI: 02010100
            {
                protocol: "DLT64507", periodIndex: 74,
                indexAPP: 150, indexCMD: 1, copySize: 6, preamble: 4,
                cmd: "0x68 22 01 13 07 11 25 68 11 04 33 34 34 35 28 16",
                ack: "0x68 22 01 13 07 11 25 68 91 06 33 34 34 35 33 33 10 16",
                listVal: [
                    { start: "14", end: "15" }
                ]
            },
            // 电流,listVal[0] = I,DI: 02020100
            {
                protocol: "DLT64507", periodIndex: 74,
                indexAPP: 150, indexCMD: 1, copySize: 6, preamble: 4,
                cmd: "0x68 22 01 13 07 11 25 68 11 04 33 34 35 35 29 16",
                ack: "0x68 22 01 13 07 11 25 68 91 07 33 34 35 35 33 33 33 45 16",
                listVal: [
                    { start: "14", end: "16" }
                ]
            },
            // 有功功率,listVal[0] = P,DI: 02030000
            {
                protocol: "DLT64507", periodIndex: 74,
                indexAPP: 150, indexCMD: 1, copySize: 6, preamble: 4,
                cmd: "0x68 22 01 13 07 11 25 68 11 04 33 33 36 35 29 16",
                ack: "0x68 22 01 13 07 11 25 68 91 07 33 33 36 35 33 33 33 45 16",
                listVal: [
                    { start: "14", end: "16" }
                ]
            },
            // 无功功率,listVal[0] = Q,DI: 02040000
            {
                protocol: "DLT64507", periodIndex: 74,
                indexAPP: 150, indexCMD: 1, copySize: 6, preamble: 4,
                cmd: "0x68 22 01 13 07 11 25 68 11 04 33 33 37 35 2A 16",
                ack: "0x68 22 01 13 07 11 25 68 91 07 33 33 37 35 33 33 33 46 16",
                listVal: [
                    { start: "14", end: "16" }
                ]
            },
            // 功率因数,listVal[0] = PF,DI: 02060000
            {
                protocol: "DLT64507", periodIndex: 74,
                indexAPP: 150, indexCMD: 1, copySize: 6, preamble: 4,
                cmd: "0x68 22 01 13 07 11 25 68 11 04 33 33 39 35 2C 16",
                ack: "0x68 22 01 13 07 11 25 68 91 06 33 33 39 35 33 33 14 16",
                listVal: [
                    { start: "14", end: "15" }
                ]
            },
            // 电网频率,listVal[0] = FREQ,DI: 02800000
            {
                protocol: "DLT64507", periodIndex: 74,
                indexAPP: 150, indexCMD: 1, copySize: 6, preamble: 4,
                cmd: "0x68 22 01 13 07 11 25 68 11 04 33 33 B3 35 A6 16",
                ack: "0x68 22 01 13 07 11 25 68 91 06 33 33 B3 35 33 33 8E 16",
                listVal: [
                    { start: "14", end: "15" }
                ]
            }
        ]
    }
]
let otaConfig = getOtaConfig({
    BaudRate: 9600,
    StopBits: 1,
    DataBits: 8,
    Checkbit: CheckbitEnum.EVEN,
    Battery: false, // 非电池供电,Class C模式
    ConfirmDuty: 60,
    BzType: 23108,
    BzVersion: 11
})
const MODBUS_TT = (ebModel: EBModel) => {
    for (let i=0; i<eventInfo.length; i++){
        let event=new EventInfoItem(eventInfo[i]);
        event.upEventSetup()
        event.eventInstall()
    }
    return JSON.stringify(ebModel, null, 2)
}
buildOtaFile(import.meta.url, otaConfig, MODBUS_TT)

物模型与 RPC 代码

RPC: [DLT64507-1P GET] para

id_name: dlt64507_1p_get_23108 · ID: 101062552481435653

javascript
import {RPCHelper, Utils} from '#tklHelper';

function rpc_script({ device, params, alarms, logger, org_params }) {
let paraDef= {
        app_70: {name: "period_up", field_name: "period_up", unit: "s",  type: "uint32LE"},
        app_74: {name: "period_read", field_name: "period_read", unit: "s", type: "uint32LE"},
        app_150: {name: "addr_645", field_name: "addr_645", unit: "", type: "hexBE6"}
    }
    let frames=RPCHelper.buildFrame({
        paraDef:paraDef,
        params:params});
    let msg=RPCHelper.makeMSG({
        msgType:Utils.msgType.paras,
        device:device,
        dnBuffer:frames.readBuffer,
        sleepTime:0,
    })
    return [msg]
}
rpc_script({
    device: { server_attrs: {}, shared_attrs: {} },
    params: {},
    alarms: [],
    logger: console,
    org_params: {}
})

RPC: [DLT64507-1P SET] para

id_name: dlt64507_1p_set_23108 · ID: 101062392342908933

javascript
import {RPCHelper, Utils} from '#tklHelper';
import {Buffer} from "buffer";

function rpc_script({ device, params, alarms, logger, org_params }) {
let classMode = (device && device.shared_attrs && device.shared_attrs.class_mode) || "ClassA";
    const rpcName="dlt64507_1p_para_23108"
    let paraDef= {
        app_70: {name: "period_up", field_name: "period_up", unit: "s",  type: "uint32LE"},
        app_74: {name: "period_read", field_name: "period_read", unit: "s", type: "uint32LE"},
        app_150: {name: "addr_645", field_name: "addr_645", unit: "", type: "hexBE6"}
    }
    logger.info("set paras")
    let frames=RPCHelper.buildFrame({
        paraDef:paraDef,
        params:params});
    let redoBuffer=RPCHelper.redo()
    let dnBuffer=Buffer.alloc(frames.writeBuffer.length+frames.readBuffer.length);
    frames.writeBuffer.copy(dnBuffer,0)
    frames.readBuffer.copy(dnBuffer,frames.writeBuffer.length)
    let msgQue=Utils.makeParaSetMSG({
        device:device,
        classMode:classMode,
        rpcName:rpcName,
        params:params,
        paraDownBuffer:dnBuffer,
        extraAppBuffer:redoBuffer
    })
    if (msgQue.length==0)  return null
    return msgQue
}
rpc_script({
    device: { server_attrs: {}, shared_attrs: {} },
    params: {},
    alarms: [],
    logger: console,
    org_params: {}
})

Thing Model: [DLT64507-1P]

id_name: dlt64507_1p_23108 · ID: 101059204525068293

javascript
import {BufferTKL, RPCHelper} from '#tklHelper';
import {Buffer} from "buffer";

function payload_parser(device, msg, thingModelId, noticeAttrs, org_params) {
let frameInfo = {
        port: 22, dataLen: 34, rssi: true,
        subDevice: { index: 5, type: "hexBE6" },
        tagList: [
            { index: 0, tag: 0x87 },
            { index: 1, tag: 0x08 }
        ]
    };

    if (msg?.userdata?.payload === undefined) return null;
    if (msg?.userdata?.payload === "") return null;
    /**
     * DLT645 采用余三码:
     * EB 上行中 appData 保存的是表计原始回复数据,
     * 即每个数据字节仍然是 +0x33 后的值。
     *
     * 因此在进入 PayParser 前,需要把应用数据区逐字节 -0x33。
     *
     * 注意:
     * 0-10 字节为 EB 上行头 + 表地址,不处理。
     * 11 字节开始为 DLT645 数据区,需要处理余三码。
     */
    let payload = Buffer.from(msg.userdata.payload, "base64");

    // 从 offset 11 开始是 appData,全部做 DLT645 余三码还原
    for (let i = 11; i < payload.length; i++) {
        payload[i] = (payload[i] - 0x33 + 0x100) & 0xff;
    }

    // 将处理后的 payload 写回 msg,供 PayParser 使用
    msg = JSON.parse(JSON.stringify(msg));
    msg.userdata.payload = payload.toString("base64");

    let appInfo = [
        // 正向 / 反向有功总电能
        {name: "正向有功总电能", unit: "kWh", field_name: "energy_import_total", index: 11, dataType: "bcdle4", coefficient: 0.01, decimal: 2},
        {name: "反向有功总电能", unit: "kWh", field_name: "energy_export_total", index: 15, dataType: "bcdle4", coefficient: 0.01, decimal: 2},
        // 单相电压 / 电流
        {name: "电压", unit: "V", field_name: "voltage", index: 19, dataType: "bcdle2", coefficient: 0.1, decimal: 1},
        {name: "电流", unit: "A", field_name: "current", index: 21, dataType: "bcdle3", coefficient: 0.001, decimal: 3},
        // 有功 / 无功功率
        {name: "有功功率", unit: "kW", field_name: "active_power",index: 24, dataType: "bcdle3", coefficient: 0.0001, decimal: 4},
        {name: "无功功率", unit: "kvar", field_name: "reactive_power", index: 27, dataType: "bcdle3", coefficient: 0.0001, decimal: 4},
        // 功率因数
        {name: "功率因数", unit: "", field_name: "power_factor", index: 30, dataType: "bcdle2", coefficient: 0.001, decimal: 3},
        // 电网频率
        {name: "电网频率", unit: "Hz", field_name: "frequency", index: 32, dataType: "bcdle2", coefficient: 0.01, decimal: 2}
    ];
    let payParser = new PayParser({
        device: device,
        msg: msg,
        frameInfo: frameInfo,
        appInfo: appInfo
    });

    let tdata = payParser.telemetry();

    if ((tdata?.status & 0x02) === 0x02) {
        // timeout,只更新 status,保留原来的遥测数据
        const status = tdata.status;
        tdata = {
            ...(device.telemetry_data?.[thingModelId] ?? {})
        };
        tdata.status = status;
    }

    let result = {
        sub_device: tdata?.addr === undefined ? null : tdata.addr,
        telemetry_data: tdata,
        server_attrs: null,
        shared_attrs: {
            class_mode: msg?.userdata?.class
        }
    };
    // ── rpcHook (设备对接通用规则) ──
    if (typeof RPCHelper.buildRpcHookAction === "function") {
      const __a = RPCHelper.buildRpcHookAction({ device, msg, thingModelId, idName: "dlt64507_1p_23108", name: "[DLT64507-1P]", parsed: { telemetry_data: result.telemetry_data, server_attrs: result.server_attrs, shared_attrs: result.shared_attrs } });
      if (__a) { result.actions = result.actions || []; result.actions.push(__a); }
    }
    return result;
}
console.log(payload_parser(
    { telemetry_data: {} },
    { userdata: { port: 11, payload: "" } },
    "1",
    { telemetry_data: true },
    {}
))

Thing Model: [MT-23108-DLT64507-1P资产] 区域聚合

id_name: dlt64507_1p_asset_23108 · ID: 119677189950959622

javascript
import {PayloadParser, RPCHelper} from '#tklHelper';

// 资产(VIRTUAL)聚合物模型 — 通用 agg_spec 驱动聚合器,见 docs/references/workflow/asset-aggregation-model.md
// device=资产, msg=源设备快照, thingModelId=本物模型ID, noticeAttrs=变更标记。
// 聚合规格在资产 server_attrs.agg_spec:min_snr=取最小(snr);min_rssi=取最小(rssi);zone_current_sum=时点累加(current);zone_voltage_avg=空间均值(voltage);zone_frequency_avg=空间均值(frequency);zone_active_power_sum=时点累加(active_power);zone_power_factor_avg=空间均值(power_factor);zone_reactive_power_sum=时点累加(reactive_power);zone_energy_export_total_sum=谨慎累加(energy_export_total);zone_energy_import_total_sum=谨慎累加(energy_import_total);online_count=在线数(—)
function payload_parser(device, msg, thingModelId, noticeAttrs) {
    if (!noticeAttrs || !noticeAttrs.telemetry_data) {
        return { telemetry_data: null, server_attrs: null, shared_attrs: null };
    }
    const sa      = device?.server_attrs || {};
    const spec    = sa.agg_spec || {};
    const members = { ...(sa.members || {}) };
    const staleMs = sa.stale_ms != null ? sa.stale_ms : 600000;
    const now     = (typeof Date !== "undefined" && Date.now) ? Date.now() : null;

    // 合并源设备各物模型的最新快照为一个扁平对象
    const srcTd = {};
    const all = msg?.telemetry_data || {};
    for (const k in all) { Object.assign(srcTd, all[k]); }

    // 收集 spec 引用到的全部源字段,把本帧带到的值并进该成员快照
    const want = {};
    for (const out in spec) { if (spec[out].src) want[spec[out].src] = true; }
    const got = {}; let touched = false;
    for (const f in want) { if (srcTd[f] !== undefined && srcTd[f] !== null) { got[f] = srcTd[f]; touched = true; } }
    if (touched && msg && msg.eui) {
        const prev = (members[msg.eui] && members[msg.eui].v) || {};
        const seq  = (members[msg.eui] && members[msg.eui].ts) || 0;
        members[msg.eui] = { v: Object.assign({}, prev, got), ts: now != null ? now : seq + 1 };
    }

    const euis = Object.keys(members);
    const fresh = euis.filter(function (e) {
        if (now == null || staleMs <= 0) return true;
        const ts = members[e].ts;
        return ts != null && ts <= now && (now - ts) <= staleMs;
    });
    const num = function (x) { return (x != null && !isNaN(x)) ? Number(x) : null; };

    const out = {};
    for (const field in spec) {
        const op = spec[field].op, src = spec[field].src;
        if (op === "count_online") { out[field] = fresh.length; continue; }
        const pool = (op === "sum_cumul") ? euis : fresh;
        const vals = pool.map(function (e) { return num(members[e].v && members[e].v[src]); }).filter(function (x) { return x != null; });
        if (op === "avg")        out[field] = vals.length ? Number((vals.reduce(function (a, b) { return a + b; }, 0) / vals.length).toFixed(2)) : null;
        else if (op === "sum_snap" || op === "sum_cumul") out[field] = vals.length ? Number(vals.reduce(function (a, b) { return a + b; }, 0).toFixed(3)) : null;
        else if (op === "max")   out[field] = vals.length ? Math.max.apply(null, vals) : null;
        else if (op === "min")   out[field] = vals.length ? Math.min.apply(null, vals) : null;
        else if (op === "or")    out[field] = pool.some(function (e) { const x = members[e].v && members[e].v[src]; return x != null && x != 0; }) ? 1 : 0;
        else if (op === "count_on") out[field] = pool.filter(function (e) { const x = members[e].v && members[e].v[src]; return x != null && x != 0; }).length;
        else out[field] = null;
    }
    let result = { telemetry_data: out, server_attrs: { members: members }, shared_attrs: null };
    // ── rpcHook (设备对接通用规则) ──
    if (typeof RPCHelper.buildRpcHookAction === "function") {
      const __a = RPCHelper.buildRpcHookAction({ device, msg, thingModelId, idName: "dlt64507_1p_asset_23108", name: "[MT-23108-DLT64507-1P资产] 区域聚合", parsed: { telemetry_data: result.telemetry_data, server_attrs: result.server_attrs, shared_attrs: result.shared_attrs } });
      if (__a) { result.actions = result.actions || []; result.actions.push(__a); }
    }
    return result;
}

// --- local debug ---(两台成员先后上报;平台会把返回的 members 持久化回 device,这里手动模拟)
const agg_spec = {
  "min_snr": {
    "op": "min",
    "src": "snr"
  },
  "min_rssi": {
    "op": "min",
    "src": "rssi"
  },
  "zone_current_sum": {
    "op": "sum_snap",
    "src": "current"
  },
  "zone_voltage_avg": {
    "op": "avg",
    "src": "voltage"
  },
  "zone_frequency_avg": {
    "op": "avg",
    "src": "frequency"
  },
  "zone_active_power_sum": {
    "op": "sum_snap",
    "src": "active_power"
  },
  "zone_power_factor_avg": {
    "op": "avg",
    "src": "power_factor"
  },
  "zone_reactive_power_sum": {
    "op": "sum_snap",
    "src": "reactive_power"
  },
  "zone_energy_export_total_sum": {
    "op": "sum_cumul",
    "src": "energy_export_total"
  },
  "zone_energy_import_total_sum": {
    "op": "sum_cumul",
    "src": "energy_import_total"
  },
  "online_count": {
    "op": "count_online",
    "src": ""
  }
};
const device = { name: "MT-23108-DLT64507-1P资产-1", server_attrs: { agg_spec, stale_ms: 1800000, members: {} } };
const r1 = payload_parser(device, { eui: "MEMBER_A", telemetry_data: { m1: {"snr":1,"rssi":1,"current":1,"voltage":1,"frequency":1,"active_power":1,"power_factor":1,"reactive_power":1,"energy_export_total":1,"energy_import_total":1} } }, "tmid", { telemetry_data: true });
device.server_attrs.members = r1.server_attrs.members;            // 平台持久化
console.log("成员A上报后:", JSON.stringify(r1.telemetry_data));
const r2 = payload_parser(device, { eui: "MEMBER_B", telemetry_data: { m1: {"snr":2,"rssi":2,"current":2,"voltage":2,"frequency":2,"active_power":2,"power_factor":2,"reactive_power":2,"energy_export_total":2,"energy_import_total":2} } }, "tmid", { telemetry_data: true });
device.server_attrs.members = r2.server_attrs.members;
console.log("成员B上报后(2台聚合):", JSON.stringify(r2.telemetry_data));
void PayloadParser;

Parameter Thing Model: [DLT64507-1P-PARA]

id_name: dlt64507_1p_para_23108 · ID: 101058843898810373

javascript
import {PayloadParser, RPCHelper, Utils} from '#tklHelper';

function payload_parser(device, msg, thingModelId, noticeAttrs, org_params) {
let    port=msg?.userdata?.port || null;
    const rpcName="dlt64507_1p_para_23108"
    let paraDef= {
        app_70: {name: "period_up", field_name: "period_up", unit: "s",  type: "uint32LE"},
        app_74: {name: "period_read", field_name: "period_read", unit: "s", type: "uint32LE"},
        app_150: {name: "addr_645", field_name: "addr_645", unit: "", type: "hexBE6"}
    }
    if (port!==214) {
        let checkData=Utils.paraCheck(rpcName,device.server_attrs,device.shared_attrs)
        return {
            server_attrs: checkData.sdata,
            actions:checkData.actions,
        }
    }
    let pdata=(new PayloadParser({
        device:device,
        msg:msg,
        paraInfo:paraDef,
    })).paras()
    let checkData= Utils.paraCheck(rpcName,device.server_attrs,pdata)
    let result = {
        telemetry_data: pdata,
        server_attrs: checkData.sdata,
        shared_attrs: pdata,
        actions: checkData.actions,
    };
    // ── rpcHook (设备对接通用规则) ──
    if (typeof RPCHelper.buildRpcHookAction === "function") {
      const __a = RPCHelper.buildRpcHookAction({ device, msg, thingModelId, idName: "dlt64507_1p_para_23108", name: "[DLT64507-1P-PARA]", parsed: { telemetry_data: result.telemetry_data, server_attrs: result.server_attrs, shared_attrs: result.shared_attrs } });
      if (__a) { result.actions = result.actions || []; result.actions.push(__a); }
    }
    return result;
}
console.log(payload_parser(
    { telemetry_data: {} },
    { userdata: { port: 11, payload: "" } },
    "1",
    { telemetry_data: true },
    {}
))

物模型字段定义

物模型字段类型单位名称
dlt64507_1p_23108snrnumberdBSNR
dlt64507_1p_23108rssinumberdBmRSSI
dlt64507_1p_23108currentnumberACurrent
dlt64507_1p_23108voltagenumberVVoltage
dlt64507_1p_23108frequencynumberHzGrid Frequency
dlt64507_1p_23108active_powernumberkWTotal Active Power
dlt64507_1p_23108power_factornumberPower Factor
dlt64507_1p_23108reactive_powernumberkvarReactive Power
dlt64507_1p_23108energy_export_totalnumberkWhTotal Export Active Energy
dlt64507_1p_23108energy_import_totalnumberkWhTotal Import Active Energy
dlt64507_1p_asset_23108min_snrnumberdBZone SNR
dlt64507_1p_asset_23108min_rssinumberdBmZone RSSI
dlt64507_1p_asset_23108zone_current_sumnumberAZone Current
dlt64507_1p_asset_23108zone_voltage_avgnumberVZone Voltage
dlt64507_1p_asset_23108zone_frequency_avgnumberHzZone Grid Frequency
dlt64507_1p_asset_23108zone_active_power_sumnumberkWZone Total Active Power
dlt64507_1p_asset_23108zone_power_factor_avgnumberZone Power Factor
dlt64507_1p_asset_23108zone_reactive_power_sumnumberkvarZone Reactive Power
dlt64507_1p_asset_23108zone_energy_export_total_sumnumberkWhZone Total Export Active Energy
dlt64507_1p_asset_23108zone_energy_import_total_sumnumberkWhZone Total Import Active Energy
dlt64507_1p_asset_23108online_countnumberZone Online Count
dlt64507_1p_para_23108addr_645stringDL/T 645 Address
dlt64507_1p_para_23108period_upnumbersUpload Period
dlt64507_1p_para_23108period_readnumbersCollect Period

RPC 参数定义

RPC参数类型说明默认值单位
dlt64507_1p_set_23108addr_645stringDL/T 645 Addresshex
dlt64507_1p_set_23108period_upnumberUpload Period (s)s
dlt64507_1p_set_23108period_readnumberCollect Period (s)s

触发器定义

无项目专用触发器。

第三方平台数据订阅

MQTT Topic: /v32/{Organization Account}/tkl/up/telemetry/{eui}

json
{
  "eui": "6353012af10a9331",
  "active_time": "2026-07-13T08:35:48.000Z",
  "thingModelId": "Use the platform model ID from the model inventory",
  "thingModelIdName": "Use the current telemetry model id_name",
  "telemetry_data": {
    "snr": 13.5,
    "rssi": -51,
    "battery": 3.37,
    "energy_import_total": 1.25,
    "energy_export_total": 2.5,
    "voltage": 3.75,
    "current": 5,
    "active_power": 6.25,
    "reactive_power": 7.5,
    "power_factor": 8.75,
    "frequency": 10
  }
}

模板选择与验证

在 ThinkLink 平台按项目名称、业务代码或模型清单中的 id_name、ID 搜索并绑定模型。部署后使用真实上行帧核对字段、单位、RPC 和触发器行为。

补充说明

需求与决策依据:requirement/requirements.md