Распиши эту цитату: "Алгоритмы для оценки физиологического и психофизиологического состояний пилота слишком упрощены и могут не учитывать все необходимые параметры, что снижает надёжность получаемых метрик."




Вот код:
using Newtonsoft.Json;
using System;
using WebSocketSharp;
using System.Threading;
using RingBuffer;
using System.Collections;
using DataType.ExternalSystems.Psy;
using Newtonsoft.Json.Linq;

namespace ClassLibBRD
{
    public class HW_interface
    {

        public void Init()
        {
            // m_MainModel = new MainModel();
            HW_interface.Init();
        }

        public static void Execute(ref PilotMetrics outputs)
        {
            HW_interface.GetPilotState(ref outputs);
            HW_interface.GetBILast(ref outputs);
            HW_interface.GetHRLast(ref outputs);
            HW_interface.GetEEGLast(ref outputs);
            //HW_interface.BufferTransfer(ref outputs);

            // Simulate method calls
            HW_interface.GetPilotPhysiologicalState(ref outputs);
            HW_interface.GetPilotPsychophysiologicalState(ref outputs);

            HW_interface.IsPilotInCabin(ref outputs);

            HW_interface.IsPilotingIncorrectly(ref outputs);
            HW_interface.GetEEGFrequencyInterval(ref outputs);

            HW_interface.GetCVSControlCenterState(ref outputs);
            HW_interface.GetAlertnessLevel(ref outputs);
            //HW_interface.GetCognitiveLoadCapacity(ref outputs);
            HW_interface.GetWithWideEyesClosed(ref outputs);

            //HW_interface.GetIncorrectManeuverType(ref outputs);
            //HW_interface.IsBaevskyIndexInformative(ref outputs);
            HW_interface.GetLastCardiacCycleLength(ref outputs);
            HW_interface.GetEEGSpectrumPower(ref outputs);
            // Так и не разобрались, нужен фурье или нет
            //HW_interface.GetFourierResultsIntervalogram(ref outputs);
        }

        private static void GetWithWideEyesClosed(ref PilotMetrics outputs)
        {
            outputs.IsEyesClosed = bs.gdalrt.WithWideEyesClosed;
        }

        private static void GetPilotPhysiologicalState(ref PilotMetrics outputs)
        {
            /*
 * obtain values of requested params from stored value ring buffers
 * **/
            PState pst = PSateByRule();
            outputs.PhysiologicalState = pst.PilotPhysiologicalState;
        } // Implement fetching logic

        private static void GetPilotPsychophysiologicalState(ref PilotMetrics outputs)
        {
            PState pst = PSateByRule();
            outputs.PsychophysiologicalState = pst.PilotPsychophysiologicalState;
        } // Implement fetching logic

        private static void IsPilotInCabin(ref PilotMetrics outputs)
        {
            //WARNING: HARDCODE
            outputs.IsNotInCabin = false; // Можно добавить из ГДА bs.gdalrt.NotInCabin

        } // Implement fetching logic

        private static void IsPilotingIncorrectly(ref PilotMetrics outputs)
        {
            //outputs.PilotOutputs.PilotingIsNotCorrectly = false;
        } // Implement fetching logic

        private static void GetEEGFrequencyInterval(ref PilotMetrics outputs)
        {
            outputs.EEGFrequencyInterval = (sbyte)EEGPoolingRate;
        } // Implement fetching logic

        private static void GetCVSControlCenterState(ref PilotMetrics outputs)
        {
            //WARNING: HARDCODE
            outputs.CardiovascularCenterState = 4;
        } // Implement fetching logic

        private static void GetAlertnessLevel(ref PilotMetrics outputs)
        {
            //WARNING: HARDCODE Перенесли с ГДА, должна вычисляться "по-нормальному"
            outputs.AlertnessLevel = bs.gdalrt.Level;
            

        } // Implement fetching logic

        private static void GetCognitiveLoadCapacity(ref PilotMetrics outputs)
        {
            //outputs.PilotOutputs.CognitiveLoadCapacity = 0.95;
        }  // Implement fetching logic
        private static void GetIncorrectManeuverType(ref PilotMetrics outputs)
        {
            //outputs.PilotOutputs.IncorrectManeuverType = "TakeOff";
        } // Implement fetching logic

        private static void IsBaevskyIndexInformative(ref PilotMetrics outputs)
        {
            //outputs.ECGOutputs.isIndexInformative = BIInformative;

        } // Implement fetching logic
        private static void GetLastCardiacCycleLength(ref PilotMetrics outputs)
        {
            outputs.RR = (ushort)bs.HRDataBuffer[bs.GetHRDataBufferLast()].data.RR;
        } 
        // Implement fetching logic
        private static void GetEEGSpectrumPower(ref PilotMetrics outputs)
        {
            outputs.SpectrumPower = bs.EEGDataBuffer[bs.GetEEGDataBufferLast()].data;
        } // Implement fetching logic
        private static void GetFourierResultsIntervalogram(ref PilotMetrics outputs)
        {
            //outputs.EEGOutputs.FourierResultsIntervalogram = bs.EEGPDGBuffer[bs.GetEEGPDGBufferLast()];
        } // Implement fetching logic

        public static void Init(String COMID = "COM10", int portWS = 1200, int portGDA = 0000)
        {
            /*
             * Initialize windows process from exe path ControllServerPath and pass
             * arguments to it input COMID is EEG reciever COM port alias e/g/ COM8 where 8 is number of
             * serrial port which binded to reciver hardware, and portWS is web-socket port number
             * which Initialized process would use to recive comands from DLL and return data collected with hardware
            */
            InitHWControllServer(COMID, portWS, portGDA);
            /*
             * AwaitSocket is timer which used to be sure that server process is ready to recieve
             * input connections, there is no any direct logic to ensure that connection is possible
             * probably right non lazy way is to recall SocketTimerCallback while there are no
             * exceptions in connection method, but here we just wait 5 seconds then call for SocketTimerCallback
             * which init client socet connection from DLL then dispose Timer
             */
            Thread.Sleep(5000);
            BindHWControlServerSocket();
            //AwaitSocket = new Timer(SocketTimerCallback, null, 5000, 5000);
            /*
             * only 2 verbocity levels is possible
             *          0 - means no debug messages printed
             *          1 - means all debug messages printed
             */
            setVerbocity(0);
            /*
             * EEG pointsappears in com port buffer when ADC triggers transfer from mcu registers to
             * mcu serrial port. DLL reads this values on onThreadTimerOverflow with regular interval
             * defined with EEGPoolingRate. subscribeEEGData - initialize and start this timer
             */
            subscribeEEGData();
            subscribGDA();
            /*
             * ConnectBLE, make HWControl server advertising for HR monitor mac if mac adress found,
             * HWControl server discorev services and characteristics of corresponding device which 
             * is necessary to represent cardiocycle info
             */
            ConnectBLE();
        }

        const String ControllServerPath = "serial-plot-server.exe";
        const String address = "localhost";
        const int BILagTime = 60 * 4 * 1000;
        static int VERBOCITY = 1;
        static int port = 1200;
        static int EEGPoolingRate = 10;

        static bool BIInformative = false;
        static int BIITypeCounter = 0;

        static WebSocket ws;
        static Timer AwaitSocket;
        static Timer EEGPoolTimer;

        public static BuferState bs = new BuferState();


        public class EEGPoint
        {
#pragma warning disable CS0649 // Полю "HW_interface.EEGPoint.evt" нигде не присваивается значение, поэтому оно всегда будет иметь значение по умолчанию null.
            public String evt;
#pragma warning restore CS0649 // Полю "HW_interface.EEGPoint.evt" нигде не присваивается значение, поэтому оно всегда будет иметь значение по умолчанию null.
#pragma warning disable CS0649 // Полю "HW_interface.EEGPoint.data" нигде не присваивается значение, поэтому оно всегда будет иметь значение по умолчанию 0.
            public Int16 data;
#pragma warning restore CS0649 // Полю "HW_interface.EEGPoint.data" нигде не присваивается значение, поэтому оно всегда будет иметь значение по умолчанию 0.
        }
        public class PDGVal
        {
#pragma warning disable CS0649 // Полю "HW_interface.PDGVal.evt" нигде не присваивается значение, поэтому оно всегда будет иметь значение по умолчанию null.
            public String evt;
#pragma warning restore CS0649 // Полю "HW_interface.PDGVal.evt" нигде не присваивается значение, поэтому оно всегда будет иметь значение по умолчанию null.
            public double[] data = new double[255];
        }
        public class BCIVal
        {
            public String evt;
            public double[] data = new double[5];

        }

        public class HRD
        {
            public bool isHRu16;
            public bool isSensorPlacementControlSystemPresented;
            public bool isSensorCorrectlyPlaced;
            public bool isRRDataAvailable;
            public double CI;
            public Int16 HR;
            public Int16 RR;
            public Int16 Battery;
        }
        public class HRVal
        {
            public String evt;
            public HRD data;

        }

        public class GDALRT 
{
    [JsonProperty("level")]
    public byte Level { get; set; }

    [JsonProperty("isValid")]
    public bool IsValid { get; set; }

    [JsonProperty("notInCabin")]
    public bool NotInCabin { get; set; }

    [JsonProperty("withWideEyesClosed")]
    public bool WithWideEyesClosed { get; set; }
}

        public class BuferState
        {
            static int bsize = 2048;
            int EEGPointBufferLast = 0;
            int HRPointBufferLast = 0;
            int EEGDataBufferLast = 0;
            int HRDataBufferLast = 0;
            int EEGPDGBufferLast = 0;

            public GDALRT gdalrt = new GDALRT();


            public int[] EEGPointBuffer = new int[bsize];
            public RingBuffer.RingBuffer<int> EEGPointBufferRing = new RingBuffer.RingBuffer<int>(bsize, true);

            public int[] HRPointBuffer = new int[bsize];
            public RingBuffer.RingBuffer<int> HRPointBufferRing = new RingBuffer.RingBuffer<int>(bsize, true);

            public double[][] EEGPDGBuffer = new double[bsize][];
            public RingBuffer.RingBuffer<double[]> EEGPDGBufferRing = new RingBuffer.RingBuffer<double[]>(bsize, true);

            public HW_interface.BCIVal[] EEGDataBuffer = new HW_interface.BCIVal[bsize];
            public RingBuffer.RingBuffer<HW_interface.BCIVal> EEGDataBufferRing = new RingBuffer.RingBuffer<HW_interface.BCIVal>(bsize, true);

            public HW_interface.HRVal[] HRDataBuffer = new HW_interface.HRVal[bsize];
            public RingBuffer.RingBuffer<HW_interface.HRVal> HRDataBufferRing = new RingBuffer.RingBuffer<HW_interface.HRVal>(bsize, true);



            public int GetEEGPointBufferLast()
            {
                // int t = EEGPointBufferLast;
                // EEGPointBufferLast = (EEGPointBufferLast + 1) % bsize;

                return EEGPointBufferRing.Count - 1;
            }
            public void SetEEGPointBufferLast(int value)
            {
                EEGPointBufferLast = value;
            }

            public int GetHRPointBufferLast()
            {
                //int t = HRPointBufferLast;
                //HRPointBufferLast = (HRPointBufferLast + 1) % bsize;
                return HRPointBufferRing.Count - 1;
            }
            public void SetHRPointBufferLast(int value)
            {
                if (!BIInformative)
                {
                    BIITypeCounter += value;
                    if (BIITypeCounter >= BILagTime)
                    {
                        BIInformative = true;
                    }
                }
                HRPointBufferLast = value;
            }

            public int GetEEGDataBufferLast()
            {
                // int t = EEGDataBufferLast;
                // EEGDataBufferLast = (EEGDataBufferLast + 1) % bsize;
                return EEGDataBufferRing.Count - 1;
            }
            public void SetEEGDataBufferLast(int value)
            {
                EEGDataBufferLast = value;
            }

            public int GetHRDataBufferLast()
            {
                // int t = HRDataBufferLast;
                // HRDataBufferLast = (HRDataBufferLast + 1) % bsize;
                return HRDataBufferRing.Count - 1;
            }
            public void SetHRDataBufferLast(int value)
            {
                HRDataBufferLast = value;
            }
            public int GetEEGPDGBufferLast()
            {
                // int t = HRDataBufferLast;
                // HRDataBufferLast = (HRDataBufferLast + 1) % bsize;
                return EEGPDGBufferRing.Count - 1;
            }
            public void SetEEGPDGBufferLast(int value)
            {
                EEGPDGBufferLast = value;
            }
        }

        private class PState
        {
            public byte PilotPhysiologicalState;
            public byte PilotPsychophysiologicalState;
        }


        public static void BindHWControlServerSocket()
        {
            ws = new WebSocket($"ws://{address}:{port.ToString()}");
            ws.OnMessage += Ws_OnMessage;
            ws.OnClose += Ws_OnClose;
            ws.OnOpen += Ws_OnOpen;
            ws.Connect();
        }
        public static System.Diagnostics.Process InitHWControllServer(String COMID = "COM10", int portWS = 1200, int portGDA = 1111)
        {
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo.FileName = ControllServerPath;
            //p.StartInfo.Arguments = COMID + " " + Convert.ToString(portWS) + " OFF " + Convert.ToString(portGDA);
            p.StartInfo.Arguments = "COM10 " + Convert.ToString(portWS) + " OFF " + Convert.ToString(portGDA);
            Console.WriteLine(p.StartInfo.FileName);
            Console.WriteLine(p.StartInfo.Arguments);
            p.Start();
            return p;
        }

        private static bool RingbufferReady(RingBuffer.RingBuffer<IEnumerable> rb)
        {
            return rb.Count > 0 ? true : false;
        }

        private static double BCIFastEstimate()
        {
            int eegBSize = bs.GetEEGDataBufferLast();
            double mavg = 0;
            for (int i = 0; i < eegBSize; i++)
            {
                double[] bseg = bs.EEGDataBuffer[i].data;
                mavg += bseg[2] / (bseg[0] + bseg[1] + bseg[3]);
            }
            return mavg / eegBSize;
        }

/*        private static void BufferTransfer(ref PilotMetrics outputs)
        {

            outputs.DBGOutputs.HRPointBuffer = bs.HRPointBuffer;
            outputs.DBGOutputs.HRDataBuffer = bs.HRDataBuffer;
            outputs.DBGOutputs.EEGPointBuffer = bs.EEGPointBuffer;
            outputs.DBGOutputs.EEGDataBuffer = bs.EEGDataBuffer;

        }*/

        private static String FormatDoubleOutput(double[] a)
        {
            String p = "";
            for (int i = 0; i < a.Length - 1; i++)
            {
                p += (a[i].ToString() + " ");
            }
            return "[ " + p + " ]";
        }

        private static PState PSateByRule()
        {

            PState pst = new PState();

            pst.PilotPhysiologicalState = 0;
            pst.PilotPsychophysiologicalState = 0;

            int eegBSize = bs.GetEEGDataBufferLast();
            int hrBSize = bs.GetHRDataBufferLast();

            int hrLowCounter = 0;
            int hrHighCounter = 0;
            int hrOverflowCounter = 0;
            int eegCounter = 0;
            double alpProp = 0;

            double[] bseg;
            HW_interface.HRD bsdb;

            /*
             * Get quantity of eeg data entrtyes where Alpha rythm is dominant
             */
            for (int i = 0; i < eegBSize; i++)
            {
                bseg = bs.EEGDataBuffer[i].data;
                if (getMaxIndex(bseg) == 2)
                {
                    eegCounter++;
                }
            }


            for (int i = 0; i < hrBSize; i++)
            {
                bsdb = bs.HRDataBuffer[i].data;
                if (bsdb.isSensorCorrectlyPlaced)
                {
                    /*
                     * Get count of cardiocycles which corresponds to lesser then 40 bpm heart rate
                     */
                    if ((bsdb.HR <= 40))
                    {
                        hrLowCounter++;
                    }
                    /*
                     * From stored entries get count items with HRV stress index from 300 to 500 (extreamly high value)
                     */
                    if ((bsdb.CI < 500) && (bsdb.CI > 300))
                    {
                        hrHighCounter++;
                    }
                    /*
                     * From stored entries get count items with HRV stress index is over 500 (unbelivebaly high value)
                     */
                    if ((bsdb.CI > 500))
                    {
                        hrOverflowCounter++;
                    }
                }

            }

            /*
             * if heartbeat is deadly low in 30+ estimates then pilot is probably dead or too close to death to manage 
             * cocpit dutyes**/
            if (hrLowCounter >= 30)
            {
                pst.PilotPhysiologicalState = 1;
            }
            /*
             * if stress index is valuebly higher then normal/expected in 300+ estimates then pilot is extreamly 
             * close to NOP PilotPsychophysiologicalState **/
            if (hrHighCounter > 300)
            {
                pst.PilotPsychophysiologicalState = 1;
            }
            /*
             * if stress index is FUCKING UNBELIVEBLY higher then normal/expected in more than 300 estimates
             * then pilot is for sure IN NOP PilotPsychophysiologicalState **/
            if (hrOverflowCounter > 300)
            {

                pst.PilotPsychophysiologicalState = 2;
            }
            /*
             * if eegBuffer is filled with 256+ estimates then complex estimate of alertness level may be obtained with 
             * next algorythm
             * **/
            if (eegBSize > 256)
            {
                alpProp = eegCounter / eegBSize;
                if ((pst.PilotPhysiologicalState != 1) && (eegBSize > 1000))
                {
                    if ((0.7 > alpProp) && (alpProp > 0.5))
                    {
                        pst.PilotPhysiologicalState = 2;
                    }
                    else if (alpProp > 0.7)
                    {
                        pst.PilotPhysiologicalState = 3;
                    }
                }
            }

            return pst;
        }

        public static void GetPilotState(ref PilotMetrics outputs)
        {
            /*
             * obtain values of requested params from stored value ring buffers
             * **/
            PState pst = PSateByRule();

            /*
             * return given values by referenced structures of caller process
             * **/
            outputs.PhysiologicalState = pst.PilotPhysiologicalState;
            outputs.PsychophysiologicalState = pst.PilotPsychophysiologicalState;
        }
        public static void GetBILast(ref PilotMetrics outputs) {
            if (bs.HRDataBufferRing.Count > 0)
            {
                outputs.SI = (ushort)bs.HRDataBuffer[bs.GetHRDataBufferLast()].data.CI;
            }
            else
            {
                outputs.SI = -1;
            }
        }
        public static void GetHRLast(ref PilotMetrics outputs)
        {
            // if (RingbufferReady(bs.HRDataBufferRing))
            if (bs.HRPointBufferRing.Count > 0)
            {
                outputs.HR = bs.HRPointBuffer[bs.GetHRPointBufferLast()];

            }
            else
            {
                outputs.HR = -1;
            }
        }

        public static void GetEEGPDGLast(ref PilotMetrics outputs)
        {
            // if (RingbufferReady(bs.HRDataBufferRing))
            if (bs.EEGPDGBufferRing.Count > 0)
            {
                outputs.SpectrumPower = bs.EEGPDGBuffer[bs.GetEEGPDGBufferLast()];

            }
            else
            {
                outputs.SpectrumPower = (new double[255]);
            }
        }

        public static void GetEEGLast(ref PilotMetrics outputs)
        {
            //if (RingbufferReady(bs.HRDataBufferRing))

                if (bs.EEGDataBufferRing.Count > 0)
                {
                    outputs.EEGLastPoint = (float)BCIFastEstimate();
                }
                else
                {
                    outputs.EEGLastPoint = -1;

                }
            //outputs.ECGOutputs.ECGLastPoint = 90;
        }
        public static void GetGDALevelAlertness(ref PilotMetrics outputs)
        {
            //if (RingbufferReady(bs.HRDataBufferRing))
            outputs.IsGDAValid = bs.gdalrt.IsValid;
            //outputs.GDALevelAlertness = bs.gdalrt.Level;
            outputs.IsNotInCabin = bs.gdalrt.NotInCabin;
            outputs.IsEyesClosed = bs.gdalrt.WithWideEyesClosed;

        }
        public static void setVerbocity(int v = 1)
        {
            VERBOCITY = v > 0 ? 1 : 0;
        }
        public static int getVerbocity()
        {
            return VERBOCITY;
        }
        public static void logStart(String loglabel)
        {
            if (DataSocketReady())
            {
                ws.Send("{\"evt\":\"new_rec\",\"data\":{ \"label\":\"" + loglabel + "\"}}");
            }
        }


        public static bool DataSocketReady()
        {
            return (ws != null) && (ws.ReadyState == WebSocketState.Open);
        }
        public static void ConnectBLE()
        {
            if (DataSocketReady())
            {
                ws.Send("{\"evt\":\"connectDevice\",\"data\":{}}");
            }
        }
        public static void subscribeEEGData()
        {
            EEGPoolTimer = new Timer(onThreadTimerOverflow, null, 0, EEGPoolingRate);
        }
        public static void unSubscribeEEGData()
        {
            EEGPoolTimer.Dispose();
        }

        private static void tell(string msg)
        {
            if (VERBOCITY == 0) { return; }
            if (VERBOCITY == 1)
            {
                Console.WriteLine(msg);
            }
        }
        private static void subscribeFFT()
        {
            if (DataSocketReady())
            {
                ws.Send("{\"evt\":\"subscribe_fft\",\"data\":{}}");
            }
        }
        private static void subscribGDA()
        {
            if (DataSocketReady())
            {
                ws.Send("{\"evt\":\"subscribe_gda\",\"data\":{}}");
            }
        }
        private static void readPoint()
        {
            if (DataSocketReady())
            {
                ws.Send("{\"evt\":\"point\",\"data\":{ }}");
            }
        }
        private static int getMaxIndex(double[] bseg)
        {
            int mi = 0; double mv = bseg[0];

            for (int i = 0; i < bseg.GetLength(0) - 1; i++)
            {
                if (mv < bseg[i])
                {
                    mi = i;
                }
            }
            return mi;
        }

        private static void onThreadTimerOverflow(Object o)
        {
            readPoint();
        }
        private static void SocketTimerCallback(Object o)
        {
            BindHWControlServerSocket();
            AwaitSocket.Dispose();
        }
        private static void Ws_OnOpen(object sender, EventArgs e)
        {
            tell("EEG capturing device data socket ready!");

        }
        private static void Ws_OnClose(object sender, CloseEventArgs e)
        {
            tell("Passtrough data socket was closed....: ");
        }
        private static void Ws_OnMessage(object sender, MessageEventArgs e)
        {
            // tell("Received from the server: " + e.Data);
            try
            {

                //if (e.Data.Contains("GDALRT"))
                //{
                //    GDALRT gdalrt = JsonConvert.DeserializeObject<GDALRT>(e.Data);
                //    bs.gdalrt=gdalrt;
                //}

                if (e.Data.Contains("GDALRT"))
                {
                    JObject json = JObject.Parse(e.Data);
                    JToken dataToken = json["data"];

                    if (dataToken != null)
                    {
                        bs.gdalrt = dataToken.ToObject<GDALRT>();
                    }
                }

                //if (e.Data.Contains("BCI"))
                //{
                //    BCIVal bci = JsonConvert.DeserializeObject<BCIVal>(e.Data);
                //    bs.EEGDataBufferRing.Add(bci);
                //    bs.EEGDataBufferRing.CopyTo(bs.EEGDataBuffer, 0);

                //    tell("Got estimates: " + FormatDoubleOutput(bci.data));
                //}

                if (e.Data.Contains("BCI"))
                {
                    HW_interface.BCIVal bci = JsonConvert.DeserializeObject<HW_interface.BCIVal>(e.Data);
                    bs.EEGDataBufferRing.Add(bci);
                    bs.EEGDataBufferRing.CopyTo(bs.EEGDataBuffer, 0);

                    tell("Got estimates: " + FormatDoubleOutput(bci.data));
                }

                if (e.Data.Contains("point"))
                {
                    EEGPoint pos = JsonConvert.DeserializeObject<EEGPoint>(e.Data);
                    bs.EEGPointBufferRing.Add(pos.data);
                    bs.EEGPointBufferRing.CopyTo(bs.EEGPointBuffer, 0);
                    tell("Got point data: " + pos.data);
                }
                if (e.Data.Contains("PDG"))
                {
                    PDGVal pdg = JsonConvert.DeserializeObject<PDGVal>(e.Data);
                    bs.EEGPDGBufferRing.Add(pdg.data);
                    bs.EEGPDGBufferRing.CopyTo(bs.EEGPDGBuffer, 0);

                    tell("Got estimates: " + FormatDoubleOutput(pdg.data));

                    // tell("Got spectral: " + FormatDoubleOutput(pdg.data));
                }
                if (e.Data.Contains("hrm_data"))
                {
                    HW_interface.HRVal hr = JsonConvert.DeserializeObject<HW_interface.HRVal>(e.Data);

                    bs.HRDataBufferRing.Add(hr);
                    bs.HRDataBufferRing.CopyTo(bs.HRDataBuffer, 0);

                    bs.HRPointBufferRing.Add(hr.data.HR);
                    bs.HRPointBufferRing.CopyTo(bs.HRPointBuffer, 0);


                    tell("Got HR data: " + "[ HR=" + hr.data.HR + " CI:" + hr.data.RR + " bi:" + hr.data.CI + "..");

                    // Console.WriteLine("Got HR monitor battery info: " + "[" + e.Data + "..");
                }
                if (e.Data.Contains("bat_data"))
                {
                    // PDGVal pdg = JsonConvert.DeserializeObject<PDGVal>(e.Data);
                    tell("Got HR monitor battery info: " + "[" + e.Data + "..");
                    // Console.WriteLine("Got HR monitor battery info: " + "[" + e.Data + "..");
                }
                if (e.Data.Contains("adv_state"))
                {
                    // PDGVal pdg = JsonConvert.DeserializeObject<PDGVal>(e.Data);
                    // tell("Got HR monitor battery info: " + "[" + e.Data + "..");
                    Console.WriteLine("BLE adversier state: " + "[" + e.Data + "..");
                }

            }
#pragma warning disable CS0168 // Переменная "ex" объявлена, но ни разу не использована.
            catch (Exception ex)
#pragma warning restore CS0168 // Переменная "ex" объявлена, но ни разу не использована.
            {
                tell("I don't know what to do with \"" + e.Data + "\"");
            }

        }


    }


}