Merge branch 'master' into use11b

This commit is contained in:
Gunnar Skjold
2023-09-23 14:03:55 +02:00
committed by GitHub
24 changed files with 450 additions and 180 deletions

View File

@@ -22,7 +22,7 @@ public:
void apply(AmsData& other);
unsigned long getLastUpdateMillis();
uint64_t getLastUpdateMillis();
time_t getPackageTimestamp();
@@ -73,8 +73,8 @@ public:
void setLastError(int8_t);
protected:
unsigned long lastUpdateMillis = 0;
unsigned long lastList2 = 0;
uint64_t lastUpdateMillis = 0;
uint64_t lastList2 = 0;
uint8_t listType = 0, meterType = AmsTypeUnknown;
time_t packageTimestamp = 0;
String listId = "", meterId = "", meterModel = "";

View File

@@ -82,7 +82,7 @@ void AmsData::apply(AmsData& other) {
this->activeExportPower = other.getActiveExportPower();
}
unsigned long AmsData::getLastUpdateMillis() {
uint64_t AmsData::getLastUpdateMillis() {
return this->lastUpdateMillis;
}

View File

@@ -547,7 +547,7 @@ uint8_t AmsDataStorage::getDayAccuracy() {
void AmsDataStorage::setDayAccuracy(uint8_t accuracy) {
if(day.accuracy != accuracy) {
uint16_t multiplier = pow(10, day.accuracy)/pow(10, accuracy);
double multiplier = pow(10, day.accuracy)/pow(10, accuracy);
for(uint8_t i = 0; i < 24; i++) {
day.hImport[i] = day.hImport[i] * multiplier;
day.hExport[i] = day.hExport[i] * multiplier;
@@ -562,7 +562,7 @@ uint8_t AmsDataStorage::getMonthAccuracy() {
void AmsDataStorage::setMonthAccuracy(uint8_t accuracy) {
if(month.accuracy != accuracy) {
uint16_t multiplier = pow(10, month.accuracy)/pow(10, accuracy);
double multiplier = pow(10, month.accuracy)/pow(10, accuracy);
for(uint8_t i = 0; i < 31; i++) {
month.dImport[i] = month.dImport[i] * multiplier;
month.dExport[i] = month.dExport[i] * multiplier;

View File

@@ -56,10 +56,25 @@ struct EnergyAccountingData2 {
uint16_t costLastMonth;
};
struct EnergyAccountingRealtimeData {
uint8_t magic;
uint8_t currentHour;
uint8_t currentDay;
uint8_t currentThresholdIdx;
float use;
float costHour;
float costDay;
float produce;
float incomeHour;
float incomeDay;
unsigned long lastImportUpdateMillis;
unsigned long lastExportUpdateMillis;
};
class EnergyAccounting {
public:
EnergyAccounting(RemoteDebug*);
EnergyAccounting(RemoteDebug*, EnergyAccountingRealtimeData*);
void setup(AmsDataStorage *ds, EnergyAccountingConfig *config);
void setEapi(EntsoeApi *eapi);
void setTimezone(Timezone*);
@@ -103,16 +118,13 @@ public:
private:
RemoteDebug* debugger = NULL;
unsigned long lastUpdateMillis = 0;
bool init = false, initPrice = false;
AmsDataStorage *ds = NULL;
EntsoeApi *eapi = NULL;
EnergyAccountingConfig *config = NULL;
Timezone *tz = NULL;
uint8_t currentHour = 0, currentDay = 0, currentThresholdIdx = 0;
float use = 0, costHour = 0, costDay = 0;
float produce = 0, incomeHour = 0, incomeDay = 0;
EnergyAccountingData data = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
EnergyAccountingRealtimeData* realtimeData = NULL;
float fixedPrice = 0;
String currency = "";

View File

@@ -3,15 +3,29 @@
#include "AmsStorage.h"
#include "FirmwareVersion.h"
EnergyAccounting::EnergyAccounting(RemoteDebug* debugger) {
EnergyAccounting::EnergyAccounting(RemoteDebug* debugger, EnergyAccountingRealtimeData* rtd) {
data.version = 1;
this->debugger = debugger;
if(rtd->magic != 0x6A) {
rtd->magic = 0x6A;
rtd->currentHour = 0;
rtd->currentDay = 0;
rtd->currentThresholdIdx = 0;
rtd->use = 0;
rtd->costHour = 0;
rtd->costDay = 0;
rtd->produce = 0;
rtd->incomeHour = 0;
rtd->incomeDay = 0;
rtd->lastImportUpdateMillis = 0;
rtd->lastExportUpdateMillis = 0;
}
this->realtimeData = rtd;
}
void EnergyAccounting::setup(AmsDataStorage *ds, EnergyAccountingConfig *config) {
this->ds = ds;
this->config = config;
this->currentThresholdIdx = 0;
}
void EnergyAccounting::setEapi(EntsoeApi *eapi) {
@@ -44,8 +58,8 @@ bool EnergyAccounting::update(AmsData* amsData) {
breakTime(tz->toLocal(now), local);
if(!init) {
currentHour = local.Hour;
currentDay = local.Day;
this->realtimeData->currentHour = local.Hour;
this->realtimeData->currentDay = local.Day;
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf_P(PSTR("(EnergyAccounting) Initializing data at %lu\n"), (int32_t) now);
if(!load()) {
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf_P(PSTR("(EnergyAccounting) Unable to load existing data\n"));
@@ -75,7 +89,7 @@ bool EnergyAccounting::update(AmsData* amsData) {
calcDayCost();
}
if(local.Hour != currentHour && (amsData->getListType() >= 3 || local.Minute == 1)) {
if(local.Hour != this->realtimeData->currentHour && (amsData->getListType() >= 3 || local.Minute == 1)) {
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf_P(PSTR("(EnergyAccounting) New local hour %d\n"), local.Hour);
tmElements_t oneHrAgo, oneHrAgoLocal;
@@ -85,28 +99,28 @@ bool EnergyAccounting::update(AmsData* amsData) {
breakTime(tz->toLocal(now-3600), oneHrAgoLocal);
ret |= updateMax(val, oneHrAgoLocal.Day);
currentHour = local.Hour; // Need to be defined here so that day cost is correctly calculated
this->realtimeData->currentHour = local.Hour; // Need to be defined here so that day cost is correctly calculated
if(local.Hour > 0) {
calcDayCost();
}
use = 0;
produce = 0;
costHour = 0;
incomeHour = 0;
this->realtimeData->use = 0;
this->realtimeData->produce = 0;
this->realtimeData->costHour = 0;
this->realtimeData->incomeHour = 0;
uint8_t prevDay = currentDay;
if(local.Day != currentDay) {
uint8_t prevDay = this->realtimeData->currentDay;
if(local.Day != this->realtimeData->currentDay) {
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf_P(PSTR("(EnergyAccounting) New day %d\n"), local.Day);
data.costYesterday = costDay * 100;
data.costThisMonth += costDay * 100;
costDay = 0;
data.costYesterday = this->realtimeData->costDay * 100;
data.costThisMonth += this->realtimeData->costDay * 100;
this->realtimeData->costDay = 0;
data.incomeYesterday = incomeDay * 100;
data.incomeThisMonth += incomeDay * 100;
incomeDay = 0;
data.incomeYesterday = this->realtimeData->incomeDay * 100;
data.incomeThisMonth += this->realtimeData->incomeDay * 100;
this->realtimeData->incomeDay = 0;
currentDay = local.Day;
this->realtimeData->currentDay = local.Day;
ret = true;
}
@@ -137,40 +151,47 @@ bool EnergyAccounting::update(AmsData* amsData) {
data.lastMonthAccuracy = accuracy;
data.month = local.Month;
currentThresholdIdx = 0;
this->realtimeData->currentThresholdIdx = 0;
ret = true;
}
}
unsigned long ms = this->lastUpdateMillis > amsData->getLastUpdateMillis() ? 0 : amsData->getLastUpdateMillis() - this->lastUpdateMillis;
float kwhi = (amsData->getActiveImportPower() * (((float) ms) / 3600000.0)) / 1000.0;
float kwhe = (amsData->getActiveExportPower() * (((float) ms) / 3600000.0)) / 1000.0;
lastUpdateMillis = amsData->getLastUpdateMillis();
if(kwhi > 0) {
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf_P(PSTR("(EnergyAccounting) Adding %.4f kWh import\n"), kwhi);
use += kwhi;
if(price != ENTSOE_NO_VALUE) {
float cost = price * kwhi;
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf_P(PSTR("(EnergyAccounting) and %.4f %s\n"), cost / 100.0, currency.c_str());
costHour += cost;
costDay += cost;
if(this->realtimeData->lastImportUpdateMillis < amsData->getLastUpdateMillis()) {
unsigned long ms = amsData->getLastUpdateMillis() - this->realtimeData->lastImportUpdateMillis;
float kwhi = (amsData->getActiveImportPower() * (((float) ms) / 3600000.0)) / 1000.0;
if(kwhi > 0) {
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf_P(PSTR("(EnergyAccounting) Adding %.4f kWh import\n"), kwhi);
this->realtimeData->use += kwhi;
if(price != ENTSOE_NO_VALUE) {
float cost = price * kwhi;
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf_P(PSTR("(EnergyAccounting) and %.4f %s\n"), cost / 100.0, currency.c_str());
this->realtimeData->costHour += cost;
this->realtimeData->costDay += cost;
}
}
this->realtimeData->lastImportUpdateMillis = amsData->getLastUpdateMillis();
}
if(kwhe > 0) {
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf_P(PSTR("(EnergyAccounting) Adding %.4f kWh export\n"), kwhe);
produce += kwhe;
if(price != ENTSOE_NO_VALUE) {
float income = price * kwhe;
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf_P(PSTR("(EnergyAccounting) and %.4f %s\n"), income / 100.0, currency.c_str());
incomeHour += income;
incomeDay += income;
if(amsData->getListType() > 1 && this->realtimeData->lastExportUpdateMillis < amsData->getLastUpdateMillis()) {
unsigned long ms = amsData->getLastUpdateMillis() - this->realtimeData->lastExportUpdateMillis;
float kwhe = (amsData->getActiveExportPower() * (((float) ms) / 3600000.0)) / 1000.0;
if(kwhe > 0) {
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf_P(PSTR("(EnergyAccounting) Adding %.4f kWh export\n"), kwhe);
this->realtimeData->produce += kwhe;
if(price != ENTSOE_NO_VALUE) {
float income = price * kwhe;
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf_P(PSTR("(EnergyAccounting) and %.4f %s\n"), income / 100.0, currency.c_str());
this->realtimeData->incomeHour += income;
this->realtimeData->incomeDay += income;
}
}
this->realtimeData-> lastExportUpdateMillis = amsData->getLastUpdateMillis();
}
if(config != NULL) {
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf_P(PSTR("(EnergyAccounting) calculating threshold, currently at %d\n"), currentThresholdIdx);
while(getMonthMax() > config->thresholds[currentThresholdIdx] && currentThresholdIdx < 10) currentThresholdIdx++;
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf_P(PSTR("(EnergyAccounting) new threshold %d\n"), currentThresholdIdx);
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf_P(PSTR("(EnergyAccounting) calculating threshold, currently at %d\n"), this->realtimeData->currentThresholdIdx);
while(getMonthMax() > config->thresholds[this->realtimeData->currentThresholdIdx] && this->realtimeData->currentThresholdIdx < 10) this->realtimeData->currentThresholdIdx++;
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf_P(PSTR("(EnergyAccounting) new threshold %d\n"), this->realtimeData->currentThresholdIdx);
}
return ret;
@@ -184,25 +205,25 @@ void EnergyAccounting::calcDayCost() {
if(getPriceForHour(0) != ENTSOE_NO_VALUE) {
if(initPrice) {
costDay = 0;
incomeDay = 0;
this->realtimeData->costDay = 0;
this->realtimeData->incomeDay = 0;
}
for(uint8_t i = 0; i < currentHour; i++) {
for(uint8_t i = 0; i < this->realtimeData->currentHour; i++) {
float price = getPriceForHour(i - local.Hour);
if(price == ENTSOE_NO_VALUE) break;
breakTime(now - ((local.Hour - i) * 3600), utc);
int16_t wh = ds->getHourImport(utc.Hour);
costDay += price * (wh / 1000.0);
this->realtimeData->costDay += price * (wh / 1000.0);
wh = ds->getHourExport(utc.Hour);
incomeDay += price * (wh / 1000.0);
this->realtimeData->incomeDay += price * (wh / 1000.0);
}
initPrice = true;
}
}
float EnergyAccounting::getUseThisHour() {
return use;
return this->realtimeData->use;
}
float EnergyAccounting::getUseToday() {
@@ -212,7 +233,7 @@ float EnergyAccounting::getUseToday() {
if(now < FirmwareVersion::BuildEpoch) return 0.0;
tmElements_t utc, local;
breakTime(tz->toLocal(now), local);
for(uint8_t i = 0; i < currentHour; i++) {
for(uint8_t i = 0; i < this->realtimeData->currentHour; i++) {
breakTime(now - ((local.Hour - i) * 3600), utc);
ret += ds->getHourImport(utc.Hour) / 1000.0;
}
@@ -223,7 +244,7 @@ float EnergyAccounting::getUseThisMonth() {
time_t now = time(nullptr);
if(now < FirmwareVersion::BuildEpoch) return 0.0;
float ret = 0;
for(uint8_t i = 1; i < currentDay; i++) {
for(uint8_t i = 1; i < this->realtimeData->currentDay; i++) {
ret += ds->getDayImport(i) / 1000.0;
}
return ret + getUseToday();
@@ -234,7 +255,7 @@ float EnergyAccounting::getUseLastMonth() {
}
float EnergyAccounting::getProducedThisHour() {
return produce;
return this->realtimeData->produce;
}
float EnergyAccounting::getProducedToday() {
@@ -244,7 +265,7 @@ float EnergyAccounting::getProducedToday() {
if(now < FirmwareVersion::BuildEpoch) return 0.0;
tmElements_t utc, local;
breakTime(tz->toLocal(now), local);
for(uint8_t i = 0; i < currentHour; i++) {
for(uint8_t i = 0; i < this->realtimeData->currentHour; i++) {
breakTime(now - ((local.Hour - i) * 3600), utc);
ret += ds->getHourExport(utc.Hour) / 1000.0;
}
@@ -255,7 +276,7 @@ float EnergyAccounting::getProducedThisMonth() {
time_t now = time(nullptr);
if(now < FirmwareVersion::BuildEpoch) return 0.0;
float ret = 0;
for(uint8_t i = 1; i < currentDay; i++) {
for(uint8_t i = 1; i < this->realtimeData->currentDay; i++) {
ret += ds->getDayExport(i) / 1000.0;
}
return ret + getProducedToday();
@@ -266,11 +287,11 @@ float EnergyAccounting::getProducedLastMonth() {
}
float EnergyAccounting::getCostThisHour() {
return costHour;
return this->realtimeData->costHour;
}
float EnergyAccounting::getCostToday() {
return costDay;
return this->realtimeData->costDay;
}
float EnergyAccounting::getCostYesterday() {
@@ -286,11 +307,11 @@ float EnergyAccounting::getCostLastMonth() {
}
float EnergyAccounting::getIncomeThisHour() {
return incomeHour;
return this->realtimeData->incomeHour;
}
float EnergyAccounting::getIncomeToday() {
return incomeDay;
return this->realtimeData->incomeDay;
}
float EnergyAccounting::getIncomeYesterday() {
@@ -308,7 +329,7 @@ float EnergyAccounting::getIncomeLastMonth() {
uint8_t EnergyAccounting::getCurrentThreshold() {
if(config == NULL)
return 0;
return config->thresholds[currentThresholdIdx];
return config->thresholds[this->realtimeData->currentThresholdIdx];
}
float EnergyAccounting::getMonthMax() {
@@ -521,11 +542,11 @@ bool EnergyAccounting::updateMax(uint16_t val, uint8_t day) {
return false;
}
}
uint16_t test = 0;
uint16_t test = val;
uint8_t idx = 255;
for(uint8_t i = 0; i < 5; i++) {
if(val > data.peaks[i].value) {
if(test < data.peaks[i].value) {
if(test > data.peaks[i].value) {
test = data.peaks[i].value;
idx = i;
}

View File

@@ -301,14 +301,14 @@ float EntsoeApi::getCurrencyMultiplier(const char* from, const char* to, time_t
}
PricesContainer* EntsoeApi::fetchPrices(time_t t) {
tmElements_t tm;
breakTime(t, tm);
if(strlen(getToken()) > 0) {
time_t e1 = t - (tm.Hour * 3600) - (tm.Minute * 60) - tm.Second; // UTC midnight
tmElements_t tm;
breakTime(tz->toLocal(t), tm);
time_t e1 = t - (tm.Hour * 3600) - (tm.Minute * 60) - tm.Second; // Local midnight
time_t e2 = e1 + SECS_PER_DAY;
tmElements_t d1, d2;
breakTime(tz->toUTC(e1), d1); // To get day and hour for CET/CEST at UTC midnight
breakTime(tz->toUTC(e2), d2);
breakTime(e1, d1);
breakTime(e2, d2);
snprintf_P(buf, BufferSize, PSTR("https://web-api.tp.entsoe.eu/api?securityToken=%s&documentType=A44&periodStart=%04d%02d%02d%02d%02d&periodEnd=%04d%02d%02d%02d%02d&in_Domain=%s&out_Domain=%s"),
getToken(),
@@ -333,6 +333,9 @@ PricesContainer* EntsoeApi::fetchPrices(time_t t) {
return NULL;
}
} else if(hub) {
tmElements_t tm;
breakTime(tz->toLocal(t), tm);
String data;
snprintf_P(buf, BufferSize, PSTR("http://hub.amsleser.no/hub/price/%s/%d/%d/%d?currency=%s"),
config->area,

View File

@@ -444,7 +444,7 @@ void HomeAssistantMqttHandler::publishRealtimeSensors(EnergyAccounting* ea, Ents
char name[strlen(RealtimePeakSensor.name)];
snprintf(name, strlen(RealtimePeakSensor.name), RealtimePeakSensor.name, i+1);
char path[strlen(RealtimePeakSensor.path)];
snprintf(path, strlen(RealtimePeakSensor.path), RealtimePeakSensor.path, i+1);
snprintf(path, strlen(RealtimePeakSensor.path), RealtimePeakSensor.path, i);
HomeAssistantSensor sensor = {
name,
RealtimePeakSensor.topic,
@@ -524,7 +524,7 @@ void HomeAssistantMqttHandler::publishPriceSensors(EntsoeApi* eapi) {
path,
uom.c_str(),
PriceSensor.devcl,
PriceSensor.stacl
i == 0 ? "total" : PriceSensor.stacl
};
publishSensor(sensor);
prInit[i] = true;

View File

@@ -267,7 +267,7 @@ bool RawMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccountin
return false;
mqtt->publish(topic + "/id", WiFi.macAddress(), true, 0);
mqtt->publish(topic + "/uptime", String((unsigned long) millis64()/1000));
mqtt->publish(topic + "/uptime", String((uint32_t) (millis64()/1000)));
float vcc = hw->getVcc();
if(vcc > 0) {
mqtt->publish(topic + "/vcc", String(vcc, 2));

View File

@@ -9,7 +9,7 @@
$:{
showFull = Math.abs(new Date().getTime()-timestamp.getTime()) < 300000;
if(!isNaN(offset))
addHours(timestamp, offset - ((timestamp.getHours() - timestamp.getUTCHours())%24));
addHours(timestamp, offset - ((24 + timestamp.getHours() - timestamp.getUTCHours())%24));
}
</script>

View File

@@ -17,7 +17,7 @@
min = max = 0;
let cur = addHours(new Date(), -24);
let currentHour = new Date().getUTCHours();
addHours(cur, sysinfo.clock_offset - ((cur.getHours() - cur.getUTCHours())%24));
addHours(cur, sysinfo.clock_offset - ((24 + cur.getHours() - cur.getUTCHours())%24));
for(i = currentHour; i<24; i++) {
let imp = json["i"+zeropad(i)];
let exp = json["e"+zeropad(i)];
@@ -63,24 +63,27 @@
addHours(cur, 1);
};
let boundary = Math.ceil(Math.max(min, max));
max = boundary;
min = min == 0 ? 0 : boundary*-1;
min *= -1;
let range = Math.max(max, Math.abs(min));
if(min < 0) {
let yTickDistDown = min/4;
for(i = 1; i < 5; i++) {
min = Math.min((range/4)*-1, min);
let yTicksNum = Math.ceil((Math.abs(min)/range) * 4);
let yTickDistDown = min/yTicksNum;
for(i = 1; i < yTicksNum+1; i++) {
let val = (yTickDistDown*i);
yTicks.push({
value: val,
label: (val/10).toFixed(1)
});
}
console.log(yTicksNum);
}
let yTickDistUp = max/4;
for(i = 0; i < 5; i++) {
max = Math.max((range/4), max);
let xTicksNum = Math.ceil((max/range) * 4);
let yTickDistUp = max/xTicksNum;
for(i = 0; i < xTicksNum+1; i++) {
let val = (yTickDistUp*i);
yTicks.push({
value: val,

View File

@@ -17,8 +17,8 @@
min = max = 0;
let cur = new Date();
let lm = new Date();
addHours(cur, sysinfo.clock_offset - ((cur.getHours() - cur.getUTCHours())%24));
addHours(lm, sysinfo.clock_offset - ((lm.getHours() - lm.getUTCHours())%24));
addHours(cur, sysinfo.clock_offset - ((24 + cur.getHours() - cur.getUTCHours())%24));
addHours(lm, sysinfo.clock_offset - ((24 + lm.getHours() - lm.getUTCHours())%24));
lm.setDate(0);
for(i = cur.getDate(); i<=lm.getDate(); i++) {
@@ -64,14 +64,14 @@
max = Math.max(max, imp);
}
let boundary = Math.ceil(Math.max(min, max)/10)*10;
max = boundary;
min = min == 0 ? 0 : boundary*-1;
min *= -1;
let range = Math.max(max, Math.abs(min));
if(min < 0) {
let yTickDistDown = min/4;
for(i = 0; i < 5; i++) {
min = Math.min((range/4)*-1, min);
let yTicksNum = Math.ceil((Math.abs(min)/range) * 4);
let yTickDistDown = min/yTicksNum;
for(i = 1; i < yTicksNum+1; i++) {
let val = (yTickDistDown*i);
yTicks.push({
value: val,
@@ -80,8 +80,10 @@
}
}
let yTickDistUp = max/4;
for(i = 0; i < 5; i++) {
max = Math.max((range/4), max);
let xTicksNum = Math.ceil((max/range) * 4);
let yTickDistUp = max/xTicksNum;
for(i = 0; i < xTicksNum+1; i++) {
let val = (yTickDistUp*i);
yTicks.push({
value: val,

View File

@@ -88,7 +88,7 @@
<div class="cnt">
<strong class="text-sm">Device information</strong>
<div class="my-2">
Chip: {sysinfo.chip}
Chip: {sysinfo.chip} ({sysinfo.cpu}MHz)
</div>
<div class="my-2">
Device: <Link to="/vendor">{boardtype(sysinfo.chip, sysinfo.board)}</Link>

View File

@@ -1,12 +1,15 @@
static const char HEADER_CACHE_CONTROL[] PROGMEM = "Cache-Control";
static const char HEADER_CONTENT_ENCODING[] PROGMEM = "Content-Encoding";
static const char HEADER_PRAGMA[] PROGMEM = "Pragma";
static const char HEADER_EXPIRES[] PROGMEM = "Expires";
static const char HEADER_AUTHENTICATE[] PROGMEM = "WWW-Authenticate";
static const char HEADER_LOCATION[] PROGMEM = "Location";
static const char CACHE_CONTROL_NO_CACHE[] PROGMEM = "no-cache, no-store, must-revalidate";
static const char CONTENT_ENCODING_GZIP[] PROGMEM = "gzip";
static const char CACHE_1HR[] PROGMEM = "public, max-age=3600";
static const char CACHE_1MO[] PROGMEM = "public, max-age=2592000";
static const char CACHE_1MO[] PROGMEM = "public, max-age=2630000";
static const char CACHE_1YR[] PROGMEM = "public, max-age=31536000";
static const char PRAGMA_NO_CACHE[] PROGMEM = "no-cache";
static const char EXPIRES_OFF[] PROGMEM = "-1";
static const char AUTHENTICATE_BASIC[] PROGMEM = "Basic realm=\"Secure Area\"";

View File

@@ -2,6 +2,7 @@
"version": "%s",
"chip": "%s",
"chipId": "%s",
"cpu": %d,
"mac": "%s",
"apmac": "%s",
"board": %d,

View File

@@ -2,6 +2,7 @@ import os
import re
import shutil
import subprocess
import gzip
try:
from css_html_js_minify import html_minify, js_minify, css_minify
@@ -65,16 +66,24 @@ for webroot in ["lib/SvelteUi/app/dist", "lib/SvelteUi/json"]:
content = js_minify(content)
except:
print("WARN: Unable to minify")
content_bytes = content.encode("utf-8")
if filename in ["index.js", "index.css"]:
content_bytes = gzip.compress(content_bytes, compresslevel=9)
content_len = len(content_bytes)
else:
content_len = len(content_bytes)
content_bytes += b"\0"
with open(dstfile, "w") as dst:
dst.write("static const char ")
dst.write(varname)
dst.write("[] PROGMEM = R\"==\"==(")
dst.write(content)
dst.write(")==\"==\";\n")
dst.write("[] PROGMEM = {")
dst.write(", ".join([str(c) for c in content_bytes]))
dst.write("};\n")
dst.write("const int ");
dst.write(varname)
dst.write("_LEN PROGMEM = ");
dst.write(str(len(content)))
dst.write(str(content_len))
dst.write(";");

View File

@@ -35,6 +35,7 @@
#if defined(ESP32)
#include <esp_task_wdt.h>
#include <esp_wifi.h>
#include <esp_clk.h>
#endif
@@ -190,14 +191,14 @@ void AmsWebServer::notFound() {
void AmsWebServer::githubSvg() {
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf_P(PSTR("Serving /github.svg over http...\n"));
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_1HR);
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_1MO);
server.send_P(200, "image/svg+xml", GITHUB_SVG);
}
void AmsWebServer::faviconSvg() {
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf_P(PSTR("Serving /favicon.ico over http...\n"));
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_1HR);
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_1MO);
server.send_P(200, "image/svg+xml", FAVICON_SVG);
}
@@ -239,9 +240,11 @@ void AmsWebServer::sysinfoJson() {
#if defined(ESP8266)
wifi_get_macaddr(STATION_IF, mac);
wifi_get_macaddr(SOFTAP_IF, apmac);
uint32_t cpu_freq = 80;
#elif defined(ESP32)
esp_wifi_get_mac((wifi_interface_t)ESP_IF_WIFI_STA, mac);
esp_wifi_get_mac((wifi_interface_t)ESP_IF_WIFI_AP, apmac);
uint32_t cpu_freq = esp_clk_cpu_freq();
#endif
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
@@ -277,6 +280,7 @@ void AmsWebServer::sysinfoJson() {
"esp8266",
#endif
chipIdStr.c_str(),
cpu_freq / 1000000,
macStr,
apMacStr,
sys.boardType,
@@ -764,9 +768,9 @@ void AmsWebServer::indexCss() {
if(!checkSecurity(2))
return;
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_1MO);
server.setContentLength(INDEX_CSS_LEN);
server.send_P(200, MIME_CSS, INDEX_CSS);
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_1YR);
server.sendHeader(HEADER_CONTENT_ENCODING, CONTENT_ENCODING_GZIP);
server.send_P(200, MIME_CSS, INDEX_CSS, INDEX_CSS_LEN);
}
void AmsWebServer::indexJs() {
@@ -775,8 +779,9 @@ void AmsWebServer::indexJs() {
if(!checkSecurity(2))
return;
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_1MO);
server.send_P(200, MIME_JS, INDEX_JS);
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_1YR);
server.sendHeader(HEADER_CONTENT_ENCODING, CONTENT_ENCODING_GZIP);
server.send_P(200, MIME_JS, INDEX_JS, INDEX_JS_LEN);
}
void AmsWebServer::configurationJson() {
@@ -1005,6 +1010,13 @@ void AmsWebServer::handleSave() {
gpioConfig->ledPin = 15;
gpioConfig->ledInverted = false;
gpioConfig->apPin = 0;
gpioConfig->hanPin = hanPin > 0 ? hanPin : 18;
if(gpioConfig->hanPin != 18) {
gpioConfig->vccPin = 18;
gpioConfig->vccResistorGnd = 45;
gpioConfig->vccResistorVcc = 10;
}
break;
case 50: // Generic ESP32-S2
gpioConfig->hanPin = hanPin > 0 ? hanPin : 18;
break;