手机:vivo y30
开发目标:小米手环5
unity版本:2021.3.21LTS
目的:开发一个unity 安卓app,通过蓝牙通信读取到小米手环正在运动时测量到的心率值。
//
1.问题
unity安卓使用 BluetoothLEHardwareInterface插件开发小米手环5报错"failed to write characteristic descriptor",从而无法读取小米手环5的心率值功能
(读取到的uuid是对的)
////
2.报错内容
①报错:无法读取到正在测量的心率值。
BluetoothLEHardwareInterface.SubscribeCharacteristic方法,报错为:failed to write characteristic descriptor(无法写入特征描述符)。
②更改了读取数据的方法
BluetoothLEHardwareInterface.ReadCharacteristic出现了报错:failed to read a characteristic(无法读取特征)。
但我觉得应该不能用ReadCharacteristic方法因为
因为是notify属性。可能就不能用读方法了
3.已知信息
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" xmlns:tools="http://schemas.android.com/tools" android:installLocation="preferExternal">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application android:theme="@style/UnityThemeSelector" android:icon="@drawable/app_icon" android:label="@string/app_name" android:isGame="true">
<activity android:label="@string/app_name" android:screenOrientation="fullSensor" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:hardwareAccelerated="false" android:name="com.unity3d.player.UnityPlayerActivity">
<intent-filter>
<!--<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />-->
<action android:name="android.intent.action.MAIN" />
<action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
</application>
<!--
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-feature android:name="android.hardware.bluetooth_le" android:required="false"/>
-->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission-sdk-23 android:name="android.permission.BLUETOOTH" />
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!--
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
-->
</manifest>
①蓝牙服务的UUID↓
②获取到该字段即可获得环5正在测量的心率值
4.代码片段
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class BLContect01 : MonoBehaviour
{
#region
public class UUIDS
{
public static readonly string miband1 = "0000fee0-0000-1000-8000-00805f9b34fb";
public static readonly string miband2 = "0000fee1-0000-1000-8000-00805f9b34fb";
public static readonly string alert = "00001802-0000-1000-8000-00805f9b34fb";
public static readonly string devinfo = "0000180a-0000-1000-8000-00805f9b34fb";
public static readonly string heartrate = "0000180d-0000-1000-8000-00805f9b34fb";
public static readonly string notifications = "00001811-0000-1000-8000-00805f9b34fb";
}
public class CHAR_UUIDS
{
public static readonly string devicename = "00002a00-0000-1000-8000-00805f9b34fb";
public static readonly string hz = "00000002-0000-3512-2118-0009af100700";
public static readonly string sensor = "00000001-0000-3512-2118-0009af100700";
public static readonly string auth = "00000009-0000-3512-2118-0009af100700";
public static readonly string alert = "00002a06-0000-1000-8000-00805f9b34fb";
public static readonly string current_time = "00002a2b-0000-1000-8000-00805f9b34fb";
// unknown= "00002a23-0000-1000-8000-00805f9b34fb";
public static readonly string serial = "00002a25-0000-1000-8000-00805f9b34fb";
public static readonly string hrdw_revision = "00002a27-0000-1000-8000-00805f9b34fb";
public static readonly string revision = "00002a28-0000-1000-8000-00805f9b34fb";
public static readonly string heartrate_measure = "00002a37-0000-1000-8000-00805f9b34fb";
public static readonly string heartrate_control = "00002a39-0000-1000-8000-00805f9b34fb";
public static readonly string notifications = "00002a46-0000-1000-8000-00805f9b34fb";
// unknown= "00002a50-0000-1000-8000-00805f9b34fb";
public static readonly string age = "00002a80-0000-1000-8000-00805f9b34fb";
public static readonly string le_params = "0000ff09-0000-1000-8000-00805f9b34fb";
public static readonly string configuration = "00000003-0000-3512-2118-0009af100700";
public static readonly string fetch = "00000004-0000-3512-2118-0009af100700";
public static readonly string activity_data = "00000005-0000-3512-2118-0009af100700";
public static readonly string battery = "00000006-0000-3512-2118-0009af100700";
public static readonly string steps = "00000007-0000-3512-2118-0009af100700";
public static readonly string user_settings = "00000008-0000-3512-2118-0009af100700";
public static readonly string music_notification = "00000010-0000-3512-2118-0009af100700";
public static readonly string deviceevent = "00000010-0000-3512-2118-0009af100700";
public static readonly string chunked_transfer = "00000020-0000-3512-2118-0009af100700";
}
public class NOTIFICATION_TYPES
{
public static readonly byte[] auth = { 0x02, 0x00 };
public static readonly byte[] msg = { 0x01, 0x01 };
public static readonly byte[] call = { 0x03, 0x01 };
public static readonly byte[] missed = { 0x04, 0x01 };
public static readonly byte[] sms = { 0x05, 0x01 };
}
public class AUTH_TYPES
{
public static readonly byte[] received = { 0x10, 0x01, 0x01 };
public static readonly byte[] requestcode = { 0x10, 0x02, 0x01 };
public static readonly byte[] authed = { 0x10, 0x03, 0x01 };
public static readonly byte[] authfail = { 0x10, 0x03, 0x08 };
}
public class HEARTRATECONTROL_TYPES
{
public static readonly byte[] stop_heartrate_manual = { 0x15, 0x01, 0x00 };
public static readonly byte[] stop_heartrate_auto = { 0x15, 0x02, 0x00 };
public static readonly byte[] start_heartrate_manual = { 0x15, 0x01, 0x01 };
public static readonly byte[] start_heartrate_auto = { 0x15, 0x02, 0x01 };
public static readonly byte[] ping = { 0x16 };
}
#endregion
const string TargetBLEDeviceAddress="C1:02:07:05:62:14";
const string TargetBLEDeviceName = "Mi Smart Band 5";
const int BLEDevice_arrLength = 5;
public Text text_warn;
public Text text_TempValue;
public Text[] Text_AddressArr = new Text[BLEDevice_arrLength];
public bool lock_connectPrint = false;//true 可打印
bool ok = false;
//test
int num = 0;
class BLEDeviceData
{
public BLEDeviceData(string _address, string _name, string _rssi, string _advertisingInfo)
{
this._address = _address;
this._rssi = _rssi;
this._name = _name;
this._advertisingInfo = _advertisingInfo;
}
public BLEDeviceData()
{
this._address = "00:00";//
this._name = "no name";//
this._rssi = "0";//
this._advertisingInfo = "0";//
}
public string _address = "00:00";//设备地址
public string _name = "no name";//设备名
public string _rssi = "0";//信号强度重新赋值
public string _advertisingInfo = "0";//蓝牙设备的广播信息
public string Print_BLEDeviceData()
{
//设备
string x = string.Format("Device: {0} RSSI: {1} Address: {2}\nData Length: {3} Bytes: {4} ", this._name, this._rssi, this._address, this._advertisingInfo.Length, this._advertisingInfo);
return x;
}
}
BLEDeviceData[] BLEDevice_Arr = new BLEDeviceData[BLEDevice_arrLength];
string[] Test = new string[BLEDevice_arrLength];
int BLEDevice_arr_Index = 0;
void Start()
{
BluetoothLEHardwareInterface.Initialize(true, false,
() =>
{
show("蓝牙初始化成功");
Invoke("scanBLE", 1f);
},
(string errorInfo) =>
{
show("蓝牙初始化报错\n" + errorInfo.ToString());
});
for (int i = 0; i < BLEDevice_arrLength; i++)
{
BLEDevice_Arr[i] = new BLEDeviceData();
}
#region
//BluetoothDeviceScript.
/*BluetoothLEHardwareInterface.Initialize(true, false, delegate
{
Invoke("scanBLE", 0.1f);
text_warn.text = "初始化中";
},delegate(string errorInfo) {
text_warn.text = "初始化报错"+ errorInfo.ToString();
});
*/
#endregion
//F5();
}
public void scanBLE()//扫描蓝牙
{
BluetoothLEHardwareInterface.ScanForPeripheralsWithServices(null, (address, name) =>
{ }, (address, name, rssi, advertisingInfo) =>
{
//蓝牙搜索
#region
/*if (BLEaddress_find(address, name, rssi.ToString(), advertisingInfo.ToString()))//找到相同,不操作
{
}
else
{
}*/
#endregion
//找到对应的蓝牙名称
if (name == TargetBLEDeviceName)
{
show("找到了米环5");
//连接蓝牙、接收数据
BLEConnect(address, name, rssi.ToString(), advertisingInfo.ToString());
}
});
}
public void BLEConnect(string getaddress, string getname, string getrssi, string getadvertisingInfo)
{
show("停止搜索");
BluetoothLEHardwareInterface.StopScan();
show("开始连接" + getaddress);
lock_connectPrint = true;
BluetoothLEHardwareInterface.ConnectToPeripheral(getaddress, (getaddress)=> {
}, null, (getaddress, serviceUUID, characteristicUUID) =>//要更改
{
if (lock_connectPrint)
{
//加个锁,平均每次连接打印54次
show("成功连接到" + string.Format("getaddress:{0} serviceUUID:{1} characteristicUUID:{2}", getaddress, serviceUUID, characteristicUUID));
}
lock_connectPrint = false;
//BLEReviceData(getaddress,serviceUUID);
StartCoroutine(BLEDataAnalyse());
});
}
public void BLEReviceData(string getaddress,string serviceUUID)
{
//接收数据
//BluetoothLEHardwareInterface.SubscribeCharacteristicWithDeviceAddress(getaddress, serviceUUID, characteristicUUID, null, BLEDataAnalyse);//要更改
//show("收数据");
/*BluetoothLEHardwareInterface.SubscribeCharacteristicWithDeviceAddress(getaddress, UUIDS.heartrate, CHAR_UUIDS.heartrate_measure, null, (string arg1, string arg2, byte[] arg3)=>
{
});*/
}
string hearttemp="";
IEnumerator BLEDataAnalyse()
{
/* yield return new WaitForSeconds(1);
BluetoothLEHardwareInterface.WriteCharacteristic(TargetBLEDeviceAddress, UUIDS.heartrate, CHAR_UUIDS.heartrate_control,
HEARTRATECONTROL_TYPES.stop_heartrate_auto, HEARTRATECONTROL_TYPES.stop_heartrate_auto.Length, false, (charUUID) =>
{
});
yield return new WaitForSeconds(1);
BluetoothLEHardwareInterface.WriteCharacteristic(TargetBLEDeviceAddress, UUIDS.heartrate, CHAR_UUIDS.heartrate_control,
HEARTRATECONTROL_TYPES.stop_heartrate_manual, HEARTRATECONTROL_TYPES.stop_heartrate_manual.Length, false, (charUUID) =>
{
});*/
yield return new WaitForSeconds(1);
BluetoothLEHardwareInterface.SubscribeCharacteristicWithDeviceAddress(TargetBLEDeviceAddress, UUIDS.heartrate, CHAR_UUIDS.heartrate_measure, null, (address, characteristicUUID, bytes) =>
{
show("数据Sub");
hearttemp = "";//重置读取到的数据
for (int i = 0; i < bytes.Length; i++)
{
hearttemp += bytes[i];
}
show(hearttemp);
hearttemp = "";
});
/**/
}
public void show(string str)
{
text_TempValue.text += "\n"+str;
}
bool BLEaddress_find(string getaddress, string getname, string getrssi, string getadvertisingInfo)
{
for (int i = 0; i <= BLEDevice_arr_Index; i++)
{
if (BLEDevice_Arr[i]._address.Contains(getaddress))//找到相同地址
{
//更换信号
//BLEDevice_Arr[i] = new BLEDeviceData(getaddress, getname, getrssi, getadvertisingInfo);
BLEDevice_Arr[i]._rssi = getrssi;
//text_TempValue.text = BLEDevice_Arr[i]._address+"和"+getaddress + "相同,替换信号强度RSSI";
return true;
}
}
//text_TempValue.text = BLEDevice_Arr[BLEDevice_arr_Index]._address + "和" + getaddress + "不同,添加替换";
BLEDevice_arr_Index = (BLEDevice_arr_Index + 1) % BLEDevice_arrLength;
BLEDevice_Arr[BLEDevice_arr_Index] = new BLEDeviceData(getaddress, getname, getrssi, getadvertisingInfo);
return false;
}
/// <summary>unity蓝牙获取到其他设备信息添加
///
/// </summary>
/// 蓝牙获取到的数组的添加
/// <param name="addressInstance">地址</param>
/// <param name="name">设备名</param>
/// <param name="rssi">信号强弱</param>
/// <param name="advertisingInfo">蓝牙设备的广播信息</param>
/// <returns></returns>
//屏幕显示
#region
//屏幕刷新携程
/*IEnumerator ShowUI()
{
while (true)
{
yield return new WaitForSeconds(1f);
F5();
}
}
//屏幕刷新方法
void F5()
{
for (int i = 0; i <= BLEDevice_arr_Index; i++)
{
Text_AddressArr[i].text = BLEDevice_Arr[i].Print_BLEDeviceData();
}
}*/
#endregion
}
/////////////////////////////