根据前面讲到的协议,完成如下场景的收发功能。
正确的命令格式:01 41 30 30 30 50 30 35 02 起始码为01 结束码为02长度为26字节的数据
外面接受一串含有合法命令格式的数据. sendInfo = "01 41 30 30 30 50 30 35 02 00 00 01 09 09 41 30 30 30 50 30 35 02 01 41 30 30 30 50 30 35 02"
实现,当外来数据有多个正确的命令格式时组成队列模式,从前到后依次发送指令。达到发送第一条命令得到响应信息之后依次发送下一条命令数据。
详细代码后面会给出,主要布骤如下:
1、根据头和尾以及长度判断是否是合法的数据,循环添加到队列中
bool flag = true;
while (flag)
{
int count = sendInfo.IndexOf("01");
string a = sendInfo.Substring(count + 24, 2);//01 41 30 30 30 50 30 35 02
if (count > -1 && a == "02") // 起始码和结束码都正确
{
// 添加到队列中
queue.Enqueue(sendInfo.Substring(count, 26));
}
sendInfo = sendInfo.Substring(count + 26);
if (sendInfo.Length < 26)
flag = false;
}
2、判断队列中是否有数据,有就发送并移除这条数据
// 当有多个可用命令时开始只发送先到的一个,后面的等接收到返回值再发送
if (IsCountAvailable)
{
SendDataInfo(queue.Dequeue());
}
public bool IsCountAvailable
{
get { return queue.Count > 0; }
}
3、根据响应的命令判断是否继续发送数据
if (arr[1] == "43")
{
// 如果有等待的发送命令将继续发送
if (IsCountAvailable)
{
SendDataInfo(queue.Dequeue());
}
}
详细代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.Ports;
namespace WebServiceSerialPort
{
public class Service
{
SerialPort mySerialPort = new SerialPort();
private static readonly Lazy<Service> _instance = new Lazy<Service>(() => new Service());
private Queue<string> queue = new Queue<string>();
private string backStop = "";
private string backStart = "";
private Service()
{
}
public static Service Instance
{
get
{
return _instance.Value;
}
}
/// <summary>
/// 打开服务
/// </summary>
public void Open()
{
try
{
if (!mySerialPort.IsOpen)
{
BindSerialPortInfo();
OpenSerialPort();
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(mySerialPort_DataReceived);
}
}
catch (Exception ex)
{
}
}
/// <summary>
/// 发送数据
/// 取出数据中合法的数据
/// </summary>
/// <param name="sendInfo"></param>
public void SendData(string sendInfo)
{
// sendInfo = "01 41 30 30 30 50 30 35 02 00 00 01 09 09 41 30 30 30 50 30 35 02 01 41 30 30 30 50 30 35 02";
bool flag = true;
while (flag)
{
int count = sendInfo.IndexOf("01");
string a = sendInfo.Substring(count + 24, 2);//01 41 30 30 30 50 30 35 02
if (count > -1 && a == "02") // 起始码和结束码都正确
{
queue.Enqueue(sendInfo.Substring(count, 26));
}
sendInfo = sendInfo.Substring(count + 26);
if (sendInfo.Length < 26)
flag = false;
}
// 当有多个可用命令时开始只发送先到的一个,后面的等接收到返回值再发送
if (IsCountAvailable)
{
SendDataInfo(queue.Dequeue());
}
}
public bool IsCountAvailable
{
get { return queue.Count > 0; }
}
// 接受数据
public void mySerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
string strReceived = string.Empty;
byte[] result = new byte[mySerialPort.BytesToRead];
mySerialPort.Read(result, 0, mySerialPort.BytesToRead);
//strReceived = Encoding.ASCII.GetString(result);
//strReceived += strReceived;
foreach (byte b in result)
{
strReceived += Convert.ToString(b, 16).ToUpper().PadLeft(2, '0') + " ";
}
if (strReceived.Length >= 26)
{
bool flag = true;
while (flag)
{
int count = strReceived.IndexOf("01");
string a = strReceived.Substring(count + 24, 2);
if (count > -1 && a == "02") // 起始码和结束码都正确
{
string[] arr = strReceived.Substring(count, 26).Split(' ');
// 判断是否接受到AGV停止信息
if (arr[1] == "43")
{
// 如果有等待的发送命令将继续发送
if (IsCountAvailable)
{
SendDataInfo(queue.Dequeue());
}
}
}
strReceived = strReceived.Substring(count + 26);
if (strReceived.Length < 26)
flag = false;
}
}
}
catch { }
}
/// <summary>
/// 加载串口参数
/// </summary>
private void BindSerialPortInfo()
{
string temppath = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
string path = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase + @"SerialPortConfig.ini";
if (File.Exists(path))
{
using (StreamReader sreader = new StreamReader(path, Encoding.UTF8))
{
mySerialPort.PortName = sreader.ReadLine();
mySerialPort.BaudRate = Convert.ToInt32(sreader.ReadLine());
switch (Convert.ToInt32(sreader.ReadLine()))
{
case 0:
mySerialPort.Parity = Parity.None;
break;
case 1:
mySerialPort.Parity = Parity.Odd;
break;
case 2:
mySerialPort.Parity = Parity.Even;
break;
case 3:
mySerialPort.Parity = Parity.Mark;
break;
case 4:
mySerialPort.Parity = Parity.Space;
break;
default:
mySerialPort.Parity = Parity.None;
break;
}
mySerialPort.DataBits = Convert.ToInt32(sreader.ReadLine());
switch (Convert.ToInt32(sreader.ReadLine()))
{
case 1:
mySerialPort.StopBits = StopBits.One;
break;
case 2:
mySerialPort.StopBits = StopBits.Two;
break;
case 3:
mySerialPort.StopBits = StopBits.OnePointFive;
break;
default:
mySerialPort.StopBits = StopBits.One;
break;
}
}
}
}
/// <summary>
/// 发送数据(十六进制数据)
/// </summary>
/// <param name="command"></param>
public void SendDataInfo(string command)
{
string strCommand = string.Empty;
string[] open = command.Split(' ');
foreach (string str in open)
{
strCommand += str;
}
string temp = string.Empty;
for (int i = 0; i <= strCommand.Length - 2; i = i + 2)
{
temp = strCommand.Substring(i, 2);
byte[] buffer = new byte[1];
try
{
buffer[0] = byte.Parse(temp, System.Globalization.NumberStyles.AllowHexSpecifier);
mySerialPort.Write(buffer, 0, buffer.Length);
}
catch
{
return;
}
}
}
/// <summary>
/// 打开串口
/// </summary>
public void OpenSerialPort()
{
if (!mySerialPort.IsOpen)
mySerialPort.Open();
}
/// <summary>
/// 关闭串口
/// </summary>
public void CloseSerialPort()
{
if (IsCountAvailable)
queue.Clear();
if (mySerialPort.IsOpen)
{
mySerialPort.Close();
}
}
}
}
Thanks