From 9dd99ad6a834af691b40cfcd6f12625d567632ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9verin=20F=C3=A9rard?= Date: Fri, 10 Jan 2025 17:13:14 +0100 Subject: [PATCH] fix acc and gyro convertions from ble buffer --- basic/index.js | 707 ++++++++++++++++----------- react-dashboard/package-lock.json | 4 +- react-dashboard/src/BleMonitoring.ts | 94 +++- 3 files changed, 515 insertions(+), 290 deletions(-) diff --git a/basic/index.js b/basic/index.js index 5af4f6a..6aa3ba0 100644 --- a/basic/index.js +++ b/basic/index.js @@ -7,7 +7,6 @@ const BLE_ERROR_SERVICE_UUID = 0x1200; const BLE_ERROR_CHARACTERISTIC_UUID = 0x1201; - const BLE_IMU_SERVICE_UUID = 0x1101; const BLE_ACC_CHARACTERISTIC_UUID = 0x1102; const BLE_GYR_CHARACTERISTIC_UUID = 0x1103; @@ -22,13 +21,12 @@ const BLE_LEDSEQ1A_PD2CHARACTERISTIC2_UUID = 0x1307; const BLE_SNR1_2PD1CHARACTERISTIC2_UUID = 0x1313; const BLE_SNR2_2PD2CHARACTERISTIC2_UUID = 0x1314; - /////////////////////////////////////////////////////// -const BLE_StartStop_SERVICE_UUID = 0x1400 -let BLE_Start_CHARACTERISTIC -let BLE_IntensityLEDS_CHARACTERISTIC -let BLE_SampleRate_CHARACTERISTIC -let BLE_SampleAvg_CHARACTERISTIC +const BLE_StartStop_SERVICE_UUID = 0x1400; +let BLE_Start_CHARACTERISTIC; +let BLE_IntensityLEDS_CHARACTERISTIC; +let BLE_SampleRate_CHARACTERISTIC; +let BLE_SampleAvg_CHARACTERISTIC; //let inputIntensityLEDS //let inputSampleRate //let inputSampleAvg @@ -58,244 +56,344 @@ let IMUMagXLine; let IMUMagYLine; let IMUMagZLine; -let gyrData = {x: null, y: null, z: null} -let pitch -let roll -let yaw +let gyrData = { x: null, y: null, z: null }; +let pitch; +let roll; +let yaw; function int16ToFloat32(inputArray, startIndex, length) { - var output = new Float32Array(inputArray.length-startIndex); + var output = new Float32Array(inputArray.length - startIndex); for (var i = startIndex; i < length; i++) { var int = inputArray[i]; // If the high bit is on, then it is a negative number, and actually counts backwards. - var float = (int >= 0x8000) ? -(0x10000 - int) / 0x8000 : int / 0x7FFF; + var float = int >= 0x8000 ? -(0x10000 - int) / 0x8000 : int / 0x7fff; output[i] = float; } return output; } async function onConnectButtonClick() { - -// ################## Received from device ############# -try{ - - console.log('Requesting any Bluetooth Device...'); + // ################## Received from device ############# + try { + console.log("Requesting any Bluetooth Device..."); const device = await navigator.bluetooth.requestDevice({ - // filters: [...] <- Prefer filters to save energy & show relevant devices. - acceptAllDevices: true, - optionalServices:[BLE_PPG86_SERVICE_UUID,BLE_ERROR_SERVICE_UUID,BLE_IMU_SERVICE_UUID - ,BLE_StartStop_SERVICE_UUID] - }); - - console.log('Connecting to GATT Server...'); + // filters: [...] <- Prefer filters to save energy & show relevant devices. + acceptAllDevices: true, + optionalServices: [ + BLE_PPG86_SERVICE_UUID, + BLE_ERROR_SERVICE_UUID, + BLE_IMU_SERVICE_UUID, + BLE_StartStop_SERVICE_UUID, + ], + }); + + console.log("Connecting to GATT Server..."); const server = await device.gatt.connect(); // Note that we could also get all services that match a specific UUID by // passing it to getPrimaryServices(). - console.log('Getting Services...'); + console.log("Getting Services..."); const services = await server.getPrimaryServices(); - console.log('Getting Characteristics...'); + console.log("Getting Characteristics..."); for (const service of services) { - console.log('> Service: ' + service.uuid); + console.log("> Service: " + service.uuid); const characteristics = await service.getCharacteristics(); - characteristics.forEach(characteristic => { - console.log('>> Characteristic: ' + characteristic.uuid + ' ' + - getSupportedProperties(characteristic)); - - if(characteristic.uuid== '00001201-0000-1000-8000-00805f9b34fb'){ - errorCharacteristic= characteristic; - errorCharacteristic.addEventListener('characteristicvaluechanged',(event)=>{ - const value = event.target.value; // Read the error buffer - const IMUError = value.getUint8(0); // Extract the value for each sensors - const PPG86Error = value.getUint8(1); - console.log("IMUError: ", IMUError, " PPGError: ", PPG86Error); - document.getElementById("IMU-state").classList = IMUError ? "status-ko" : "status-ok"; // Update DOM - document.getElementById("PPG-state").classList = PPG86Error ? "status-ko" : "status-ok"; - }); - errorCharacteristic.startNotifications(); - } - - if(characteristic.uuid== '00001102-0000-1000-8000-00805f9b34fb'){ - ACCCharacteristic= characteristic; - ACCCharacteristic.addEventListener('characteristicvaluechanged',(event)=>{ - const value = event.target.value; - const timestamp = (value.getUint8(0) << 24) | (value.getUint8(1) << 16) | (value.getUint8(2) << 8) | value.getUint8(3); - //console.log("timeStamp 111: ",timestamp); - var v = value.getInt8(5)<<8 | value.getInt8(6); - var x = ((v * -1) * 16) / 0x8000; - - v = value.getInt8(7)<<8 | value.getInt8(8); - var y = ((v * -1) * 16) / 0x8000; - - v = value.getInt8(9)<<8 | value.getInt8(10); - var z = ((v * -1) * 16) / 0x8000; - - IMUAccXLine.append(new Date().getTime(), x) - IMUAccYLine.append(new Date().getTime(), y) - IMUAccZLine.append(new Date().getTime(), z) - + characteristics.forEach((characteristic) => { + console.log( + ">> Characteristic: " + + characteristic.uuid + + " " + + getSupportedProperties(characteristic) + ); + + if (characteristic.uuid == "00001201-0000-1000-8000-00805f9b34fb") { + errorCharacteristic = characteristic; + errorCharacteristic.addEventListener( + "characteristicvaluechanged", + (event) => { + const value = event.target.value; // Read the error buffer + const IMUError = value.getUint8(0); // Extract the value for each sensors + const PPG86Error = value.getUint8(1); + console.log("IMUError: ", IMUError, " PPGError: ", PPG86Error); + document.getElementById("IMU-state").classList = IMUError + ? "status-ko" + : "status-ok"; // Update DOM + document.getElementById("PPG-state").classList = PPG86Error + ? "status-ko" + : "status-ok"; } - ); - ACCCharacteristic.startNotifications(); + ); + errorCharacteristic.startNotifications(); + } + + if (characteristic.uuid == "00001102-0000-1000-8000-00805f9b34fb") { + ACCCharacteristic = characteristic; + ACCCharacteristic.addEventListener( + "characteristicvaluechanged", + (event) => { + const value = event.target.value; + const timestamp = + (value.getUint8(0) << 24) | + (value.getUint8(1) << 16) | + (value.getUint8(2) << 8) | + value.getUint8(3); + //console.log("timeStamp 111: ",timestamp); + var v = (value.getUint8(5) << 8) | value.getUint8(6); + if (v & 0x8000) { + v = v - 0x10000; // Convert to a signed 16-bit value + } + var x = (v * -1 * 16) / 0x8000; + + v = (value.getUint8(7) << 8) | value.getUint8(8); + if (v & 0x8000) { + v = v - 0x10000; // Convert to a signed 16-bit value + } + var y = (v * -1 * 16) / 0x8000; + + v = (value.getUint8(9) << 8) | value.getUint8(10); + if (v & 0x8000) { + v = v - 0x10000; // Convert to a signed 16-bit value + } + var z = (v * -1 * 16) / 0x8000; + + // console.log(value.getUint8(9), value.getUint8(10), z); + console.log(x, y, z); + + IMUAccXLine.append(new Date().getTime(), x); + IMUAccYLine.append(new Date().getTime(), y); + IMUAccZLine.append(new Date().getTime(), z); } - - - if(characteristic.uuid== '00001103-0000-1000-8000-00805f9b34fb'){ - GYRCharacteristic= characteristic; - GYRCharacteristic.addEventListener('characteristicvaluechanged',(event) => { - const value = event.target.value; - const timestamp = (value.getUint8(0) << 24) | (value.getUint8(1) << 16) | (value.getUint8(2) << 8) | value.getUint8(3); - - var v1 = value.getInt8(5)<<8 | value.getInt8(6); - - var x = (v1 * -1) * 2000 / 0x8000; - - v1 = value.getInt8(7)<<8 | value.getInt8(8); - var y = (v1 * -1) * 2000 / 0x8000; - - v1 = value.getInt8(9)<<8 | value.getInt8(10); - var z = (v1 * -1) * 2000 / 0x8000; - - IMUGyrXLine.append(new Date().getTime(), x) - IMUGyrYLine.append(new Date().getTime(), y) - IMUGyrZLine.append(new Date().getTime(), z) - }); - GYRCharacteristic.startNotifications(); - } - if(characteristic.uuid== '00001104-0000-1000-8000-00805f9b34fb'){ - MAGCharacteristic= characteristic; - MAGCharacteristic.addEventListener('characteristicvaluechanged',(event) => { - const value = event.target.value; - - const timestamp = (value.getUint8(0) << 24) | (value.getUint8(1) << 16) | (value.getUint8(2) << 8) | value.getUint8(3); - - var x = (value.getInt8(4)<<8 | value.getInt8(5) * (((( 174 - 128) * 0.5) / 128) + 1)); - var y = (value.getInt8(6)<<8 | value.getInt8(7) * (((( 177 - 128) * 0.5) / 128) + 1)); - - var z = (value.getInt8(8)<<8 | value.getInt8(9) * (((( 164 - 128) * 0.5) / 128) + 1)); - //console.log(x,y,z) - IMUMagXLine.append(new Date().getTime(), x) - IMUMagYLine.append(new Date().getTime(), y) - IMUMagZLine.append(new Date().getTime(), z) - }); - MAGCharacteristic.startNotifications(); - } - - if(characteristic.uuid== '00001305-0000-1000-8000-00805f9b34fb'){ - LEDSEQ1A_PD1CHARACTERISTIC2= characteristic; - LEDSEQ1A_PD1CHARACTERISTIC2.addEventListener('characteristicvaluechanged',LEDSEQ1A_PD1CHARACTERISTIC2Changed); - LEDSEQ1A_PD1CHARACTERISTIC2.startNotifications(); - } - if(characteristic.uuid== '00001307-0000-1000-8000-00805f9b34fb'){ - LEDSEQ1A_PD2CHARACTERISTIC2= characteristic; - LEDSEQ1A_PD2CHARACTERISTIC2.addEventListener('characteristicvaluechanged',LEDSEQ1A_PD2CHARACTERISTIC2Changed); - LEDSEQ1A_PD2CHARACTERISTIC2.startNotifications(); - } - if(characteristic.uuid== '00001313-0000-1000-8000-00805f9b34fb'){ - SNR1_2PD1CHARACTERISTIC2= characteristic; - SNR1_2PD1CHARACTERISTIC2.addEventListener('characteristicvaluechanged',SNR1_2PD1CHARACTERISTIC2Changed); - SNR1_2PD1CHARACTERISTIC2.startNotifications(); - } - if(characteristic.uuid== '00001314-0000-1000-8000-00805f9b34fb'){ - SNR1_2PD2CHARACTERISTIC2= characteristic; - SNR1_2PD2CHARACTERISTIC2.addEventListener('characteristicvaluechanged',SNR1_2PD2CHARACTERISTIC2Changed); - SNR1_2PD2CHARACTERISTIC2.startNotifications(); - } - - if(characteristic.uuid== '00001401-0000-1000-8000-00805f9b34fb'){ - BLE_Start_CHARACTERISTIC = characteristic; - } - - if(characteristic.uuid== '00001402-0000-1000-8000-00805f9b34fb'){ - BLE_IntensityLEDS_CHARACTERISTIC = characteristic - } - - if(characteristic.uuid== '00001403-0000-1000-8000-00805f9b34fb'){ - BLE_SampleRate_CHARACTERISTIC = characteristic - } - - if(characteristic.uuid== '00001404-0000-1000-8000-00805f9b34fb'){ - BLE_SampleAvg_CHARACTERISTIC = characteristic - } - + ); + ACCCharacteristic.startNotifications(); + } + + if (characteristic.uuid == "00001103-0000-1000-8000-00805f9b34fb") { + GYRCharacteristic = characteristic; + GYRCharacteristic.addEventListener( + "characteristicvaluechanged", + (event) => { + const value = event.target.value; + const timestamp = + (value.getUint8(0) << 24) | + (value.getUint8(1) << 16) | + (value.getUint8(2) << 8) | + value.getUint8(3); + + var v1 = (value.getUint8(5) << 8) | value.getUint8(6); + if (v & 0x8000) { + v = v - 0x10000; // Convert to a signed 16-bit value + } + var x = (v1 * -1 * 2000) / 0x8000; + + v1 = (value.getUint8(7) << 8) | value.getUint8(8); + if (v & 0x8000) { + v = v - 0x10000; // Convert to a signed 16-bit value + } + var y = (v1 * -1 * 2000) / 0x8000; + + v1 = (value.getUint8(9) << 8) | value.getUint8(10); + if (v & 0x8000) { + v = v - 0x10000; // Convert to a signed 16-bit value + } + var z = (v1 * -1 * 2000) / 0x8000; + + IMUGyrXLine.append(new Date().getTime(), x); + IMUGyrYLine.append(new Date().getTime(), y); + IMUGyrZLine.append(new Date().getTime(), z); + } + ); + GYRCharacteristic.startNotifications(); + } + if (characteristic.uuid == "00001104-0000-1000-8000-00805f9b34fb") { + MAGCharacteristic = characteristic; + MAGCharacteristic.addEventListener( + "characteristicvaluechanged", + (event) => { + const value = event.target.value; + + const timestamp = + (value.getUint8(0) << 24) | + (value.getUint8(1) << 16) | + (value.getUint8(2) << 8) | + value.getUint8(3); + + var x = + (value.getInt8(4) << 8) | + (value.getInt8(5) * (((174 - 128) * 0.5) / 128 + 1)); + var y = + (value.getInt8(6) << 8) | + (value.getInt8(7) * (((177 - 128) * 0.5) / 128 + 1)); + + var z = + (value.getInt8(8) << 8) | + (value.getInt8(9) * (((164 - 128) * 0.5) / 128 + 1)); + //console.log(x,y,z) + IMUMagXLine.append(new Date().getTime(), x); + IMUMagYLine.append(new Date().getTime(), y); + IMUMagZLine.append(new Date().getTime(), z); + } + ); + MAGCharacteristic.startNotifications(); + } + + if (characteristic.uuid == "00001305-0000-1000-8000-00805f9b34fb") { + LEDSEQ1A_PD1CHARACTERISTIC2 = characteristic; + LEDSEQ1A_PD1CHARACTERISTIC2.addEventListener( + "characteristicvaluechanged", + LEDSEQ1A_PD1CHARACTERISTIC2Changed + ); + LEDSEQ1A_PD1CHARACTERISTIC2.startNotifications(); + } + if (characteristic.uuid == "00001307-0000-1000-8000-00805f9b34fb") { + LEDSEQ1A_PD2CHARACTERISTIC2 = characteristic; + LEDSEQ1A_PD2CHARACTERISTIC2.addEventListener( + "characteristicvaluechanged", + LEDSEQ1A_PD2CHARACTERISTIC2Changed + ); + LEDSEQ1A_PD2CHARACTERISTIC2.startNotifications(); + } + if (characteristic.uuid == "00001313-0000-1000-8000-00805f9b34fb") { + SNR1_2PD1CHARACTERISTIC2 = characteristic; + SNR1_2PD1CHARACTERISTIC2.addEventListener( + "characteristicvaluechanged", + SNR1_2PD1CHARACTERISTIC2Changed + ); + SNR1_2PD1CHARACTERISTIC2.startNotifications(); + } + if (characteristic.uuid == "00001314-0000-1000-8000-00805f9b34fb") { + SNR1_2PD2CHARACTERISTIC2 = characteristic; + SNR1_2PD2CHARACTERISTIC2.addEventListener( + "characteristicvaluechanged", + SNR1_2PD2CHARACTERISTIC2Changed + ); + SNR1_2PD2CHARACTERISTIC2.startNotifications(); + } + + if (characteristic.uuid == "00001401-0000-1000-8000-00805f9b34fb") { + BLE_Start_CHARACTERISTIC = characteristic; + } + + if (characteristic.uuid == "00001402-0000-1000-8000-00805f9b34fb") { + BLE_IntensityLEDS_CHARACTERISTIC = characteristic; + } + + if (characteristic.uuid == "00001403-0000-1000-8000-00805f9b34fb") { + BLE_SampleRate_CHARACTERISTIC = characteristic; + } + + if (characteristic.uuid == "00001404-0000-1000-8000-00805f9b34fb") { + BLE_SampleAvg_CHARACTERISTIC = characteristic; + } }); } - } catch(error) { - console.log('Argh! ' + error); + } catch (error) { + console.log("Argh! " + error); } } -function startReceiving(){ - var data = new Uint8Array(1); - data[0] = 1 - BLE_Start_CHARACTERISTIC.writeValue(data) +function startReceiving() { + var data = new Uint8Array(1); + data[0] = 1; + BLE_Start_CHARACTERISTIC.writeValue(data); } -function stopReceiving(){ - var data = new Uint8Array(1); - data[0] = 2 - BLE_Start_CHARACTERISTIC.writeValue(data) +function stopReceiving() { + var data = new Uint8Array(1); + data[0] = 2; + BLE_Start_CHARACTERISTIC.writeValue(data); } -function sendValues(){ - var inputIntensityLEDS = new Uint8Array(1) - var inputSampleRate = new Uint8Array(1) - var inputSampleAvg = new Uint8Array(1) +function sendValues() { + var inputIntensityLEDS = new Uint8Array(1); + var inputSampleRate = new Uint8Array(1); + var inputSampleAvg = new Uint8Array(1); + + inputIntensityLEDS[0] = parseInt( + document.getElementById("intensity").value, + 10 + ); - inputIntensityLEDS[0] = parseInt(document.getElementById("intensity").value,10) - //inputSampleRate[0] = parseInt(document.getElementById("smpl_rate").value,10) var selectElmt1 = document.getElementById("smpl_rate"); - var valeurselectionnee1 = selectElmt1.options[selectElmt1.selectedIndex].value - console.log("valeurselectionnee1 "+valeurselectionnee1) + var valeurselectionnee1 = + selectElmt1.options[selectElmt1.selectedIndex].value; + console.log("valeurselectionnee1 " + valeurselectionnee1); if (valeurselectionnee1 == 25) { - inputSampleRate[0] = 0 + inputSampleRate[0] = 0; + } else if (valeurselectionnee1 == 50) { + inputSampleRate[0] = 1; + } else if (valeurselectionnee1 == 84) { + inputSampleRate[0] = 2; + } else if (valeurselectionnee1 == 100) { + inputSampleRate[0] = 3; + } else if (valeurselectionnee1 == 200) { + inputSampleRate[0] = 4; + } else if (valeurselectionnee1 == 400) { + inputSampleRate[0] = 5; + } else if (valeurselectionnee1 == 128) { + inputSampleRate[0] = 14; + } else if (valeurselectionnee1 == 256) { + inputSampleRate[0] = 15; + } else if (valeurselectionnee1 == 512) { + inputSampleRate[0] = 16; + } else if (valeurselectionnee1 == 1024) { + inputSampleRate[0] = 17; + } else if (valeurselectionnee1 == 2048) { + inputSampleRate[0] = 18; + } else { + inputSampleRate[0] = 19; } - else if (valeurselectionnee1 == 50) {inputSampleRate[0]= 1} - else if (valeurselectionnee1 == 84) {inputSampleRate[0]= 2} - else if (valeurselectionnee1 == 100) {inputSampleRate[0]= 3} - else if (valeurselectionnee1 == 200) {inputSampleRate[0]= 4} - else if (valeurselectionnee1 == 400) {inputSampleRate[0]= 5} - else if (valeurselectionnee1 == 128) { inputSampleRate[0]= 14 - } - else if (valeurselectionnee1 == 256) {inputSampleRate[0]= 15} - else if (valeurselectionnee1 == 512) {inputSampleRate[0]= 16} - else if (valeurselectionnee1 == 1024) {inputSampleRate[0]= 17} - else if (valeurselectionnee1 == 2048) {inputSampleRate[0]= 18} - else {inputSampleRate[0]= 19} //inputSampleAvg[0] = document.getElementById("smpl_avg").value var selectElmt = document.getElementById("smpl_avg"); - var valeurselectionnee = selectElmt.options[selectElmt.selectedIndex].value - console.log("valeurselectionnee "+valeurselectionnee) + var valeurselectionnee = selectElmt.options[selectElmt.selectedIndex].value; + console.log("valeurselectionnee " + valeurselectionnee); if (valeurselectionnee == 1) { - inputSampleAvg[0] = 0 + inputSampleAvg[0] = 0; + } else if (valeurselectionnee == 2) { + inputSampleAvg[0] = 1; + } else if (valeurselectionnee == 4) { + inputSampleAvg[0] = 2; + } else if (valeurselectionnee == 8) { + inputSampleAvg[0] = 3; + } else if (valeurselectionnee == 16) { + inputSampleAvg[0] = 4; + } else if (valeurselectionnee == 32) { + inputSampleAvg[0] = 5; + } else if (valeurselectionnee == 64) { + inputSampleAvg[0] = 6; + } else { + inputSampleAvg[0] = 7; } - else if (valeurselectionnee == 2) {inputSampleAvg[0]= 1 -} - else if (valeurselectionnee == 4) {inputSampleAvg[0]= 2} - else if (valeurselectionnee == 8) {inputSampleAvg[0]= 3} - else if (valeurselectionnee == 16) {inputSampleAvg[0]= 4} - else if (valeurselectionnee == 32) {inputSampleAvg[0]= 5} - else if (valeurselectionnee == 64) {inputSampleAvg[0]= 6} - else {inputSampleAvg[0]= 7 } - - console.log("les valeurs saisies sont: "+inputIntensityLEDS[0] + " "+inputSampleRate[0]+" "+ inputSampleAvg[0]) - - BLE_IntensityLEDS_CHARACTERISTIC.writeValue(inputIntensityLEDS) - BLE_SampleRate_CHARACTERISTIC.writeValue(inputSampleRate) - BLE_SampleAvg_CHARACTERISTIC.writeValue(inputSampleAvg) + console.log( + "les valeurs saisies sont: " + + inputIntensityLEDS[0] + + " " + + inputSampleRate[0] + + " " + + inputSampleAvg[0] + ); + + BLE_IntensityLEDS_CHARACTERISTIC.writeValue(inputIntensityLEDS); + BLE_SampleRate_CHARACTERISTIC.writeValue(inputSampleRate); + BLE_SampleAvg_CHARACTERISTIC.writeValue(inputSampleAvg); } window.onload = () => { // wait for the page to load so that the DOM elements are available - console.log(navigator.bluetooth ? "Web-BLE Available" : "Web-BLE Unavailable"); - document.getElementById("connect-btn").addEventListener("click", onConnectButtonClick); - document.getElementById("start-btn").addEventListener("click", startReceiving); + console.log( + navigator.bluetooth ? "Web-BLE Available" : "Web-BLE Unavailable" + ); + document + .getElementById("connect-btn") + .addEventListener("click", onConnectButtonClick); + document + .getElementById("start-btn") + .addEventListener("click", startReceiving); document.getElementById("stop-btn").addEventListener("click", stopReceiving); document.getElementById("start-btn").disabled = false; @@ -304,10 +402,10 @@ window.onload = () => { document.getElementById("apply-btn").addEventListener("click", sendValues); //document.getElementById("disconnect-btn").addEventListener("click", onDisconnected); - + let IMUAccSmoothie = new SmoothieChart(); let IMUGyrSmoothie = new SmoothieChart(); - let IMUMagSmoothie = new SmoothieChart() + let IMUMagSmoothie = new SmoothieChart(); IMUAccXLine = new TimeSeries(); IMUAccYLine = new TimeSeries(); @@ -315,36 +413,72 @@ window.onload = () => { IMUGyrXLine = new TimeSeries(); IMUGyrYLine = new TimeSeries(); IMUGyrZLine = new TimeSeries(); - IMUMagXLine = new TimeSeries() - IMUMagYLine = new TimeSeries() - IMUMagZLine = new TimeSeries() + IMUMagXLine = new TimeSeries(); + IMUMagYLine = new TimeSeries(); + IMUMagZLine = new TimeSeries(); - IMUAccSmoothie.addTimeSeries(IMUAccXLine, { strokeStyle: "rgb(255, 0, 0)", lineWidth: 3 }); - IMUAccSmoothie.addTimeSeries(IMUAccYLine, { strokeStyle: "rgb(0, 255, 0)", lineWidth: 3 }); - IMUAccSmoothie.addTimeSeries(IMUAccZLine, { strokeStyle: "rgb(0, 0, 255)", lineWidth: 3 }); + IMUAccSmoothie.addTimeSeries(IMUAccXLine, { + strokeStyle: "rgb(255, 0, 0)", + lineWidth: 3, + }); + IMUAccSmoothie.addTimeSeries(IMUAccYLine, { + strokeStyle: "rgb(0, 255, 0)", + lineWidth: 3, + }); + IMUAccSmoothie.addTimeSeries(IMUAccZLine, { + strokeStyle: "rgb(0, 0, 255)", + lineWidth: 3, + }); IMUAccSmoothie.streamTo(document.getElementById("smoothie-imu-acc")); - IMUGyrSmoothie.addTimeSeries(IMUGyrXLine, { strokeStyle: "rgb(255, 0, 0)", lineWidth: 3 }); - IMUGyrSmoothie.addTimeSeries(IMUGyrYLine, { strokeStyle: "rgb(0, 255, 0)", lineWidth: 3 }); - IMUGyrSmoothie.addTimeSeries(IMUGyrZLine, { strokeStyle: "rgb(0, 0, 255)", lineWidth: 3 }); + IMUGyrSmoothie.addTimeSeries(IMUGyrXLine, { + strokeStyle: "rgb(255, 0, 0)", + lineWidth: 3, + }); + IMUGyrSmoothie.addTimeSeries(IMUGyrYLine, { + strokeStyle: "rgb(0, 255, 0)", + lineWidth: 3, + }); + IMUGyrSmoothie.addTimeSeries(IMUGyrZLine, { + strokeStyle: "rgb(0, 0, 255)", + lineWidth: 3, + }); IMUGyrSmoothie.streamTo(document.getElementById("smoothie-imu-gyr")); - IMUMagSmoothie.addTimeSeries(IMUMagXLine, { strokeStyle: "rgb(255, 0, 0)", lineWidth: 3 }); - IMUMagSmoothie.addTimeSeries(IMUMagYLine, { strokeStyle: "rgb(0, 255, 0)", lineWidth: 3 }); - IMUMagSmoothie.addTimeSeries(IMUMagZLine, { strokeStyle: "rgb(0, 0, 255)", lineWidth: 3 }); + IMUMagSmoothie.addTimeSeries(IMUMagXLine, { + strokeStyle: "rgb(255, 0, 0)", + lineWidth: 3, + }); + IMUMagSmoothie.addTimeSeries(IMUMagYLine, { + strokeStyle: "rgb(0, 255, 0)", + lineWidth: 3, + }); + IMUMagSmoothie.addTimeSeries(IMUMagZLine, { + strokeStyle: "rgb(0, 0, 255)", + lineWidth: 3, + }); IMUMagSmoothie.streamTo(document.getElementById("smoothie-imu-mag")); let LEDSEQ1A_PD1Characteristic2Smoothie = new SmoothieChart(); // Create SmoothieChart objects LEDSEQ1A_PD1Characteristic2Line = new TimeSeries(); // Create a TimeSeries to store the data for each sensor - LEDSEQ1A_PD1Characteristic2Smoothie.addTimeSeries(LEDSEQ1A_PD1Characteristic2Line, { strokeStyle: "rgb(255, 0, 0)", lineWidth: 3 }); // Link TimeSeries to the SmoothieChart object and add a bit of color - LEDSEQ1A_PD1Characteristic2Smoothie.streamTo(document.getElementById("smoothie-pd1-led")); // Link the SoothieChart object to its canvas in the HTML + LEDSEQ1A_PD1Characteristic2Smoothie.addTimeSeries( + LEDSEQ1A_PD1Characteristic2Line, + { strokeStyle: "rgb(255, 0, 0)", lineWidth: 3 } + ); // Link TimeSeries to the SmoothieChart object and add a bit of color + LEDSEQ1A_PD1Characteristic2Smoothie.streamTo( + document.getElementById("smoothie-pd1-led") + ); // Link the SoothieChart object to its canvas in the HTML let LEDSEQ1A_PD2Characteristic2Smoothie = new SmoothieChart(); // Create SmoothieChart objects LEDSEQ1A_PD2Characteristic2Line = new TimeSeries(); // Create a TimeSeries to store the data for each sensor - LEDSEQ1A_PD2Characteristic2Smoothie.addTimeSeries(LEDSEQ1A_PD2Characteristic2Line, { strokeStyle: "rgb(255, 0, 0)", lineWidth: 3 }); // Link TimeSeries to the SmoothieChart object and add a bit of color - LEDSEQ1A_PD2Characteristic2Smoothie.streamTo(document.getElementById("smoothie-pd2-led")); // Link the SoothieChart object to its canvas in the HTML - -} + LEDSEQ1A_PD2Characteristic2Smoothie.addTimeSeries( + LEDSEQ1A_PD2Characteristic2Line, + { strokeStyle: "rgb(255, 0, 0)", lineWidth: 3 } + ); // Link TimeSeries to the SmoothieChart object and add a bit of color + LEDSEQ1A_PD2Characteristic2Smoothie.streamTo( + document.getElementById("smoothie-pd2-led") + ); // Link the SoothieChart object to its canvas in the HTML +}; /*function connectToBle() { // Connect to a device by passing the service UUID @@ -370,7 +504,7 @@ function getSupportedProperties(characteristic) { supportedProperties.push(p.toUpperCase()); } } - return '[' + supportedProperties.join(', ') + ']'; + return "[" + supportedProperties.join(", ") + "]"; } async function LEDSEQ1A_PD1CHARACTERISTIC2Changed(event) { @@ -380,81 +514,110 @@ async function LEDSEQ1A_PD1CHARACTERISTIC2Changed(event) { //console.log("timestamp: ", timestamp, "ledSeq1A_PD1Characteristic2: ", ledSeq1A_PD1Characteristic2); LEDSEQ1A_PD1Characteristic2Line.append(new Date().getTime(), ledSeq1A_PD1Characteristic2);*/ const value = event.target.value; - const timestamp = (value.getUint8(0) << 24) | (value.getUint8(1) << 16) | (value.getUint8(2) << 8) | value.getUint8(3); // shifts 4 Uint8 to make a Uint32 - const data1 = (value.getUint8(4) << 24) | (value.getUint8(5) << 16) | (value.getUint8(6) << 8) | value.getUint8(7); // shifts 4 Uint8 to make a Uint32 - const data2 = (value.getUint8(8) << 24) | (value.getUint8(9) << 16) | (value.getUint8(10) << 8) | value.getUint8(11); // shifts 4 Uint8 to make a Uint32 + const timestamp = + (value.getUint8(0) << 24) | + (value.getUint8(1) << 16) | + (value.getUint8(2) << 8) | + value.getUint8(3); // shifts 4 Uint8 to make a Uint32 + const data1 = + (value.getUint8(4) << 24) | + (value.getUint8(5) << 16) | + (value.getUint8(6) << 8) | + value.getUint8(7); // shifts 4 Uint8 to make a Uint32 + const data2 = + (value.getUint8(8) << 24) | + (value.getUint8(9) << 16) | + (value.getUint8(10) << 8) | + value.getUint8(11); // shifts 4 Uint8 to make a Uint32 //console.log("timestamp: ", timestamp); - console.log("data1: ", data1,"data2: ", data2); + console.log("data1: ", data1, "data2: ", data2); var tab; - tab = [data1,data2] + tab = [data1, data2]; //console.log("data1: ", data1,"data2: ", data2,"data3: ", data3,"data4: ", data4); - for (var i = 0; i<2; i++) { - if(tab[i]!=0){ - LEDSEQ1A_PD1Characteristic2Line.append(new Date().getTime(), tab[i]); + for (var i = 0; i < 2; i++) { + if (tab[i] != 0) { + LEDSEQ1A_PD1Characteristic2Line.append(new Date().getTime(), tab[i]); + } } } -} async function LEDSEQ1A_PD2CHARACTERISTIC2Changed(event) { - /*const value = event.target.value; + /*const value = event.target.value; const ledSeq1A_PD2Characteristic2 = (value.getUint8(0) << 24) | (value.getUint8(1) << 16) | (value.getUint8(2) << 8) | value.getUint8(3); // shifts 4 Uint8 to make a Uint32 console.log("ledSeq1A_PD2Characteristic2: ", ledSeq1A_PD2Characteristic2); LEDSEQ1A_PD2Characteristic2Line.append(new Date().getTime(), ledSeq1A_PD2Characteristic2);*/ const value = event.target.value; - const timestamp = (value.getUint8(0) << 24) | (value.getUint8(1) << 16) | (value.getUint8(2) << 8) | value.getUint8(3); // shifts 4 Uint8 to make a Uint32 - const data1 = (value.getUint8(4) << 24) | (value.getUint8(5) << 16) | (value.getUint8(6) << 8) | value.getUint8(7); // shifts 4 Uint8 to make a Uint32 - const data2 = (value.getUint8(8) << 24) | (value.getUint8(9) << 16) | (value.getUint8(10) << 8) | value.getUint8(11); // shifts 4 Uint8 to make a Uint32 - - //console.log("timestamp: ", timestamp); + const timestamp = + (value.getUint8(0) << 24) | + (value.getUint8(1) << 16) | + (value.getUint8(2) << 8) | + value.getUint8(3); // shifts 4 Uint8 to make a Uint32 + const data1 = + (value.getUint8(4) << 24) | + (value.getUint8(5) << 16) | + (value.getUint8(6) << 8) | + value.getUint8(7); // shifts 4 Uint8 to make a Uint32 + const data2 = + (value.getUint8(8) << 24) | + (value.getUint8(9) << 16) | + (value.getUint8(10) << 8) | + value.getUint8(11); // shifts 4 Uint8 to make a Uint32 + + //console.log("timestamp: ", timestamp); var tab; - tab = [data1,data2] - for (var i = 0; i<2; i++) { - if(tab[i]!=0){ - LEDSEQ1A_PD2Characteristic2Line.append(new Date().getTime(), tab[i]); + tab = [data1, data2]; + for (var i = 0; i < 2; i++) { + if (tab[i] != 0) { + LEDSEQ1A_PD2Characteristic2Line.append(new Date().getTime(), tab[i]); + } } } -} async function SNR1_2PD1CHARACTERISTIC2Changed(event) { - const value = event.target.value; - var snr1_2PD1CHARACTERISTIC2 = (value.getUint8(0) << 24) | (value.getUint8(1) << 16) | (value.getUint8(2) << 8) | value.getUint8(3); // shifts 4 Uint8 to make a Uint32 - - //console.log("snr1_2PD1CHARACTERISTIC2: ", snr1_2PD1CHARACTERISTIC2); - if(snr1_2PD1CHARACTERISTIC2 %100==0){ - var snr_neg= snr1_2PD1CHARACTERISTIC2; - snr_neg= -(snr_neg/10000); - //console.log("snr1_2PD1CHARACTERISTIC2: ",snr_neg); - document.getElementById('snr1_2PD1').innerHTML = String(snr_neg); - } - else{ - var snr_pos= snr1_2PD1CHARACTERISTIC2; - snr_pos = snr_pos/100; - //console.log("snr1_2PD1CHARACTERISTIC2: ",snr_pos); - document.getElementById('snr1_2PD1').innerHTML = String(snr_pos); - } + const value = event.target.value; + var snr1_2PD1CHARACTERISTIC2 = + (value.getUint8(0) << 24) | + (value.getUint8(1) << 16) | + (value.getUint8(2) << 8) | + value.getUint8(3); // shifts 4 Uint8 to make a Uint32 + + //console.log("snr1_2PD1CHARACTERISTIC2: ", snr1_2PD1CHARACTERISTIC2); + if (snr1_2PD1CHARACTERISTIC2 % 100 == 0) { + var snr_neg = snr1_2PD1CHARACTERISTIC2; + snr_neg = -(snr_neg / 10000); + //console.log("snr1_2PD1CHARACTERISTIC2: ",snr_neg); + document.getElementById("snr1_2PD1").innerHTML = String(snr_neg); + } else { + var snr_pos = snr1_2PD1CHARACTERISTIC2; + snr_pos = snr_pos / 100; + //console.log("snr1_2PD1CHARACTERISTIC2: ",snr_pos); + document.getElementById("snr1_2PD1").innerHTML = String(snr_pos); + } } async function SNR1_2PD2CHARACTERISTIC2Changed(event) { - const value = event.target.value; - const snr1_2PD2CHARACTERISTIC2 = (value.getUint8(0) << 24) | (value.getUint8(1) << 16) | (value.getUint8(2) << 8) | value.getUint8(3); // shifts 4 Uint8 to make a Uint32 - - //console.log("snr1_2PD2CHARACTERISTIC2: ", snr1_2PD2CHARACTERISTIC2); - - if(snr1_2PD2CHARACTERISTIC2 %100==0){ - var snr_neg= snr1_2PD2CHARACTERISTIC2; - snr_neg= -(snr_neg/10000); - // console.log("snr1_2PD2CHARACTERISTIC2: ",snr_neg); - document.getElementById('snr2_2PD2').innerHTML = String(snr_neg); - } - else{ - var snr_pos= snr1_2PD2CHARACTERISTIC2; - snr_pos = snr_pos/100; - // console.log("snr1_2PD2CHARACTERISTIC2: ",snr_pos); - document.getElementById('snr2_2PD2').innerHTML = String(snr_pos); - } + const value = event.target.value; + const snr1_2PD2CHARACTERISTIC2 = + (value.getUint8(0) << 24) | + (value.getUint8(1) << 16) | + (value.getUint8(2) << 8) | + value.getUint8(3); // shifts 4 Uint8 to make a Uint32 + + //console.log("snr1_2PD2CHARACTERISTIC2: ", snr1_2PD2CHARACTERISTIC2); + + if (snr1_2PD2CHARACTERISTIC2 % 100 == 0) { + var snr_neg = snr1_2PD2CHARACTERISTIC2; + snr_neg = -(snr_neg / 10000); + // console.log("snr1_2PD2CHARACTERISTIC2: ",snr_neg); + document.getElementById("snr2_2PD2").innerHTML = String(snr_neg); + } else { + var snr_pos = snr1_2PD2CHARACTERISTIC2; + snr_pos = snr_pos / 100; + // console.log("snr1_2PD2CHARACTERISTIC2: ",snr_pos); + document.getElementById("snr2_2PD2").innerHTML = String(snr_pos); + } } - diff --git a/react-dashboard/package-lock.json b/react-dashboard/package-lock.json index 29f9810..a9057c6 100644 --- a/react-dashboard/package-lock.json +++ b/react-dashboard/package-lock.json @@ -1,12 +1,12 @@ { "name": "react-dashboard", - "version": "0.2.1", + "version": "0.2.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "react-dashboard", - "version": "0.2.1", + "version": "0.2.2", "dependencies": { "@emotion/react": "^11.8.2", "@mantine/core": "^4.0.7", diff --git a/react-dashboard/src/BleMonitoring.ts b/react-dashboard/src/BleMonitoring.ts index 6b5238f..6cf269b 100644 --- a/react-dashboard/src/BleMonitoring.ts +++ b/react-dashboard/src/BleMonitoring.ts @@ -7,13 +7,35 @@ export interface axis3I { z: number[]; } -const monitorAccFactory = (ref: MutableRefObject, svgClassName: string, maxLength: number) => { +function getValueFromBuffer(buffer: DataView, index: number, range: number) { + let v = (buffer.getUint8(index) << 8) | buffer.getUint8(index + 1); + + if (v & 0x8000) { + v = v - 0x10000; // Convert to a signed 16-bit value + } + return (v * -1 * range) / 0x8000; +} + +const monitorAccFactory = ( + ref: MutableRefObject, + svgClassName: string, + maxLength: number +) => { return function (this: BluetoothRemoteGATTCharacteristic, ev: Event) { // const timestamp = this.value?.getUint32(0); if (!this.value) return; - const x = (((this.value.getInt8(5) << 8) | this.value.getInt8(6)) * -1 * 16) / 0x8000; - const y = (((this.value.getInt8(7) << 8) | this.value.getInt8(8)) * -1 * 16) / 0x8000; - const z = (((this.value.getInt8(9) << 8) | this.value.getInt8(10)) * -1 * 16) / 0x8000; + const x = getValueFromBuffer(this.value, 5, 16); + const y = getValueFromBuffer(this.value, 7, 16); + const z = getValueFromBuffer(this.value, 9, 16); + + // (((this.value.getInt8(5) << 8) | this.value.getInt8(6)) * -1 * 16) / + // 0x8000; + // const y = + // (((this.value.getInt8(7) << 8) | this.value.getInt8(8)) * -1 * 16) / + // 0x8000; + // const z = + // (((this.value.getInt8(9) << 8) | this.value.getInt8(10)) * -1 * 16) / + // 0x8000; ref.current.x.push(x); ref.current.y.push(y); ref.current.z.push(z); @@ -24,20 +46,32 @@ const monitorAccFactory = (ref: MutableRefObject, svgClassName: string, } const elements = document.getElementsByClassName(svgClassName); for (let element of elements as any) { - updateChart([ref.current.x, ref.current.y, ref.current.z], element, { bottom: 10, left: 10, top: 10, right: 10 }, ["#8CE99A", "#74C0FC", "#FF8787"]); + updateChart( + [ref.current.x, ref.current.y, ref.current.z], + element, + { bottom: 10, left: 10, top: 10, right: 10 }, + ["#8CE99A", "#74C0FC", "#FF8787"] + ); } }; }; const monitorGyrFactory = monitorAccFactory; -const monitorMagFactory = (ref: MutableRefObject, svgClassName: string, maxLength: number) => { +const monitorMagFactory = ( + ref: MutableRefObject, + svgClassName: string, + maxLength: number +) => { return function (this: BluetoothRemoteGATTCharacteristic, ev: Event) { // const timestamp = this.value?.getUint32(0); if (!this.value) return; - const x = ((this.value.getInt8(4) << 8) | this.value.getInt8(5)) * 1.1796875; - const y = ((this.value.getInt8(6) << 8) | this.value.getInt8(7)) * 1.1796875; - const z = ((this.value.getInt8(8) << 8) | this.value.getInt8(9)) * 1.1796875; + const x = + ((this.value.getInt8(4) << 8) | this.value.getInt8(5)) * 1.1796875; + const y = + ((this.value.getInt8(6) << 8) | this.value.getInt8(7)) * 1.1796875; + const z = + ((this.value.getInt8(8) << 8) | this.value.getInt8(9)) * 1.1796875; ref.current.x.push(x); ref.current.y.push(y); ref.current.z.push(z); @@ -48,36 +82,64 @@ const monitorMagFactory = (ref: MutableRefObject, svgClassName: string, } const elements = document.getElementsByClassName(svgClassName); for (let element of elements as any) { - updateChart([ref.current.x, ref.current.y, ref.current.z], element, { bottom: 10, left: 10, top: 10, right: 10 }, ["#8CE99A", "#74C0FC", "#FF8787"]); + updateChart( + [ref.current.x, ref.current.y, ref.current.z], + element, + { bottom: 10, left: 10, top: 10, right: 10 }, + ["#8CE99A", "#74C0FC", "#FF8787"] + ); } }; }; -const monitorPpgFactory = (ref: MutableRefObject<{ timestamp: number; value: number }[]>, svgClassName: string, maxLength: number) => { +const monitorPpgFactory = ( + ref: MutableRefObject<{ timestamp: number; value: number }[]>, + svgClassName: string, + maxLength: number +) => { return function (this: BluetoothRemoteGATTCharacteristic, ev: Event) { const timestamp = this.value?.getUint32(0); const val1 = this.value?.getUint32(4); const val2 = this.value?.getUint32(8); - if (val1 === undefined || val2 === undefined || timestamp === undefined) return; + if (val1 === undefined || val2 === undefined || timestamp === undefined) + return; ref.current.push({ timestamp: timestamp, value: (val1 + val2) / 2 }); if (ref.current.length >= maxLength) ref.current.shift(); const elements = document.getElementsByClassName(svgClassName); for (let element of elements as any) { - updateChart([ref.current.map((e) => e.value)], element, { bottom: 10, left: 10, top: 10, right: 10 }, ["#8CE99A", "#74C0FC", "#FF8787"]); + updateChart( + [ref.current.map((e) => e.value)], + element, + { bottom: 10, left: 10, top: 10, right: 10 }, + ["#8CE99A", "#74C0FC", "#FF8787"] + ); } }; }; -const monitorSnrFactory = (setState: React.Dispatch>) => { +const monitorSnrFactory = ( + setState: React.Dispatch> +) => { return function (this: BluetoothRemoteGATTCharacteristic, ev: Event) { setState((this.value?.getUint32(0) ?? 0) / 100); }; }; -const readSnr = async (characteristic: BluetoothRemoteGATTCharacteristic, setState: React.Dispatch>, ref: React.MutableRefObject) => { +const readSnr = async ( + characteristic: BluetoothRemoteGATTCharacteristic, + setState: React.Dispatch>, + ref: React.MutableRefObject +) => { const val = (await characteristic.readValue()).getUint32(0) / 100; setState(val); ref.current = val; }; -export { monitorAccFactory, monitorGyrFactory, monitorMagFactory, monitorPpgFactory, monitorSnrFactory, readSnr }; +export { + monitorAccFactory, + monitorGyrFactory, + monitorMagFactory, + monitorPpgFactory, + monitorSnrFactory, + readSnr, +};