... | ... |
@@ -0,0 +1,123 @@ |
1 |
+ |
|
2 |
+#ifndef ARDUINO_ESP8266_WEMOS_D1MINI |
|
3 |
+ #ifndef ARDUINO_ESP8266_WEMOS_D1R1 |
|
4 |
+ error "Board Must be /LOLIN(WEMOS) D1 R2 & Mini/ OR /Wemos D1 R1/" |
|
5 |
+ #endif //ARDUINO_ESP8266_WEMOS_D1R1 |
|
6 |
+#endif //ARDUINO_ESP8266_WEMOS_D1MINI |
|
7 |
+ |
|
8 |
+//--------------------------------------------------------------------- |
|
9 |
+//Note: |
|
10 |
+//--------------------------------------------------------------------- |
|
11 |
+// ARDUINO_ESP8266_WEMOS_D1MINI : |
|
12 |
+// - ESP DevBoard with onboard direct connector for DHT & OLED |
|
13 |
+// - ESP Devboard with no screen |
|
14 |
+// ARDUINO_ESP8266_WEMOS_D1R1 |
|
15 |
+// - ESP DevBoard with Battery holder |
|
16 |
+//--------------------------------------------------------------------- |
|
17 |
+ |
|
18 |
+// My Includes |
|
19 |
+#include <dummy.h> |
|
20 |
+#include <ESP8266WiFi.h> |
|
21 |
+//#include <ESP8266WebServer.h> |
|
22 |
+#include <DHT.h> |
|
23 |
+#include <ArduinoOTA.h> |
|
24 |
+ |
|
25 |
+#include "my_constants.h" |
|
26 |
+#include "my_draw.h" |
|
27 |
+#include "my_wifi.h" |
|
28 |
+#include "my_dht.h" |
|
29 |
+#include "my_ntp.h" |
|
30 |
+#include "my_isr.h" |
|
31 |
+ |
|
32 |
+ |
|
33 |
+#ifdef USE_OTA |
|
34 |
+#include "my_ota.h" |
|
35 |
+#endif //USE_OTA |
|
36 |
+ |
|
37 |
+#ifdef USE_MQTT |
|
38 |
+#include "my_mqtt.h" |
|
39 |
+#endif //USE_MQTT |
|
40 |
+ |
|
41 |
+#include "my_http.h" |
|
42 |
+ |
|
43 |
+ |
|
44 |
+void setup() { |
|
45 |
+ Serial.begin(115200); |
|
46 |
+ Serial.setDebugOutput(true); |
|
47 |
+ Serial.println(); |
|
48 |
+ |
|
49 |
+ Serial.println("Initialization Screen"); |
|
50 |
+ drawInit(); |
|
51 |
+ draw(compile_time, NOLOGO, 0, 0); |
|
52 |
+ |
|
53 |
+ Serial.println("Initialization DHT"); |
|
54 |
+ dht.begin(); |
|
55 |
+ Serial.println("Initialization WIFI"); |
|
56 |
+ WiFiConnect(); |
|
57 |
+ |
|
58 |
+ // Sync clock |
|
59 |
+ if( WiFi.status() == WL_CONNECTED ) { |
|
60 |
+ setClock(); |
|
61 |
+ sprintf(clientID,clientIDFmt,WiFi.macAddress().c_str()); |
|
62 |
+#ifdef USE_MQTT |
|
63 |
+ mqtt_connect(); |
|
64 |
+#endif //USE_MQTT |
|
65 |
+ } |
|
66 |
+ Serial.println("BuildDate:["+String(compile_date)+"]"); |
|
67 |
+ ota_set(); |
|
68 |
+ |
|
69 |
+#ifdef ARDUINO_ESP8266_WEMOS_D1MINI |
|
70 |
+ digitalWrite(LED_BUILTIN, LOW); |
|
71 |
+#endif //ARDUINO_ESP8266_WEMOS_D1MINI |
|
72 |
+ |
|
73 |
+ Serial.println("Initialization HTTP server on port "+String(PORT)); |
|
74 |
+ http_set(); |
|
75 |
+ |
|
76 |
+ isr_set(); |
|
77 |
+ |
|
78 |
+ delay(1000); |
|
79 |
+ displaySetStatus(0); |
|
80 |
+} |
|
81 |
+ |
|
82 |
+// the loop function runs over and over again forever |
|
83 |
+void loop() { |
|
84 |
+ ArduinoOTA.handle(); |
|
85 |
+ unsigned long time; |
|
86 |
+ time = millis(); |
|
87 |
+ if (time - timeSinceLastModeSwitch > UPDATE_PERIOD) { |
|
88 |
+ #ifdef HAS_DHT |
|
89 |
+ float mT = readDHTTemperature(); |
|
90 |
+ float mH = readDHTHumidity(); |
|
91 |
+ String dispMsg = String(mT)+" | "+String(mH)+"%"; |
|
92 |
+ countMeasures++; |
|
93 |
+ getTimeString(); |
|
94 |
+ #ifdef USE_MQTT |
|
95 |
+ mqtt_reconnect(); |
|
96 |
+ String MQTTMsg = "{\"time\": \""+String(acTimeStringTZ)+"\", \"MAC\": \""+WiFi.macAddress()+"\", \"temp\":"+String(mT)+", \"humidity\": "+String(mH)+"}"; |
|
97 |
+ if (!client.publish(mqtt_topic, MQTTMsg.c_str())) { |
|
98 |
+ Serial.println("ERROR: MQTT not sent!"); |
|
99 |
+ } |
|
100 |
+ #endif //USE_MQTT |
|
101 |
+ draw(acTimeString, NOLOGO, mT, mH); |
|
102 |
+ #endif //HAS_DHT |
|
103 |
+ |
|
104 |
+ timeSinceLastModeSwitch = millis(); |
|
105 |
+ } else if( time > MAX_RUNNING_TIME ) { |
|
106 |
+ //Restart the board if running time is > MAX_RUNNING_TIME |
|
107 |
+ #ifdef USE_MQTT |
|
108 |
+ mqtt_reconnect(); |
|
109 |
+ String MQTTMsg = "{\"time\": \""+String(acTimeStringTZ)+"\", \"MAC\": \""+WiFi.macAddress()+"\", \"status\": \"Triggered reboot\"}"; |
|
110 |
+ if (!client.publish(mqtt_topic, MQTTMsg.c_str())) { |
|
111 |
+ Serial.println("ERROR: MQTT not sent!"); |
|
112 |
+ } |
|
113 |
+ #endif //USE_MQTT |
|
114 |
+ Serial.println("Triggered reboot"); |
|
115 |
+ ESP.restart(); |
|
116 |
+ } else if(WiFi.status() != WL_CONNECTED) { |
|
117 |
+ //Reconnect WiFi if not connected |
|
118 |
+ WiFiConnect(); |
|
119 |
+ mqtt_connect(); |
|
120 |
+ } |
|
121 |
+ server.handleClient(); |
|
122 |
+ delay(LOOP_DELAY); |
|
123 |
+} |
... | ... |
@@ -0,0 +1,43 @@ |
1 |
+#ifndef _MY_CONSTANTS |
|
2 |
+#define _MY_CONSTANTS |
|
3 |
+ |
|
4 |
+#define APPVER "1.0.3" |
|
5 |
+#define APPNAME "DHT" |
|
6 |
+const char compile_date[] = APPNAME " v" APPVER " " __DATE__ " " __TIME__; |
|
7 |
+const char compile_time[] = __DATE__ " " __TIME__; |
|
8 |
+ |
|
9 |
+//Global Switches |
|
10 |
+#define HAS_DHT |
|
11 |
+#define USE_MQTT |
|
12 |
+#define USE_OTA |
|
13 |
+ |
|
14 |
+#define LED_BUILTIN 2 |
|
15 |
+ |
|
16 |
+/* |
|
17 |
+#define MAX_RUNNING_TIME 50000 //50s |
|
18 |
+#define MAX_RUNNING_TIME 100000 //100s |
|
19 |
+#define MAX_RUNNING_TIME 3600000 //1hour |
|
20 |
+#define MAX_RUNNING_TIME 7200000 //2hours |
|
21 |
+#define MAX_RUNNING_TIME 10800000 //3hours |
|
22 |
+#define MAX_RUNNING_TIME 14400000 //4 hours |
|
23 |
+#define MAX_RUNNING_TIME 18000000 //5 hours |
|
24 |
+#define MAX_RUNNING_TIME 21600000 //6 hours |
|
25 |
+#define MAX_RUNNING_TIME 25200000 //7 hours |
|
26 |
+#define MAX_RUNNING_TIME 28800000 //8 hours |
|
27 |
+#define MAX_RUNNING_TIME 32400000 //9 hours |
|
28 |
+#define MAX_RUNNING_TIME 36000000 //10 hours |
|
29 |
+#define MAX_RUNNING_TIME 39600000 //11 hours |
|
30 |
+#define MAX_RUNNING_TIME 43200000 //12 hours |
|
31 |
+*/ |
|
32 |
+#define MAX_RUNNING_TIME 14400000 //4 hours |
|
33 |
+#define BLINK_FLASH // Define if you want flash blinking during Wifi connection attempts |
|
34 |
+//#define UPDATE_PERIOD 30000 // Will cause MQTT reconnect as it is too long |
|
35 |
+#define UPDATE_PERIOD 20000 |
|
36 |
+long timeSinceLastModeSwitch = 0; |
|
37 |
+uint32_t countMeasures=0; |
|
38 |
+ |
|
39 |
+ |
|
40 |
+//#define LOOP_DELAY 10 //Initial Value |
|
41 |
+#define LOOP_DELAY 100 //Test Value |
|
42 |
+ |
|
43 |
+#endif //_MY_CONSTANTS |
... | ... |
@@ -0,0 +1,46 @@ |
1 |
+#ifndef _MY_DHT_H |
|
2 |
+#define _MY_DHT_H |
|
3 |
+ |
|
4 |
+#ifndef ARDUINO_ESP8266_WEMOS_D1R1 |
|
5 |
+ #define DHTPIN 5 // D1 : Digital pin connected to the DHT sensor |
|
6 |
+#else |
|
7 |
+ //LCD + Battery ESP |
|
8 |
+ //See : https://oneguyoneblog.com/2018/12/28/wemos-d1-esp-wroom-02-arduino-ide/ |
|
9 |
+ //#define DHTPIN 0 // D3 : Digital pin connected to the DHT sensor |
|
10 |
+ #define DHTPIN 3 // D9 : Digital pin connected to the DHT sensor |
|
11 |
+#endif //ARDUINO_ESP8266_WEMOS_D1R1 |
|
12 |
+#define DHTTYPE DHT11 // DHT 11 |
|
13 |
+ |
|
14 |
+DHT dht(DHTPIN, DHTTYPE); |
|
15 |
+ |
|
16 |
+float readDHTTemperature() { |
|
17 |
+ // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) |
|
18 |
+ // Read temperature as Celsius (the default) |
|
19 |
+ float t = dht.readTemperature(); |
|
20 |
+ // Read temperature as Fahrenheit (isFahrenheit = true) |
|
21 |
+ //float t = dht.readTemperature(true); |
|
22 |
+ // Check if any reads failed and exit early (to try again). |
|
23 |
+ if (isnan(t)) { |
|
24 |
+ Serial.println("Temperature : Failed to read from DHT sensor!"); |
|
25 |
+ return 0; |
|
26 |
+ } |
|
27 |
+ else { |
|
28 |
+ Serial.println("Temperature :"+String(t)); |
|
29 |
+ return t; |
|
30 |
+ } |
|
31 |
+} |
|
32 |
+ |
|
33 |
+float readDHTHumidity() { |
|
34 |
+ // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) |
|
35 |
+ float h = dht.readHumidity(); |
|
36 |
+ if (isnan(h)) { |
|
37 |
+ Serial.println("Humidity : Failed to read from DHT sensor!"); |
|
38 |
+ return 0; |
|
39 |
+ } |
|
40 |
+ else { |
|
41 |
+ Serial.println("Humidity :"+String(h)); |
|
42 |
+ return h; |
|
43 |
+ } |
|
44 |
+} |
|
45 |
+ |
|
46 |
+#endif //_MY_DHT_H |
... | ... |
@@ -0,0 +1,216 @@ |
1 |
+#ifndef _MY_DRAW_H |
|
2 |
+#define _MY_DRAW_H |
|
3 |
+ |
|
4 |
+#define NOLOGO -1 |
|
5 |
+#define SUN 0 |
|
6 |
+#define SUN_CLOUD 1 |
|
7 |
+#define CLOUD 2 |
|
8 |
+#define RAIN 3 |
|
9 |
+#define THUNDER 4 |
|
10 |
+ |
|
11 |
+ |
|
12 |
+#define SCREEN_WIDTH 128 // OLED display width, in pixels |
|
13 |
+#define SCREEN_HEIGHT 64 // OLED display height, in pixels |
|
14 |
+ |
|
15 |
+ |
|
16 |
+//-------------------------------------------------------------------------------------------- |
|
17 |
+//-------------------------------------------------------------------------------------------- |
|
18 |
+#ifdef ARDUINO_ESP8266_WEMOS_D1MINI |
|
19 |
+//-------------------------------------------------------------------------------------------- |
|
20 |
+//-------------------------------------------------------------------------------------------- |
|
21 |
+#include <U8g2lib.h> |
|
22 |
+#ifdef U8X8_HAVE_HW_SPI |
|
23 |
+ #include <SPI.h> |
|
24 |
+#endif |
|
25 |
+#ifdef U8X8_HAVE_HW_I2C |
|
26 |
+ #include <Wire.h> |
|
27 |
+#endif |
|
28 |
+ |
|
29 |
+#define SCROLL_Y 10 |
|
30 |
+#define T_FONTSZ 18 |
|
31 |
+ |
|
32 |
+U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 14, /* data=*/ 2); |
|
33 |
+//https://github.com/olikraus/u8g2/wiki/fntlistall |
|
34 |
+//https://github.com/olikraus/u8g2/wiki/setup_tutorial |
|
35 |
+ |
|
36 |
+ |
|
37 |
+void drawScreenReset() { |
|
38 |
+ pinMode(2, OUTPUT); // Initialize the LED_BUILTIN pin as an output |
|
39 |
+} |
|
40 |
+void drawInit() { |
|
41 |
+ drawScreenReset(); |
|
42 |
+ u8g2.begin(); |
|
43 |
+ u8g2.enableUTF8Print(); |
|
44 |
+} |
|
45 |
+ |
|
46 |
+void drawWeatherSymbol(u8g2_uint_t x, u8g2_uint_t y, uint8_t symbol) |
|
47 |
+{ |
|
48 |
+ // fonts used: |
|
49 |
+ // u8g2_font_open_iconic_embedded_6x_t |
|
50 |
+ // u8g2_font_open_iconic_weather_6x_t |
|
51 |
+ // encoding values, see: https://github.com/olikraus/u8g2/wiki/fntgrpiconic |
|
52 |
+ |
|
53 |
+ switch(symbol) |
|
54 |
+ { |
|
55 |
+ case SUN: |
|
56 |
+ u8g2.setFont(u8g2_font_open_iconic_weather_6x_t); |
|
57 |
+ u8g2.drawGlyph(x, y, 69); |
|
58 |
+ break; |
|
59 |
+ case SUN_CLOUD: |
|
60 |
+ u8g2.setFont(u8g2_font_open_iconic_weather_6x_t); |
|
61 |
+ u8g2.drawGlyph(x, y, 65); |
|
62 |
+ break; |
|
63 |
+ case CLOUD: |
|
64 |
+ u8g2.setFont(u8g2_font_open_iconic_weather_6x_t); |
|
65 |
+ u8g2.drawGlyph(x, y, 64); |
|
66 |
+ break; |
|
67 |
+ case RAIN: |
|
68 |
+ u8g2.setFont(u8g2_font_open_iconic_weather_6x_t); |
|
69 |
+ u8g2.drawGlyph(x, y, 67); |
|
70 |
+ break; |
|
71 |
+ case THUNDER: |
|
72 |
+ u8g2.setFont(u8g2_font_open_iconic_embedded_6x_t); |
|
73 |
+ u8g2.drawGlyph(x, y, 67); |
|
74 |
+ break; |
|
75 |
+ default: |
|
76 |
+ break; |
|
77 |
+ } |
|
78 |
+} |
|
79 |
+ |
|
80 |
+void drawWeather(uint8_t symbol, float degree, float humidity) |
|
81 |
+{ |
|
82 |
+ drawWeatherSymbol(0, 48, symbol); |
|
83 |
+ //u8g2.setFont(u8g2_font_logisoso32_tf); |
|
84 |
+ u8g2.setFont(u8g2_font_logisoso18_tf ); |
|
85 |
+ //u8g2.setCursor(48+3, 50); |
|
86 |
+ if(-1 != degree) { |
|
87 |
+ u8g2.setCursor(60, T_FONTSZ+SCROLL_Y+9); |
|
88 |
+ u8g2.print((float)((int)(10*degree+0.5))/10); |
|
89 |
+ u8g2.print("°"); // requires enableUTF8Print() |
|
90 |
+ } |
|
91 |
+ if(-1 != humidity) { |
|
92 |
+ u8g2.setCursor(0, 60); |
|
93 |
+ u8g2.print((float)((int)(10*humidity+0.5))/10); |
|
94 |
+ u8g2.print("%"); // requires enableUTF8Print() |
|
95 |
+ } |
|
96 |
+} |
|
97 |
+ |
|
98 |
+/* |
|
99 |
+ Draw a string with specified pixel offset. |
|
100 |
+ The offset can be negative. |
|
101 |
+ Limitation: The monochrome font with 8 pixel per glyph |
|
102 |
+*/ |
|
103 |
+void drawScrollString(int16_t offset, const char *s) |
|
104 |
+{ |
|
105 |
+ static char buf[36]; // should for screen with up to 256 pixel width |
|
106 |
+ size_t len; |
|
107 |
+ size_t char_offset = 0; |
|
108 |
+ u8g2_uint_t dx = 0; |
|
109 |
+ size_t visible = 0; |
|
110 |
+ |
|
111 |
+ |
|
112 |
+ u8g2.setDrawColor(0); // clear the scrolling area |
|
113 |
+ u8g2.drawBox(0, 0, u8g2.getDisplayWidth()-1, SCROLL_Y); |
|
114 |
+ u8g2.setDrawColor(1); // set the color for the text |
|
115 |
+ |
|
116 |
+ |
|
117 |
+ len = strlen(s); |
|
118 |
+ if ( offset < 0 ) |
|
119 |
+ { |
|
120 |
+ char_offset = (-offset)/8; |
|
121 |
+ dx = offset + char_offset*8; |
|
122 |
+ if ( char_offset >= u8g2.getDisplayWidth()/8 ) |
|
123 |
+ return; |
|
124 |
+ visible = u8g2.getDisplayWidth()/8-char_offset+1; |
|
125 |
+ strncpy(buf, s, visible); |
|
126 |
+ buf[visible] = '\0'; |
|
127 |
+ u8g2.setFont(u8g2_font_8x13_mf); |
|
128 |
+ //u8g2.drawStr(char_offset*8-dx, 62, buf); |
|
129 |
+ u8g2.drawStr(char_offset*8-dx, SCROLL_Y, buf); |
|
130 |
+ } |
|
131 |
+ else |
|
132 |
+ { |
|
133 |
+ char_offset = offset / 8; |
|
134 |
+ if ( char_offset >= len ) |
|
135 |
+ return; // nothing visible |
|
136 |
+ dx = offset - char_offset*8; |
|
137 |
+ visible = len - char_offset; |
|
138 |
+ if ( visible > u8g2.getDisplayWidth()/8+1 ) |
|
139 |
+ visible = u8g2.getDisplayWidth()/8+1; |
|
140 |
+ strncpy(buf, s+char_offset, visible); |
|
141 |
+ buf[visible] = '\0'; |
|
142 |
+ u8g2.setFont(u8g2_font_8x13_mf); |
|
143 |
+ u8g2.drawStr(-dx, SCROLL_Y, buf); |
|
144 |
+ } |
|
145 |
+} |
|
146 |
+ |
|
147 |
+void draw(const char *s, uint8_t symbol, float degree, float humidity) |
|
148 |
+{ |
|
149 |
+ int16_t offset = -(int16_t)u8g2.getDisplayWidth(); |
|
150 |
+ int16_t len = strlen(s); |
|
151 |
+ |
|
152 |
+ u8g2.clearBuffer(); // clear the internal memory |
|
153 |
+ drawWeather(symbol, degree, humidity); // draw the icon and degree only once |
|
154 |
+ drawScrollString(0, s); |
|
155 |
+ u8g2.sendBuffer(); // transfer internal memory to the display |
|
156 |
+} |
|
157 |
+void displaySetStatus(int state) {} |
|
158 |
+//-------------------------------------------------------------------------------------------- |
|
159 |
+//-------------------------------------------------------------------------------------------- |
|
160 |
+#elif ARDUINO_ESP8266_WEMOS_D1R1 |
|
161 |
+//-------------------------------------------------------------------------------------------- |
|
162 |
+//-------------------------------------------------------------------------------------------- |
|
163 |
+#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier |
|
164 |
+#include "SSD1306.h" // alias for `#include "SSD1306Wire.h"` |
|
165 |
+ |
|
166 |
+SSD1306 display(0x3c, 5, 4);//d1 d2 |
|
167 |
+ |
|
168 |
+#define SCROLL_Y 10 |
|
169 |
+#define T_FONTSZ 18 |
|
170 |
+ |
|
171 |
+void drawScreenReset() { |
|
172 |
+} |
|
173 |
+void drawInit() { |
|
174 |
+ // Initialising the UI will init the display too. |
|
175 |
+ display.init(); |
|
176 |
+ display.flipScreenVertically(); |
|
177 |
+} |
|
178 |
+void drawWeatherSymbol(uint8_t x, uint8_t y, uint8_t symbol) {} |
|
179 |
+void drawWeather(uint8_t symbol, float degree, float humidity) { |
|
180 |
+ display.setFont(ArialMT_Plain_24); |
|
181 |
+ if(-1 != degree) { |
|
182 |
+ char myString[8]=""; |
|
183 |
+ sprintf(myString,"%2.1f°",(float)((int)(10*degree+0.5))/10); |
|
184 |
+ display.drawString(60, T_FONTSZ-4, myString ); |
|
185 |
+ } |
|
186 |
+ if(-1 != humidity) { |
|
187 |
+ char myString[8]=""; |
|
188 |
+ sprintf(myString,"%2.0f%%",(float)((int)(10*humidity+0.5))/10); |
|
189 |
+ display.drawString(0,2*T_FONTSZ, myString ); |
|
190 |
+ } |
|
191 |
+} |
|
192 |
+void drawScrollString(int16_t offset, const char *s) { |
|
193 |
+ display.setFont(ArialMT_Plain_10); |
|
194 |
+ display.drawString(0, offset, s ); |
|
195 |
+} |
|
196 |
+void draw(const char *s, uint8_t symbol, float degree, float humidity) { |
|
197 |
+ display.setTextAlignment(TEXT_ALIGN_LEFT); |
|
198 |
+ display.clear(); |
|
199 |
+ drawWeather(NOLOGO, degree, humidity); |
|
200 |
+ drawScrollString(0, s); |
|
201 |
+ display.display(); |
|
202 |
+} |
|
203 |
+void displaySetStatus(int state) { |
|
204 |
+ if( 0 == state ) { |
|
205 |
+ display.displayOff(); |
|
206 |
+ } else { |
|
207 |
+ display.displayOn(); |
|
208 |
+ } |
|
209 |
+} |
|
210 |
+#endif // |
|
211 |
+ |
|
212 |
+ |
|
213 |
+ |
|
214 |
+ |
|
215 |
+ |
|
216 |
+#endif //_MY_DRAW_H |
... | ... |
@@ -0,0 +1,97 @@ |
1 |
+#ifndef _MY_HTTP |
|
2 |
+#define _MY_HTTP |
|
3 |
+#include <ESP8266WebServer.h> |
|
4 |
+ |
|
5 |
+#ifdef USE_OTA |
|
6 |
+#include "my_ota.h" |
|
7 |
+#endif //USE_OTA |
|
8 |
+ |
|
9 |
+#define PORT 80 |
|
10 |
+ESP8266WebServer server(PORT); |
|
11 |
+ |
|
12 |
+ |
|
13 |
+String message=""; |
|
14 |
+ |
|
15 |
+void handleRoot() { |
|
16 |
+ unsigned long time = millis()/1000; |
|
17 |
+ byte mac[6]; |
|
18 |
+ char macStr[6]; |
|
19 |
+ WiFi.macAddress(mac); |
|
20 |
+ sprintf(macStr,"%02x%02x%02x", mac[3], mac[4], mac[5]); |
|
21 |
+ String macStrString=macStr; |
|
22 |
+ message = ""; |
|
23 |
+ message += "<!DOCTYPE HTML><html>"; |
|
24 |
+ message += "<head>"; |
|
25 |
+ message += " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"; |
|
26 |
+ message += " <link rel=\"stylesheet\" href=\"https://use.fontawesome.com/releases/v5.7.2/css/all.css\" integrity=\"sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr\" crossorigin=\"anonymous\">"; |
|
27 |
+ message += " <title>esp8266-"+macStrString+"</title>"; |
|
28 |
+ message += "<style>"; |
|
29 |
+ message += "html{font-family:Arial;display:inline-block;margin:0px auto;text-align:center;}"; |
|
30 |
+ message += "h2{font-size:2.0rem;}"; |
|
31 |
+ message += "p{font-size:3.0rem;}"; |
|
32 |
+ message += ".app {font-size:0.8rem;font-style: italic;}"; |
|
33 |
+ message += ".dht-labels{font-size:1.5rem;vertical-align:middle;padding-bottom:15px;}"; |
|
34 |
+ message += "</style>"; |
|
35 |
+ message += "</head>"; |
|
36 |
+ message += "<body>"; |
|
37 |
+ message += "<h2>esp8266-"+macStrString+"</h2>"; |
|
38 |
+ message += "<p><i class=\"fas fa-thermometer-half\" style=\"color:#059e8a;\"></i><span class=\"dht-labels\">Temperature</span> <span id=\"temperature\">"+String(readDHTTemperature())+"</span><sup class=\"units\">°C</sup></p>"; |
|
39 |
+ message += "<p><i class=\"fas fa-tint\" style=\"color:#00add6;\"></i><span class=\"dht-labels\">Humidity</span> <span id=\"temperature\">"+String(readDHTHumidity())+"</span><sup class=\"units\">%</sup></p>"; |
|
40 |
+ message += "<p><i class=\"fas fa-clock\" style=\"color:#00add6;\"></i><span class=\"dht-labels\">Date</span> <span id=\"temperature\">"+String(acTimeString)+"</span></p>"; |
|
41 |
+ message += "<div class=\"app\">"+String(compile_date)+"</div>"; |
|
42 |
+ message += "</body></html>"; |
|
43 |
+ server.send(200, "text/html", message ); |
|
44 |
+} |
|
45 |
+void handleT() { |
|
46 |
+ server.send(200, "text/html", String(readDHTTemperature()) ); |
|
47 |
+} |
|
48 |
+void handleH() { |
|
49 |
+ server.send(200, "text/html", String(readDHTHumidity()) ); |
|
50 |
+} |
|
51 |
+void handleS() { |
|
52 |
+ byte mac[6]; |
|
53 |
+ char macStr[6]; |
|
54 |
+ WiFi.macAddress(mac); |
|
55 |
+ sprintf(macStr,"%02x%02x%02x", mac[3], mac[4], mac[5]); |
|
56 |
+ String statusMsg = "{"; |
|
57 |
+ statusMsg += "\"app_name\": \""+String(APPNAME)+"\","; |
|
58 |
+ statusMsg += "\"app_version\": \""+String(APPVER)+"\","; |
|
59 |
+ statusMsg += "\"build_date\": \""+String(compile_time)+"\","; |
|
60 |
+ statusMsg += "\"mac\": \""+WiFi.macAddress()+"\","; |
|
61 |
+ statusMsg += "\"ip\": \""+WiFiIP+"\","; |
|
62 |
+ statusMsg += "\"ota_name\": \"esp8266-"+String(macStr)+"\","; |
|
63 |
+ statusMsg += "\"uptime\": "+String(millis())+","; |
|
64 |
+ statusMsg += "\"countMeasures\": "+String(countMeasures)+","; |
|
65 |
+ statusMsg += "\"period\": "+String(UPDATE_PERIOD)+","; |
|
66 |
+ statusMsg += "\"loop_delay\": "+String(LOOP_DELAY)+","; |
|
67 |
+ statusMsg += "\"last_update\": \""+String(acTimeStringTZ)+"\""; |
|
68 |
+ statusMsg += "}"; |
|
69 |
+ server.send(200, "text/html", String(statusMsg) ); |
|
70 |
+} |
|
71 |
+ |
|
72 |
+void handleNotFound() { |
|
73 |
+ String message = "File Not Found\n\n"; |
|
74 |
+ message += "URI: "; |
|
75 |
+ message += server.uri(); |
|
76 |
+ message += "\nMethod: "; |
|
77 |
+ message += (server.method() == HTTP_GET) ? "GET" : "POST"; |
|
78 |
+ message += "\nArguments: "; |
|
79 |
+ message += server.args(); |
|
80 |
+ message += "\n"; |
|
81 |
+ |
|
82 |
+ for (uint8_t i = 0; i < server.args(); i++) { |
|
83 |
+ message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; |
|
84 |
+ } |
|
85 |
+ server.send(404, "text/plain", message); |
|
86 |
+} |
|
87 |
+ |
|
88 |
+ |
|
89 |
+void http_set() { |
|
90 |
+ server.on("/", handleRoot); |
|
91 |
+ server.on("/temperature", handleT); |
|
92 |
+ server.on("/humidity", handleH); |
|
93 |
+ server.on("/status", handleS); |
|
94 |
+ server.onNotFound(handleNotFound); |
|
95 |
+ server.begin(); |
|
96 |
+} |
|
97 |
+#endif //_MY_HTTP |
... | ... |
@@ -0,0 +1,78 @@ |
1 |
+#ifndef _MY_ISR_H |
|
2 |
+#define _MY_ISR_H |
|
3 |
+ |
|
4 |
+#include "my_mqtt.h" |
|
5 |
+ |
|
6 |
+#ifdef ARDUINO_ESP8266_WEMOS_D1R1 |
|
7 |
+uint8_t buttonDown=0; |
|
8 |
+uint8_t buttonUp=0; |
|
9 |
+uint8_t buttonRight=0; |
|
10 |
+uint8_t buttonPush=0; |
|
11 |
+ |
|
12 |
+void ICACHE_RAM_ATTR interrupt0() // Right |
|
13 |
+{ |
|
14 |
+ //Way: Opposite screen |
|
15 |
+ // Disabled as it makes the board reboot |
|
16 |
+ Serial.println("Right"); |
|
17 |
+ if(0==buttonRight) { |
|
18 |
+ buttonRight = 1; |
|
19 |
+ WiFiConnect(); |
|
20 |
+ mqtt_connect(); |
|
21 |
+ } else { |
|
22 |
+ buttonRight = 0; |
|
23 |
+ } |
|
24 |
+} |
|
25 |
+ |
|
26 |
+void ICACHE_RAM_ATTR interrupt12() // Down |
|
27 |
+{ |
|
28 |
+ //Way: Toward edge of the board |
|
29 |
+ Serial.println("Down"); |
|
30 |
+ if(0==buttonDown) { |
|
31 |
+ buttonDown = 1; |
|
32 |
+ } else { |
|
33 |
+ buttonDown = 0; |
|
34 |
+ } |
|
35 |
+ displaySetStatus(buttonDown); |
|
36 |
+} |
|
37 |
+ |
|
38 |
+void ICACHE_RAM_ATTR interrupt13() // Up |
|
39 |
+{ |
|
40 |
+ //Way: Toward hole in the board |
|
41 |
+ Serial.println("Up"); |
|
42 |
+ if(0==buttonUp) { |
|
43 |
+ buttonUp = 1; |
|
44 |
+ } else { |
|
45 |
+ buttonUp = 0; |
|
46 |
+ } |
|
47 |
+ displaySetStatus(1); |
|
48 |
+ //WiFiConnect(); |
|
49 |
+ WiFi.disconnect(true); |
|
50 |
+ //WiFi.mode(WIFI_STA); |
|
51 |
+} |
|
52 |
+ |
|
53 |
+void ICACHE_RAM_ATTR interrupt14() // Push |
|
54 |
+{ |
|
55 |
+ //Way: Toward hole in the board |
|
56 |
+ Serial.println("Push"); |
|
57 |
+ if(0==buttonPush) { |
|
58 |
+ buttonPush = 1; |
|
59 |
+ } else { |
|
60 |
+ buttonPush = 0; |
|
61 |
+ } |
|
62 |
+} |
|
63 |
+ |
|
64 |
+void isr_set() { |
|
65 |
+ //pinMode(0, INPUT_PULLUP); |
|
66 |
+ //attachInterrupt(digitalPinToInterrupt(0), interrupt0, FALLING); // Right |
|
67 |
+ pinMode(12, INPUT_PULLUP); |
|
68 |
+ attachInterrupt(digitalPinToInterrupt(12), interrupt12, FALLING); // Down |
|
69 |
+ pinMode(13, INPUT_PULLUP); |
|
70 |
+ attachInterrupt(digitalPinToInterrupt(13), interrupt13, FALLING); // Up |
|
71 |
+ pinMode(14, INPUT_PULLUP); |
|
72 |
+ attachInterrupt(digitalPinToInterrupt(14), interrupt14, FALLING); // Push |
|
73 |
+} |
|
74 |
+#else |
|
75 |
+void isr_set() {} |
|
76 |
+#endif //ARDUINO_ESP8266_WEMOS_D1R1 |
|
77 |
+ |
|
78 |
+#endif //_MY_ISR_H |
... | ... |
@@ -0,0 +1,56 @@ |
1 |
+#ifndef _MQTT_H |
|
2 |
+#define _MQTT_H |
|
3 |
+ |
|
4 |
+#include <PubSubClient.h> // Allows us to connect to, and publish to the MQTT broker |
|
5 |
+ |
|
6 |
+ |
|
7 |
+// MQTT |
|
8 |
+const int MAX_MQTT_CNX_RETRIES = 3; |
|
9 |
+static char mqtt_server[32] = ""; |
|
10 |
+const char* mqtt_server_int = "192.168.0.1"; |
|
11 |
+const char* mqtt_server_ext = "a.domain.tld"; |
|
12 |
+const char* mqtt_topic = "topicDHT"; |
|
13 |
+const int mqtt_port = 1883; |
|
14 |
+// The client id identifies the ESP8266 device. Think of it a bit like a hostname (Or just a name, like Greg). |
|
15 |
+char clientID[22] = ""; |
|
16 |
+const char* clientIDFmt="esp-%s"; |
|
17 |
+ |
|
18 |
+const char* mqtt_user="esp8266"; |
|
19 |
+const char* mqtt_password="SomeRandomPassword"; |
|
20 |
+ |
|
21 |
+// Initialise the WiFi and MQTT Client objects |
|
22 |
+WiFiClient wifiClient; |
|
23 |
+PubSubClient client(mqtt_server, 1883, wifiClient); // 1883 is the listener port for the Broker |
|
24 |
+ |
|
25 |
+void mqtt_connect() { |
|
26 |
+ if( 0 == strcmp(aplist[currentAPIndex].ssid,"wifi1") ) { |
|
27 |
+ //House Wifi |
|
28 |
+ client.setServer(mqtt_server_int, mqtt_port); |
|
29 |
+ //if (client.connect(clientID)) { |
|
30 |
+ if (client.connect(clientID,mqtt_user,mqtt_password)) { |
|
31 |
+ Serial.println("Connected to MQTT Broker : "+String(mqtt_server_int)); |
|
32 |
+ } else { |
|
33 |
+ Serial.println("Connection to MQTT Broker "+String(mqtt_server_int)+"failed..."); |
|
34 |
+ delay(2000); |
|
35 |
+ } |
|
36 |
+ } else { |
|
37 |
+ // External Wifi |
|
38 |
+ client.setServer(mqtt_server_ext, mqtt_port); |
|
39 |
+ if (client.connect(clientID,mqtt_user,mqtt_password)) { |
|
40 |
+ Serial.println("Connected to MQTT Broker : "+String(mqtt_server_ext)); |
|
41 |
+ } else { |
|
42 |
+ Serial.println("Connection to MQTT Broker "+String(mqtt_server_ext)+"failed..."); |
|
43 |
+ delay(2000); |
|
44 |
+ } |
|
45 |
+ } |
|
46 |
+} |
|
47 |
+ |
|
48 |
+void mqtt_reconnect() { |
|
49 |
+ byte count = 0; |
|
50 |
+ while (!client.connected() && count < MAX_MQTT_CNX_RETRIES ) { |
|
51 |
+ Serial.print("Attempting MQTT reconnection..."); |
|
52 |
+ mqtt_connect(); |
|
53 |
+ count++; |
|
54 |
+ } |
|
55 |
+} |
|
56 |
+#endif //_MQTT_H |
... | ... |
@@ -0,0 +1,35 @@ |
1 |
+#ifndef _MY_NTP_H |
|
2 |
+#define _MY_NTP_H |
|
3 |
+ |
|
4 |
+#define TIMEZONE_OFFSET 8 // CET |
|
5 |
+#define DST_OFFSET 0 // CEST |
|
6 |
+#define UPDATE_CYCLE (1 * 1000) // every second |
|
7 |
+ |
|
8 |
+static char acTimeString[32]; |
|
9 |
+static char acTimeStringTZ[38]; |
|
10 |
+const char* getTimeString(void) { |
|
11 |
+ time_t now = time(nullptr); |
|
12 |
+ struct tm *ts; |
|
13 |
+ ts = localtime(&now); |
|
14 |
+ strftime(acTimeString, sizeof(acTimeString), "%Y-%m-%d %H:%M:%S", ts); |
|
15 |
+ strftime(acTimeStringTZ, sizeof(acTimeStringTZ), "%Y-%m-%d %H:%M:%S+0800", ts); |
|
16 |
+ return acTimeString; |
|
17 |
+} |
|
18 |
+ |
|
19 |
+ |
|
20 |
+void setClock(void) { |
|
21 |
+ configTime((TIMEZONE_OFFSET * 3600), (DST_OFFSET * 3600), "time.google.com", "pool.ntp.org", "time.nist.gov"); |
|
22 |
+ int count = 0; |
|
23 |
+ Serial.print("Waiting for NTP time sync: "); |
|
24 |
+ time_t now = time(nullptr); // Secs since 01.01.1970 (when uninitalized starts with (8 * 3600 = 28800) |
|
25 |
+ while (now < 8 * 3600 * 2) { // Wait for realistic value |
|
26 |
+ delay(500); |
|
27 |
+ Serial.print("."); |
|
28 |
+ now = time(nullptr); |
|
29 |
+ if(count>20) break; |
|
30 |
+ count++; |
|
31 |
+ } |
|
32 |
+ Serial.printf("\nCurrent time: %s\n", getTimeString()); |
|
33 |
+} |
|
34 |
+ |
|
35 |
+#endif //_MY_NTP_H |
... | ... |
@@ -0,0 +1,41 @@ |
1 |
+#ifndef _MY_OTA_H |
|
2 |
+#define _MY_OTA_H |
|
3 |
+ |
|
4 |
+void ota_set() { |
|
5 |
+ #ifdef USE_OTA |
|
6 |
+ //ArduinoOTA.setPort(8266); |
|
7 |
+ //ArduinoOTA.setHostname(clientID); |
|
8 |
+ //ArduinoOTA.setPassword(WiFi.macAddress().c_str()); |
|
9 |
+ ArduinoOTA.onStart([]() { |
|
10 |
+ String type; |
|
11 |
+ displaySetStatus(1); |
|
12 |
+ if (ArduinoOTA.getCommand() == U_FLASH) { |
|
13 |
+ type = "sketch"; |
|
14 |
+ } else { // U_FS |
|
15 |
+ type = "filesystem"; |
|
16 |
+ } |
|
17 |
+ |
|
18 |
+ // NOTE: if updating FS this would be the place to unmount FS using FS.end() |
|
19 |
+ Serial.println("Start updating " + type); |
|
20 |
+ }); |
|
21 |
+ ArduinoOTA.onEnd([]() { |
|
22 |
+ Serial.println("\nEnd"); |
|
23 |
+ draw("DONE.", -1, -1, 100); |
|
24 |
+ }); |
|
25 |
+ ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { |
|
26 |
+ Serial.printf("Progress: %u%%\r", (progress / (total / 100))); |
|
27 |
+ draw("Upgrading....", -1, -1, (progress / (total / 100))); |
|
28 |
+ }); |
|
29 |
+ ArduinoOTA.onError([](ota_error_t error) { |
|
30 |
+ Serial.printf("Error[%u]: ", error); |
|
31 |
+ if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); |
|
32 |
+ else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); |
|
33 |
+ else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); |
|
34 |
+ else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); |
|
35 |
+ else if (error == OTA_END_ERROR) Serial.println("End Failed"); |
|
36 |
+ }); |
|
37 |
+ ArduinoOTA.begin(); |
|
38 |
+ #endif //USE_OTA |
|
39 |
+} |
|
40 |
+ |
|
41 |
+#endif //_MY_OTA_H |
... | ... |
@@ -0,0 +1,86 @@ |
1 |
+#ifndef _MY_WIFI_H |
|
2 |
+#define _MY_WIFI_H |
|
3 |
+ |
|
4 |
+//----------------------------------------------------------------------------------- |
|
5 |
+//Wifi Constants |
|
6 |
+//----------------------------------------------------------------------------------- |
|
7 |
+String WiFiIP; |
|
8 |
+typedef struct _ssid_list_t { |
|
9 |
+ const char* ssid; |
|
10 |
+ const char* password; |
|
11 |
+} ssid_list_t; |
|
12 |
+ |
|
13 |
+//#define _TEST |
|
14 |
+#ifndef _TEST |
|
15 |
+static int currentAPIndex = -1; |
|
16 |
+const int MAX_CNX_RETRIES = 20; |
|
17 |
+ssid_list_t aplist[]={ |
|
18 |
+ {"wifi1", "pass1"}, |
|
19 |
+ {"wifi2", "pass2"}, |
|
20 |
+ {"wifi3", "pass3"}, |
|
21 |
+ {NULL,NULL} |
|
22 |
+}; |
|
23 |
+#else |
|
24 |
+const int MAX_CNX_RETRIES = 1; |
|
25 |
+ssid_list_t aplist[]={ |
|
26 |
+ {"Phony", "phonyaccount"}, |
|
27 |
+ {NULL,NULL} |
|
28 |
+}; |
|
29 |
+#endif //_TEST |
|
30 |
+ |
|
31 |
+byte WiFiConnect() { |
|
32 |
+ WiFiIP = "No IP"; |
|
33 |
+ //WiFi.disconnect(true); |
|
34 |
+ //delay(2000); |
|
35 |
+ //WiFi.mode(WIFI_STA); |
|
36 |
+ //WiFi.setAutoConnect(true); |
|
37 |
+ |
|
38 |
+ byte i = 0; |
|
39 |
+ while(aplist[i].ssid!= NULL) { |
|
40 |
+ WiFi.persistent(false); |
|
41 |
+ WiFi.mode(WIFI_STA); |
|
42 |
+ WiFi.disconnect(true); |
|
43 |
+ delay(1000); |
|
44 |
+ WiFi.softAPdisconnect(true); |
|
45 |
+ delay(1000); |
|
46 |
+ Serial.print("WIFI status = "); |
|
47 |
+ Serial.println(WiFi.getMode()); |
|
48 |
+ |
|
49 |
+ WiFi.begin(aplist[i].ssid, aplist[i].password); |
|
50 |
+ byte count = 0; |
|
51 |
+ Serial.print("WiFiConnect: Connecting to "); |
|
52 |
+ Serial.print(aplist[i].ssid); |
|
53 |
+ draw(aplist[i].ssid, -1, -1, -1); |
|
54 |
+ while(WiFi.status() != WL_CONNECTED && count < MAX_CNX_RETRIES) |
|
55 |
+ { |
|
56 |
+ count ++; |
|
57 |
+ #ifdef BLINK_FLASH |
|
58 |
+ digitalWrite(LED_BUILTIN, 3); |
|
59 |
+ delay(500); |
|
60 |
+ digitalWrite(LED_BUILTIN, 0); |
|
61 |
+ delay(500); |
|
62 |
+ #else |
|
63 |
+ delay(500); |
|
64 |
+ #endif //BLINK_FLASH |
|
65 |
+ Serial.print("."); |
|
66 |
+ draw(aplist[i].ssid, NOLOGO, -1, 100*count/MAX_CNX_RETRIES); |
|
67 |
+ } |
|
68 |
+ if( WiFi.status() == WL_CONNECTED ) { |
|
69 |
+ Serial.println(""); |
|
70 |
+ IPAddress ip = WiFi.localIP(); |
|
71 |
+ WiFiIP = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]); |
|
72 |
+ Serial.println("WiFiConnect: "+WiFiIP); |
|
73 |
+ currentAPIndex = i; |
|
74 |
+ break; |
|
75 |
+ } |
|
76 |
+ if(WiFi.status() != WL_CONNECTED) |
|
77 |
+ { |
|
78 |
+ Serial.println("WiFiConnect: Failed"); |
|
79 |
+ } |
|
80 |
+ i++; |
|
81 |
+ } |
|
82 |
+ digitalWrite(LED_BUILTIN, HIGH); |
|
83 |
+ return (WiFi.status() == WL_CONNECTED) ? 1 : 0; |
|
84 |
+} |
|
85 |
+ |
|
86 |
+#endif //_MY_WIFI_H |