From dbc23459fdf4e8b74a5f955fbb9fc631b4babc70 Mon Sep 17 00:00:00 2001
From: 陈嘉乐 <cjl@hdlchina.com.cn>
Date: 星期三, 17 三月 2021 11:56:16 +0800
Subject: [PATCH] Merge branch 'temp-wxr' into WJC

---
 HDL_ON/UI/UI0-Stan/Logic/HdlBluetoothAndroidLogic.cs |  590 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 590 insertions(+), 0 deletions(-)

diff --git a/HDL_ON/UI/UI0-Stan/Logic/HdlBluetoothAndroidLogic.cs b/HDL_ON/UI/UI0-Stan/Logic/HdlBluetoothAndroidLogic.cs
new file mode 100644
index 0000000..b416038
--- /dev/null
+++ b/HDL_ON/UI/UI0-Stan/Logic/HdlBluetoothAndroidLogic.cs
@@ -0,0 +1,590 @@
+锘縰sing Shared;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace HDL_ON.Stan
+{
+#if __Android__
+    public class HdlBluetoothLogic
+    {
+        #region 鈻� 鍙橀噺澹版槑___________________________
+
+        /// <summary>
+        /// 瀹夊崜钃濈墮鐨勯�昏緫
+        /// </summary>
+        private static HdlBluetoothLogic m_Current = null;
+        /// <summary>
+        /// 瀹夊崜钃濈墮鐨勯�昏緫
+        /// </summary>
+        public static HdlBluetoothLogic Current
+        {
+            get
+            {
+                if (m_Current == null)
+                {
+                    m_Current = new HdlBluetoothLogic();
+                }
+                return m_Current;
+            }
+        }
+
+        /// <summary>
+        /// 褰撳墠钃濈墮瀹㈡埛绔�
+        /// </summary>
+        private Blufi.Espressif.BlufiClient nowBlufiClient = null;
+        /// <summary>
+        /// 鎺ユ敹浜嬩欢
+        /// </summary>
+        private Action<string> ReceiveEvent = null;
+        /// <summary>
+        /// 鍙戦�佺姸鎬�(0:鍙戦�佸け璐� 1:鍙戦�佹垚鍔�)
+        /// </summary>
+        private int sendStatuValue = -1;
+
+        #endregion
+
+        #region 鈻� 钃濈墮鎵�闇�鍔熻兘妫�娴媉__________________
+
+        /// <summary>
+        /// 妫�娴嬫槸鍚﹁兘澶熸悳绱㈣摑鐗�(鍐呴儴浼氬脊鍑篗sg妗�,鍥犱负鍐呴儴闇�瑕佹娴嬬郴缁熸潈闄�,鎵�浠ュ弬鏁伴噰鐢ㄥ洖璋冪殑鏂瑰紡)
+        /// </summary>
+        /// <param name="resultEvent">妫�娴嬬粨鏋滀簨浠�</param>
+        public void CheckCanScanBluetooth(Action<bool> resultEvent)
+        {
+            var adapter = Android.Bluetooth.BluetoothAdapter.DefaultAdapter;
+            var scanner = adapter.BluetoothLeScanner;
+            if (adapter.IsEnabled == false || scanner == null)
+            {
+                HdlMessageLogic.Current.ShowMassage(ShowMsgType.Tip, Language.StringByID(StringId.PleaseTurnOnBluetooth));
+                resultEvent?.Invoke(false);
+                return;
+            }
+            //妫�娴嬫槸鍚︽墦寮�浜嗙郴缁熷姛鑳�
+            if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.M)
+            {
+                var locationManager = (Android.Locations.LocationManager)Application.Activity.GetSystemService(Android.Content.Context.LocationService);
+                if (locationManager == null)
+                {
+                    //浣嶇疆淇℃伅(GBS)涓嶅彲鐢�
+                    HdlMessageLogic.Current.ShowMassage(ShowMsgType.Tip, Language.StringByID(StringId.GbsIsNotAvailable));
+                    resultEvent?.Invoke(false);
+                    return;
+                }
+                if (locationManager.IsProviderEnabled("network") == false)
+                {
+                    HdlMessageLogic.Current.ShowMassage(ShowMsgType.Tip, Language.StringByID(StringId.NetworkIsNotAvailable));
+                    resultEvent?.Invoke(false);
+                    return;
+                }
+                if (locationManager.IsProviderEnabled("gps") == false)
+                {
+                    //浣嶇疆淇℃伅(GBS)涓嶅彲鐢�
+                    HdlMessageLogic.Current.ShowMassage(ShowMsgType.Tip, Language.StringByID(StringId.GbsIsNotAvailable));
+                    resultEvent?.Invoke(false);
+                    return;
+                }
+            }
+            //妫�娴嬭摑鐗欓渶瑕佺殑鏉冮檺
+            ((BaseActivity)Application.Activity).SetPermission((result1) =>
+            {
+                if (result1 == false) 
+                {
+                    resultEvent?.Invoke(false);
+                    return;
+                }
+                ((BaseActivity)Application.Activity).SetPermission((result2) =>
+                {
+                    if (result2 == false)
+                    {
+                        resultEvent?.Invoke(false);
+                        return;
+                    }
+                    //鍏ㄩ儴閫氳繃
+                    resultEvent?.Invoke(true);
+
+                }, "android.permission.ACCESS_FINE_LOCATION");
+
+            }, "android.permission.ACCESS_COARSE_LOCATION");
+        }
+
+        #endregion
+
+        #region 鈻� 钃濈墮鎵弿___________________________
+
+        /// <summary>
+        /// 鎼滅储钃濈墮
+        /// </summary>
+        /// <param name="waitTime">鎼滅储鏃堕棿(绉�)</param>
+        /// <param name="FinishEvent">鎼滅储缁撴潫鐨勪簨浠�</param>
+        public void ScanBluetooth(int waitTime, Action<List<BluetoothInfo>> FinishEvent)
+        {
+            HdlThreadLogic.Current.RunMain(() =>
+            {
+                //鍐嶆妫�娴嬫槸鍚﹁兘澶熸悳绱㈣摑鐗�
+                this.CheckCanScanBluetooth((result) =>
+                {
+                    if (result == true)
+                    {
+                        HdlThreadLogic.Current.RunThread(() =>
+                        {
+                            //寮�濮嬫悳绱㈣摑鐗�
+                            this.DoScanBluetooth(waitTime, FinishEvent);
+                        });
+                    }
+                });
+            });
+        }
+
+        /// <summary>
+        /// 寮�濮嬫悳绱㈣摑鐗�
+        /// </summary>
+        /// <param name="waitTime">鎼滅储鏃堕棿(绉�)</param>
+        /// <param name="FinishEvent">鎼滅储缁撴潫鐨勪簨浠�</param>
+        private void DoScanBluetooth(int waitTime, Action<List<BluetoothInfo>> FinishEvent)
+        {
+            var listBluetoothInfo = new List<BluetoothInfo>();
+
+            BluetoothScanCallback scanCallback = null;
+            Android.Bluetooth.BluetoothAdapter adapter = null;
+            Android.Bluetooth.LE.BluetoothLeScanner scanner = null;
+
+            //浠ラ槻涓囦竴,钃濈墮閮戒涪鍦ㄤ富绾跨▼涓繍琛�
+            HdlThreadLogic.Current.RunMain(() =>
+            {
+                adapter = Android.Bluetooth.BluetoothAdapter.DefaultAdapter;
+                scanner = adapter.BluetoothLeScanner;
+
+                scanCallback = new BluetoothScanCallback();
+                scanner.StartScan(null, new Android.Bluetooth.LE.ScanSettings.Builder().SetScanMode(Android.Bluetooth.LE.ScanMode.LowLatency).Build(), scanCallback);
+            }, ShowErrorMode.NO);
+
+            //绛夊緟
+            System.Threading.Thread.Sleep(waitTime * 1000);
+
+            HdlThreadLogic.Current.RunMain(() =>
+            {
+                scanner.StopScan(scanCallback);
+                adapter.Dispose();
+
+                foreach (var data in scanCallback.listData)
+                {
+                    listBluetoothInfo.Add(data);
+                }
+                scanCallback.listData.Clear();
+
+                FinishEvent?.Invoke(listBluetoothInfo);
+            });
+        }
+
+        /// <summary>
+        /// 钃濈墮鐨勫洖璋冨璞�
+        /// </summary>
+        private class BluetoothScanCallback : Android.Bluetooth.LE.ScanCallback
+        {
+            /// <summary>
+            /// 钃濈墮鍒楄〃
+            /// </summary>
+            public List<BluetoothInfo> listData = new List<BluetoothInfo>();
+            /// <summary>
+            /// 閲嶅妫�娴�
+            /// </summary>
+            private List<string> listCheck = new List<string>();
+
+            /// <summary>
+            /// 钃濈墮缁撴灉鎺ユ敹
+            /// </summary>
+            /// <param name="listResult"></param>
+            public override void OnBatchScanResults(IList<Android.Bluetooth.LE.ScanResult> listResult)
+            {
+                foreach (var result in listResult)
+                {
+                    this.AddBluetoothResult(result);
+                }
+            }
+
+            /// <summary>
+            /// 钃濈墮缁撴灉鎺ユ敹
+            /// </summary>
+            /// <param name="callbackType"></param>
+            /// <param name="result"></param>
+            public override void OnScanResult(Android.Bluetooth.LE.ScanCallbackType callbackType, Android.Bluetooth.LE.ScanResult result)
+            {
+                this.AddBluetoothResult(result);
+            }
+
+            /// <summary>
+            /// 娣诲姞钃濈墮缂撳瓨
+            /// </summary>
+            /// <param name="result"></param>
+            private void AddBluetoothResult(Android.Bluetooth.LE.ScanResult result)
+            {
+                var device = result.Device;
+                if (device == null || listCheck.Contains(device.Address) == true)
+                {
+                    return;
+                }
+                listCheck.Add(device.Address);
+
+                var data = new BluetoothInfo();
+                data.Name = device.Name;
+                if (data.Name == null) { data.Name = string.Empty; }
+                data.Address = device.Address;
+                data.Device = device;
+                listData.Add(data);
+            }
+        }
+
+        #endregion
+
+        #region 鈻� 钃濈墮閾炬帴___________________________
+
+        /// <summary>
+        /// 钃濈墮閾炬帴(false:杩炴帴澶辫触 true:杩炴帴鎴愬姛)
+        /// </summary>
+        /// <param name="bluetooth">闇�瑕侀摼鎺ョ殑钃濈墮瀵硅薄</param>
+        /// <param name="connectEvent">鍥犱负闇�瑕佸鏂瑰弽棣�,鎵�浠ヤ娇鐢ㄥ洖璋�(閾炬帴缁撴灉 false:杩炴帴澶辫触 true:杩炴帴鎴愬姛)</param>
+        public void ContectBluetooth(BluetoothInfo bluetooth, Action<bool> connectEvent)
+        {
+            HdlThreadLogic.Current.RunMain(() =>
+            {
+                try
+                {
+                    this.nowBlufiClient = new Blufi.Espressif.BlufiClient(Application.Activity, bluetooth.Device);
+
+                    //涓�涓洖璋冧簨浠�
+                    var callback = new InnerGattCallback();
+                    callback.ConnectionStateEvent += (div, newState) =>
+                    {
+                        if (div == 1)
+                        {
+                            if (newState == Android.Bluetooth.ProfileState.Connected)
+                            {
+                                //閾炬帴寤虹珛鎴愬姛
+                                connectEvent?.Invoke(true);
+                                //鍙�氱煡涓�娆�
+                                connectEvent = null;
+                            }
+                            else if (newState == Android.Bluetooth.ProfileState.Disconnected)
+                            {
+                                //鍏抽棴閾炬帴
+                                this.DisContectBluetooth();
+                                connectEvent?.Invoke(false);
+                                //鍙�氱煡涓�娆�
+                                connectEvent = null;
+                            }
+                        }
+                        else if (div == -1)
+                        {
+                            //鍏抽棴閾炬帴
+                            this.DisContectBluetooth();
+                            connectEvent?.Invoke(false);
+                            //鍙�氱煡涓�娆�
+                            connectEvent = null;
+                        }
+                    };
+                    nowBlufiClient.SetGattCallback(callback);
+
+                    //鍙﹀涓�涓洖璋冧簨浠�
+                    var blufiCall = new BlufiCallbackMain();
+                    blufiCall.StateEvent += (div, data) =>
+                    {
+                        //-1:寮傚父 1:姝e父 2:鍙戦�佹暟鎹垚鍔� 3:鍙戦�佹暟鎹け璐�
+                        if (div == StatuEnum.A寮傚父)
+                        {
+                            //鍏抽棴閾炬帴
+                            this.DisContectBluetooth();
+                            connectEvent?.Invoke(false);
+                            //鍙�氱煡涓�娆�
+                            connectEvent = null;
+                        }
+                        else if (div == StatuEnum.A鍙戦�佹垚鍔� || div == StatuEnum.A鍙戦�佸け璐�)
+                        {
+                            sendStatuValue = div == StatuEnum.A鍙戦�佹垚鍔� ? 1 : 0;
+                        }
+                        else if (div == StatuEnum.A钃濈墮鍙嶉)
+                        {
+                            //钃濈墮杩斿洖鐨勭粨鏋�
+                            this.ReceiveEvent?.Invoke(data);
+                        }
+                    };
+                    nowBlufiClient.SetBlufiCallback(blufiCall);
+                    //鎵ц閾炬帴
+                    nowBlufiClient.Connect();
+                }
+                catch
+                {
+                    connectEvent?.Invoke(false);
+                    connectEvent = null;
+                }
+            });
+        }
+
+        /// <summary>
+        /// 鍏堣繖涔堝畾涔変竴涓┖鐨勭户鎵�
+        /// </summary>
+        private class InnerGattCallback : Android.Bluetooth.BluetoothGattCallback
+        {
+            /// <summary>
+            /// 鐘舵�佷簨浠跺洖璋�(-1:寮傚父 1:OnConnectionStateChange)
+            /// </summary>
+            public Action<int,Android.Bluetooth.ProfileState> ConnectionStateEvent = null;
+            /// <summary>
+            /// 閾炬帴鐘舵�佹敼鍙�
+            /// </summary>
+            /// <param name="gatt"></param>
+            /// <param name="status"></param>
+            /// <param name="newState"></param>
+            public override void OnConnectionStateChange(Android.Bluetooth.BluetoothGatt gatt, Android.Bluetooth.GattStatus status, Android.Bluetooth.ProfileState newState)
+            {
+                if (status == Android.Bluetooth.GattStatus.Success)
+                {
+                    //鍥炶皟浜嬩欢
+                    this.ConnectionStateEvent?.Invoke(1, newState);
+                }
+                else
+                {
+                    //鍥炶皟浜嬩欢
+                    this.ConnectionStateEvent?.Invoke(-1, 0);
+                }
+            }
+
+            /// <summary>
+            /// 鎴愬姛鍙戠幇璁惧鐨剆ervices鏃讹紝璋冪敤姝ゆ柟娉�
+            /// </summary>
+            /// <param name="gatt"></param>
+            /// <param name="status"></param>
+            public override void OnServicesDiscovered(Android.Bluetooth.BluetoothGatt gatt, Android.Bluetooth.GattStatus status)
+            {
+                if (status != Android.Bluetooth.GattStatus.Success)
+                {
+                    //鍥炶皟浜嬩欢
+                    this.ConnectionStateEvent?.Invoke(-1, 0);
+                }
+            }
+
+            /// <summary>
+            /// 搴旇鏄啓鍏ヤ簨浠跺惂
+            /// </summary>
+            /// <param name="gatt"></param>
+            /// <param name="characteristic"></param>
+            /// <param name="status"></param>
+            public override void OnCharacteristicWrite(Android.Bluetooth.BluetoothGatt gatt, Android.Bluetooth.BluetoothGattCharacteristic characteristic, Android.Bluetooth.GattStatus status)
+            {
+                if (status != Android.Bluetooth.GattStatus.Success)
+                {
+                    //鍥炶皟浜嬩欢
+                    this.ConnectionStateEvent?.Invoke(-1, 0);
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鎶凷DK鐨勶紝鎴戜篃涓嶇煡閬撹繖涓槸浠�涔�
+        /// </summary>
+        private class BlufiCallbackMain : Blufi.Espressif.BlufiCallback
+        {
+            /// <summary>
+            /// 鐘舵�佷簨浠跺洖璋� 褰撶涓�涓弬鏁颁负"A钃濈墮鍙嶉"鏃�,绗簩涓弬鏁颁负钃濈墮杩斿洖鐨勪俊鎭�
+            /// </summary>
+            public Action<StatuEnum, string> StateEvent = null;
+
+            /// <summary>
+            /// 鎶凷DK鐨勶紝鎴戜篃涓嶇煡閬撹繖涓槸浠�涔�
+            /// </summary>
+            /// <param name="client"></param>
+            /// <param name="gatt"></param>
+            /// <param name="service"></param>
+            /// <param name="writeChar"></param>
+            /// <param name="notifyChar"></param>
+            public override void OnGattPrepared(Blufi.Espressif.BlufiClient client, Android.Bluetooth.BluetoothGatt gatt, Android.Bluetooth.BluetoothGattService service,
+                Android.Bluetooth.BluetoothGattCharacteristic writeChar, Android.Bluetooth.BluetoothGattCharacteristic notifyChar)
+            {
+                if (service == null || writeChar == null || notifyChar == null)
+                {
+                    StateEvent?.Invoke(StatuEnum.A寮傚父, null);
+                    return;
+                }
+
+                try
+                {
+                    int mtu = 128;
+                    if ((int)Android.OS.Build.VERSION.SdkInt == 29
+                      && Android.OS.Build.Manufacturer.ToLower().StartsWith("samsung") == true)
+                    {
+                        mtu = 23;
+                    }
+
+                    var requestMtu = gatt.RequestMtu(mtu);
+                    if (!requestMtu)
+                    {
+                        //Request mtu failed
+                        client.SetPostPackageLengthLimit(20);
+                    }
+                    StateEvent?.Invoke(StatuEnum.A姝e父, null); ;
+                }
+                catch
+                {
+                    StateEvent?.Invoke(StatuEnum.A寮傚父, null);
+                    return;
+                }
+            }
+
+            /// <summary>
+            /// 鎵嬫満绔彂閫佹暟鎹埌钃濈墮鐨勭粨鏋�
+            /// </summary>
+            /// <param name="client"></param>
+            /// <param name="status">0:鎴愬姛 鍏朵粬閮芥槸澶辫触</param>
+            /// <param name="data">鎵嬫満绔彂閫佺殑鏁版嵁</param>
+            public override void OnPostCustomDataResult(Blufi.Espressif.BlufiClient client, int status, byte[] data)
+            {
+                StateEvent?.Invoke(status == 0 ? StatuEnum.A鍙戦�佹垚鍔� : StatuEnum.A鍙戦�佸け璐�, null);
+            }
+
+            /// <summary>
+            /// 钃濈墮鍥炲鐨勭粨鏋�
+            /// </summary>
+            /// <param name="client"></param>
+            /// <param name="status">0:鎴愬姛 鍏朵粬閮芥槸澶辫触</param>
+            /// <param name="data">钃濈墮鍥炲鐨勬暟鎹�</param>
+            public override void OnReceiveCustomData(Blufi.Espressif.BlufiClient client, int status, byte[] data)
+            {
+                if (status == 0)
+                {
+                    var receiveData = System.Text.Encoding.UTF8.GetString(data);
+                    StateEvent?.Invoke(StatuEnum.A钃濈墮鍙嶉, receiveData);
+                }
+            }
+        }
+
+        #endregion
+
+        #region 鈻� 钃濈墮鍏抽棴___________________________
+
+        /// <summary>
+        ///  鍏抽棴钃濈墮閾炬帴
+        /// </summary>
+        public void DisContectBluetooth()
+        {
+            HdlThreadLogic.Current.RunMain(() =>
+            {
+                this.nowBlufiClient?.RequestCloseConnection();
+                this.nowBlufiClient = null;
+
+                m_Current = null;
+
+            }, ShowErrorMode.NO);
+        }
+
+        /// <summary>
+        /// 鎽ф瘉
+        /// </summary>
+        public void Dispone()
+        {
+            //鍏抽棴钃濈墮閾炬帴
+            this.DisContectBluetooth();
+            this.ReceiveEvent = null;
+            m_Current = null;
+        }
+
+        #endregion
+
+        #region 鈻� 鍙戦�佹暟鎹甠__________________________
+
+        /// <summary>
+        /// 鍙戦�佹暟鎹粰钃濈墮
+        /// </summary>
+        /// <param name="i_data">鍙戦�佺殑鏁版嵁</param>
+        /// <param name="waiTime">绛夊緟鏃堕棿(绉�),濡傛灉璁剧疆涓�0,鍒欏彧瑕佸彂閫佷笉鍑虹幇寮傚父,鐩存帴鍒ゅ畾涓烘垚鍔�</param>
+        public bool SendData(string i_data, int waiTime = 0)
+        {
+            if (this.nowBlufiClient == null)
+            {
+                return false;
+            }
+
+            try
+            {
+                this.sendStatuValue = -1;
+                HdlThreadLogic.Current.RunMain(() =>
+                {
+                    //鍙戦�佹暟鎹�
+                    var byteData = System.Text.Encoding.UTF8.GetBytes(i_data);
+                    this.nowBlufiClient.PostCustomData(byteData);
+
+                }, ShowErrorMode.NO);
+
+                if (waiTime == 0) { return true; }
+
+                waiTime *= 5;
+                while (this.sendStatuValue == -1 && waiTime > 0)
+                {
+                    System.Threading.Thread.Sleep(200);
+                    waiTime--;
+                }
+                return this.sendStatuValue == 1;
+            }
+            catch { return false; }
+        }
+
+        #endregion
+
+        #region 鈻� 涓�鑸柟娉昣__________________________
+
+        /// <summary>
+        /// 娣诲姞钃濈墮鐨勬帴鏀朵簨浠�
+        /// </summary>
+        /// <param name="i_ReceiveEvent">钃濈墮鎺ユ敹浜嬩欢</param>
+        public void AddReceiveEvent(Action<string> i_ReceiveEvent)
+        {
+            this.ReceiveEvent = i_ReceiveEvent;
+        }
+
+        /// <summary>
+        /// 绉婚櫎钃濈墮鐨勬帴鏀朵簨浠�
+        /// </summary>
+        public void RemoveReceiveEvent()
+        {
+            this.ReceiveEvent = null;
+        }
+
+        #endregion
+
+        #region 鈻� 缁撴瀯浣揰____________________________
+
+        /// <summary>
+        /// 钃濈墮杩斿洖鐨勪俊鎭�
+        /// </summary>
+        public class BluetoothInfo
+        {
+            /// <summary>
+            /// 鍚嶅瓧(姝ゅ悕瀛椾笉浼歯ull,濡傛灉瀹冩湰韬槸null,鍙細鏄痵tring.empty)
+            /// </summary>
+            public string Name = string.Empty;
+            /// <summary>
+            /// 鍦板潃
+            /// </summary>
+            public string Address = string.Empty;
+            /// <summary>
+            /// 钃濈墮璁惧
+            /// </summary>
+            public Android.Bluetooth.BluetoothDevice Device = null;
+        }
+
+        /// <summary>
+        /// 鐘舵�佹灇涓�
+        /// </summary>
+        private enum StatuEnum
+        {
+            A寮傚父 = -1,
+            A姝e父 = 1,
+            A鍙戦�佹垚鍔� = 2,
+            A鍙戦�佸け璐� = 3,
+            A钃濈墮鍙嶉 = 4
+        }
+
+        #endregion
+    }
+#endif
+}
+

--
Gitblit v1.8.0