Не удается подключить ноутбук с Windows с адаптером BLE к устройству BLE
Я пытаюсь настроить демонстрацию на основе Nodejs на моем ноутбуке с Windows с дополнительным адаптером BLE для подключения моего ноутбука к другому устройству BLE (Anki Overdrive). Я видел эту демонстрацию в Интернете, и мне было любопытно, если бы я мог настроить ее тоже. Я следовал всем инструкциям, но потерпел неудачу, потому что оригинальная демонстрация была сделана с MacBook, который использует другой тип встроенного адаптера BLE. Я тоже попробовал его на MacBook, и он работал более чем нормально, но я бы хотел настроить его на устройстве Windows. Я прикрепил часть кода Nodejs, который должен возвращать периферийный идентификатор устройства BLE:
//UUID for Anki Overdrive Car be15beef6186407e83810bd89c4d8df4
var noble = require('noble');
noble.on('stateChange', function(state) {
if (state === 'poweredOn') {
noble.startScanning();
setTimeout(function() {
noble.stopScanning();
process.exit(0);
}, 2000);
} else {
noble.stopScanning();
}
});
noble.on('discover', function(peripheral) {
var serviceUuids = JSON.stringify(peripheral.advertisement.serviceUuids);
if(serviceUuids.indexOf("be15beef6186407e83810bd89c4d8df4") > -1) {
console.log('Car discovered. ID: ' + peripheral.id);
}
});
До сих пор я понял, что встроенный BLE от MacBook отправляет обратно идентификатор периферийного устройства. Для сравнения, адаптер BLE Windows возвращает только MAC-адрес другого устройства BLE. Может кто-нибудь мне помочь? Я действительно понятия не имею, что я мог сделать, чтобы решить проблему.
Для дальнейшего понимания я предоставил ссылку на оригинальную демоверсию, которая была установлена на MacBook. https://github.com/IBM-Bluemix/node-mqtt-for-anki-overdrive.
Спасибо заранее.
1 ответ
Работа с автомобилями Anki Overdrive всегда доставляет массу хлопот.
Следующие фрагменты показывают соответствующий код относительно вашего вопроса.
Отказ от ответственности: я создал WIP Anki Overdrive SDK [1], который пытается облегчить жизнь (фрагменты копируются оттуда)
- Сканирование для устройств с использованием благородных (scanner.js)
module.exports = class Scanner {
constructor() {
this.peripherals = []
this.state = undefined
}
/**
* Set up noble listeners. Mandatory before scan.
*/
async setUpNoble () {
try {
await noble.on('discover', (peripheral) => {
const isAnkiDevice = function(peripheral) {
const serviceUuids = JSON.stringify(peripheral.advertisement.serviceUuids)
return (serviceUuids.indexOf("be15beef6186407e83810bd89c4d8df4") > -1)
}
if(isAnkiDevice(peripheral)) {
this.peripherals.push(peripheral)
}
})
await noble.on('stateChange', (status) => {
this.state = status
})
} catch (err) {
throw new Error(err)
}
}
/**
* Scans for devices and returns peripherals. Scans for 20 seconds before stopping.
*/
async scan() {
try {
let that = this
await waitUntil(() => {
return (that.state === 'poweredOn')
}, 20000)
console.log('Starting to scan...')
return await waitUntil(() => {
noble.stopScanning()
if(that.peripherals.length <= 0) {
console.log('Scanning...')
noble.startScanning()
} else {
console.log('Found ' + that.peripherals.length + ' devices.')
return that.peripherals
}
}, 20000, 4000)
} catch (err) {
throw new Error(err)
}
}
}
- Запустить сканирование и создать объект устройства (anki.js)
async scanDevices() {
try {
const that = this
const scanner = new Scanner()
scanner.setUpNoble()
const peripherals = await scanner.scan()
const devices = peripherals.map((peripheral) => {
return new Device(peripheral)
})
return devices
} catch (err) {
throw new Error(err)
}
}
- Установите id и serviceUUids из периферийного устройства в конструкторе объекта Device (device.js)
module.exports = class AnkiDevice {
constructor (peripheral) {
this.peripheral = peripheral
this.id = peripheral.uuid
this.serviceUuids = JSON.stringify(peripheral.advertisement.serviceUuids)
....
- Подключиться к машине (device.js)
connect() {
try {
const that = this
console.log('Connecting with ' + this.id)
const getService = function(services){
if (os.platform() === 'win32' || os.platform() === 'linux') {
return services[2]
} else {
return service[0] // macOS
}
}
const setCharacteristics = function(characteristics) {
for(let i in characteristics) {
const characteristic = characteristics[i]
if (characteristic.uuid == 'be15bee06186407e83810bd89c4d8df4') {
that.readCharacteristic = characteristic
}
if (characteristic.uuid == 'be15bee16186407e83810bd89c4d8df4') {
that.writeCharacteristic = characteristic
}
}
}
const onConnect = async function() {
const services = await that.peripheral.discoverServices([])
const service = await getService(services)
const characteristics = await service.discoverCharacteristics([])
await setCharacteristics(characteristics)
// Listen to own disconnect
that.peripheral.once('disconnect', () => {
mediator.private.emit('deviceDisconnected', this)
})
mediator.private.emit('deviceConnected', that)
}
this.peripheral.once('connect', onConnect)
this.peripheral.connect()
} catch(err) {
throw new Error(err)
}
}
- THEN: активировать режим SDK (device.js)
activateSDKMode() {
console.log('Activating SDKMode for ' + this.id)
const that = this
if(!this.isConnected) {
return new Error('Car is not connected yet.')
}
const message = coder.encodeSDKActivation()
this._writeMessage(message)
.then(() => {
mediator.private.emit('SDKModeOn', that)
})
}
- THEN: включите ведение журнала (device.js)
turnOnLogging() {
console.log('Turning logging on for ' + this.id)
let that = this
if(!that.isConnected) {
return new Error('Car is not connected yet.')
}
that.readCharacteristic.notify(true)
that.readCharacteristic.on('read', (data) => {
that._onMessage(data)
})
mediator.private.emit('loggingOn', that)
}