using System; using System.IO; using System.Threading; using Microsoft.SPOT; using Microsoft.SPOT.Hardware; using Microsoft.SPOT.IO; using GHI.Premium.IO; namespace LOGGER { public class SD_Card_WTF_Exception : System.Exception { public SD_Card_WTF_Exception() : base() { } public SD_Card_WTF_Exception(string message) : base(message) { } public SD_Card_WTF_Exception(string message, System.Exception inner) : base(message, inner) { } } public class SD_Logger : IDisposable { // A write queue to (help) mask the latency of writing to the SD card private SynchronizedLogEntryQueue _logQ; private Thread _writingThread; private LogEntry _writeBuffer; private AutoResetEvent _SD_CardMounted; private AutoResetEvent _logQ_written; private const string FILE_NAME_FORMAT = "yyyyMMdd"; // format for file name data logging (YYYYMMDD.txt) private const string FILE_EXT = ".log"; // extension for data logging files private string _rootDirectory; private string _dirPath; // directory on SD for data logging private string _logDirectory; private FileStream _fs; // file stream for data logging private TextWriter _tw; // text writer for data logging private bool _isOpen; // data logger opened or not private bool _disposed = false; // disposing state // Constructor, "dirpath" = Directory on SD for data logging public SD_Logger(string logDirectory) { _logDirectory = logDirectory; _isOpen = true; _rootDirectory = null; _dirPath = null; // _rootDirectory = VolumeInfo.GetVolumes()[0].RootDirectory; _dirPath = _rootDirectory + logDirectory; _logQ = new SynchronizedLogEntryQueue(128); _SD_CardMounted = new AutoResetEvent(false); _logQ_written = new AutoResetEvent(false); _writingThread = new Thread(new ThreadStart(LogWriter)); _writingThread.Start(); //_writeBuffer = new LogEntry(); } static void VolumeInfo() { Debug.Print("SD card inserted"); #if FOO 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]); #endif } public void Open() { // create root data directory if doesn't exist if (!Directory.Exists(_dirPath)) Directory.CreateDirectory(_dirPath); // create file path for data logging string filePath = _dirPath + DateTime.Now.ToString(FILE_NAME_FORMAT) + FILE_EXT; // open the file in append mode or create it if (_fs == null) { _fs = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.Read); _tw = new StreamWriter(_fs); } } public void Close() { this.Dispose(true); GC.SuppressFinalize(this); _isOpen = false; _logQ_written.WaitOne(); } public void Log(LogEntry e) { _logQ.Add(e); } #if FOO private void LogWriter() { PersistentStorage sdPS = null; const int POLL_TIME = 500; // check every 500 millisecond bool sdExists; while (IsOpen) { try // If SD card was removed while mounting, it may throw exceptions { sdExists = PersistentStorage.DetectSDCard(); // make sure it is fully inserted and stable if (sdExists) { Thread.Sleep(50); sdExists = PersistentStorage.DetectSDCard(); } if (sdExists && sdPS == null) { sdPS = new PersistentStorage("SD"); sdPS.MountFileSystem(); _rootDirectory = VolumeInfo.GetVolumes()[0].RootDirectory; _dirPath = _rootDirectory + _logDirectory; _SD_CardMounted.Set(); } if (!sdExists && sdPS != null) { sdPS.UnmountFileSystem(); sdPS.Dispose(); sdPS = null; } } catch { if (sdPS != null) { sdPS.Dispose(); sdPS = null; } } while (!_logQ.Empty() && sdPS != null) { _logQ.Remove(ref _writeBuffer); string writeThis = _writeBuffer.ToString(); Debug.Print(writeThis); byte[] buffer = System.Text.Encoding.UTF8.GetBytes(writeThis); _fs.Write(buffer, 0, buffer.Length); } if (_isOpen == false) // Closing the log _logQ_written.Set(); Thread.Sleep(POLL_TIME); } } #endif private void LogWriter() { PersistentStorage sdPS = null; const int POLL_TIME = 500; // check every 500 millisecond bool sdExists; while (IsOpen) { try // If SD card was removed while mounting, it may throw exceptions { sdExists = PersistentStorage.DetectSDCard(); // make sure it is fully inserted and stable if (sdExists) { Thread.Sleep(50); sdExists = PersistentStorage.DetectSDCard(); } if (sdExists && sdPS == null) { sdPS = new PersistentStorage("SD"); sdPS.MountFileSystem(); } if (!sdExists && sdPS != null) { sdPS.UnmountFileSystem(); sdPS.Dispose(); sdPS = null; } } catch { if (sdPS != null) { sdPS.Dispose(); sdPS = null; } } while (!_logQ.Empty() && sdPS != null) { _logQ.Remove(ref _writeBuffer); string writeThis = _writeBuffer.ToString(); Debug.Print(writeThis); byte[] buffer = System.Text.Encoding.UTF8.GetBytes(writeThis); _fs.Write(buffer, 0, buffer.Length); } Thread.Sleep(POLL_TIME); } } public bool IsOpen { get { return _isOpen; } } ~SD_Logger() { Dispose(false); } public void Dispose() { Close(); } // Dispose managed and unmanaged resources private void Dispose(bool disposing) { if (!_disposed) { if (disposing) { // dispose managed resources if (_tw != null) _tw.Dispose(); _tw = null; if (_fs != null) _fs.Dispose(); _fs = null; } // no unmanaged resources to dispose } _disposed = true; } // Check SD card presence private void CheckSD() { bool isSDCardInserted = false; // VolumeInfo[] volumes = VolumeInfo.GetVolumes(); // isSDCardInserted = (volumes.Length > 0); if (!isSDCardInserted) { throw new SD_Card_WTF_Exception(); } } } }