Berry: add BLE server/advertiser (#18494)

This commit is contained in:
Christian Baars 2023-04-26 08:39:29 +02:00 committed by GitHub
parent c8318248bb
commit f6763eb37b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 396 additions and 21 deletions

View File

@ -44,12 +44,17 @@ module MI32 (scope: global) {
* To use: `import BLE`
*******************************************************************/
extern int be_BLE_init(bvm *vm);
extern void be_BLE_reg_conn_cb(void* function, uint8_t *buffer);
BE_FUNC_CTYPE_DECLARE(be_BLE_reg_conn_cb, "", "cc");
extern void be_BLE_reg_adv_cb(void* function, uint8_t *buffer);
BE_FUNC_CTYPE_DECLARE(be_BLE_reg_adv_cb, "", "c[c]");
extern void be_BLE_reg_server_cb(void* function, uint8_t *buffer);
BE_FUNC_CTYPE_DECLARE(be_BLE_reg_server_cb, "", "c[c]");
extern void be_BLE_set_MAC(struct bvm *vm, uint8_t *buf, size_t size, uint8_t type);
BE_FUNC_CTYPE_DECLARE(be_BLE_set_MAC, "", "@(bytes)~[i]");
@ -73,6 +78,7 @@ BE_FUNC_CTYPE_DECLARE(be_BLE_adv_block, "", "@(bytes)~[i]");
/* @const_object_info_begin
module BLE (scope: global) {
init, func(be_BLE_init)
conn_cb, ctype_func(be_BLE_reg_conn_cb)
set_svc, ctype_func(be_BLE_set_service)
run, ctype_func(be_BLE_run)
@ -81,6 +87,7 @@ module BLE (scope: global) {
set_MAC, ctype_func(be_BLE_set_MAC)
adv_watch, ctype_func(be_BLE_adv_watch)
adv_block, ctype_func(be_BLE_adv_block)
serv_cb, ctype_func(be_BLE_reg_server_cb)
}
@const_object_info_end */

View File

@ -148,6 +148,7 @@ struct MI32connectionContextBerry_t{
NimBLEUUID serviceUUID;
NimBLEUUID charUUID;
uint16_t returnCharUUID;
uint16_t handle;
uint8_t MAC[6];
uint8_t * buffer;
uint8_t operation;
@ -162,17 +163,29 @@ struct MI32notificationBuffer_t{
uint16_t returnCharUUID;
};
struct BLEqueueBuffer_t{
union{
uint8_t *buffer;
int32_t value;
};
size_t length;
uint16_t returnCharUUID;
uint16_t handle;
uint16_t type;
};
struct {
// uint32_t period; // set manually in addition to TELE-period, is set to TELE-period after start
TaskHandle_t ScanTask = nullptr;
TaskHandle_t ConnTask = nullptr;
TaskHandle_t ServerTask = nullptr;
MI32connectionContextBerry_t *conCtx = nullptr;
union {
struct {
uint32_t init:1;
uint32_t connected:1;
uint32_t autoScan:1;
uint32_t canScan:1;
// uint32_t canScan:1;
uint32_t runningScan:1;
uint32_t updateScan:1;
uint32_t deleteScanTask:1;
@ -191,6 +204,11 @@ struct {
uint32_t triggerNextConnJob:1;
uint32_t readyForNextConnJob:1;
uint32_t discoverAttributes:1;
uint32_t triggerNextServerJob:1;
uint32_t readyForNextServerJob:1;
uint32_t triggerBerryServerCB:1;
uint32_t deleteServerTask:1;
};
uint32_t all = 0;
} mode;
@ -218,8 +236,9 @@ struct {
uint8_t HKinfoMsg = 0;
char hk_setup_code[11];
#endif //USE_MI_HOMEKIT
void *beConnCB;
void *beConnCB;
void *beAdvCB;
void *beServerCB;
uint8_t *beAdvBuf;
uint8_t infoMsg = 0;
} MI32;
@ -379,7 +398,7 @@ const char kMI32DeviceType[] PROGMEM = {"Flora|MJ_HT_V1|LYWSD02|LYWSD03|CGG1|CGD
const char kMI32_ConnErrorMsg[] PROGMEM = "no Error|could not connect|did disconnect|got no service|got no characteristic|can not read|can not notify|can not write|did not write|notify time out";
const char kMI32_BLEInfoMsg[] PROGMEM = "Scan ended|Got Notification|Did connect|Did disconnect|Still connected|Start passive scanning|Start active scanning";
const char kMI32_BLEInfoMsg[] PROGMEM = "Scan ended|Got Notification|Did connect|Did disconnect|Still connected|Start passive scanning|Start active scanning|Server characteristic set|Server advertisement set|Server scan response set|Server client did connect|Server client did disconnect";
const char kMI32_HKInfoMsg[] PROGMEM = "HAP core started|HAP core did not start!!|HAP controller disconnected|HAP controller connected|HAP outlet added";
@ -397,6 +416,33 @@ enum MI32_Commands { // commands useable in console or rules
enum MI32_TASK {
MI32_TASK_SCAN = 0,
MI32_TASK_CONN = 1,
MI32_TASK_SERV = 2,
};
enum BLE_CLIENT_OP {
BLE_OP_READ = 1,
BLE_OP_WRITE,
BLE_OP_SUBSCRIBE,
BLE_OP_UNSUBSCRIBE, //maybe used later
BLE_OP_DISCONNECT,
BLE_OP_GET_NOTIFICATION = 103,
};
enum BLE_SERVER_OP {
//commands
BLE_OP_SET_ADV = 201,
BLE_OP_SET_SCAN_RESP,
BLE_OP_SET_CHARACTERISTIC = 211,
//response
BLE_OP_ON_READ = 221,
BLE_OP_ON_WRITE,
BLE_OP_ON_UNSUBSCRIBE,
BLE_OP_ON_SUBSCRIBE_TO_NOTIFICATIONS,
BLE_OP_ON_SUBSCRIBE_TO_INDICATIONS,
BLE_OP_ON_SUBSCRIBE_TO_NOTIFICATIONS_AND_INDICATIONS,
BLE_OP_ON_CONNECT,
BLE_OP_ON_DISCONNECT,
BLE_OP_ON_STATUS,
};
enum MI32_ConnErrorMsg {
@ -419,7 +465,12 @@ enum MI32_BLEInfoMsg {
MI32_DID_DISCONNECT,
MI32_STILL_CONNECTED,
MI32_START_SCANNING_PASSIVE,
MI32_START_SCANNING_ACTIVE
MI32_START_SCANNING_ACTIVE,
MI32_SERV_CHARACTERISTIC_ADDED,
MI32_SERV_ADVERTISEMENT_ADDED,
MI32_SERV_SCANRESPONSE_ADDED,
MI32_SERV_CLIENT_CONNECTED,
MI32_SERV_CLIENT_DISCONNECTED
};
enum MI32_HKInfoMsg {

View File

@ -74,9 +74,11 @@ extern "C" {
/********************************************************************
** BLE - generic BLE functions
********************************************************************/
********************************************************************/
extern bool MI32checkBLEinitialization();
extern void MI32setBerryAdvCB(void* function, uint8_t *buffer);
extern void MI32setBerryConnCB(void* function, uint8_t *buffer);
extern void MI32setBerryServerCB(void* function, uint8_t *buffer);
extern bool MI32runBerryConnection(uint8_t operation, bbool response);
extern bool MI32setBerryCtxSvc(const char *Svc, bbool discoverAttributes);
extern bool MI32setBerryCtxChr(const char *Chr);
@ -84,12 +86,25 @@ extern "C" {
extern bool MI32addMACtoBlockList(uint8_t *MAC, uint8_t type);
extern bool MI32addMACtoWatchList(uint8_t *MAC, uint8_t type);
int be_BLE_init(bvm *vm);
int be_BLE_init(bvm *vm) {
if (MI32checkBLEinitialization() == true){
be_return(vm);
}
be_raise(vm, "ble_error", "BLE: device not initialized");
be_return_nil(vm);
}
void be_BLE_reg_conn_cb(void* function, uint8_t *buffer);
void be_BLE_reg_conn_cb(void* function, uint8_t *buffer){
MI32setBerryConnCB(function,buffer);
}
void be_BLE_reg_server_cb(void* function, uint8_t *buffer);
void be_BLE_reg_server_cb(void* function, uint8_t *buffer){
MI32setBerryServerCB(function,buffer);
}
void be_BLE_reg_adv_cb(void* function, uint8_t *buffer);
void be_BLE_reg_adv_cb(void* function, uint8_t *buffer){
if(function == 0){
@ -193,7 +208,9 @@ BLE.set_chr
BLE.set_MAC
BLE.run(op, optional: bool response)
be_BLE_op:
# client
1 read
2 write
3 subscribe
@ -205,8 +222,28 @@ be_BLE_op:
13 subscribe once, then disconnect
14 unsubscribe once, then disconnect - maybe later
#server
__commands
201 add/set advertisement
202 add/set scan response
211 add/set characteristic
__response
221 onRead
222 onWrite
223 unsubscribed
224 subscribed to notifications
225 subscribed to indications
226 subscribed to notifications and indications
227 onConnect
228 onDisconnect
229 onStatus
BLE.conn_cb(cb,buffer)
BLE.adv_cb(cb,buffer)
BLE.serv_cb(cb,buffer)
BLE.adv_watch(MAC)
BLE.adv_block(MAC)

View File

@ -163,9 +163,77 @@ class MI32AdvCallbacks: public NimBLEAdvertisedDeviceCallbacks {
};
};
static std::queue<BLEqueueBuffer_t> BLEmessageQueue;
class MI32ServerCallbacks: public NimBLEServerCallbacks {
void onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) {
BLEqueueBuffer_t q;
q.length = 6;
q.type = BLE_OP_ON_CONNECT;
q.buffer = new uint8_t[q.length];
memcpy(q.buffer,desc->peer_ota_addr.val,6);
BLEmessageQueue.push(q);
MI32.infoMsg = MI32_SERV_CLIENT_CONNECTED;
};
void onDisconnect(NimBLEServer* pServer) {
BLEqueueBuffer_t q;
q.length = 0;
q.type = BLE_OP_ON_DISCONNECT;
memset(MI32.conCtx->MAC,0,6);
BLEmessageQueue.push(q);
MI32.infoMsg = MI32_SERV_CLIENT_DISCONNECTED;
NimBLEDevice::startAdvertising();
};
};
class MI32CharacteristicCallbacks: public NimBLECharacteristicCallbacks {
void onRead(NimBLECharacteristic* pCharacteristic){
BLEqueueBuffer_t q;
q.length = 0;
q.type = BLE_OP_ON_READ;
q.returnCharUUID = pCharacteristic->getUUID().getNative()->u16.value;
q.handle = pCharacteristic->getHandle();
BLEmessageQueue.push(q);
};
void onWrite(NimBLECharacteristic* pCharacteristic) {
BLEqueueBuffer_t q;
q.type = BLE_OP_ON_WRITE;
q.returnCharUUID = pCharacteristic->getUUID().getNative()->u16.value;
q.handle = pCharacteristic->getHandle();
q.length = pCharacteristic->getDataLength();
q.buffer = new uint8_t[q.length];
memcpy(q.buffer,pCharacteristic->getValue(),pCharacteristic->getDataLength());
BLEmessageQueue.push(q);
};
/** The status returned in status is defined in NimBLECharacteristic.h.
* The value returned in code is the NimBLE host return code.
*/
void onStatus(NimBLECharacteristic* pCharacteristic, Status status, int code) {
BLEqueueBuffer_t q;
q.length = 0;
q.type = BLE_OP_ON_STATUS;
q.returnCharUUID = pCharacteristic->getUUID().getNative()->u16.value;
q.handle = pCharacteristic->getHandle();
q.value = code;
BLEmessageQueue.push(q);
};
void onSubscribe(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc, uint16_t subValue) {
BLEqueueBuffer_t q;
q.length = 0;
q.type = BLE_OP_ON_UNSUBSCRIBE + subValue;
q.returnCharUUID = pCharacteristic->getUUID().getNative()->u16.value;
q.handle = pCharacteristic->getHandle();
BLEmessageQueue.push(q);
};
};
static MI32AdvCallbacks MI32ScanCallbacks;
static MI32SensorCallback MI32SensorCB;
static MI32CharacteristicCallbacks MI32ChrCallback;
static NimBLEClient* MI32Client;
static std::queue<MI32notificationBuffer_t> MI32NotificationQueue;
@ -653,8 +721,9 @@ void MI32Init(void) {
if (!MI32.mode.init) {
NimBLEDevice::setScanFilterMode(CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE);
NimBLEDevice::setScanDuplicateCacheSize(40); // will not be perfect for every situation (few vs many BLE devices nearby)
NimBLEDevice::init("");
AddLog(LOG_LEVEL_INFO,PSTR("M32: Init BLE device"));
const std::string name(TasmotaGlobal.hostname);
NimBLEDevice::init(name);
AddLog(LOG_LEVEL_INFO,PSTR("M32: Init BLE device: %s"),TasmotaGlobal.hostname);
MI32.mode.init = 1;
MI32.mode.readyForNextConnJob = 1;
MI32StartTask(MI32_TASK_SCAN); // Let's get started !!
@ -672,21 +741,41 @@ void MI32Init(void) {
\*********************************************************************************************/
extern "C" {
bool MI32checkBLEinitialization(){
return (MI32.mode.init && Settings->flag5.mi32_enable);
}
bool MI32runBerryServer(uint16_t operation, bool response){
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);
if(MI32.mode.readyForNextServerJob == 0){
MI32.mode.triggerNextServerJob = 0;
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: old server job not finished yet!!"));
return false;
}
MI32.mode.triggerNextServerJob = 1;
return true;
}
bool MI32runBerryConnection(uint8_t operation, bool response){
if(MI32.conCtx != nullptr){
if(operation > 200){
return MI32runBerryServer(operation,response);
}
MI32.conCtx->oneOp = (operation > 9);
MI32.conCtx->operation = operation%10;
MI32.conCtx->response = response;
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: 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){
MI32StartConnectionTask();
}
else{
if(MI32.mode.connected){
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: continue connection job"));
AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: continue connection job"));
MI32.mode.triggerNextConnJob = 1;
if(!MI32.mode.readyForNextConnJob){
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: old connection job not finished yet!!"));
AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: old connection job not finished yet!!"));
}
}
else{
@ -704,7 +793,24 @@ extern "C" {
}
MI32.conCtx->buffer = buffer;
MI32.beConnCB = function;
AddLog(LOG_LEVEL_INFO,PSTR("M32: Connection Ctx created"));
AddLog(LOG_LEVEL_INFO,PSTR("BLE: Connection Ctx created"));
}
void MI32setBerryServerCB(void* function, uint8_t *buffer){
if(function == nullptr || buffer == nullptr)
{
MI32.mode.deleteServerTask = 1;
MI32.beServerCB = nullptr;
AddLog(LOG_LEVEL_INFO,PSTR("BLE: Server session stopping"));
return;
}
if(MI32.conCtx == nullptr){
MI32.conCtx = new MI32connectionContextBerry_t;
}
MI32.conCtx->buffer = buffer;
MI32.beServerCB = function;
MI32StartTask(MI32_TASK_SERV);
AddLog(LOG_LEVEL_INFO,PSTR("BLE: Server Ctx created"));
}
bool MI32setBerryCtxSvc(const char *Svc, bool discoverAttributes){
@ -723,7 +829,7 @@ extern "C" {
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: CHR: %s"),MI32.conCtx->charUUID.toString().c_str());
uint16_t _uuid = MI32.conCtx->charUUID.getNative()->u16.value; //if not "notify op" -> present requested characteristic as return UUID
MI32.conCtx->returnCharUUID = _uuid;
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: return UUID: %04x"),MI32.conCtx->returnCharUUID);
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: return 16-bit UUID: %04x"),MI32.conCtx->returnCharUUID);
return true;
}
return false;
@ -846,7 +952,7 @@ extern "C" {
case 5: //HAP_EVENT_PAIRING_STARTED
MI32suspendScanTask();
default:
vTaskResume(MI32.ScanTask);
MI32resumeScanTask();
}
if(event==4){
MI32.HKinfoMsg = MI32_HAP_CONTROLLER_DISCONNECTED;
@ -1042,7 +1148,11 @@ void MI32saveConfig(){
\*********************************************************************************************/
void MI32suspendScanTask(void){
if (MI32.ScanTask != nullptr) vTaskSuspend(MI32.ScanTask);
if (MI32.ScanTask != nullptr && MI32.mode.runningScan == 1) vTaskSuspend(MI32.ScanTask);
}
void MI32resumeScanTask(void){
if (MI32.ScanTask != nullptr && MI32.mode.runningScan == 1) vTaskResume(MI32.ScanTask);
}
void MI32StartTask(uint32_t task){
@ -1057,15 +1167,22 @@ void MI32StartTask(uint32_t task){
MI32.mode.deleteScanTask = 1;
MI32StartConnectionTask();
break;
case MI32_TASK_SERV:
MI32.mode.deleteScanTask = 1;
MI32StartServerTask();
break;
default:
break;
}
}
// Scan task section
void MI32StartScanTask(){
if (MI32.mode.connected) return;
if (MI32.mode.connected == 1) return;
if(MI32.ScanTask!=nullptr) vTaskDelete(MI32.ScanTask);
MI32.mode.runningScan = 1;
MI32.mode.deleteScanTask = 0;
xTaskCreatePinnedToCore(
MI32ScanTask, /* Function to implement the task */
"MI32ScanTask", /* Name of the task */
@ -1098,13 +1215,14 @@ void MI32ScanTask(void *pvParameters){
uint32_t timer = 0;
for(;;){
vTaskDelay(1000/ portTICK_PERIOD_MS);
if(MI32.mode.deleteScanTask){
vTaskDelay(100/ portTICK_PERIOD_MS);
if(MI32.mode.deleteScanTask == 1){
MI32Scan->stop();
MI32.mode.runningScan = 0;
MI32.ScanTask = nullptr;
break;
}
if(MI32.mode.updateScan){
if(MI32.mode.updateScan == 1){
MI32Scan->stop();
MI32Scan->setActiveScan(MI32.option.activeScan == 1);
MI32Scan->start(0,true);
@ -1115,6 +1233,8 @@ void MI32ScanTask(void *pvParameters){
vTaskDelete( NULL );
}
// connection task section
bool MI32ConnectActiveSensor(){ // only use inside a task !!
if(MI32.conCtx->operation == 5) {
return false;
@ -1307,6 +1427,144 @@ void MI32ConnectionTask(void *pvParameters){
vTaskDelete( NULL );
}
// server task section
bool MI32StartServerTask(){
AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: Server task ... start"));
MI32NotificationQueue = {};
xTaskCreatePinnedToCore(
MI32ServerTask, /* Function to implement the task */
"MI32ServerTask", /* Name of the task */
8192, /* Stack size in words */
NULL, /* Task input parameter */
2, /* Priority of the task */
&MI32.ServerTask, /* Task handle. */
0); /* Core where the task should run */
return true;
}
void MI32ServerSetAdv(NimBLEServer *pServer, std::vector<NimBLEService*>& servicesToStart, bool &shallStartServices);
void MI32ServerSetAdv(NimBLEServer *pServer, std::vector<NimBLEService*>& servicesToStart, bool &shallStartServices){
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
BLEqueueBuffer_t q;
q.length = 0;
if(shallStartServices && MI32.conCtx->operation == BLE_OP_SET_ADV){
q.buffer = new uint8_t[256];
for (auto & pService : servicesToStart) {
pService->start();
}
shallStartServices = false; // only do this at the first run
if(servicesToStart.size() != 0){
pServer->start(); // only start server when svc and chr do exist
uint32_t idx = 0;
for (auto & pService : servicesToStart) {
std::vector<NimBLECharacteristic *> characteristics = pService->getCharacteristics();
for (auto & pCharacteristic : characteristics) {
uint16_t handle = pCharacteristic->getHandle(); // now we have handles, so pass them to Berry
q.buffer[idx] = (uint8_t)handle>>8;
q.buffer[idx+1] = (uint8_t)handle&0xff;
if (idx > 254) break; // limit to 127 characteristics
idx += 2;
}
}
q.length = idx;
}
servicesToStart.clear(); // release vector
}
NimBLEAdvertisementData adv;
adv.addData((char *)&MI32.conCtx->buffer[1], MI32.conCtx->buffer[0]);
if(MI32.conCtx->operation == BLE_OP_SET_ADV){
pAdvertising->setAdvertisementData(adv); // replace whole advertisement with our custom data from the Berry side
pAdvertising->start();
} else
{
pAdvertising->setScanResponseData(adv);
pAdvertising->setScanResponse(true);
}
MI32.infoMsg = MI32_SERV_SCANRESPONSE_ADDED + (MI32.conCtx->operation - BLE_OP_SET_SCAN_RESP); // .. ADV or SCAN RESPONSE
q.type = MI32.conCtx->operation;
q.returnCharUUID = 0; // does not matter
q.handle = 0; //dito
BLEmessageQueue.push(q);
}
void MI32ServerSetCharacteristic(NimBLEServer *pServer, std::vector<NimBLEService*>& servicesToStart, bool &shallStartServices);
void MI32ServerSetCharacteristic(NimBLEServer *pServer, std::vector<NimBLEService*>& servicesToStart, bool &shallStartServices){
MI32.conCtx->error = MI32_CONN_NO_ERROR;
NimBLEService *pService = pServer->getServiceByUUID(MI32.conCtx->serviceUUID); // retrieve ...
if(pService == nullptr){
pService = pServer->createService(MI32.conCtx->serviceUUID); //... or create service.
if(pService == nullptr){
MI32.conCtx->error = MI32_CONN_NO_SERVICE;
return;
}
if(shallStartServices){
servicesToStart.push_back(pService);
}
}
NimBLECharacteristic *pCharacteristic = pService->getCharacteristic(MI32.conCtx->charUUID); // again retrieve ...
if(pCharacteristic == nullptr){
uint32_t _writeRSP = MI32.conCtx->response ? NIMBLE_PROPERTY::WRITE : NIMBLE_PROPERTY::WRITE_NR;
pCharacteristic = pService->createCharacteristic(MI32.conCtx->charUUID,
NIMBLE_PROPERTY::READ |
_writeRSP |
NIMBLE_PROPERTY::NOTIFY |
NIMBLE_PROPERTY::INDICATE); //... or create characteristic.
if(pCharacteristic == nullptr){
MI32.conCtx->error = MI32_CONN_NO_CHARACTERISTIC;
return;
}
pCharacteristic->setCallbacks(&MI32ChrCallback);
MI32.infoMsg = MI32_SERV_CHARACTERISTIC_ADDED;
}
pCharacteristic->setValue(MI32.conCtx->buffer + 1, MI32.conCtx->buffer[0]); // set value
pCharacteristic->notify(true); // always notify .. for now
BLEqueueBuffer_t q;
q.length = 0;
q.type = BLE_OP_SET_CHARACTERISTIC;
q.returnCharUUID = pCharacteristic->getUUID().getNative()->u16.value;
q.handle = pCharacteristic->getHandle(); // this returns "-1", no valid handle yet :(
BLEmessageQueue.push(q);
}
void MI32ServerTask(void *pvParameters){
MI32.conCtx->error = MI32_CONN_NO_ERROR;
NimBLEServer *pServer = NimBLEDevice::createServer();
pServer->setCallbacks(new MI32ServerCallbacks());
MI32.mode.readyForNextServerJob = 1;
MI32.mode.deleteServerTask = 0;
std::vector<NimBLEService*> servicesToStart;
bool shallStartServices = true; //will start service at the first call MI32ServerSetAdv()
for(;;){
while(MI32.mode.triggerNextServerJob == 0){
if(MI32.mode.deleteServerTask == 1){
delete MI32.conCtx;
MI32.conCtx = nullptr;
pServer->stopAdvertising();
MI32StartTask(MI32_TASK_SCAN);
vTaskDelete( NULL );
}
vTaskDelay(50/ portTICK_PERIOD_MS);
}
MI32.mode.readyForNextServerJob = 0;
switch(MI32.conCtx->operation){
case BLE_OP_SET_ADV: case BLE_OP_SET_SCAN_RESP:
MI32ServerSetAdv(pServer, servicesToStart, shallStartServices);
break;
case BLE_OP_SET_CHARACTERISTIC:
MI32ServerSetCharacteristic(pServer, servicesToStart, shallStartServices);
break;
}
MI32.mode.triggerNextServerJob = 0;
MI32.mode.readyForNextServerJob = 1;
MI32.mode.triggerBerryServerCB = 1;
}
}
/*********************************************************************************************\
* parse the response from advertisements
\*********************************************************************************************/
@ -1720,6 +1978,28 @@ void MI32Every50mSecond(){
}
MI32.mode.triggerBerryConnCB = 0;
}
if(!BLEmessageQueue.empty()){
BLEqueueBuffer_t q = BLEmessageQueue.front();
BLEmessageQueue.pop();
MI32.conCtx->returnCharUUID = q.returnCharUUID;
MI32.conCtx->handle = q.handle;
MI32.conCtx->operation = q.type;
MI32.conCtx->error = 0;
if(q.length != 0){
MI32.conCtx->buffer[0] = q.length;
memcpy(MI32.conCtx->buffer + 1,q.buffer,q.length);
delete q.buffer;
}
if(MI32.beServerCB != nullptr){
void (*func_ptr)(int, int, int, int) = (void (*)(int, int, int, int))MI32.beServerCB;
char _message[32];
GetTextIndexed(_message, sizeof(_message), MI32.conCtx->error, kMI32_ConnErrorMsg);
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: BryCbMsg: %s"),_message);
func_ptr(MI32.conCtx->error, MI32.conCtx->operation , MI32.conCtx->returnCharUUID, MI32.conCtx->handle);
}
}
if(MI32.infoMsg > 0){
char _message[32];
GetTextIndexed(_message, sizeof(_message), MI32.infoMsg-1, kMI32_BLEInfoMsg);
@ -2057,7 +2337,7 @@ void MI32InitGUI(void){
WSContentSend_P(PSTR("</div>"));
WSContentSpaceButton(BUTTON_MAIN);
WSContentStop();
vTaskResume(MI32.ScanTask);
MI32resumeScanTask();
}
void MI32HandleWebGUI(void){
@ -2246,7 +2526,7 @@ void MI32Show(bool json)
MI32addHistory(MI32.energy_history,Energy->active_power[0],100); //TODO: which value??
#endif //USE_MI_ESP32_ENERGY
#endif //USE_MI_EXT_GUI
vTaskResume(MI32.ScanTask);
MI32resumeScanTask();
#ifdef USE_WEBSERVER
} else {
MI32suspendScanTask();
@ -2309,7 +2589,7 @@ void MI32Show(bool json)
#endif //USE_MI_EXT_GUI
#endif // USE_WEBSERVER
}
vTaskResume(MI32.ScanTask);
MI32resumeScanTask();
}
int ExtStopBLE(){