none
蓝牙接入

    问题

  • 公司安排我做一个数据采集的软件,主要功能是以蓝牙方式从医疗设备(除颤监护仪)获取病人的生理状况到PC上,该设备厂商提供有.net开发的SDK,比较要命的是该SDK包基本没有任何注释;但是,本人是一枚iOS开发者,对于.net完全属于小白,对蓝牙更是一无所知。目前,本人遇到的主要问题是:医疗设备和PC进行蓝牙配对后,每次传输数据的时候都要像打电话一样进行拨号(我只晓得这是蓝牙里面的DUN),可是我根本就不知道该拨打什么号码,不知道PC端应该做什么;通过查看SDK,只找到了一个调制解调器模块的接口,可以设置串口、波特率、停止位和数据位等等。

    对于蓝牙这一块我目前写的代码如下:

     #region Class ZOLLTransfer
            public class ZOLLTransfer : Object
            {
                #region Private
                private SerialPortDriver _serialPortDriver;
                private ZOLLModemReceiver _modemReceiver;
                private ZModemParser _modemParser;
                #endregion
    
                #region Serial port driver
                public SerialPortDriver SerialPortDriver
                {
                    get
                    {
                        if (_serialPortDriver == null)
                        {
                            _serialPortDriver = new SerialPortDriver();
    
                            _serialPortDriver.DataSent += _serialPortDriver_DataSent;
                            _serialPortDriver.ErrorEvent += _serialPortDriver_ErrorEvent;
                            _serialPortDriver.DataReceived += _serialPortDriver_DataReceived;
                            _serialPortDriver.PortParametersChanged += _serialPortDriver_PortParametersChanged;
                        }
                        return _serialPortDriver;
                    }
                }
    
                void _serialPortDriver_PortParametersChanged()
                {
                    MessageBox.Show(SerialPortDriver.PortName);
                }
    
                void _serialPortDriver_ErrorEvent(ByteStreamDriver.ErrorCode error)
                {
                    
                }
    
                void _serialPortDriver_DataSent(byte sent_byte)
                {
                  
                }
    
                void _serialPortDriver_DataReceived(byte received_byte)
                {
                    ModemParser.AddByte(received_byte);
                }
                #endregion
    
                #region Modem receiver
    
                private ZOLLModemReceiver ModemReceiver
                {
                    get
                    {
                        if (_modemReceiver == null)
                        {
                            _modemReceiver = new ZOLLModemReceiver();
    
                            _modemReceiver.LogOutput += _modemReceiver_LogOutput;
                            _modemReceiver.ErrorReport += _modemReceiver_ErrorReport;
                            _modemReceiver.FileReceived += _modemReceiver_FileReceived;
                            _modemReceiver.SendFrameHeader += _modemReceiver_SendFrameHeader;
                            _modemReceiver.FileReceiveProgress += _modemReceiver_FileReceiveProgress;
                            _modemReceiver.FileReceiveStarting += _modemReceiver_FileReceiveStarting;
                            _modemReceiver.FileReceiverStateChange += _modemReceiver_FileReceiverStateChange;
                        }
                        return _modemReceiver;
                    }
                }
    
                void _modemReceiver_SendFrameHeader(byte[] header)
                {
                    
                }
    
                void _modemReceiver_LogOutput(string log_entry)
                {
                    
                }
    
                void _modemReceiver_FileReceiveStarting(string path, uint file_size)
                {
                   
                }
    
                void _modemReceiver_FileReceiverStateChange(ZOLLModemReceiver.ReceiverState entered_state)
                {
                    
                }
    
                void _modemReceiver_FileReceiveProgress(uint bytes_received, uint file_size)
                {
                    
                }
    
                void _modemReceiver_FileReceived(ZOLLModemReceiver.TransferStats transfer_completed)
                {
                    var fileName = transfer_completed.FileName;
    
                }
    
                void _modemReceiver_ErrorReport(ZOLLModemReceiver.Error code, string message, int arg1, int arg2)
                {
                    
                }
                #endregion
    
                #region Modem parser
                private ZModemParser ModemParser
                {
                    get
                    {
                        if (_modemParser == null)
                        {
                            _modemParser = new ZModemParser();
    
                            _modemParser.DataBlockCRCError += _modemParser_DataBlockCRCError;
                            _modemParser.DataBlockReceived += _modemParser_DataBlockReceived;
                            _modemParser.FrameHeaderCRCError += _modemParser_FrameHeaderCRCError;
                            _modemParser.FrameHeaderReceived += _modemParser_FrameHeaderReceived;
                            _modemParser.AccumulationBufferReset += _modemParser_AccumulationBufferReset;
                        }
                        return _modemParser;
                    }
                }
    
                void _modemParser_AccumulationBufferReset(int discarded_byte_count)
                {
                    
                }
    
                void _modemParser_FrameHeaderReceived(FrameHeader header)
                {
                    ModemReceiver.FrameHeaderReceived(header);
                }
    
                void _modemParser_FrameHeaderCRCError(FrameHeader header)
                {
                    ModemReceiver.FrameHeaderError(header);
                }
    
                void _modemParser_DataBlockReceived(DataBlock block)
                {
                    ModemReceiver.DataBlockReceived(block);
                }
    
                void _modemParser_DataBlockCRCError(DataBlock block)
                {
                    ModemReceiver.DataBlockError(block);
                }
                #endregion
            }
            #endregion

    上面的代码中主要用到了三个SDK里面的类,分别是SerialPortDriver:

    namespace ZOLL.Communications.ZOLLModem
    {
        public class SerialPortDriver : ByteStreamDriver
        {
            public SerialPortDriver();
    
            public int BaudRate { get; set; }
            public int DataBits { get; set; }
            public DriverParity Parity { get; set; }
            public string PortName { get; set; }
            public override bool Run { get; set; }
            public float StopBits { get; set; }
    
            public override event ByteStreamDriver.DataReceivedHandler DataReceived;
            public override event ByteStreamDriver.DataSentHandler DataSent;
            public override event ByteStreamDriver.ErrorHandler ErrorEvent;
            public event SerialPortDriver.PortParametersChangedHandler PortParametersChanged;
    
            public override void Close();
            public static string[] EnumeratePorts();
            public override void Flush();
            public override void TransmitByte(byte send_byte);
            public override void TransmitBytes(byte[] send_bytes);
    
            public delegate void PortParametersChangedHandler();
        }
    }

    第二个类是ZModemParser:

    namespace ZOLL.Communications.ZOLLModem
    {
        public class ZModemParser
        {
            public ZModemParser();
    
            public ZModemParser.ParserControl RunState { get; set; }
    
            public event ZModemParser.AccumulationBufferResetHandler AccumulationBufferReset;
            public event ZModemParser.DataBlockCRCErrorHandler DataBlockCRCError;
            public event ZModemParser.DataBlockReceivedHandler DataBlockReceived;
            public event ZModemParser.FrameHeaderCRCErrorHandler FrameHeaderCRCError;
            public event ZModemParser.FrameHeaderReceivedHandler FrameHeaderReceived;
    
            public void AddByte(byte received_byte);
            public static byte[] GetGenericHexFrameHeader(ZModemParser.FrameType type, byte p0, byte p1, byte p2, byte p3);
            public static byte[] GetZACKHexFrameHeader(uint file_pos);
            public static byte[] GetZCanHeader();
            public static byte[] GetZChallengeHexFrameHeader(byte p0, byte p1, byte p2, byte p3);
            public static byte[] GetZFErrorHexFrameHeader();
            public static byte[] GetZFinHexFrameHeader(byte p0, byte p1, byte p2, byte p3);
            public static byte[] GetZNAKHexFrameHeader();
            public static byte[] GetZRInitHexFrameHeader(byte p0, byte p1, byte p2, byte p3);
            public static byte[] GetZRPosHexFrameHeader(uint file_pos);
            public static byte[] GetZSkipHexFrameHeader(byte p0, byte p1, byte p2, byte p3);
    
            public enum Constants
            {
                None = 0,
                ZDLE = 24,
                ZPAD = 42,
                ZBIN = 65,
                ZHEX = 66,
                ZBIN32 = 67,
                ZDLEE = 72,
            }
    
            public enum FrameEndType
            {
                None = 0,
                ZCRCE = 104,
                ZCRCG = 105,
                ZCRCQ = 106,
                ZCRCW = 107,
            }
    
            public enum FrameType
            {
                ZRQINIT = 0,
                ZRINIT = 1,
                ZSINIT = 2,
                ZACK = 3,
                ZFILE = 4,
                ZSKIP = 5,
                ZNAK = 6,
                ZABORT = 7,
                ZFIN = 8,
                ZRPOS = 9,
                ZDATA = 10,
                ZEOF = 11,
                ZFERR = 12,
                ZCRC = 13,
                ZCHALLENGE = 14,
                ZCOMPL = 15,
                ZCAN = 16,
                ZFREECNT = 17,
                ZCOMMAND = 18,
                ZSTDERR = 19,
                ZMAXFRAMETYPE = 20,
            }
    
            public enum ParserControl
            {
                Manual = 0,
                AutomaticReceiver = 1,
                AutomaticSender = 2,
            }
    
            public delegate void AccumulationBufferResetHandler(int discarded_byte_count);
    
            public delegate void DataBlockCRCErrorHandler(DataBlock block);
    
            public delegate void DataBlockReceivedHandler(DataBlock block);
    
            public delegate void FrameHeaderCRCErrorHandler(FrameHeader header);
    
            public delegate void FrameHeaderReceivedHandler(FrameHeader header);
        }
    }

    第三个类是:ZollModemReceiver

    namespace ZOLL.Communications.ZOLLModem
    {
        public class ZOLLModemReceiver
        {
            public ZOLLModemReceiver();
    
            public ZOLLModemReceiver.ReceiverState CurrentState { get; }
            public ZOLLModemReceiver.TransferStats CurrentTransfer { get; }
            public DateTime CurrentTransferStart { get; }
            public ZOLLModemReceiver.TransferStats LastTransfer { get; }
            public ZOLLModemReceiver.TransferStats[] PreviousTransfers { get; }
            public string ReceivedFilePath { get; set; }
            public int ResetTimeout { get; set; }
            public bool Run { get; set; }
    
            public event ZOLLModemReceiver.ErrorReportHandler ErrorReport;
            public event ZOLLModemReceiver.FileReceivedHandler FileReceived;
            public event ZOLLModemReceiver.FileReceiveProgressHandler FileReceiveProgress;
            public event ZOLLModemReceiver.FileReceiverStateChangeHandler FileReceiverStateChange;
            public event ZOLLModemReceiver.FileReceiveStartingHandler FileReceiveStarting;
            public event ZOLLModemReceiver.LogOutputHandler LogOutput;
            public event ZOLLModemReceiver.SendFrameHeaderHandler SendFrameHeader;
    
            public void DataBlockError(DataBlock block);
            public void DataBlockReceived(DataBlock block);
            public void FrameHeaderError(FrameHeader header);
            public void FrameHeaderReceived(FrameHeader header);
    
            public enum Error
            {
                NoError = 0,
                Timeout = 1,
                DefibTooFarAhead = 2,
                BadDataBlock = 3,
                BadHeaderBlock = 4,
                DefibLongPause = 5,
                ErrorThresholdReached = 6,
                Cancelled = 7,
            }
    
            public enum ReceiverState
            {
                Halted = 0,
                Idle = 1,
                Initializing = 2,
                NegotiatingFileName = 3,
                ReceivingFileData = 4,
                FlushAndReposition = 5,
                Finishing = 6,
            }
    
            public delegate void ErrorReportHandler(ZOLLModemReceiver.Error code, string message, int arg1, int arg2);
    
            public delegate void FileReceivedHandler(ZOLLModemReceiver.TransferStats transfer_completed);
    
            public delegate void FileReceiveProgressHandler(uint bytes_received, uint file_size);
    
            public delegate void FileReceiverStateChangeHandler(ZOLLModemReceiver.ReceiverState entered_state);
    
            public delegate void FileReceiveStartingHandler(string path, uint file_size);
    
            public delegate void LogOutputHandler(string log_entry);
    
            public delegate void SendFrameHeaderHandler(byte[] header);
    
            public class TransferStats
            {
                public TransferStats(string full_file_path, int file_size, DateTime start_time);
    
                public int BadBlocksReceived { get; }
                public int BadDataBlocksReceived { get; set; }
                public int BadHeadersReceived { get; set; }
                public double CommunicationLinkQuality { get; }
                public bool Completed { get; set; }
                public int DefibInitiatedRepositions { get; set; }
                public int DefibLongSilenceCount { get; set; }
                public double EffectiveBitRate { get; }
                public double ElapsedTime { get; }
                public TimeSpan ElapsedTimeSpan { get; }
                public TimeSpan EstimatedTimeSpanToFinish { get; }
                public double EstimatedTimeToFinish { get; }
                public string FileName { get; set; }
                public int FileSize { get; set; }
                public DateTime FinishTime { get; set; }
                public int GoodBlocksReceived { get; }
                public int GoodDataBlocksReceived { get; set; }
                public int GoodHeadersReceived { get; set; }
                public ZOLLModemReceiver.Error LastError { get; set; }
                public int ReceivedByteCount { get; set; }
                public int ReceiverInitiatedRepositions { get; set; }
                public DateTime StartTime { get; set; }
                public int TotalErrorCount { get; }
            }
        }
    }

    求大虾帮忙看看。


    2016年6月15日 3:05

答案

  • 要参考下.net开发的SDK的sample,或是反编译下.net SDK的源代码,从源代码中分析各个类的关系和调用方法


    专注于.NET ERP/CRM开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    2016年6月15日 3:50
  • Hi,

    蓝牙这边应该也使用的类似串口通讯的方式吧,你仔细看下sdk里面有没有具体参数,没有的话就去网上搜下使用设备的型号,一般这些基础信息都还是提供的。

    顺便说一句,如果有sdk的话,在sdk中基本已经把指令封装成方法了,你只要照着说明书调用就行了。

    Regards,

    Moonlight


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    2016年6月22日 5:57

全部回复

  • 要参考下.net开发的SDK的sample,或是反编译下.net SDK的源代码,从源代码中分析各个类的关系和调用方法


    专注于.NET ERP/CRM开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    2016年6月15日 3:50
  • Hi,

    蓝牙这边应该也使用的类似串口通讯的方式吧,你仔细看下sdk里面有没有具体参数,没有的话就去网上搜下使用设备的型号,一般这些基础信息都还是提供的。

    顺便说一句,如果有sdk的话,在sdk中基本已经把指令封装成方法了,你只要照着说明书调用就行了。

    Regards,

    Moonlight


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    2016年6月22日 5:57