DLT645-2007協(xié)議是由中國電力公司發(fā)布的一種用于電能表與外部設(shè)備(如集抄終端)之間通信的標(biāo)準(zhǔn)協(xié)議。它主要用于實(shí)時(shí)獲取電能表的數(shù)據(jù),支持?jǐn)?shù)據(jù)傳輸、參數(shù)設(shè)定、控制等功能。該協(xié)議的傳輸方式一般是通過串口或TCP/IP網(wǎng)絡(luò)進(jìn)行。DLT645-2007協(xié)議結(jié)構(gòu)簡單,以數(shù)據(jù)幀的形式組織信息。每幀數(shù)據(jù)包含起始符、地址域、控制域、數(shù)據(jù)域和校驗(yàn)碼等信息。
1.起始符:一般為“0x68”字節(jié)。
2.地址域:用于標(biāo)識電能表的地址,通常為1個字節(jié)。
3.控制域:定義操作類型(讀、寫等),一般為1個字節(jié)。
4.數(shù)據(jù)域:包含實(shí)際傳輸?shù)臄?shù)據(jù),長度可變。
5.校驗(yàn)碼:用于校驗(yàn)數(shù)據(jù)的完整性,通常采用LRC(縱向冗余校驗(yàn))。
6.結(jié)束符:標(biāo)志報(bào)文結(jié)束
在DLT645-2007協(xié)議中,所有數(shù)據(jù)的傳輸都需要校驗(yàn)和控制,確保數(shù)據(jù)的正確性和可靠性。
FE FE FE FE //數(shù)據(jù)起始
68 //幀起始符
62 01 76 00 00 81 //地址域
68 //幀起始符
11 //控制碼
04 //數(shù)據(jù)域長度
35 37 33 37 //數(shù)據(jù)域
15 //校驗(yàn)碼
16 //結(jié)束符
如下所示的是智能DLT645-2007通信時(shí)的控制碼格式,通過不同的控制碼,可以實(shí)現(xiàn)對電表進(jìn)行寫入或讀取電表的數(shù)據(jù)信息。
發(fā)送咨詢用電量命令:fefefefe 68 292507072120 68 11 04 33333333 4e16
格式講解
fefefefe 數(shù)據(jù)頭每條數(shù)據(jù)都要帶
68 針起始符
292507072120 表號 解析為 202107072529 從右向左每一個16進(jìn)制byte拼接在一起,就是電表貼的條碼上的數(shù)字
68 針起始符
11 控制碼 讀取的意思
04 讀取寄存器的數(shù)據(jù)長度
33333333 寄存器,解析為要讀取00000000號寄存器,從右向左每一個16進(jìn)制-33(16進(jìn)制拼接) (33-33)+(33-33)+(33-33)+(33-33)=00000000
4e 校驗(yàn)位和后兩位 68+29+25+07+07+21+20+68+11+04+33+33+33+33=24e 取后兩位=4e
16 結(jié)束符
接收到數(shù)據(jù)fefefefe 68 292507072120 68 91 08 33333333 a94a3633 2e16
格式講解
fefefefe 數(shù)據(jù)頭每條數(shù)據(jù)都要帶
68 針起始符
292507072120 表號 解析為 202107072529 從右向左每一個16進(jìn)制byte拼接在一起
68 針起始符
91 控制碼 讀取的意思
08 返回寄存器加數(shù)據(jù)的長度為8個byte
33333333 寄存器,解析為要讀取00000000號寄存器,從右向左每一個16進(jìn)制-33(16進(jìn)制拼接) (33-33)+(33-33)+(33-33)+(33-33)=00000000
a94a3633 返回的數(shù)據(jù),代表電量, 從右向左每一個16進(jìn)制-33(16進(jìn)制拼接)(33-33)+(36-33)+(4a-33)+(a9-33)=31776*0.01=317.76 kw/h
2e 校驗(yàn)位和后兩位,除去數(shù)據(jù)頭對其它數(shù)據(jù)進(jìn)行16進(jìn)制相加68+29+25+07+07+21+20+68+11+04+33+33+33+33+a9+4a+36+33=42e 取后兩位=2e
16 結(jié)束符
public void decode(OperatorSupplier supplier, DeviceSession deviceSession, ProtocolMessage<?> message, MessageExporter<DeviceMessage<?>> messageExporter) {
TcpProtocolMessage message1 = (TcpProtocolMessage) message;
ByteBuf payload = message1.getPayload();
/*byte[] bytes = new byte[payload.readableBytes()];
payload.readBytes(bytes);
String payloadStr = HexStringUtil.bytes2HexStr(bytes);*/
if (payload.readableBytes() < 6) {
return; // 數(shù)據(jù)不足,等待更多數(shù)據(jù)
}
// 獲取起始符(0x68)
byte startByte = payload.readByte();
if (startByte != (byte) 0x68) {
throw new ServiceException("Invalid start byte");
}
// 獲取數(shù)據(jù)長度
int length = payload.readByte(); // 假設(shè)1字節(jié)長度字段
if (payload.readableBytes() < length + 2) {
return; // 等待數(shù)據(jù)完整
}
// 解析數(shù)據(jù)域
byte[] data = new byte[length];
payload.readBytes(data);
// 校驗(yàn)數(shù)據(jù)(LRC校驗(yàn))
byte checkByte = payload.readByte();
if (!checkLRC(data, checkByte)) {
throw new ServiceException("LRC checksum failed");
}
// 構(gòu)造消息實(shí)體通過消息總線發(fā)布
DLT645Data dlt645Data = new DLT645Data(data);
}
校驗(yàn)方法
private boolean checkLRC(byte[] data, byte checkByte) {
byte lrc = 0;
for (byte b : data) {
lrc ^= b;
}
return lrc == checkByte;
}
以上就是對于DLT645協(xié)議的解析,如有不足之處望大家多多指出,我們加以學(xué)習(xí)改進(jìn)。