reverted back to old BLE lib - works well with only one characteristic

This commit is contained in:
vanarebane 2025-02-25 19:27:40 +02:00
parent ff3e411860
commit eed2a53460
5 changed files with 172 additions and 260 deletions

View File

@ -31,16 +31,18 @@
<span>millilux</span>
</div>
<div class="profilegroup">
<label for="strain" class="pwroff">Strain:</label>
<input style="width: 100%;" name="strain" value="0" type="text" disabled>
<label for="strain" class="pwroff">Scale:</label>
<button style="width: 100%; text-align: center;" class="statebtns" id="strain_push">Push</button>
<input style="width: 100%; text-align: right;" name="strain_raw" value="0" type="number" disabled>
<span>raw</span>
</div>
<div class="profilegroup">
<label for="strain" class="pwroff">Button:</label>
<label for="knob_button" class="pwroff">Button:</label>
<input style="width: 100%;" name="knob_button" value="0" type="text" disabled>
</div>
<div class="profilegroup">
<label for="strain" class="pwroff">Profile:</label>
<label for="profile_name" class="pwroff">Profile:</label>
<input style="width: 100%;" name="profile_name" value="" type="text" disabled>
</div>
@ -83,8 +85,6 @@
</div>
</div>
<!-- <button id="alarmtest" data-cmd="ARM">Alarm test</button><br> -->
<!-- <button id="setwifi" data-cmd="SWN">Connect Wifi</button> -->
</div>
<script>
@ -93,140 +93,24 @@
let sk = new SmartKnob()
var buffer = new ArrayBuffer(4);
var data = new Int32Array(buffer);
// message_disconnected = "Disconnected"
// message_connecting = "Connecting"
// message_connected = "Connected"
// message_tryagain = "Try again"
// message_error = "Error"
// /////////////////////////////////////////////////
// // https://gist.github.com/sam016/4abe921b5a9ee27f67b3686910293026#file-allgattcharacteristics-java
// var serviceUuid = 0x340f
// var characteristicUuid = "000042ff-0000-1000-8000-00805f9b34fb" //0x42ff
// var serviceCharacteristic;
// navigator.bluetooth.addEventListener("availabilitychanged", onavailabilitychanged)
async function onStartButtonClick() {
$('#request').on('click', async event => {sk.connect()});
sk.connect()
// try {
// isDisconnected(message_connecting, "processing")
// console.log('Requesting Bluetooth Device...');
// const device = await navigator.bluetooth.requestDevice({
// filters: [{"namePrefix": "SmartKnob_"}], // <- Prefer filters to save energy & show relevant devices
// optionalServices: [serviceUuid] // <- Required because "secuuurity"
// });
// console.log('Connecting to GATT Server...');
// const server = await device.gatt.connect();
// console.log('Getting Service...');
// const service = await server.getPrimaryService(serviceUuid);
// console.log('Getting Characteristic...');
// let serviceCharacteristics = await service.getCharacteristics()
// console.log(serviceCharacteristics)
// serviceCharacteristic = await service.getCharacteristic(serviceCharacteristics[0].uuid);
// await serviceCharacteristic.startNotifications();
// console.log('> Notifications started');
// serviceCharacteristic.addEventListener('characteristicvaluechanged', handleNotifications);
// // console.log('Getting Service 2...');
// // const service2 = await server.getPrimaryService(serviceUuid2);
// // console.log('Getting Characteristic 2...');
// // powerCharacteristic = await service2.getCharacteristic(powerCharacteristicUuid);
// // await powerCharacteristic.startNotifications();
// // console.log('> Notifications started');
// // powerCharacteristic.addEventListener('characteristicvaluechanged', handlePwrNotifications);
// isConnected()
// // document.querySelector('#writeButton').disabled = false;
// // console.log('Reading Alert Level...');
// // const value = await serviceCharacteristic.readValue();
// // console.log('> Alert Level: ' + getAlertLevel(value));
// } catch(error) {
// // document.querySelector('#writeButton').disabled = true;
// // NetworkError: GATT Server is disconnected. Cannot retrieve services. (Re)connect first with `device.gatt.connect`.
// console.log('! BT Connection error' + error);
// isDisconnected(message_tryagain, "error")
// }
}
// function onStopButtonClick(){
// if(serviceCharacteristic){
// serviceCharacteristic.stopNotifications()
// .then(_ => {
// console.log('> Notifications stopped');
// serviceCharacteristic.removeEventListener('characteristicvaluechanged', handleNotifications);
// })
// .catch(error => {
// if(error == "NotFoundError: User cancelled the requestDevice() chooser."){
// isDisconnected(message_tryagain)
// }
// //NetworkError: GATT operation already in progress.
// //NotSupportedError: GATT operation failed for unknown reason.
// //NetworkError: Failed to execute 'writeValue' on 'BluetoothRemoteGATTCharacteristic': GATT Server is disconnected. Cannot perform GATT operations. (Re)connect first with `device.gatt.connect`.
// //NetworkError: GATT Server is disconnected. Cannot retrieve services. (Re)connect first with `device.gatt.connect`.
// else{
// console.log('! BT error: ' + error);
// isDisconnected(message_error, "error")
// }
// });
// }
// }
// function onavailabilitychanged(event){
// this.log("Availabiliy changed: "+event.value)
// }
// function handleNotifications(event) {
// let buffer = event.target.value;
// // Display raw hex
// // let a = [];
// // for (let i = 0; i < buffer.byteLength; i++) {
// // a.push('0x' + ('00' + buffer.getUint8(i).toString(16)).slice(-2));
// // }
// // console.log('>> ' + a.join(' '));
// //let data = bufferToString(value)
// // let data = new DataView(buffer, 0)
// //let data = new Uint8Array(buffer)
// let value = buffer.getUint8(0)+(buffer.getUint8(1)*256)+(buffer.getUint8(2)*256)+(buffer.getUint8(3)*256)
// if(buffer.getUint8(2) > 0){
// value = (value-196096)
// }
// $('[name="position_cur"]').val(value)
// //console.log(value);
// //processNotificationState(data)
// }
sk.addListener('handleNotifications', (e)=>{
sk.addListener('handlePositionNotifications', (e)=>{
$('[name="position_cur"]').val(e.detail.value)
})
sk.addListener('handleScaleNotifications', (e)=>{
if(e.detail.value == 1){
$('#strain_push').addClass('active')
}
else{
$('#strain_push').removeClass('active')
}
})
/////////////////////////////////////////////////
/// PROCESSOR
var processNotificationState = function(response){
var [command, values] = response.split("+")
switch(command){
@ -274,6 +158,7 @@
break;
}
}
let PI = Math.PI;
@ -376,40 +261,6 @@
$('[name="new_profile_name"]').val(v[6].replace("\n", " / "))
})
$('#request').on('click', async event => {
try {
onStartButtonClick()
// btn_read(1)
// bt.startDoorNotifications(doorNotification)
// console.log("Request")
// await bt.request();
// console.log("Connect")
// if(bt.connected)
// await bt.connect();
// console.log("Connected")
// btn_read(1)
// bt.startDoorNotifications(doorNotification)
// await bt.readDoor();
//console.log("Done")
/* Do something with bt... */
} catch(error) {
console.log(error);
}
});
var btn_read = async function(number){
console.log("Readdoor "+number)
@ -421,7 +272,6 @@
console.log(" Done")
}
$('#profileconfig').on('click', async event => {
// OPEN CONFIG WINDOW
@ -432,46 +282,26 @@
$('#profileconfig_send').on('click', async event => {
let msg = $('#profile_message')
cmd = "SWN|"+$('[name="ssid"]').val()+"|"+$('[name="wifipass"]').val()
elem = $(event.target)
elem.addClass('processing')
// cmd = "SWN|"+$('[name="ssid"]').val()+"|"+$('[name="wifipass"]').val()
// elem = $(event.target)
// elem.addClass('processing')
msg.html("Sending config to SmartKnob")
// msg.html("Sending config to SmartKnob")
let value = stringToBuffer("CMD|"+cmd)
try{
console.log('Sending command: '+cmd+'...');
await serviceCharacteristic.writeValue(value);
// let value = stringToBuffer("CMD|"+cmd)
// try{
// console.log('Sending command: '+cmd+'...');
// await serviceCharacteristic.writeValue(value);
msg.html("Sending done, waiting back")
elem.removeClass('processing')
console.log('> Command sent: '+cmd);
}
catch(error){
msg.html("Sending error: "+error)
console.log('> Command BT error: '+error);
isDisconnected(message_tryagain, "error")
}
})
$('#setwifi').on('click', async event => {
cmd = event.target.dataset.cmd
elem = $(event.target)
elem.addClass('processing').removeClass('open')
let value = stringToBuffer("CMD|"+cmd)
try{
console.log('Sending command: '+cmd+'...');
await serviceCharacteristic.writeValue(value);
elem.removeClass('processing').addClass('open')
console.log('> Command sent: '+cmd);
}
catch(error){
console.log('> Command BT error: '+error);
isDisconnected(message_tryagain, "error")
}
// msg.html("Sending done, waiting back")
// elem.removeClass('processing')
// console.log('> Command sent: '+cmd);
// }
// catch(error){
// msg.html("Sending error: "+error)
// console.log('> Command BT error: '+error);
// isDisconnected(message_tryagain, "error")
// }
})

View File

@ -48,21 +48,23 @@ const SmartKnob = class {
serviceUuid = 0x340f // Primary service
serviceCharacteristics = []
characteristicUuids = {
'ambient': {
'uuid': "0000420f-0000-1000-8000-00805f9b34fb",
'functions': ['read', 'write', 'notify', 'indicate']
},
'push': {
'uuid': "0000421f-0000-1000-8000-00805f9b34fb",
'scale': {
'uuid': "e65dc16e-fb3e-4800-ad86-f78485cc65c2",
'functions': ['read', 'notify', 'indicate']
},
'button': {
'uuid': "0000422f-0000-1000-8000-00805f9b34fb",
'uuid': "d769e5b4-601c-4506-b1da-29f64069869d",
'functions': ['read', 'notify', 'indicate']
},
'position': {
'uuid': "0000423f-0000-1000-8000-00805f9b34fb",
'uuid': "602f75a0-697d-4690-8dd5-fa52781446d1",
'functions': ['read', 'write', 'notify', 'indicate']
},
'lights': {
@ -85,10 +87,9 @@ const SmartKnob = class {
async connect(){
this.serviceCharacteristic;
navigator.bluetooth.addEventListener("availabilitychanged", this.onavailabilitychanged)
try {
// try {
this.eventDisconnected(this.debug_messages.connecting, "processing")
this.log('Requesting Bluetooth Device...');
@ -103,14 +104,25 @@ const SmartKnob = class {
this.log('Getting Service...');
const service = await server.getPrimaryService(this.serviceUuid);
this.log('Getting Characteristic...');
let serviceCharacteristics = await service.getCharacteristics()
this.log(serviceCharacteristics)
let serviceCharacteristic = await service.getCharacteristic(serviceCharacteristics[0].uuid);
this.log('Getting List of Characteristics...');
let serviceCharacteristicsList = await service.getCharacteristics()
this.log(serviceCharacteristicsList)
let i=0
// for(let i=0; i<serviceCharacteristicsList.length; i++){
let charac = serviceCharacteristicsList[i]
await serviceCharacteristic.startNotifications();
this.log('> Notifications started');
serviceCharacteristic.addEventListener('characteristicvaluechanged', this.handleNotifications);
console.log("startNotifications on "+charac.uuid)
this.serviceCharacteristics[i] = charac //await service.getCharacteristic(charac.uuid);
console.log(this.serviceCharacteristics[i])
// let value = await this.serviceCharacteristics[i].readValue()
// console.log("value: "+ value)
await this.serviceCharacteristics[i].startNotifications();
this.log('> Notifications started on '+charac.uuid);
this.serviceCharacteristics[i].addEventListener('characteristicvaluechanged', this.handleNotifications);
// }
this.eventConnected()
@ -131,12 +143,12 @@ const SmartKnob = class {
// log('> Alert Level: ' + getAlertLevel(value));
} catch(error) {
// document.querySelector('#writeButton').disabled = true;
// NetworkError: GATT Server is disconnected. Cannot retrieve services. (Re)connect first with `device.gatt.connect`.
this.log('! BT Connection error' + error);
this.eventDisconnected(this.debug_messages.tryagain, "error")
}
// } catch(error) {
// // document.querySelector('#writeButton').disabled = true;
// // NetworkError: GATT Server is disconnected. Cannot retrieve services. (Re)connect first with `device.gatt.connect`.
// this.log('! BT Connection error' + error);
// this.eventDisconnected(this.debug_messages.tryagain, "error")
// }
}
disconnect(){
@ -144,29 +156,33 @@ const SmartKnob = class {
navigator.bluetooth.removeEventListener("availabilitychanged")
this.serviceCharacteristic.stopNotifications()
.then(_ => {
this.log('> Notifications stopped');
this.serviceCharacteristic.removeEventListener('characteristicvaluechanged', handleNotifications);
})
.catch(error => {
if(error == "NotFoundError: User cancelled the requestDevice() chooser."){
this.eventDisconnected(this.debug_messages.tryagain)
}
//NetworkError: GATT operation already in progress.
//NotSupportedError: GATT operation failed for unknown reason.
//NetworkError: Failed to execute 'writeValue' on 'BluetoothRemoteGATTCharacteristic': GATT Server is disconnected. Cannot perform GATT operations. (Re)connect first with `device.gatt.connect`.
//NetworkError: GATT Server is disconnected. Cannot retrieve services. (Re)connect first with `device.gatt.connect`.
else{
console.log('! BT error: ' + error);
this.eventDisconnected(this.debug_messages.error, "error")
}
});
this.serviceCharacteristics.forEach(async (charac, i) => {
this.charac.stopNotifications()
.then(_ => {
this.log('> Notifications stopped');
this.charac.removeEventListener('characteristicvaluechanged', handleNotifications);
})
.catch(error => {
if(error == "NotFoundError: User cancelled the requestDevice() chooser."){
this.eventDisconnected(this.debug_messages.tryagain)
}
//NetworkError: GATT operation already in progress.
//NotSupportedError: GATT operation failed for unknown reason.
//NetworkError: Failed to execute 'writeValue' on 'BluetoothRemoteGATTCharacteristic': GATT Server is disconnected. Cannot perform GATT operations. (Re)connect first with `device.gatt.connect`.
//NetworkError: GATT Server is disconnected. Cannot retrieve services. (Re)connect first with `device.gatt.connect`.
else{
console.log('! BT error: ' + error);
this.eventDisconnected(this.debug_messages.error, "error")
}
});
})
}
}
handleNotifications(event) {
console.log(event.currentTarget.uuid)
let buffer = event.target.value;
// Display raw hex
@ -180,14 +196,30 @@ const SmartKnob = class {
//let data = bufferToString(value)
// let data = new DataView(buffer, 0)
//let data = new Uint8Array(buffer)
let value = buffer.getUint8(0)+(buffer.getUint8(1)*256)+(buffer.getUint8(2)*256)+(buffer.getUint8(3)*256)
if(buffer.getUint8(2) > 0){
value = (value-196096)
switch(event.currentTarget.uuid){
case "602f75a0-697d-4690-8dd5-fa52781446d1":{
let value = buffer.getUint8(0)+(buffer.getUint8(1)*256)+(buffer.getUint8(2)*256)+(buffer.getUint8(3)*256)
if(buffer.getUint8(2) > 0){
value = (value-196096)
}
document.dispatchEvent(new CustomEvent('handlePositionNotifications', {detail: {'value': value}}))
break;
}
case "0000421f-0000-1000-8000-00805f9b34fb":{
let value = buffer.getUint8(0)
document.dispatchEvent(new CustomEvent('handleScaleNotifications', {detail: {'value': value}}))
break;
}
}
// $('[name="position_cur"]').val(value)
//console.log(value);
//processNotificationState(data)
document.dispatchEvent(new CustomEvent('handleNotifications', {detail: {'value': value}}))
//document.dispatchEvent(new CustomEvent('handleNotifications', {detail: {'value': value}}))
}

View File

@ -37,7 +37,9 @@ void BLETask::run() {
// https://www.uuidgenerator.net/
#define SERVICE_UUID "0000340f-0000-1000-8000-00805f9b34fb"
#define CHARACTERISTIC_UUID "000042ff-0000-1000-8000-00805f9b34fb"
#define SCALE_UUID "0000421f-0000-1000-8000-00805f9b34fb"
#define BUTTON_UUID "0000422f-0000-1000-8000-00805f9b34fb"
#define POSITION_CUR_UUID "602f75a0-697d-4690-8dd5-fa52781446d1"
// Create the BLE Device
BLEDevice::init("SmartKnob_0123");
@ -49,18 +51,40 @@ void BLETask::run() {
// Create the BLE Service
BLEService *pService = pServer->createService(SERVICE_UUID);
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
// Create a BLE Characteristic
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
pCharacteristic1 = pService->createCharacteristic(
POSITION_CUR_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
// Create a BLE Descriptor
pCharacteristic->addDescriptor(new BLE2902());
pCharacteristic1->addDescriptor(new BLE2902());
// // Create a BLE Characteristic
// pCharacteristic2 = pService->createCharacteristic(
// SCALE_UUID,
// BLECharacteristic::PROPERTY_READ |
// BLECharacteristic::PROPERTY_WRITE |
// BLECharacteristic::PROPERTY_NOTIFY |
// BLECharacteristic::PROPERTY_INDICATE
// );
// // Create a BLE Descriptor
// pCharacteristic2->addDescriptor(new BLE2902());
// // Create a BLE Characteristic
// pCharacteristic3 = pService->createCharacteristic(
// BUTTON_UUID,
// BLECharacteristic::PROPERTY_READ |
// BLECharacteristic::PROPERTY_WRITE |
// BLECharacteristic::PROPERTY_NOTIFY |
// BLECharacteristic::PROPERTY_INDICATE
// );
// // Create a BLE Descriptor
// pCharacteristic3->addDescriptor(new BLE2902());
// Start the service
pService->start();
@ -87,8 +111,8 @@ void BLETask::run() {
if (deviceConnected && !oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
delay(500);
pCharacteristic->notify(); // DOES NOT WORK
//delay(500);
//pCharacteristic->notify(); // DOES NOT WORK
}
if (xQueueReceive(knob_state_queue_, &state, portMAX_DELAY) == pdFALSE) {
@ -99,13 +123,26 @@ void BLETask::run() {
if (deviceConnected) {
if (current_position != state.current_position){
logf(state.current_position);
pCharacteristic->setValue((uint8_t*)&state.current_position, 4);
pCharacteristic->notify();
pCharacteristic1->setValue((uint8_t*)&state.current_position, 4);
pCharacteristic1->notify();
current_position = state.current_position;
delay(3); // bluetooth stack will go into congestion, if too many packets are sent, in 6 hours test i was able to go as low as 3ms
}
// if (num_positions != state.config.num_positions){
// pCharacteristic2->setValue((uint8_t*)&state.config.num_positions, 4);
// pCharacteristic2->notify();
// num_positions = state.config.num_positions;
// delay(3); // bluetooth stack will go into congestion, if too many packets are sent, in 6 hours test i was able to go as low as 3ms
// }
// if (press_value_unit_old != press_value_unit_){
// pCharacteristic1->setValue((uint8_t*)&press_value_unit_, 1);
// pCharacteristic1->notify();
// press_value_unit_old = press_value_unit_;
// delay(3);
// }
}
// // Check queue for pending requests from other tasks
@ -131,6 +168,10 @@ void BLETask::run() {
}
void BLETask::updateScale(int32_t new_press_value_unit){
press_value_unit_ = new_press_value_unit;
}
void BLETask::addListener(QueueHandle_t queue) {
listeners_.push_back(queue);
}

View File

@ -40,6 +40,8 @@ class BLETask : public Task<BLETask> {
// void playHaptic(bool press);
// void runCalibration();
void updateScale(int32_t press_value_unit);
QueueHandle_t getKnobStateQueue();
void addListener(QueueHandle_t queue);
@ -56,10 +58,16 @@ class BLETask : public Task<BLETask> {
// BLE Setup
BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
BLECharacteristic* pCharacteristic1 = NULL;
BLECharacteristic* pCharacteristic2 = NULL;
BLECharacteristic* pCharacteristic3 = NULL;
// bool BLE_CONNECTED;
bool oldDeviceConnected = false;
int32_t press_value_unit_;
int32_t press_value_unit_old;
int32_t current_position;
int32_t num_positions;
QueueHandle_t knob_state_queue_;

View File

@ -37,6 +37,7 @@ extends = base_config
board = esp32doit-devkit-v1
lib_deps =
${base_config.lib_deps}
;arduino-libraries/ArduinoBLE@^1.3.7
bodmer/TFT_eSPI@2.4.25
fastled/FastLED @ 3.5.0
bogde/HX711 @ 0.7.5