//#define USB_STORAGE //enable if using USB memory using System; using System.Text; using System.IO; using System.Threading; using Microsoft.SPOT; using Microsoft.SPOT.IO; using GHI.Processor; using GHI.IO.Storage; #if(USB_STORAGE) using GHI.Usb; using GHI.Usb.Host; #endif namespace CPF { public static class EngrLogger { private static StringBuilder columnNames = new StringBuilder(); private static SDCard sdCard; public 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'; public static bool fileOpen { get; private set; } private static bool SDMounted = false; private static bool USBMounted = false; public enum ColumnNums : int { //First the prefix for all records dateTime = 0, state, comment, //Then the verbosity level 0 stuff pressure, bellowsPosition, batteryBusVolts, //CTD Stuff CTDTemp, CTDSalinity, //PTH Stuff LPS331Pressure, LPS331Temperature, SHT21Humidity, SHT21Temperature, //Science data FLBB, TOpt, TPhase, RPhase, NO3, pH, //CTD stuff SBE41Pressure, SBE41LPFPressure, SBE41LPFVelocity, SBE41DiffVelocity, SBE41Diff2Velocity, SBE41Slope, CTDSamplePeriod, //PID stuff PID_SP, PID_PV, PID_y1, PID_y2, PID_I, PID_v, PID_u, PID_uCPS, PID_h, //ADC Stuff batteryBusAmps, Amps12V, Amps33V, debug, //GPS Stuff GPS, //Iridium Modem Stuff IModem, lastColumn, } private static StringBuilder[] columnName = new StringBuilder[(int)ColumnNums.lastColumn]; #if(USB_STORAGE) private static AutoResetEvent usbInsertEvent = new AutoResetEvent(false); private static MassStorage usbStorage; #endif private static Register resetControllerStatus = new Register(0xFFFFFE04); public static bool init() { for (int i = 0; i < (int)ColumnNums.lastColumn; i++) columnName[i] = new StringBuilder(32); columnName[(int)ColumnNums.dateTime].Append("$\tDate\tTime"); columnName[(int)ColumnNums.state].Append("State"); columnName[(int)ColumnNums.comment].Append("Comment"); columnName[(int)ColumnNums.pressure].Append("Pressure"); columnName[(int)ColumnNums.bellowsPosition].Append("Bel Pos"); columnName[(int)ColumnNums.batteryBusVolts].Append("Batt Volt"); columnName[(int)ColumnNums.GPS].Append("GPS"); columnName[(int)ColumnNums.IModem].Append("Irid Modem"); columnName[(int)ColumnNums.LPS331Pressure].Append("LPS331 Press"); columnName[(int)ColumnNums.LPS331Temperature].Append("LPS311 Temp"); columnName[(int)ColumnNums.SHT21Humidity].Append("SHT21 Humid"); columnName[(int)ColumnNums.SHT21Temperature].Append("SHT21 Temp"); columnName[(int)ColumnNums.CTDTemp].Append("CTD Temp"); columnName[(int)ColumnNums.CTDSalinity].Append("CTD Sal"); columnName[(int)ColumnNums.FLBB].Append("FLBB"); columnName[(int)ColumnNums.TOpt].Append("Topt"); columnName[(int)ColumnNums.TPhase].Append("Tphase"); columnName[(int)ColumnNums.RPhase].Append("Rphase"); columnName[(int)ColumnNums.NO3].Append("NO3"); columnName[(int)ColumnNums.pH].Append("pH"); columnName[(int)ColumnNums.SBE41Pressure].Append("Raw Press"); columnName[(int)ColumnNums.SBE41LPFPressure].Append("LPF Press"); columnName[(int)ColumnNums.SBE41LPFVelocity].Append("LPF Vel"); columnName[(int)ColumnNums.SBE41DiffVelocity].Append("Diff Vel"); columnName[(int)ColumnNums.SBE41Diff2Velocity].Append("Diff 2 Vel"); columnName[(int)ColumnNums.SBE41Slope].Append("Slope of LPF Press."); columnName[(int)ColumnNums.CTDSamplePeriod].Append("CTD Sample Period"); columnName[(int)ColumnNums.PID_SP].Append("PID SP"); columnName[(int)ColumnNums.PID_PV].Append("PID PV"); columnName[(int)ColumnNums.PID_y1].Append("PID Y1"); columnName[(int)ColumnNums.PID_y2].Append("PID Y2"); columnName[(int)ColumnNums.PID_I].Append("PID I"); columnName[(int)ColumnNums.PID_v].Append("PID v"); columnName[(int)ColumnNums.PID_u].Append("PID u"); columnName[(int)ColumnNums.PID_uCPS].Append("PID uCPS"); columnName[(int)ColumnNums.PID_h].Append("PID h"); columnName[(int)ColumnNums.batteryBusAmps].Append("Batt Amps"); columnName[(int)ColumnNums.Amps12V].Append("12V Amps"); columnName[(int)ColumnNums.Amps33V].Append("3.3V Amps"); columnName[(int)ColumnNums.debug].Append("Debug"); columnNames.Clear(); for (int i = 0; i < (int)ColumnNums.lastColumn; i++) { columnNames.Append(columnName[i]); columnNames.Append("\t"); } columnNames.Append("\r\n"); for (int i = 0; i < sbFileNames.Length; i++) sbFileNames[i] = new StringBuilder(128); #if(USB_STORAGE) try { RemovableMedia.Insert += new InsertEventHandler(usbRemovableMedia_Insert); RemovableMedia.Eject += new EjectEventHandler(usbRemovableMedia_Eject); Controller.MassStorageConnected += (sender, massStorage) => { usbStorage = massStorage; usbStorage.Mount(); // fires the insert event when finished }; Controller.Start(); usbInsertEvent.WaitOne(); // yield here until mounting and initializing is finished sdVol = new VolumeInfo("USB"); USBMounted = true; } catch { USBMounted = false; sbTemp.Clear(); sbTemp.Append("\r\n***Exception mounting USB card\r\n"); Debug.Print(sbTemp.ToString()); Program.btConsole.SendLine(sbTemp); } #else try { sdCard = new SDCard(); sdCard.Mount(); sdVol = new VolumeInfo("SD"); SDMounted = true; } catch { SDMounted = false; sbTemp.Clear(); sbTemp.Append("\r\n***Exception mounting SD card\r\n"); Debug.Print(sbTemp.ToString()); Program.btConsole.SendLine(sbTemp); } #endif if (SDMounted || USBMounted) { openFile(); uint resetControllerStatusValue = resetControllerStatus.Value; sbTemp.Clear(); sbTemp.Append("Reset Controller Status Register Value = "); sbTemp.Append(resetControllerStatusValue.ToString()); writeToColumns(sbTemp); sbTemp.Clear(); sbTemp.Append("File Name = "); sbTemp.Append(fileName.ToString()); writeToColumns(sbTemp); sbTemp.Clear(); sbTemp.Append("Volume Total Size: "); sbTemp.Append(sdVol.TotalSize.ToString()); writeToColumns(sbTemp); sbTemp.Clear(); sbTemp.Append("Volume Free Space: "); sbTemp.Append(sdVol.TotalFreeSpace.ToString()); writeToColumns(sbTemp); } sbTemp.Clear(); sbTemp.Append("PlatVel PID K = "); sbTemp.Append(configFile.KPlatVel.ToString()); writeToColumns(sbTemp); sbTemp.Clear(); sbTemp.Append("PlatVel PID Ti = "); sbTemp.Append(configFile.TiPlatVel.ToString()); writeToColumns(sbTemp); sbTemp.Clear(); sbTemp.Append("PlatVel PID Td = "); sbTemp.Append(configFile.TdPlatVel.ToString()); writeToColumns(sbTemp); sbTemp.Clear(); sbTemp.Append("PlatVel PID Tf = "); sbTemp.Append(configFile.TfPlatVel.ToString()); writeToColumns(sbTemp); sbTemp.Clear(); sbTemp.Append("PlatVel PID Tt = "); sbTemp.Append(configFile.TtPlatVel.ToString()); writeToColumns(sbTemp); sbTemp.Clear(); sbTemp.Append("PlatVel PID B = "); sbTemp.Append(configFile.BPlatVel.ToString()); writeToColumns(sbTemp); sbTemp.Clear(); sbTemp.Append("PlatVel PID uLow = "); sbTemp.Append(configFile.uLowPlatVel.ToString()); writeToColumns(sbTemp); sbTemp.Clear(); sbTemp.Append("PlatVel PID uHigh = "); sbTemp.Append(configFile.uHighPlatVel.ToString()); writeToColumns(sbTemp); sbTemp.Clear(); sbTemp.Append("PlatVel PID h = "); sbTemp.Append(configFile.hPlatVel.ToString()); writeToColumns(sbTemp); if (SDMounted || USBMounted) return (true); else return (false); } private static int lastValueIndex = 0; private static int columnNum = 0; private static int valueNum = 0; private static StringBuilder sbTemp2 = new StringBuilder(512); //If only one entry is in value array passed to his method, it gets treated as a comment and this method prepends date, time and state //All CR/LF are removed from the data until just before writing to SD card public static void writeToColumns(params object[] values) { lock (loggerLock) { timeNow = DateTime.Now; sbWrite.Clear(); sbWrite.Append("$"); sbWrite.Append(token); if (values.Length == 1) { sbWrite.Append(timeNow.ToString("dd-MMM-yyyy")); sbWrite.Append(token); sbWrite.Append(timeNow.ToString("HH:mm:ss.fff")); sbWrite.Append(token); sbWrite.Append(Program.cpfState[(int)Program.CurrentState].stateName); sbWrite.Append(token); sbWrite.Append(values[0]); } else { lastValueIndex = values.Length - 1; 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.dateTime) { timeNow = (DateTime)values[valueNum + 1]; sbWrite.Append(timeNow.ToString("dd-MMM-yyyy")); sbWrite.Append(token); sbWrite.Append(timeNow.ToString("HH:mm:ss.fff")); } else if (columnNum == (int)ColumnNums.state) sbWrite.Append(Program.cpfState[(int)Program.CurrentState].stateName); else if (columnNum == (int)ColumnNums.comment) sbWrite.Append(values[valueNum + 1]); else if ((columnNum == (int)ColumnNums.CTDSalinity) || (columnNum == (int)ColumnNums.TOpt) || (columnNum == (int)ColumnNums.IModem) || (columnNum == (int)ColumnNums.GPS) || (columnNum == (int)ColumnNums.FLBB)) { sbTemp.Clear(); try { sbTemp.Append(UTF8Encoding.UTF8.GetChars((byte[])values[valueNum + 1])); sbTemp.Replace('\r', ' '); sbTemp.Replace('\n', ' '); } catch { sbTemp2.Clear(); sbTemp2.Append("EngrLogger /r/n .Replace error location 1 string: "); sbTemp2.Append(sbTemp); EngrLogger.writeToColumns(sbTemp2); } sbWrite.Append(sbTemp); } else sbWrite.Append(((double)values[valueNum + 1]).ToString("f6")); break; } } sbWrite.Append(token); } } if (SDMounted || USBMounted) { try { sbWrite.Replace('\r', ' '); sbWrite.Replace('\n', ' '); } catch { sbTemp.Clear(); sbTemp.Append("EngrLogger /r/n .Replace error location 2 string: "); sbTemp.Append(sbWrite); EngrLogger.writeToColumns(sbTemp); } sbWrite.Append("\r\n"); Array.Clear(writeArray, 0, writeArray.Length); try { Array.Copy(UTF8Encoding.UTF8.GetBytes(sbWrite.ToString()), writeArray, sbWrite.Length); logFile.Write(writeArray, 0, sbWrite.Length); } catch { sbTemp.Clear(); sbTemp.Append("EngrLogger /r/n .Replace error location 3 string: "); sbTemp.Append(sbWrite); EngrLogger.writeToColumns(sbTemp); } } else { sbTemp.Clear(); sbTemp.Append("No SD: "); sbTemp.Append(sbWrite); sbWrite.Clear(); sbWrite.Append(sbTemp); } Program.btConsole.SendLine(sbWrite); } //Clear any terminating CR or LF since Debug.Print adds a CR/LF and TerraTerm should be set up to add a CR/LF try { sbWrite.Replace('\r', (char)32); sbWrite.Replace('\n', (char)32); } catch { sbTemp.Clear(); sbTemp.Append("EngrLogger /r/n .Replace error location 3 string: "); sbTemp.Append(sbWrite); EngrLogger.writeToColumns(sbTemp); } Debug.Print(sbWrite.ToString()); } private static void printVolInfo() { sbTemp.Clear(); sbTemp.Append("Volume Total Size: "); sbTemp.Append(sdVol.TotalSize.ToString()); writeToColumns(ColumnNums.comment, sbTemp); sbTemp.Clear(); sbTemp.Append("Volume Free Space: "); sbTemp.Append(sdVol.TotalFreeSpace.ToString()); writeToColumns(ColumnNums.comment, sbTemp); } private const int numFilesToGet = 20; public static int numFilesOnDisk = 0; public static StringBuilder[] sbFileNames = new StringBuilder[numFilesToGet]; public static void getDirectory() { String[] fileNames = Directory.GetFiles(sdVol.RootDirectory); sbTemp.Clear(); sbTemp.Append("Processing GETDIR Console message"); EngrLogger.writeToColumns(sbTemp); numFilesOnDisk = Directory.GetFiles(sdVol.RootDirectory).Length; int fileID = numFilesToGet - 1; int lastFile = numFilesOnDisk - numFilesToGet; if (lastFile < 0) lastFile = 0; if (numFilesOnDisk > 0) { for (int i = lastFile; i < numFilesOnDisk; i++) { try { fileID = numFilesOnDisk - (i + 1); FileInfo fileInfo = new FileInfo(fileNames[i]); sbFileNames[fileID].Clear(); sbFileNames[fileID].Append(fileNames[i]); sbTemp.Clear(); sbTemp.Append("File ID = " + fileID.ToString() + " File Name = " + fileInfo.Name + " Creation Date = " + fileInfo.CreationTime.ToString() + " Length = " + fileInfo.Length.ToString() + " FileNum = " + i.ToString()); Debug.Print(sbTemp.ToString()); sbTemp.AppendLine(); Program.btConsole.SendLine(sbTemp); fileID--; } catch { EngrLogger.writeToColumns("Error in getDir get FileInfo"); } } } else { sbTemp.Clear(); sbTemp.Append("No files on disk!"); Debug.Print(sbTemp.ToString()); sbTemp.AppendLine(); Program.btConsole.SendLine(sbTemp); } } 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; Thread.Sleep(1000); lock (loggerLock) { logFile.Write(UTF8Encoding.UTF8.GetBytes(columnNames.ToString()), 0, columnNames.Length); } Program.btConsole.SendLine(columnNames); Debug.Print(columnNames.ToString()); } public static void unMount() { if (SDMounted) sdCard.Unmount(); #if(USB_STORAGE) if (USBMounted) usbStorage.Unmount(); #endif } 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.cpfState[(int)Program.CurrentState].stateName); sbPrefix.Append(token); sbPrefix.Append(comment); return (sbPrefix); } // This event is fired by unmount static void usbRemovableMedia_Eject(object sender, MediaEventArgs e) { Debug.Print("USB unmounted, eject event fired"); } static void usbRemovableMedia_Insert(object sender, MediaEventArgs e) { Debug.Print("Insert event fired; USB Storage mount is finished."); //if (e.Volume.IsFormatted) //{ // rootDirectory = e.Volume.RootDirectory; // Debug.Print("Available folders:"); // string[] strs = Directory.GetDirectories(e.Volume.RootDirectory); // for (int i = 0; i < strs.Length; i++) // Debug.Print(strs[i]); // Debug.Print("Available files:"); // strs = Directory.GetFiles(e.Volume.RootDirectory); // for (int i = 0; i < strs.Length; i++) // Debug.Print(strs[i]); //} //else //{ // Debug.Print("Media is not formatted. Formatting..."); // e.Volume.Format("FAT", 0); // rootDirectory = e.Volume.RootDirectory; //} #if(USB_STORAGE) usbInsertEvent.Set(); // proceed with other processing #endif } } }