More work on webserver

This commit is contained in:
2026-03-07 19:32:24 +01:00
parent 90d5261670
commit 99668574b3
9 changed files with 119 additions and 80 deletions

View File

@@ -220,6 +220,13 @@ void Config::dump() {
LOGI(TAG, "====================================");
}
void Config::clear() {
LOGI(TAG, "Clearing NVS volume: %s", PREF_NAME);
prefs.begin(PREF_NAME, false);
prefs.clear();
prefs.end();
}
template<typename T>
T Config::get(const char* key) const {
return std::get<T>(values.at(key));

View File

@@ -623,16 +623,18 @@ void send_sensor_brightness(uint16_t value) {
// device instance 8bits
// brightness 0-100%, resolution 0.1% 16bits
// 3 bytes reserved
uint16_t n2kvalue = value * 1000UL / 4095; // 0..100%, resolution 0.1
tN2kMsg N2kMsg;
N2kMsg.SetPGN(65280); // proprietary PGN
N2kMsg.Priority = 6;
// 11bits manuf.-code, 2bits reserved (1), 3bits industry group
N2kMsg.Add2ByteUInt((N2K_MANUFACTURERCODE & 0x7FF) | (0x03 << 11) | ((N2K_INDUSTRYGROUP & 0x7) << 13));
N2kMsg.AddByte(0); // instance not yet used now
N2kMsg.Add2ByteUInt(value * 1000UL / 4095); // resolution 0.1
N2kMsg.Add2ByteUInt(n2kvalue);
N2kMsg.AddByte(0xFF); //reserved bytes
N2kMsg.AddByte(0xFF);
N2kMsg.AddByte(0xFF);
LOGI(TAG, "Sending LDR value=%d (%d)", n2kvalue, value);
NMEA2000.SendMsg(N2kMsg);
}
@@ -772,10 +774,9 @@ void loop() {
send_sensor_temphum(temp + 273.15, hum);
#ifdef HARDWARE_V2
// Send brightness to NMEA2000 (proprietary)
int ldrval = analogRead(LDR);
LOGI(TAG, "LDR value =%d", ldrval);
// TODO send brightness to NMEA2000
//send_sensor_brightness(ldrval);
send_sensor_brightness(ldrval);
#endif
}

View File

@@ -76,6 +76,18 @@ String uptime_with_unit() {
return String(uptime) + " " + uptime_unit;
}
bool check_pass(String hash) {
if (! config.getBool("useAdminPass")) {
return true;
}
char salt[9]; // use to easy get upper case hex
sprintf(salt, "%08X", apiToken + (millis()/1000UL & ~0x7UL));
String passhash = get_sha256(String(salt) + config.getString("adminPassword"));
LOGD(TAG, "check hash: %s", hash.c_str());
LOGD(TAG, "check against: %s", passhash.c_str());
return hash == passhash;
}
void webserver_init() {
// Route for root / web page
@@ -103,16 +115,23 @@ void webserver_init() {
server.on("/api/checkpass", HTTP_GET, [](AsyncWebServerRequest *request) {
// hash has to be in sha256 format
AsyncResponseStream *response = request->beginResponseStream("application/json");
LOGD(TAG, "checkpass called");
String hash = request->arg("hash");
StaticJsonDocument<100> doc;
String passhash = get_sha256(config.getString("adminPassword"));
LOGD(TAG, "check hash: %s", hash.c_str());
LOGD(TAG, "check against: %s", passhash.c_str());
doc["status"] = hash == passhash ? "OK" : "FAILED";
String out;
serializeJson(doc, out);
request->send(200, "application/json", out);
//StaticJsonDocument<100> doc;
//char salt[9];
//sprintf(salt, "%08X", apiToken + (millis()/1000UL & ~0x7UL));
//String passhash = get_sha256(String(salt) + config.getString("adminPassword"));
//LOGD(TAG, "check hash: %s", hash.c_str());
//LOGD(TAG, "check against: %s", passhash.c_str());
//doc["status"] = check_pass(hash) ? "OK" : "FAILED";
//String out;
//serializeJson(doc, out);
//request->send(200, "application/json", out);
response->print(R"({"status":)");
response->print(check_pass(hash) ? R"("OK")" : R"("FAILED")");
response->print("}");
request->send(response);
});
server.on("/api/config", HTTP_GET, [](AsyncWebServerRequest *request) {
@@ -125,12 +144,10 @@ void webserver_init() {
doc["instDesc2"] = config.getString("instDesc2");
doc["logLevel"] = loglevel;
doc["version"] = VERSION;
doc["AdminPassword"] = "********";
doc["useAdminPass"] = config.getBool("useAdminPass") ? "true" : "false";
doc["apEnable"] = config.getBool("apEnable") ? "true" : "false";
doc["apIp"] = config.getString("apIp");
doc["apMask"] = config.getString("apMask");
doc["apPassword"] = "********";
doc["stopApTime"] = config.getShort("stopApTime");
doc["apHidden"] = config.getBool("apHidden") ? "true" : "false";
doc["cpuSpeed"] = config.getShort("cpuSpeed");
@@ -160,31 +177,55 @@ void webserver_init() {
doc["n2kDestC"] = config.getString("n2kDestC");
doc["switchBankC"] = config.getByte("switchBankC");
doc["envInterval"] = config.getShort("envInterval");
// TODO needed? Perhaps because entry fields are created by this list
doc["AdminPassword"] = "********";
doc["apPassword"] = "********";
String out;
serializeJson(doc, out);
request->send(200, "application/json", out);
});
server.on("/api/reset", HTTP_GET, [](AsyncWebServerRequest *request) {
LOGD(TAG, "reset called");
StaticJsonDocument<100> doc;
AsyncResponseStream *response = request->beginResponseStream("application/json");
String hash = request->arg("hash");
response->print(R"([{"status":)");
if (check_pass(hash)) {
LOGD(TAG, "reset called");
response->print(R"("OK")");
response->print("}]");
ledcWrite(LEDC_RGBLED_B, 0); // blue config light off
led_blink(LEDC_RGBLED_G, 3, 4095, 500);
esp_rom_uart_tx_wait_idle(0);
ESP.restart();
}
LOGD(TAG, "reset failed: wrong password");
response->print(R"("FAILED")");
response->print("}]");
/*StaticJsonDocument<100> doc;
doc["status"] = "OK";
String out;
serializeJson(doc, out);
request->send(200, "application/json", out);
ledcWrite(LEDC_RGBLED_B, 0); // blue config light off
led_blink(LEDC_RGBLED_G, 3, 4095, 500);
esp_rom_uart_tx_wait_idle(0);
ESP.restart();
request->send(200, "application/json", out); */
});
server.on("/api/resetconfig", HTTP_GET, [](AsyncWebServerRequest *request) {
AsyncResponseStream *response = request->beginResponseStream("application/json");
String hash = request->arg("hash");
if (check_pass(hash)) {
LOGD(TAG, "resetconfig: checkpass successful");
} else {
LOGD(TAG, "resetconfig: checkpass failed");
}
LOGD(TAG, "resetconfig called");
StaticJsonDocument<100> doc;
doc["status"] = "FAILED";
String out;
serializeJson(doc, out);
request->send(200, "application/json", out);
// config.clear();
response->print("{");
response->print(R"DELIM({"status": "FAILED"})DELIM");
response->print("}");
request->send(response);
});
server.on("/api/status", HTTP_GET, [](AsyncWebServerRequest *request) {
@@ -229,6 +270,10 @@ void webserver_init() {
sprintf(salt, "%08X", apiToken + (millis()/1000UL & ~0x7UL));
doc["salt"] = salt;
// security warnings
doc["warnAdminPass"] = config.getString("AdminPassword") == ADMIN_PASS ? "true" : "false";
doc["warnApPass"] = config.getString("apPassword") == WIFI_PASS ? "true" : "false";
doc["status"] = "OK";
String out;
serializeJson(doc, out);