using System; using Microsoft.SPOT; //using Microsoft.SPOT.Hardware; using Microsoft.SPOT.IO; using System.Text; using System.IO; using GHI.Premium.IO; namespace CPF { class EngrLogger { private static StringBuilder columnNames = new StringBuilder(); private static PersistentStorage sdCard; private static VolumeInfo sdVol; private static FileStream logFile; private static StringBuilder sbTemp = new StringBuilder(4096); private static StringBuilder sbWrite = new StringBuilder(4096); private static StringBuilder sbPrefix = new StringBuilder(4096); private static object loggerLock = new object(); private static byte[] writeArray = new byte[4096]; private static DateTime timeNow; private static char token = '\t'; private static bool fileOpen = false; public enum ColumnNums : int { //After the date and time and current state goes the comment comment = 0, //Then the verbosity level 0 stuff pressure, bellowsPosition, batteryBusVolts, //Science data temp, salinity, TOpt, TPhase, RPhase, NO3, pH, FSig, BbSig, TSig, lat, lon, //CTD stuff pressureTimestamp, platformLPFVel, platformDiffVel, platformLPFAcc, pressureAverage, pressureVariance, //PID stuff PID_setPoint, PID_PV, PID_y1, PID_y2, PID_I, PID_v, PID_u, PID_uCPS, //ADC Stuff batteryBusAmps, Amps12V, Amps33V, lastColumn, } public static void init() { //Column names need to be appended in the same order as ColumnNum enum above columnNames.Clear(); columnNames.Append("Date\tTime\tState\t"); columnNames.Append("Comment\t"); columnNames.Append("Pressure\tBel Pos\tBatt Volt\t"); columnNames.Append("Temp\tSalinity\t"); columnNames.Append("Topt\tTPhase\tC1Rphase\t"); columnNames.Append("NO3\tpH\t"); columnNames.Append("FSig\tBbSig\tTsig\t"); columnNames.Append("Lat\tLon\t"); columnNames.Append("Pres Timestamp\tPlat LPF Vel\tPlat Diff Vel\tPlat LPF Acc\tPress Avg\tPress Var\t"); columnNames.Append("PID SP\tPID PV\ty1\ty2\tI\tv\tu\tuCPS\t"); columnNames.Append("Batt Cur\t12V Cur\t3.3V Cur\t"); sdCard = new PersistentStorage("SD"); sdCard.MountFileSystem(); sdVol = new VolumeInfo("SD"); openFile(); lock (loggerLock) { logFile.Write(UTF8Encoding.UTF8.GetBytes(columnNames.ToString()), 0, columnNames.Length); } BTConsole.SendLine(columnNames); Debug.Print(columnNames.ToString()); sbTemp.Clear(); sbTemp.Append("File Name = "); sbTemp.Append(fileName.ToString()); lock (loggerLock) { write(ColumnNums.comment, getPrefix(sbTemp)); } sbTemp.Clear(); sbTemp.Append("Volume Total Size: "); sbTemp.Append(sdVol.TotalSize.ToString()); lock (loggerLock) { write(ColumnNums.comment, getPrefix(sbTemp)); } sbTemp.Clear(); sbTemp.Append("Volume Free Space: "); sbTemp.Append(sdVol.TotalFreeSpace.ToString()); lock (loggerLock) { write(ColumnNums.comment, getPrefix(sbTemp)); } sbTemp.Clear(); sbTemp.Append("PlatVel/Depth PID K = "); sbTemp.Append(configFile.KPlatVel.ToString()); sbTemp.Append(" "); sbTemp.Append(configFile.KDepth.ToString()); lock (loggerLock) { write(ColumnNums.comment, getPrefix(sbTemp)); } sbTemp.Clear(); sbTemp.Append("PlatVel/Depth PID Ti = "); sbTemp.Append(configFile.TiPlatVel.ToString()); sbTemp.Append(" "); sbTemp.Append(configFile.TiDepth.ToString()); lock (loggerLock) { write(ColumnNums.comment, getPrefix(sbTemp)); } sbTemp.Clear(); sbTemp.Append("PlatVel/Depth PID Td = "); sbTemp.Append(configFile.TdPlatVel.ToString()); sbTemp.Append(" "); sbTemp.Append(configFile.TdDepth.ToString()); lock (loggerLock) { write(ColumnNums.comment, getPrefix(sbTemp)); } sbTemp.Clear(); sbTemp.Append("PlatVel/Depth PID Tf = "); sbTemp.Append(configFile.TfPlatVel.ToString()); sbTemp.Append(" "); sbTemp.Append(configFile.TfDepth.ToString()); lock (loggerLock) { write(ColumnNums.comment, getPrefix(sbTemp)); } sbTemp.Clear(); sbTemp.Append("PlatVel/Depth PID Tt = "); sbTemp.Append(configFile.TtPlatVel.ToString()); sbTemp.Append(" "); sbTemp.Append(configFile.TtDepth.ToString()); lock (loggerLock) { write(ColumnNums.comment, getPrefix(sbTemp)); } sbTemp.Clear(); sbTemp.Append("PlatVel/Depth PID B = "); sbTemp.Append(configFile.BPlatVel.ToString()); sbTemp.Append(" "); sbTemp.Append(configFile.BDepth.ToString()); lock (loggerLock) { write(ColumnNums.comment, getPrefix(sbTemp)); } sbTemp.Clear(); sbTemp.Append("PlatVel/Depth PID uLow = "); sbTemp.Append(configFile.uLowPlatVel.ToString()); sbTemp.Append(" "); sbTemp.Append(configFile.uLowDepth.ToString()); lock (loggerLock) { write(ColumnNums.comment, getPrefix(sbTemp)); } sbTemp.Clear(); sbTemp.Append("PlatVel/Depth PID uHigh = "); sbTemp.Append(configFile.uHighPlatVel.ToString()); sbTemp.Append(" "); sbTemp.Append(configFile.uHighDepth.ToString()); lock (loggerLock) { write(ColumnNums.comment, getPrefix(sbTemp)); } sbTemp.Clear(); sbTemp.Append("PlatVel/Depth PID h = "); sbTemp.Append(configFile.hPlatVel.ToString()); sbTemp.Append(" "); sbTemp.Append(configFile.hDepth.ToString()); lock (loggerLock) { write(ColumnNums.comment, getPrefix(sbTemp)); } sbTemp.Clear(); sbTemp.Append("Target anchor depth = "); sbTemp.Append(MissionConfigFile.descendTable[MissionConfigFile.descendTable.Length - 1].depth.ToString()); sbTemp.Append(" "); lock (loggerLock) { write(ColumnNums.comment, getPrefix(sbTemp)); } } private static int lastValueIndex = 0; private static int columnNum = 0; private static int valueNum = 0; public static void write(params object[] values) { lock (loggerLock) { lastValueIndex = values.Length - 1; sbWrite.Clear(); for (columnNum = 0; columnNum < (int)ColumnNums.lastColumn; columnNum++) { for (valueNum = 0; valueNum < lastValueIndex; valueNum = valueNum + 2) { if ((int)values[valueNum] == columnNum) { //TODO need to do a better job formatting values to minimize length if (columnNum == (int)ColumnNums.comment) sbWrite.Append(values[valueNum + 1].ToString()); else sbWrite.Append(((double)values[valueNum + 1]).ToString("f6")); break; } } sbWrite.Append(token); } Debug.Print(sbWrite.ToString()); sbWrite.AppendLine(); Array.Clear(writeArray, 0, writeArray.Length); Array.Copy(UTF8Encoding.UTF8.GetBytes(sbWrite.ToString()), writeArray, sbWrite.Length); logFile.Write(writeArray, 0, Array.IndexOf(writeArray, 0)); BTConsole.SendLine(sbWrite); } } private static StringBuilder sbRecord = new StringBuilder(StructQueue.qRecordWidth); public static StringBuilder formatRecord(params object[] values) { lock (loggerLock) { lastValueIndex = values.Length - 1; sbRecord.Clear(); for (columnNum = 0; columnNum < (int)ColumnNums.lastColumn; columnNum++) { for (valueNum = 0; valueNum < lastValueIndex; valueNum = valueNum + 2) { if ((int)values[valueNum] == columnNum) { //TODO need to do a better job formatting values to minimize length if (columnNum == (int)ColumnNums.comment) sbRecord.Append(values[valueNum + 1].ToString()); else sbRecord.Append(((double)values[valueNum + 1]).ToString("f6")); break; } } sbRecord.Append(token); } //Debug.Print(sbRecord.ToString()); sbRecord.AppendLine(); return sbRecord; } } private static void printVolInfo() { sbTemp.Clear(); sbTemp.Append("Volume Total Size: "); sbTemp.Append(sdVol.TotalSize.ToString()); lock (loggerLock) { write(ColumnNums.comment, sbTemp); } sbTemp.Clear(); sbTemp.Append("Volume Free Space: "); sbTemp.Append(sdVol.TotalFreeSpace.ToString()); lock (loggerLock) { write(ColumnNums.comment, sbTemp); } //String[] fileNames = Directory.GetFiles(sdVol.RootDirectory); //for (int i = 0; i < fileNames.Length; i++) //{ // FileInfo fileInfo = new FileInfo(fileNames[i]); // Debug.Print(i.ToString() + " File name: " + fileNames[i] // + " Creation Date = " + fileInfo.CreationTime.ToString() // + " Length = " + fileInfo.Length.ToString()); //} } public static void closeFile() { if (fileOpen) logFile.Close(); fileOpen = false; } public static StringBuilder fileName = new StringBuilder(128); public static void openFile() { if (fileOpen) closeFile(); timeNow = DateTime.Now; fileName.Clear(); fileName.Append(sdVol.RootDirectory); fileName.Append("\\"); fileName.Append(timeNow.Year.ToString()); fileName.Append("-"); fileName.Append(timeNow.Month.ToString()); fileName.Append("-"); fileName.Append(timeNow.Day.ToString()); fileName.Append("T"); fileName.Append(timeNow.Hour.ToString()); fileName.Append("-"); fileName.Append(timeNow.Minute.ToString()); fileName.Append("-"); fileName.Append(timeNow.Second.ToString()); logFile = new FileStream(fileName.ToString(), FileMode.OpenOrCreate, FileAccess.Write); fileOpen = true; } public static void unMount() { sdCard.UnmountFileSystem(); } public static StringBuilder getPrefix(StringBuilder comment) { timeNow = DateTime.Now; sbPrefix.Clear(); sbPrefix.Append(timeNow.ToString("MMM dd, yyyy")); sbPrefix.Append(token); sbPrefix.Append(timeNow.ToString("HH:mm:ss.fff")); sbPrefix.Append(token); sbPrefix.Append(Program.sbStateNames[(int)Program.CPFState]); sbPrefix.Append(token); sbPrefix.Append(comment); return (sbPrefix); } public static StringBuilder getPrefix(DateTime timeStamp, Program.CPFStates state, StringBuilder comment) { sbPrefix.Clear(); sbPrefix.Append(timeStamp.ToString("MMM dd, yyyy")); sbPrefix.Append(token); sbPrefix.Append(timeStamp.ToString("HH:mm:ss.fff")); sbPrefix.Append(token); sbPrefix.Append(Program.sbStateNames[(int)state]); sbPrefix.Append(token); sbPrefix.Append(comment); return (sbPrefix); } private static byte[] inArray = new byte[StructQueue.qRecordWidth]; private static StringBuilder qWriterSB = new StringBuilder(StructQueue.qRecordWidth); public static void qWriter(byte[] inArray) { logFile.Write(inArray, 0, Array.IndexOf(inArray, 0) + 1); BTConsole.SendLine(sbWrite); qWriterSB.Clear(); qWriterSB.Append(UTF8Encoding.UTF8.GetChars(inArray)); Debug.Print(qWriterSB.ToString()); } } }