ESPSomfy-RTS/ConfigSettings.cpp
2023-07-19 11:07:43 -07:00

492 lines
16 KiB
C++

#include <Arduino.h>
#include <LittleFS.h> // https://github.com/espressif/arduino-esp32/tree/master/libraries/LittleFS
#include <time.h>
#include <WiFi.h>
#include <Preferences.h>
#include "ConfigSettings.h"
Preferences pref;
bool BaseSettings::load() { return true; }
bool BaseSettings::loadFile(const char *filename) {
size_t filesize = 10;
String data = "";
if(LittleFS.exists(filename)) {
File file = LittleFS.open(filename, "r");
filesize += file.size();
while(file.available()) {
char c = file.read();
data += c;
}
DynamicJsonDocument doc(filesize);
deserializeJson(doc, data);
JsonObject obj = doc.as<JsonObject>();
this->fromJSON(obj);
file.close();
}
return false;
}
bool BaseSettings::saveFile(const char *filename) {
File file = LittleFS.open(filename, "w");
DynamicJsonDocument doc(2048);
JsonObject obj = doc.as<JsonObject>();
this->toJSON(obj);
serializeJson(doc, file);
file.close();
return true;
}
bool BaseSettings::parseValueString(JsonObject &obj, const char *prop, char *pdest, size_t size) {
if(obj.containsKey(prop)) strlcpy(pdest, obj[prop], size);
return true;
}
bool BaseSettings::parseIPAddress(JsonObject &obj, const char *prop, IPAddress *pdest) {
if(obj.containsKey(prop)) {
char buff[16];
strlcpy(buff, obj[prop], sizeof(buff));
pdest->fromString(buff);
}
return true;
}
int BaseSettings::parseValueInt(JsonObject &obj, const char *prop, int defVal) {
if(obj.containsKey(prop)) return obj[prop];
return defVal;
}
double BaseSettings::parseValueDouble(JsonObject &obj, const char *prop, double defVal) {
if(obj.containsKey(prop)) return obj[prop];
return defVal;
}
bool ConfigSettings::begin() {
uint32_t chipId = 0;
uint64_t mac = ESP.getEfuseMac();
for(int i=0; i<17; i=i+8) {
chipId |= ((mac >> (40 - i)) & 0xff) << i;
}
snprintf_P(this->serverId, sizeof(this->serverId), "%02X%02X%02X",
(uint16_t)((chipId >> 16) & 0xff),
(uint16_t)((chipId >> 8) & 0xff),
(uint16_t)chipId & 0xff);
this->load();
this->Security.begin();
this->IP.begin();
this->WIFI.begin();
this->Ethernet.begin();
this->NTP.begin();
this->MQTT.begin();
this->print();
return true;
}
bool ConfigSettings::load() {
pref.begin("CFG");
pref.getString("hostname", this->hostname, sizeof(this->hostname));
this->ssdpBroadcast = pref.getBool("ssdpBroadcast", true);
this->connType = static_cast<conn_types>(pref.getChar("connType", 0x00));
Serial.printf("Preference GFG Free Entries: %d\n", pref.freeEntries());
pref.end();
if(this->connType == conn_types::unset) {
// We are doing this to convert the data from previous versions.
this->connType = conn_types::wifi;
pref.begin("WIFI");
pref.getString("hostname", this->hostname, sizeof(this->hostname));
this->ssdpBroadcast = pref.getBool("ssdpBroadcast", true);
pref.remove("hostname");
pref.remove("ssdpBroadcast");
pref.end();
this->save();
}
return true;
}
bool ConfigSettings::save() {
pref.begin("CFG");
pref.putString("hostname", this->hostname);
pref.putBool("ssdpBroadcast", this->ssdpBroadcast);
pref.putChar("connType", static_cast<uint8_t>(this->connType));
pref.end();
return true;
}
bool ConfigSettings::toJSON(JsonObject &obj) {
obj["ssdpBroadcast"] = this->ssdpBroadcast;
obj["hostname"] = this->hostname;
obj["connType"] = static_cast<uint8_t>(this->connType);
return true;
}
bool ConfigSettings::requiresAuth() { return this->Security.type != security_types::None; }
bool ConfigSettings::fromJSON(JsonObject &obj) {
if(obj.containsKey("ssdpBroadcast")) this->ssdpBroadcast = obj["ssdpBroadcast"];
if(obj.containsKey("hostname")) this->parseValueString(obj, "hostname", this->hostname, sizeof(this->hostname));
if(obj.containsKey("connType")) this->connType = static_cast<conn_types>(obj["connType"].as<uint8_t>());
return true;
}
void ConfigSettings::print() {
this->Security.print();
Serial.printf("Connection Type: %u\n", (unsigned int) this->connType);
this->NTP.print();
if(this->connType == conn_types::wifi || this->connType == conn_types::unset) this->WIFI.print();
if(this->connType == conn_types::ethernet || this->connType == conn_types::ethernetpref) this->Ethernet.print();
}
void ConfigSettings::emitSockets() {}
void ConfigSettings::emitSockets(uint8_t num) {}
bool MQTTSettings::begin() {
this->load();
return true;
}
bool MQTTSettings::toJSON(JsonObject &obj) {
obj["enabled"] = this->enabled;
obj["protocol"] = this->protocol;
obj["hostname"] = this->hostname;
obj["port"] = this->port;
obj["username"] = this->username;
obj["password"] = this->password;
obj["rootTopic"] = this->rootTopic;
return true;
}
bool MQTTSettings::fromJSON(JsonObject &obj) {
if(obj.containsKey("enabled")) this->enabled = obj["enabled"];
this->parseValueString(obj, "protocol", this->protocol, sizeof(this->protocol));
this->parseValueString(obj, "hostname", this->hostname, sizeof(this->hostname));
this->parseValueString(obj, "username", this->username, sizeof(this->username));
this->parseValueString(obj, "password", this->password, sizeof(this->password));
this->parseValueString(obj, "rootTopic", this->rootTopic, sizeof(this->rootTopic));
if(obj.containsKey("port")) this->port = obj["port"];
return true;
}
bool MQTTSettings::save() {
pref.begin("MQTT");
pref.clear();
pref.putString("protocol", this->protocol);
pref.putString("hostname", this->hostname);
pref.putShort("port", this->port);
pref.putString("username", this->username);
pref.putString("password", this->password);
pref.putString("rootTopic", this->rootTopic);
pref.putBool("enabled", this->enabled);
pref.end();
return true;
}
bool MQTTSettings::load() {
pref.begin("MQTT");
pref.getString("protocol", this->protocol, sizeof(this->protocol));
pref.getString("hostname", this->hostname, sizeof(this->hostname));
this->port = pref.getShort("port", 1883);
pref.getString("username", this->username, sizeof(this->username));
pref.getString("password", this->password, sizeof(this->password));
pref.getString("rootTopic", this->rootTopic, sizeof(this->rootTopic));
this->enabled = pref.getBool("enabled", false);
pref.end();
return true;
}
bool ConfigSettings::toJSON(DynamicJsonDocument &doc) {
doc["fwVersion"] = this->fwVersion;
JsonObject objWIFI = doc.createNestedObject("WIFI");
this->WIFI.toJSON(objWIFI);
JsonObject objNTP = doc.createNestedObject("NTP");
this->NTP.toJSON(objNTP);
JsonObject objMQTT = doc.createNestedObject("MQTT");
this->MQTT.toJSON(objMQTT);
return true;
}
bool NTPSettings::begin() {
this->load();
this->apply();
return true;
}
bool NTPSettings::save() {
pref.begin("NTP");
pref.clear();
pref.putString("ntpServer", this->ntpServer);
pref.putString("posixZone", this->posixZone);
pref.end();
struct tm dt;
configTime(0, 0, this->ntpServer);
if(!getLocalTime(&dt)) return false;
setenv("TZ", this->posixZone, 1);
return true;
}
bool NTPSettings::load() {
pref.begin("NTP");
pref.getString("ntpServer", this->ntpServer, sizeof(this->ntpServer));
pref.getString("posixZone", this->posixZone, sizeof(this->posixZone));
pref.end();
return true;
}
void NTPSettings::print() {
Serial.println("NTP Settings ");
Serial.print(this->ntpServer);
Serial.print(" TZ:");
Serial.println(this->posixZone);
}
bool NTPSettings::fromJSON(JsonObject &obj) {
this->parseValueString(obj, "ntpServer", this->ntpServer, sizeof(this->ntpServer));
this->parseValueString(obj, "posixZone", this->posixZone, sizeof(this->posixZone));
return true;
}
bool NTPSettings::toJSON(JsonObject &obj) {
obj["ntpServer"] = this->ntpServer;
obj["posixZone"] = this->posixZone;
return true;
}
bool NTPSettings::apply() {
struct tm dt;
configTime(0, 0, this->ntpServer);
if(!getLocalTime(&dt)) return false;
setenv("TZ", this->posixZone, 1);
return true;
}
IPSettings::IPSettings() {}
bool IPSettings::begin() {
this->load();
return true;
}
bool IPSettings::fromJSON(JsonObject &obj) {
if(obj.containsKey("dhcp")) this->dhcp = obj["dhcp"];
this->parseIPAddress(obj, "ip", &this->ip);
this->parseIPAddress(obj, "gateway", &this->gateway);
this->parseIPAddress(obj, "subnet", &this->subnet);
this->parseIPAddress(obj, "dns1", &this->dns1);
this->parseIPAddress(obj, "dns2", &this->dns2);
return true;
}
bool IPSettings::toJSON(JsonObject &obj) {
IPAddress ipEmpty(0,0,0,0);
obj["dhcp"] = this->dhcp;
obj["ip"] = this->ip == ipEmpty ? "" : this->ip.toString();
obj["gateway"] = this->gateway == ipEmpty ? "" : this->gateway.toString();
obj["subnet"] = this->subnet == ipEmpty ? "" : this->subnet.toString();
obj["dns1"] = this->dns1 == ipEmpty ? "" : this->dns1.toString();
obj["dns2"] = this->dns2 == ipEmpty ? "" : this->dns2.toString();
return true;
}
bool IPSettings::save() {
pref.begin("IP");
pref.clear();
pref.putBool("dhcp", this->dhcp);
pref.putString("ip", this->ip.toString());
pref.putString("gateway", this->gateway.toString());
pref.putString("subnet", this->subnet.toString());
pref.putString("dns1", this->dns1.toString());
pref.putString("dns2", this->dns2.toString());
pref.end();
return true;
}
bool IPSettings::load() {
pref.begin("IP");
this->dhcp = pref.getBool("dhcp", true);
char buff[16];
if(pref.isKey("ip")) {
pref.getString("ip", buff, sizeof(buff));
this->ip.fromString(buff);
}
if(pref.isKey("gateway")) {
pref.getString("gateway", buff, sizeof(buff));
this->gateway.fromString(buff);
}
if(pref.isKey("subnet")) {
pref.getString("subnet", buff, sizeof(buff));
this->subnet.fromString(buff);
}
if(pref.isKey("dns1")) {
pref.getString("dns1", buff, sizeof(buff));
this->dns1.fromString(buff);
}
if(pref.isKey("dns2")) {
pref.getString("dns2", buff, sizeof(buff));
this->dns2.fromString(buff);
}
Serial.printf("Preference IP Free Entries: %d\n", pref.freeEntries());
pref.end();
return true;
}
bool SecuritySettings::begin() {
this->load();
return true;
}
bool SecuritySettings::fromJSON(JsonObject &obj) {
if(obj.containsKey("type")) this->type = static_cast<security_types>(obj["type"].as<uint8_t>());
this->parseValueString(obj, "username", this->username, sizeof(this->username));
this->parseValueString(obj, "password", this->password, sizeof(this->password));
this->parseValueString(obj, "pin", this->pin, sizeof(this->pin));
if(obj.containsKey("permissions")) this->permissions = obj["permissions"];
return true;
}
bool SecuritySettings::toJSON(JsonObject &obj) {
IPAddress ipEmpty(0,0,0,0);
obj["type"] = static_cast<uint8_t>(this->type);
obj["username"] = this->username;
obj["password"] = this->password;
obj["pin"] = this->pin;
obj["permissions"] = this->permissions;
return true;
}
bool SecuritySettings::save() {
pref.begin("SEC");
pref.clear();
pref.putChar("type", static_cast<uint8_t>(this->type));
pref.putString("username", this->username);
pref.putString("password", this->password);
pref.putString("pin", this->pin);
pref.putChar("permissions", this->permissions);
pref.end();
return true;
}
bool SecuritySettings::load() {
pref.begin("SEC");
this->type = static_cast<security_types>(pref.getChar("type", 0));
if(pref.isKey("username")) pref.getString("username", this->username, sizeof(this->username));
if(pref.isKey("password")) pref.getString("password", this->password, sizeof(this->password));
if(pref.isKey("pin")) pref.getString("pin", this->pin, sizeof(this->pin));
if(pref.isKey("permissions")) this->permissions = pref.getChar("permissions", this->permissions);
pref.end();
return true;
}
void SecuritySettings::print() {
Serial.print("SECURITY Type:");
Serial.print(static_cast<uint8_t>(this->type));
Serial.print(" Username:[");
Serial.print(this->username);
Serial.print("] Password:[");
Serial.print(this->password);
Serial.print("] Pin:[");
Serial.print(this->pin);
Serial.print("] Permissions:");
Serial.println(this->permissions);
}
WifiSettings::WifiSettings() {}
bool WifiSettings::begin() {
this->load();
return true;
}
bool WifiSettings::fromJSON(JsonObject &obj) {
this->parseValueString(obj, "ssid", this->ssid, sizeof(this->ssid));
this->parseValueString(obj, "passphrase", this->passphrase, sizeof(this->passphrase));
return true;
}
bool WifiSettings::toJSON(JsonObject &obj) {
obj["ssid"] = this->ssid;
obj["passphrase"] = this->passphrase;
return true;
}
bool WifiSettings::save() {
pref.begin("WIFI");
pref.clear();
pref.putString("ssid", this->ssid);
pref.putString("passphrase", this->passphrase);
pref.end();
return true;
}
bool WifiSettings::load() {
pref.begin("WIFI");
pref.getString("ssid", this->ssid, sizeof(this->ssid));
pref.getString("passphrase", this->passphrase, sizeof(this->passphrase));
this->ssid[sizeof(this->ssid) - 1] = '\0';
this->passphrase[sizeof(this->passphrase) - 1] = '\0';
pref.end();
return true;
}
String WifiSettings::mapEncryptionType(int type) {
switch(type) {
case WIFI_AUTH_OPEN:
return "Open";
case WIFI_AUTH_WEP:
return "WEP";
case WIFI_AUTH_WPA_PSK:
return "WPA/PSK";
case WIFI_AUTH_WPA2_PSK:
return "WPA2/PSK";
case WIFI_AUTH_WPA_WPA2_PSK:
return "WPA/WPA2/PSK";
case WIFI_AUTH_WPA2_ENTERPRISE:
return "WPA/Enterprise";
}
return "Unknown";
}
void WifiSettings::print() {
Serial.println("WIFI Settings");
Serial.print(" SSID: [");
Serial.print(this->ssid);
Serial.print("] PassPhrase: [");
Serial.print(this->passphrase);
Serial.println("]");
}
void WifiSettings::printNetworks() {
int n = WiFi.scanNetworks(false, true);
Serial.print("Scanned ");
Serial.print(n);
Serial.println(" Networks...");
String network;
for(int i = 0; i < n; i++) {
if(WiFi.SSID(i).compareTo(this->ssid) == 0) Serial.print("*");
else Serial.print(" ");
Serial.print(i);
Serial.print(": ");
Serial.print(WiFi.SSID(i));
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print("dBm) CH:");
Serial.print(WiFi.channel(i));
Serial.print(" MAC:");
Serial.print(WiFi.BSSIDstr(i));
Serial.println();
}
}
bool WifiSettings::ssidExists(const char *ssid) {
int n = WiFi.scanNetworks(false, true);
for(int i = 0; i < n; i++) {
if(WiFi.SSID(i).compareTo(ssid) == 0) return true;
}
return false;
}
EthernetSettings::EthernetSettings() {}
bool EthernetSettings::begin() {
this->load();
return true;
}
bool EthernetSettings::fromJSON(JsonObject &obj) {
if(obj.containsKey("boardType")) this->boardType = obj["boardType"];
if(obj.containsKey("phyAddress")) this->phyAddress = obj["phyAddress"];
if(obj.containsKey("CLKMode")) this->CLKMode = static_cast<eth_clock_mode_t>(obj["CLKMode"]);
if(obj.containsKey("phyType")) this->phyType = static_cast<eth_phy_type_t>(obj["phyType"]);
if(obj.containsKey("PWRPin")) this->PWRPin = obj["PWRPin"];
if(obj.containsKey("MDCPin")) this->MDCPin = obj["MDCPin"];
if(obj.containsKey("MDIOPin")) this->MDIOPin = obj["MDIOPin"];
return true;
}
bool EthernetSettings::toJSON(JsonObject &obj) {
obj["boardType"] = this->boardType;
obj["phyAddress"] = this->phyAddress;
obj["CLKMode"] = static_cast<uint8_t>(this->CLKMode);
obj["phyType"] = static_cast<uint8_t>(this->phyType);
obj["PWRPin"] = this->PWRPin;
obj["MDCPin"] = this->MDCPin;
obj["MDIOPin"] = this->MDIOPin;
return true;
}
bool EthernetSettings::save() {
pref.begin("ETH");
pref.clear();
pref.putChar("boardType", this->boardType);
pref.putChar("phyAddress", this->phyAddress);
pref.putChar("phyType", static_cast<uint8_t>(this->phyType));
pref.putChar("CLKMode", static_cast<uint8_t>(this->CLKMode));
pref.putChar("PWRPin", this->PWRPin);
pref.putChar("MDCPin", this->MDCPin);
pref.putChar("MDIOPin", this->MDIOPin);
pref.end();
return true;
}
bool EthernetSettings::load() {
pref.begin("ETH");
this->boardType = pref.getChar("boardType", this->boardType);
this->phyType = static_cast<eth_phy_type_t>(pref.getChar("phyType", ETH_PHY_LAN8720));
this->CLKMode = static_cast<eth_clock_mode_t>(pref.getChar("CLKMode", ETH_CLOCK_GPIO0_IN));
this->phyAddress = pref.getChar("phyAddress", this->phyAddress);
this->PWRPin = pref.getChar("PWRPin", this->PWRPin);
this->MDCPin = pref.getChar("MDCPin", this->MDCPin);
this->MDIOPin = pref.getChar("MDIOPin", this->MDIOPin);
pref.end();
return true;
}
void EthernetSettings::print() {
Serial.println("Ethernet Settings");
Serial.printf("Board:%d PHYType:%d CLK:%d ADDR:%d PWR:%d MDC:%d MDIO:%d\n", this->boardType, this->phyType, this->CLKMode, this->phyAddress, this->PWRPin, this->MDCPin, this->MDIOPin);
}