Unity3D蓝牙连接Mi Band 5手环获取实时心率
直接上代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class BLEMiBand : MonoBehaviour
{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 };}public string DeviceName = "Mi Smart Band 5";public string AuthKey = "50a2c4668b3e565c0f495885251c4346";public Text txtMiBandLabel;public Text txtMiBandStatus;public Text txtBluetoothStatus;public GameObject PanelMiddle;public Text txtHeartRate;enum States{None,Scan,Connect,Auth,Subscribe,Unsubscribe,Disconnect,Communication,}[SerializeField]private bool bConnected = false;[SerializeField]private bool bAuthed = false;[SerializeField]private bool bSubscribed = false;[SerializeField]private string device;[SerializeField]bool foundChartAuth = false;[SerializeField]bool foundChartHeartrateControl = false;[SerializeField]bool foundChartHeartrateMeasurement = false;[SerializeField]bool foundChartSensor = false;void Reset(){bConnected = false;bAuthed = false;device = null;foundChartAuth = false;foundChartHeartrateControl = false;foundChartHeartrateMeasurement = false;foundChartSensor = false;PanelMiddle.SetActive(false);}void InitBLE(){txtMiBandStatus.text = "";txtBluetoothStatus.text = "Initializing...";Reset();BluetoothLEHardwareInterface.Initialize(true, false, () => {StartCoroutine(delayScan(0.1f));txtBluetoothStatus.text = "Initialized";}, (error) => {BluetoothLEHardwareInterface.Log("Error: " + error);});}// Use this for initializationvoid Start(){InitBLE();}// Update is called once per framevoid Update(){}IEnumerator delayScan(float delay){yield return new WaitForSeconds(delay);txtBluetoothStatus.text = "Scanning devices[" + DeviceName + "]";BluetoothLEHardwareInterface.ScanForPeripheralsWithServices(null, (address, name) =>{// we only want to look at devices that have the name we are looking for// this is the best way to filter out devicesif (name.Contains(DeviceName)){DeviceName = name;// it is always a good idea to stop scanning while you connect to a device// and get things set upBluetoothLEHardwareInterface.StopScan();txtBluetoothStatus.text = "";// add it to the list and set to connect to itdevice = address;txtMiBandLabel.text = DeviceName + "[" + device + "]";txtMiBandStatus.text = "Found " + DeviceName;StartCoroutine(delayConnect(0.5f));}}, null, false, false);}IEnumerator delayConnect(float delay){yield return new WaitForSeconds(delay);// set these flagstxtMiBandStatus.text = "Connecting to " + DeviceName;// note that the first parameter is the address, not the name. I have not fixed this because// of backwards compatiblity.// also note that I am note using the first 2 callbacks. If you are not looking for specific characteristics you can use one of// the first 2, but keep in mind that the device will enumerate everything and so you will want to have a timeout// large enough that it will be finished enumerating before you try to subscribe or do any other operations.BluetoothLEHardwareInterface.ConnectToPeripheral(device, null, null, (address, serviceUUID, characteristicUUID) =>{if (IsEqual(serviceUUID, UUIDS.miband2) && IsEqual(characteristicUUID, CHAR_UUIDS.auth)){foundChartAuth = true;}else if (IsEqual(serviceUUID, UUIDS.heartrate) && IsEqual(characteristicUUID, CHAR_UUIDS.heartrate_control)){foundChartHeartrateControl = true;}else if (IsEqual(serviceUUID, UUIDS.heartrate) && IsEqual(characteristicUUID, CHAR_UUIDS.heartrate_measure)){foundChartHeartrateMeasurement = true;}else if (IsEqual(serviceUUID, UUIDS.miband1) && IsEqual(characteristicUUID, CHAR_UUIDS.sensor)){foundChartSensor = true;}// all need characteristics foundif (foundChartAuth && foundChartHeartrateControl && foundChartHeartrateMeasurement && foundChartSensor){bConnected = true;txtMiBandStatus.text = "Connected to " + DeviceName;// if we have found the characteristic that we are waiting for// authenticate. make sure there is enough timeout that if the// device is still enumerating other characteristics it finishes// before we try to subscribeStartCoroutine(delayAuthenticate(12f));}}, (disconnectedAddress) =>{BluetoothLEHardwareInterface.Log("Device disconnected: " + disconnectedAddress);txtMiBandStatus.text = "Disconnected";bConnected = false;bAuthed = false;bSubscribed = false;});}IEnumerator delayAuthenticate(float delay){PanelMiddle.SetActive(true);yield return new WaitForSeconds(delay);SubscribeAuth();yield return new WaitForSeconds(0.5f);SendAuth();}IEnumerator delaySubscribeHeartrate(float delay){yield return new WaitForSeconds(delay);BluetoothLEHardwareInterface.WriteCharacteristic(device, UUIDS.heartrate, CHAR_UUIDS.heartrate_control,HEARTRATECONTROL_TYPES.stop_heartrate_auto, HEARTRATECONTROL_TYPES.stop_heartrate_auto.Length, false, (charUUID) =>{});yield return new WaitForSeconds(0.5f);BluetoothLEHardwareInterface.WriteCharacteristic(device, UUIDS.heartrate, CHAR_UUIDS.heartrate_control,HEARTRATECONTROL_TYPES.stop_heartrate_manual, HEARTRATECONTROL_TYPES.stop_heartrate_manual.Length, false, (charUUID) =>{});yield return new WaitForSeconds(0.5f);BluetoothLEHardwareInterface.SubscribeCharacteristicWithDeviceAddress(device, UUIDS.heartrate, CHAR_UUIDS.heartrate_measure, null, (address, characteristicUUID, bytes) =>{txtMiBandStatus.text = "Received Subscribe[" + bytes.Length.ToString() + "][" + Time.time.ToString("F2") + "]" + Utility.Bytes2Hex(bytes) + "";if (2 == bytes.Length){byte[] heartrate = { bytes[1], bytes[0] };txtHeartRate.text = System.BitConverter.ToInt16(heartrate, 0).ToString("D3") + "BPM";}else if (1 == bytes.Length){txtHeartRate.text = ((int)(bytes[0])).ToString("D3") + "BPM";}});yield return new WaitForSeconds(0.5f);txtMiBandStatus.text = "Starting manual heart rate detection...";BluetoothLEHardwareInterface.WriteCharacteristic(device, UUIDS.heartrate, CHAR_UUIDS.heartrate_control,HEARTRATECONTROL_TYPES.start_heartrate_manual, HEARTRATECONTROL_TYPES.start_heartrate_manual.Length, false, (charUUID) =>{txtMiBandStatus.text = "Startedmanual heart rate detection...";});while (bSubscribed){yield return new WaitForSeconds(12f);BluetoothLEHardwareInterface.WriteCharacteristic(device, UUIDS.heartrate, CHAR_UUIDS.heartrate_control,HEARTRATECONTROL_TYPES.ping, HEARTRATECONTROL_TYPES.ping.Length, false, (charUUID) =>{});}}IEnumerator delayUnsubscribeHeartrate(float delay){yield return new WaitForSeconds(delay);BluetoothLEHardwareInterface.UnSubscribeCharacteristic(device, UUIDS.heartrate, CHAR_UUIDS.heartrate_measure, null);bSubscribed = false;StartCoroutine(delayDisconnect(4f));}IEnumerator delayDisconnect(float delay){yield return new WaitForSeconds(delay);if (bConnected){BluetoothLEHardwareInterface.DisconnectPeripheral(device, (address) =>{BluetoothLEHardwareInterface.DeInitialize(() =>{bConnected = false;});});}else{BluetoothLEHardwareInterface.DeInitialize(() =>{});}}public void SubscribeAuth(){txtMiBandStatus.text = "Subscribe Characteristic[CHAR_UUIDS.auth]";BluetoothLEHardwareInterface.SubscribeCharacteristic(device, UUIDS.miband2, CHAR_UUIDS.auth, null, (characteristicUUID, bytes) =>{string msg = "Received Serial[CHAR_UUIDS.auth]";if (bytes.Length >= 3){byte[] code = { bytes[0], bytes[1], bytes[2] };if (IsEqual(code, AUTH_TYPES.received)){msg = "Authenticate Received";}else if (bytes.Length == 19 && IsEqual(code, AUTH_TYPES.requestcode)){msg = "Authenticate Request Code";List<byte> serial = new List<byte>();serial.AddRange(bytes);serial.RemoveRange(0, 3);if (serial.Count != 16){txtMiBandStatus.text = "Unknown Request Code[" + Utility.Bytes2Hex(serial.ToArray()) + "]";msg = "";}else{try{byte[] key = Utility.Hex2Bytes(AuthKey);if (key.Length != 16){txtMiBandStatus.text = "AuthKey must be 16 bytes[" + AuthKey + "]";msg = "";}else{byte[] iv = new byte[16];byte[] aes = AesEncrypt(serial.ToArray(), key, iv);List<byte> ls = new List<byte>();ls.Add(0x03);ls.Add(0x00);ls.AddRange(aes);byte[] authKey = ls.ToArray();txtMiBandStatus.text = "Writing Auth Code[" + Utility.Bytes2Hex(authKey) + "]";msg = "";BluetoothLEHardwareInterface.WriteCharacteristic(device, UUIDS.miband2, CHAR_UUIDS.auth, authKey, authKey.Length, false, (charUUID) =>{txtMiBandStatus.text = "Writed Auth Code[" + Utility.Bytes2Hex(authKey) + "]";});}}catch(System.Exception E){msg = "Unknown Exception[" + E.Message + "]";}}}else if (IsEqual(code, AUTH_TYPES.authfail)){msg = "Authenticate Failed";Invoke("SendAuth", 5); // retry after 5 seconds}else if (IsEqual(code, AUTH_TYPES.authed)){msg = "Authenticate Successful";bAuthed = true;StartCoroutine(delaySubscribeHeartrate(0.5f));}else{msg = "Authenticate Received Unknown Message";}}if (!string.IsNullOrEmpty(msg)){txtMiBandStatus.text = msg + "[" + bytes.Length.ToString() + "]" + Utility.Bytes2Hex(bytes);}});}public void SendAuth(){txtMiBandStatus.text = "Sending Auth Request[" + Utility.Bytes2Hex(NOTIFICATION_TYPES.auth) + "]";if (bConnected){if (!bAuthed){BluetoothLEHardwareInterface.WriteCharacteristic(device, UUIDS.miband2, CHAR_UUIDS.auth, NOTIFICATION_TYPES.auth, NOTIFICATION_TYPES.auth.Length, false, (charUUID) =>{txtMiBandStatus.text = "Sent Auth Request[" + Utility.Bytes2Hex(NOTIFICATION_TYPES.auth) + "][" + charUUID + "]";});}}}public void Unsubscribe(){txtMiBandStatus.text = "Unsubscribe";StartCoroutine(delayUnsubscribeHeartrate(1.0f));}string FullUUID(string uuid){return "0000" + uuid + "-0000-1000-8000-00805F9B34FB";}bool IsEqual(string uuid1, string uuid2){if (uuid1.Length == 4)uuid1 = FullUUID(uuid1);if (uuid2.Length == 4)uuid2 = FullUUID(uuid2);return (uuid1.ToUpper().Equals(uuid2.ToUpper()));}bool IsEqual(byte[] data1, byte[] data2){if (data1.Length != data2.Length){return false;}for (int i = 0; i < data1.Length; ++i){if (data1[i] != data2[i]){return false;}}return true;}// AES CBCpublic static byte[] AesEncrypt(byte[] byteContnet, byte[] byteKEY, byte[] byteIV){var aes = new System.Security.Cryptography.RijndaelManaged(); ;aes.Padding = System.Security.Cryptography.PaddingMode.None;aes.Mode = System.Security.Cryptography.CipherMode.CBC;aes.Key = byteKEY;aes.IV = byteIV;var crypto = aes.CreateEncryptor(byteKEY, byteIV);byte[] decrypted = crypto.TransformFinalBlock(byteContnet, 0, byteContnet.Length);crypto.Dispose();return decrypted;}public static byte[] Hex2Bytes(string src){System.Collections.Generic.List<byte> ls = new System.Collections.Generic.List<byte>();char[] chs = src.ToCharArray();for (int i = 0; i < chs.Length; i += 2){byte b = System.Convert.ToByte(new string(chs, i, 2), 16);ls.Add(b);}return ls.ToArray();}public static string Bytes2Hex(byte[] src){System.Collections.Generic.List<char> ls = new System.Collections.Generic.List<char>();char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };for (int i = 0; i < src.Length; i++){ls.Add(hexDigits[src[i] >> 4 & 0x0f]);ls.Add(hexDigits[src[i] & 0x0f]);}return new string(ls.ToArray());}
}

以上代码适用于MiBand 3,4,5,不适用于MiBand 6,Auth验证方法应该有调整了

参考:
Unity3D BLE插件
蓝牙通信插件最新版Bluetooth LE for iOS tvOS and Android.unitypackage

MiBand AuthKey获取
Your Soul, Your Beats! —— 小米手环实时心率采集

GitHub项目
Mi Band 4/5 Heart Rate Monitor

Unity3D蓝牙连接Mi Band 5手环获取实时心率相关推荐

  1. 热点连接的设备android,Android获取实时连接热点的设备IP

    最近有很多网友向小编咨询这样的问题:通过读取/proc/net/arp文件可以得到连接当前热点的设备的IP,但是一旦设备断开后,该设备的IP还是存在该文件中,遇到这样的麻烦不知道该如何解决了. 就像系 ...

  2. 【微信小程序】蓝牙连接 流程

    小程序蓝牙低功耗蓝牙主要有以下几个步骤以及会用到的接口: 打开适配器(openBluetoothAdapter) 监听蓝牙适配器状态变化(onBluetoothAdapterStateChange) ...

  3. 【Android -- 蓝牙】蓝牙连接打印机

    1. 效果图 2. 开发环境 Gprinter佳博打印机,型号GP-2120TU Android Studio 3.6.1,gradle 3.5.3 3. 涉及知识点 蓝牙相关 多线程开发 线程池 构 ...

  4. Android手机HC-05蓝牙连接Arduino nano获取DHT-11温湿度传感器数据

    如果您觉得本文对您有用,希望您点赞,收藏并且把它分享出去,不明白的可以在评论区留言,我会一一解答,感谢您的支持!! 目标 Android手机HC-05蓝牙连接Arduino nano获取DHT-11温 ...

  5. 微信小程序使用蓝牙通信协议连接硬件整理总结(蓝牙连接、获取设备UUID、开水器notify及关闭蓝牙)

    大家好,我是雄雄. 文章目录 前言 进行蓝牙连接 获取蓝牙设备的UUID 获取UUID中的特征值 开启notify 关闭蓝牙 前言 书接前文,上篇文章我们主要介绍了初始化蓝牙.以及搜索附近蓝牙设备以及 ...

  6. Android 设备蓝牙连接扫描枪获取扫描内容

    Android 设备蓝牙连接扫描枪获取扫描内容 标签(空格分隔): 未分类 条形扫描枪主要可以扫描条形码和二维码等,扫描速度比手机扫描设备快得多,本文简单介绍android 通过蓝牙监听蓝牙连接,当扫 ...

  7. VMware安装android 使用蓝牙连接智能手环

    vmware 创建的android虚拟机可以挂载主机自带的蓝牙设备去连接智能手环,即不需要单独购买蓝牙适配器.网上帖子实在太少,这里我就分享一下自己的心得,希望能帮助到需要的人.特别是windows ...

  8. 在HbuilderX中实现微信小程序下蓝牙连接打印机完整实战案例

    1.基础开发环境,所用到的 Api 以及实现的思路. 应用场景: 商家打印小票,小票包含顾客消费的商品明细信息以及末尾附上二维码,二维码供顾客扫码开票. HbuilderX开发工具: HBuilder ...

  9. 百度云Dulife平台首发Boom Band智能手环

    近日,百度云Dulife智能可穿戴设备官网上线(http://dulife.baidu.com/),从其上一层主属页面可以厘清他们的内部关系,这是百度云创新实验室(http://x.baidu.com ...

最新文章

  1. 怎样在VirtualBox 虚拟机中挂载共享目录
  2. iOS:MBProgressHUD的基本使用
  3. Centos 6.x 安装 docker
  4. 使用 Docker 部署 Spring Boot 项目
  5. kafka reassign 限速_RabbitMQ 与 Kafka 的技术差异以及使用注意点
  6. centos6.5系统自带python2.6升级到python2.7
  7. Unobtrusive JavaScript介绍
  8. 从“梁漱溟:思考问题有八层境界”所联想到的
  9. SharePoint 2010多语言包的安装
  10. win 二进制门安装mysql_MySQL5.7 windows二进制安装
  11. [码海拾贝 之JS] JS 之删除数组中的元素
  12. 全国计算机一级考试网络知识,全国计算机等级考试一级网络基础知识复习题及答案.doc...
  13. pulse 去马赛克软件_打马赛克就安全了吗?AI消除马赛克,上线三天收获近7000星...
  14. Pycharm 远程连接服务器(ssh)运行深度学习代码 | 详细步骤
  15. 数据库锁,事务特性,脏读,幻读,不可重复度,隔离级别,分布式事务,本地事务的介绍
  16. MySQL函数及用法
  17. 洛谷 P1957 口算练习题 题解 字符串 C/C++
  18. 贴吧老矣,尚能饭否?
  19. shiny | 使用R创建一个网页应用(Web App)
  20. 冒泡排序与快速排序比较

热门文章

  1. 【数据库系统工程师】1.1计算机硬件基础知识
  2. 关于Freesurfer6.0海马体的分割环境以及步骤
  3. 人工智能中的分析学快速入门之著名教材
  4. 怎么画好软件产品原型图?
  5. data whitening
  6. docker--compose
  7. 丁小平:浅谈科学模型及突变论等问题
  8. 网站前台-登陆与用户中心
  9. 《了凡四训》全文 + 译文
  10. 2021年保安员(初级)考试资料及保安员(初级)复审考试