Skip to main content

DL/T 645

The Zeus DL/T 645 module targets electric meters and energy acquisition devices. It supports common DL/T 645-2007 read/write flows and handles reversed meter addresses, leading 0xFE wake-up bytes, dual 0x68 headers, the 0x33 data offset, checksums, exception codes, and low-byte-first BCD decoding.

Run Without Hardware

const string meterAddress = "000000000001";

var memory = new Dlt645SlaveMemory();
memory.SetBcd(0x00000000, 1234.56, byteLength: 4, scale: 0.01);
memory.SetBcd(0x02010100, 220.5, byteLength: 2, scale: 0.1);

await using var app = ZeusHost.Create(builder =>
{
builder.AddVirtualChannel("meter-link", new Dlt645SlaveResponder(meterAddress, memory));
builder.AddDlt645(
"meter",
"meter-link",
new Dlt645Options { MeterAddress = meterAddress, WakeUpPreambleCount = 0 },
points: map => map
.Bcd("energy", 0x00000000, dataLength: 4, scale: 0.01)
.Bcd("voltageA", 0x02010100, dataLength: 2, scale: 0.1));
});

await app.StartAsync();
ComponentMeaning
Dlt645SlaveMemoryVirtual meter data item memory, keyed by four-byte DI
Dlt645SlaveResponder(address, memory)Simulates one DL/T 645 meter address
AddDlt645("meter", "meter-link", options)Registers a DL/T 645 device on an existing channel
.Bcd("energy", 0x00000000, 4, 0.01)Maps total active energy into the point table

Runnable sample: samples/Zeus.Samples.Console.Dlt645.

Real Meters

DL/T 645 usually runs over RS-485 serial lines. The channel only moves bytes; Dlt645Device handles the meter address and protocol frame:

await using var app = ZeusHost.Create(builder =>
{
builder.AddSerialPort("meter-link", "COM3", 2400);
builder.AddDlt645(
"meter",
"meter-link",
new Dlt645Options
{
MeterAddress = "000000000001",
WakeUpPreambleCount = 4
},
points: map => map.TotalActiveEnergy("energy"));
});

For transparent TCP-to-serial gateways, switch only the channel:

builder.AddTcpClient("meter-link", "192.168.1.50", 5000);
builder.AddDlt645("meter", "meter-link", new Dlt645Options { MeterAddress = "000000000001" });

Direct Reads And Writes

var meter = app.Devices.Get<Dlt645Device>("meter");

var energy = await meter.ReadBcdAsync(0x00000000, byteLength: 4, scale: 0.01);
var voltageA = await meter.ReadBcdAsync(0x02010100, byteLength: 2, scale: 0.1);

var raw = await meter.ReadDataAsync(0x04000401);
await meter.WriteBcdAsync(0x04000101, 88.8, byteLength: 2, scale: 0.1);

ReadDataAsync returns payload bytes without the four-byte DI and without the protocol 0x33 offset. BCD values are decoded low-byte-first; a four-byte item with scale: 0.01 is commonly used for XXXXXX.XX energy values.

Point Polling

builder.AddAcquisition(TimeSpan.FromSeconds(1));
builder.AddDlt645("meter", "meter-link", new Dlt645Options { MeterAddress = "000000000001" }, points: map => map
.Bcd("energy", 0x00000000, dataLength: 4, scale: 0.01, alarmLimits: new PointAlarmLimits(high: 10000))
.Bcd("voltageA", 0x02010100, dataLength: 2, scale: 0.1)
.RawBytes("status", 0x04000401, dataLength: 1));
Point TypePoint ValueNotes
BcddoubleEngineering value after scale; supports alarm limits and write-back
RawBytesbyte[]Raw payload bytes for status words or vendor extensions

Common helpers:

map.TotalActiveEnergy("energy"); // DI 00000000, 4 bytes, 0.01 kWh
map.VoltageA("voltageA"); // DI 02010100, 2 bytes, 0.1 V
map.CurrentA("currentA"); // DI 02020100, 3 bytes, 0.001 A

JSON Configuration

{
"channels": [
{
"name": "meter-link",
"type": "serial",
"portName": "COM3",
"baudRate": 2400
}
],
"devices": [
{
"name": "meter",
"channel": "meter-link",
"type": "dlt645",
"meterAddress": "000000000001",
"wakeUpPreambleCount": 4,
"points": [
{ "name": "energy", "address": "0x00000000", "dataType": "bcd", "dataLength": 4, "scale": 0.01 },
{ "name": "voltageA", "address": "0x02010100", "dataType": "bcd", "dataLength": 2, "scale": 0.1 },
{ "name": "status", "address": "0x04000401", "dataType": "raw", "dataLength": 1 }
]
}
]
}

For hardware-free tests, replace the channel with:

{
"name": "meter-link",
"type": "virtual",
"responder": "dlt645",
"meterAddress": "000000000001"
}

Copyable configuration sample: samples/Zeus.Samples.Console.Config/zeus-dlt645.json.

Common Data Items

Data ItemCommon MeaningSuggested Declaration
0x00000000Current total active energydataLength: 4, scale: 0.01
0x02010100Phase A voltagedataLength: 2, scale: 0.1
0x02020100Phase A currentdataLength: 3, scale: 0.001

Vendor extensions vary by meter model, so use the meter protocol manual or project point list as the final source of truth.