mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-23 10:46:31 +00:00
Berry: add BLE server/advertiser (#18494)
This commit is contained in:
parent
c8318248bb
commit
f6763eb37b
@ -44,12 +44,17 @@ module MI32 (scope: global) {
|
|||||||
* To use: `import BLE`
|
* To use: `import BLE`
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
|
|
||||||
|
extern int be_BLE_init(bvm *vm);
|
||||||
|
|
||||||
extern void be_BLE_reg_conn_cb(void* function, uint8_t *buffer);
|
extern void be_BLE_reg_conn_cb(void* function, uint8_t *buffer);
|
||||||
BE_FUNC_CTYPE_DECLARE(be_BLE_reg_conn_cb, "", "cc");
|
BE_FUNC_CTYPE_DECLARE(be_BLE_reg_conn_cb, "", "cc");
|
||||||
|
|
||||||
extern void be_BLE_reg_adv_cb(void* function, uint8_t *buffer);
|
extern void be_BLE_reg_adv_cb(void* function, uint8_t *buffer);
|
||||||
BE_FUNC_CTYPE_DECLARE(be_BLE_reg_adv_cb, "", "c[c]");
|
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);
|
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]");
|
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
|
/* @const_object_info_begin
|
||||||
module BLE (scope: global) {
|
module BLE (scope: global) {
|
||||||
|
init, func(be_BLE_init)
|
||||||
conn_cb, ctype_func(be_BLE_reg_conn_cb)
|
conn_cb, ctype_func(be_BLE_reg_conn_cb)
|
||||||
set_svc, ctype_func(be_BLE_set_service)
|
set_svc, ctype_func(be_BLE_set_service)
|
||||||
run, ctype_func(be_BLE_run)
|
run, ctype_func(be_BLE_run)
|
||||||
@ -81,6 +87,7 @@ module BLE (scope: global) {
|
|||||||
set_MAC, ctype_func(be_BLE_set_MAC)
|
set_MAC, ctype_func(be_BLE_set_MAC)
|
||||||
adv_watch, ctype_func(be_BLE_adv_watch)
|
adv_watch, ctype_func(be_BLE_adv_watch)
|
||||||
adv_block, ctype_func(be_BLE_adv_block)
|
adv_block, ctype_func(be_BLE_adv_block)
|
||||||
|
serv_cb, ctype_func(be_BLE_reg_server_cb)
|
||||||
}
|
}
|
||||||
@const_object_info_end */
|
@const_object_info_end */
|
||||||
|
|
||||||
|
@ -148,6 +148,7 @@ struct MI32connectionContextBerry_t{
|
|||||||
NimBLEUUID serviceUUID;
|
NimBLEUUID serviceUUID;
|
||||||
NimBLEUUID charUUID;
|
NimBLEUUID charUUID;
|
||||||
uint16_t returnCharUUID;
|
uint16_t returnCharUUID;
|
||||||
|
uint16_t handle;
|
||||||
uint8_t MAC[6];
|
uint8_t MAC[6];
|
||||||
uint8_t * buffer;
|
uint8_t * buffer;
|
||||||
uint8_t operation;
|
uint8_t operation;
|
||||||
@ -162,17 +163,29 @@ struct MI32notificationBuffer_t{
|
|||||||
uint16_t returnCharUUID;
|
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 {
|
struct {
|
||||||
// uint32_t period; // set manually in addition to TELE-period, is set to TELE-period after start
|
// uint32_t period; // set manually in addition to TELE-period, is set to TELE-period after start
|
||||||
TaskHandle_t ScanTask = nullptr;
|
TaskHandle_t ScanTask = nullptr;
|
||||||
TaskHandle_t ConnTask = nullptr;
|
TaskHandle_t ConnTask = nullptr;
|
||||||
|
TaskHandle_t ServerTask = nullptr;
|
||||||
MI32connectionContextBerry_t *conCtx = nullptr;
|
MI32connectionContextBerry_t *conCtx = nullptr;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
uint32_t init:1;
|
uint32_t init:1;
|
||||||
uint32_t connected:1;
|
uint32_t connected:1;
|
||||||
uint32_t autoScan:1;
|
uint32_t autoScan:1;
|
||||||
uint32_t canScan:1;
|
// uint32_t canScan:1;
|
||||||
uint32_t runningScan:1;
|
uint32_t runningScan:1;
|
||||||
uint32_t updateScan:1;
|
uint32_t updateScan:1;
|
||||||
uint32_t deleteScanTask:1;
|
uint32_t deleteScanTask:1;
|
||||||
@ -191,6 +204,11 @@ struct {
|
|||||||
uint32_t triggerNextConnJob:1;
|
uint32_t triggerNextConnJob:1;
|
||||||
uint32_t readyForNextConnJob:1;
|
uint32_t readyForNextConnJob:1;
|
||||||
uint32_t discoverAttributes: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;
|
uint32_t all = 0;
|
||||||
} mode;
|
} mode;
|
||||||
@ -218,8 +236,9 @@ struct {
|
|||||||
uint8_t HKinfoMsg = 0;
|
uint8_t HKinfoMsg = 0;
|
||||||
char hk_setup_code[11];
|
char hk_setup_code[11];
|
||||||
#endif //USE_MI_HOMEKIT
|
#endif //USE_MI_HOMEKIT
|
||||||
void *beConnCB;
|
void *beConnCB;
|
||||||
void *beAdvCB;
|
void *beAdvCB;
|
||||||
|
void *beServerCB;
|
||||||
uint8_t *beAdvBuf;
|
uint8_t *beAdvBuf;
|
||||||
uint8_t infoMsg = 0;
|
uint8_t infoMsg = 0;
|
||||||
} MI32;
|
} 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_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";
|
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 {
|
enum MI32_TASK {
|
||||||
MI32_TASK_SCAN = 0,
|
MI32_TASK_SCAN = 0,
|
||||||
MI32_TASK_CONN = 1,
|
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 {
|
enum MI32_ConnErrorMsg {
|
||||||
@ -419,7 +465,12 @@ enum MI32_BLEInfoMsg {
|
|||||||
MI32_DID_DISCONNECT,
|
MI32_DID_DISCONNECT,
|
||||||
MI32_STILL_CONNECTED,
|
MI32_STILL_CONNECTED,
|
||||||
MI32_START_SCANNING_PASSIVE,
|
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 {
|
enum MI32_HKInfoMsg {
|
||||||
|
@ -74,9 +74,11 @@ extern "C" {
|
|||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
** BLE - generic BLE functions
|
** BLE - generic BLE functions
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
extern bool MI32checkBLEinitialization();
|
||||||
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 bool MI32runBerryConnection(uint8_t operation, bbool response);
|
extern bool MI32runBerryConnection(uint8_t operation, bbool response);
|
||||||
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);
|
||||||
@ -84,12 +86,25 @@ extern "C" {
|
|||||||
extern bool MI32addMACtoBlockList(uint8_t *MAC, uint8_t type);
|
extern bool MI32addMACtoBlockList(uint8_t *MAC, uint8_t type);
|
||||||
extern bool MI32addMACtoWatchList(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);
|
||||||
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);
|
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);
|
||||||
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){
|
if(function == 0){
|
||||||
@ -193,7 +208,9 @@ BLE.set_chr
|
|||||||
|
|
||||||
BLE.set_MAC
|
BLE.set_MAC
|
||||||
BLE.run(op, optional: bool response)
|
BLE.run(op, optional: bool response)
|
||||||
|
|
||||||
be_BLE_op:
|
be_BLE_op:
|
||||||
|
# client
|
||||||
1 read
|
1 read
|
||||||
2 write
|
2 write
|
||||||
3 subscribe
|
3 subscribe
|
||||||
@ -205,8 +222,28 @@ be_BLE_op:
|
|||||||
13 subscribe once, then disconnect
|
13 subscribe once, then disconnect
|
||||||
14 unsubscribe once, then disconnect - maybe later
|
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.conn_cb(cb,buffer)
|
||||||
BLE.adv_cb(cb,buffer)
|
BLE.adv_cb(cb,buffer)
|
||||||
|
BLE.serv_cb(cb,buffer)
|
||||||
BLE.adv_watch(MAC)
|
BLE.adv_watch(MAC)
|
||||||
BLE.adv_block(MAC)
|
BLE.adv_block(MAC)
|
||||||
|
|
||||||
|
@ -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 MI32AdvCallbacks MI32ScanCallbacks;
|
||||||
static MI32SensorCallback MI32SensorCB;
|
static MI32SensorCallback MI32SensorCB;
|
||||||
|
static MI32CharacteristicCallbacks MI32ChrCallback;
|
||||||
static NimBLEClient* MI32Client;
|
static NimBLEClient* MI32Client;
|
||||||
static std::queue<MI32notificationBuffer_t> MI32NotificationQueue;
|
static std::queue<MI32notificationBuffer_t> MI32NotificationQueue;
|
||||||
|
|
||||||
@ -653,8 +721,9 @@ void MI32Init(void) {
|
|||||||
if (!MI32.mode.init) {
|
if (!MI32.mode.init) {
|
||||||
NimBLEDevice::setScanFilterMode(CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE);
|
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::setScanDuplicateCacheSize(40); // will not be perfect for every situation (few vs many BLE devices nearby)
|
||||||
NimBLEDevice::init("");
|
const std::string name(TasmotaGlobal.hostname);
|
||||||
AddLog(LOG_LEVEL_INFO,PSTR("M32: Init BLE device"));
|
NimBLEDevice::init(name);
|
||||||
|
AddLog(LOG_LEVEL_INFO,PSTR("M32: Init BLE device: %s"),TasmotaGlobal.hostname);
|
||||||
MI32.mode.init = 1;
|
MI32.mode.init = 1;
|
||||||
MI32.mode.readyForNextConnJob = 1;
|
MI32.mode.readyForNextConnJob = 1;
|
||||||
MI32StartTask(MI32_TASK_SCAN); // Let's get started !!
|
MI32StartTask(MI32_TASK_SCAN); // Let's get started !!
|
||||||
@ -672,21 +741,41 @@ void MI32Init(void) {
|
|||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
extern "C" {
|
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){
|
bool MI32runBerryConnection(uint8_t operation, bool response){
|
||||||
if(MI32.conCtx != nullptr){
|
if(MI32.conCtx != nullptr){
|
||||||
|
if(operation > 200){
|
||||||
|
return MI32runBerryServer(operation,response);
|
||||||
|
}
|
||||||
MI32.conCtx->oneOp = (operation > 9);
|
MI32.conCtx->oneOp = (operation > 9);
|
||||||
MI32.conCtx->operation = operation%10;
|
MI32.conCtx->operation = operation%10;
|
||||||
MI32.conCtx->response = response;
|
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){
|
if(MI32.conCtx->oneOp){
|
||||||
MI32StartConnectionTask();
|
MI32StartConnectionTask();
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if(MI32.mode.connected){
|
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;
|
MI32.mode.triggerNextConnJob = 1;
|
||||||
if(!MI32.mode.readyForNextConnJob){
|
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{
|
else{
|
||||||
@ -704,7 +793,24 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
MI32.conCtx->buffer = buffer;
|
MI32.conCtx->buffer = buffer;
|
||||||
MI32.beConnCB = function;
|
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){
|
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());
|
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
|
uint16_t _uuid = MI32.conCtx->charUUID.getNative()->u16.value; //if not "notify op" -> present requested characteristic as return UUID
|
||||||
MI32.conCtx->returnCharUUID = _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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -846,7 +952,7 @@ extern "C" {
|
|||||||
case 5: //HAP_EVENT_PAIRING_STARTED
|
case 5: //HAP_EVENT_PAIRING_STARTED
|
||||||
MI32suspendScanTask();
|
MI32suspendScanTask();
|
||||||
default:
|
default:
|
||||||
vTaskResume(MI32.ScanTask);
|
MI32resumeScanTask();
|
||||||
}
|
}
|
||||||
if(event==4){
|
if(event==4){
|
||||||
MI32.HKinfoMsg = MI32_HAP_CONTROLLER_DISCONNECTED;
|
MI32.HKinfoMsg = MI32_HAP_CONTROLLER_DISCONNECTED;
|
||||||
@ -1042,7 +1148,11 @@ void MI32saveConfig(){
|
|||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
void MI32suspendScanTask(void){
|
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){
|
void MI32StartTask(uint32_t task){
|
||||||
@ -1057,15 +1167,22 @@ void MI32StartTask(uint32_t task){
|
|||||||
MI32.mode.deleteScanTask = 1;
|
MI32.mode.deleteScanTask = 1;
|
||||||
MI32StartConnectionTask();
|
MI32StartConnectionTask();
|
||||||
break;
|
break;
|
||||||
|
case MI32_TASK_SERV:
|
||||||
|
MI32.mode.deleteScanTask = 1;
|
||||||
|
MI32StartServerTask();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scan task section
|
||||||
|
|
||||||
void MI32StartScanTask(){
|
void MI32StartScanTask(){
|
||||||
if (MI32.mode.connected) return;
|
if (MI32.mode.connected == 1) return;
|
||||||
if(MI32.ScanTask!=nullptr) vTaskDelete(MI32.ScanTask);
|
if(MI32.ScanTask!=nullptr) vTaskDelete(MI32.ScanTask);
|
||||||
MI32.mode.runningScan = 1;
|
MI32.mode.runningScan = 1;
|
||||||
|
MI32.mode.deleteScanTask = 0;
|
||||||
xTaskCreatePinnedToCore(
|
xTaskCreatePinnedToCore(
|
||||||
MI32ScanTask, /* Function to implement the task */
|
MI32ScanTask, /* Function to implement the task */
|
||||||
"MI32ScanTask", /* Name of the task */
|
"MI32ScanTask", /* Name of the task */
|
||||||
@ -1098,13 +1215,14 @@ void MI32ScanTask(void *pvParameters){
|
|||||||
|
|
||||||
uint32_t timer = 0;
|
uint32_t timer = 0;
|
||||||
for(;;){
|
for(;;){
|
||||||
vTaskDelay(1000/ portTICK_PERIOD_MS);
|
vTaskDelay(100/ portTICK_PERIOD_MS);
|
||||||
if(MI32.mode.deleteScanTask){
|
if(MI32.mode.deleteScanTask == 1){
|
||||||
MI32Scan->stop();
|
MI32Scan->stop();
|
||||||
MI32.mode.runningScan = 0;
|
MI32.mode.runningScan = 0;
|
||||||
|
MI32.ScanTask = nullptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(MI32.mode.updateScan){
|
if(MI32.mode.updateScan == 1){
|
||||||
MI32Scan->stop();
|
MI32Scan->stop();
|
||||||
MI32Scan->setActiveScan(MI32.option.activeScan == 1);
|
MI32Scan->setActiveScan(MI32.option.activeScan == 1);
|
||||||
MI32Scan->start(0,true);
|
MI32Scan->start(0,true);
|
||||||
@ -1115,6 +1233,8 @@ void MI32ScanTask(void *pvParameters){
|
|||||||
vTaskDelete( NULL );
|
vTaskDelete( NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// connection task section
|
||||||
|
|
||||||
bool MI32ConnectActiveSensor(){ // only use inside a task !!
|
bool MI32ConnectActiveSensor(){ // only use inside a task !!
|
||||||
if(MI32.conCtx->operation == 5) {
|
if(MI32.conCtx->operation == 5) {
|
||||||
return false;
|
return false;
|
||||||
@ -1307,6 +1427,144 @@ void MI32ConnectionTask(void *pvParameters){
|
|||||||
vTaskDelete( NULL );
|
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
|
* parse the response from advertisements
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
@ -1720,6 +1978,28 @@ void MI32Every50mSecond(){
|
|||||||
}
|
}
|
||||||
MI32.mode.triggerBerryConnCB = 0;
|
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){
|
if(MI32.infoMsg > 0){
|
||||||
char _message[32];
|
char _message[32];
|
||||||
GetTextIndexed(_message, sizeof(_message), MI32.infoMsg-1, kMI32_BLEInfoMsg);
|
GetTextIndexed(_message, sizeof(_message), MI32.infoMsg-1, kMI32_BLEInfoMsg);
|
||||||
@ -2057,7 +2337,7 @@ void MI32InitGUI(void){
|
|||||||
WSContentSend_P(PSTR("</div>"));
|
WSContentSend_P(PSTR("</div>"));
|
||||||
WSContentSpaceButton(BUTTON_MAIN);
|
WSContentSpaceButton(BUTTON_MAIN);
|
||||||
WSContentStop();
|
WSContentStop();
|
||||||
vTaskResume(MI32.ScanTask);
|
MI32resumeScanTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MI32HandleWebGUI(void){
|
void MI32HandleWebGUI(void){
|
||||||
@ -2246,7 +2526,7 @@ void MI32Show(bool json)
|
|||||||
MI32addHistory(MI32.energy_history,Energy->active_power[0],100); //TODO: which value??
|
MI32addHistory(MI32.energy_history,Energy->active_power[0],100); //TODO: which value??
|
||||||
#endif //USE_MI_ESP32_ENERGY
|
#endif //USE_MI_ESP32_ENERGY
|
||||||
#endif //USE_MI_EXT_GUI
|
#endif //USE_MI_EXT_GUI
|
||||||
vTaskResume(MI32.ScanTask);
|
MI32resumeScanTask();
|
||||||
#ifdef USE_WEBSERVER
|
#ifdef USE_WEBSERVER
|
||||||
} else {
|
} else {
|
||||||
MI32suspendScanTask();
|
MI32suspendScanTask();
|
||||||
@ -2309,7 +2589,7 @@ void MI32Show(bool json)
|
|||||||
#endif //USE_MI_EXT_GUI
|
#endif //USE_MI_EXT_GUI
|
||||||
#endif // USE_WEBSERVER
|
#endif // USE_WEBSERVER
|
||||||
}
|
}
|
||||||
vTaskResume(MI32.ScanTask);
|
MI32resumeScanTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
int ExtStopBLE(){
|
int ExtStopBLE(){
|
||||||
|
Loading…
x
Reference in New Issue
Block a user