33#include < WiFiMulti.h>
44#include < HTTPClient.h>
55#include < ESP.h>
6+ #include < Preferences.h>
7+ #include < WiFiClient.h>
8+ #include < HTTPUpdate.h>
69
710// This is inspired from https://github.com/lucafabbri/HiGrow-Arduino-Esp
811
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)
1016
1117// Pin layout
1218#define PIN_LED_BLUE 16
1925
2026// For secrets
2127#define EEDOMUS_API_SECRET " ********"
28+ #define OTAP_URL_SECRET " ********"
2229#define WIFI_PASSWORD_1 " ********"
2330#define WIFI_PASSWORD_2 " ********"
2431#define WIFI_PASSWORD_3 " ********"
2532#define WIFI_PASSWORD_4 " ********"
2633
34+ #define NELEMS (x ) (sizeof (x) / sizeof ((x)[0 ]))
35+
2736void pinsSetup () {
2837 pinMode (PIN_POWER, INPUT); // No idea what this does
2938
@@ -36,14 +45,43 @@ void pinsSetup() {
3645void serialSetup () {
3746 Serial.begin (115200 );
3847 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__);
4049}
4150
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] = "";
4373void 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 ();
4785}
4886
4987WiFiMulti wifiMulti;
@@ -56,22 +94,20 @@ void wifiSetAPs() {
5694}
5795
5896void 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 () + " \" " );
72108
73- Serial.print (" IP address: " );
74- Serial.println (WiFi.localIP ());
109+ Serial.print (" IP address: " );
110+ Serial.println (WiFi.localIP ());
75111}
76112
77113void wifiSetup () {
@@ -80,17 +116,17 @@ void wifiSetup() {
80116}
81117
82118// 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 () {
84120 esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause ();
85121
86- switch (wakeup_reason) {
122+ switch (wakeup_reason) {
87123 case ESP_SLEEP_WAKEUP_EXT0 : Serial.println (" Wakeup caused by external signal using RTC_IO" ); break ;
88124 case ESP_SLEEP_WAKEUP_EXT1 : Serial.println (" Wakeup caused by external signal using RTC_CNTL" ); break ;
89125 case ESP_SLEEP_WAKEUP_TIMER : Serial.println (" Wakeup caused by timer" ); break ;
90126 case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println (" Wakeup caused by touchpad" ); break ;
91127 case ESP_SLEEP_WAKEUP_ULP : Serial.println (" Wakeup caused by ULP program" ); break ;
92128 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 ;
94130 }
95131}
96132
@@ -121,9 +157,9 @@ void IRAM_ATTR watchdogReset() {
121157
122158void watchdogSetup () {
123159 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
125161 timerAttachInterrupt (watchdogTimer, &watchdogReset, true );
126- timerAlarmWrite (watchdogTimer, 1L * 60 * 1000 * 1000 , false );
162+ timerAlarmWrite (watchdogTimer, 5L * 60 * 1000 * 1000 , false );
127163 timerAlarmEnable (watchdogTimer);
128164}
129165
@@ -132,33 +168,107 @@ void watchdogDisable() {
132168 timerEnd (watchdogTimer);
133169}
134170
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+ }
137222
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 ();
144233}
145234
146235// Sensors used
147236typedef struct {
148237 float airHumidity;
149238 float airTemperature;
150239 float soilMoisture;
151- float light;
240+ // float light;
152241} t_sensors;
153242
154243t_sensors sensors = {};
155244
156245// 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+
158267 float per = 100.0 * (value - valueMin) / (valueMax - valueMin);
159268 if ( revert ) {
160269 per = 100 - per;
161270 }
271+
162272 return per;
163273}
164274
@@ -173,14 +283,20 @@ void sensorsFetchDht () {
173283}
174284
175285void 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;
179297 Serial.printf (" Soil moisture (raw): %d\n " , soilMoistureLevel);
180- Serial.printf (" Light (raw): %d\n " , lightLevel);
181298
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" );
184300
185301 Serial.printf (" Soil moisture (corrected): %.2f%%\n " , sensors.soilMoisture );
186302}
@@ -191,21 +307,40 @@ void sensorsFetch() {
191307}
192308
193309void 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+ }
196326
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 );
201331}
202332
203333void sendSensorsData () {
204334 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 );
209344}
210345
211346void loop () {
0 commit comments