mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev
This commit is contained in:
@@ -7,9 +7,9 @@ import type { HardwareStatus, LogSettings, SystemStatus } from 'types';
|
|||||||
|
|
||||||
import { alovaInstance, alovaInstanceGH } from './endpoints';
|
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 = () =>
|
export const readHardwareStatus = () =>
|
||||||
alovaInstance.Get<HardwareStatus>('/rest/HardwareStatus');
|
alovaInstance.Get<HardwareStatus>('/rest/hardwareStatus');
|
||||||
|
|
||||||
// SystemStatus
|
// SystemStatus
|
||||||
export const readSystemStatus = () =>
|
export const readSystemStatus = () =>
|
||||||
|
|||||||
@@ -50,6 +50,10 @@ export function boardProfileSelectItems() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ApplicationSettings: FC = () => {
|
const ApplicationSettings: FC = () => {
|
||||||
|
const { data: hardwareData, error } = useRequest(SystemApi.readHardwareStatus, {
|
||||||
|
force: true
|
||||||
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
loadData,
|
loadData,
|
||||||
saveData,
|
saveData,
|
||||||
@@ -835,7 +839,7 @@ const ApplicationSettings: FC = () => {
|
|||||||
checked={data.modbus_enabled}
|
checked={data.modbus_enabled}
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
name="modbus_enabled"
|
name="modbus_enabled"
|
||||||
disabled={saving}
|
disabled={!hardwareData.psram}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label={LL.ENABLE_MODBUS()}
|
label={LL.ENABLE_MODBUS()}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export interface HardwareStatus {
|
|||||||
fs_used: number;
|
fs_used: number;
|
||||||
fs_free: number;
|
fs_free: number;
|
||||||
free_mem: number;
|
free_mem: number;
|
||||||
|
psram: boolean;
|
||||||
psram_size?: number;
|
psram_size?: number;
|
||||||
free_psram?: number;
|
free_psram?: number;
|
||||||
has_loader: boolean;
|
has_loader: boolean;
|
||||||
|
|||||||
@@ -336,7 +336,7 @@ const SYSTEM_STATUS_ENDPOINT = REST_ENDPOINT_ROOT + 'systemStatus';
|
|||||||
const ACTIVITY_ENDPOINT = REST_ENDPOINT_ROOT + 'activity';
|
const ACTIVITY_ENDPOINT = REST_ENDPOINT_ROOT + 'activity';
|
||||||
|
|
||||||
// SETTINGS
|
// 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 SECURITY_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'securitySettings';
|
||||||
const RESTART_ENDPOINT = REST_ENDPOINT_ROOT + 'restart';
|
const RESTART_ENDPOINT = REST_ENDPOINT_ROOT + 'restart';
|
||||||
const RESTART_PARTITION_ENDPOINT = REST_ENDPOINT_ROOT + 'partition';
|
const RESTART_PARTITION_ENDPOINT = REST_ENDPOINT_ROOT + 'partition';
|
||||||
@@ -366,6 +366,8 @@ const hardware_status = {
|
|||||||
fs_used: 24,
|
fs_used: 24,
|
||||||
fs_free: 2024,
|
fs_free: 2024,
|
||||||
free_mem: 100,
|
free_mem: 100,
|
||||||
|
psram: true,
|
||||||
|
// psram: false,
|
||||||
psram_size: 4093,
|
psram_size: 4093,
|
||||||
free_psram: 4074,
|
free_psram: 4074,
|
||||||
has_loader: true,
|
has_loader: true,
|
||||||
@@ -604,42 +606,53 @@ const emsesp_allvalues = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let settings = {
|
let settings = {
|
||||||
locale: 'en',
|
"locale": "en",
|
||||||
tx_mode: 4,
|
"tx_mode": 1,
|
||||||
ems_bus_id: 11,
|
"ems_bus_id": 11,
|
||||||
syslog_enabled: false,
|
"syslog_enabled": false,
|
||||||
syslog_level: 3,
|
"syslog_level": 3,
|
||||||
trace_raw: false,
|
"trace_raw": false,
|
||||||
syslog_mark_interval: 0,
|
"syslog_mark_interval": 0,
|
||||||
syslog_host: '192.168.1.4',
|
"syslog_host": "192.168.1.8",
|
||||||
syslog_port: 514,
|
"syslog_port": 514,
|
||||||
shower_timer: true,
|
"boiler_heatingoff": false,
|
||||||
shower_alert: true,
|
"remote_timeout": 24,
|
||||||
shower_alert_trigger: 7,
|
"remote_timeout_en": false,
|
||||||
shower_alert_coldshot: 10,
|
"shower_timer": true,
|
||||||
shower_min_duration: 120,
|
"shower_alert": false,
|
||||||
rx_gpio: 23,
|
"shower_alert_coldshot": 10,
|
||||||
tx_gpio: 5,
|
"shower_alert_trigger": 7,
|
||||||
phy_type: 0,
|
"shower_min_duration": 180,
|
||||||
eth_power: 0,
|
"rx_gpio": 4,
|
||||||
eth_phy_addr: 0,
|
"tx_gpio": 5,
|
||||||
eth_clock_mode: 0,
|
"dallas_gpio": 14,
|
||||||
dallas_gpio: 3,
|
"dallas_parasite": false,
|
||||||
dallas_parasite: false,
|
"led_gpio": 2,
|
||||||
led_gpio: 2,
|
"hide_led": true,
|
||||||
hide_led: false,
|
"low_clock": false,
|
||||||
notoken_api: false,
|
"telnet_enabled": true,
|
||||||
readonly_mode: false,
|
"notoken_api": false,
|
||||||
low_clock: false,
|
"readonly_mode": false,
|
||||||
boiler_heatingoff: false,
|
"analog_enabled": true,
|
||||||
telnet_enabled: true,
|
"pbutton_gpio": 34,
|
||||||
analog_enabled: false,
|
"solar_maxflow": 30,
|
||||||
pbutton_gpio: 0,
|
"board_profile": "E32V2",
|
||||||
board_profile: 'S32',
|
"fahrenheit": false,
|
||||||
bool_format: 1,
|
"bool_format": 1,
|
||||||
bool_dashboard: 1,
|
"bool_dashboard": 1,
|
||||||
enum_format: 1,
|
"enum_format": 1,
|
||||||
fahrenheit: false
|
"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 = {
|
const emsesp_devices = {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ uuid::log::Logger Command::logger_{F_(command), uuid::log::Facility::DAEMON};
|
|||||||
|
|
||||||
std::vector<Command::CmdFunction> Command::cmdfunctions_;
|
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 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>/)
|
// the entry point will be either via the Web API (api/) or MQTT (<base>/)
|
||||||
// returns a return code and json output
|
// 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
|
SUrlParser p; // parse URL for the path names
|
||||||
p.parse(path);
|
p.parse(path);
|
||||||
|
|
||||||
if (!p.paths().size()) {
|
// check first if it's from API or MQTT, if so strip the "api/" or "<base>/" from the path
|
||||||
return json_message(CommandRet::ERROR, "invalid path", output);
|
if (p.paths().size() && ((p.paths().front() == "api") || (p.paths().front() == Mqtt::base()))) {
|
||||||
}
|
|
||||||
|
|
||||||
// check first if it's from API, if so strip the "api/"
|
|
||||||
if (p.paths().front() == "api") {
|
|
||||||
p.paths().erase(p.paths().begin());
|
p.paths().erase(p.paths().begin());
|
||||||
} else {
|
} else {
|
||||||
// not /api, so must be MQTT path. Check for base and remove it.
|
return json_message(CommandRet::ERROR, "invalid path", output, path); // error
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// re-calculate new path
|
// re-calculate new path
|
||||||
@@ -701,15 +690,21 @@ void Command::show_all(uuid::console::Shell & shell) {
|
|||||||
shell.println();
|
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.clear();
|
||||||
|
if (object) {
|
||||||
|
output["message"] = std::string(message) + " " + object;
|
||||||
|
} else {
|
||||||
output["message"] = message;
|
output["message"] = message;
|
||||||
|
}
|
||||||
return error_code;
|
return error_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// **************************
|
||||||
// SUrlParser class
|
// **** SUrlParser class ****
|
||||||
//
|
// **************************
|
||||||
|
|
||||||
// Extract only the path component from the passed URI and normalized it
|
// Extract only the path component from the passed URI and normalized it
|
||||||
// e.g. //one/two////three/// becomes /one/two/three
|
// e.g. //one/two////three/// becomes /one/two/three
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ class Command {
|
|||||||
|
|
||||||
static std::vector<CmdFunction> cmdfunctions_; // the list of commands
|
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 {
|
class SUrlParser {
|
||||||
|
|||||||
@@ -580,7 +580,7 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
return;
|
return;
|
||||||
} else if (!has_data) {
|
} else if (!has_data) {
|
||||||
// show message if no data returned (e.g. for analogsensor, temperaturesensor, custom)
|
// 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;
|
return;
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -438,7 +438,7 @@ ModbusMessage Modbus::handleWrite(const ModbusMessage & request) {
|
|||||||
if (output.size()) {
|
if (output.size()) {
|
||||||
snprintf(error,
|
snprintf(error,
|
||||||
sizeof(error),
|
sizeof(error),
|
||||||
"Modbus write command failed with error: %s (%s)",
|
"Modbus write command failed with error %s (%s)",
|
||||||
(const char *)output["message"],
|
(const char *)output["message"],
|
||||||
Command::return_code_string(return_code));
|
Command::return_code_string(return_code));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -228,9 +228,9 @@ void Mqtt::on_message(const char * topic, const uint8_t * payload, size_t len) {
|
|||||||
|
|
||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
if (len) {
|
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 {
|
} else {
|
||||||
LOG_DEBUG("Received topic `%s`", topic);
|
LOG_DEBUG("Received topic %s", topic);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// remove HA topics if we don't use discovery
|
// remove HA topics if we don't use discovery
|
||||||
|
|||||||
@@ -1172,7 +1172,9 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
test("boiler");
|
test("boiler");
|
||||||
test("thermostat");
|
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;
|
ok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, Securit
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WebSettings::read(WebSettings & settings, JsonObject root) {
|
void WebSettings::read(WebSettings & settings, JsonObject root) {
|
||||||
root["version"] = settings.version;
|
|
||||||
root["locale"] = settings.locale;
|
root["locale"] = settings.locale;
|
||||||
root["tx_mode"] = settings.tx_mode;
|
root["tx_mode"] = settings.tx_mode;
|
||||||
root["ems_bus_id"] = settings.ems_bus_id;
|
root["ems_bus_id"] = settings.ems_bus_id;
|
||||||
|
|||||||
@@ -24,9 +24,9 @@
|
|||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
// /rest/HardwareStatus
|
// /rest/hardwareStatus
|
||||||
WebStatusService::WebStatusService(AsyncWebServer * server, SecurityManager * securityManager) {
|
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); });
|
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);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebStatusService::HardwareStatus(AsyncWebServerRequest * request) {
|
void WebStatusService::hardwareStatus(AsyncWebServerRequest * request) {
|
||||||
EMSESP::system_.refreshHeapMem(); // refresh free heap and max alloc heap
|
EMSESP::system_.refreshHeapMem(); // refresh free heap and max alloc heap
|
||||||
|
|
||||||
auto * response = new AsyncJsonResponse(false);
|
auto * response = new AsyncJsonResponse(false);
|
||||||
@@ -121,6 +121,7 @@ void WebStatusService::HardwareStatus(AsyncWebServerRequest * request) {
|
|||||||
root["fs_free"] = EMSESP::system_.FStotal() - FSused;
|
root["fs_free"] = EMSESP::system_.FStotal() - FSused;
|
||||||
root["free_caps"] = heap_caps_get_free_size(MALLOC_CAP_8BIT) / 1024; // includes heap and psram
|
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()) {
|
if (EMSESP::system_.PSram()) {
|
||||||
root["psram_size"] = EMSESP::system_.PSram();
|
root["psram_size"] = EMSESP::system_.PSram();
|
||||||
root["free_psram"] = ESP.getFreePsram() / 1024;
|
root["free_psram"] = ESP.getFreePsram() / 1024;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef WebStatusService_h
|
#ifndef WebStatusService_h
|
||||||
#define 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"
|
#define SYSTEM_STATUS_SERVICE_PATH "/rest/systemStatus"
|
||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
@@ -12,7 +12,7 @@ class WebStatusService {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void systemStatus(AsyncWebServerRequest * request);
|
void systemStatus(AsyncWebServerRequest * request);
|
||||||
void HardwareStatus(AsyncWebServerRequest * request);
|
void hardwareStatus(AsyncWebServerRequest * request);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
Reference in New Issue
Block a user