using System; using System.IO.Ports; using System.Text; using System.Threading; using SWModules; namespace HWModules { // This is a Singleton instantiation based on // C# in Depth, Third Edition Jon Skeet // http://csharpindepth.com/Articles/General/Singleton.aspx // "a singleton is a class which only allows a single instance of itself to be created, and usually gives simple access to that instance" public sealed class Optode1 : Aandera4330Optode { private Optode1() : base("OPTODE1", "COM6", 9600, Parity.None, 8, StopBits.One, 5000, 20, false, 10) { } private static Optode1 instance; public static Optode1 Instance { get { return instance ?? (instance = new Optode1()); } } } public class Aandera4330Optode { private static byte[] txBytes = new byte[64]; //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 } private NativeUART IOPort; public Aandera4330Optode (string id, string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits, int readTimeout, int writeTimeout, bool useSTX, byte STX) { IOPort = new NativeUART(id, processMessage, portName, baudRate, parity, dataBits, stopBits, readTimeout, writeTimeout, useSTX, STX); } public void init() { IOPort.Open(); IOPort.DiscardInBuffer(); IOPort.DiscardOutBuffer(); wakeUp(); Thread.Sleep(1000); const string setPasskeyLow = "Set Passkey(1)\r\n"; const string disableText = "Set Enable Text(no)\r\n"; const string disableAirSat = "Set Enable AirSaturation(no)\r\n"; const string disableRawdata = "Set Enable Rawdata(no)\r\n"; Array.Clear(txBytes, 0, txBytes.Length); Array.Copy(Encoding.UTF8.GetBytes(setPasskeyLow), txBytes, setPasskeyLow.Length); IOPort.Write(txBytes, 0, setPasskeyLow.Length); Thread.Sleep(1000); Array.Clear(txBytes, 0, txBytes.Length); Array.Copy(Encoding.UTF8.GetBytes(disableText), txBytes, disableText.Length); IOPort.Write(txBytes, 0, disableText.Length); Thread.Sleep(1000); Array.Clear(txBytes, 0, txBytes.Length); Array.Copy(Encoding.UTF8.GetBytes(disableAirSat), txBytes, disableAirSat.Length); IOPort.Write(txBytes, 0, disableAirSat.Length); Thread.Sleep(1000); //Array.Clear(txBytes, 0, txBytes.Length); //Array.Copy(Encoding.UTF8.GetBytes(disableRawdata), txBytes, disableRawdata.Length); //IOPort.Write(txBytes, 0, disableRawdata.Length); //Thread.Sleep(1000); } public enum commands : int { none = 0, getAll, doSample } 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 = SV.CurrentState; // qS.qRecordType = StructQueue.QRecordType.Optode; // 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 void wakeUp() { //Debug.Print("Sending Wake Up"); EngrLogger.writeToColumns("Sending Optode Wakeup"); Array.Clear(txBytes, 0, txBytes.Length); Array.Copy(Encoding.UTF8.GetBytes(wakeUpCmd.ToString()), txBytes, wakeUpCmd.Length); IOPort.Write(txBytes, 0, wakeUpCmd.Length); } private const string doSampleCmd = "Do Sample\r\n"; private const string doSampleHeader = "Sending Optode Do Sample"; public void doSample() { //Debug.Print("Sending Optode wakeup and Do Sample"); EngrLogger.writeToColumns(doSampleHeader); //Array.Clear(qS.byteArray, 0, qS.byteArray.Length); //Array.Copy(UTF8Encoding.UTF8.GetBytes(doSampleHeader), qS.byteArray, doSampleHeader.Length); //qS.state = SV.CurrentState; //qS.qRecordType = StructQueue.QRecordType.Optode; //qS.timeStamp = DateTime.Now; //Program.sQueue.Enqueue(qS); wakeUp(); Thread.Sleep(500); Array.Clear(txBytes, 0, txBytes.Length); Array.Copy(Encoding.UTF8.GetBytes(doSampleCmd.ToString()), txBytes, doSampleCmd.Length); IOPort.Write(txBytes, 0, doSampleCmd.Length); } private const string getAllCmd = "get all\r\n"; public void getAll() { //Debug.Print("Sending Get All"); EngrLogger.writeToColumns("Sending Optode GetAll"); wakeUp(); Thread.Sleep(500); Array.Clear(txBytes, 0, txBytes.Length); Array.Copy(Encoding.UTF8.GetBytes(getAllCmd), txBytes, getAllCmd.Length); IOPort.Write(txBytes, 0, getAllCmd.Length); } private static int msgLength = 0; private static readonly StringBuilder OptodeHeader = new StringBuilder("Optode Message"); public void processMessage(QRecord qRecord) { for (int i = 0; i < qRecord.byteArray.Length; i++) { if (qRecord.byteArray[i] == 9) qRecord.byteArray[i] = 44; } EngrLogger.writeToColumns(EngrLogger.ColumnNums.dateTime, qRecord.timeStamp, EngrLogger.ColumnNums.state, qRecord.state, EngrLogger.ColumnNums.comment, OptodeHeader, EngrLogger.ColumnNums.pressure, SV.Pressure, EngrLogger.ColumnNums.TOpt, qRecord.byteArray); //check for expectedResponse anywhere in the SBE41 response message msgLength = qRecord.byteArray.Length; if (Aandera4330Optode.waitingForResponse) { if (msgLength > Aandera4330Optode.expectedResponseLength) { for (int j = 0; j < msgLength - Aandera4330Optode.expectedResponseLength; j++) { for (int k = 0; k < Aandera4330Optode.expectedResponseLength; k++) { if (qRecord.byteArray[j + k] != Aandera4330Optode.expectedResponse[k]) { Aandera4330Optode.gotResponse = false; break; } } } Aandera4330Optode.gotResponse = true; } } if (SciLogger.samplingInstruments) SciLogger.logSciSample(QRecordType.Optode, qRecord.byteArray); } //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 = SV.CurrentState; // qS.qRecordType = StructQueue.QRecordType.Optode; // 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 = SV.CurrentState; // qS.qRecordType = StructQueue.QRecordType.Optode; // Program.sQueue.Enqueue(qS); // } //} } }