<分区>
这是我要解决的问题...
我正在编写一个程序来控制一台测试设备。程序每秒通过串口轮询仪器,返回一串测试数据。
连接速度为 9600 波特,仪器一次仅发送约 100 个字符,因此性能不是问题。
要求之一是“循环”模式,其工作方式如下:
用户设置三个计时器间隔 - 预测试时间、测试时间和测试间时间 - 然后单击 UI 上的“开始”按钮。
程序命令仪器开始测试周期,并显示仪器接收到的数据,直到预测试时间结束。
程序然后显示并记录数据,直到测试时间到期。
然后程序会显示数据,直到测试时间结束。
重复步骤 2 - 4,直到用户点击 UI 上的“停止”按钮。
过去,我曾为此类问题编写过简单的状态机。但是对于这个项目,(在 SO Rx 专家的帮助下),我已经能够使用 Rx 来解析串行数据,并且对生成的代码非常满意。
我的直觉告诉我,这个问题也可以由 Rx 很好地处理,但完全不清楚如何进行。
那么,我的直觉是否正确,或者您会建议采用不同的方法吗?
如果 Rx 很合适,有人可以提供一些快速而粗略的示例代码来演示解决方案吗?
根据 Enigmativity 编辑...:
这是读取串行数据的代码。简而言之,它将串行数据流转换为单独的数据包字符串,例如“A0”、“C00004”、“H0501100”等。这些被传递给 ProcessPacket 方法,该方法将数据包解释为仪器状态、压力等。
/// <summary>
/// Create a Reactive Extensions subscription to the selected serial port
/// </summary>
private IDisposable SetupSerialDataSubscription()
{
// Create Observable stream of chars from serial port's DataRecieved event
var serialData = Observable
.FromEventPattern<SerialDataReceivedEventArgs>(_serialPort, "DataReceived")
// Collapse groups of chars into stream of individual chars
.SelectMany(_ =>
{
int bytesToRead = _serialPort.BytesToRead;
byte[] bytes = new byte[bytesToRead];
int nbrBytesRead = _serialPort.Read(bytes, 0, bytesToRead);
// Empty array if no bytes were actually read
if (nbrBytesRead == 0)
return new char[0];
var chars = Encoding.ASCII.GetChars(bytes);
return chars;
})
// Strip out null chars, which can cause trouble elsewhere (e.g. Console.WriteLine)
.SkipWhile(c => c == '\0');
// Emits packets, one string per packet, e.g. "A0", "C00004", "H0501100", etc
var packets = serialData
.Scan(string.Empty, (prev, cur) => char.IsLetter(cur) ? cur.ToString() : prev + cur)
.Where(IsCompletePacket);
// Process each packet, on the UI thread
var packetsSubscription = packets
.ObserveOn(this)
.Subscribe(packet => ProcessPacket(packet) );
return packetsSubscription;
}