React-native BlE藍(lán)牙連接打印機(jī)

藍(lán)牙知識(shí)

在iOS開發(fā)中板甘,實(shí)現(xiàn)藍(lán)牙通信有兩種方式恃鞋,一種是使用傳統(tǒng)的GameKit.framework拐邪,另一種就是使用在iOS 5中加入的CoreBluetooth.framework睬塌。
BLE分為三部分Service(服務(wù))庐船、Characteristic(特征)颖御、Descriptor(描述符)榄棵,這三部分都由UUID作為唯一標(biāo)示符。一個(gè)藍(lán)牙4.0的終端可以包含多個(gè)Service潘拱,一個(gè)Service可以包含多個(gè)Characteristic疹鳄,一個(gè)Characteristic包含一個(gè)Value和多個(gè)Descriptor,一個(gè)Descriptor包含一個(gè)Value芦岂。一般來說瘪弓,Characteristic是手機(jī)與BLE終端交換數(shù)據(jù)的關(guān)鍵,Characteristic有跟權(quán)限相關(guān)的字段禽最,如Property腺怯,Property有讀寫等各種屬性,如Notify川无、Read呛占、Write、WriteWithoutResponse懦趋。(引自:Android BLE開發(fā)之Android手機(jī)與BLE終端通信)

利用CoreBluetooth框架晾虑,我們可以輕松實(shí)現(xiàn)兩個(gè)iOS設(shè)備、iOS設(shè)備與非iOS藍(lán)牙設(shè)備的交互愕够。要注意的一點(diǎn)是目前這個(gè)框架只能支持藍(lán)牙4.0BLE標(biāo)準(zhǔn)走贪,所以對(duì)硬件上是有一定要求的,iPhone 4S及以后的設(shè)備惑芭,第三代iPad及以后的設(shè)備是支持這一標(biāo)準(zhǔn)的坠狡。

  • 由于項(xiàng)目需要,基于React Native 開發(fā)的App要跟BLE藍(lán)牙設(shè)備通信遂跟。
    js.coach上搜索React Native BLE藍(lán)牙組件逃沿,只找到三個(gè)組件:
    1. react-native-ble-plx文檔閱讀起來有點(diǎn)難度婴渡,但API很豐富,相比react-native-ble-manager 顯的比較專業(yè)凯亮。(PS:這個(gè)組件的ios環(huán)境配置比較容易出錯(cuò)边臼,我試用了這個(gè)組件并寫了一個(gè)demo,代碼已上傳到github : demo源碼地址)
    1. react-native-ble:由Node.js BLE移植而成假消,而且久未更新柠并,能不能適配最新React Native版本還是個(gè)問題,沒有深入研究富拗。
      綜上分析臼予,我當(dāng)初選擇的是react-native-ble-manager,組件的安裝啃沪、配置看官方文檔即可粘拾。
      PS:由于react-native-ble-manager更新比較頻繁,本教程最初是基于3.2.1版本編寫创千,由于版本跨度比較大缰雇,導(dǎo)致demo出現(xiàn)了一些問題,現(xiàn)已將代碼和文章教程全部更新到6.2.4版本追驴,如后面的版本沒有及時(shí)更新適配械哟,自己也可以根據(jù)官方文檔作出相對(duì)應(yīng)的更改,但通信原理和步驟是不變的氯檐。
      image.png

項(xiàng)目初始化

import BleManager from 'react-native-blemanager';

const BleManagerModule = NativeModules.BleManager;
const bleManagerEmitter = new NativeEventEmitter(BleManagerModule);

初步運(yùn)行-然后打開藍(lán)牙-點(diǎn)擊打開scan Bluetooth

//掃描可用設(shè)備戒良,5秒后結(jié)束 
BleManager.scan([], 5, true)
    .then(() => {
        console.log('Scan started');
    })
    .catch( (err)=>{
        console.log('Scan started fail');
    });

//停止掃描
BleManager.stopScan()
    .then(() => {
        console.log('Scan stopped');
    })
    .catch( (err)=>{
        console.log('Scan stopped fail',err);
    });

掃描后的列表


image.png

這時(shí)候就是選擇想連接的藍(lán)牙了
首先我們要添加相應(yīng)的監(jiān)聽器

//搜索到一個(gè)新設(shè)備監(jiān)聽
bleManagerEmitter.addListener('BleManagerDiscoverPeripheral', (data) => {
    console.log('BleManagerDiscoverPeripheral:', data);
    let id;  //藍(lán)牙連接id
    let macAddress;  //藍(lán)牙Mac地址            
    if(Platform.OS == 'android'){
        macAddress = data.id;
        id = macAddress;
    }else{  
        //ios連接時(shí)不需要用到Mac地址,但跨平臺(tái)識(shí)別是否是同一設(shè)備時(shí)需要Mac地址
        //如果廣播攜帶有Mac地址冠摄,ios可通過廣播0x18獲取藍(lán)牙Mac地址糯崎,
        macAddress = getMacAddressFromIOS(data);
        id = data.id;
    }            
});

//搜索結(jié)束監(jiān)聽
bleManagerEmitter.addListener('BleManagerStopScan', () => {
     console.log('BleManagerStopScan:','Scanning is stopped');      
    //搜索結(jié)束后,獲取搜索到的藍(lán)牙設(shè)備列表河泳,如監(jiān)聽了BleManagerDiscoverPeripheral,可省去這個(gè)步驟
    BleManager.getDiscoveredPeripherals([])
       .then((peripheralsArray) => {
           console.log('Discovered peripherals: ', peripheralsArray);
       });
});

/** ios系統(tǒng)從藍(lán)牙廣播信息中獲取藍(lán)牙MAC地址 */
getMacAddressFromIOS(data){
    let macAddressInAdvertising = data.advertising.kCBAdvDataManufacturerMacAddress;
    //為undefined代表此藍(lán)牙廣播信息里不包括Mac地址
    if(!macAddressInAdvertising){  
        return;
    }
    macAddressInAdvertising = macAddressInAdvertising.replace("<","").replace(">","").replace(" ","");
    if(macAddressInAdvertising != undefined && macAddressInAdvertising != null && macAddressInAdvertising != '') {
    macAddressInAdvertising = swapEndianWithColon(macAddressInAdvertising);
    }
    return macAddressInAdvertising;
}

/**
* ios從廣播中獲取的mac地址進(jìn)行大小端格式互換沃呢,并加上冒號(hào):
* @param str         010000CAEA80
* @returns string    80:EA:CA:00:00:01
*/
swapEndianWithColon(str){
    let format = '';
    let len = str.length;
    for(let j = 2; j <= len; j = j + 2){
        format += str.substring(len-j, len-(j-2));
        if(j != len) {
            format += ":";
        }
    }
    return format.toUpperCase();
}

然后就是連接
android使用Mac地址與藍(lán)牙連接,ios使用UUID與藍(lán)牙連接

//連接藍(lán)牙
BleManager.connect(id)
   .then(() => {
       console.log('Connected');
   })
   .catch((error) => {
       console.log('Connected error:',error);
   });

//斷開藍(lán)牙連接
BleManager.disconnect(id)
    .then( () => {
        console.log('Disconnected');
    })
    .catch( (error) => {
        console.log('Disconnected error:',error);
    });

添加相應(yīng)的監(jiān)聽器

//藍(lán)牙設(shè)備已連接監(jiān)聽
bleManagerEmitter.addListener('BleManagerConnectPeripheral', (args) => {
    log('BleManagerConnectPeripheral:', args);
});

//藍(lán)牙設(shè)備已斷開連接監(jiān)聽
bleManagerEmitter.addListener('BleManagerDisconnectPeripheral', (args) => {
    console.log('BleManagerDisconnectPeripheral:', args);
});
image.png

藍(lán)牙連接后會(huì)顯示該設(shè)備的具體信息拆挥,android平臺(tái)下連接成功后返回的數(shù)據(jù)如下:

{ characteristics:
  [ { properties: { Read: 'Read' },
       characteristic: '2a00',
       service: '1800' },
     { properties: { Read: 'Read' },
       characteristic: '2a01',
       service: '1800' },
     { properties: { Write: 'Write', Read: 'Read' },
       characteristic: '2a02',
       service: '1800' },
     { properties: { Read: 'Read' },
       characteristic: '2a04',
       service: '1800' },
     { descriptors: [ { value: null, uuid: '2902' } ],
       properties: { Indicate: 'Indicate', Read: 'Read' },
       characteristic: '2a05',
       service: '1801' },
     { descriptors: [ { value: null, uuid: '2902' }, { value: null, uuid: '2901' } ],
       properties: { Notify: 'Notify' },
       characteristic: '0783b03e-8535-b5a0-7140-a304d2495cb8',
       service: '0783b03e-8535-b5a0-7140-a304d2495cb7' },
     { descriptors: [ { value: null, uuid: '2902' }, { value: null, uuid: '2901' } ],
       properties: { WriteWithoutResponse: 'WriteWithoutResponse' },
       characteristic: '0783b03e-8535-b5a0-7140-a304d2495cba',
       service: '0783b03e-8535-b5a0-7140-a304d2495cb7' },
      { descriptors: [ { value: null, uuid: '2902' }, { value: null, uuid: '2901' } ],
        properties:
        { Notify: 'Notify',
           WriteWithoutResponse: 'WriteWithoutResponse',
           Read: 'Read' },
        characteristic: '0783b03e-8535-b5a0-7140-a304d2495cb9',
        service: '0783b03e-8535-b5a0-7140-a304d2495cb7' } ],
  services:
  [ { uuid: '1800' },
    { uuid: '1801' },
    { uuid: '0783b03e-8535-b5a0-7140-a304d2495cb7' } ],
  rssi: -46,
  advertising:{ data: 'AgEGEQe3XEnSBKNAcaC1NYU+sIMHCQlQRVAtUEVOLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=',CDVType: 'ArrayBuffer' },
  id: '00:CD:FF:00:22:2D',
  name: 'PEP-HC001' 
}

ios平臺(tái)下連接成功后返回的數(shù)據(jù)如下:

{ name: 'PEP-HC001',
  id: '64319987-E97B-46C0-91AE-261E93EADBFD',
  advertising: 
   { kCBAdvDataLocalName: 'PEP-HC001',
     kCBAdvDataIsConnectable: true,
     kCBAdvDataServiceUUIDs: [ '0783' ],
     kCBAdvDataManufacturerMacAddress: '<472200ff cd00>',
     kCBAdvDataManufacturerData: { CDVType: 'ArrayBuffer', data: 'RyIA/80A' } },
  services: [ '0783B03E-8535-B5A0-7140-A304D2495CB7' ],
  characteristics: 
   [ { service: '0783B03E-8535-B5A0-7140-A304D2495CB7',
       isNotifying: false,
       characteristic: '0783B03E-8535-B5A0-7140-A304D2495CB8',
       properties: [ 'Notify' ] },
     { service: '0783B03E-8535-B5A0-7140-A304D2495CB7',
       isNotifying: false,
       characteristic: '0783B03E-8535-B5A0-7140-A304D2495CBA',
       properties: [ 'WriteWithoutResponse' ] },
     { service: '0783B03E-8535-B5A0-7140-A304D2495CB7',
       isNotifying: false,
       characteristic: '0783B03E-8535-B5A0-7140-A304D2495CB9',
       properties: [ 'Read', 'WriteWithoutResponse', 'Notify' ] } ],
  rssi: -35 }

獲取Service和Characteristic

BLE分為三部分Service(服務(wù))薄霜、Characteristic(特征)、Descriptor(描述符)纸兔,這三部分都由UUID作為唯一標(biāo)示符惰瓜。一個(gè)藍(lán)牙4.0的終端可以包含多個(gè)Service,一個(gè)Service可以包含多個(gè)Characteristic崎坊,一個(gè)Characteristic包含一個(gè)Value和多個(gè)Descriptor奈揍,一個(gè)Descriptor包含一個(gè)Value。一般來說另患,Characteristic是手機(jī)與BLE終端交換數(shù)據(jù)的關(guān)鍵昆箕,Characteristic有跟權(quán)限相關(guān)的字段为严,如Property,Property有讀寫等各種屬性话原,如Notify繁仁、Read黄虱、Write捻浦、WriteWithoutResponse朱灿。(引自:Android BLE開發(fā)之Android手機(jī)與BLE終端通信)

Service

一個(gè)低功耗藍(lán)牙設(shè)備可以定義多個(gè)Service, Service可以理解為一個(gè)功能的集合盗扒。設(shè)備中每一個(gè)不同的 Service 都有一個(gè) 128 bit 的 UUID 作為這個(gè) Service 的獨(dú)立標(biāo)志侣灶。藍(lán)牙核心規(guī)范制定了兩種不同的UUID褥影,一種是基本的UUID伪阶,一種是代替基本UUID的16位UUID。所有的藍(lán)牙技術(shù)聯(lián)盟定義UUID共用了一個(gè)基本的UUID:
0x0000xxxx-0000-1000-8000-00805F9B34FB
為了進(jìn)一步簡(jiǎn)化基本UUID斟湃,每一個(gè)藍(lán)牙技術(shù)聯(lián)盟定義的屬性有一個(gè)唯一的16位UUID凝赛,以代替上面的基本UUID的”x”部分墓猎。例如毙沾,心率測(cè)量特性使用0X2A37作為它的16位UUID左胞,因此它完整的128位UUID為:
0x00002A37-0000-1000-8000-00805F9B34FB(引自:Android BLE 藍(lán)牙開發(fā)入門

Characteristic

在 Service 下面烤宙,又包括了許多的獨(dú)立數(shù)據(jù)項(xiàng)躺枕,我們把這些獨(dú)立的數(shù)據(jù)項(xiàng)稱作 Characteristic拐云。同樣的慨丐,每一個(gè) Characteristic 也有一個(gè)唯一的 UUID 作為標(biāo)識(shí)符房揭。建立藍(lán)牙連接后捅暴,我們說的通過藍(lán)牙發(fā)送數(shù)據(jù)給外圍設(shè)備就是往這些 Characteristic 中的 Value 字段寫入數(shù)據(jù)蓬痒;外圍設(shè)備發(fā)送數(shù)據(jù)給手機(jī)就是監(jiān)聽這些 Charateristic 中的 Value 字段有沒有變化梧奢,如果發(fā)生了變化亲轨,手機(jī)的 BLE API 就會(huì)收到一個(gè)監(jiān)聽的回調(diào)惦蚊。(引自:Android BLE 藍(lán)牙開發(fā)入門

藍(lán)牙連接成功后蹦锋,需要調(diào)用retrieveServices方法獲取Notify莉掂、Read憎妙、WriteserviceUUIDcharacteristicUUID作為參數(shù)來跟藍(lán)牙進(jìn)一步通信

//獲取藍(lán)牙Service和Characteristics
BleManager.retrieveServices(peripheralId)
    .then((peripheralInfo) => {
        this.getUUID();
        console.log('Peripheral info:', peripheralInfo);
    });  

peripheralInfo下的characteristics字段值是一個(gè)特征數(shù)組尚氛,每一項(xiàng)代表一個(gè)特征通道阅嘶,找到properties中包含有Notify讯柔、Read魂迄、Write捣炬、WriteWithoutResponse屬性的那一項(xiàng)湿酸,其service和characteristic即是我們需要的參數(shù)推溃。
PS:serviceUUID和characteristicUUID標(biāo)準(zhǔn)格式為XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX的128bit的UUID铁坎。所以需要將獲到的’XXXX’格式的UUID轉(zhuǎn)換為標(biāo)準(zhǔn)的128bit的UUID格式才可能進(jìn)行通信硬萍。
不同的藍(lán)牙設(shè)備襟铭,可能有多個(gè)特征通道包含Notify寒砖、Read哩都、Write漠嵌、WriteWithoutResponse屬性值儒鹿,那每個(gè)通道屬性的功能可能會(huì)不一樣约炎,應(yīng)根據(jù)具體的藍(lán)牙設(shè)備選擇符合我們要求的特征通道圾浅。有些可能不包含Notify狸捕、Read灸拍、Write鸡岗、WriteWithoutResponse中的一個(gè)或多個(gè)屬性纤房,具體跟藍(lán)牙硬件有關(guān)系,一般有Notify和Write兩個(gè)屬性就可以滿足通信的要求了碰煌。

//獲取Notify芦圾、Read个少、Write夜焦、WriteWithoutResponse的serviceUUID和characteristicUUID
getUUID(peripheralInfo){       
    this.readServiceUUID = [];
    this.readCharacteristicUUID = [];   
    this.writeWithResponseServiceUUID = [];
    this.writeWithResponseCharacteristicUUID = [];
    this.writeWithoutResponseServiceUUID = [];
    this.writeWithoutResponseCharacteristicUUID = [];
    this.nofityServiceUUID = [];
    this.nofityCharacteristicUUID = [];  
    for(let item of peripheralInfo.characteristics){  
        item.service = this.fullUUID(item.service);
        item.characteristic = this.fullUUID(item.characteristic); 
        if(Platform.OS == 'android'){  
             if(item.properties.Notify == 'Notify'){    
                 this.nofityServiceUUID.push(item.service);     
                 this.nofityCharacteristicUUID.push(item.characteristic);
             }
             if(item.properties.Read == 'Read'){
                 this.readServiceUUID.push(item.service);
                 this.readCharacteristicUUID.push(item.characteristic);
             }
             if(item.properties.Write == 'Write'){
                 this.writeWithResponseServiceUUID.push(item.service);
                 this.writeWithResponseCharacteristicUUID.push(item.characteristic);
             }
             if(item.properties.Write == 'WriteWithoutResponse'){
                 this.writeWithoutResponseServiceUUID.push(item.service);
                 this.writeWithoutResponseCharacteristicUUID.push(item.characteristic);
             }               
         }else{  //ios
             for(let property of item.properties){
                 if(property == 'Notify'){
                     this.nofityServiceUUID.push(item.service);
                     this.nofityCharacteristicUUID.push(item.characteristic);
                 }
                 if(property == 'Read'){
                     this.readServiceUUID.push(item.service);
                     this.readCharacteristicUUID.push(item.characteristic);
                 }
                 if(property == 'Write'){
                     this.writeWithResponseServiceUUID.push(item.service);
                     this.writeWithResponseCharacteristicUUID.push(item.characteristic);
                 }
                 if(property == 'WriteWithoutResponse'){
                     this.writeWithoutResponseServiceUUID.push(item.service);
                     this.writeWithoutResponseCharacteristicUUID.push(item.characteristic);
                 }                  
             }
         }
     }
}
/**
 * Converts UUID to full 128bit.
 * 
 * @param {UUID} uuid 16bit, 32bit or 128bit UUID.
 * @returns {UUID} 128bit UUID.
 */
 fullUUID(uuid) {
     if (uuid.length === 4){
         return '0000' + uuid.toUpperCase() + '-0000-1000-8000-00805F9B34FB'
      }             
     if (uuid.length === 8) {
         return uuid.toUpperCase() + '-0000-1000-8000-00805F9B34FB'
      }            
      return uuid.toUpperCase()
  }  

通知監(jiān)聽

藍(lán)牙連接成功萎津,當(dāng)我們向設(shè)備寫入數(shù)據(jù)成功并且指令也正確的話锉屈,我們就會(huì)得到設(shè)備通過藍(lán)牙發(fā)送給APP的響應(yīng)數(shù)據(jù)颈渊,實(shí)現(xiàn)這一響應(yīng)的前提是需要開啟通知監(jiān)聽儡炼,這樣就能在回調(diào)中監(jiān)聽到數(shù)據(jù)返回了乌询。

//打開通知
BleManager.startNotification(peripheralId, this.nofityServiceUUID[0], this.nofityCharacteristicUUID[0])
    .then(() => {
        console.log('Notification started');
    })
    .catch((error) => {
        console.log('Notification error:',error);
    });

//關(guān)閉通知
BleManager.stopNotification(peripheralId, this.nofityServiceUUID[0], this.nofityCharacteristicUUID[0])
   .then(() => {
        console.log('stopNotification success!');
    })
    .catch((error) => {
        console.log('stopNotification error:',error);
    });

添加相應(yīng)的監(jiān)聽器

//接收到新數(shù)據(jù)監(jiān)聽,開啟通知成功后鹃共,該監(jiān)聽才可接收到數(shù)據(jù)
bleManagerEmitter.addListener('BleManagerDidUpdateValueForCharacteristic', (data) => {
    //ios接收到的是小寫的16進(jìn)制晶衷,android接收的是大寫的16進(jìn)制,統(tǒng)一轉(zhuǎn)化為大寫16進(jìn)制
    let value = data.value.toUpperCase();               
    console.log('BluetoothUpdateValue', value);
});
讀數(shù)據(jù)
//讀取藍(lán)牙數(shù)據(jù)
BleManager.read(peripheralId, this.readServiceUUID[0], this.readCharacteristicUUID[0])
     .then((data) => {
         console.log('Read: ',data);                    
     })
     .catch((error) => {
         console.log(error);
     });
寫數(shù)據(jù)

寫數(shù)據(jù)有兩個(gè)方法,write和writeWithoutResponse锹漱,大部分藍(lán)牙都有write屬性哥牍,而writeWithoutResponse屬性比較少嗅辣。

寫數(shù)據(jù)注意事項(xiàng):

BLE藍(lán)牙傳輸速率比經(jīng)典藍(lán)牙慢的多辩诞,而且GATT底層需要封裝7個(gè)字節(jié)的額外協(xié)議數(shù)據(jù)译暂, 即一次最多只能傳輸20字節(jié)外永,所以一般選用16進(jìn)制數(shù)據(jù)來提高單次數(shù)據(jù)傳輸量伯顶。而且如果發(fā)送的數(shù)據(jù)大于20字節(jié)的話要分包發(fā)送,例如要發(fā)送30個(gè)字節(jié)灶体,可以先write(前20個(gè)字節(jié))蝎抽,等這次寫入成功后(或者開啟線程sleep幾十毫秒后)樟结,再write(后面10個(gè)字節(jié))瓢宦。

發(fā)送的時(shí)候需要先將其裝載到byte[]數(shù)組中驮履,例如要發(fā)送FE FD 01 0A FC FB這個(gè)指令,需要把它轉(zhuǎn)化為
new byte[] { (byte) 0xFE,(byte) 0xFD,0x01,0x0A,(byte) 0xFC,(byte) 0xFB }
這樣去發(fā)送座每。

這是官方最新的例子
import { stringToBytes } from 'convert-string';
//發(fā)送給藍(lán)牙的指令
let command = 'FEFD010AFCFB'; 
//將字符串轉(zhuǎn)換成字節(jié)數(shù)組傳送峭梳,stringToByte方法將每個(gè)16進(jìn)制的字符轉(zhuǎn)換成指定位置的字符的 Unicode編碼葱椭,這個(gè)返回值是 0 - 65535 之間的整數(shù)
let bytes = stringToBytes(command);  
// 轉(zhuǎn)換后為:[ 70, 69, 70, 68, 48, 49, 48, 65, 70, 67, 70, 66 ]

5.0.1之前的版本寫數(shù)據(jù)是需要經(jīng)過base64編碼轉(zhuǎn)換后發(fā)送的孵运,5.0.1之后的版本雖然能發(fā)送byte[]治笨,但卻是通過stringToBytes將其轉(zhuǎn)化為Unicode編碼位置的byte[]旷赖,然而藍(lán)牙那邊只能接收16進(jìn)制的byte[]數(shù)據(jù)等孵。帶著這個(gè)疑問俯萌,我提了一個(gè)issue給作者咐熙,問題是:Can I send hexadecimal data to BLE instead of base64 format?然而作者卻沒有
給我一個(gè)滿意的解決辦法棋恼。所以,自己動(dòng)手對(duì)源碼做一些小小的修改以符合我們的實(shí)際需求吧嘲玫。

android源碼修改

修改的源文件只有一個(gè):在react-native-ble-manager\android\src\main\java\it\innove目錄下的BleManager.java文件去团。
點(diǎn)擊跳轉(zhuǎn)到修改后的BleManager.java文件

BleManager.java文件

  • 增加的方法
/** 16進(jìn)制字符串轉(zhuǎn)換成16進(jìn)制byte數(shù)組昼汗,每?jī)晌晦D(zhuǎn)換 */
public static byte[] strToHexByteArray(String str){
    byte[] hexByte = new byte[str.length()/2];
    for(int i = 0,j = 0; i < str.length(); i = i + 2,j++){
        hexByte[j] = (byte)Integer.parseInt(str.substring(i,i+2), 16);
    }
    return hexByte;
}

寫到這里 藍(lán)牙打印就已經(jīng)成功了 貼出我所有的代碼顷窒,藍(lán)牙打印不需要配對(duì) 連接上了直接發(fā)送指令就可以了

test(peripheral) {
        console.log('jinlai')
        if (peripheral){
            if (peripheral.connected){
                BleManager.disconnect(peripheral.id);
            }else{
                BleManager.connect(peripheral.id).then(() => {
                    let peripherals = this.state.peripherals;
                    let p = peripherals.get(peripheral.id);
                    if (p) {
                        p.connected = true;
                        peripherals.set(peripheral.id, p);
                        this.setState({peripherals});
                    }
                    console.log('Connected to ' + peripheral.id);


                    setTimeout(() => {

                        /* Test read current RSSI value
                        BleManager.retrieveServices(peripheral.id).then((peripheralData) => {
                          console.log('Retrieved peripheral services', peripheralData);

                          BleManager.readRSSI(peripheral.id).then((rssi) => {
                            console.log('Retrieved actual RSSI value', rssi);
                          });
                        });*/

                        // Test using bleno's pizza example
                        // https://github.com/sandeepmistry/bleno/tree/master/examples/pizza
                        BleManager.retrieveServices(peripheral.id).then((peripheralInfo) => {

                            this.getUUID(peripheralInfo)

                            console.log('peripheralInfo =',peripheralInfo);
                            var service = this.nofityServiceUUID[0];
                            // var bakeCharacteristic = '11C5ABAA-AC2D-458D-B12E-260DCB629AE4';
                            var crustCharacteristic = this.nofityCharacteristicUUID[0];

                            setTimeout(() => {
                                //打開通知
                                console.log('peripheral.id ='+peripheral.id)
                                console.log('bakeCharacteristic='+this.nofityServiceUUID[0])
                                console.log('crustCharacteristic='+this.nofityCharacteristicUUID[0])
                                BleManager.startNotification(peripheral.id,  this.nofityServiceUUID[0], this.nofityCharacteristicUUID[0]).then(() => {
                                    console.log('Started notification on ' + peripheral.id);
                                   //寫入
                                    setTimeout(() => {
                                        //1.id 2.寫入的UDID
                                        BleManager.write(peripheral.id, this.writeWithResponseServiceUUID[0], this.writeWithResponseCharacteristicUUID[0], [0]).then(() => {
                                            console.log('Writed NORMAL crust');
                                            BleManager.write(peripheral.id, this.writeWithResponseServiceUUID[0], this.writeWithResponseCharacteristicUUID[0], [1,3]).then(() => {
                                                console.log('Writed 351 temperature, the pizza should be BAKED');
                                                /*
                                                var PizzaBakeResult = {
                                                  HALF_BAKED: 0,
                                                  BAKED:      1,
                                                  CRISPY:     2,
                                                  BURNT:      3,
                                                  ON_FIRE:    4
                                                };*/
                                            });
                                        });

                                    }, 500);
                                }).catch((error) => {
                                    console.log('Notification error', error);
                                });
                            }, 200);
                        });

                    }, 900);
                }).catch((error) => {
                    console.log('Connection error', error);
                });
            }
        }
    }
image.png

看到這里就知道[0],[1,3]是什么意思了把谓着!他代表的是data赊锚,數(shù)據(jù)必須以數(shù)組形式 否則會(huì)報(bào)錯(cuò)舷蒲,不懂的 可以私聊筆者

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末系瓢,一起剝皮案震驚了整個(gè)濱河市夷陋,隨后出現(xiàn)的幾起案子骗绕,更是在濱河造成了極大的恐慌,老刑警劉巖荆忍,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刹枉,死亡現(xiàn)場(chǎng)離奇詭異微宝,居然都是意外死亡虎眨,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門凄敢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涝缝,“玉大人蒙袍,你說我怎么就攤上這事害幅。” “怎么了狠怨?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵佣赖,是天一觀的道長(zhǎng)憎蛤。 經(jīng)常有香客問我俩檬,道長(zhǎng)棚辽,這世上最難降的妖魔是什么冰肴? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任联逻,我火速辦了婚禮包归,結(jié)果婚禮上攀细,老公的妹妹穿的比我還像新娘。我一直安慰自己境钟,他們只是感情好慨削,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布缚态。 她就那樣靜靜地躺著玫芦,像睡著了一般本辐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上老虫,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天祈匙,我揣著相機(jī)與錄音夺欲,去河邊找鬼洁闰。 笑死扑眉,一個(gè)胖子當(dāng)著我的面吹牛腰素,可吹牛的內(nèi)容都是我干的弓千。 我是一名探鬼主播献起,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼呆抑!你這毒婦竟也來了鹊碍?” 一聲冷哼從身側(cè)響起侈咕,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤耀销,失蹤者是張志新(化名)和其女友劉穎树姨,沒想到半個(gè)月后帽揪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辅斟,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡查邢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年扰藕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了邓深。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芥备。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡萌壳,死狀恐怖袱瓮,靈堂內(nèi)的尸體忽然破棺而出尺借,到底是詐尸還是另有隱情褐望,我是刑警寧澤瘫里,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布谨读,位于F島的核電站劳殖,受9級(jí)特大地震影響拨脉,放射性物質(zhì)發(fā)生泄漏哆姻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一玫膀、第九天 我趴在偏房一處隱蔽的房頂上張望矛缨。 院中可真熱鬧,春花似錦帖旨、人聲如沸箕昭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽落竹。三九已至,卻和暖如春货抄,著一層夾襖步出監(jiān)牢的瞬間桨武,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纫雁,地道東北人忌愚。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓腊徙,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親胶逢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • ## 用到的工具: react-native react-native-ble-manager iconv-lit...
    404_454a閱讀 4,342評(píng)論 2 1
  • 在寫這個(gè)博客之前吴菠,空余時(shí)間抽看了近一個(gè)月的文檔和Demo,系統(tǒng)給的解釋很詳細(xì)榨乎,接口也比較實(shí)用,唯獨(dú)有一點(diǎn)隐绵,對(duì)于設(shè)備...
    木易林1閱讀 3,345評(píng)論 3 4
  • 前言 最近比較忙恬偷,兩三周沒有更新簡(jiǎn)書了竣付,公司正好在做藍(lán)牙BLE的項(xiàng)目,本來覺得挺簡(jiǎn)單的東西從網(wǎng)上找了個(gè)框架惹恃,就咔咔...
    肖邦kaka閱讀 75,560評(píng)論 34 88
  • ? 在藍(lán)牙開發(fā)中,有些情況是不需要連接的浙值,只要外設(shè)廣播自己的數(shù)據(jù)即可负蚊,例如蘋果的ibeacon。自An...
    大棋17閱讀 34,136評(píng)論 27 27
  • 偷走太陽的氣味回家 我看不見外面哨坪, 卻在享受著一種遼闊, 我也承認(rèn)金顿,我寫的每一字嫂拴,都在呼喚一種分享, 如果現(xiàn)在面前...
    麥子和花閱讀 138評(píng)論 0 0