summaryrefslogtreecommitdiff
path: root/sensor/thermostat.ino
blob: d2b8bce2580b37db3b9fcc90435ce25b6c6f11e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include <string>
#include <Wire.h>  
#include "DHTesp.h"
#include <esp_bt.h>
#include "BLEDevice.h"
#include "Ticker.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 MyAdvertisedDeviceCallbackspublic 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(9600);
}
 
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");
  teardown_and_sleep(ON_ERROR_SLEEP_TIME);
}
 
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);
}