SeerAGV\Program.cs
using Seer.SeerSocket;
var seer = new SeerSocket();
var msg = seer.Send(0x0410,"""{"motor_names": ["motor1"]}""",19204);
Console.WriteLine(msg);
// System.Console.ReadKey();
SeerAGV\SeerAGV.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
SeerAGV\SeerSocket.cs
using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace Seer.SeerSocket;
public struct SeerMessageHead
{
public byte sync; // 0x5A
public byte version; // 0x01
public ushort number; // 0-65536
public uint length; // 数据区长度,json序列化数据长度
public ushort type; // 报文的类型
#pragma warning disable 0414 //禁用警告
#pragma warning disable 0169 //禁用警告
private readonly byte ref0; //保留
private readonly byte ref1; //保留
private readonly byte ref2; //保留
private readonly byte ref3; //保留
private readonly byte ref4; //保留
private readonly byte ref5; //保留
#pragma warning restore 0414 //恢复警告
#pragma warning restore 0169 //恢复警告
public SeerMessageHead()
{
this.sync = 0x5A;
this.version = 0x01;
this.number = 0x0001;
}
public SeerMessageHead(ushort type)
{
this.type = type;
}
public readonly byte[] ToBytes()
{
int size = Marshal.SizeOf(this);
byte[] bytes = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(this, ptr, true);
Marshal.Copy(ptr, bytes, 0, size);
Marshal.FreeHGlobal(ptr);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes, 2, 2);
Array.Reverse(bytes, 4, 4);
Array.Reverse(bytes, 8, 2);
}
return bytes;
}
};
public class SeerSocket
{
private readonly TcpClient statusClient;
private readonly TcpClient? controlClient;
private readonly TcpClient? navClient;
private readonly TcpClient? configClient;
private readonly TcpClient? otherClient;
private bool isWrite=false;
public SeerSocket(bool isWrite=false)
{
this.isWrite = isWrite;
if (isWrite)
{
// 创建tcp连接
this.statusClient = new TcpClient("", 19204);
this.controlClient = new TcpClient("", 19205);
this.navClient = new TcpClient("", 19206);
this.configClient = new TcpClient("", 19207);
this.otherClient = new TcpClient("", 19210);
}
else
{
this.statusClient = new TcpClient("", 19204);
}
}
public string Send(ushort type, string msg = "", int port = 19204)
{
var msgBody = NormalStrToHexByte(msg);
var msgHead = CreateMsgHead(type, (uint)msgBody.Length);
if (port == 19204)
{
return this.SendRaw(msgHead, msgBody, statusClient);
}
else if (port == 19205 && this.isWrite)
{
return this.SendRaw(msgHead, msgBody, controlClient!);
}
else if (port == 19206 && this.isWrite)
{
return this.SendRaw(msgHead, msgBody, navClient!);
}
else if (port == 19207 && this.isWrite)
{
return this.SendRaw(msgHead, msgBody, configClient!);
}
else if (port == 19210 && this.isWrite)
{
return this.SendRaw(msgHead, msgBody, otherClient!);
}
return "";
}
private string SendRaw(byte[] msgHead, byte[] msgBody, TcpClient client)
{
try
{
if (!client.Connected) return "fail";
// Console.WriteLine("connect successed!!!");
NetworkStream serverStream = client.GetStream();
serverStream.Write(msgHead, 0, msgHead.Length);
serverStream.Write(msgBody, 0, msgBody.Length);
serverStream.Flush();
byte[] inStream = new byte[16];
while (16 != serverStream.Read(inStream, 0, 16))
{
Thread.Sleep(20);
}
var recv_head = BytesToStructure<SeerMessageHead>(inStream);
byte[] recvbyte = BitConverter.GetBytes(recv_head.length);
Array.Reverse(recvbyte);
var dsize = BitConverter.ToUInt32(recvbyte, 0);
const int bufferSize = 512;
List<byte> datalist = new List<byte>();
int count = 0;
while (true)
{
byte[] buffer = new byte[bufferSize];
int readSize = serverStream.Read(buffer, 0, bufferSize);
count += readSize;
datalist.AddRange(buffer);
if (count == dsize)
{
break;
}
// Thread.Sleep(3);
}
// var content = BitConverter.ToString(SeerMessageHeadToBytes(recv_head)).Replace("-", " ");
// Console.WriteLine(content);
string resMsg = System.Text.Encoding.UTF8.GetString(datalist.ToArray());
// System.Console.WriteLine(resMsg);
return resMsg;
// client.Close();
}
catch (SocketException)
{
return "fail";
}
catch (IOException)
{
return "fail";
}
}
private T BytesToStructure<T>(byte[] bytesBuffer)
{
if (bytesBuffer.Length < Marshal.SizeOf(typeof(T)))
{
throw new ArgumentException("size error");
}
nint bufferHandler = Marshal.AllocHGlobal(bytesBuffer.Length);
for (int index = 0; index < bytesBuffer.Length; index++)
{
Marshal.WriteByte(bufferHandler, index, bytesBuffer[index]);
}
// T? structObject = (T)Marshal.PtrToStructure(bufferHandler, typeof(T));
T? structObject = Marshal.PtrToStructure<T>(bufferHandler);
Marshal.FreeHGlobal(bufferHandler);
if (structObject == null)
{
throw new InvalidOperationException("Failed to convert bytes to structure.");
}
return structObject!;
}
private byte[] NormalStrToHexByte(string str)
{
byte[] result = new byte[str.Length];
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
for (int i = 0; i < buffer.Length; i++)
{
result[i] = Convert.ToByte(buffer[i].ToString("X2"), 16);
}
return result;
}
private byte[] CreateMsgHead(ushort type, uint msgLen)
{
var msgHead = new SeerMessageHead
{
type = type,
length = msgLen
};
return msgHead.ToBytes();
}
public static void PrintBytes(byte[] bytes)
{
foreach (byte b in bytes)
{
Console.Write("{0:X2} ", b);
}
}
}