This commit is contained in:
MichaelDvP
2024-07-26 18:30:14 +02:00
13 changed files with 87 additions and 72 deletions

View File

@@ -7,9 +7,9 @@ import type { HardwareStatus, LogSettings, SystemStatus } from 'types';
import { alovaInstance, alovaInstanceGH } from './endpoints';
// HardwareStatus - also used to ping in Restart monitor for pinging
// hardwareStatus - also used to ping in Restart monitor for pinging
export const readHardwareStatus = () =>
alovaInstance.Get<HardwareStatus>('/rest/HardwareStatus');
alovaInstance.Get<HardwareStatus>('/rest/hardwareStatus');
// SystemStatus
export const readSystemStatus = () =>

View File

@@ -50,6 +50,10 @@ export function boardProfileSelectItems() {
}
const ApplicationSettings: FC = () => {
const { data: hardwareData, error } = useRequest(SystemApi.readHardwareStatus, {
force: true
});
const {
loadData,
saveData,
@@ -835,7 +839,7 @@ const ApplicationSettings: FC = () => {
checked={data.modbus_enabled}
onChange={updateFormValue}
name="modbus_enabled"
disabled={saving}
disabled={!hardwareData.psram}
/>
}
label={LL.ENABLE_MODBUS()}

View File

@@ -21,6 +21,7 @@ export interface HardwareStatus {
fs_used: number;
fs_free: number;
free_mem: number;
psram: boolean;
psram_size?: number;
free_psram?: number;
has_loader: boolean;

View File

@@ -336,7 +336,7 @@ const SYSTEM_STATUS_ENDPOINT = REST_ENDPOINT_ROOT + 'systemStatus';
const ACTIVITY_ENDPOINT = REST_ENDPOINT_ROOT + 'activity';
// SETTINGS
const HARDWARE_STATUS_ENDPOINT = REST_ENDPOINT_ROOT + 'HardwareStatus';
const HARDWARE_STATUS_ENDPOINT = REST_ENDPOINT_ROOT + 'hardwareStatus';
const SECURITY_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'securitySettings';
const RESTART_ENDPOINT = REST_ENDPOINT_ROOT + 'restart';
const RESTART_PARTITION_ENDPOINT = REST_ENDPOINT_ROOT + 'partition';
@@ -366,6 +366,8 @@ const hardware_status = {
fs_used: 24,
fs_free: 2024,
free_mem: 100,
psram: true,
// psram: false,
psram_size: 4093,
free_psram: 4074,
has_loader: true,
@@ -604,42 +606,53 @@ const emsesp_allvalues = {
};
let settings = {
locale: 'en',
tx_mode: 4,
ems_bus_id: 11,
syslog_enabled: false,
syslog_level: 3,
trace_raw: false,
syslog_mark_interval: 0,
syslog_host: '192.168.1.4',
syslog_port: 514,
shower_timer: true,
shower_alert: true,
shower_alert_trigger: 7,
shower_alert_coldshot: 10,
shower_min_duration: 120,
rx_gpio: 23,
tx_gpio: 5,
phy_type: 0,
eth_power: 0,
eth_phy_addr: 0,
eth_clock_mode: 0,
dallas_gpio: 3,
dallas_parasite: false,
led_gpio: 2,
hide_led: false,
notoken_api: false,
readonly_mode: false,
low_clock: false,
boiler_heatingoff: false,
telnet_enabled: true,
analog_enabled: false,
pbutton_gpio: 0,
board_profile: 'S32',
bool_format: 1,
bool_dashboard: 1,
enum_format: 1,
fahrenheit: false
"locale": "en",
"tx_mode": 1,
"ems_bus_id": 11,
"syslog_enabled": false,
"syslog_level": 3,
"trace_raw": false,
"syslog_mark_interval": 0,
"syslog_host": "192.168.1.8",
"syslog_port": 514,
"boiler_heatingoff": false,
"remote_timeout": 24,
"remote_timeout_en": false,
"shower_timer": true,
"shower_alert": false,
"shower_alert_coldshot": 10,
"shower_alert_trigger": 7,
"shower_min_duration": 180,
"rx_gpio": 4,
"tx_gpio": 5,
"dallas_gpio": 14,
"dallas_parasite": false,
"led_gpio": 2,
"hide_led": true,
"low_clock": false,
"telnet_enabled": true,
"notoken_api": false,
"readonly_mode": false,
"analog_enabled": true,
"pbutton_gpio": 34,
"solar_maxflow": 30,
"board_profile": "E32V2",
"fahrenheit": false,
"bool_format": 1,
"bool_dashboard": 1,
"enum_format": 1,
"weblog_level": 6,
"weblog_buffer": 50,
"weblog_compact": true,
"phy_type": 1,
"eth_power": 15,
"eth_phy_addr": 0,
"eth_clock_mode": 1,
"platform": "ESP32R",
"modbus_enabled": false,
"modbus_port": 502,
"modbus_max_clients": 10,
"modbus_timeout": 10000
};
const emsesp_devices = {

View File

@@ -26,7 +26,7 @@ uuid::log::Logger Command::logger_{F_(command), uuid::log::Facility::DAEMON};
std::vector<Command::CmdFunction> Command::cmdfunctions_;
// takes a path and a json body, parses the data and calls the command
// takes a URI path and a json body, parses the data and calls the command
// the path is leading so if duplicate keys are in the input JSON it will be ignored
// the entry point will be either via the Web API (api/) or MQTT (<base>/)
// returns a return code and json output
@@ -34,22 +34,11 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec
SUrlParser p; // parse URL for the path names
p.parse(path);
if (!p.paths().size()) {
return json_message(CommandRet::ERROR, "invalid path", output);
}
// check first if it's from API, if so strip the "api/"
if (p.paths().front() == "api") {
// check first if it's from API or MQTT, if so strip the "api/" or "<base>/" from the path
if (p.paths().size() && ((p.paths().front() == "api") || (p.paths().front() == Mqtt::base()))) {
p.paths().erase(p.paths().begin());
} else {
// not /api, so must be MQTT path. Check for base and remove it.
if (!strncmp(path, Mqtt::base().c_str(), Mqtt::base().length())) {
char new_path[Mqtt::MQTT_TOPIC_MAX_SIZE];
strlcpy(new_path, path, sizeof(new_path));
p.parse(new_path + Mqtt::base().length() + 1); // re-parse the stripped path
} else {
return json_message(CommandRet::ERROR, "unrecognized path", output); // error
}
return json_message(CommandRet::ERROR, "invalid path", output, path); // error
}
// re-calculate new path
@@ -701,15 +690,21 @@ void Command::show_all(uuid::console::Shell & shell) {
shell.println();
}
uint8_t Command::json_message(uint8_t error_code, const char * message, const JsonObject output) {
// creates a single json document with an error message
// object is optional
uint8_t Command::json_message(uint8_t error_code, const char * message, const JsonObject output, const char * object) {
output.clear();
output["message"] = message;
if (object) {
output["message"] = std::string(message) + " " + object;
} else {
output["message"] = message;
}
return error_code;
}
//
// SUrlParser class
//
// **************************
// **** SUrlParser class ****
// **************************
// Extract only the path component from the passed URI and normalized it
// e.g. //one/two////three/// becomes /one/two/three

View File

@@ -143,7 +143,7 @@ class Command {
static std::vector<CmdFunction> cmdfunctions_; // the list of commands
static uint8_t json_message(uint8_t error_code, const char * message, const JsonObject output);
static uint8_t json_message(uint8_t error_code, const char * message, JsonObject output, const char * object = nullptr);
};
class SUrlParser {

View File

@@ -580,7 +580,7 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
return;
} else if (!has_data) {
// show message if no data returned (e.g. for analogsensor, temperaturesensor, custom)
shell.println("Command executed. Check log for messages.");
shell.println("Command executed");
return;
} else {
return;

View File

@@ -438,7 +438,7 @@ ModbusMessage Modbus::handleWrite(const ModbusMessage & request) {
if (output.size()) {
snprintf(error,
sizeof(error),
"Modbus write command failed with error: %s (%s)",
"Modbus write command failed with error %s (%s)",
(const char *)output["message"],
Command::return_code_string(return_code));
} else {

View File

@@ -228,9 +228,9 @@ void Mqtt::on_message(const char * topic, const uint8_t * payload, size_t len) {
#if defined(EMSESP_DEBUG)
if (len) {
LOG_DEBUG("Received topic `%s` => payload `%s` (length %d)", topic, message, len);
LOG_DEBUG("Received topic %s => payload '%s' (length %d)", topic, message, len);
} else {
LOG_DEBUG("Received topic `%s`", topic);
LOG_DEBUG("Received topic %s", topic);
}
#endif
// remove HA topics if we don't use discovery

View File

@@ -1172,7 +1172,9 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
test("boiler");
test("thermostat");
EMSESP::mqtt_.incoming("ems-esp/boiler/wwseltemp", "59");
EMSESP::mqtt_.incoming("ems-esp/boiler/seltemp", "59");
EMSESP::mqtt_.incoming("badems-esp/boiler/seltemp", "59"); // should fail
ok = true;
}

View File

@@ -32,7 +32,6 @@ WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, Securit
}
void WebSettings::read(WebSettings & settings, JsonObject root) {
root["version"] = settings.version;
root["locale"] = settings.locale;
root["tx_mode"] = settings.tx_mode;
root["ems_bus_id"] = settings.ems_bus_id;

View File

@@ -24,9 +24,9 @@
namespace emsesp {
// /rest/HardwareStatus
// /rest/hardwareStatus
WebStatusService::WebStatusService(AsyncWebServer * server, SecurityManager * securityManager) {
server->on(HARDWARE_STATUS_SERVICE_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { HardwareStatus(request); });
server->on(HARDWARE_STATUS_SERVICE_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { hardwareStatus(request); });
server->on(SYSTEM_STATUS_SERVICE_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { systemStatus(request); });
}
@@ -85,7 +85,7 @@ void WebStatusService::systemStatus(AsyncWebServerRequest * request) {
request->send(response);
}
void WebStatusService::HardwareStatus(AsyncWebServerRequest * request) {
void WebStatusService::hardwareStatus(AsyncWebServerRequest * request) {
EMSESP::system_.refreshHeapMem(); // refresh free heap and max alloc heap
auto * response = new AsyncJsonResponse(false);
@@ -121,6 +121,7 @@ void WebStatusService::HardwareStatus(AsyncWebServerRequest * request) {
root["fs_free"] = EMSESP::system_.FStotal() - FSused;
root["free_caps"] = heap_caps_get_free_size(MALLOC_CAP_8BIT) / 1024; // includes heap and psram
root["psram"] = EMSESP::system_.PSram();
if (EMSESP::system_.PSram()) {
root["psram_size"] = EMSESP::system_.PSram();
root["free_psram"] = ESP.getFreePsram() / 1024;

View File

@@ -1,7 +1,7 @@
#ifndef WebStatusService_h
#define WebStatusService_h
#define HARDWARE_STATUS_SERVICE_PATH "/rest/HardwareStatus"
#define HARDWARE_STATUS_SERVICE_PATH "/rest/hardwareStatus"
#define SYSTEM_STATUS_SERVICE_PATH "/rest/systemStatus"
namespace emsesp {
@@ -12,7 +12,7 @@ class WebStatusService {
private:
void systemStatus(AsyncWebServerRequest * request);
void HardwareStatus(AsyncWebServerRequest * request);
void hardwareStatus(AsyncWebServerRequest * request);
};
} // namespace emsesp