Интерпретация / анализ данных с пульсометра Bluetooth (Cordova)
Я создаю приложение с использованием Cordova, которое требует интерпретации данных с монитора Bluetooth HR (способного записывать необработанные интервалы RR, такие как Polar H7). Я использую Cordova-Plugin-Ble-Central
Мне трудно разобраться в данных, полученных с монитора, несмотря на то, что я часто трачу в Интернете ответы и читаю спецификацию характеристики сердечного ритма Bluetooth.
Вот моя функция, которая запускается при каждом получении данных:
onData: function(buffer) {
console.log(buffer);
// var data8 = new Uint8Array(buffer);
var data16 = new Uint16Array(buffer);
var rrIntervals = data.slice(1);
for (i=0; i<rrIntervals.length; i++) {
rrInterval = rrIntervals[i];
heartRate.addReading(rrInterval); // process RR interval elsewhere
}
},
Когда я регистрирую данные, полученные в буфере, на консоль выводится следующее: вывод на консоль
Я знаю, как извлечь интервалы RR (выделено желтым цветом), но я не совсем понимаю, что представляют другие значения, что мне необходимо, поскольку пользователи могут подключаться к другим мониторам, которые не передают интервалы RR и т. Д.
Очень хотелось бы получить быстрое и понятное объяснение того, что означают полученные данные и как их анализировать. Например, какое число составляет поле флагов и как преобразовать его в двоичный файл для извлечения подполей (т. Е. Для проверки наличия интервалов RR - я знаю, что это определяется 5-м битом в поле флагов).
Плагин также заявляет, что "Необработанные данные передаются из собственного кода в обратный вызов успеха в виде ArrayBuffer", но я не знаю, как проверить флаги, чтобы определить, имеют ли данные от конкретного монитора HR 8 или 16-битный формат. Ниже приведен еще один консольный журнал, когда я создаю массивы Uint8 и Uint16 из полученных данных. Опять же, я выделил частоту сердечных сокращений и интервалы RR, но мне нужно знать, что представляют другие значения и как правильно их анализировать.
лог консоли с выводом Uint8 и Uint16
Весь код ниже:
var heartRateSpec = {
service: '180d',
measurement: '2a37'
};
var app = {
initialize: function() {
this.bindEvents();
},
bindEvents: function() {
document.addEventListener('deviceready', this.onDeviceReady, false);
},
onDeviceReady: function() {
app.scan();
},
scan: function() {
app.status("Scanning for Heart Rate Monitor");
var foundHeartRateMonitor = false;
function onScan(peripheral) {
// this is demo code, assume there is only one heart rate monitor
console.log("Found " + JSON.stringify(peripheral));
foundHeartRateMonitor = true;
ble.connect(peripheral.id, app.onConnect, app.onDisconnect);
}
function scanFailure(reason) {
alert("BLE Scan Failed");
}
ble.scan([heartRateSpec.service], 5, onScan, scanFailure);
setTimeout(function() {
if (!foundHeartRateMonitor) {
app.status("Did not find a heart rate monitor.");
}
}, 5000);
},
onConnect: function(peripheral) {
app.status("Connected to " + peripheral.id);
ble.startNotification(peripheral.id, heartRateSpec.service, heartRateSpec.measurement, app.onData, app.onError);
},
onDisconnect: function(reason) {
alert("Disconnectedz " + reason);
beatsPerMinute.innerHTML = "...";
app.status("Disconnected");
},
onData: function(buffer) {
var data = new Uint16Array(buffer);
if (heartRate.hasStarted() == false) {
heartRate.beginReading(Date.now());
} else {
var rrIntervals = data.slice(1);
for (i=0; i<rrIntervals.length; i++) {
rrInterval = rrIntervals[i];
heartRate.addReading(rrInterval);
}
}
},
onError: function(reason) {
alert("There was an error " + reason);
},
status: function(message) {
console.log(message);
statusDiv.innerHTML = message;
}
};
app.initialize();
Заранее большое спасибо за любую помощь или совет.
1 ответ
ОБНОВЛЕНИЕ для более глубокого объяснения проверьте этот пост, который я написал на предмете.
Я понял это - вот краткое объяснение для любого, кто сталкивается с подобной проблемой:
Данные, передаваемые в onData (буфер), являются просто двоичными данными, поэтому независимо от того, преобразуем ли мы их в массив Uint8Array или Uint16Array, он все равно представляет те же двоичные данные. Конечно, целые числа в Uint16, вероятно, будут больше, поскольку они содержат 16 бит, а не 8.
Поле флагов всегда представлено первым байтом, поэтому мы можем получить его, преобразовав данные (переданные в виде буфера) в массив Uint8Array и получив доступ к первому элементу этого массива, который будет элементом с индексом 0.
Затем мы можем проверить различные битовые поля, используя побитовые операции. Например, спецификация характеристики службы сердечного ритма Bluetooth говорит нам, что пятый бит представляет, содержит ли чтение интервалы RR (1) или нет (0).
Ниже мы видим, что пятый бит - это число 16 в двоичном виде:
128 64 32 16 8 4 2 1
0 0 0 1 0 0 0 0
Поэтому операция 16 & flag (где flag - это байт, содержащий поле flags) вернет 16 (который может быть поднят в true), если чтение содержит интервалы RR, и 0 (поднят в false), если это не так.