summaryrefslogtreecommitdiff
path: root/sensor/thermostat.ino
blob: 23bc610959676bbef8074376d9df7962de253ba3 (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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#include <string>
#include <Wire.h>  
#include "SSD1306.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 
 
SSD1306 display(0x3c54);
DHTesp dht;
 
void show(String x) {
  display.clear();
  display.drawString(0,0,x);
  display.display();
}
 
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(12,OUTPUT);
  digitalWrite(12,enable ? HIGH : LOW);
  delay(500);
}
 
bool read_sensor(float* humidity, float* temperature) {
  dht.setup(13,DHTesp::DHT11);
 
  int tries=0;bool ret=false;
  while (!ret && ++tries<10{
    delay(dht.getMinimumSamplingPeriod());
    *humidity = dht.getHumidity();
    *temperature = dht.getTemperature();
 
    String data = "";
    data += *humidity;
    data += " ";
    data += *temperature;
    data += " ";
    data += dht.getStatusString();
    show(data);
 
    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();
  show("Sc");
  bool ok = pClient->connect(*pAddress);
  if (!ok) {
    show("connect fail");
    return ON_ERROR_SLEEP_TIME;
  }
  String status = "SC";
  status += pClient->getPeerAddress().toString().c_str();
  show(status);
  try {
    BLERemoteService* pThermoService = pClient->getService(thermo_service_uuid);
    if (!pThermoService) {
      show("NO SERVICE");
      return 60;
    }
    BLERemoteCharacteristic* pTemp = pThermoService->getCharacteristic(thermo_temp_uuid);
    if (!pTemp) {
      show("NO TEMP CHAR");
      return 60;
    }
    show("SCw");
    pTemp->writeValue(data->c_str(),data->length());
    show("SCWr");
    BLERemoteCharacteristic* pTime = pThermoService->getCharacteristic(thermo_time_uuid);
    if (!pTime) {
      show("NO TIME CHAR");
      return 60;
    }
    std::string next_time = pTime->readValue();
    show("SCWRd");
    pClient->disconnect();
    show("SCWRD");
    return String(next_time.c_str()).toInt();
  }
  catch (...) {
    show("Fail");
    pClient->disconnect();
    return ON_ERROR_SLEEP_TIME;
  }
}
 
void setup() {
  display.init();
  display.connect();
  display.displayOn();
  display.clear();
  show("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);
  show("setup+bt");
  enable_sensor(true);
  show("setup+bt+sensor");
}
 
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() {
  show("watchdog");
  teardown_and_sleep(ON_ERROR_SLEEP_TIME);
}
 
void loop() {
  Ticker watchdog_timer;
  watchdog_timer.attach(WATCHDOG_SECONDS,watchdog_cb);
 
  BLEScan* pBLEScan = BLEDevice::getScan();
  MyAdvertisedDeviceCallbacks* cb = new MyAdvertisedDeviceCallbacks();
  pBLEScan->setAdvertisedDeviceCallbacks(cb);
  pBLEScan->setActiveScan(true);
  show("s");
  BLEScanResults foundDevices = pBLEScan->start(30);
  int next_time;
 
  if (cb->pServerAddress) {
    show("S");
 
    float humidity, temperature;
    bool ok = read_sensor(&humidity,&temperature);
    if (ok) {
      String data = String(BLEDevice::getAddress().toString().c_str()) + " " + String(humidity) + " " + String(temperature) + "\n";
      show(data);
    
      next_time = send_data_and_get_time(cb->pServerAddress,&data);
    }
    else {
      show("no thermo");
      next_time=ON_ERROR_SLEEP_TIME;
    }
  }
  else {
    display.drawString(0,0,"s!");display.display();
    next_time = NO_SERVER_SLEEP_TIME;
  }
 
  delete cb;
 
  String nt = "Next time:";nt+=next_time;
  display.drawString(0,20,nt);display.display();
  teardown_and_sleep(next_time);
 
  show("woken up");
  delay(2000);
}