private SerialCommand QueueCommandString(string cmd) { if (string.IsNullOrEmpty(cmd)) { return(null); } if (CommandToUpper) { cmd = cmd.ToUpper(); } cmd = cmd.Replace('\t', ' '); var c = new SerialCommand { SeqId = _commandSeqId++, CommandText = cmd }; int queueLength; lock (_pendingCommands) { queueLength = _pendingCommands.Count; if (queueLength == 0) { _autoEvent.Set(); // start Async task now! } _pendingCommands.Add(c); queueLength++; } Logger?.LogTrace($"Queue: {cmd}"); OnCommandQueueChanged(new SerialEventArgs(queueLength, c)); return(c); }
public SerialEventArgs(SerialCommand cmd) { Command = cmd; if (cmd != null) { Info = cmd.CommandText; SeqId = cmd.SeqId; } }
public SerialEventArgs(int queueLenght, SerialCommand cmd) { QueueLenght = queueLenght; Command = cmd; if (cmd != null) { Info = cmd.CommandText; SeqId = cmd.SeqId; } }
private void SendCommand(SerialCommand cmd) { // SendCommands is called in the async Write thread var eventArgs = new SerialEventArgs(cmd); OnCommandSending(eventArgs); if (eventArgs.Abort || Aborted) { return; } lock (_commands) { if (_commands.Count > MaxCommandHistoryCount) { _commands.RemoveAt(0); } _commands.Add(cmd); } string commandText = cmd.CommandText; const int CRLF_SIZE = 2; if (commandText.Length >= ArduinoLineSize + CRLF_SIZE) { commandText = commandText.Substring(0, ArduinoLineSize - 1 - CRLF_SIZE); } while (commandText.Length > ArduinoBufferSize - 1) { // give "control" class the chance to read from arduino to control buffer int firstSize = ArduinoBufferSize * 2 / 3; string firstX = commandText.Substring(0, firstSize); commandText = commandText.Substring(firstSize); if (!WriteSerial(firstX, false)) { return; } Thread.Sleep(250); } if (WriteSerial(commandText, true)) { cmd.SentTime = DateTime.Now; eventArgs = new SerialEventArgs(cmd); OnCommandSent(eventArgs); } }
private IEnumerable <SerialCommand> SplitAndQueueCommand(string line) { var cmdlist = new List <SerialCommand>(); string[] cmds = SplitCommand(line); foreach (string cmd in cmds) { SerialCommand pcmd = QueueCommandString(cmd); if (pcmd != null) { // sending is done in Write-Thread cmdlist.Add(pcmd); } } return(cmdlist); }
public SerialEventArgs(string info, SerialCommand cmd) { Command = cmd; if (cmd != null && string.IsNullOrEmpty(info)) { Info = cmd.CommandText; } else { Info = info; } if (cmd != null) { SeqId = cmd.SeqId; } }
/// <summary> /// Wait until command queue is empty /// </summary> /// <param name="maxMilliseconds"></param> /// <returns>true = ok, false = timeout or aborting</returns> public async Task <bool> WaitUntilQueueEmptyAsync(int maxMilliseconds = DefaultTimeout) { var sw = Stopwatch.StartNew(); while (Continue) { SerialCommand cmd = null; lock (_pendingCommands) { if (_pendingCommands.Count > 0) { cmd = _pendingCommands[0]; } } if (cmd == null) { return(true); } var eventArgs = new SerialEventArgs(cmd); OnWaitCommandSent(eventArgs); if (Aborted || eventArgs.Abort) { return(false); } if (_autoEvent.WaitOne(10) == false) { await Task.Delay(1); } if (sw.ElapsedMilliseconds > maxMilliseconds) { return(false); } } return(false); // aborting }
private void MessageReceived(string message) { SerialCommand cmd = null; lock (_pendingCommands) { if (_pendingCommands.Count > 0) { cmd = _pendingCommands[0]; } } if (string.IsNullOrEmpty(message) == false) { Logger?.LogTrace($"Read: {message.Replace("\n", @"\n").Replace("\r", @"\r").Replace("\t", @"\t")}"); bool endCommand = false; message = message.Trim(); if (cmd != null) { SetSystemKeepAlive(); string result = cmd.ResultText; if (string.IsNullOrEmpty(result)) { result = message; } else { result = result + "\n" + message; } cmd.ResultText = result; cmd.ReplyReceivedTime = DateTime.Now; } OnReplyReceived(new SerialEventArgs(message, cmd)); if (message.StartsWith(OkTag)) { endCommand = true; if (cmd != null) { cmd.ReplyType |= EReplyType.ReplyOK; } OnReplyDone(new SerialEventArgs(message, cmd)); } else if (message.StartsWith(ErrorTag, StringComparison.OrdinalIgnoreCase)) { if (ErrorIsReply) { endCommand = true; } if (cmd != null) { cmd.ReplyType |= EReplyType.ReplyError; } OnReplyError(new SerialEventArgs(message, cmd)); } else if (message.StartsWith(InfoTag, StringComparison.OrdinalIgnoreCase)) { if (cmd != null) { cmd.ReplyType |= EReplyType.ReplyInfo; } OnReplyInfo(new SerialEventArgs(message, cmd)); } else { if (cmd != null) { cmd.ReplyType |= EReplyType.ReplyUnknown; } OnReplyUnknown(new SerialEventArgs(message, cmd)); } if (endCommand && cmd != null) { int queueLength; lock (_pendingCommands) { if (_pendingCommands.Count > 0) // may cause because of a reset { _pendingCommands.RemoveAt(0); } queueLength = _pendingCommands.Count; _autoEvent.Set(); } OnCommandQueueChanged(new SerialEventArgs(queueLength, cmd)); if (queueLength == 0) { OnCommandQueueEmpty(new SerialEventArgs(queueLength, cmd)); ClearSystemKeepAlive(); } } } }
private void Write() { Thread.CurrentThread.Priority = ThreadPriority.AboveNormal; // Async write thread to send commands to the arduino while (Continue) { SerialCommand nextCmd = null; int queuedCmdLength = 0; // commands are sent to the arduino until the buffer is full // In the _pendingCommand list also the commands are still stored with no reply. lock (_pendingCommands) { foreach (SerialCommand cmd in _pendingCommands) { if (cmd.SentTime.HasValue) { queuedCmdLength += cmd.CommandText.Length; queuedCmdLength += 2; // CRLF } else { nextCmd = cmd; break; } } } // nextCmd => next command to be sent // queuedCmdLength => length of command in the arduino buffer if (nextCmd != null && (!Pause || SendNext)) { if (queuedCmdLength == 0 || queuedCmdLength + nextCmd.CommandText.Length + 2 < ArduinoBufferSize) { // send everything if queue is empty // or send command if pending commands + this fit into arduino queue SendCommand(nextCmd); SendNext = false; } else { var eventArgs = new SerialEventArgs(nextCmd); OnWaitForSend(eventArgs); if (Aborted || eventArgs.Abort) { return; } lock (_pendingCommands) { if (_pendingCommands.Count > 0 && _pendingCommands[0].SentTime.HasValue) { _autoEvent.Reset(); // expect an answer } } _autoEvent.WaitOne(10); } } else { _autoEvent.WaitOne(100); // no command in queue => wait => CreateCommand(...) will set AutoEvent } } }