using System; using Microsoft.SPOT; using System.Text; using System.Threading; namespace CPF { class ErrorHandler { public enum ErrorType { warning = 0, nonCritical, critical } public delegate void CriticalErrorHandler(object sender, ErrorType e); public event CriticalErrorHandler criticalErrorHandler; private static StructQueue.qStruct qS = new StructQueue.qStruct(); private int errorCount = 0; private int maxErrors = 1; private TimeSpan timeLimit = new TimeSpan(0, 0, 0); private StringBuilder label = new StringBuilder(64); private DateTime startTime; public bool goneCritical = false; public ErrorType errorType; public static StringBuilder sbTemp = new StringBuilder(128); public ErrorHandler(int maxErrors, TimeSpan timeLimit, StringBuilder label, ErrorType errorType) { this.maxErrors = maxErrors; this.timeLimit = new TimeSpan(timeLimit.Hours, timeLimit.Minutes, timeLimit.Seconds); this.label.Clear(); this.label.Append(label); this.errorType = errorType; qS.byteArray = new byte[StructQueue.byteArrayWidth]; } public void logError() { if (!goneCritical) { Debug.Print(label.ToString() + ": Processing error"); if (errorCount == 0) { startTime = DateTime.Now; errorCount = 1; } else { if (DateTime.Now - startTime >= timeLimit) { errorCount = 1; startTime = DateTime.Now; Debug.Print(label.ToString() + " Cleared error counter due to time limit expired"); } else errorCount++; } Debug.Print(label.ToString() + ": Error count = " + errorCount.ToString()); qS.timeStamp = DateTime.Now; sbTemp.Clear(); sbTemp.Append("ERROR: "); sbTemp.Append(this.label); sbTemp.Append(" count = "); sbTemp.Append(this.errorCount.ToString()); sbTemp.Append(" of "); sbTemp.Append(this.maxErrors.ToString()); Array.Clear(qS.byteArray, 0, qS.byteArray.Length); Array.Copy(UTF8Encoding.UTF8.GetBytes(sbTemp.ToString()), qS.byteArray, sbTemp.Length); qS.qRecordType = StructQueue.QRecordType.Error; qS.errorCode = 0; Program.sQueue.Enqueue(qS); if (errorCount >= maxErrors) { criticalErrorHandler(this, this.errorType); goneCritical = true; } } } public static void setRecoveryMode(object o, ErrorType e) { SV.ForceRecoveryMode = true; } //TODO replace everything below this with object oriented approach above //Count parsePOnlyErrors private static int parsePOnlyErrors = 0; private static int parsePOnlyErrorsLimit = 10; private static TimeSpan parsePOnlyErrorTimeout = new TimeSpan(0, 10, 0); private static TimeSpan lastParsePOnlyErrorTime = new TimeSpan(); private static TimeSpan parsePOnlyTimeNow = new TimeSpan(); public static void incrParsePOnlyErrors() { parsePOnlyTimeNow = Microsoft.SPOT.Hardware.Utility.GetMachineTime(); if (parsePOnlyErrors == 0) { lastParsePOnlyErrorTime = parsePOnlyTimeNow; parsePOnlyErrors = 1; } else { if ((parsePOnlyTimeNow - lastParsePOnlyErrorTime) < parsePOnlyErrorTimeout) { parsePOnlyErrors = parsePOnlyErrors + 1; if (parsePOnlyErrors > parsePOnlyErrorsLimit) Debug.Print("parsePOnly Errors exceeds limit"); } else { parsePOnlyErrors = 1; } lastParsePOnlyErrorTime = parsePOnlyTimeNow; } } //Count Optode Event Handler errors private static int optodeEHErrors = 0; private static int optodeEHErrorsLimit = 10; private static TimeSpan optodeEHErrorTimeout = new TimeSpan(0, 10, 0); private static TimeSpan lastoptodeEHErrorTime = new TimeSpan(); private static TimeSpan optodeEHTimeNow = new TimeSpan(); public static void incrOptodeEHErrors() { optodeEHTimeNow = Microsoft.SPOT.Hardware.Utility.GetMachineTime(); if (optodeEHErrors == 0) { lastoptodeEHErrorTime = optodeEHTimeNow; optodeEHErrors = 1; } else { if ((optodeEHTimeNow - lastoptodeEHErrorTime) < optodeEHErrorTimeout) { optodeEHErrors = optodeEHErrors + 1; if (optodeEHErrors > optodeEHErrorsLimit) Debug.Print("optodeEH Errors exceeds limit"); } else { optodeEHErrors = 1; } lastoptodeEHErrorTime = optodeEHTimeNow; } } //Count structured queue Enqueue errors private static int enqueueErrors = 0; private static int enqueueErrorsLimit = 10; private static TimeSpan enqueueErrorTimeout = new TimeSpan(0, 10, 0); private static TimeSpan lastEnqueueErrorTime = new TimeSpan(); private static TimeSpan enqueueTimeNow = new TimeSpan(); public static void incrEnqueueErrors() { enqueueTimeNow = Microsoft.SPOT.Hardware.Utility.GetMachineTime(); if (enqueueErrors == 0) { lastEnqueueErrorTime = enqueueTimeNow; enqueueErrors = 1; } else { if ((enqueueTimeNow - lastEnqueueErrorTime) < enqueueErrorTimeout) { enqueueErrors = enqueueErrors + 1; if (enqueueErrors > enqueueErrorsLimit) Debug.Print("enqueueError Errors exceeds limit"); } else { enqueueErrors = 1; } lastEnqueueErrorTime = enqueueTimeNow; } } //Check for too many sequential identical pressure values in a given time period private static int stuckPressureErrors = -1; private static int stuckPressureErrorsLimit = 20; //GM 2015Oct28 Changed from 34 to 20 private static double lastPressure = double.NaN; private static TimeSpan stuckPressureErrorPeriod = new TimeSpan(0, 2, 0); //GM 2015Aug04 Changed from (0, 1, 0) to (0, 2, 0) private static TimeSpan stuckPressureStartTime = new TimeSpan(); private static TimeSpan stuckPressureTimeNow = new TimeSpan(); public static bool isPressureStuck(double inPressure) { //SV.Pressure is initialized as double.NaN, so if SBE41 hasn't given a pressure yet, inPressure //will come in as double.NaN. Here we change double.NaN to (double)0 so logical evaluations conducted //below will not produce eroneous results (for example: 17.5 == double.NaN evaluates true). if (double.IsNaN(inPressure)) inPressure = 0; stuckPressureTimeNow = Microsoft.SPOT.Hardware.Utility.GetMachineTime(); //Initialize the timer and counter if (stuckPressureErrors == -1) { lastPressure = inPressure; stuckPressureErrors = stuckPressureErrors + 1; stuckPressureStartTime = stuckPressureTimeNow; } else //Increment or reset the counter { if (inPressure == lastPressure) { stuckPressureErrors = stuckPressureErrors + 1; } else stuckPressureErrors = -1; } //If the error Period has has expired check if error count exceeds the limit if ((stuckPressureTimeNow - stuckPressureStartTime) > stuckPressureErrorPeriod) { if (stuckPressureErrors > stuckPressureErrorsLimit) { //Try resetting the CTD with qsr command. TODO Do a power reset when we have power switching EngrLogger.writeToColumns(false, "Resetting SBE41 with qsr"); SBE41.resetSBE41(); stuckPressureErrors = -1; return (true); } else return (false); } else //TODO return below bool to false. this is here to force EAAscend because RomBOOT was seen when stuck in EA. return (false); } } }