#include #include #include "DHTesp.h" #include #include "BLEDevice.h" #include "Ticker.h" #include "esp_system.h" static BLEUUID thermo_service_uuid("11111111-2222-3333-4444-000000000000"); static BLEUUID thermo_temp_uuid("11111111-2222-3333-4444-000000000001"); static BLEUUID thermo_time_uuid("11111111-2222-3333-4444-000000000002"); #define NO_SERVER_SLEEP_TIME 60 #define ON_ERROR_SLEEP_TIME 30 #define WATCHDOG_SECONDS 30 /* Conversion factor for micro seconds to seconds */ #define uS_TO_S_FACTOR 1000000 #define BLE_POWER ESP_PWR_LVL_P7 // #define BLE_POWER ESP_PWR_LVL_N14 #define SENSOR_POWER_PIN 12 #define SENSOR_DATA_PIN 27 #define VBAT_PIN A13 DHTesp dht; class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { public: BLEAddress* pServerAddress; MyAdvertisedDeviceCallbacks() : BLEAdvertisedDeviceCallbacks(), pServerAddress(0) {} ~MyAdvertisedDeviceCallbacks() { if (pServerAddress) delete pServerAddress; } void onResult(BLEAdvertisedDevice advertisedDevice) { // We have found a device, let us now see if it contains the service we are looking for. if (advertisedDevice.haveName() && advertisedDevice.getName() == "termostore") { advertisedDevice.getScan()->stop(); pServerAddress = new BLEAddress(advertisedDevice.getAddress()); } // Found our server } // onResult }; // MyAdvertisedDeviceCallbacks void enable_sensor(bool enable) { pinMode(SENSOR_POWER_PIN,OUTPUT); digitalWrite(SENSOR_POWER_PIN,enable ? HIGH : LOW); delay(500); } bool read_sensor(float* humidity, float* temperature) { dht.setup(SENSOR_DATA_PIN,DHTesp::DHT11); int tries=0;bool ret=false; while (!ret && ++tries<10) { delay(dht.getMinimumSamplingPeriod()); *humidity = dht.getHumidity(); *temperature = dht.getTemperature(); if (dht.getStatus() != DHTesp::ERROR_TIMEOUT) ret = true; } return ret; } uint32_t send_data_and_get_time(BLEAddress* pAddress,String* data) { BLEClient* pClient = BLEDevice::createClient(); Serial.println("connecting"); bool ok = pClient->connect(*pAddress); if (!ok) { Serial.println("connect fail"); return ON_ERROR_SLEEP_TIME; } Serial.println("connected"); try { BLERemoteService* pThermoService = pClient->getService(thermo_service_uuid); if (!pThermoService) { Serial.println("failed to find service"); return 60; } BLERemoteCharacteristic* pTemp = pThermoService->getCharacteristic(thermo_temp_uuid); if (!pTemp) { Serial.println("failed to find writing characteristic"); return 60; } Serial.println("sending data"); pTemp->writeValue(data->c_str(),data->length()); Serial.println("sent"); BLERemoteCharacteristic* pTime = pThermoService->getCharacteristic(thermo_time_uuid); if (!pTime) { Serial.println("failed to find reading characteristic"); return 60; } Serial.println("receiving data"); std::string next_time = pTime->readValue(); Serial.println("received"); pClient->disconnect(); Serial.println("done"); return String(next_time.c_str()).toInt(); } catch (...) { Serial.println("general fail"); pClient->disconnect(); return ON_ERROR_SLEEP_TIME; } } void setup() { BLEDevice::init(""); esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, BLE_POWER); esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_SCAN, BLE_POWER); esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT, BLE_POWER); enable_sensor(true); Serial.begin(115200); } void teardown_and_sleep(int next_time) { enable_sensor(false); BLEDevice::uninit(); //esp_wifi_stop(); delay(2000); esp_sleep_enable_timer_wakeup(next_time * uS_TO_S_FACTOR); esp_deep_sleep_start(); } void watchdog_cb() { Serial.println("watchdog"); esp_restart(); } void loop() { Ticker watchdog_timer; watchdog_timer.attach(WATCHDOG_SECONDS,watchdog_cb); Serial.println("start BLE scan"); BLEScan* pBLEScan = BLEDevice::getScan(); MyAdvertisedDeviceCallbacks* cb = new MyAdvertisedDeviceCallbacks(); pBLEScan->setAdvertisedDeviceCallbacks(cb); pBLEScan->setActiveScan(true); BLEScanResults foundDevices = pBLEScan->start(30); int next_time; if (cb->pServerAddress) { Serial.println("found BLE server"); float humidity, temperature; bool ok = read_sensor(&humidity,&temperature); int batteryLevel = analogRead(VBAT_PIN); batteryLevel *= 2; if (ok) { String data = String(BLEDevice::getAddress().toString().c_str()) + " " + String(humidity) + " " + String(temperature) + " " + String(batteryLevel) + "\n"; Serial.println(data); next_time = send_data_and_get_time(cb->pServerAddress,&data); } else { Serial.println("sensor error"); next_time=ON_ERROR_SLEEP_TIME; } } else { Serial.println("failed to find BLE server"); next_time = NO_SERVER_SLEEP_TIME; } delete cb; teardown_and_sleep(next_time); delay(2000); }