1 /*********************************************************************************************\
3 \*********************************************************************************************/
9 addLog(LOG_LEVEL_INFO, "Config: Use default configuration");
10 memset(&sysCfg, 0x00, sizeof(SYSCFG));
11 memset(&myCfg, 0x00, sizeof(SYSCFG));
12 sysCfg.cfg_holder = CFG_HOLDER;
14 sysCfg.version = VERSION;
15 sysCfg.seriallog_level = SERIAL_LOG_LEVEL;
16 sysCfg.syslog_level = SYS_LOG_LEVEL;
17 strlcpy(sysCfg.syslog_host, SYS_LOG_HOST, sizeof(sysCfg.syslog_host));
18 strlcpy(sysCfg.sta_ssid, STA_SSID, sizeof(sysCfg.sta_ssid));
19 strlcpy(sysCfg.sta_pwd, STA_PASS, sizeof(sysCfg.sta_pwd));
20 strlcpy(sysCfg.otaUrl, OTA_URL, sizeof(sysCfg.otaUrl));
21 strlcpy(sysCfg.mqtt_host, MQTT_HOST, sizeof(sysCfg.mqtt_host));
22 strlcpy(sysCfg.mqtt_grptopic, MQTT_GRPTOPIC, sizeof(sysCfg.mqtt_grptopic));
23 strlcpy(sysCfg.mqtt_topic, MQTT_TOPIC, sizeof(sysCfg.mqtt_topic));
24 strlcpy(sysCfg.mqtt_topic2, "0", sizeof(sysCfg.mqtt_topic2));
25 strlcpy(sysCfg.mqtt_subtopic, MQTT_SUBTOPIC, sizeof(sysCfg.mqtt_subtopic));
26 sysCfg.timezone = APP_TIMEZONE;
27 sysCfg.power = APP_POWER;
28 sysCfg.ledstate = APP_LEDSTATE;
33 #include "spi_flash.h"
35 extern "C" uint32_t _SPIFFS_end;
36 #define CFG_LOCATION (((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE) - 2 // End of SPIFFS area
42 if (memcmp(&myCfg, &sysCfg, sizeof(SYSCFG))) {
44 if (sysCfg.saveFlag == 0) { // Handle default and rollover
45 spi_flash_erase_sector(CFG_LOCATION + (sysCfg.saveFlag &1));
46 spi_flash_write((CFG_LOCATION + (sysCfg.saveFlag &1)) * SPI_FLASH_SEC_SIZE, (uint32 *)&sysCfg, sizeof(SYSCFG));
49 spi_flash_erase_sector(CFG_LOCATION + (sysCfg.saveFlag &1));
50 spi_flash_write((CFG_LOCATION + (sysCfg.saveFlag &1)) * SPI_FLASH_SEC_SIZE, (uint32 *)&sysCfg, sizeof(SYSCFG));
52 snprintf_P(log, sizeof(log), PSTR("Config: Saved configuration to flash at %X and count %d"), CFG_LOCATION + (sysCfg.saveFlag &1), sysCfg.saveFlag);
53 addLog(LOG_LEVEL_DEBUG, log);
63 spi_flash_read((CFG_LOCATION) * SPI_FLASH_SEC_SIZE, (uint32 *)&sysCfg, sizeof(SYSCFG));
64 spi_flash_read((CFG_LOCATION + 1) * SPI_FLASH_SEC_SIZE, (uint32 *)&myCfg, sizeof(SYSCFG));
66 if (sysCfg.saveFlag < myCfg.saveFlag) sysCfg = myCfg;
67 snprintf_P(log, sizeof(log), PSTR("Config: Loaded configuration from flash at %X and count %d"), CFG_LOCATION + (sysCfg.saveFlag &1), sysCfg.saveFlag);
68 addLog(LOG_LEVEL_DEBUG, log);
69 if (sysCfg.cfg_holder != CFG_HOLDER) CFG_Default();
76 SpiFlashOpResult result;
78 uint32_t _sectorStart = (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 1;
79 uint32_t _sectorEnd = ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE;
80 byte seriallog_level = sysCfg.seriallog_level;
82 snprintf_P(log, sizeof(log), PSTR("Config: Erasing %d flash sectors"), _sectorEnd - _sectorStart);
83 addLog(LOG_LEVEL_DEBUG, log);
85 for (uint32_t _sector = _sectorStart; _sector < _sectorEnd; _sector++) {
87 result = spi_flash_erase_sector(_sector);
89 if (LOG_LEVEL_DEBUG_MORE <= seriallog_level) {
90 Serial.print(F("Flash: Erased sector "));
91 Serial.print(_sector);
92 if (result == SPI_FLASH_RESULT_OK)
93 Serial.println(F(" OK"));
95 Serial.println(F(" Error"));
101 /*********************************************************************************************\
103 \*********************************************************************************************/
105 #define WIFI_SMARTSEC 60 // seconds
106 #define WIFI_CHECKSEC 20 // seconds
107 #define WIFI_RETRY 16
110 uint8_t wifiretry = WIFI_RETRY;
111 uint8_t smartcounter = 0;
113 void WIFI_smartconfig()
115 smartcounter = WIFI_SMARTSEC; // Allow up to WIFI_SMARTSECS seconds for phone to provide ssid/pswd
116 wificounter = smartcounter +5;
117 addLog(LOG_LEVEL_INFO, "Smartconfig: Started and active for 1 minute");
118 WiFi.beginSmartConfig();
123 if ((WiFi.status() == WL_CONNECTED) && (static_cast<uint32_t>(WiFi.localIP()) != 0)) {
124 wificounter = WIFI_CHECKSEC;
125 wifiretry = WIFI_RETRY;
127 switch (WiFi.status()) {
128 case WL_NO_SSID_AVAIL:
129 case WL_CONNECT_FAILED:
130 addLog(LOG_LEVEL_DEBUG, "Wifi: STATION_CONNECT_FAIL");
134 addLog(LOG_LEVEL_DEBUG, "Wifi: STATION_IDLE");
135 if (wifiretry == (WIFI_RETRY / 2)) WiFi.begin();
146 void WIFI_Check(uint8_t param)
152 case WIFI_SMARTCONFIG:
156 if (wificounter <= 0) {
157 addLog(LOG_LEVEL_DEBUG_MORE, "Wifi: Check connection");
158 wificounter = WIFI_CHECKSEC;
164 if (WiFi.smartConfigDone()) {
166 memcpy(sysCfg.sta_ssid, WiFi.SSID().c_str(), strlen(WiFi.SSID().c_str())+1);
167 memcpy(sysCfg.sta_pwd, WiFi.psk().c_str(), strlen(WiFi.psk().c_str())+1);
168 snprintf_P(log, sizeof(log), PSTR("Smartconfig: SSID %s and Password %s"), sysCfg.sta_ssid, sysCfg.sta_pwd);
169 addLog(LOG_LEVEL_INFO, log);
172 if (smartcounter == 0) {
173 WiFi.stopSmartConfig();
181 void WIFI_Connect(char *Hostname)
185 WiFi.persistent(false); // Solve possible wifi init errors
186 WiFi.hostname(Hostname);
187 snprintf_P(log, sizeof(log), PSTR("Wifi: Connecting to %s as %s"), sysCfg.sta_ssid, Hostname);
188 addLog(LOG_LEVEL_DEBUG, log);
189 WiFi.setAutoConnect(true);
190 WiFi.mode(WIFI_STA); // Disable AP mode
191 WiFi.begin(sysCfg.sta_ssid, sysCfg.sta_pwd);
195 /*********************************************************************************************\
197 \*********************************************************************************************/
199 #define NTP_SERVER1 "pool.ntp.org"
200 #define NTP_SERVER2 "nl.pool.ntp.org"
201 #define NTP_SERVER3 "0.nl.pool.ntp.org"
207 #define LEAP_YEAR(Y) ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) )
209 static const uint8_t monthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; // API starts months from 1, this array starts from 0
211 static const char monthNames[37] = { "JanFebMrtAprMayJunJulAugSepOctNovDec" };
218 // given myrtc as time in Linux format break into time components
219 // this is a more compact version of the C library localtime function
220 // note that internally the year is offset from 1970 - compensated at the end
223 uint8_t month, monthLength;
227 time = (uint32_t) myrtc;
228 rtcTime.Second = time % 60;
229 time /= 60; // now it is minutes
230 rtcTime.Minute = time % 60;
231 time /= 60; // now it is hours
232 rtcTime.Hour = time % 24;
233 time /= 24; // now it is days
234 rtcTime.Wday = ((time + 4) % 7) + 1; // Sunday is day 1
238 while ((unsigned) (days += (LEAP_YEAR(year) ? 366 : 365)) <= time) {
241 rtcTime.Year = year; // year is offset from 1970
243 days -= LEAP_YEAR(year) ? 366 : 365;
244 time -= days; // now it is days in this year, starting at 0
249 for (month = 0; month < 12; month++) {
250 if (month == 1) { // february
251 if (LEAP_YEAR(year)) {
259 monthLength = monthDays[month];
262 if (time >= monthLength) {
269 strlcpy(rtcTime.MonthName, monthNames +(month *3), sizeof(rtcTime.MonthName));
270 rtcTime.Month = month + 1; // jan is month 1
271 rtcTime.Day = time + 1; // day of month
272 rtcTime.Year = rtcTime.Year + 1970;
279 // NTP Sync every hour at x:0:10
280 if (rtcTime.Minute == 0) {
281 if ((rtcTime.Second >= 10) && !ntpsync) {
282 myrtc = sntp_get_current_timestamp();
283 ntpsync = (myrtc) ? 1 : 0;
284 snprintf_P(log, sizeof(log), PSTR("RTC: sntp %d, %s"), myrtc, sntp_get_real_time(myrtc));
285 addLog(LOG_LEVEL_DEBUG, log);
287 if (rtcTime.Second == 40) ntpsync = 0;
293 void rtc_timezone(uint8_t timezone)
296 // if (true == sntp_set_timezone(sysCfg.timezone))
297 sntp_set_timezone(timezone);
299 myrtc = sntp_get_current_timestamp();
303 void rtc_init(uint8_t timezone)
305 sntp_setservername(0, NTP_SERVER1);
306 sntp_setservername(1, NTP_SERVER2);
307 // sntp_setservername(2, NTP_SERVER3);
309 // if (true == sntp_set_timezone(sysCfg.timezone))
310 sntp_set_timezone(timezone);
315 /*********************************************************************************************\
317 \*********************************************************************************************/
319 void syslog(const char *message)
321 char mess[MESSZ], str[TOPSZ+MESSZ];
323 portUDP.beginPacket(sysCfg.syslog_host, SYS_LOG_PORT);
324 strlcpy(mess, message, sizeof(mess));
325 mess[sizeof(mess)-1] = 0;
326 snprintf_P(str, sizeof(str), PSTR("%s %s"), Hostname, mess);
331 void addLog(byte loglevel, const char *line)
333 #ifdef DEBUG_ESP_PORT
334 DEBUG_ESP_PORT.printf("DebugMsg %s\n", line);
337 if (loglevel <= sysCfg.seriallog_level) Serial.println(line);
339 if ((WiFi.status() == WL_CONNECTED) && (loglevel <= sysCfg.syslog_level)) syslog(line);
342 void addLog(byte loglevel, String& string)
344 addLog(loglevel, string.c_str());
347 /*********************************************************************************************\
349 \*********************************************************************************************/