MI32 legacy: add optional argument to BLE.run() (#20431)

* add optional argument to BLE.run()

* set default of scan response to NO
This commit is contained in:
Christian Baars 2024-01-09 09:10:45 +01:00 committed by GitHub
parent 2f6ab10146
commit 81fac80859
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 94 additions and 35 deletions

View File

@ -64,8 +64,8 @@ BE_FUNC_CTYPE_DECLARE(be_BLE_set_MAC, "", "@(bytes)~[i]");
extern void be_BLE_set_characteristic(struct bvm *vm, const char *Chr); extern void be_BLE_set_characteristic(struct bvm *vm, const char *Chr);
BE_FUNC_CTYPE_DECLARE(be_BLE_set_characteristic, "", "@s"); BE_FUNC_CTYPE_DECLARE(be_BLE_set_characteristic, "", "@s");
extern void be_BLE_run(struct bvm *vm, uint8_t operation, bbool response); extern void be_BLE_run(struct bvm *vm, uint8_t operation, bbool response, int32_t arg1);
BE_FUNC_CTYPE_DECLARE(be_BLE_run, "", "@i[b]"); BE_FUNC_CTYPE_DECLARE(be_BLE_run, "", "@i[bi]");
extern void be_BLE_set_service(struct bvm *vm, const char *Svc, bbool discoverAttributes); extern void be_BLE_set_service(struct bvm *vm, const char *Svc, bbool discoverAttributes);
BE_FUNC_CTYPE_DECLARE(be_BLE_set_service, "", "@s[b]"); BE_FUNC_CTYPE_DECLARE(be_BLE_set_service, "", "@s[b]");

View File

@ -67,7 +67,7 @@ void NimBLEAdvertising::reset() {
m_advParams.disc_mode = BLE_GAP_DISC_MODE_GEN; m_advParams.disc_mode = BLE_GAP_DISC_MODE_GEN;
m_customAdvData = false; m_customAdvData = false;
m_customScanResponseData = false; m_customScanResponseData = false;
m_scanResp = true; m_scanResp = false;
m_advDataSet = false; m_advDataSet = false;
// Set this to non-zero to prevent auto start if host reset before started by app. // Set this to non-zero to prevent auto start if host reset before started by app.
m_duration = BLE_HS_FOREVER; m_duration = BLE_HS_FOREVER;

View File

@ -156,11 +156,13 @@ struct MI32connectionContextBerry_t{
NimBLEUUID charUUID; NimBLEUUID charUUID;
uint16_t returnCharUUID; uint16_t returnCharUUID;
uint16_t handle; uint16_t handle;
uint8_t MAC[6];
uint8_t * buffer; uint8_t * buffer;
uint8_t MAC[6];
uint8_t operation; uint8_t operation;
uint8_t addrType; uint8_t addrType;
int error; int error;
int32_t arg1;
bool hasArg1;
bool oneOp; bool oneOp;
bool response; bool response;
}; };

View File

@ -80,7 +80,7 @@ extern "C" {
extern void MI32setBerryAdvCB(void* function, uint8_t *buffer); extern void MI32setBerryAdvCB(void* function, uint8_t *buffer);
extern void MI32setBerryConnCB(void* function, uint8_t *buffer); extern void MI32setBerryConnCB(void* function, uint8_t *buffer);
extern void MI32setBerryServerCB(void* function, uint8_t *buffer); extern void MI32setBerryServerCB(void* function, uint8_t *buffer);
extern bool MI32runBerryConnection(uint8_t operation, bbool response); extern bool MI32runBerryConnection(uint8_t operation, bbool response, int32_t *arg1);
extern bool MI32setBerryCtxSvc(const char *Svc, bbool discoverAttributes); extern bool MI32setBerryCtxSvc(const char *Svc, bbool discoverAttributes);
extern bool MI32setBerryCtxChr(const char *Chr); extern bool MI32setBerryCtxChr(const char *Chr);
extern bool MI32setBerryCtxMAC(uint8_t *MAC, uint8_t type); extern bool MI32setBerryCtxMAC(uint8_t *MAC, uint8_t type);
@ -161,13 +161,19 @@ extern "C" {
be_raisef(vm, "ble_error", "BLE: could not set characteristic"); be_raisef(vm, "ble_error", "BLE: could not set characteristic");
} }
void be_BLE_run(struct bvm *vm, uint8_t operation, bbool response); void be_BLE_run(struct bvm *vm, uint8_t operation, bbool response, int32_t arg1);
void be_BLE_run(struct bvm *vm, uint8_t operation, bbool response){ void be_BLE_run(struct bvm *vm, uint8_t operation, bbool response, int32_t arg1){
int32_t argc = be_top(vm); // Get the number of arguments
bool _response = false; bool _response = false;
if(response){ if(response){
_response = response; _response = response;
} }
if (MI32runBerryConnection(operation,_response)) return; int32_t *ptr_arg1 = nullptr;
int32_t _arg1 = arg1;
if(argc == 3){
ptr_arg1 = &_arg1;
}
if (MI32runBerryConnection(operation, _response, ptr_arg1)) return;
be_raisef(vm, "ble_error", "BLE: could not run operation"); be_raisef(vm, "ble_error", "BLE: could not run operation");
} }

View File

@ -93,6 +93,7 @@ class MI32SensorCallback : public NimBLEClientCallbacks {
MI32.infoMsg = MI32_DID_CONNECT; MI32.infoMsg = MI32_DID_CONNECT;
MI32.mode.willConnect = 0; MI32.mode.willConnect = 0;
MI32.mode.connected = 1; MI32.mode.connected = 1;
pclient->updateConnParams(8,11,0,1000);
} }
void onDisconnect(NimBLEClient* pclient) { void onDisconnect(NimBLEClient* pclient) {
MI32.mode.connected = 0; MI32.mode.connected = 0;
@ -250,7 +251,7 @@ void MI32notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pD
memcpy(item.buffer,pData,length); memcpy(item.buffer,pData,length);
item.header.returnCharUUID = pRemoteCharacteristic->getUUID().getNative()->u16.value; item.header.returnCharUUID = pRemoteCharacteristic->getUUID().getNative()->u16.value;
item.header.handle = pRemoteCharacteristic->getHandle(); item.header.handle = pRemoteCharacteristic->getHandle();
xRingbufferSend(BLERingBufferQueue, (const void*)&item, sizeof(BLERingBufferItem_t) + length , pdMS_TO_TICKS(1)); xRingbufferSend(BLERingBufferQueue, (const void*)&item, sizeof(BLERingBufferItem_t) + length , pdMS_TO_TICKS(5));
MI32.mode.readingDone = 1; MI32.mode.readingDone = 1;
MI32.infoMsg = MI32_GOT_NOTIFICATION; MI32.infoMsg = MI32_GOT_NOTIFICATION;
return; return;
@ -711,9 +712,8 @@ extern "C" {
MI32BLELoop(); MI32BLELoop();
} }
bool MI32runBerryServer(uint16_t operation, bool response){ bool MI32runBerryServer(uint16_t operation){
MI32.conCtx->operation = operation; MI32.conCtx->operation = operation;
MI32.conCtx->response = response;
AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: Berry server op: %d, response: %u"),MI32.conCtx->operation, MI32.conCtx->response); AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: Berry server op: %d, response: %u"),MI32.conCtx->operation, MI32.conCtx->response);
if(MI32.mode.readyForNextServerJob == 0){ if(MI32.mode.readyForNextServerJob == 0){
MI32.mode.triggerNextServerJob = 0; MI32.mode.triggerNextServerJob = 0;
@ -724,14 +724,22 @@ extern "C" {
return true; return true;
} }
bool MI32runBerryConnection(uint8_t operation, bool response){ bool MI32runBerryConnection(uint8_t operation, bool response, int32_t* arg1){
if(MI32.conCtx != nullptr){ if(MI32.conCtx != nullptr){
if(arg1 != nullptr){
MI32.conCtx->arg1 = *arg1;
MI32.conCtx->hasArg1 = true;
AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: arg1: %u"),MI32.conCtx->arg1);
}
else{
MI32.conCtx->hasArg1 = false;
}
MI32.conCtx->response = response;
if(operation > 200){ if(operation > 200){
return MI32runBerryServer(operation,response); return MI32runBerryServer(operation);
} }
MI32.conCtx->oneOp = (operation > 9); MI32.conCtx->oneOp = (operation > 9);
MI32.conCtx->operation = operation%10; MI32.conCtx->operation = operation%10;
MI32.conCtx->response = response;
AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: Berry connection op: %d, addrType: %d, oneOp: %u, response: %u"),MI32.conCtx->operation, MI32.conCtx->addrType, MI32.conCtx->oneOp, MI32.conCtx->response); AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: Berry connection op: %d, addrType: %d, oneOp: %u, response: %u"),MI32.conCtx->operation, MI32.conCtx->addrType, MI32.conCtx->oneOp, MI32.conCtx->response);
if(MI32.conCtx->oneOp){ if(MI32.conCtx->oneOp){
MI32StartConnectionTask(); MI32StartConnectionTask();
@ -1214,7 +1222,7 @@ bool MI32StartConnectionTask(){
2, /* Priority of the task */ 2, /* Priority of the task */
&MI32.ConnTask, /* Task handle. */ &MI32.ConnTask, /* Task handle. */
0); /* Core where the task should run */ 0); /* Core where the task should run */
return true; return true;
} }
void MI32ConnectionTask(void *pvParameters){ void MI32ConnectionTask(void *pvParameters){
@ -1240,7 +1248,7 @@ void MI32ConnectionTask(void *pvParameters){
timer++; timer++;
vTaskDelay(10/ portTICK_PERIOD_MS); vTaskDelay(10/ portTICK_PERIOD_MS);
} }
if(MI32.mode.discoverAttributes){ if(MI32.mode.discoverAttributes || MI32.conCtx->hasArg1){ // explicit or in the first run with selection by handle
MI32Client->discoverAttributes(); // solves connection problems on i.e. yeelight dimmer MI32Client->discoverAttributes(); // solves connection problems on i.e. yeelight dimmer
} }
NimBLERemoteService* pSvc = nullptr; NimBLERemoteService* pSvc = nullptr;
@ -1271,7 +1279,12 @@ void MI32ConnectionTask(void *pvParameters){
MI32ConnectionGetServices(); MI32ConnectionGetServices();
} }
else{ else{
pSvc = MI32Client->getService(MI32.conCtx->serviceUUID); if(MI32.conCtx->hasArg1){
pSvc = nullptr; // invalidate possible dangling service from last operation
}
else{
pSvc = MI32Client->getService(MI32.conCtx->serviceUUID);
}
} }
if(pSvc) { if(pSvc) {
@ -1279,9 +1292,12 @@ void MI32ConnectionTask(void *pvParameters){
MI32ConnectionGetCharacteristics(pSvc); MI32ConnectionGetCharacteristics(pSvc);
} }
else{ else{
pChr = pSvc->getCharacteristic(MI32.conCtx->charUUID); pChr = pSvc->getCharacteristic(MI32.conCtx->charUUID);
} }
} }
else if(MI32.conCtx->hasArg1){
pChr = MI32Client->getCharacteristic(MI32.conCtx->arg1); // get by handle, overriding svc and chr values
}
else{ else{
if(MI32.conCtx->operation != 6){ if(MI32.conCtx->operation != 6){
MI32.conCtx->error = MI32_CONN_NO_SERVICE; MI32.conCtx->error = MI32_CONN_NO_SERVICE;
@ -1291,12 +1307,13 @@ void MI32ConnectionTask(void *pvParameters){
switch(MI32.conCtx->operation){ switch(MI32.conCtx->operation){
case 1: case 1:
if(pChr->canRead()) { if(pChr->canRead()) {
NimBLEAttValue _val = pChr->readValue(); NimBLEAttValue _val = pChr->readValue();
MI32.conCtx->buffer[0] = _val.size(); MI32.conCtx->buffer[0] = _val.size();
memcpy( MI32.conCtx->buffer + 1,_val.data(),MI32.conCtx->buffer[0]); memcpy( MI32.conCtx->buffer + 1,_val.data(),MI32.conCtx->buffer[0]);
MI32.conCtx->handle = pChr->getHandle();
} }
else{ else{
MI32.conCtx->error = MI32_CONN_CAN_NOT_READ; MI32.conCtx->error = MI32_CONN_CAN_NOT_READ;
} }
break; break;
case 2: case 2:
@ -1304,6 +1321,7 @@ void MI32ConnectionTask(void *pvParameters){
uint8_t len = MI32.conCtx->buffer[0]; uint8_t len = MI32.conCtx->buffer[0];
if(pChr->writeValue(MI32.conCtx->buffer + 1,len,MI32.conCtx->response & !pChr->canWriteNoResponse())) { // falls always back to "no response" if server provides both options if(pChr->writeValue(MI32.conCtx->buffer + 1,len,MI32.conCtx->response & !pChr->canWriteNoResponse())) { // falls always back to "no response" if server provides both options
// AddLog(LOG_LEVEL_DEBUG,PSTR("M32: write op done")); // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: write op done"));
MI32.conCtx->handle = pChr->getHandle();
} }
else{ else{
MI32.conCtx->error = MI32_CONN_DID_NOT_WRITE; MI32.conCtx->error = MI32_CONN_DID_NOT_WRITE;
@ -1322,15 +1340,31 @@ void MI32ConnectionTask(void *pvParameters){
break; break;
} }
} }
charvector = pSvc->getCharacteristics(true); // always try to subscribe to all characteristics with the same UUID if(MI32.conCtx->hasArg1){ // characteristic selected by handle
for (auto &it: *charvector) { if (pChr->canNotify()) {
if (it->getUUID() == MI32.conCtx->charUUID) { if(!pChr->subscribe(true, MI32notifyCB, MI32.conCtx->response)) {
if (it->canNotify()) { MI32.conCtx->error = MI32_CONN_CAN_NOT_NOTIFY; // will return the last result only ATM, maybe check differently
if(!it->subscribe(true, MI32notifyCB, MI32.conCtx->response)) { }
MI32.conCtx->error = MI32_CONN_CAN_NOT_NOTIFY; // will return the last result only ATM, maybe check differently }
}
else { // characteristic selected by UUID
charvector = pSvc->getCharacteristics(true); // always try to subscribe to all characteristics with the same UUID
uint32_t position = 1;
for (auto &it: *charvector) {
if (it->getUUID() == MI32.conCtx->charUUID) {
if (it->canNotify()) {
if(!it->subscribe(true, MI32notifyCB, MI32.conCtx->response)) {
MI32.conCtx->error = MI32_CONN_CAN_NOT_NOTIFY; // will return the last result only ATM, maybe check differently
}
else{
MI32.conCtx->buffer[position++] = it->getHandle() >> 8;
MI32.conCtx->buffer[position++] = it->getHandle() & 0xff;
MI32.conCtx->handle = it->getHandle();
}
} }
} }
} }
MI32.conCtx->buffer[0] = position - 1;
} }
break; break;
default: default:
@ -1403,7 +1437,7 @@ bool MI32StartServerTask(){
2, /* Priority of the task */ 2, /* Priority of the task */
&MI32.ServerTask, /* Task handle. */ &MI32.ServerTask, /* Task handle. */
0); /* Core where the task should run */ 0); /* Core where the task should run */
return true; return true;
} }
void MI32ServerSetAdv(NimBLEServer *pServer, std::vector<NimBLEService*>& servicesToStart, bool &shallStartServices); void MI32ServerSetAdv(NimBLEServer *pServer, std::vector<NimBLEService*>& servicesToStart, bool &shallStartServices);
@ -1416,6 +1450,15 @@ void MI32ServerSetAdv(NimBLEServer *pServer, std::vector<NimBLEService*>& servic
*/ */
void MI32ServerSetAdv(NimBLEServer *pServer, std::vector<NimBLEService*>& servicesToStart, bool &shallStartServices){ void MI32ServerSetAdv(NimBLEServer *pServer, std::vector<NimBLEService*>& servicesToStart, bool &shallStartServices){
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising(); NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
/** optional argument arg1
BLE_GAP_CONN_MODE_NON (0) - not connectable advertising
BLE_GAP_CONN_MODE_DIR (1) - directed connectable advertising
BLE_GAP_CONN_MODE_UND (2) - undirected connectable advertising
*/
if(MI32.conCtx->hasArg1){
pAdvertising->setAdvertisementType(MI32.conCtx->arg1);
// AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: AdvertisementType: %u"),MI32.conCtx->arg1);
}
struct{ struct{
BLERingBufferItem_t header; BLERingBufferItem_t header;
uint8_t buffer[255]; uint8_t buffer[255];
@ -1447,7 +1490,10 @@ void MI32ServerSetAdv(NimBLEServer *pServer, std::vector<NimBLEService*>& servic
adv.addData((char *)&MI32.conCtx->buffer[1], MI32.conCtx->buffer[0]); adv.addData((char *)&MI32.conCtx->buffer[1], MI32.conCtx->buffer[0]);
if(MI32.conCtx->operation == BLE_OP_SET_ADV){ if(MI32.conCtx->operation == BLE_OP_SET_ADV){
pAdvertising->setAdvertisementData(adv); // replace whole advertisement with our custom data from the Berry side pAdvertising->setAdvertisementData(adv); // replace whole advertisement with our custom data from the Berry side
pAdvertising->start(); if(pAdvertising->isAdvertising() == false && !shallStartServices){ // first advertisement
vTaskDelay(1000/ portTICK_PERIOD_MS); // work around to prevent crash on start
pAdvertising->start();
}
} else } else
{ {
pAdvertising->setScanResponseData(adv); pAdvertising->setScanResponseData(adv);
@ -1486,11 +1532,16 @@ void MI32ServerSetCharacteristic(NimBLEServer *pServer, std::vector<NimBLEServic
NimBLECharacteristic *pCharacteristic = pService->getCharacteristic(MI32.conCtx->charUUID); // again retrieve ... NimBLECharacteristic *pCharacteristic = pService->getCharacteristic(MI32.conCtx->charUUID); // again retrieve ...
if(pCharacteristic == nullptr){ if(pCharacteristic == nullptr){
uint32_t _writeRSP = MI32.conCtx->response ? NIMBLE_PROPERTY::WRITE : NIMBLE_PROPERTY::WRITE_NR; uint32_t _writeRSP = MI32.conCtx->response ? NIMBLE_PROPERTY::WRITE : NIMBLE_PROPERTY::WRITE_NR;
uint32_t _property = NIMBLE_PROPERTY::READ |
_writeRSP |
NIMBLE_PROPERTY::NOTIFY |
NIMBLE_PROPERTY::INDICATE; // default to "all"
if(MI32.conCtx->hasArg1){
_property = MI32.conCtx->arg1; // override with optional argument
// AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: _property: %u"),_property);
}
pCharacteristic = pService->createCharacteristic(MI32.conCtx->charUUID, pCharacteristic = pService->createCharacteristic(MI32.conCtx->charUUID,
NIMBLE_PROPERTY::READ | _property); //... or create characteristic.
_writeRSP |
NIMBLE_PROPERTY::NOTIFY |
NIMBLE_PROPERTY::INDICATE); //... or create characteristic.
if(pCharacteristic == nullptr){ if(pCharacteristic == nullptr){
MI32.conCtx->error = MI32_CONN_NO_CHARACTERISTIC; MI32.conCtx->error = MI32_CONN_NO_CHARACTERISTIC;
return; return;
@ -1499,7 +1550,7 @@ void MI32ServerSetCharacteristic(NimBLEServer *pServer, std::vector<NimBLEServic
MI32.infoMsg = MI32_SERV_CHARACTERISTIC_ADDED; MI32.infoMsg = MI32_SERV_CHARACTERISTIC_ADDED;
} }
pCharacteristic->setValue(MI32.conCtx->buffer + 1, MI32.conCtx->buffer[0]); // set value pCharacteristic->setValue(MI32.conCtx->buffer + 1, MI32.conCtx->buffer[0]); // set value
pCharacteristic->notify(true); // always notify .. for now pCharacteristic->notify(true); // TODO: fallback to indication
struct{ struct{
BLERingBufferItem_t header; BLERingBufferItem_t header;
} item; } item;