190 lines
5.7 KiB
C#
190 lines
5.7 KiB
C#
|
|
using System.Buffers;
|
|||
|
|
using System.Buffers.Binary;
|
|||
|
|
using System.ComponentModel.DataAnnotations;
|
|||
|
|
using System.IO.Ports;
|
|||
|
|
|
|||
|
|
|
|||
|
|
//string bx = "4F000000780000004F00000078000000000000000000";
|
|||
|
|
|
|||
|
|
//ReadOnlySpan<byte> rs = Convert.FromHexString(bx);
|
|||
|
|
//int x = rs.Length;
|
|||
|
|
//ushort checksum = Crc16IbmSdlc.ComputeChecksum(rs);
|
|||
|
|
|
|||
|
|
string bufp = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
|
|||
|
|
string buf = "ffffffffc0ffffff003f00c1";
|
|||
|
|
|
|||
|
|
Span<byte> discoverID = [ 0xff, 0xff, 0xff];
|
|||
|
|
Span<byte> curID = [ 0xff, 0xf9, 0x07 ];
|
|||
|
|
Span<byte> curIDrest = [ 0x00, 0x00, 0xc2, 0x01, 0x00 ];
|
|||
|
|
|
|||
|
|
byte[] bufferp = Convert.FromHexString(bufp);
|
|||
|
|
byte[] buffer = Convert.FromHexString(buf);
|
|||
|
|
byte[] buffer2 = new byte[256];
|
|||
|
|
|
|||
|
|
ReadOnlySpan<byte> bConnect = MakeConnect(4, curID, curIDrest);
|
|||
|
|
ReadOnlySpan<byte> bDiscover = MakeDiscover(discoverID);
|
|||
|
|
string hexString;
|
|||
|
|
|
|||
|
|
SerialPort sp = new SerialPort("COM3", 9600);
|
|||
|
|
sp.Open();
|
|||
|
|
sp.BaudRate = 9600; sp.Parity = Parity.None; sp.DataBits = 8; sp.StopBits = StopBits.One;
|
|||
|
|
sp.DtrEnable = true;
|
|||
|
|
sp.RtsEnable = true;
|
|||
|
|
|
|||
|
|
sp.ReadTimeout = 1000;
|
|||
|
|
sp.Handshake = Handshake.RequestToSend;
|
|||
|
|
for (int ix = 0; ix < 2; ix++)
|
|||
|
|
{
|
|||
|
|
hexString = Convert.ToHexString(bDiscover);
|
|||
|
|
Console.WriteLine($"-> Discover {hexString}");
|
|||
|
|
sp.BaseStream.Write(bDiscover);
|
|||
|
|
|
|||
|
|
int b = sp.Read(buffer2, 0, 255);
|
|||
|
|
hexString = Convert.ToHexString(buffer2,0,b);
|
|||
|
|
Console.WriteLine($"<- ok {b} bytes: {hexString}");
|
|||
|
|
Thread.Sleep(500);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
sp.ReadTimeout = 1000;
|
|||
|
|
sp.DiscardInBuffer();
|
|||
|
|
sp.DiscardOutBuffer();
|
|||
|
|
for (int ix = 0; ix < 2; ix++)
|
|||
|
|
{
|
|||
|
|
hexString = Convert.ToHexString(bConnect);
|
|||
|
|
Console.WriteLine($"-> Connect {hexString}");
|
|||
|
|
sp.BaseStream.Write(bConnect);
|
|||
|
|
int b = sp.Read(buffer2, 0, 255);
|
|||
|
|
hexString = Convert.ToHexString(buffer2, 0, b);
|
|||
|
|
Console.WriteLine($"<- ok {b} bytes: {hexString}");
|
|||
|
|
Thread.Sleep(500);
|
|||
|
|
} //-> "C0FFF907879994C1"
|
|||
|
|
|
|||
|
|
//for (int ix = 0; ix < 32; ix++)
|
|||
|
|
//{
|
|||
|
|
// //hexString = Convert.ToHexString(makeBuf, 0, makeBuf.Length);
|
|||
|
|
// //Console.WriteLine($"-> {hexString}");
|
|||
|
|
// //sp.Write(makeBuf, 0, makeBuf.Length);
|
|||
|
|
// int b = 0;
|
|||
|
|
// try
|
|||
|
|
// {
|
|||
|
|
// b = sp.Read(buffer2, 0, 255);
|
|||
|
|
// }
|
|||
|
|
// catch (TimeoutException)
|
|||
|
|
// {
|
|||
|
|
// Console.WriteLine("Read timeout");
|
|||
|
|
// }
|
|||
|
|
// if (b > 0)
|
|||
|
|
// {
|
|||
|
|
// hexString = Convert.ToHexString(buffer2, 0, b);
|
|||
|
|
// Console.WriteLine($"ok {b} bytes: {hexString}");
|
|||
|
|
|
|||
|
|
// }
|
|||
|
|
//} //-> "C0FFF907879994C1"
|
|||
|
|
|
|||
|
|
|
|||
|
|
sp.Close();
|
|||
|
|
|
|||
|
|
Console.ReadLine();
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
ReadOnlySpan<byte> MakeDiscover(Span<byte> discoverID)
|
|||
|
|
{
|
|||
|
|
return BuildPacket(64, discoverID , new byte[] { 0x00 });
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ReadOnlySpan<byte> MakeConnect(int syncbytes, ReadOnlySpan<byte> ID, ReadOnlySpan<byte> IDrest)
|
|||
|
|
{
|
|||
|
|
byte[] packet = new byte[1 + ID.Length + IDrest.Length];
|
|||
|
|
|
|||
|
|
packet[0] = 0x07; //connectcommnand
|
|||
|
|
ID.CopyTo(packet.AsSpan(1));
|
|||
|
|
IDrest.CopyTo(packet.AsSpan(1 + ID.Length));
|
|||
|
|
|
|||
|
|
return BuildPacket(syncbytes, ID, packet);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ReadOnlySpan<byte> BuildPacket(int syncbytes, ReadOnlySpan<byte> ID, byte[] payload)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
ArrayBufferWriter<byte> writer = new ArrayBufferWriter<byte>();
|
|||
|
|
if (syncbytes > 0)
|
|||
|
|
{
|
|||
|
|
Span<byte> span = writer.GetSpan(syncbytes);
|
|||
|
|
span.Fill(0xFF);
|
|||
|
|
writer.Advance(syncbytes);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
writer.Write(new byte[] { 0xC0 }); // STX
|
|||
|
|
int startCS = writer.WrittenCount;
|
|||
|
|
if (ID!=ReadOnlySpan<byte>.Empty) writer.Write(ID);
|
|||
|
|
|
|||
|
|
// 3. Schrijf de dynamische payload
|
|||
|
|
writer.Write(payload);
|
|||
|
|
|
|||
|
|
// 4. Pak alle geschreven data, maar sla de eerste byte (index 0) over via Slice(1)
|
|||
|
|
ReadOnlySpan<byte> dataToChecksum = writer.WrittenSpan.Slice(startCS);
|
|||
|
|
|
|||
|
|
// Bereken de 16-bit checksum
|
|||
|
|
ushort checksum = Crc16IbmSdlc.ComputeChecksum(dataToChecksum);
|
|||
|
|
|
|||
|
|
// 5. Reserveer ruimte voor de staart: 2 bytes checksum + 1 finale byte = 3 bytes
|
|||
|
|
Span<byte> tailSpan = writer.GetSpan(3);
|
|||
|
|
|
|||
|
|
// Checksum wegschrijven in Little Endian (LSB eerst, dan MSB)
|
|||
|
|
tailSpan[0] = (byte)(checksum & 0xFF); // Least Significant Byte
|
|||
|
|
tailSpan[1] = (byte)((checksum >> 8) & 0xFF); // Most Significant Byte
|
|||
|
|
|
|||
|
|
// Finale byte toevoegen
|
|||
|
|
tailSpan[2] = 0xc1; // ETX (End of Text)
|
|||
|
|
|
|||
|
|
// Geef door aan de writer dat we exact 3 bytes hebben toegevoegd
|
|||
|
|
writer.Advance(3);
|
|||
|
|
|
|||
|
|
// 6. Return het resultaat (of stuur writer.WrittenSpan direct naar je Socket)
|
|||
|
|
return writer.WrittenSpan;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
byte[] MakeBuf(int synccount, string prefix, string id, string playloadrest, string suffix)
|
|||
|
|
{
|
|||
|
|
// Calculate lengths
|
|||
|
|
int prefixLen = prefix.Length / 2;
|
|||
|
|
int idLen = id.Length / 2;
|
|||
|
|
int payloadLen = playloadrest.Length / 2;
|
|||
|
|
int suffixLen = suffix.Length / 2;
|
|||
|
|
int chkLen = 2; // 2 bytes for the CRC16
|
|||
|
|
|
|||
|
|
int blen = synccount + chkLen + prefixLen + idLen + payloadLen + suffixLen;
|
|||
|
|
byte[] buf = new byte[blen];
|
|||
|
|
|
|||
|
|
// 1. Fill sync count bytes with 0xFF
|
|||
|
|
buf.AsSpan(0, synccount).Fill(0xFF);
|
|||
|
|
|
|||
|
|
int currentOffset = synccount;
|
|||
|
|
|
|||
|
|
Convert.FromHexString(prefix, buf.AsSpan(currentOffset), out _, out int written);
|
|||
|
|
currentOffset += written;
|
|||
|
|
int chkstart = currentOffset;
|
|||
|
|
|
|||
|
|
Convert.FromHexString(id, buf.AsSpan(currentOffset), out _, out int idWritten);
|
|||
|
|
currentOffset += idWritten;
|
|||
|
|
|
|||
|
|
Convert.FromHexString(playloadrest, buf.AsSpan(currentOffset), out _, out int payloadWritten);
|
|||
|
|
currentOffset += payloadWritten;
|
|||
|
|
|
|||
|
|
int chkOffset = currentOffset;
|
|||
|
|
int chkend = chkOffset - chkstart;
|
|||
|
|
currentOffset += 2;
|
|||
|
|
|
|||
|
|
Convert.FromHexString(suffix, buf.AsSpan(currentOffset), out _, out int suffixWritten);
|
|||
|
|
currentOffset += suffixWritten;
|
|||
|
|
|
|||
|
|
|
|||
|
|
UInt16 chk = (UInt16)Crc16IbmSdlc.ComputeChecksum(buf.AsSpan(chkstart, chkend));
|
|||
|
|
|
|||
|
|
BinaryPrimitives.WriteUInt16LittleEndian(buf.AsSpan(chkOffset, 2), chk);
|
|||
|
|
|
|||
|
|
return buf;
|
|||
|
|
}
|
|||
|
|
|