using System; using Microsoft.SPOT; using System.Threading; using System.IO.Ports; using System.Text; using Microsoft.SPOT.Hardware; namespace CPF { class Optode { public static SerialPort optodePort = new SerialPort("COM6", 9600, Parity.None, 8, StopBits.One); private static byte[] txBytes = new byte[64]; private static int messageIndex = 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.byteArrayWidth]; optodePort.ReadTimeout = 5000; optodePort.Open(); optodePort.DiscardInBuffer(); optodePort.DiscardOutBuffer(); optodePort.DataReceived += new SerialDataReceivedEventHandler(optodeDataReceived); wakeUp(); Thread.Sleep(2000); } public enum commands : int { none = 0, getAll } public static bool waitingForResponse = false; public static bool gotResponse = false; private static readonly StringBuilder getAllResponse = new StringBuilder("#\r"); public static byte[] expectedResponse = new byte[64]; public static int expectedResponseLength = 0; private static int numRetries = 0; private static readonly int maxNumRetries = 3; private static TimeSpan wfrStartTime = new TimeSpan(); private static readonly TimeSpan wfrTimeout = new TimeSpan(0, 0, 30); private static readonly string wfrFail = "Optode waitingForResponse expended all retries"; private static StringBuilder sbTemp = new StringBuilder(128); public static int waitForResponse(commands commandNum) { if (waitingForResponse) //Do this after the first call to this method { if (gotResponse) //success { waitingForResponse = false; return (1); } else if ((Microsoft.SPOT.Hardware.Utility.GetMachineTime() - wfrStartTime) > wfrTimeout) //if timeout has expired, try again up to the max number of retries { if (numRetries > maxNumRetries) { Debug.Print(wfrFail); Array.Clear(qS.byteArray, 0, qS.byteArray.Length); Array.Copy(UTF8Encoding.UTF8.GetBytes(wfrFail), qS.byteArray, wfrFail.Length); qS.timeStamp = DateTime.Now; qS.state = Program.CPFState; qS.qRecordType = StructQueue.QRecordType.Optode; lock (optodeLock) { Program.sQueue.Enqueue(qS); } return (-1); } else { waitingForResponse = false; sbTemp.Clear(); sbTemp.Append("Optode waitingForResponse try number "); sbTemp.Append(numRetries); Debug.Print(sbTemp.ToString()); return (0); } } else return (0); } else //Do this the first time the method is called and after a timeout { switch (commandNum) { case commands.getAll: Array.Copy(UTF8Encoding.UTF8.GetBytes(getAllResponse.ToString()), expectedResponse, getAllResponse.Length); expectedResponseLength = getAllResponse.Length; //Debug.Print(DateTime.Now.TimeOfDay.ToString() + " Sending getAll command"); getAll(); break; } wfrStartTime = Microsoft.SPOT.Hardware.Utility.GetMachineTime(); numRetries = numRetries + 1; gotResponse = false; waitingForResponse = true; return (0); } } private static StringBuilder wakeUpCmd = new StringBuilder("\r"); public static void wakeUp() { //Debug.Print("Sending Wake Up"); Array.Clear(txBytes, 0, txBytes.Length); Array.Copy(Encoding.UTF8.GetBytes(wakeUpCmd.ToString()), txBytes, wakeUpCmd.Length); optodePort.Write(txBytes, 0, wakeUpCmd.Length); } private const string doSampleCmd = "Do Sample\r\n"; private const string doSampleHeader = "Sending Optode Do Sample"; public static void doSample() { //Debug.Print("Sending Optode wakeup and Do Sample"); Array.Clear(qS.byteArray, 0, qS.byteArray.Length); Array.Copy(UTF8Encoding.UTF8.GetBytes(doSampleHeader), qS.byteArray, doSampleHeader.Length); qS.state = Program.CPFState; qS.qRecordType = StructQueue.QRecordType.Optode; qS.timeStamp = DateTime.Now; lock (optodeLock) { Program.sQueue.Enqueue(qS); } wakeUp(); Thread.Sleep(500); Array.Clear(txBytes, 0, txBytes.Length); Array.Copy(Encoding.UTF8.GetBytes(doSampleCmd.ToString()), txBytes, doSampleCmd.Length); optodePort.Write(txBytes, 0, doSampleCmd.Length); } private const string getAllCmd = "get all\r\n"; public static void getAll() { //Debug.Print("Sending Optode wakeup and Get All"); wakeUp(); Thread.Sleep(500); Array.Clear(txBytes, 0, txBytes.Length); Array.Copy(Encoding.UTF8.GetBytes(getAllCmd), txBytes, getAllCmd.Length); optodePort.Write(txBytes, 0, getAllCmd.Length); } private const int ehBufferSize = 2048; private static byte[] portBytes = new byte[ehBufferSize]; private static byte[] messageBytes = new byte[ehBufferSize]; private static byte[] errorHeader = new byte[5] { (byte)69, (byte)114, (byte)114, (byte)111, (byte)114 }; private static byte LF = 10; //End of text = LF private static void optodeDataReceived(object sender, SerialDataReceivedEventArgs e) { numPortBytes = optodePort.BytesToRead; if ((numPortBytes + messageIndex + 50) < ehBufferSize) { 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] != LF) { messageBytes[messageIndex] = portBytes[i]; messageIndex = messageIndex + 1; } else { Array.Clear(qS.byteArray, 0, qS.byteArray.Length); Array.Copy(messageBytes, qS.byteArray, (messageIndex - 1)); qS.timeStamp = DateTime.Now; qS.state = Program.CPFState; qS.qRecordType = StructQueue.QRecordType.Optode; lock (optodeLock) { Program.sQueue.Enqueue(qS); } messageIndex = 0; } } } else { ErrorHandler.incrOptodeEHErrors(); Array.Clear(qS.byteArray, 0, qS.byteArray.Length); Array.Copy(errorHeader, qS.byteArray, errorHeader.Length); Array.Copy(messageBytes, qS.byteArray, (messageIndex - 1)); qS.timeStamp = DateTime.Now; qS.state = Program.CPFState; qS.qRecordType = StructQueue.QRecordType.Optode; lock (optodeLock) { Program.sQueue.Enqueue(qS); } } } } }