3
3
#include < WiFiMulti.h>
4
4
#include < HTTPClient.h>
5
5
#include < ESP.h>
6
+ #include < Preferences.h>
7
+ #include < WiFiClient.h>
8
+ #include < HTTPUpdate.h>
6
9
7
10
// This is inspired from https://github.com/lucafabbri/HiGrow-Arduino-Esp
8
11
9
- #define VERSION " 0.1"
12
+ #define VERSION_MAJOR 0
13
+ #define VERSION_MINOR 2
14
+ #define VERSION_PATCH 4
15
+ #define VERSION_INT (VERSION_MAJOR*10000 +VERSION_MINOR*100 +VERSION_PATCH)
10
16
11
17
// Pin layout
12
18
#define PIN_LED_BLUE 16
19
25
20
26
// For secrets
21
27
#define EEDOMUS_API_SECRET " ********"
28
+ #define OTAP_URL_SECRET " ********"
22
29
#define WIFI_PASSWORD_1 " ********"
23
30
#define WIFI_PASSWORD_2 " ********"
24
31
#define WIFI_PASSWORD_3 " ********"
25
32
#define WIFI_PASSWORD_4 " ********"
26
33
34
+ #define NELEMS (x ) (sizeof (x) / sizeof ((x)[0 ]))
35
+
27
36
void pinsSetup () {
28
37
pinMode (PIN_POWER, INPUT); // No idea what this does
29
38
@@ -36,14 +45,43 @@ void pinsSetup() {
36
45
void serialSetup () {
37
46
Serial.begin (115200 );
38
47
delay (10 );
39
- Serial.printf (" Wifi Soil Moisture Sensor (%s / %s %s)\n " , VERSION , __DATE__, __TIME__);
48
+ Serial.printf (" Wifi Soil Moisture Sensor v%d.%d.%d ( %s %s)\n " , VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH , __DATE__, __TIME__);
40
49
}
41
50
42
- char deviceid[21 ] = " " ;
51
+ typedef struct {
52
+ String name;
53
+ String macAddr;
54
+ int deviceIdSoil;
55
+ int deviceIdAirHumidity;
56
+ int deviceIdAirTemperature;
57
+ } t_device_ids;
58
+
59
+ // This is where I list all my sensors
60
+ t_device_ids ids[] = {
61
+ { .name = " C1" , .macAddr = " 30:AE:A4:F4:C9:2C" , .deviceIdSoil = 1579253 },
62
+ { .name = " C2" , .macAddr = " CC:50:E3:A8:6B:64" , .deviceIdSoil = 1579248 },
63
+ { .name = " C3" , .macAddr = " CC:50:E3:A8:72:EC" , .deviceIdSoil = 1579249 },
64
+ { .name = " C4" , .macAddr = " 30:AE:A4:F3:48:80" , .deviceIdSoil = 1579250 },
65
+ { .name = " C5" , .macAddr = " CC:50:E3:A8:97:54" , .deviceIdSoil = 1584398 },
66
+ { .name = " C6" , .macAddr = " CC:50:E3:A8:6E:48" , .deviceIdSoil = 1579254 }
67
+ };
68
+
69
+ t_device_ids * current_device_ids = NULL ;
70
+ Preferences preferences;
71
+
72
+ // char deviceid[21] = "";
43
73
void settingsSetup () {
44
- sprintf (deviceid, " %" PRIu64, ESP.getEfuseMac ());
45
- Serial.print (" DeviceId: " );
46
- Serial.println (deviceid);
74
+ String macAddress = WiFi.macAddress ();
75
+ for ( int i = 0 ; i < NELEMS (ids); i++ ) {
76
+ t_device_ids * dev_id = & ids[i];
77
+ if ( dev_id->macAddr == macAddress ) {
78
+ current_device_ids = dev_id;
79
+ Serial.print (" Device identified: " + dev_id->name + " \n " );
80
+ return ;
81
+ }
82
+ }
83
+ Serial.print (" We don't know this device (" + macAddress + " )\n " );
84
+ sleepGo ();
47
85
}
48
86
49
87
WiFiMulti wifiMulti;
@@ -56,22 +94,20 @@ void wifiSetAPs() {
56
94
}
57
95
58
96
void wifiConnect () {
59
- Serial.print (String (" MAC address: " )+WiFi.macAddress ());
60
- Serial.println ();
61
-
62
- WiFi.setHostname (" wifi_gms" );
63
-
64
- Serial.print (" Connecting Wifi..." );
65
- WiFi.mode (WIFI_STA);
66
- while (wifiMulti.run () != WL_CONNECTED) {
67
- Serial.print (" ." );
68
- delay (500 );
69
- }
70
- Serial.println (" " );
71
- Serial.println (String (" WiFi connected to \" " )+WiFi.SSID ()+" \" " );
97
+ Serial.print (" Connecting Wifi..." );
98
+ if ( current_device_ids ) {
99
+ WiFi.setHostname (current_device_ids->name .c_str ());
100
+ }
101
+ WiFi.enableSTA (true );
102
+ while (wifiMulti.run () != WL_CONNECTED) {
103
+ Serial.print (" ." );
104
+ delay (500 );
105
+ }
106
+ Serial.println (" " );
107
+ Serial.println (String (" WiFi connected to \" " ) + WiFi.SSID () + " \" " );
72
108
73
- Serial.print (" IP address: " );
74
- Serial.println (WiFi.localIP ());
109
+ Serial.print (" IP address: " );
110
+ Serial.println (WiFi.localIP ());
75
111
}
76
112
77
113
void wifiSetup () {
@@ -80,17 +116,17 @@ void wifiSetup() {
80
116
}
81
117
82
118
// TODO: The whole coming back from sleep logic is broken (bot for the RTC-attached memory and wake up reason). I have no idea of why.
83
- void sleepWakeUpReason (){
119
+ void sleepWakeUpReason () {
84
120
esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause ();
85
121
86
- switch (wakeup_reason) {
122
+ switch (wakeup_reason) {
87
123
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println (" Wakeup caused by external signal using RTC_IO" ); break ;
88
124
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println (" Wakeup caused by external signal using RTC_CNTL" ); break ;
89
125
case ESP_SLEEP_WAKEUP_TIMER : Serial.println (" Wakeup caused by timer" ); break ;
90
126
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println (" Wakeup caused by touchpad" ); break ;
91
127
case ESP_SLEEP_WAKEUP_ULP : Serial.println (" Wakeup caused by ULP program" ); break ;
92
128
case 0 : break ;
93
- default : Serial.printf (" Unknwon wake up reason: %d\n " ,wakeup_reason); break ;
129
+ default : Serial.printf (" Unknwon wake up reason: %d\n " , wakeup_reason); break ;
94
130
}
95
131
}
96
132
@@ -121,9 +157,9 @@ void IRAM_ATTR watchdogReset() {
121
157
122
158
void watchdogSetup () {
123
159
watchdogTimer = timerBegin (0 , 80 , true );
124
- // It shouldn't take more than 1 minute to run the program
160
+ // It shouldn't take more than 5 minute to run or even reflash the program
125
161
timerAttachInterrupt (watchdogTimer, &watchdogReset, true );
126
- timerAlarmWrite (watchdogTimer, 1L * 60 * 1000 * 1000 , false );
162
+ timerAlarmWrite (watchdogTimer, 5L * 60 * 1000 * 1000 , false );
127
163
timerAlarmEnable (watchdogTimer);
128
164
}
129
165
@@ -132,33 +168,107 @@ void watchdogDisable() {
132
168
timerEnd (watchdogTimer);
133
169
}
134
170
135
- void setup () {
136
- serialSetup ();
171
+ void otapSetup () {
172
+ const int r = esp_random () % 1 ;
173
+ if ( r != 0 ) {
174
+ Serial.println (" OTAP: Skipping it this time..." );
175
+ return ;
176
+ }
177
+
178
+ {
179
+ HTTPClient client;
180
+ client.begin (String (OTAP_URL_SECRET) + " version.txt" );
181
+ int status = client.GET ();
182
+ if (status != 200 ) {
183
+ Serial.printf (" OTAP: Wrong HTTP status: %d\n " , status);
184
+ return ;
185
+ }
186
+ int version = client.getString ().toInt ();
187
+ if ( version <= VERSION_INT ) {
188
+ Serial.printf (" OTAP: No update available (%d <= %d)\n " , version, VERSION_INT);
189
+ return ;
190
+ }
191
+ Serial.printf (" OTAP: Updating from %d to %d\n " , VERSION_INT, version);
192
+ }
193
+ {
194
+ Serial.println (" OTAP: Starting update" );
195
+ WiFiClient client;
196
+
197
+ // The line below is optional. It can be used to blink the LED on the board during flashing
198
+ // The LED will be on during download of one buffer of data from the network. The LED will
199
+ // be off during writing that buffer to flash
200
+ // On a good connection the LED should flash regularly. On a bad connection the LED will be
201
+ // on much longer than it will be off. Other pins than LED_BUILTIN may be used. The second
202
+ // value is used to put the LED on. If the LED is on with HIGH, that value should be passed
203
+ // httpUpdate.setLedPin(LED_BUILTIN, LOW);
204
+
205
+ t_httpUpdate_return ret = httpUpdate.update (client, String (OTAP_URL_SECRET) + " file.bin" );
206
+
207
+ switch (ret) {
208
+ case HTTP_UPDATE_FAILED:
209
+ Serial.printf (" OTAP: Failed: Error (%d): %s\n " , httpUpdate.getLastError (), httpUpdate.getLastErrorString ().c_str ());
210
+ break ;
211
+
212
+ case HTTP_UPDATE_NO_UPDATES:
213
+ Serial.println (" OTAP: No update" );
214
+ break ;
215
+
216
+ case HTTP_UPDATE_OK:
217
+ Serial.println (" OTAP: OK" );
218
+ break ;
219
+ }
220
+ }
221
+ }
137
222
138
- // We need a watchdog because the WifiMulti module is extremely buggy. It can hang forever if it doesn't find a network immediately.
139
- watchdogSetup ();
140
- sleepSetup ();
141
- pinsSetup ();
142
- settingsSetup ();
143
- wifiSetup ();
223
+ void setup () {
224
+ serialSetup ();
225
+
226
+ // We need a watchdog because the WifiMulti module is extremely buggy. It can hang forever if it doesn't find a network immediately.
227
+ watchdogSetup ();
228
+ sleepSetup ();
229
+ pinsSetup ();
230
+ settingsSetup ();
231
+ wifiSetup ();
232
+ otapSetup ();
144
233
}
145
234
146
235
// Sensors used
147
236
typedef struct {
148
237
float airHumidity;
149
238
float airTemperature;
150
239
float soilMoisture;
151
- float light;
240
+ // float light;
152
241
} t_sensors;
153
242
154
243
t_sensors sensors = {};
155
244
156
245
// Converts a raw value into a percentage
157
- float toPercentage (int value, const int valueMin, const int valueMax, bool revert ) {
246
+ float toPercentage (int value, int valueMin, int valueMax, bool revert, String type) {
247
+ {
248
+ char prefName[100 ];
249
+ sprintf (prefName, " per.%s" , type);
250
+ preferences.begin (prefName, false );
251
+ }
252
+ valueMin = preferences.getInt (" min" , valueMin);
253
+ valueMax = preferences.getInt (" max" , valueMax);
254
+ if ( value > valueMax ) {
255
+ valueMax = value;
256
+ Serial.printf (" Saving new max: %d\n " , valueMax);
257
+ preferences.putInt (" max" , valueMax);
258
+ } else if ( value < valueMin ) {
259
+ valueMin = value;
260
+ Serial.printf (" Saving new min: %d\n " , valueMin);
261
+ preferences.putInt (" min" , valueMin);
262
+ }
263
+ preferences.end ();
264
+
265
+ Serial.printf (" Value: %d, Min: %d, Max: %d\n " , value, valueMin, valueMax);
266
+
158
267
float per = 100.0 * (value - valueMin) / (valueMax - valueMin);
159
268
if ( revert ) {
160
269
per = 100 - per;
161
270
}
271
+
162
272
return per;
163
273
}
164
274
@@ -173,14 +283,20 @@ void sensorsFetchDht () {
173
283
}
174
284
175
285
void sensorsFetchAdc () { // Fetching data from ADC
176
- int soilMoistureLevel = analogRead (PIN_SOIL);
177
- int lightLevel = analogRead (PIN_LIGHT);
178
-
286
+ const int nb_readings = 20 ;
287
+ const int measures_time = 30000 ;
288
+ int soilMoistureLevel = 0 ;
289
+
290
+ for ( int i = 0 ; i < nb_readings; i++ ) {
291
+ int reading = analogRead (PIN_SOIL);
292
+ soilMoistureLevel += reading;
293
+ Serial.printf (" Soil moisture (raw): %d (%d)\n " , reading, i);
294
+ delay (measures_time/nb_readings);
295
+ }
296
+ soilMoistureLevel /= nb_readings;
179
297
Serial.printf (" Soil moisture (raw): %d\n " , soilMoistureLevel);
180
- Serial.printf (" Light (raw): %d\n " , lightLevel);
181
298
182
- sensors.soilMoisture = toPercentage (soilMoistureLevel, 1400 , 3250 , true );
183
- sensors.light = lightLevel; // Light gives completely bogus data
299
+ sensors.soilMoisture = toPercentage (soilMoistureLevel, 1100 , 3000 , true , " soil" );
184
300
185
301
Serial.printf (" Soil moisture (corrected): %.2f%%\n " , sensors.soilMoisture );
186
302
}
@@ -191,21 +307,40 @@ void sensorsFetch() {
191
307
}
192
308
193
309
void eedomusSend (int periphId, String value) {
194
- Serial.print (String (" Eedomus: Setting \" " )+ value+" \" for periphId " + periphId + " ... " );
195
- String url = String (" http://api.eedomus.com/set?api_user=" )+EEDOMUS_API_KEY+" &api_secret=" +EEDOMUS_API_SECRET+" &action=periph.value&periph_id=" +periphId+" &value=" +value;
310
+ if ( ! periphId ) {
311
+ return ;
312
+ }
313
+ Serial.print (String (" Eedomus: Setting \" " ) + value + " \" for periphId " + periphId + " ... " );
314
+ String url = String (" http://api.eedomus.com/set?api_user=" ) + EEDOMUS_API_KEY + " &api_secret=" + EEDOMUS_API_SECRET + " &action=periph.value&periph_id=" + periphId + " &value=" + value;
315
+
316
+ for ( int i = 0 ; i < 3 ; i++ ) {
317
+ HTTPClient client;
318
+ client.begin (url);
319
+ int status = client.GET ();
320
+ Serial.printf (" Done (%d)\n " , status);
321
+ if ( status == 200 ) {
322
+ break ;
323
+ }
324
+ }
325
+ }
196
326
197
- HTTPClient client;
198
- client. begin (url) ;
199
- int status = client. GET ( );
200
- Serial. printf ( " Done (%d) \n " , status );
327
+ void eedomusSend ( int periphId, float value) {
328
+ char format[ 100 ] ;
329
+ sprintf (format, " %.2f " , value );
330
+ eedomusSend (periphId, format );
201
331
}
202
332
203
333
void sendSensorsData () {
204
334
sensorsFetch ();
205
- eedomusSend (1486564 , String (int (sensors.soilMoisture )));
206
- eedomusSend (1486569 , String (int (sensors.light )));
207
- eedomusSend (1488106 , String (int (sensors.airHumidity )));
208
- eedomusSend (1488113 , String (int (sensors.airTemperature )));
335
+
336
+ if ( ! current_device_ids ) {
337
+ Serial.print (" No device set !\n " );
338
+ return ;
339
+ }
340
+
341
+ eedomusSend (current_device_ids->deviceIdSoil , sensors.soilMoisture );
342
+ eedomusSend (current_device_ids->deviceIdAirHumidity , sensors.airHumidity );
343
+ eedomusSend (current_device_ids->deviceIdAirTemperature , sensors.airTemperature );
209
344
}
210
345
211
346
void loop () {
0 commit comments