using System.Buffers; using System.Buffers.Binary; using System.ComponentModel.DataAnnotations; using System.IO.Ports; //string bx = "4F000000780000004F00000078000000000000000000"; //ReadOnlySpan rs = Convert.FromHexString(bx); //int x = rs.Length; //ushort checksum = Crc16IbmSdlc.ComputeChecksum(rs); string bufp = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; string buf = "ffffffffc0ffffff003f00c1"; Span discoverID = [ 0xff, 0xff, 0xff]; Span curID = [ 0xff, 0xf9, 0x07 ]; Span curIDrest = [ 0x00, 0x00, 0xc2, 0x01, 0x00 ]; byte[] bufferp = Convert.FromHexString(bufp); byte[] buffer = Convert.FromHexString(buf); byte[] buffer2 = new byte[256]; ReadOnlySpan bConnect = MakeConnect(4, curID, curIDrest); ReadOnlySpan 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 MakeDiscover(Span discoverID) { return BuildPacket(64, discoverID , new byte[] { 0x00 }); } ReadOnlySpan MakeConnect(int syncbytes, ReadOnlySpan ID, ReadOnlySpan 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 BuildPacket(int syncbytes, ReadOnlySpan ID, byte[] payload) { ArrayBufferWriter writer = new ArrayBufferWriter(); if (syncbytes > 0) { Span span = writer.GetSpan(syncbytes); span.Fill(0xFF); writer.Advance(syncbytes); } writer.Write(new byte[] { 0xC0 }); // STX int startCS = writer.WrittenCount; if (ID!=ReadOnlySpan.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 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 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; }