如何在 React Native 中使用小米手环 3 进行身份验证
How to authenticate with Mi Band 3 in React Native
几天来,我一直在努力寻找一种使用 React Native 对我的 Mi Band 3 进行身份验证的方法。我正在使用 react-native-ble-plx 来建立连接。我可以搜索附近的设备,甚至可以连接到手环,但是当我尝试调用某些服务或特性时,任何事情都会发生。
经过几个小时的搜索,我意识到问题可能出在身份验证上,所以我开始寻找它,但我找不到任何东西。我发现了一个与此类似的问题,但唯一的答案是 'do some googling',我做了...很多。
这是我现在拥有的
const connectToSelectedDevice = async() => {
try{
if(selectedDeviceId != 0 ){
manager.stopDeviceScan()
manager.connectToDevice(selectedDeviceId).then(async(device)=>{
const services = await device.discoverAllServicesAndCharacteristics()
device.monitorCharacteristicForService('0000fee0-0000-1000-8000-00805f9b34fb','0000ff0e-0000-1000-8000-00805f9b34fb',(error, characteristic) => {
if (error) {
console.error("Error at receiving data from device", error);
return
}
else {
console.log('monitor success')
console.log('monitor success' + characteristic.value);
this.state.messagesRecieved.push(characteristic.value)
}
})
device.writeCharacteristicWithResponseForService('0000fee0-0000-1000-8000-00805f9b34fb','0000ff0e-0000-1000-8000-00805f9b34fb','AQ==')
.then(characteristic => {
console.log("Successfully sent: " + characteristic.value)
return
})
.catch(err => {
console.log(err)
})
})
}
}
catch(error){
console.log(error);
}
}
想通了,这是我的解决方案
export const connectToDevice = async(selectedDeviceId,manager,resultFunction) => {
manager.stopDeviceScan(), // Since we found the desired device, we stop scanning for devices
manager.connectToDevice(selectedDeviceId).then(async(device)=>{ //Now we connect to the device
await device.discoverAllServicesAndCharacteristics() //Before doing anything, we need to discover the device's services and characteristics
let bluetoothKey = await store.getState().unitInfo.bluetoothKey // This is my 16 bytes key
device.writeCharacteristicWithoutResponseForService('0000fee1-0000-1000-8000-00805f9b34fb','00000009-0000-3512-2118-0009af100700',btoa('\x01\x00')) // STEP 1 ------ we send \x01\x00, converted to base64
.catch((e)=>{
console.log(e);
})
//Now, we monitor this characteristic, waiting for responses and dealing with them, but Step 2 is below this, because we need to be watching his response
device.monitorCharacteristicForService('0000fee1-0000-1000-8000-00805f9b34fb', '00000009-0000-3512-2118-0009af100700', (error, characteristic) => {
if(error){
console.log(error);
}
if(characteristic!= null){
console.log(characteristic)
if(characteristic.value == 'EAEB'){ // EAEB means that the band received the key, so we move to the next step and request the band's key
requestKey(device)
}
else if(characteristic.value == 'EAEC'){ // EAEC means the user didn't confirmed the pairing on the band
resultFunction(false)
}
else if(characteristic.value == 'EAMB'){ // EAMB means the pairing ocurred with success
resultFunction(device) // SUCCESS ------ We store the device object for further use
}
else if (characteristic.value == 'EAME'){ // Some error ocurred
device.cancelConnection()
}
else{ // STEP 4 ------ Happens when the band sends the key we requested
sendEncryptedKey(characteristic,bluetoothKey,device)
}
}
})
let connectionKey = concatArrayAndCommand([1,8],base64ToArrayBuffer(bluetoothKey))
device.writeCharacteristicWithoutResponseForService('0000fee1-0000-1000-8000-00805f9b34fb','00000009-0000-3512-2118-0009af100700',arrayToBase64(connectionKey)) // STEP 2 ------ We send \x01\x00 + our key on base64
.catch((e)=>{
console.log(e);
})
}, error => {
console.log(error)
resultFunction(false)
})
}
const requestKey = (device) =>{ //STEP 3 ------ Requesting band's key, will be watched by our monitor
device.writeCharacteristicWithoutResponseForService('0000fee1-0000-1000-8000-00805f9b34fb','00000009-0000-3512-2118-0009af100700',btoa('\x02\x00'))
.catch((e)=>{
console.log(e);
})
}
const sendEncryptedKey = async(characteristic,bluetoothKey,device) => { // STEP 5 ------ One of the most difficult ones, encrypting the band's key, using our key
let receivedKey = characteristic.value.substring(4) // First we remove the first 4 digits, other result code from the band
var receivedKeyInBytes = base64ToArrayBuffer(receivedKey)
var bluetoothKeyInBytes = base64ToArrayBuffer(bluetoothKey)
let encryptor = new aesjs.ModeOfOperation.ecb(bluetoothKeyInBytes);
let encryptedKeyInBytes = encryptor.encrypt(receivedKeyInBytes);
let finalValue = concatArrayAndCommand([3,0],encryptedKeyInBytes)
// After encrypting, we send \x03\x00 + the encoded key
device.writeCharacteristicWithoutResponseForService('0000fee1-0000-1000-8000-00805f9b34fb','00000009-0000-3512-2118-0009af100700',arrayToBase64(finalValue))
.catch((e)=>{
console.log(e)
})
}
几天来,我一直在努力寻找一种使用 React Native 对我的 Mi Band 3 进行身份验证的方法。我正在使用 react-native-ble-plx 来建立连接。我可以搜索附近的设备,甚至可以连接到手环,但是当我尝试调用某些服务或特性时,任何事情都会发生。
经过几个小时的搜索,我意识到问题可能出在身份验证上,所以我开始寻找它,但我找不到任何东西。我发现了一个与此类似的问题,但唯一的答案是 'do some googling',我做了...很多。
这是我现在拥有的
const connectToSelectedDevice = async() => {
try{
if(selectedDeviceId != 0 ){
manager.stopDeviceScan()
manager.connectToDevice(selectedDeviceId).then(async(device)=>{
const services = await device.discoverAllServicesAndCharacteristics()
device.monitorCharacteristicForService('0000fee0-0000-1000-8000-00805f9b34fb','0000ff0e-0000-1000-8000-00805f9b34fb',(error, characteristic) => {
if (error) {
console.error("Error at receiving data from device", error);
return
}
else {
console.log('monitor success')
console.log('monitor success' + characteristic.value);
this.state.messagesRecieved.push(characteristic.value)
}
})
device.writeCharacteristicWithResponseForService('0000fee0-0000-1000-8000-00805f9b34fb','0000ff0e-0000-1000-8000-00805f9b34fb','AQ==')
.then(characteristic => {
console.log("Successfully sent: " + characteristic.value)
return
})
.catch(err => {
console.log(err)
})
})
}
}
catch(error){
console.log(error);
}
}
想通了,这是我的解决方案
export const connectToDevice = async(selectedDeviceId,manager,resultFunction) => {
manager.stopDeviceScan(), // Since we found the desired device, we stop scanning for devices
manager.connectToDevice(selectedDeviceId).then(async(device)=>{ //Now we connect to the device
await device.discoverAllServicesAndCharacteristics() //Before doing anything, we need to discover the device's services and characteristics
let bluetoothKey = await store.getState().unitInfo.bluetoothKey // This is my 16 bytes key
device.writeCharacteristicWithoutResponseForService('0000fee1-0000-1000-8000-00805f9b34fb','00000009-0000-3512-2118-0009af100700',btoa('\x01\x00')) // STEP 1 ------ we send \x01\x00, converted to base64
.catch((e)=>{
console.log(e);
})
//Now, we monitor this characteristic, waiting for responses and dealing with them, but Step 2 is below this, because we need to be watching his response
device.monitorCharacteristicForService('0000fee1-0000-1000-8000-00805f9b34fb', '00000009-0000-3512-2118-0009af100700', (error, characteristic) => {
if(error){
console.log(error);
}
if(characteristic!= null){
console.log(characteristic)
if(characteristic.value == 'EAEB'){ // EAEB means that the band received the key, so we move to the next step and request the band's key
requestKey(device)
}
else if(characteristic.value == 'EAEC'){ // EAEC means the user didn't confirmed the pairing on the band
resultFunction(false)
}
else if(characteristic.value == 'EAMB'){ // EAMB means the pairing ocurred with success
resultFunction(device) // SUCCESS ------ We store the device object for further use
}
else if (characteristic.value == 'EAME'){ // Some error ocurred
device.cancelConnection()
}
else{ // STEP 4 ------ Happens when the band sends the key we requested
sendEncryptedKey(characteristic,bluetoothKey,device)
}
}
})
let connectionKey = concatArrayAndCommand([1,8],base64ToArrayBuffer(bluetoothKey))
device.writeCharacteristicWithoutResponseForService('0000fee1-0000-1000-8000-00805f9b34fb','00000009-0000-3512-2118-0009af100700',arrayToBase64(connectionKey)) // STEP 2 ------ We send \x01\x00 + our key on base64
.catch((e)=>{
console.log(e);
})
}, error => {
console.log(error)
resultFunction(false)
})
}
const requestKey = (device) =>{ //STEP 3 ------ Requesting band's key, will be watched by our monitor
device.writeCharacteristicWithoutResponseForService('0000fee1-0000-1000-8000-00805f9b34fb','00000009-0000-3512-2118-0009af100700',btoa('\x02\x00'))
.catch((e)=>{
console.log(e);
})
}
const sendEncryptedKey = async(characteristic,bluetoothKey,device) => { // STEP 5 ------ One of the most difficult ones, encrypting the band's key, using our key
let receivedKey = characteristic.value.substring(4) // First we remove the first 4 digits, other result code from the band
var receivedKeyInBytes = base64ToArrayBuffer(receivedKey)
var bluetoothKeyInBytes = base64ToArrayBuffer(bluetoothKey)
let encryptor = new aesjs.ModeOfOperation.ecb(bluetoothKeyInBytes);
let encryptedKeyInBytes = encryptor.encrypt(receivedKeyInBytes);
let finalValue = concatArrayAndCommand([3,0],encryptedKeyInBytes)
// After encrypting, we send \x03\x00 + the encoded key
device.writeCharacteristicWithoutResponseForService('0000fee1-0000-1000-8000-00805f9b34fb','00000009-0000-3512-2118-0009af100700',arrayToBase64(finalValue))
.catch((e)=>{
console.log(e)
})
}