private static void AllOff(MCUBoard board, List <IOconfOut230Vac> ports) { try { board.SafeWriteLine("off", CancellationToken.None); foreach (var port in ports) { if (port.HasOnSafeState) { board.SafeWriteLine($"p{port.PortNumber} on", CancellationToken.None); } } } catch (Exception ex) { CALog.LogErrorAndConsoleLn(LogID.A, $"Error detected while attempting to set ports to default positions for board {board.ToShortDescription()}", ex); } }
private async Task BoardLoop(MCUBoard board, List <IOconfOut230Vac> ports, CancellationToken token) { var lastActions = new SwitchboardAction[ports.Max(p => p.PortNumber)]; var boardStateName = board.BoxName + "_state"; // we use the next 2 booleans to avoid spamming logs/display with an ongoing problem, so we only notify at the beginning and when we resume normal operation. // we might still get lots of entries for problems that alternate between normal and failed states, but for now is a good data point to know if that case is happening. var waitingBoardReconnect = false; var tryingToRecoverAfterTimeoutWatch = new Stopwatch(); while (!token.IsCancellationRequested) { try { var vector = await _cmd.When(_ => true, token); if (!CheckConnectedStateInVector(board, boardStateName, ref waitingBoardReconnect, vector)) { continue; // no point trying to send commands while there is no connection to the board. } foreach (var port in ports) { await DoPortActions(vector, board, port, lastActions, token); } if (tryingToRecoverAfterTimeoutWatch.IsRunning) { tryingToRecoverAfterTimeoutWatch.Stop(); CALog.LogInfoAndConsoleLn(LogID.A, $"wrote to switch board without time outs after {tryingToRecoverAfterTimeoutWatch.Elapsed}, resuming normal action frequency - {board.ToShortDescription()}"); } } catch (TimeoutException) { if (!tryingToRecoverAfterTimeoutWatch.IsRunning) { // we only notify of the situation once while this is a different way a disconnect might look like, we have CALog.LogInfoAndConsoleLn(LogID.A, $"timed out writing to switchboard, reducing action frequency until reconnect - {board.ToShortDescription()}"); tryingToRecoverAfterTimeoutWatch.Restart(); } // forcing reduced acting frequency ) try { await Task.Delay(500, token); } catch (TaskCanceledException) { } } catch (TaskCanceledException ex) { if (!token.IsCancellationRequested) { CALog.LogErrorAndConsoleLn(LogID.A, ex.ToString()); } } catch (Exception ex) { CALog.LogErrorAndConsoleLn(LogID.A, ex.ToString()); } } AllOff(board, ports); }
private static bool CheckConnectedStateInVector(MCUBoard board, string boardStateName, ref bool waitingBoardReconnect, NewVectorReceivedArgs vector) { var vectorState = (BaseSensorBox.ConnectionState)(int) vector[boardStateName]; var connected = vectorState >= BaseSensorBox.ConnectionState.Connected; if (waitingBoardReconnect && connected) { CALog.LogData(LogID.B, $"resuming switchboard actions after reconnect on {board.ToShortDescription()}"); waitingBoardReconnect = false; } else if (!waitingBoardReconnect && !connected) { CALog.LogData(LogID.B, $"stopping switchboard actions while connection is reestablished - state: {vectorState} - {board.ToShortDescription()}"); waitingBoardReconnect = true; } return(connected); }