/*******************************************************************************
* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
* 
* This software is protected by copyright laws of the United States and
* of foreign countries. This material may also be protected by patent laws
* and technology transfer regulations of the United States and of foreign
* countries. This software is furnished under a license agreement and/or a
* nondisclosure agreement and may only be used or reproduced in accordance
* with the terms of those agreements. Dissemination of this information to
* any party or parties not specified in the license agreement and/or
* nondisclosure agreement is expressly prohibited.
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Maxim Integrated
* Products, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
*******************************************************************************
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RPCSupport.Devices;
using System.Globalization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Threading;

namespace RPCSupport.DataLogging
{
    public class DataLogging : ClientDevice
    {

        public class cParametersEcg : cDeviceMethodParameters
        {
            public cParametersEcg(String className, String methodName) : base(className, methodName) { }
            public int En_ecg;
            public int Openp;
            public int Openn;
            public int Pol;
            public int Calp_sel;
            public int Caln_sel;
            public int E_fit;
            public int Rate;
            public int Gain;
            public int Dhpf;
            public int Dlpf;

            public override void AssignByIntArray(int[] intArray)
            {
                int i = 0;
                En_ecg = intArray[i++];
                Openp = intArray[i++];
                Openn = intArray[i++];
                Pol = intArray[i++];
                Calp_sel = intArray[i++];
                Caln_sel = intArray[i++];
                E_fit = intArray[i++];
                Rate = intArray[i++];
                Gain = intArray[i++];
                Dhpf = intArray[i++];
                Dlpf = intArray[i++];
            }
            public override int[] ToIntArray()
            {
                int i = 0;
                List<int> intArray = new List<int>();
                intArray.Add(En_ecg);
                intArray.Add(Openp);
                intArray.Add(Openn);
                intArray.Add(Pol);
                intArray.Add(Calp_sel);
                intArray.Add(Caln_sel);
                intArray.Add(E_fit);
                intArray.Add(Rate);
                intArray.Add(Gain);
                intArray.Add(Dhpf);
                intArray.Add(Dlpf);
                return intArray.ToArray();
            }

            public void AssignByValue(
                int En_ecg,
                int Openp,
                int Openn,
                int Pol,
                int Calp_sel,
                int Caln_sel,
                int E_fit,
                int Rate,
                int Gain,
                int Dhpf,
                int Dlpf)
            {
                this.En_ecg = En_ecg;
                this.Openp = Openp;
                this.Openn = Openn;
                this.Pol = Pol;
                this.Calp_sel = Calp_sel;
                this.Caln_sel = Caln_sel;
                this.E_fit = E_fit;
                this.Rate = Rate;
                this.Gain = Gain;
                this.Dhpf = Dhpf;
                this.Dlpf = Dlpf;
            }
        }
//        public cParametersEcg ParametersMAX30001Ecg = new cParametersEcg();
        
        public class cParametersBioz : cDeviceMethodParameters
        {
            public cParametersBioz(String className, String methodName) : base(className, methodName) { }
            public int En_bioz;
            public int Openp;
            public int Openn;
            public int Calp_sel;
            public int Caln_sel;
            public int CG_mode;
            public int B_fit;
            public int Rate;
            public int Ahpf;
            public int Ext_rbias;
            public int Gain;
            public int Dhpf;
            public int Dlpf;
            public int Fcgen;
            public int Cgmon;
            public int Cgmag;
            public int Phoff;
            public override void AssignByIntArray(int[] intArray)
            {
                int i = 0;
                En_bioz = intArray[i++];
                Openp = intArray[i++];
                Openn = intArray[i++];
                Calp_sel = intArray[i++];
                Caln_sel = intArray[i++];
                CG_mode = intArray[i++];
                B_fit = intArray[i++];
                Rate = intArray[i++];
                Ahpf = intArray[i++];
                Ext_rbias = intArray[i++];
                Gain = intArray[i++];
                Dhpf = intArray[i++];
                Dlpf = intArray[i++];
                Fcgen = intArray[i++];
                Cgmon = intArray[i++];
                Cgmag = intArray[i++];
                Phoff = intArray[i++];
            }

            public override int[] ToIntArray()
            {
                int i = 0;
                List<int> intArray = new List<int>();
                intArray.Add(En_bioz);
                intArray.Add(Openp);
                intArray.Add(Openn);
                intArray.Add(Calp_sel);
                intArray.Add(Caln_sel);
                intArray.Add(CG_mode);
                intArray.Add(B_fit);
                intArray.Add(Rate);
                intArray.Add(Ahpf);
                intArray.Add(Ext_rbias);
                intArray.Add(Gain);
                intArray.Add(Dhpf);
                intArray.Add(Dlpf);
                intArray.Add(Fcgen);
                intArray.Add(Cgmon);
                intArray.Add(Cgmag);
                intArray.Add(Phoff);
                return intArray.ToArray();
            }

            public void AssignByValue(
                int En_bioz,
                int Openp,
                int Openn,
                int Calp_sel,
                int Caln_sel,
                int CG_mode,
                int B_fit,
                int Rate,
                int Ahpf,
                int Ext_rbias,
                int Gain,
                int Dhpf,
                int Dlpf,
                int Fcgen,
                int Cgmon,
                int Cgmag,
                int Phoff)
            {
                this.En_bioz = En_bioz;
                this.Openp = Openp;
                this.Openn = Openn;
                this.Calp_sel = Calp_sel;
                this.Caln_sel = Caln_sel;
                this.CG_mode = CG_mode;
                this.B_fit = B_fit;
                this.Rate = Rate;
                this.Ahpf = Ahpf;
                this.Ext_rbias = Ext_rbias;
                this.Gain = Gain;
                this.Dhpf = Dhpf;
                this.Dlpf = Dlpf;
                this.Fcgen = Fcgen;
                this.Cgmon = Cgmon;
                this.Cgmag = Cgmag;
                this.Phoff = Phoff;
            }
        }
        //public cParametersBioz ParametersMAX30001Bioz = new cParametersBioz();

        public class cParametersRtoR : cDeviceMethodParameters
        {
            public cParametersRtoR(String className, String methodName) : base(className, methodName) { }
            public int En_rtor;
            public int Wndw;
            public int Gain;
            public int Pavg;
            public int Ptsf;
            public int Hoff;
            public int Ravg;
            public int Rhsf;
            public int Clr_rrint;
            public override void AssignByIntArray(int[] intArray)
            {
                int i = 0;
                En_rtor = intArray[i++];
                Wndw = intArray[i++];
                Gain = intArray[i++];
                Pavg = intArray[i++];
                Ptsf = intArray[i++];
                Hoff = intArray[i++];
                Ravg = intArray[i++];
                Rhsf = intArray[i++];
                Clr_rrint = intArray[i++];
            }

            public override int[] ToIntArray()
            {
                int i = 0;
                List<int> intArray = new List<int>();
                intArray.Add(En_rtor);
                intArray.Add(Wndw);
                intArray.Add(Gain);
                intArray.Add(Pavg);
                intArray.Add(Ptsf);
                intArray.Add(Hoff);
                intArray.Add(Ravg);
                intArray.Add(Rhsf);
                intArray.Add(Clr_rrint);
                return intArray.ToArray();
            }

            public void AssignByValue(
                int En_rtor,
                int Wndw,
                int Gain,
                int Pavg,
                int Ptsf,
                int Hoff,
                int Ravg,
                int Rhsf,
                int Clr_rrint)
            {
                this.En_rtor = En_rtor;
                this.Wndw = Wndw;
                this.Gain = Gain;
                this.Pavg = Pavg;
                this.Ptsf = Ptsf;
                this.Hoff = Hoff;
                this.Ravg = Ravg;
                this.Rhsf = Rhsf;
                this.Clr_rrint = Clr_rrint;
            }
        }
        //public cParametersRtoR ParametersMAX30001RtoR = new cParametersRtoR();

        public class cParametersPace : cDeviceMethodParameters
        {
            public cParametersPace(String className, String methodName) : base(className, methodName) { }
            public int En_pace;
            public int Clr_pedge;
            public int Pol;
            public int Gn_diff_off;
            public int Gain;
            public int Aout_lbw;
            public int Aout;
            public int Dacp;
            public int Dacn;
            public override void AssignByIntArray(int[] intArray)
            {
                int i = 0;
                En_pace = intArray[i++];
                Clr_pedge = intArray[i++];
                Pol = intArray[i++];
                Gn_diff_off = intArray[i++];
                Gain = intArray[i++];
                Aout_lbw = intArray[i++];
                Aout = intArray[i++];
                Dacp = intArray[i++];
                Dacn = intArray[i++];
            }

            public override int[] ToIntArray()
            {
                int i = 0;
                List<int> intArray = new List<int>();
                intArray.Add(En_pace);
                intArray.Add(Clr_pedge);
                intArray.Add(Pol);
                intArray.Add(Gn_diff_off);
                intArray.Add(Gain);
                intArray.Add(Aout_lbw);
                intArray.Add(Aout);
                intArray.Add(Dacp);
                intArray.Add(Dacn);
                return intArray.ToArray();
            }

            public void AssignByValue(
                int En_pace,
                int Clr_pedge,
                int Pol,
                int Gn_diff_off,
                int Gain,
                int Aout_lbw,
                int Aout,
                int Dacp,
                int Dacn)
            {
                this.En_pace = En_pace;
                this.Clr_pedge = Clr_pedge;
                this.Pol = Pol;
                this.Gn_diff_off = Gn_diff_off;
                this.Gain = Gain;
                this.Aout = Aout;
                this.Dacp = Dacp;
                this.Dacn = Dacn;
            }
        }

        public class cParametersCal : cDeviceMethodParameters
        {
            public cParametersCal(String className, String methodName) : base(className, methodName) { }
            public int parameter1;
            public int parameter2;
            public int parameter3;
            public int parameter4;
            public int parameter5;
            public int parameter6;
            public override void AssignByIntArray(int[] intArray)
            {
                int i = 0;
                parameter1 = intArray[i++];
                parameter2 = intArray[i++];
                parameter3 = intArray[i++];
                parameter4 = intArray[i++];
                parameter5 = intArray[i++];
                parameter6 = intArray[i++];
            }

            public override int[] ToIntArray()
            {
                int i = 0;
                List<int> intArray = new List<int>();
                intArray.Add(parameter1);
                intArray.Add(parameter2);
                intArray.Add(parameter3);
                intArray.Add(parameter4);
                intArray.Add(parameter5);
                intArray.Add(parameter6);
                return intArray.ToArray();
            }

            public void AssignByValue(
                int parameter1,
                int parameter2,
                int parameter3,
                int parameter4,
                int parameter5,
                int parameter6
                )

            {
                this.parameter1 = parameter1;
                this.parameter2 = parameter2;
                this.parameter3 = parameter3;
                this.parameter4 = parameter4;
                this.parameter5 = parameter5;
                this.parameter6 = parameter6;
            }
        }
       
        //        public cParametersPace ParametersMAX30001Pace = new cParametersPace();
        public class cParametersTemp : cDeviceMethodParameters
        {
            public cParametersTemp(String className, String methodName, int deviceNumber) : base(className, methodName) { this.deviceNumber = deviceNumber; }
            public int sampleTime;  // seconds
            private int deviceNumber;
            public override void AssignByIntArray(int[] intArray)
            {
                int i = 0;
                sampleTime = intArray[i++];
            }

            public override int[] ToIntArray()
            {
                int i = 0;
                List<int> intArray = new List<int>();
                intArray.Add(sampleTime);
                return intArray.ToArray();
            }
        }
//        public cParametersTemp1 ParametersMAX31725_1 = new cParametersTemp1();

//        public cParametersTemp2 ParametersMAX31725_2 = new cParametersTemp2();

        public class cParametersPressure : cDeviceMethodParameters
        {
            public cParametersPressure(String className, String methodName) : base(className, methodName) { }
            public int sampleTime;  // seconds
            public override void AssignByIntArray(int[] intArray)
            {
                int i = 0;
                sampleTime = intArray[i++];
            }

            public override int[] ToIntArray()
            {
                int i = 0;
                List<int> intArray = new List<int>();
                intArray.Add(sampleTime);
                return intArray.ToArray();
            }
        }
//        public cParametersPressure ParametersBMP280 = new cParametersPressure();

        public class cParametersAccel : cDeviceMethodParameters
        {
            public cParametersAccel(String className, String methodName) : base(className, methodName) { fifoDepth = 1; }
            public int sampleRate;  // Hz
            public int fifoDepth; 
            public override void AssignByIntArray(int[] intArray)
            {
                int i = 0;
                sampleRate = intArray[i++];
                fifoDepth = intArray[i++];
            }

            public override int[] ToIntArray()
            {
                int i = 0;
                List<int> intArray = new List<int>();
                intArray.Add(sampleRate);
                intArray.Add(fifoDepth);
                return intArray.ToArray();
            }
        }
//        public cParametersAccel ParametersLIS2DH = new cParametersAccel();

        public class cParameterOpticalSpO2 : cDeviceMethodParameters
        {
            public cParameterOpticalSpO2(String className, String methodName) : base(className, methodName) { }
            public int fifo_waterlevel_mark;
            public int sample_avg;
            public int sample_rate;
            public int pulse_width;
            public int red_led_current;
            public int ir_led_current;
            public override void AssignByIntArray(int[] intArray)
            {
                int i = 0;
                fifo_waterlevel_mark = intArray[i++];
                sample_avg = intArray[i++];
                sample_rate = intArray[i++];
                pulse_width = intArray[i++];
                red_led_current = intArray[i++];
                ir_led_current = intArray[i++];
            }

            public override int[] ToIntArray()
            {
                int i = 0;
                List<int> intArray = new List<int>();
                intArray.Add(fifo_waterlevel_mark);
                intArray.Add(sample_avg);
                intArray.Add(sample_rate);
                intArray.Add(pulse_width);
                intArray.Add(red_led_current);
                intArray.Add(ir_led_current);
                return intArray.ToArray();
            }
        }
//        public cParameterOpticalSpO2 ParameterMAX30101SpO2 = new cParameterOpticalSpO2();

        public class cParameterOpticalHR : cDeviceMethodParameters
        {
            public cParameterOpticalHR(String className, String methodName) : base(className, methodName) { }
            public int fifo_waterlevel_mark;
            public int sample_avg;
            public int sample_rate;
            public int pulse_width;
            public int red_led_current;
            public override void AssignByIntArray(int[] intArray)
            {
                int i = 0;
                fifo_waterlevel_mark = intArray[i++];
                sample_avg = intArray[i++];
                sample_rate = intArray[i++];
                pulse_width = intArray[i++];
                red_led_current = intArray[i++];
            }

            public override int[] ToIntArray()
            {
                int i = 0;
                List<int> intArray = new List<int>();
                intArray.Add(fifo_waterlevel_mark);
                intArray.Add(sample_avg);
                intArray.Add(sample_rate);
                intArray.Add(pulse_width);
                intArray.Add(red_led_current);
                return intArray.ToArray();
            }
        }
//        public cParameterOpticalHR ParameterMAX30101HR = new cParameterOpticalHR();

        public class cParameterOpticalMulti : cDeviceMethodParameters
        {
            public cParameterOpticalMulti(String className, String methodName) : base(className, methodName) { }
            public int fifo_waterlevel_mark;
            public int sample_avg;
            public int sample_rate;
            public int pulse_width;
            public int red_led_current;
            public int ir_led_current;
            public int green_led_current;
            public int slot_1;
            public int slot_2;
            public int slot_3;
            public int slot_4;
            public override void AssignByIntArray(int[] intArray)
            {
                int i = 0;
                fifo_waterlevel_mark = intArray[i++];
                sample_avg = intArray[i++];
                sample_rate = intArray[i++];
                pulse_width = intArray[i++];
                red_led_current = intArray[i++];
                ir_led_current = intArray[i++];
                green_led_current = intArray[i++];
                slot_1 = intArray[i++];
                slot_2 = intArray[i++];
                slot_3 = intArray[i++];
                slot_4 = intArray[i++];
            }

            public override int[] ToIntArray()
            {
                int i = 0;
                List<int> intArray = new List<int>();
                intArray.Add(fifo_waterlevel_mark);
                intArray.Add(sample_avg);
                intArray.Add(sample_rate);
                intArray.Add(pulse_width);
                intArray.Add(red_led_current);
                intArray.Add(ir_led_current);
                intArray.Add(green_led_current);
                intArray.Add(slot_1);
                intArray.Add(slot_2);
                intArray.Add(slot_3);
                intArray.Add(slot_4);
                return intArray.ToArray();
            }
        }

        public class cParametersRbiasFmstr : cDeviceMethodParameters
        {
            public cParametersRbiasFmstr(String className, String methodName) : base(className, methodName) { }

            public int en_rbias;
            public int rbias;
            public int rbiasp;
            public int rbiasn;
            public int fmstr;

            public override void AssignByIntArray(int[] intArray)
            {
                int i = 0;
                en_rbias = intArray[i++];
                rbias = intArray[i++];
                rbiasp = intArray[i++];
                rbiasn = intArray[i++];
                fmstr = intArray[i++];
            }

            public override int[] ToIntArray()
            {
                int i = 0;

                List<int> intArray = new List<int>();
                intArray.Add(en_rbias);
                intArray.Add(rbias);
                intArray.Add(rbiasp);
                intArray.Add(rbiasn);
                intArray.Add(fmstr);

                return intArray.ToArray();
            }

        }

        //PreCommand
        public class cRawRPCCommand : cDeviceMethodParameters
        {
           public String cmdString;
           public cRawRPCCommand(String className, String methodName) : base(className, methodName) { }
           public void Define(String str)
           {
               String inStr = str.Trim();
               if (inStr.CompareTo("null") == 0) str = "";
               cmdString = str;
           }
           public override void AssignByIntArray(int[] intArray)
            {
                throw new NotImplementedException();
            }

            public override int[] ToIntArray()
            {
                throw new NotImplementedException();
            }
            public override String GenerateRpcCommandString()
            {
                String str = cmdString;
                if (String.IsNullOrWhiteSpace(cmdString)) str = "null";
                String cmd = String.Format("\"{0}\"", str);
                //Console.WriteLine("cmd string  = '" + cmd + "'");
                //Console.WriteLine("cmd string length = " + cmd.Length.ToString());
                return cmd;
            }
        }
        public cParametersEcg MAX30001_Ecg = new cParametersEcg("MAX30001", "ECG_InitStart");
        public cParametersBioz MAX30001_Bioz = new cParametersBioz("MAX30001", "BIOZ_InitStart");
        public cParametersRtoR MAX30001_RtoR = new cParametersRtoR("MAX30001", "RtoR_InitStart");
        public cParametersPace MAX30001_Pace = new cParametersPace("MAX30001", "PACE_InitStart");
        public cParametersCal MAX30001_Cal = new cParametersCal("MAX30001", "CAL_InitStart");
        public cRawRPCCommand MAX30001_Rbias = new cRawRPCCommand("", "");
        public cParametersRbiasFmstr MAX30001_Rbias_Fmstr = new cParametersRbiasFmstr("MAX30001", "Rbias_FMSTR_Init");
        public cParametersTemp MAX31725_1 = new cParametersTemp("MAX30205_1", "InitStart", 1);
        public cParametersTemp MAX31725_2 = new cParametersTemp("MAX30205_2", "InitStart", 2);
        public cParametersPressure BMP280 = new cParametersPressure("BMP280", "InitStart");
        public cParametersAccel LIS2DH = new cParametersAccel("LIS2DH", "InitStart");
        public cParameterOpticalSpO2 MAX30101_SpO2 = new cParameterOpticalSpO2("MAX30101", "SpO2mode_InitStart");
        public cParameterOpticalHR MAX30101_HR = new cParameterOpticalHR("MAX30101", "HRmode_InitStart");
        public cParameterOpticalMulti MAX30101_Multi = new cParameterOpticalMulti("MAX30101", "Multimode_InitStart");
        public cRawRPCCommand PreCommand = new cRawRPCCommand("", "");
        public cRawRPCCommand PostCommand = new cRawRPCCommand("", "");

        const string CLASSNAME = "Logging";
        public DataLogging(RPCClient client)
            : base(client)
        {
            InitRpcCommandList();
        }
        /*
        public void StartLoggingUsb()
        {
            string reply;
            reply = Call(CLASSNAME, "StartLoggingUsb");
        }
        */
        private void InitStreaming()
        {
            client.pipeline.Discard();
            client.streaming.Init(client.pipeline);
            client.streaming.Start();
            //Call(CLASSNAME, "StreamTest");
            //CallNoReply(CLASSNAME, "StreamTest");
        }

        public void StartStreaming()
        {
            client.pipeline.Discard();
            InitStreaming();
            CallNoReply(CLASSNAME, "StartLoggingUsb");
            //Call(CLASSNAME, "StartTest");
        }

        public void StopStreaming()
        {
            StopStreaming(true);
        }

        public void StopStreaming(bool connected)
        {
            //if (connected)
                client.pipeline.SendSingleByte(' ');

            client.streaming.Stop();

            //if (connected)
            {
                client.pipeline.Discard();
                Thread.Sleep(500);
                client.pipeline.Discard();
            }
        }

        public void MissionRead()
        {
            int val;
            string reply;

            reply = Call(CLASSNAME, "ReadMission");
            reply = reply.Trim(new char[] { '\n', '\r', ' ', ':' });
            String[] cmds = reply.Split(new char[] { ':' });
            int i = 1;
            foreach (String str in cmds)
            {
                String cmd = str.Trim();
                if (!String.IsNullOrEmpty(cmd))
                {
                    Console.WriteLine(i.ToString() + ": " + cmd);
                    i++;
                }
            }
            //reply = Call(CLASSNAME, "ReadMission");
            //reply = "/MAX30001/ECG_InitStart 01 01 01 00 02 03 1F 00 02 00 01\r\n/BMP280/InitStart 01\r\n";

            // clear where it exists in mission flag
            foreach (cDeviceMethodParameters cmd in rpcCommandList)
            {
                cmd.ClearExistsInDeviceMission();
            }
            PreCommand.ClearExistsInDeviceMission();
            PostCommand.ClearExistsInDeviceMission();
            //reply[0]
            ParseRPCReadSequence(reply);
        }

        public string[] MissionStrings()
        {
            string reply;

            reply = Call(CLASSNAME, "ReadMission");
            reply = reply.Trim(new char[] { '\n', '\r', ' ', ':' });
            string[] cmds = reply.Split(new string[] { ": " }, StringSplitOptions.RemoveEmptyEntries);

            return cmds;
        }

        int debugMissionCmdCount;
        public void MissionStartDefinition()
        {
            string reply;
            reply = Call(CLASSNAME, "StartMissionDefine");
            debugMissionCmdCount = 0;
        }
        public void MissionAppend(cDeviceMethodParameters device)
        {
            String cmd;
            cmd = device.GenerateRpcCommandString();
            Call(CLASSNAME, "AppendMissionCmd", cmd);
            debugMissionCmdCount++;
            Console.WriteLine(debugMissionCmdCount.ToString() + ": " + cmd);
        }
        public void MissionAppend(String cmdStr)
        {
            Call(CLASSNAME, "AppendMissionCmd", "\"" + cmdStr + "\"");
            debugMissionCmdCount++;
            Console.WriteLine(debugMissionCmdCount.ToString() + ": " + cmdStr);
        }
        public void MissionWrite()
        {
            int val;
            string cmd;
            string reply;
            StringBuilder sbTest = new StringBuilder();

            reply = Call(CLASSNAME, "EndMissionDefine");
            reply = Call(CLASSNAME, "WriteMission");
             //reply = Call(CLASSNAME, "ReadReg", addr.ToString("X2"));
            //int.TryParse(reply, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val);
//            Console.WriteLine(sbTest.ToString());
        }

        // "/MAX30001/ECG_InitStart 01 01 01 00 02 03 1F 00 02 00 01/r/n/BMP280/InitStart 01 01 01 00 02 03 1F 00 02 00 01/r/n"
        private void ParseRPCReadSequence(String cmds)
        {
            int count = 0;
            cmds = cmds.Trim(new char[] { '\n', '\r', ' ', ':' });
            String[] cmdStrings = cmds.Split(new char[] { ':' });
            int lastCount = cmdStrings.Length - 1;
            foreach (String cmd in cmdStrings)
            {
                if (count == 0)
                {
                    PreCommand.Define(cmd);
                    PreCommand.existsInDeviceMission = true;
                }
                else
                    if (count == lastCount)
                    {
                        PostCommand.Define(cmd);
                        PostCommand.existsInDeviceMission = true;
                    }
                    else
                        ProcessRPCCmd(cmd);
                count++;
            }
        }

        List<cDeviceMethodParameters> rpcCommandList = new List<cDeviceMethodParameters>();

        private void InitRpcCommandList()
        {
            rpcCommandList.Add(MAX30001_Ecg);
            rpcCommandList.Add(MAX30001_Bioz);
            rpcCommandList.Add(MAX30001_RtoR);
            rpcCommandList.Add(MAX30001_Pace);
            rpcCommandList.Add(MAX30001_Cal);
            rpcCommandList.Add(MAX31725_1);
            rpcCommandList.Add(MAX31725_2);
            rpcCommandList.Add(BMP280);
            rpcCommandList.Add(LIS2DH);
            rpcCommandList.Add(MAX30101_SpO2);
            rpcCommandList.Add(MAX30101_HR);
            rpcCommandList.Add(MAX30101_Multi);
            rpcCommandList.Add(MAX30001_Rbias_Fmstr);
        }

        private void ProcessRPCCmd(String str)
        {
            if (String.IsNullOrEmpty(str)) return;
            String trimmed = str.Trim(new char[] { '\r', '\n', ' ' });
            if (String.IsNullOrEmpty(trimmed)) return;
            if (trimmed[0] != '/') return;
            String trimmed2 = trimmed.Trim(new char[] { '\r', '\n', '/', ' ' });
            String[] parts = trimmed2.Split(new char[] { '/' });
            String className = parts[0];
            String methodNameParameters = parts[1];
            String methodName = methodNameParameters.Substring(0,methodNameParameters.IndexOf(' '));
            String parameters = methodNameParameters.Substring(methodNameParameters.IndexOf(' ')).Trim();
            foreach (cDeviceMethodParameters cmd in rpcCommandList)
            {
                if (cmd.AssignIfMatch(className, methodName, parameters) == true) break;
            }
        }

        private int[] ParseHexString(String hexStr)
        {
            int val;
            List<int> intList = new List<int>();
            String[] strings = hexStr.Split(new char[] { ' ' });
            foreach (String str in strings)
            {
                if (int.TryParse(str, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val))
                {
                    intList.Add(val);
                }
                else
                {
                    throw new Exception(String.Format("Error In hex string \"{0}\" in \"{1}\"", str, hexStr));
                }
            }
            return intList.ToArray();
        }

        public void EraseMission()
        {
            int val;
            string cmd;
            string reply;

            reply = Call(CLASSNAME, "EraseMission");
        }

        public void TestMission()
        {
            int val;
            string cmd;
            string reply;

            reply = Call(CLASSNAME, "TestStartMission");
        }

        public void TestWriteLog()
        {
            throw new NotImplementedException();
        }

        public void TestReadLog()
        {
            throw new NotImplementedException();
        }

        public void TestBulkErase()
        {
            throw new NotImplementedException();
        }

        public void TestLogSectorsErase()
        {
            throw new NotImplementedException();
        }

        public string ReadPageToString(int page, out bool allOnes)
        {
            String returnStr = "";
            returnStr = CallBinary("S25FS512", "ReadPagesBinary", out allOnes, new String[] { page.ToString("X2"), page.ToString("X2") });
            return returnStr;
        }

        public void EraseWrittenSectors()
        {
            int val;
            string cmd;
            string reply;

            reply = Call(CLASSNAME, "EraseWrittenSectors");
        }
    }

    public abstract class cDeviceMethodParameters 
    {
        public String className;
        public String methodName;
        public abstract void AssignByIntArray(int[] intArray);
        public abstract int[] ToIntArray();
        public bool existsInDeviceMission;
        public bool IsExistsInDeviceMission()
        {
            return existsInDeviceMission;
        }
        public void ClearExistsInDeviceMission()
        {
            existsInDeviceMission = false;
        }
        public String ParametersToString()
        {
            StringBuilder sb = new StringBuilder();
            int[] intArray = ToIntArray();
            foreach (int val in intArray)
            {
                sb.Append(val.ToString("X2") + " ");
            }
            return sb.ToString().Trim(new char[] { ' ', ',' });
        }
        public virtual String GenerateRpcCommandString()
        {
            String cmd = String.Format("\"/{0}/{1} {2}\"", className, methodName, ParametersToString());
            //Console.WriteLine("cmd string  = '" + cmd + "'");
            //Console.WriteLine("cmd string length = " + cmd.Length.ToString());
            return cmd;
        }
        public cDeviceMethodParameters(String className, String methodName)
            {
                existsInDeviceMission = false;
                this.className = className;
                this.methodName = methodName;
            }
        public bool AssignIfMatch(String className, String methodName, String parameterStr)
        {
            bool match = false;
            if (this.className.Equals(className) && this.methodName.Equals(methodName))
            {
                match = true;
                existsInDeviceMission = true;
                AssignByIntArray(ParseHexString(parameterStr));
            }
            return match;
        }
        private int[] ParseHexString(String hexStr)
        {
            int val;
            List<int> intList = new List<int>();
            String[] strings = hexStr.Split(new char[] { ' ' });
            foreach (String str in strings)
            {
                if (int.TryParse(str, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val))
                {
                    intList.Add(val);
                }
                else
                {
                    throw new Exception(String.Format("Error In hex string \"{0}\" in \"{1}\"", str, hexStr));
                }
            }
            return intList.ToArray();
        }
    }
}
