diff --git a/README.md b/README.md index a1ac3053..4161c696 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Upload OpenMQTTGateway directly from the [upload page](https://docs.openmqttgate *Running on a computer* If you want to use the BLE decoding capabilities of OpenMQTTGateway with a Raspberry Pi, Windows or Unix PC you can now leverage [Theengs Gateway](https://theengs.github.io/gateway/). -* [List of compatible components to build your gateway](https://compatible.openmqttgateway.com/index.php/parts/), DHT, HM10, RF, IR emitters and receivers... +* [List of compatible components to build your gateway](https://compatible.openmqttgateway.com/index.php/parts/), DHT, RF, IR emitters and receivers... ## Compatible controllers, saas or software diff --git a/docs/prerequisites/board.md b/docs/prerequisites/board.md index 91e71472..89860dc5 100644 --- a/docs/prerequisites/board.md +++ b/docs/prerequisites/board.md @@ -44,13 +44,13 @@ The boards below need hardware [parts](parts.md) and electronic/hardware compete |DIY boards|RF|IR|BLE|LORA|GSM|Button|Relay| |-|:-:|:-:|:-:|:-:|:-:|:-:|:-:| |Arduino UNO|X|X(limited compared to ESP)|-|-|-|X|X| -|Arduino MEGA|X|X(limited compared to ESP)|X|-|-|X|X| +|Arduino MEGA|X|X(limited compared to ESP)|-|-|-|X|X| |ESP32|X|X|X|X|not tested|X|X| -|ESP8266|X|X|X|not tested|X|X|X| +|ESP8266|X|X|-|not tested|X|X|X| ::: tip Pilight is only supported on ESP, Arduino UNO handle only 32bits values in our context. -Setup based on HM10 doesn't support some BLE [devices](devices.md#for-ble-devices). +HM10 is no longer supported by OpenMQTTGateway ::: ![boards](../img/OpenMQTTGateway_boards.png) diff --git a/docs/use/ble.md b/docs/use/ble.md index 9ce8352b..0a5138b6 100644 --- a/docs/use/ble.md +++ b/docs/use/ble.md @@ -33,7 +33,7 @@ iOS version >=10 devices advertise without an extra app MAC address, nevertheles ## Receiving signals from BLE devices Mi Flora, Mi jia, LYWDS02, LYWSD03MMC, ClearGrass, Mi scale and [many more](https://compatible.openmqttgateway.com/index.php/devices/ble-devices/) -So as to receive BLE sensors data you need either a simple ESP32 either an ESP8266/Arduino + HM10/11 with firmware >= v601 +So as to receive BLE sensors data you need a simple ESP32 The mi flora supported firmware is >3.1.8 Verify that your sensor is working with the App and update it with the last software version. @@ -59,11 +59,10 @@ The infos will appear like this on your MQTT broker: `home/OpenMQTTGateway/BTtoMQTT/4C33A6603C79 {"hum":"52.6","tempc":"19.2","tempf":"66.56"}` -More info are available on [my blog](https://1technophile.blogspot.fr/2017/11/mi-flora-integration-to-openmqttgateway.html) (especially about how it was implemented with HM10) +More info are available on [my blog](https://1technophile.blogspot.fr/2017/11/mi-flora-integration-to-openmqttgateway.html) ::: tip -The HM10 module doesn't read enough information (servicedata UUID is missing) to support Mi Scale and Mi Band. They are supported nevertheless with ESP32. -OpenMQTTGateway publish the servicedata field of your BLE devices, with HM10 this field can be longer compared to ESP32 if the device is not recognised. +OpenMQTTGateway publish the servicedata field of your BLE devices. ::: ## Setting a white or black list @@ -352,10 +351,3 @@ Response (assuming success): "state":"on" } ``` - -## Other - -To check your hm10 firmware version upload a serial sketch to the nodemcu (this will enable communication directly with the hm10) and launch the command: -`AT+VERR?` - -More info about HM-10 is [available here](http://www.martyncurrey.com/hm-10-bluetooth-4ble-modules/) diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index cc44c560..5ee28a2b 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -32,32 +32,28 @@ Thanks to wolass https://github.com/wolass for suggesting me HM 10 and dinosd ht #ifdef ZgatewayBT -# ifdef ESP32 -# include "FreeRTOS.h" +# include "FreeRTOS.h" SemaphoreHandle_t semaphoreCreateOrUpdateDevice; SemaphoreHandle_t semaphoreBLEOperation; QueueHandle_t BLEQueue; // Headers used for deep sleep functions -# include -# include -# include -# include -# include -# include -# include -# include -# include - -# include "ZgatewayBLEConnect.h" -# include "soc/timer_group_reg.h" -# include "soc/timer_group_struct.h" - -# endif - +# include +# include +# include +# include # include +# include +# include +# include +# include +# include # include +# include "ZgatewayBLEConnect.h" +# include "soc/timer_group_reg.h" +# include "soc/timer_group_struct.h" + using namespace std; // Global struct to store live BT configuration data @@ -77,9 +73,7 @@ struct decompose { bool reverse; }; -# ifdef ESP32 vector BLEactions; -# endif vector devices; int newDevices = 0; @@ -196,7 +190,6 @@ void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) { } pub("/commands/BTtoMQTT/config", jo); -# if defined(ESP32) if (BTdata.containsKey("erase") && BTdata["erase"].as()) { // Erase config from NVS (non-volatile storage) preferences.begin(Gateway_Short_Name, false); @@ -215,10 +208,8 @@ void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) { preferences.end(); Log.notice(F("BT config saved" CR)); } -# endif } -# if defined(ESP32) void BTConfig_load() { StaticJsonDocument jsonBuffer; preferences.begin(Gateway_Short_Name, true); @@ -237,7 +228,6 @@ void BTConfig_load() { BTConfig_fromJson(jo, true); // Never send mqtt message with config Log.notice(F("BT config loaded" CR)); } -# endif void pubBTMainCore(JsonObject& data, bool haPresenceEnabled = true) { if (abs((int)data["rssi"] | 0) < abs(BTConfig.minRssi) && data.containsKey("id")) { @@ -288,7 +278,6 @@ public: void PublishDeviceData(JsonObject& BLEdata, bool processBLEData = true); -# ifdef ESP32 static TaskHandle_t xCoreTaskHandle; static TaskHandle_t xProcBLETaskHandle; @@ -340,20 +329,6 @@ void emptyBTQueue() { } } -# else - -JsonBundle jsonBTBuffer; - -JsonObject& getBTJsonObject(const char* json, bool haPresenceEnabled) { - return jsonBTBuffer.createObject(); -} - -void pubBT(JsonObject& data) { - pubBTMainCore(data); -} - -# endif - bool ProcessLock = false; // Process lock when we want to use a critical function like OTA for example void createOrUpdateDevice(const char* mac, uint8_t flags, int model, int mac_type = 0); @@ -388,12 +363,10 @@ bool updateWorB(JsonObject& BTdata, bool isWhite) { } void createOrUpdateDevice(const char* mac, uint8_t flags, int model, int mac_type) { -# ifdef ESP32 if (xSemaphoreTake(semaphoreCreateOrUpdateDevice, pdMS_TO_TICKS(30000)) == pdFALSE) { Log.error(F("Semaphore NOT taken" CR)); return; } -# endif BLEdevice* device = getDeviceByMac(mac); if (device == &NO_DEVICE_FOUND) { @@ -435,9 +408,7 @@ void createOrUpdateDevice(const char* mac, uint8_t flags, int model, int mac_typ // update oneWhite flag oneWhite = oneWhite || device->isWhtL; -# ifdef ESP32 xSemaphoreGive(semaphoreCreateOrUpdateDevice); -# endif } # define isWhite(device) device->isWhtL @@ -544,7 +515,6 @@ void DT24Discovery(const char* mac, const char* sensorModel_id) {} void XMWSDJ04MMCDiscovery(const char* mac, const char* sensorModel_id) {} # endif -# ifdef ESP32 /* Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp Ported to Arduino ESP32 by Evandro Copercini @@ -777,39 +747,39 @@ void lowPowerESP32() { // low power mode } void deepSleep(uint64_t time_in_us) { -# if defined(ZboardM5STACK) || defined(ZboardM5STICKC) || defined(ZboardM5STICKCP) || defined(ZboardM5TOUGH) +# if defined(ZboardM5STACK) || defined(ZboardM5STICKC) || defined(ZboardM5STICKCP) || defined(ZboardM5TOUGH) sleepScreen(); esp_sleep_enable_ext0_wakeup((gpio_num_t)SLEEP_BUTTON, LOW); -# endif +# endif Log.trace(F("Deactivating ESP32 components" CR)); BLEDevice::deinit(true); esp_bt_mem_release(ESP_BT_MODE_BTDM); // Ignore the deprecated warning, this call is necessary here. -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" adc_power_off(); -# pragma GCC diagnostic pop +# pragma GCC diagnostic pop esp_wifi_stop(); esp_deep_sleep(time_in_us); } void changelowpowermode(int newLowPowerMode) { Log.notice(F("Changing LOW POWER mode to: %d" CR), newLowPowerMode); -# if defined(ZboardM5STACK) || defined(ZboardM5STICKC) || defined(ZboardM5STICKCP) || defined(ZboardM5TOUGH) +# if defined(ZboardM5STACK) || defined(ZboardM5STICKC) || defined(ZboardM5STICKCP) || defined(ZboardM5TOUGH) if (lowpowermode == 2) { -# ifdef ZboardM5STACK +# ifdef ZboardM5STACK M5.Lcd.wakeup(); -# endif -# if defined(ZboardM5STICKC) || defined(ZboardM5STICKCP) || defined(ZboardM5TOUGH) +# endif +# if defined(ZboardM5STICKC) || defined(ZboardM5STICKCP) || defined(ZboardM5TOUGH) M5.Axp.SetLDO2(true); M5.Lcd.begin(); -# endif +# endif } char lpm[2]; sprintf(lpm, "%d", newLowPowerMode); M5Print("Changing LOW POWER mode to:", lpm, ""); -# endif +# endif lowpowermode = newLowPowerMode; preferences.begin(Gateway_Short_Name, false); preferences.putUInt("lowpowermode", lowpowermode); @@ -865,124 +835,6 @@ bool BTtoMQTT() { // for on demand BLE scans BLEscan(); return true; } -# else // arduino or ESP8266 working with HM10/11 - -# include -# define QUESTION_MSG "AT+DISA?" - -SoftwareSerial softserial(BT_RX, BT_TX); - -String returnedString((char*)0); -unsigned long timebt = 0; - -// this struct define which parts of the hexadecimal chain we extract and what to do with these parts -// {"mac"}, {"typ"}, {"rsi"}, {"rdl"}, {"sty"}, {"rda"} -struct decompose d[6] = {{0, 12, true}, {12, 2, false}, {14, 2, false}, {16, 2, false}, {28, 4, true}, {32, 60, false}}; - -void setupBT() { - BTConfig_init(); - Log.notice(F("BLE interval: %d" CR), BTConfig.BLEinterval); - Log.notice(F("BLE scans number before connect: %d" CR), BTConfig.BLEscanBeforeConnect); - Log.notice(F("Publishing only BLE sensors: %T" CR), BTConfig.pubOnlySensors); - Log.notice(F("minrssi: %d" CR), -abs(BTConfig.minRssi)); - softserial.begin(HMSerialSpeed); - softserial.print(F("AT+ROLE1" CR)); - delay(100); - softserial.print(F("AT+IMME1" CR)); - delay(100); - softserial.print(F("AT+RESET" CR)); - delay(100); -# ifdef HM_BLUE_LED_STOP - softserial.print(F("AT+PIO11" CR)); // When not connected (as in BLE mode) the LED is off. When connected the LED is solid on. -# endif - delay(100); -# if defined(ESP8266) - returnedString.reserve(512); //reserve memory space for BT Serial. (size should depend on available RAM) -# endif - Log.trace(F("ZgatewayBT HM1X setup done " CR)); -} - -bool BTtoMQTT() { - //extract serial data from module in hexa format - while (softserial.available() > 0) { - int a = softserial.read(); - if (a < 16) { - returnedString += "0"; - } - returnedString += String(a, HEX); - } - - if (millis() > (timebt + BTConfig.BLEinterval)) { //retrieving data - timebt = millis(); - returnedString.remove(0); //init data string - softserial.print(F(QUESTION_MSG)); //start new discovery - return false; - } - -# if defined(ESP8266) - yield(); -# endif - if (returnedString.length() > (BLEdelimiterLength + CRLR_Length)) { //packet has to be at least the (BLEdelimiter + 'CR LF') length - Log.verbose(F("returnedString: %s" CR), (char*)returnedString.c_str()); - if (returnedString.equals(F(BLEEndOfDiscovery))) //OK+DISCE - { - returnedString.remove(0); //clear data string - scanCount++; - Log.notice(F("Scan number %d end " CR), scanCount); - return false; - } - size_t pos = 0, eolPos = 0; - while ((pos = returnedString.indexOf(F(BLEdelimiter))) != -1 && (eolPos = returnedString.indexOf(F(CRLR))) != -1) { -# if defined(ESP8266) - yield(); -# endif - String token = returnedString.substring(pos + BLEdelimiterLength, eolPos); //capture a BT device frame - returnedString.remove(0, eolPos + CRLR_Length); //remove frame from main buffer (including 'CR LF' chars) - Log.trace(F("Token: %s" CR), token.c_str()); - if (token.length() > 32) { // we extract data only if we have size is at least the size of (MAC, TYPE, RSSI, and Rest Data Length) - String mac = F(""); - mac.reserve(17); - for (int i = d[0].start; i < (d[0].start + d[0].len); i += 2) { - mac += token.substring((d[0].start + d[0].len) - i - 2, (d[0].start + d[0].len) - i); - if (i < (d[0].start + d[0].len) - 2) - mac += ":"; - } - mac.toUpperCase(); - - String rssiStr = token.substring(d[2].start, (d[2].start + d[2].len)); - int rssi = (int)strtol(rssiStr.c_str(), NULL, 16) - 256; - - String restDataLengthStr = token.substring(d[3].start, (d[3].start + d[3].len)); - int restDataLength = (int)strtol(restDataLengthStr.c_str(), NULL, 16) * 2; - - String restData = F(""); - if (restDataLength <= 60) - restData = token.substring(d[5].start, (d[5].start + restDataLength)); - - Log.trace(F("Creating BLE buffer" CR)); - JsonObject& BLEdata = getBTJsonObject(); - - Log.trace(F("Id %s" CR), (char*)mac.c_str()); - BLEdata["id"] = (const char*)mac.c_str(); - BLEdevice* device = getDeviceByMac((char*)mac.c_str()); - - if (!BTConfig.ignoreWBlist && isBlack(device)) - return false; //if black listed MAC we go out - if (!BTConfig.ignoreWBlist && oneWhite && !isWhite(device)) - return false; //if WBlist is enabled AND we have at least one white MAC AND this MAC is not white we go out - - BLEdata["rssi"] = (int)rssi; - if (!BTConfig.pubOnlySensors && BTConfig.presenceEnable) - hass_presence(BLEdata); // this device has an rssi and we don't want only sensors so in consequence we can use it for home assistant room presence component - Log.trace(F("Service data: %s" CR), restData.c_str()); - BLEdata["servicedata"] = restData.c_str(); - PublishDeviceData(BLEdata); - } - } - return false; - } -} -# endif void RemoveJsonPropertyIf(JsonObject& obj, const char* key, bool condition) { if (condition) { @@ -1004,7 +856,6 @@ boolean valid_service_data(const char* data, int size) { void launchBTDiscovery() { if (newDevices == 0) return; -# ifdef ESP32 if (xSemaphoreTake(semaphoreCreateOrUpdateDevice, pdMS_TO_TICKS(1000)) == pdFALSE) { Log.error(F("Semaphore NOT taken" CR)); return; @@ -1013,10 +864,6 @@ void launchBTDiscovery() { vector localDevices = devices; xSemaphoreGive(semaphoreCreateOrUpdateDevice); for (vector::iterator it = localDevices.begin(); it != localDevices.end(); ++it) { -# else - newDevices = 0; - for (vector::iterator it = devices.begin(); it != devices.end(); ++it) { -# endif BLEdevice* p = *it; Log.trace(F("Device mac %s" CR), p->macAdr); // Do not launch discovery for the devices already discovered or that are not unique by their MAC Address (Ibeacon, GAEN and Microsoft Cdp) @@ -1186,16 +1033,13 @@ void BTforceScan() { if (!ProcessLock) { BTtoMQTT(); Log.trace(F("Scan done" CR)); -# ifdef ESP32 if (BTConfig.bleConnect) BLEconnect(); -# endif } else { Log.trace(F("Cannot launch scan due to other process running" CR)); } } -# ifdef ESP32 void immediateBTAction(void* pvParameters) { if (BLEactions.size()) { // Immediate action; we need to prevent the normal connection action and stop scanning @@ -1251,10 +1095,8 @@ void startBTActionTask() { &th, /* Task handle. */ 1); /* Core where the task should run */ } -# endif void MQTTtoBTAction(JsonObject& BTdata) { -# ifdef ESP32 BLEAction action; memset(&action, 0, sizeof(BLEAction)); if (BTdata.containsKey("SBS1")) { @@ -1319,7 +1161,6 @@ void MQTTtoBTAction(JsonObject& BTdata) { if (BTdata.containsKey("immediate") && BTdata["immediate"].as()) { startBTActionTask(); } -# endif } void MQTTtoBT(char* topicOri, JsonObject& BTdata) { // json object decoding @@ -1332,24 +1173,16 @@ void MQTTtoBT(char* topicOri, JsonObject& BTdata) { // json object decoding WorBupdated |= updateWorB(BTdata, false); if (WorBupdated) { -# ifdef ESP32 if (xSemaphoreTake(semaphoreCreateOrUpdateDevice, pdMS_TO_TICKS(1000)) == pdTRUE) { dumpDevices(); xSemaphoreGive(semaphoreCreateOrUpdateDevice); } -# else - dumpDevices(); -# endif } // Force scan now if (BTdata.containsKey("interval") && BTdata["interval"] == 0) { Log.notice(F("BLE forced scan" CR)); -# ifdef ESP32 atomic_store_explicit(&forceBTScan, 1, ::memory_order_seq_cst); // ask the other core to do the scan for us -# else - BTforceScan(); -# endif } /* @@ -1361,24 +1194,19 @@ void MQTTtoBT(char* topicOri, JsonObject& BTdata) { // json object decoding if (BTdata.containsKey("init") && BTdata["init"].as()) { // Restore the default (initial) configuration BTConfig_init(); - } -# ifdef ESP32 - else if (BTdata.containsKey("load") && BTdata["load"].as()) { + } else if (BTdata.containsKey("load") && BTdata["load"].as()) { // Load the saved configuration, if not initialised BTConfig_load(); } -# endif // Load config from json if available BTConfig_fromJson(BTdata); -# ifdef ESP32 if (BTdata.containsKey("lowpowermode")) { changelowpowermode((int)BTdata["lowpowermode"]); } MQTTtoBTAction(BTdata); -# endif } } #endif diff --git a/platformio.ini b/platformio.ini index e994f343..79a91958 100644 --- a/platformio.ini +++ b/platformio.ini @@ -73,7 +73,6 @@ extra_configs = ;default_envs = nodemcuv2-weatherstation ;default_envs = nodemcuv2-ir ;default_envs = avatto-bakeey-ir -;default_envs = nodemcuv2-ble ;default_envs = nodemcuv2-2g ;default_envs = nodemcuv2-all-test ;default_envs = nodemcuv2-fastled-test @@ -986,21 +985,6 @@ build_flags = '-DGateway_Name="OpenMQTTGateway_ESP8266_2G"' board_build.flash_mode = dout -[env:nodemcuv2-ble] -platform = ${com.esp8266_platform} -board = nodemcuv2 -lib_deps = - ${com-esp.lib_deps} - ${libraries.wifimanager8266} - ${libraries.wire} - ${libraries.esp8266_mdns} - ${libraries.decoder} -build_flags = - ${com-esp.build_flags} - '-DZgatewayBT="BT"' - '-DGateway_Name="OpenMQTTGateway_ESP8266_BLE"' -board_build.flash_mode = dout - [env:nodemcuv2-ir] platform = ${com.esp8266_platform} board = nodemcuv2 @@ -1273,14 +1257,12 @@ lib_deps = ${libraries.dallastemperature} ${libraries.rfWeatherStation} ${libraries.stl} - ${libraries.decoder} build_flags = ${com-arduino.build_flags} '-DZgatewayRF="RF"' '-DZgatewayRF="RF315"' '-DZgatewayRF2="RF2"' '-DZgatewayIR="IR"' - '-DZgatewayBT="BT"' '-DZactuatorONOFF="ONOFF"' '-DZactuatorFASTLED="FASTLED"' '-DZactuatorPWM="PWM"'