2
2
3
3
#include < ESP8266WiFi.h>
4
4
#include < ESP8266mDNS.h>
5
+ #include < DNSServer.h>
5
6
#include < WiFiUdp.h>
6
7
#include < ArduinoOTA.h>
7
8
#include < PubSubClient.h>
15
16
#include " decode.h"
16
17
#include " commands.h"
17
18
19
+ DNSServer dnsServer;
18
20
19
21
// to read bus voltage in stats
20
22
ADC_MODE (ADC_VCC);
@@ -28,6 +30,7 @@ ADC_MODE(ADC_VCC);
28
30
// of the address block
29
31
#define DRD_ADDRESS 0x00
30
32
33
+ const byte DNS_PORT = 53 ;
31
34
32
35
#define SERIALTIMEOUT 2000 // wait until all 203 bytes are read, must not be too long to avoid blocking the code
33
36
@@ -39,8 +42,13 @@ settingsStruct heishamonSettings;
39
42
40
43
bool sending = false ; // mutex for sending data
41
44
bool mqttcallbackinprogress = false ; // mutex for processing mqtt callback
45
+
46
+ #define MQTTRECONNECTTIMER 30000 // it takes 30 secs for each mqtt server reconnect attempt
42
47
unsigned long nextMqttReconnectAttempt = 0 ;
43
- #define MQTTRECONNECTTIMER 30000
48
+
49
+ #define WIFIRETRYTIMER 30000 // switch between hotspot and configured SSID each 30 secs if SSID is lost
50
+ unsigned long nextWifiRetryTimer = WIFIRETRYTIMER;
51
+
44
52
unsigned long nexttime = 0 ;
45
53
46
54
unsigned long allowreadtime = 0 ; // set to millis value during send, allow to wait millis for answer
@@ -68,15 +76,15 @@ char log_msg[256];
68
76
// mqtt topic to sprintf and then publish to
69
77
char mqtt_topic[256 ];
70
78
71
- int mqttReconnects = 0 ;
79
+ static int mqttReconnects = 0 ;
72
80
73
81
// can't have too much in buffer due to memory shortage
74
82
#define MAXCOMMANDSINBUFFER 10
75
83
76
84
// buffer for commands to send
77
85
struct cmdbuffer_t {
78
- uint8_t length;
79
- byte data[128 ];
86
+ uint8_t length;
87
+ byte data[128 ];
80
88
} cmdbuffer[MAXCOMMANDSINBUFFER];
81
89
82
90
static uint8_t cmdstart = 0 ;
@@ -90,19 +98,74 @@ DoubleResetDetect drd(DRD_TIMEOUT, DRD_ADDRESS);
90
98
WiFiClient mqtt_wifi_client;
91
99
PubSubClient mqtt_client (mqtt_wifi_client);
92
100
101
+ // check wifi bools
102
+ bool softAPenabled = false ;
103
+ bool reconnectingWiFi = false ;
104
+
105
+ /*
106
+ * check_wifi will process wifi reconnecting managing
107
+ */
108
+ void check_wifi ()
109
+ {
110
+ if ((WiFi.status () != WL_CONNECTED) || (!WiFi.localIP ())) {
111
+ /*
112
+ * if we are not connected to an AP
113
+ * we must be in softAP so respond to DNS
114
+ */
115
+ dnsServer.processNextRequest ();
116
+
117
+ if ((reconnectingWiFi) && (WiFi.softAPgetStationNum () > 0 )) {
118
+ log_message ((char *)" WiFi lost, but softAP station connecting, so stop scanning..." );
119
+ reconnectingWiFi = false ;
120
+ WiFi.disconnect ();
121
+ }
122
+
123
+ /*
124
+ * only start this routine if timeout on
125
+ * reconnecting to AP and SSID is set
126
+ */
127
+ if ((strlen (heishamonSettings.wifi_ssid ) > 0 ) && (nextWifiRetryTimer < millis ())) {
128
+ nextWifiRetryTimer = millis () + WIFIRETRYTIMER;
129
+ if (!softAPenabled) {
130
+ log_message ((char *)" WiFi lost, starting setup hotspot..." );
131
+ softAPenabled = true ;
132
+ WiFi.softAPConfig (apIP, apIP, IPAddress (255 , 255 , 255 , 0 ));
133
+ WiFi.softAP (" HeishaMon-Setup" );
134
+ }
135
+ if ((!reconnectingWiFi) && (WiFi.softAPgetStationNum () == 0 )) {
136
+ reconnectingWiFi = true ;
137
+ log_message ((char *)" Retrying configured WiFi, ..." );
138
+ if (strlen (heishamonSettings.wifi_password ) == 0 ) {
139
+ WiFi.begin (heishamonSettings.wifi_ssid );
140
+ } else {
141
+ WiFi.begin (heishamonSettings.wifi_ssid , heishamonSettings.wifi_password );
142
+ }
143
+ } else {
144
+ reconnectingWiFi = false ;
145
+ log_message ((char *)" Reconnecting to WiFi failed. Waiting a few seconds before trying again." );
146
+ WiFi.disconnect ();
147
+ }
148
+ }
149
+ } else {
150
+ if (softAPenabled) {
151
+ log_message ((char *)" WiFi (re)connected, shutting down hotspot..." );
152
+ softAPenabled = false ;
153
+ reconnectingWiFi = false ;
154
+ WiFi.softAPdisconnect (true );
155
+ }
156
+ /*
157
+ * always update if wifi is working so next time on ssid failure
158
+ * it only starts the routine above after this timeout
159
+ */
160
+ nextWifiRetryTimer = millis () + WIFIRETRYTIMER;
161
+ }
162
+ }
163
+
93
164
void mqtt_reconnect ()
94
165
{
95
166
unsigned long now = millis ();
96
167
if (now > nextMqttReconnectAttempt) { // only try reconnect each MQTTRECONNECTTIMER seconds or on boot when nextMqttReconnectAttempt is still 0
97
168
nextMqttReconnectAttempt = now + MQTTRECONNECTTIMER;
98
- if ((WiFi.status () != WL_CONNECTED) || (! WiFi.localIP ()) ) {
99
- log_message ((char *)" Lost WiFi connection!" );
100
- if (!heishamonSettings.optionalPCB ) { // do not reboot if optional pcb emulation is active because it is more important to keep transmitting data packages to heatpump
101
- log_message ((char *)" Rebooting..." );
102
- delay (1000 );
103
- ESP.restart ();
104
- }
105
- }
106
169
log_message ((char *)" Reconnecting to mqtt server ..." );
107
170
char topic[256 ];
108
171
sprintf (topic, " %s/%s" , heishamonSettings.mqtt_topic_base , mqtt_willtopic);
@@ -237,15 +300,15 @@ bool readSerial()
237
300
238
301
void popCommandBuffer () {
239
302
// to make sure we can pop a command from the buffer
240
- if ((!sending) && cmdnrel > 0 ) {
303
+ if ((!sending) && cmdnrel > 0 ) {
241
304
send_command (cmdbuffer[cmdstart].data , cmdbuffer[cmdstart].length );
242
305
cmdstart = (cmdstart + 1 ) % (MAXCOMMANDSINBUFFER);
243
306
cmdnrel--;
244
307
}
245
308
}
246
309
247
310
void pushCommandBuffer (byte* command, int length) {
248
- if (cmdnrel+ 1 > MAXCOMMANDSINBUFFER) {
311
+ if (cmdnrel + 1 > MAXCOMMANDSINBUFFER) {
249
312
log_message ((char *)" Too much commands already in buffer. Ignoring this commands.\n " );
250
313
return ;
251
314
}
@@ -368,7 +431,7 @@ void setupHttp() {
368
431
handleDebug (&httpServer, data, 203 );
369
432
});
370
433
httpServer.on (" /settings" , [] {
371
- handleSettings (&httpServer, &heishamonSettings);
434
+ handleSettings (drd, &httpServer, &heishamonSettings);
372
435
});
373
436
httpServer.on (" /smartcontrol" , [] {
374
437
handleSmartcontrol (&httpServer, &heishamonSettings, actData);
@@ -387,6 +450,28 @@ void setupHttp() {
387
450
httpServer.send ( 302 , " text/plain" , " " );
388
451
httpServer.client ().stop ();
389
452
});
453
+ httpServer.onNotFound ([]() {
454
+ httpServer.sendHeader (" Location" , String (" /" ), true );
455
+ httpServer.send (302 , " text/plain" , " " );
456
+ httpServer.client ().stop ();
457
+ });
458
+ /*
459
+ Captive portal url's
460
+ for now, the android one sometimes gets the heishamon in a wait loop during wifi reconfig
461
+
462
+ httpServer.on("/generate_204", [] {
463
+ handleSettings(drd, &httpServer, &heishamonSettings);
464
+ }); */
465
+ httpServer.on (" /hotspot-detect.html" , [] {
466
+ handleSettings (drd, &httpServer, &heishamonSettings);
467
+ });
468
+ httpServer.on (" /fwlink" , [] {
469
+ handleSettings (drd, &httpServer, &heishamonSettings);
470
+ });
471
+ httpServer.on (" /popup" , [] {
472
+ handleSettings (drd, &httpServer, &heishamonSettings);
473
+ });
474
+
390
475
httpServer.begin ();
391
476
392
477
webSocket.begin ();
@@ -441,15 +526,20 @@ void setupMqtt() {
441
526
442
527
void setup () {
443
528
setupSerial ();
529
+ setupSerial1 ();
530
+ Serial.println ();
531
+ Serial.println (F (" --- HEISHAMON ---" ));
532
+ Serial.println (F (" starting..." ));
533
+ WiFi.printDiag (Serial);
444
534
setupWifi (drd, &heishamonSettings);
445
535
MDNS.begin (heishamonSettings.wifi_hostname );
446
536
MDNS.addService (" http" , " tcp" , 80 );
447
- setupSerial1 ();
448
537
setupOTA ();
449
538
setupMqtt ();
450
539
setupHttp ();
451
540
452
541
switchSerial (); // switch serial to gpio13/gpio15
542
+ WiFi.printDiag (Serial1);
453
543
454
544
// load optional PCB data from flash
455
545
if (heishamonSettings.optionalPCB ) {
@@ -467,6 +557,9 @@ void setup() {
467
557
if (heishamonSettings.use_1wire ) initDallasSensors (log_message, heishamonSettings.updataAllDallasTime , heishamonSettings.waitDallasTime );
468
558
if (heishamonSettings.use_s0 ) initS0Sensors (heishamonSettings.s0Settings , mqtt_client, heishamonSettings.mqtt_topic_base );
469
559
560
+ dnsServer.setErrorReplyCode (DNSReplyCode::NoError);
561
+ dnsServer.start (DNS_PORT, " *" , apIP);
562
+
470
563
// wait waittime for the first start in main loop
471
564
nexttime = millis () + (1000 * heishamonSettings.waitTime );
472
565
}
@@ -503,6 +596,8 @@ void read_panasonic_data() {
503
596
}
504
597
505
598
void loop () {
599
+ // check wifi
600
+ check_wifi ();
506
601
// Handle OTA first.
507
602
ArduinoOTA.handle ();
508
603
// then handle HTTP
@@ -533,7 +628,7 @@ void loop() {
533
628
if (millis () > nexttime) {
534
629
nexttime = millis () + (1000 * heishamonSettings.waitTime );
535
630
// check mqtt
536
- if (!mqtt_client.connected ())
631
+ if ( (WiFi. isConnected ()) && ( !mqtt_client.connected ()) )
537
632
{
538
633
log_message ((char *)" Lost MQTT connection!" );
539
634
mqtt_reconnect ();
0 commit comments