diff --git a/Core/ModbusRtuCodec.c b/Core/ModbusRtuCodec.c
index 3da4910..1946906 100644
--- a/Core/ModbusRtuCodec.c
+++ b/Core/ModbusRtuCodec.c
@@ -129,6 +129,151 @@ int MrcSlaveGetLenStream(Stream_t* st)
return MrcSlaveGetLength(p, remain);
}
+/// <summary>通过包头计算数据长度,不校验</summary>
+/// <param name="p">最少给3个字节的数组</param>
+/// <returns>理论上包长。-1 数据包类型不对,0 p为null</returns>
+static int _masterCalcRxLen(byte* p)
+{
+ if (p == NULL)return 0;
+
+ byte cmd = p[1];
+ switch (cmd)
+ {
+ case 1:
+ case 2:
+ {
+ byte bitlen = p[2];
+ byte bytelen = (bitlen + 7) / 8;
+ // addr+cmd+bitcnt + 2crc * 5
+ int pklen = 5 + bytelen;
+
+ return pklen;
+ }
+ case 3:
+ case 4:
+ {
+ byte bytelen = p[2];
+ // addr+cmd+bytelen+2crc = 5
+ int pklen = 5 + bytelen;
+
+ return pklen;
+ }
+
+ case 5:
+ case 6:
+ case 0xf:
+ case 0x10:
+ {
+ return 8;
+ }
+
+ default: return -1;
+ }
+}
+
+int MrcMasterGetRxLength(byte* p, int len)
+{
+ if (p == NULL)return 0;
+ if (len < 5)return 0;
+
+ int pklen = _masterCalcRxLen(p);
+
+ // 数据包类型不对
+ if (pklen < 0)return -1;
+ // 长度超出
+ if (pklen > 130)return -2;
+ // 长度不够
+ if (pklen > len)return 0;
+
+ if (Check(p, pklen))return pklen;
+ // 校验失败
+ return -1;
+}
+
+int MrcMasterGetRxLenCircularQueue(CircularQueue_t* queue)
+{
+ if (queue == NULL)return 0;
+ int remian = CircularQueueGetLength(queue);
+ if (remian < 6)return 0;
+
+ // 缓冲
+ byte cache[130];
+ // 读3个字节判断长度
+ CircularQueueReads(queue, cache, 3, true);
+ int pklen = _masterCalcRxLen(cache);
+ // 数据包类型不对
+ if (pklen < 0)return -1;
+ // 长度超出
+ if (pklen > 130)return -2;
+ // 数据包长度
+ if (pklen > remian)return 0;
+
+ // if (sizeof(cache) >= pklen)
+ // {
+
+ // 直接使用缓冲区读出来判断
+ CircularQueueReads(queue, cache, pklen, true);
+ if (Check(cache, pklen))return pklen;
+ // 校验失败
+ return -1;
+
+ // }
+ // else
+ // {
+ // // 再弄一个缓冲区使用
+ // byte* p = (byte*)GlobleMalloc(pklen);
+ // if (p == NULL)return -1;
+ //
+ // // 读出来校验一下
+ // CircularQueueReads(queue, p, pklen, true);
+ // bool crcok = Check(p, pklen);
+ // GlobleFree(p);
+ //
+ // if (crcok)return pklen;
+ // // 校验失败
+ // return -1;
+ // }
+}
+
+int MrcMasterGetRxLenStream(Stream_t* st)
+{
+ int remain = st->Size - st->Position;
+ byte* p = &st->MemStart[st->Position];
+
+ return MrcMasterGetRxLength(p, remain);
+}
+
+/// <summary>获取应答消息内负载数据的偏移量</summary>
+/// <param name="pkt">已经校验通过的数据包</param>
+/// <returns>返回偏移量,-1 消息类型错误,0 无负载数据</returns>
+int MrcMasterGetRxPyOffset(byte* pkt)
+{
+ if (pkt == NULL)return 0;
+
+ byte cmd = pkt[1];
+ switch (cmd)
+ {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ {
+ return 3;
+ }
+ case 5:
+ case 6:
+ {
+ return 4;
+ }
+ case 0x0f:
+ case 0x10:
+ {
+ return 0;
+ }
+ default: return -1;
+ }
+}
+
// 01 02 请求指令。 len = 8
int Mrc01a02(byte addr, byte cmd, ushort regaddr, ushort bitlen, byte* data, int len)
{
diff --git a/Core/ModbusRtuCodec.h b/Core/ModbusRtuCodec.h
index b420b31..fa8b476 100644
--- a/Core/ModbusRtuCodec.h
+++ b/Core/ModbusRtuCodec.h
@@ -4,8 +4,9 @@
#include "Stream.h"
#include "CircularQueue.h"
-/*
+// Modbus Rtu Controller (Mrc)
+/*
1: 读线圈
2: 读离散输入
3: 读多个保持寄存器
@@ -15,8 +16,6 @@
15 写多个线圈
16 写多个寄存器
-// modbus 请求包格式
-
// 请求包
// 01 addr+cmd+2regaddr+2bitcnt+2crc
// 02 addr+cmd+2regaddr+2bitcnt+2crc
@@ -33,7 +32,7 @@
// 03 addr+cmd+bytelen+ (bytelen*data) +2crc
// 04 addr+cmd+bytelen+ (bytelen*data) +2crc
// 05 06 等于请求包
-// 10 addr+cmd+2regaddr+2bitcnt+2crc
+// 0f addr+cmd+2regaddr+2bitcnt+2crc
// 10 addr+cmd+2regaddr+2regcnt+2crc
解释:
@@ -57,6 +56,21 @@ int MrcSlaveGetLength(byte* data, int len);
int MrcSlaveGetLenCircularQueue(CircularQueue_t* queue);
int MrcSlaveGetLenStream(Stream_t* st);
+// 获取有效的modbus rtu数据包长度(会校验数据包)
+// 应答消息的长度(从机发送给主机的回复消息)
+// 0 没有足够长度的数据。
+// -1 数据包校验出错
+// -2 数据长度不对,modbus rtu 数据包小于 130 字节。
+int MrcMasterGetRxLength(byte* p, int len);
+int MrcMasterGetRxLenCircularQueue(CircularQueue_t* queue);
+int MrcMasterGetRxLenStream(Stream_t* st);
+
+/// <summary>获取应答消息内负载数据的偏移量</summary>
+/// <param name="pkt">已经校验通过的数据包</param>
+/// <returns>返回偏移量,-1 消息类型错误,0 无负载数据</returns>
+int MrcMasterGetRxPyOffset(byte* pkt);
+
+
// 01 02 请求指令。 len = 8
int Mrc01a02(byte addr, byte cmd, ushort regaddr, ushort bitlen, byte* data, int len);
// 01 02 指令回复。 len > (bitlen+7)/8 + 5;
diff --git a/Core/ModbusTcpCodec.c b/Core/ModbusTcpCodec.c
index fde0edd..8247506 100644
--- a/Core/ModbusTcpCodec.c
+++ b/Core/ModbusTcpCodec.c
@@ -38,6 +38,37 @@ int MtcGetLenStream(Stream_t* st)
return res;
}
+/// <summary>获取应答消息内负载数据的偏移量</summary>
+/// <param name="pkt">已经校验通过的数据包</param>
+/// <returns>返回偏移量,-1 消息类型错误,0 无负载数据</returns>
+int MtcMasterGetRxPyOffset(byte* pkt)
+{
+ if (pkt == NULL)return 0;
+
+ byte cmd = pkt[1];
+ switch (cmd)
+ {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ {
+ return 3 + 6;
+ }
+ case 5:
+ case 6:
+ {
+ return 4 + 6;
+ }
+ case 0x0f:
+ case 0x10:
+ {
+ return 0;
+ }
+ default: return -1;
+ }
+}
+
// 01 02 请求指令。 len = 12
int Mtc01a02(MtcHead_t* head, byte cmd, ushort regaddr, ushort bitlen, byte* data, int len)
{
diff --git a/Core/ModbusTcpCodec.h b/Core/ModbusTcpCodec.h
index dc7ef96..8ce6bfa 100644
--- a/Core/ModbusTcpCodec.h
+++ b/Core/ModbusTcpCodec.h
@@ -1,21 +1,15 @@
#pragma once
#include "Type.h"
-
-
-#include "CircularQueue.h"
#include "Stream.h"
+#include "CircularQueue.h"
-// 获取 modbus tcp/udp 数据包长度,不区分请求和应答
-int MtcGetLength(byte* p, int len);
-int MtcGetLenCircularQueue(CircularQueue_t* queue);
-int MtcGetLenStream(Stream_t* st);
-
+// Modbus Tcp Controller (Mtc)
// modbus tcp/udp 相对于 rtu 来说,头部增加了 6字节,尾部少2字节。
// 其余部分一致。参考 modbus-rtu 即可。
-// rtu addr cmd ndata 2crc
-// tcp 2seq 2pro 2len addr cmd ndata
+// rtu: addr cmd ndata 2crc
+// tcp: 2seq 2pro 2len addr cmd ndata
/*
1: 读线圈
@@ -28,6 +22,16 @@ int MtcGetLenStream(Stream_t* st);
16 写多个寄存器
*/
+// 获取 modbus tcp/udp 数据包长度,不区分请求和应答
+int MtcGetLength(byte* p, int len);
+int MtcGetLenCircularQueue(CircularQueue_t* queue);
+int MtcGetLenStream(Stream_t* st);
+
+/// <summary>获取应答消息内负载数据的偏移量</summary>
+/// <param name="pkt">已经校验通过的数据包</param>
+/// <returns>返回偏移量,-1 消息类型错误,0 无负载数据</returns>
+int MtcMasterGetRxPyOffset(byte* pkt);
+
#pragma pack(push)
#pragma pack(1)
typedef struct