mirror of https://github.com/lumapu/ahoy.git
7 changed files with 759 additions and 603 deletions
@ -1,328 +0,0 @@ |
|||||
//-----------------------------------------------------------------------------
|
|
||||
// 2022 Ahoy, https://www.mikrocontroller.net/topic/525778
|
|
||||
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
|
|
||||
//-----------------------------------------------------------------------------
|
|
||||
|
|
||||
#include "main.h" |
|
||||
#include "version.h" |
|
||||
|
|
||||
//-----------------------------------------------------------------------------
|
|
||||
Main::Main(void) { |
|
||||
mDns = new DNSServer(); |
|
||||
mWeb = new ESP8266WebServer(80); |
|
||||
mUdp = new WiFiUDP(); |
|
||||
|
|
||||
memset(&config, 0, sizeof(config_t)); |
|
||||
|
|
||||
config.apActive = true; |
|
||||
mWifiSettingsValid = false; |
|
||||
mSettingsValid = false; |
|
||||
|
|
||||
mLimit = 10; |
|
||||
mNextTryTs = 0; |
|
||||
mApLastTick = 0; |
|
||||
|
|
||||
// default config
|
|
||||
snprintf(config.version, 12, "%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); |
|
||||
config.apActive = false; |
|
||||
config.sendInterval = SEND_INTERVAL; |
|
||||
|
|
||||
|
|
||||
mEep = new eep(); |
|
||||
Serial.begin(115200); |
|
||||
DPRINTLN(DBG_VERBOSE, F("Main::Main")); |
|
||||
|
|
||||
mUptimeSecs = 0; |
|
||||
mUptimeTicker = 0xffffffff; |
|
||||
mUptimeInterval = 1000; |
|
||||
|
|
||||
#ifdef AP_ONLY |
|
||||
mTimestamp = 1; |
|
||||
#else |
|
||||
mTimestamp = 0; |
|
||||
#endif |
|
||||
|
|
||||
mHeapStatCnt = 0; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
//-----------------------------------------------------------------------------
|
|
||||
void Main::setup(uint32_t timeout) { |
|
||||
DPRINTLN(DBG_VERBOSE, F("Main::setup")); |
|
||||
bool startAp = config.apActive; |
|
||||
mLimit = timeout; |
|
||||
|
|
||||
|
|
||||
startAp = getConfig(); |
|
||||
|
|
||||
#ifndef AP_ONLY |
|
||||
if(false == startAp) |
|
||||
startAp = setupStation(timeout); |
|
||||
#endif |
|
||||
|
|
||||
config.apActive = startAp; |
|
||||
mStActive = !startAp; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
//-----------------------------------------------------------------------------
|
|
||||
void Main::loop(void) { |
|
||||
//DPRINTLN(DBG_VERBOSE, F("M"));
|
|
||||
if(config.apActive) { |
|
||||
mDns->processNextRequest(); |
|
||||
#ifndef AP_ONLY |
|
||||
if(checkTicker(&mNextTryTs, (WIFI_AP_ACTIVE_TIME * 1000))) { |
|
||||
config.apActive = setupStation(mLimit); |
|
||||
if(config.apActive) { |
|
||||
if(strlen(WIFI_AP_PWD) < 8) |
|
||||
DPRINTLN(DBG_ERROR, F("password must be at least 8 characters long")); |
|
||||
mApLastTick = millis(); |
|
||||
mNextTryTs = (millis() + (WIFI_AP_ACTIVE_TIME * 1000)); |
|
||||
setupAp(WIFI_AP_SSID, WIFI_AP_PWD); |
|
||||
} |
|
||||
} |
|
||||
else { |
|
||||
if(millis() - mApLastTick > 10000) { |
|
||||
uint8_t cnt = WiFi.softAPgetStationNum(); |
|
||||
if(cnt > 0) { |
|
||||
DPRINTLN(DBG_INFO, String(cnt) + F(" clients connected, resetting AP timeout")); |
|
||||
mNextTryTs = (millis() + (WIFI_AP_ACTIVE_TIME * 1000)); |
|
||||
} |
|
||||
mApLastTick = millis(); |
|
||||
DPRINTLN(DBG_INFO, F("AP will be closed in ") + String((mNextTryTs - mApLastTick) / 1000) + F(" seconds")); |
|
||||
} |
|
||||
} |
|
||||
#endif |
|
||||
} |
|
||||
mWeb->handleClient(); |
|
||||
|
|
||||
if(checkTicker(&mUptimeTicker, mUptimeInterval)) { |
|
||||
mUptimeSecs++; |
|
||||
if(0 != mTimestamp) |
|
||||
mTimestamp++; |
|
||||
else { |
|
||||
if(!config.apActive) { |
|
||||
mTimestamp = getNtpTime(); |
|
||||
DPRINTLN(DBG_INFO, "[NTP]: " + getDateTimeStr(mTimestamp)); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/*if(++mHeapStatCnt >= 10) {
|
|
||||
mHeapStatCnt = 0; |
|
||||
stats(); |
|
||||
}*/ |
|
||||
} |
|
||||
if (WiFi.status() != WL_CONNECTED) { |
|
||||
DPRINTLN(DBG_INFO, "[WiFi]: Connection Lost"); |
|
||||
mStActive = false; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
//-----------------------------------------------------------------------------
|
|
||||
bool Main::getConfig(void) { |
|
||||
DPRINTLN(DBG_VERBOSE, F("Main::getConfig")); |
|
||||
config.apActive = false; |
|
||||
|
|
||||
mWifiSettingsValid = checkEEpCrc(ADDR_START, ADDR_WIFI_CRC, ADDR_WIFI_CRC); |
|
||||
mSettingsValid = checkEEpCrc(ADDR_START_SETTINGS, ((ADDR_NEXT)-(ADDR_START_SETTINGS)), ADDR_SETTINGS_CRC); |
|
||||
|
|
||||
if(mWifiSettingsValid) { |
|
||||
mEep->read(ADDR_SSID, config.stationSsid, SSID_LEN); |
|
||||
mEep->read(ADDR_PWD, config.stationPwd, PWD_LEN); |
|
||||
mEep->read(ADDR_DEVNAME, config.deviceName, DEVNAME_LEN); |
|
||||
} |
|
||||
|
|
||||
if((!mWifiSettingsValid) || (config.stationSsid[0] == 0xff)) { |
|
||||
snprintf(config.stationSsid, SSID_LEN, "%s", FB_WIFI_SSID); |
|
||||
snprintf(config.stationPwd, PWD_LEN, "%s", FB_WIFI_PWD); |
|
||||
snprintf(config.deviceName, DEVNAME_LEN, "%s", DEF_DEVICE_NAME); |
|
||||
} |
|
||||
|
|
||||
return config.apActive; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
//-----------------------------------------------------------------------------
|
|
||||
void Main::setupAp(const char *ssid, const char *pwd) { |
|
||||
DPRINTLN(DBG_VERBOSE, F("Main::setupAp")); |
|
||||
IPAddress apIp(192, 168, 1, 1); |
|
||||
|
|
||||
DPRINTLN(DBG_INFO, F("\n---------\nAP MODE\nSSID: ") |
|
||||
+ String(ssid) + F("\nPWD: ") |
|
||||
+ String(pwd) + F("\nActive for: ") |
|
||||
+ String(WIFI_AP_ACTIVE_TIME) + F(" seconds") |
|
||||
+ F("\n---------\n")); |
|
||||
DPRINTLN(DBG_DEBUG, String(mNextTryTs)); |
|
||||
|
|
||||
WiFi.mode(WIFI_AP); |
|
||||
WiFi.softAPConfig(apIp, apIp, IPAddress(255, 255, 255, 0)); |
|
||||
WiFi.softAP(ssid, pwd); |
|
||||
|
|
||||
mDns->start(mDnsPort, "*", apIp); |
|
||||
|
|
||||
/*mWeb->onNotFound([&]() {
|
|
||||
showSetup(); |
|
||||
}); |
|
||||
mWeb->on("/", std::bind(&Main::showSetup, this)); |
|
||||
|
|
||||
mWeb->begin();*/ |
|
||||
} |
|
||||
|
|
||||
|
|
||||
//-----------------------------------------------------------------------------
|
|
||||
bool Main::setupStation(uint32_t timeout) { |
|
||||
DPRINTLN(DBG_VERBOSE, F("Main::setupStation")); |
|
||||
int32_t cnt; |
|
||||
bool startAp = false; |
|
||||
|
|
||||
if(timeout >= 3) |
|
||||
cnt = (timeout - 3) / 2 * 10; |
|
||||
else { |
|
||||
timeout = 1; |
|
||||
cnt = 1; |
|
||||
} |
|
||||
|
|
||||
WiFi.mode(WIFI_STA); |
|
||||
WiFi.begin(config.stationSsid, config.stationPwd); |
|
||||
if(String(config.deviceName) != "") |
|
||||
WiFi.hostname(config.deviceName); |
|
||||
|
|
||||
delay(2000); |
|
||||
DPRINTLN(DBG_INFO, F("connect to network '") + String(config.stationSsid) + F("' ...")); |
|
||||
while (WiFi.status() != WL_CONNECTED) { |
|
||||
delay(100); |
|
||||
if(cnt % 100 == 0) |
|
||||
Serial.println("."); |
|
||||
else |
|
||||
Serial.print("."); |
|
||||
|
|
||||
if(timeout > 0) { // limit == 0 -> no limit
|
|
||||
if(--cnt <= 0) { |
|
||||
if(WiFi.status() != WL_CONNECTED) { |
|
||||
startAp = true; |
|
||||
WiFi.disconnect(); |
|
||||
} |
|
||||
delay(100); |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Serial.println("."); |
|
||||
|
|
||||
if(false == startAp) { |
|
||||
mWeb->begin(); |
|
||||
} |
|
||||
|
|
||||
delay(1000); |
|
||||
|
|
||||
return startAp; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
//-----------------------------------------------------------------------------
|
|
||||
void Main::saveValues(uint32_t saveMask = 0) { |
|
||||
DPRINTLN(DBG_VERBOSE, F("Main::saveValues")); |
|
||||
|
|
||||
if(CHK_MSK(saveMask, SAVE_SSID)) |
|
||||
mEep->write(ADDR_SSID, config.stationSsid, SSID_LEN); |
|
||||
if(CHK_MSK(saveMask, SAVE_PWD)) |
|
||||
mEep->write(ADDR_PWD, config.stationPwd, SSID_LEN); |
|
||||
if(CHK_MSK(saveMask, SAVE_DEVICE_NAME)) |
|
||||
mEep->write(ADDR_DEVNAME, config.deviceName, DEVNAME_LEN); |
|
||||
|
|
||||
if(saveMask > 0) { |
|
||||
updateCrc(); |
|
||||
mEep->commit(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
//-----------------------------------------------------------------------------
|
|
||||
void Main::updateCrc(void) { |
|
||||
DPRINTLN(DBG_VERBOSE, F("Main::updateCrc")); |
|
||||
uint16_t crc; |
|
||||
crc = buildEEpCrc(ADDR_START, ADDR_WIFI_CRC); |
|
||||
//Serial.println("new CRC: " + String(crc, HEX));
|
|
||||
mEep->write(ADDR_WIFI_CRC, crc); |
|
||||
mEep->commit(); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
//-----------------------------------------------------------------------------
|
|
||||
time_t Main::getNtpTime(void) { |
|
||||
//DPRINTLN(DBG_VERBOSE, F("Main::getNtpTime"));
|
|
||||
time_t date = 0; |
|
||||
IPAddress timeServer; |
|
||||
uint8_t buf[NTP_PACKET_SIZE]; |
|
||||
uint8_t retry = 0; |
|
||||
|
|
||||
WiFi.hostByName(NTP_SERVER_NAME, timeServer); |
|
||||
mUdp->begin(NTP_LOCAL_PORT); |
|
||||
|
|
||||
|
|
||||
sendNTPpacket(timeServer); |
|
||||
|
|
||||
while(retry++ < 5) { |
|
||||
int wait = 150; |
|
||||
while(--wait) { |
|
||||
if(NTP_PACKET_SIZE <= mUdp->parsePacket()) { |
|
||||
uint64_t secsSince1900; |
|
||||
mUdp->read(buf, NTP_PACKET_SIZE); |
|
||||
secsSince1900 = (buf[40] << 24); |
|
||||
secsSince1900 |= (buf[41] << 16); |
|
||||
secsSince1900 |= (buf[42] << 8); |
|
||||
secsSince1900 |= (buf[43] ); |
|
||||
|
|
||||
date = secsSince1900 - 2208988800UL; // UTC time
|
|
||||
date += (TIMEZONE + offsetDayLightSaving(date)) * 3600; |
|
||||
break; |
|
||||
} |
|
||||
else |
|
||||
delay(10); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return date; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
//-----------------------------------------------------------------------------
|
|
||||
void Main::sendNTPpacket(IPAddress& address) { |
|
||||
//DPRINTLN(DBG_VERBOSE, F("Main::sendNTPpacket"));
|
|
||||
uint8_t buf[NTP_PACKET_SIZE] = {0}; |
|
||||
|
|
||||
buf[0] = B11100011; // LI, Version, Mode
|
|
||||
buf[1] = 0; // Stratum
|
|
||||
buf[2] = 6; // Max Interval between messages in seconds
|
|
||||
buf[3] = 0xEC; // Clock Precision
|
|
||||
// bytes 4 - 11 are for Root Delay and Dispersion and were set to 0 by memset
|
|
||||
buf[12] = 49; // four-byte reference ID identifying
|
|
||||
buf[13] = 0x4E; |
|
||||
buf[14] = 49; |
|
||||
buf[15] = 52; |
|
||||
|
|
||||
mUdp->beginPacket(address, 123); // NTP request, port 123
|
|
||||
mUdp->write(buf, NTP_PACKET_SIZE); |
|
||||
mUdp->endPacket(); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
//-----------------------------------------------------------------------------
|
|
||||
// calculates the daylight saving time for middle Europe. Input: Unixtime in UTC
|
|
||||
// from: https://forum.arduino.cc/index.php?topic=172044.msg1278536#msg1278536
|
|
||||
time_t Main::offsetDayLightSaving (uint32_t local_t) { |
|
||||
//DPRINTLN(DBG_VERBOSE, F("Main::offsetDayLightSaving"));
|
|
||||
int m = month (local_t); |
|
||||
if(m < 3 || m > 10) return 0; // no DSL in Jan, Feb, Nov, Dez
|
|
||||
if(m > 3 && m < 10) return 1; // DSL in Apr, May, Jun, Jul, Aug, Sep
|
|
||||
int y = year (local_t); |
|
||||
int h = hour (local_t); |
|
||||
int hToday = (h + 24 * day(local_t)); |
|
||||
if((m == 3 && hToday >= (1 + TIMEZONE + 24 * (31 - (5 * y /4 + 4) % 7))) |
|
||||
|| (m == 10 && hToday < (1 + TIMEZONE + 24 * (31 - (5 * y /4 + 1) % 7))) ) |
|
||||
return 1; |
|
||||
else |
|
||||
return 0; |
|
||||
} |
|
@ -1,183 +0,0 @@ |
|||||
//-----------------------------------------------------------------------------
|
|
||||
// 2022 Ahoy, https://www.mikrocontroller.net/topic/525778
|
|
||||
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
|
|
||||
//-----------------------------------------------------------------------------
|
|
||||
|
|
||||
#ifndef __MAIN_H__ |
|
||||
#define __MAIN_H__ |
|
||||
|
|
||||
#include "dbg.h" |
|
||||
#include "Arduino.h" |
|
||||
|
|
||||
#include <ESP8266WiFi.h> |
|
||||
#include <DNSServer.h> |
|
||||
#include <ESP8266WebServer.h> |
|
||||
|
|
||||
// NTP
|
|
||||
#include <WiFiUdp.h> |
|
||||
#include <TimeLib.h> |
|
||||
|
|
||||
#include "eep.h" |
|
||||
#include "defines.h" |
|
||||
#include "crc.h" |
|
||||
|
|
||||
|
|
||||
const byte mDnsPort = 53; |
|
||||
|
|
||||
/* NTP TIMESERVER CONFIG */ |
|
||||
#define NTP_SERVER_NAME "pool.ntp.org" |
|
||||
#define NTP_LOCAL_PORT 8888 |
|
||||
#define NTP_PACKET_SIZE 48 |
|
||||
#define TIMEZONE 1 // Central European time +1
|
|
||||
|
|
||||
|
|
||||
typedef struct { |
|
||||
char version[12]; |
|
||||
char deviceName[DEVNAME_LEN]; |
|
||||
|
|
||||
// wifi
|
|
||||
char stationSsid[SSID_LEN]; |
|
||||
char stationPwd[PWD_LEN]; |
|
||||
bool apActive; |
|
||||
|
|
||||
// nrf24
|
|
||||
uint16_t sendInterval; |
|
||||
} config_t; |
|
||||
|
|
||||
|
|
||||
#define SAVE_SSID 0x00000001 |
|
||||
#define SAVE_PWD 0x00000002 |
|
||||
#define SAVE_DEVICE_NAME 0x00000004 |
|
||||
|
|
||||
#define CHK_MSK(v, m) ((m & v) == m) |
|
||||
|
|
||||
class Main { |
|
||||
public: |
|
||||
Main(void); |
|
||||
virtual void setup(uint32_t timeout); |
|
||||
virtual void loop(); |
|
||||
void saveValues(uint32_t saveMask); |
|
||||
|
|
||||
String getDateTimeStr(time_t t) { |
|
||||
char str[20] = {0}; |
|
||||
if(0 == t) |
|
||||
sprintf(str, "n/a"); |
|
||||
else |
|
||||
sprintf(str, "%04d-%02d-%02d %02d:%02d:%02d", year(t), month(t), day(t), hour(t), minute(t), second(t)); |
|
||||
return String(str); |
|
||||
} |
|
||||
|
|
||||
inline uint32_t getUptime(void) { |
|
||||
return mUptimeSecs; |
|
||||
} |
|
||||
|
|
||||
inline uint32_t getTimestamp(void) { |
|
||||
return mTimestamp; |
|
||||
} |
|
||||
|
|
||||
void eraseSettings(bool all = false) { |
|
||||
//DPRINTLN(DBG_VERBOSE, F("main.h:eraseSettings"));
|
|
||||
uint8_t buf[64] = {0}; |
|
||||
uint16_t addr = (all) ? ADDR_START : ADDR_START_SETTINGS; |
|
||||
uint16_t end; |
|
||||
do { |
|
||||
end = addr + 64; |
|
||||
if(end > (ADDR_SETTINGS_CRC + 2)) |
|
||||
end = (ADDR_SETTINGS_CRC + 2); |
|
||||
DPRINTLN(DBG_DEBUG, F("erase: 0x") + String(addr, HEX) + " - 0x" + String(end, HEX)); |
|
||||
mEep->write(addr, buf, (end-addr)); |
|
||||
addr = end; |
|
||||
} while(addr < (ADDR_SETTINGS_CRC + 2)); |
|
||||
mEep->commit(); |
|
||||
} |
|
||||
|
|
||||
ESP8266WebServer *mWeb; |
|
||||
config_t config; |
|
||||
|
|
||||
|
|
||||
protected: |
|
||||
virtual void updateCrc(void); |
|
||||
|
|
||||
inline uint16_t buildEEpCrc(uint32_t start, uint32_t length) { |
|
||||
DPRINTLN(DBG_VERBOSE, F("main.h:buildEEpCrc")); |
|
||||
uint8_t buf[32]; |
|
||||
uint16_t crc = 0xffff; |
|
||||
uint8_t len; |
|
||||
|
|
||||
while(length > 0) { |
|
||||
len = (length < 32) ? length : 32; |
|
||||
mEep->read(start, buf, len); |
|
||||
crc = crc16(buf, len, crc); |
|
||||
start += len; |
|
||||
length -= len; |
|
||||
} |
|
||||
return crc; |
|
||||
} |
|
||||
|
|
||||
bool checkEEpCrc(uint32_t start, uint32_t length, uint32_t crcPos) { |
|
||||
DPRINTLN(DBG_VERBOSE, F("main.h:checkEEpCrc")); |
|
||||
DPRINTLN(DBG_DEBUG, F("start: ") + String(start) + F(", length: ") + String(length)); |
|
||||
uint16_t crcRd, crcCheck; |
|
||||
crcCheck = buildEEpCrc(start, length); |
|
||||
mEep->read(crcPos, &crcRd); |
|
||||
DPRINTLN(DBG_DEBUG, "CRC RD: " + String(crcRd, HEX) + " CRC CALC: " + String(crcCheck, HEX)); |
|
||||
return (crcCheck == crcRd); |
|
||||
} |
|
||||
|
|
||||
inline bool checkTicker(uint32_t *ticker, uint32_t interval) { |
|
||||
//DPRINTLN(DBG_VERBOSE, F("c"));
|
|
||||
uint32_t mil = millis(); |
|
||||
if(mil >= *ticker) { |
|
||||
*ticker = mil + interval; |
|
||||
return true; |
|
||||
} |
|
||||
else if(mil < (*ticker - interval)) { |
|
||||
*ticker = mil + interval; |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
void stats(void) { |
|
||||
DPRINTLN(DBG_VERBOSE, F("main.h:stats")); |
|
||||
uint32_t free; |
|
||||
uint16_t max; |
|
||||
uint8_t frag; |
|
||||
ESP.getHeapStats(&free, &max, &frag); |
|
||||
DPRINT(DBG_VERBOSE, F("free: ") + String(free)); |
|
||||
DPRINT(DBG_VERBOSE, F(" - max: ") + String(max) + "%"); |
|
||||
DPRINTLN(DBG_VERBOSE, F(" - frag: ") + String(frag)); |
|
||||
} |
|
||||
|
|
||||
bool mWifiSettingsValid; |
|
||||
bool mSettingsValid; |
|
||||
bool mStActive; |
|
||||
|
|
||||
eep *mEep; |
|
||||
uint32_t mTimestamp; |
|
||||
uint32_t mLimit; |
|
||||
uint32_t mNextTryTs; |
|
||||
uint32_t mApLastTick; |
|
||||
|
|
||||
private: |
|
||||
bool getConfig(void); |
|
||||
void setupAp(const char *ssid, const char *pwd); |
|
||||
bool setupStation(uint32_t timeout); |
|
||||
|
|
||||
|
|
||||
time_t getNtpTime(void); |
|
||||
void sendNTPpacket(IPAddress& address); |
|
||||
time_t offsetDayLightSaving (uint32_t local_t); |
|
||||
|
|
||||
uint32_t mUptimeTicker; |
|
||||
uint16_t mUptimeInterval; |
|
||||
uint32_t mUptimeSecs; |
|
||||
uint8_t mHeapStatCnt; |
|
||||
|
|
||||
DNSServer *mDns; |
|
||||
|
|
||||
WiFiUDP *mUdp; // for time server
|
|
||||
}; |
|
||||
|
|
||||
#endif /*__MAIN_H__*/ |
|
@ -0,0 +1,218 @@ |
|||||
|
//-----------------------------------------------------------------------------
|
||||
|
// 2022 Ahoy, https://www.mikrocontroller.net/topic/525778
|
||||
|
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
|
||||
|
//-----------------------------------------------------------------------------
|
||||
|
|
||||
|
#ifndef __WEB_H__ |
||||
|
#define __WEB_H__ |
||||
|
|
||||
|
#include "dbg.h" |
||||
|
#include <ESP8266WebServer.h> |
||||
|
#include <ESP8266HTTPUpdateServer.h> |
||||
|
|
||||
|
#include "app.h" |
||||
|
|
||||
|
#include "html/h/index_html.h" |
||||
|
#include "html/h/style_css.h" |
||||
|
#include "favicon.h" |
||||
|
#include "html/h/setup_html.h" |
||||
|
|
||||
|
|
||||
|
class web { |
||||
|
public: |
||||
|
web(app *main) { |
||||
|
mMain = main; |
||||
|
mWeb = main->mWeb; |
||||
|
//mWeb = new ESP8266WebServer(80);
|
||||
|
mUpdater = new ESP8266HTTPUpdateServer(); |
||||
|
mUpdater->setup(mWeb); |
||||
|
} |
||||
|
|
||||
|
void setup(void) { |
||||
|
mWeb->on("/", std::bind(&web::showIndex, this)); |
||||
|
mWeb->on("/style.css", std::bind(&web::showCss, this)); |
||||
|
mWeb->on("/favicon.ico", std::bind(&web::showFavicon, this)); |
||||
|
mWeb->onNotFound ( std::bind(&web::showNotFound, this)); |
||||
|
mWeb->on("/uptime", std::bind(&web::showUptime, this)); |
||||
|
mWeb->on("/reboot", std::bind(&web::showReboot, this)); |
||||
|
mWeb->on("/erase", std::bind(&web::showErase, this)); |
||||
|
mWeb->on("/factory", std::bind(&web::showFactoryRst, this)); |
||||
|
|
||||
|
mWeb->on("/setup", std::bind(&web::showSetup, this)); |
||||
|
mWeb->on("/save", std::bind(&web::showSave, this)); |
||||
|
} |
||||
|
|
||||
|
void showIndex(void) { |
||||
|
DPRINTLN(DBG_VERBOSE, F("showIndex")); |
||||
|
String html = FPSTR(index_html); |
||||
|
html.replace(F("{DEVICE}"), mMain->config.deviceName); |
||||
|
html.replace(F("{VERSION}"), mMain->config.version); |
||||
|
html.replace(F("{TS}"), String(mMain->config.sendInterval) + " "); |
||||
|
html.replace(F("{JS_TS}"), String(mMain->config.sendInterval * 1000)); |
||||
|
html.replace(F("{BUILD}"), String(AUTO_GIT_HASH)); |
||||
|
mWeb->send(200, "text/html", html); |
||||
|
} |
||||
|
|
||||
|
void showCss(void) { |
||||
|
mWeb->send(200, "text/css", FPSTR(style_css)); |
||||
|
} |
||||
|
|
||||
|
void showFavicon(void) { |
||||
|
static const char favicon_type[] PROGMEM = "image/x-icon"; |
||||
|
static const char favicon_content[] PROGMEM = FAVICON_PANEL_16; |
||||
|
mWeb->send_P(200, favicon_type, favicon_content, sizeof(favicon_content)); |
||||
|
} |
||||
|
|
||||
|
void showNotFound(void) { |
||||
|
DPRINTLN(DBG_VERBOSE, F("showNotFound - ") + mWeb->uri()); |
||||
|
String msg = F("File Not Found\n\nURI: "); |
||||
|
msg += mWeb->uri(); |
||||
|
mWeb->send(404, F("text/plain"), msg); |
||||
|
} |
||||
|
|
||||
|
void showUptime(void) { |
||||
|
char time[21] = {0}; |
||||
|
uint32_t uptime = mMain->getUptime(); |
||||
|
|
||||
|
uint32_t upTimeSc = uint32_t((uptime) % 60); |
||||
|
uint32_t upTimeMn = uint32_t((uptime / (60)) % 60); |
||||
|
uint32_t upTimeHr = uint32_t((uptime / (60 * 60)) % 24); |
||||
|
uint32_t upTimeDy = uint32_t((uptime / (60 * 60 * 24)) % 365); |
||||
|
|
||||
|
snprintf(time, 20, "%d Days, %02d:%02d:%02d;", upTimeDy, upTimeHr, upTimeMn, upTimeSc); |
||||
|
|
||||
|
mWeb->send(200, "text/plain", String(time) + mMain->getDateTimeStr(mMain->getTimestamp())); |
||||
|
} |
||||
|
|
||||
|
void showReboot(void) { |
||||
|
mWeb->send(200, F("text/html"), F("<!doctype html><html><head><title>Rebooting ...</title><meta http-equiv=\"refresh\" content=\"10; URL=/\"></head><body>rebooting ... auto reload after 10s</body></html>")); |
||||
|
delay(1000); |
||||
|
ESP.restart(); |
||||
|
} |
||||
|
|
||||
|
void showErase() { |
||||
|
DPRINTLN(DBG_VERBOSE, F("showErase")); |
||||
|
mMain->eraseSettings(); |
||||
|
showReboot(); |
||||
|
} |
||||
|
|
||||
|
void showFactoryRst(void) { |
||||
|
DPRINTLN(DBG_VERBOSE, F("showFactoryRst")); |
||||
|
String content = ""; |
||||
|
int refresh = 3; |
||||
|
if(mWeb->args() > 0) { |
||||
|
if(mWeb->arg("reset").toInt() == 1) { |
||||
|
mMain->eraseSettings(true); |
||||
|
content = F("factory reset: success\n\nrebooting ... "); |
||||
|
refresh = 10; |
||||
|
} |
||||
|
else { |
||||
|
content = F("factory reset: aborted"); |
||||
|
refresh = 3; |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
content = F("<h1>Factory Reset</h1>" |
||||
|
"<p><a href=\"/factory?reset=1\">RESET</a><br/><br/><a href=\"/factory?reset=0\">CANCEL</a><br/></p>"); |
||||
|
refresh = 120; |
||||
|
} |
||||
|
mWeb->send(200, F("text/html"), F("<!doctype html><html><head><title>Factory Reset</title><meta http-equiv=\"refresh\" content=\"") + String(refresh) + F("; URL=/\"></head><body>") + content + F("</body></html>")); |
||||
|
if(refresh == 10) { |
||||
|
delay(1000); |
||||
|
ESP.restart(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void showSetup(void) { |
||||
|
DPRINTLN(DBG_VERBOSE, F("showSetup")); |
||||
|
String html = FPSTR(setup_html); |
||||
|
html.replace(F("{SSID}"), mMain->config.stationSsid); |
||||
|
// PWD will be left at the default value (for protection)
|
||||
|
// -> the PWD will only be changed if it does not match the default "{PWD}"
|
||||
|
html.replace(F("{DEVICE}"), String(mMain->config.deviceName)); |
||||
|
html.replace(F("{VERSION}"), String(mMain->config.version)); |
||||
|
if(mMain->config.apActive) |
||||
|
html.replace("{IP}", String(F("http://192.168.1.1"))); |
||||
|
else |
||||
|
html.replace("{IP}", (F("http://") + String(WiFi.localIP().toString()))); |
||||
|
|
||||
|
mWeb->send(200, F("text/html"), html); |
||||
|
} |
||||
|
|
||||
|
void showSave(void) { |
||||
|
DPRINTLN(DBG_VERBOSE, F("showSave")); |
||||
|
|
||||
|
if(mWeb->args() > 0) { |
||||
|
uint32_t saveMask = 0; |
||||
|
char buf[20] = {0}; |
||||
|
|
||||
|
// general
|
||||
|
if(mWeb->arg("ssid") != "") { |
||||
|
mWeb->arg("ssid").toCharArray(mMain->config.stationSsid, SSID_LEN); |
||||
|
saveMask |= SAVE_SSID; |
||||
|
} |
||||
|
if(mWeb->arg("pwd") != "{PWD}") { |
||||
|
mWeb->arg("pwd").toCharArray(mMain->config.stationPwd, PWD_LEN); |
||||
|
saveMask |= SAVE_PWD; |
||||
|
} |
||||
|
if(mWeb->arg("device") != "") { |
||||
|
mWeb->arg("device").toCharArray(mMain->config.deviceName, DEVNAME_LEN); |
||||
|
saveMask |= SAVE_DEVICE_NAME; |
||||
|
} |
||||
|
|
||||
|
// inverter
|
||||
|
Inverter<> *iv; |
||||
|
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) { |
||||
|
iv = mMain->mSys->getInverterByPos(i, false); |
||||
|
// address
|
||||
|
mWeb->arg("inv" + String(i) + "Addr").toCharArray(buf, 20); |
||||
|
if(strlen(buf) == 0) |
||||
|
memset(buf, 0, 20); |
||||
|
else |
||||
|
saveMask |= SAVE_INVERTERS; |
||||
|
iv->serial.u64 = mMain->Serial2u64(buf); |
||||
|
|
||||
|
// active power limit
|
||||
|
uint16_t actPwrLimit = mWeb->arg("inv" + String(i) + "ActivePowerLimit").toInt(); |
||||
|
if (actPwrLimit != 0xffff && actPwrLimit > 0) |
||||
|
iv->powerLimit[0] = actPwrLimit; |
||||
|
|
||||
|
// name
|
||||
|
mWeb->arg("inv" + String(i) + "Name").toCharArray(iv->name, MAX_NAME_LENGTH); |
||||
|
|
||||
|
// max channel power / name
|
||||
|
for(uint8_t j = 0; j < 4; j++) { |
||||
|
iv->chMaxPwr[j] = mWeb->arg("inv" + String(i) + "ModPwr" + String(j)).toInt() & 0xffff; |
||||
|
mWeb->arg("inv" + String(i) + "ModName" + String(j)).toCharArray(iv->chName[j], MAX_NAME_LENGTH); |
||||
|
} |
||||
|
} |
||||
|
if(mWeb->arg("invInterval") != "") { |
||||
|
mMain->config.sendInterval = mWeb->arg("invInterval").toInt(); |
||||
|
saveMask |= SAVE_INV_SEND_INTERVAL; |
||||
|
} |
||||
|
if(mWeb->arg("invRetry") != "") { |
||||
|
mMain->config.sendInterval = mWeb->arg("invRetry").toInt(); |
||||
|
saveMask |= SAVE_INV_RETRY; |
||||
|
} |
||||
|
|
||||
|
mMain->saveValues(saveMask); |
||||
|
|
||||
|
if(mWeb->arg("reboot") == "on") |
||||
|
showReboot(); |
||||
|
else |
||||
|
mWeb->send(200, F("text/html"), F("<!doctype html><html><head><title>Setup saved</title><meta http-equiv=\"refresh\" content=\"0; URL=/setup\"></head><body>" |
||||
|
"<p>saved</p></body></html>")); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
private: |
||||
|
ESP8266WebServer *mWeb; |
||||
|
ESP8266HTTPUpdateServer *mUpdater; |
||||
|
app *mMain; |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
#endif /*__WEB_H__*/ |
Loading…
Reference in new issue