我正在尝试从串口读取MBUS电报。 我将serialport中的所有内容放入一个字节数组中。
每个MBUS电报都以此模式开始(十六进制):68 XX XX 68
其中XX是字节中电报的长度。
实施例: Example http://img97.imageshack.us/img97/6004/mbustele.jpg
在这里你看到一个例子,突出显示了长度为99的电报的开头(十六进制)
我想将每个电报添加到像这样的列表中
List<byte[]> telegramms;
如何实现这一目标?
答案 0 :(得分:1)
我刚刚在VisualStudio 2010中输入了这个内容,它对endian-ness做了各种各样的假设,并且没有管理MBus数据包比串口的采样字节大的潜在问题,或者更重要的是,如果数据包 header 本身跨越串行端口的数据包之间的边界。
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace StackOverflowTest
{
[TestClass]
public class ByteTest
{
private bool FindEndMark(byte[] source, int index, out int size)
{
int endIndex = index + 3;
if (endIndex > source.Count())
{
// need to cope with the fact that the datapacket might be shorter than the MBus message.
throw new Exception("end count > length of array");
}
if (source[endIndex] == 0x68)
{
// According to the updated spec, the size is emitted twice as a verification
if (source[index + 1] == source[index + 2])
{
size = source[index] + 1;
return true;
}
}
size = 0;
return false;
}
[TestMethod]
public void FindMbusDatagram()
{
byte[] src = new byte[]
{
// Random junk to start
00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 0xa, 0xb, 0xc, 0xd,
// An MBus Packet
0x68, 06, 00, 0x68, 08, 05, 72, 00, 00, 00,
// More junk
00, 00, 00, 0x16, 00, 00, 00, 00, 01,
// Put a rogue 0x68 in so we can prove we don't get false positives in the datastream
0x68, 03, 04, 05, 06, 07, 08, 09, 0xa, 0xb, 0xc, 0xd,
// Another Packet
0x68, 01, 00, 0x68, 0xFF,
//final junk
00, 16, 00, 00, 00, 01, 02, 03
};
List<byte[]> packets = new List<byte[]>();
for (int i = 0; i < src.Length; i++ )
{
if (src[i] != 0x68)
{
continue;
}
else
{
int packetSize = 0;
if (FindEndMark(src, i, out packetSize))
{
if (packetSize > (src.Length - i))
{
// read more data from your port and append it somehow.
}
else
{
// We're packetSize+4 includes the header information + checksum and end
// NB: packetSize+5 is a checksum byte
// NB: packetSize+6 should be 0x16 according to the MBus spec.
byte[] packet = new byte[packetSize + 4];
int count = 0;
// Copy the packet + header into a byte[]
for (int j = i; j < (i + packetSize + 4); j++)
{
packet[count++] = src[j];
}
packets.Add(packet);
// Move the counter along
i += (packetSize + 4);
}
}
}
}
// Should have two packets here.
Assert.IsTrue(packets.Count > 0);
}
}
}
答案 1 :(得分:0)
这是我的尝试,你怎么看?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MBUS_Parse_Test.MDL64_Communication
{
/// <summary>
/// Extracts MBUS telegramms
/// </summary>
class GetMBUS_Telegramms
{
#region Eigenschaften
private static List<MbusTelegram> telegrams = new List<MbusTelegram>();
#endregion
public static List<MbusTelegram> GetTelegramms(byte[] logfile)
{
int startOfTele = ExtractFirstMBUSTelegramm(logfile);
while (startOfTele != 0)
{
byte[] NewLogFile = new byte[logfile.Length - startOfTele];
Buffer.BlockCopy(logfile, startOfTele, NewLogFile, 0, NewLogFile.Length);
startOfTele = ExtractFirstMBUSTelegramm(NewLogFile);
logfile = NewLogFile;
}
return telegrams;
}
private static int ExtractFirstMBUSTelegramm(byte[] logfile)
{
byte mbus_start = 0x68;
int Start = Array.IndexOf(logfile, mbus_start);
int offset = 10;
if (logfile[Start + 3] == mbus_start)
{
byte[] newMBUS = new byte[logfile[Start + 1] + offset];
Buffer.BlockCopy(logfile, Start, newMBUS, 0, logfile[Start + 1] + offset);
MbusTelegram nuMBUS = new MbusTelegram(newMBUS);
telegrams.Add(nuMBUS);
return (Start + logfile[Start + 1] + offset);
}
return 0;
}
private System.Array ResizeArray(System.Array oldArray, int newSize)
{
int oldSize = oldArray.Length;
System.Type elementType = oldArray.GetType().GetElementType();
System.Array newArray = System.Array.CreateInstance(elementType, newSize);
int preserveLength = System.Math.Min(oldSize, newSize);
if (preserveLength > 0)
System.Array.Copy(oldArray, newArray, preserveLength);
return newArray;
}
}
}