Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BT] Add gateway deactivation/activation command #1821

Merged
merged 1 commit into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/use/ble.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ With the ability to monitor and analyze data such as temperature, humidity, mois
Support the project by purchasing the [Theengs plug](https://shop.theengs.io/products/theengs-plug-smart-plug-ble-gateway-and-energy-consumption)
The plug is available in North America only, other regions are planned.

## Disable or enable the BLE gateway (default: true, available with HA discovery)

If you want to deactivate the BLE gateway:

`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"enabled":false}'`

If you want to activate the BLE gateway:

`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"enabled":true}'`

## Receiving signals from [compatible BLE sensors](https://decoder.theengs.io/devices/devices_by_brand.html) to publish it to an MQTT broker.
To receive data from BLE sensors you can use an ESP32-based device with a programming USB port or use a Serial adapter.

Expand Down
22 changes: 11 additions & 11 deletions main/ZgatewayBLEConnect.ino
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# include "ZgatewayBLEConnect.h"
# define convertTemp_CtoF(c) ((c * 1.8) + 32)

extern bool ProcessLock;
extern bool BTProcessLock;
extern std::vector<BLEdevice*> devices;

NimBLERemoteCharacteristic* zBLEConnect::getCharacteristic(const NimBLEUUID& service,
Expand Down Expand Up @@ -135,7 +135,7 @@ void LYWSD03MMC_connect::notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pD
if (m_taskHandle == nullptr) {
return; // unexpected notification
}
if (!ProcessLock) {
if (!BTProcessLock) {
Log.trace(F("Callback from %s characteristic" CR), pChar->getUUID().toString().c_str());

if (length == 5) {
Expand Down Expand Up @@ -167,7 +167,7 @@ void LYWSD03MMC_connect::notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pD
return;
}
} else {
Log.trace(F("Callback process canceled by processLock" CR));
Log.trace(F("Callback process canceled by BTProcessLock" CR));
}

xTaskNotifyGive(m_taskHandle);
Expand Down Expand Up @@ -199,7 +199,7 @@ void DT24_connect::notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, s
return; // unexpected notification
}

if (!ProcessLock) {
if (!BTProcessLock) {
Log.trace(F("Callback from %s characteristic" CR), pChar->getUUID().toString().c_str());
if (length == 20) {
m_data.assign(pData, pData + length);
Expand Down Expand Up @@ -232,7 +232,7 @@ void DT24_connect::notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, s
return;
}
} else {
Log.trace(F("Callback process canceled by processLock" CR));
Log.trace(F("Callback process canceled by BTProcessLock" CR));
}

xTaskNotifyGive(m_taskHandle);
Expand Down Expand Up @@ -264,7 +264,7 @@ void BM2_connect::notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, si
return; // unexpected notification
}

if (!ProcessLock) {
if (!BTProcessLock) {
Log.trace(F("Callback from %s characteristic" CR), pChar->getUUID().toString().c_str());
if (length == 16) {
Log.trace(F("Device identified creating BLE buffer" CR));
Expand Down Expand Up @@ -309,7 +309,7 @@ void BM2_connect::notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, si
return;
}
} else {
Log.trace(F("Callback process canceled by processLock" CR));
Log.trace(F("Callback process canceled by BTProcessLock" CR));
}

xTaskNotifyGive(m_taskHandle);
Expand Down Expand Up @@ -375,7 +375,7 @@ void XMWSDJ04MMC_connect::notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* p
if (m_taskHandle == nullptr) {
return; // unexpected notification
}
if (!ProcessLock) {
if (!BTProcessLock) {
Log.trace(F("Callback from %s characteristic" CR), pChar->getUUID().toString().c_str());

if (length == 6) {
Expand All @@ -399,7 +399,7 @@ void XMWSDJ04MMC_connect::notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* p
return;
}
} else {
Log.trace(F("Callback process canceled by processLock" CR));
Log.trace(F("Callback process canceled by BTProcessLock" CR));
}

xTaskNotifyGive(m_taskHandle);
Expand Down Expand Up @@ -430,7 +430,7 @@ void SBS1_connect::notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, s
if (m_taskHandle == nullptr) {
return; // unexpected notification
}
if (!ProcessLock) {
if (!BTProcessLock) {
Log.trace(F("Callback from %s characteristic" CR), pChar->getUUID().toString().c_str());

if (length) {
Expand All @@ -440,7 +440,7 @@ void SBS1_connect::notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, s
return;
}
} else {
Log.trace(F("Callback process canceled by processLock" CR));
Log.trace(F("Callback process canceled by BTProcessLock" CR));
}

xTaskNotifyGive(m_taskHandle);
Expand Down
72 changes: 47 additions & 25 deletions main/ZgatewayBT.ino
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ void BTConfig_init() {
BTConfig.presenceAwayTimer = PresenceAwayTimer;
BTConfig.movingTimer = MovingTimer;
BTConfig.forcePassiveScan = false;
BTConfig.enabled = true;
}

unsigned long timeBetweenConnect = 0;
Expand Down Expand Up @@ -133,6 +134,7 @@ String stateBTMeasures(bool start) {
jo["presenceawaytimer"] = BTConfig.presenceAwayTimer;
jo["movingtimer"] = BTConfig.movingTimer;
jo["forcepassivescan"] = BTConfig.forcePassiveScan;
jo["enabled"] = BTConfig.enabled;
jo["bletaskstack"] = uxTaskGetStackHighWaterMark(xProcBLETaskHandle);
jo["blecoretaskstack"] = uxTaskGetStackHighWaterMark(xCoreTaskHandle);

Expand Down Expand Up @@ -178,6 +180,13 @@ void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) {
eraseTopic("number", (char*)getUniqueId("intervalacts", "").c_str());
# endif
}
// Identify if the gateway is enabled or not and stop start accordingly
if (BTdata.containsKey("enabled") && BTdata["enabled"] == false && BTConfig.enabled == true) {
stopProcessing();
} else if (BTdata.containsKey("enabled") && BTdata["enabled"] == true && BTConfig.enabled == false) {
BTProcessLock = false;
setupBTTasksAndBLE();
}
}
Config_update(BTdata, "adaptivescan", BTConfig.adaptiveScan);
// Home Assistant presence message
Expand Down Expand Up @@ -225,6 +234,8 @@ void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) {
Config_update(BTdata, "pubBeaconUuidForTopic", BTConfig.pubBeaconUuidForTopic);
// Disable Whitelist & Blacklist
Config_update(BTdata, "ignoreWBlist", (BTConfig.ignoreWBlist));
// Enable or disable the BT gateway
Config_update(BTdata, "enabled", BTConfig.enabled);

stateBTMeasures(startup);

Expand Down Expand Up @@ -266,6 +277,7 @@ void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) {
jo["presenceawaytimer"] = BTConfig.presenceAwayTimer;
jo["movingtimer"] = BTConfig.movingTimer;
jo["forcepassivescan"] = BTConfig.forcePassiveScan;
jo["enabled"] = BTConfig.enabled;
// Save config into NVS (non-volatile storage)
String conf = "";
serializeJson(jsonBuffer, conf);
Expand Down Expand Up @@ -580,7 +592,7 @@ void procBLETask(void* pvParameters) {
xQueueReceive(BLEQueue, &advertisedDevice, portMAX_DELAY);
// Feed the watchdog
//esp_task_wdt_reset();
if (!ProcessLock) {
if (!BTProcessLock) {
Log.trace(F("Creating BLE buffer" CR));
StaticJsonDocument<JSON_MSG_BUFFER> BLEdataBuffer;
JsonObject BLEdata = BLEdataBuffer.to<JsonObject>();
Expand Down Expand Up @@ -675,7 +687,7 @@ void BLEscan() {
* Connect to BLE devices and initiate the callbacks with a service/characteristic request
*/
void BLEconnect() {
if (!ProcessLock) {
if (!BTProcessLock) {
Log.notice(F("BLE Connect begin" CR));
do {
for (vector<BLEdevice*>::iterator it = devices.begin(); it != devices.end(); ++it) {
Expand Down Expand Up @@ -742,33 +754,39 @@ void BLEconnect() {
}

void stopProcessing() {
ProcessLock = true;
// We stop the scan
Log.notice(F("Stopping BLE scan" CR));
BLEScan* pBLEScan = BLEDevice::getScan();
if (pBLEScan->isScanning()) {
pBLEScan->stop();
if (BTConfig.enabled) {
BTProcessLock = true;
// We stop the scan
Log.notice(F("Stopping BLE scan" CR));
BLEScan* pBLEScan = BLEDevice::getScan();
if (pBLEScan->isScanning()) {
pBLEScan->stop();
}

if (xSemaphoreTake(semaphoreBLEOperation, pdMS_TO_TICKS(5000)) == pdTRUE) {
Log.notice(F("Stopping BLE tasks" CR));
//Suspending, deleting tasks and stopping BT to free memory
vTaskSuspend(xCoreTaskHandle);
vTaskDelete(xCoreTaskHandle);
vTaskSuspend(xProcBLETaskHandle);
vTaskDelete(xProcBLETaskHandle);
xSemaphoreGive(semaphoreBLEOperation);
}
}
Log.notice(F("Stopping BLE tasks" CR));
//Suspending, deleting tasks and stopping BT to free memory
vTaskSuspend(xCoreTaskHandle);
vTaskDelete(xCoreTaskHandle);
vTaskSuspend(xProcBLETaskHandle);
vTaskDelete(xProcBLETaskHandle);
Log.notice(F("BLE gateway stopped %T, free heap: %d" CR), ESP.getFreeHeap());
}

void coreTask(void* pvParameters) {
while (true) {
if (!ProcessLock) {
if (!BTProcessLock) {
int n = 0;
while (client.state() != 0 && n <= InitialMQTTConnectionTimeout && !ProcessLock) {
while (client.state() != 0 && n <= InitialMQTTConnectionTimeout && !BTProcessLock) {
n++;
delay(1000);
}
if (client.state() != 0) {
Log.warning(F("MQTT client disconnected no BLE scan" CR));
} else if (!ProcessLock) {
} else if (!BTProcessLock) {
if (xSemaphoreTake(semaphoreBLEOperation, pdMS_TO_TICKS(30000)) == pdTRUE) {
BLEscan();
// Launching a connect every TimeBtwConnect
Expand Down Expand Up @@ -813,6 +831,7 @@ void deepSleep(uint64_t time_in_us) {

Log.trace(F("Deactivating ESP32 components" CR));
stopProcessing();
ProcessLock = true;
// Ignore the deprecated warning, this call is necessary here.
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
Expand Down Expand Up @@ -891,6 +910,7 @@ void setupBT() {
Log.notice(F("Presence Away Timer: %d" CR), BTConfig.presenceAwayTimer);
Log.notice(F("Moving Timer: %d" CR), BTConfig.movingTimer);
Log.notice(F("Force passive scan: %T" CR), BTConfig.forcePassiveScan);
Log.notice(F("Enabled BLE: %T" CR), BTConfig.enabled);

atomic_init(&forceBTScan, 0); // in theory, we don't need this

Expand All @@ -901,10 +921,12 @@ void setupBT() {
xSemaphoreGive(semaphoreBLEOperation);

BLEQueue = xQueueCreate(QueueSize, sizeof(NimBLEAdvertisedDevice*));

setupBTTasksAndBLE();

Log.trace(F("ZgatewayBT multicore ESP32 setup done " CR));
if (BTConfig.enabled) {
setupBTTasksAndBLE();
Log.notice(F("ZgatewayBT multicore ESP32 setup done" CR));
} else {
Log.notice(F("ZgatewayBT multicore ESP32 setup disabled" CR));
}
}

bool BTtoMQTT() { // for on demand BLE scans
Expand Down Expand Up @@ -1230,7 +1252,7 @@ void hass_presence(JsonObject& HomePresence) {
}

void BTforceScan() {
if (!ProcessLock) {
if (!BTProcessLock) {
BTtoMQTT();
Log.trace(F("Scan done" CR));
if (BTConfig.bleConnect)
Expand All @@ -1243,7 +1265,7 @@ void BTforceScan() {
void immediateBTAction(void* pvParameters) {
if (BLEactions.size()) {
// Immediate action; we need to prevent the normal connection action and stop scanning
ProcessLock = true;
BTProcessLock = true;
NimBLEScan* pScan = NimBLEDevice::getScan();
if (pScan->isScanning()) {
pScan->stop();
Expand All @@ -1261,7 +1283,7 @@ void immediateBTAction(void* pvParameters) {
std::swap(BLEactions, act_swap);

// Unlock here to allow the action to be performed
ProcessLock = false;
BTProcessLock = false;
BLEconnect();
// back to normal
std::swap(devices, dev_swap);
Expand All @@ -1282,7 +1304,7 @@ void immediateBTAction(void* pvParameters) {
buildTopicFromId(BLEdata, subjectBTtoMQTT);
handleJsonEnqueue(BLEdata, QueueSemaphoreTimeOutTask);
BLEactions.pop_back();
ProcessLock = false;
BTProcessLock = false;
}
}
vTaskDelete(NULL);
Expand Down
10 changes: 10 additions & 0 deletions main/ZmqttDiscovery.ino
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,16 @@ void pubMqttDiscovery() {
stateClassNone, //State Class
"false", "true" //state_off, state_on
);
createDiscovery("switch", //set Type
subjectBTtoMQTT, "BT: Enabled", (char*)getUniqueId("enabled", "").c_str(), //set state_topic,name,uniqueId
will_Topic, "", "{{ value_json.enabled }}", //set availability_topic,device_class,value_template,
"{\"enabled\":true,\"save\":true}", "{\"enabled\":false,\"save\":true}", "", //set,payload_on,payload_off,unit_of_meas,
0, //set off_delay
Gateway_AnnouncementMsg, will_Message, true, subjectMQTTtoBTset, //set,payload_available,payload_not available ,is a gateway entity, command topic
"", "", "", "", false, // device name, device manufacturer, device model, device MAC, retain
stateClassNone, //State Class
"false", "true" //state_off, state_on
);

# define EntitiesCount 8
const char* obsoleteEntities[EntitiesCount][2] = {
Expand Down
1 change: 1 addition & 0 deletions main/config_BT.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ struct BTConfig_s {
unsigned long presenceAwayTimer; //Timer that trigger a tracker/PIR state as offline/off if not seen
unsigned long movingTimer; //Timer that trigger a moving sensor state as offline if not seen
bool forcePassiveScan; //Force passive scan
bool enabled; // Enable or disable the BT gateway
};

// Global struct to store live BT configuration data
Expand Down
Loading