using System; using Microsoft.SPOT; using System.Threading; using System.IO.Ports; using System.Text; using Microsoft.SPOT.Hardware; namespace miniCPF { class Optode { public static SerialPort optodePort = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One); private const string wakeUpCmd = "\r"; private const string getAllCmd = "get all\r\n"; private const string doSampleCmd = "Do Sample\r\n"; private static byte[] txBytes = new byte[64]; private static byte ETX = 10; //End of text = LF private static int msgIndex = 0; private static int numPortBytes = 0; private static object optodeLock = new object(); private static StructQueue.qStruct qS = new StructQueue.qStruct(); //MEASUREMENT 4330 1532 // O2Concentration[uM] 2.644894E+02 AirSaturation[%] 9.722411E+01 // Temperature[Deg.C] 2.217678E+01 CalPhase[Deg] 2.919595E+01 // TCPhase[Deg] 2.919595E+01 C1RPh[Deg] 3.770208E+01 // C2RPh[Deg] 8.506126E+00 C1Amp[mV] 8.645895E+02 // C2Amp[mV] 9.500998E+02 RawTemp[mV] 1.244538E+02 public enum OptodeSampleFields : int { O2Conc = 0, AirSat, TOpt, CalPhase, TCPhase, C1RPh, C2RPh, C1Amp, C2Amp, RawTemp } public static void init() { qS.byteArray = new byte[StructQueue.qRecordWidth]; optodePort.ReadTimeout = 5000; optodePort.Open(); optodePort.DiscardInBuffer(); optodePort.DiscardOutBuffer(); wakeUp(); getAll(); optodePort.DataReceived += new SerialDataReceivedEventHandler(optodeDataReceived); optodePort.DiscardInBuffer(); optodePort.DiscardOutBuffer(); } public static void wakeUp() { //Debug.Print("Sending Wake Up"); Array.Clear(txBytes, 0, txBytes.Length); txBytes = Encoding.UTF8.GetBytes(wakeUpCmd); optodePort.Write(txBytes, 0, wakeUpCmd.Length); } private static bool endGetAll = false; private static int lineNum = 0; private static StringBuilder sbTemp = new StringBuilder(4096); private static byte[] getAllPortBytes = new byte[4096]; private static byte[] getAllMsgBytes = new byte[4096]; public static void getAll() { optodePort.DiscardInBuffer(); optodePort.DiscardOutBuffer(); //Debug.Print("Sending Get All"); Array.Clear(txBytes, 0, txBytes.Length); txBytes = Encoding.UTF8.GetBytes(getAllCmd); optodePort.Write(txBytes, 0, getAllCmd.Length); Thread.Sleep(1000); sbTemp.Clear(); Array.Clear(getAllMsgBytes, 0, msgBytes.Length); Array.Clear(getAllPortBytes, 0, portBytes.Length); msgIndex = 0; endGetAll = false; while (!endGetAll) { numPortBytes = optodePort.BytesToRead; try { optodePort.Read(getAllPortBytes, 0, numPortBytes); } catch { Debug.Print("Optode Port Get All Read Exception"); //Probably should do something smarter here } for (int i = 0; i < numPortBytes; i++) { if (getAllPortBytes[i] != ETX) { if ((msgIndex == 0) && (getAllPortBytes[i] == '#')) { endGetAll = true; } else { getAllMsgBytes[msgIndex] = getAllPortBytes[i]; msgIndex = msgIndex + 1; } } else { sbTemp.Append(UTF8Encoding.UTF8.GetChars(getAllMsgBytes, 0, (msgIndex - 1))); lock (optodeLock) { EngrLogger.write(EngrLogger.ColumnNums.comment, EngrLogger.getPrefix(sbTemp)); } sbTemp.Clear(); msgIndex = 0; lineNum = lineNum + 1; } } } optodePort.DiscardInBuffer(); optodePort.DiscardOutBuffer(); } private static DateTime timeStamp; private static Program.CPFStates cpfState; public static void doSample() { //Debug.Print("Sending Do Sample"); Array.Clear(txBytes, 0, txBytes.Length); txBytes = Encoding.UTF8.GetBytes(doSampleCmd); optodePort.Write(txBytes, 0, doSampleCmd.Length); timeStamp = DateTime.Now; cpfState = Program.CPFState; } private static byte[] portBytes = new byte[512]; private static byte[] msgBytes = new byte[512]; private static void optodeDataReceived(object sender, SerialDataReceivedEventArgs e) { numPortBytes = optodePort.BytesToRead; try { optodePort.Read(portBytes, 0, numPortBytes); } catch { Debug.Print("Optode Port Read Exception"); //Probably should do something smarter here } for (int i = 0; i < numPortBytes; i++) { if (portBytes[i] != 35) { msgBytes[msgIndex] = portBytes[i]; msgIndex = msgIndex + 1; } else { Array.Clear(qS.byteArray, 0, qS.byteArray.Length); Array.Copy(msgBytes, qS.byteArray, (msgIndex - 1)); qS.timeStamp = timeStamp; qS.state = cpfState; qS.qDel = qDelegate; lock (optodeLock) { Program.sQ.Enqueue(qS); } msgIndex = 0; } } } private static int startIndex = 0; private static int endIndex = 0; private static int measurementIndex = 0; private static byte[] valueBytes = new byte[64]; private static byte[] inByteArray = new byte[512]; private static double[] optodeMeasurements = new double[16]; private static void parseOptodeSample(byte[] inByteArray) { measurementIndex = 0; startIndex = Array.IndexOf(inByteArray, '\t'); Array.Clear(optodeMeasurements, 0, optodeMeasurements.Length); for (int i = 0; i < 22; i++) { if (i == 21) endIndex = Array.IndexOf(inByteArray, 0); else endIndex = Array.IndexOf(inByteArray, '\t', startIndex + 1); if ((i == 3) || (i == 5) || (i == 7) || (i == 9) || (i == 11) || (i == 13) || (i == 15) || (i == 17) || (i == 19) || (i == 21)) { Array.Clear(valueBytes, 0, valueBytes.Length); //The last field will have a /r in it and we need to get rid of it before Parsing if(i != 21) Array.Copy(inByteArray, startIndex + 1, valueBytes, 0, endIndex - startIndex - 1); else Array.Copy(inByteArray, startIndex + 1, valueBytes, 0, endIndex - startIndex - 2); sbTemp.Clear(); sbTemp.Append(UTF8Encoding.UTF8.GetChars(valueBytes)); optodeMeasurements[measurementIndex] = double.Parse(sbTemp.ToString()); measurementIndex = measurementIndex + 1; } startIndex = endIndex; } } private static StringBuilder sbLogMsg = new StringBuilder(StructQueue.qRecordWidth); private static StringBuilder sbLogPrefix = new StringBuilder(StructQueue.qRecordWidth); private static readonly StringBuilder optodeComment = new StringBuilder("O2 Msg"); private static void qDelegate(StructQueue.qStruct inQStruct) { sbTemp.Clear(); sbTemp.Append(UTF8Encoding.UTF8.GetChars(inQStruct.byteArray)); Debug.Print(sbTemp.ToString()); parseOptodeSample(inQStruct.byteArray); sbLogMsg.Clear(); sbLogPrefix.Clear(); sbLogMsg = EngrLogger.formatRecord( EngrLogger.ColumnNums.comment, EngrLogger.getPrefix(inQStruct.timeStamp, inQStruct.state, optodeComment), EngrLogger.ColumnNums.TOpt, optodeMeasurements[(int)OptodeSampleFields.TOpt], EngrLogger.ColumnNums.TPhase, optodeMeasurements[(int)OptodeSampleFields.TCPhase], EngrLogger.ColumnNums.RPhase, optodeMeasurements[(int)OptodeSampleFields.C2RPh]); Array.Clear(qS.byteArray, 0, qS.byteArray.Length); Array.Copy(UTF8Encoding.UTF8.GetBytes(sbLogMsg.ToString()), qS.byteArray, sbLogMsg.Length); qS.timeStamp = timeStamp; qS.state = cpfState; qS.qDel = EngrLogger.qDelegate; lock (optodeLock) { Program.sQ.Enqueue(qS); } } } }