Merge pull request #3122 from proddy/commands

Commands - update web
This commit is contained in:
Proddy
2026-06-14 17:11:13 +02:00
committed by GitHub
9 changed files with 229 additions and 67 deletions

View File

@@ -18,6 +18,5 @@ For more details go to [emsesp.org](https://emsesp.org/).
## Changed
- various memory optimizations [#3083](https://github.com/emsesp/EMS-ESP32/issues/3083)
- Scheduler name is mandatory
- Scheduler with type "Immediate", click Execute does not run the command [#3092](https://github.com/emsesp/EMS-ESP32/issues/3092)
- Scheduler name is now mandatory
- network fallback to AP only after start [#3090](https://github.com/emsesp/EMS-ESP32/issues/3090)

View File

@@ -1,6 +1,7 @@
{
"type": "systembackup",
"version": "3.9.0",
"date": "2026-06-14T10:59:16",
"systembackup": [
{
"type": "settings",
@@ -18,7 +19,7 @@
"tx_power": 0
},
"AP": {
"provision_mode": 1,
"provision_mode": 2,
"ssid": "ems-esp",
"password": "ems-esp-neo",
"channel": 1,
@@ -31,13 +32,13 @@
"MQTT": {
"enableTLS": false,
"rootCA": "",
"enabled": false,
"host": "",
"enabled": true,
"host": "192.168.1.2",
"port": 1883,
"base": "ems-esp",
"username": "",
"password": "",
"client_id": "esp32-b8ffc9ec",
"username": "username",
"password": "password",
"client_id": "esp32",
"keep_alive": 60,
"clean_session": false,
"entity_format": 1,
@@ -51,17 +52,17 @@
"publish_time_heartbeat": 60,
"mqtt_qos": 0,
"mqtt_retain": false,
"ha_enabled": false,
"ha_enabled": true,
"nested_format": 1,
"discovery_prefix": "homeassistant",
"discovery_type": 0,
"ha_number_mode": 0,
"ha_number_mode": 1,
"publish_single": false,
"publish_single2cmd": false,
"send_response": false
},
"NTP": {
"enabled": false,
"enabled": true,
"server": "time.google.com",
"tz_label": "Europe/Amsterdam",
"tz_format": "CET-1CEST,M3.5.0,M10.5.0/3"
@@ -85,8 +86,9 @@
"version": "3.9.0",
"board_profile": "E32V2_2",
"platform": "ESP32",
"system_name": "prod",
"locale": "en",
"tx_mode": 5,
"tx_mode": 1,
"ems_bus_id": 73,
"syslog_enabled": false,
"syslog_level": 3,
@@ -97,7 +99,7 @@
"boiler_heatingoff": false,
"remote_timeout": 24,
"remote_timeout_en": false,
"shower_timer": false,
"shower_timer": true,
"shower_alert": false,
"shower_alert_coldshot": 10,
"shower_alert_trigger": 7,
@@ -107,7 +109,7 @@
"dallas_gpio": 14,
"dallas_parasite": false,
"led_gpio": 32,
"hide_led": false,
"hide_led": true,
"led_type": 1,
"low_clock": false,
"telnet_enabled": true,
@@ -131,22 +133,68 @@
"modbus_port": 502,
"modbus_max_clients": 10,
"modbus_timeout": 300,
"developer_mode": false,
"email_enabled": false,
"developer_mode": true,
"email_enabled": true,
"email_security": 2,
"email_server": "smtp.example.net",
"email_server": "smtp.gmail.com",
"email_port": 587,
"email_login": "",
"email_pass": "",
"email_sender": "ems-esp@example.net",
"email_recp": "",
"email_login": "test@emsesp.org",
"email_pass": "password",
"email_sender": "test@emsesp.org",
"email_recp": "test@emsesp.org",
"email_subject": "ems-esp notification"
}
},
{
"type": "commands",
"Commands": {
"commands": [
{
"id": 1,
"cmd": "{\"url\":\"https://api.pushover.net/1/messages.json\"}",
"value": "{\"user\":\"userkey\", \"token\":\"tokenkey\", \"message\":\"custom/message2\"}",
"name": "push_over"
},
{
"id": 2,
"cmd": "system/message",
"value": "hello",
"name": "sendmessage"
},
{
"id": 3,
"cmd": "system/message",
"value": "{\"url\":\"http://emsesp.org/versions.json\"}",
"name": "sendversions"
},
{
"id": 4,
"cmd": "custom/message",
"value": "{\"url\":\"http://emsesp.org/versions.json\"}",
"name": "getversions"
},
{
"id": 5,
"cmd": "system/sendmail",
"value": "\"test email with \" + custom/message2",
"name": "sendmail"
}
]
}
},
{
"type": "schedule",
"Schedule": {
"schedule": []
"schedule": [
{
"id": 1,
"flags": 128,
"active": false,
"time": "",
"cmd_name": "sendmail",
"name": "sendmailtest"
}
]
}
},
{
@@ -187,7 +235,36 @@
{
"type": "entities",
"Entities": {
"entities": []
"entities": [
{
"id": 0,
"ram": 1,
"device_id": 0,
"type_id": 0,
"offset": 0,
"factor": 1,
"name": "message",
"uom": 0,
"value_type": 9,
"writeable": true,
"hide": false,
"value": "{\"stable\":{\"version\":\"3.8.2\",\"date\":\"2026-05-12\"},\"dev\":{\"version\":\"3.8.3-dev.5\",\"date\":\"2026-05-28T09:55:29Z\"}}"
},
{
"id": 1,
"ram": 1,
"device_id": 0,
"type_id": 0,
"offset": 0,
"factor": 1,
"name": "message2",
"uom": 0,
"value_type": 9,
"writeable": true,
"hide": false,
"value": "testing"
}
]
}
},
{
@@ -199,10 +276,65 @@
{
"type": "nvs",
"nvs": [
{
"type": 1,
"key": "nompower",
"value": 30
},
{
"type": 33,
"key": "boot",
"value": "3.9.0"
},
{
"type": 17,
"key": "led",
"value": 0
},
{
"type": 33,
"key": "intTemp",
"value": "28_1767_7B13_2502"
},
{
"type": 4,
"key": "d_boot",
"value": 1
},
{
"type": 33,
"key": "app1",
"value": "3.9.0"
},
{
"type": 33,
"key": "app0",
"value": "3.9.0"
},
{
"type": 66,
"key": "nrgheat",
"value": 49355.29793
},
{
"type": 4,
"key": "d_app1",
"value": 1781336521
},
{
"type": 1,
"key": "fresh_firmware",
"value": 0
},
{
"type": 4,
"key": "d_app0",
"value": 1781363944
},
{
"type": 66,
"key": "nrgww",
"value": 41852.79107
}
]
}

View File

@@ -51,7 +51,7 @@
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"concurrently": "^10.0.3",
"eslint": "^10.4.1",
"eslint": "^10.5.0",
"eslint-config-prettier": "^10.1.8",
"prettier": "^3.8.4",
"rollup-plugin-visualizer": "^7.0.1",

View File

@@ -68,7 +68,7 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^10.0.1
version: 10.0.1(eslint@10.4.1)
version: 10.0.1(eslint@10.5.0)
'@preact/preset-vite':
specifier: ^2.10.5
version: 2.10.5(@babel/core@7.29.7)(preact@10.29.2)(vite@8.0.16(@types/node@25.9.3)(terser@5.48.0))
@@ -88,11 +88,11 @@ importers:
specifier: ^10.0.3
version: 10.0.3
eslint:
specifier: ^10.4.1
version: 10.4.1
specifier: ^10.5.0
version: 10.5.0
eslint-config-prettier:
specifier: ^10.1.8
version: 10.1.8(eslint@10.4.1)
version: 10.1.8(eslint@10.5.0)
prettier:
specifier: ^3.8.4
version: 3.8.4
@@ -104,7 +104,7 @@ importers:
version: 5.48.0
typescript-eslint:
specifier: ^8.61.0
version: 8.61.0(eslint@10.4.1)(typescript@6.0.3)
version: 8.61.0(eslint@10.5.0)(typescript@6.0.3)
vite:
specifier: ^8.0.16
version: 8.0.16(@types/node@25.9.3)(terser@5.48.0)
@@ -853,8 +853,8 @@ packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
baseline-browser-mapping@2.10.36:
resolution: {integrity: sha512-lVq/Df7LXlO79MVaaUHztSwWiG9oXoWHlgvNS51v8Dpd4+G4/VIy6qYePTw31nAVls33nUtnfezYeLkYAak9dg==}
baseline-browser-mapping@2.10.37:
resolution: {integrity: sha512-girxaJ7WZssDOFhzCGZTDKoTa1gk6A1TbflaYTpykLJ4UU9Fz9kx1aREM8JCuoVHbL8X8T/mJg7w2oYSq72Oig==}
engines: {node: '>=6.0.0'}
hasBin: true
@@ -1371,8 +1371,8 @@ packages:
resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==}
engines: {node: ^20.19.0 || ^22.13.0 || >=24}
eslint@10.4.1:
resolution: {integrity: sha512-AyIKhnOBuOAdueD7RB3xB+YeAWScb9jHsJBgH2Hcde8InP5JYhqrRR6iTMHyTEwgENK54Cp44e4v8BwNhsuHuw==}
eslint@10.5.0:
resolution: {integrity: sha512-1y+7C+vi12bUK1IpZeaV3gsH9fHLBmPvYmPx42pvT/E9yG0IC8g3PUZZgp0+JLJl7ZDK0flc2gc+Aw9dpCvIsQ==}
engines: {node: ^20.19.0 || ^22.13.0 || >=24}
hasBin: true
peerDependencies:
@@ -3240,9 +3240,9 @@ snapshots:
'@esbuild/linux-loong64@0.14.54':
optional: true
'@eslint-community/eslint-utils@4.9.1(eslint@10.4.1)':
'@eslint-community/eslint-utils@4.9.1(eslint@10.5.0)':
dependencies:
eslint: 10.4.1
eslint: 10.5.0
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.2': {}
@@ -3263,9 +3263,9 @@ snapshots:
dependencies:
'@types/json-schema': 7.0.15
'@eslint/js@10.0.1(eslint@10.4.1)':
'@eslint/js@10.0.1(eslint@10.5.0)':
optionalDependencies:
eslint: 10.4.1
eslint: 10.5.0
'@eslint/object-schema@3.0.5': {}
@@ -3631,15 +3631,15 @@ snapshots:
dependencies:
'@types/node': 25.9.3
'@typescript-eslint/eslint-plugin@8.61.0(@typescript-eslint/parser@8.61.0(eslint@10.4.1)(typescript@6.0.3))(eslint@10.4.1)(typescript@6.0.3)':
'@typescript-eslint/eslint-plugin@8.61.0(@typescript-eslint/parser@8.61.0(eslint@10.5.0)(typescript@6.0.3))(eslint@10.5.0)(typescript@6.0.3)':
dependencies:
'@eslint-community/regexpp': 4.12.2
'@typescript-eslint/parser': 8.61.0(eslint@10.4.1)(typescript@6.0.3)
'@typescript-eslint/parser': 8.61.0(eslint@10.5.0)(typescript@6.0.3)
'@typescript-eslint/scope-manager': 8.61.0
'@typescript-eslint/type-utils': 8.61.0(eslint@10.4.1)(typescript@6.0.3)
'@typescript-eslint/utils': 8.61.0(eslint@10.4.1)(typescript@6.0.3)
'@typescript-eslint/type-utils': 8.61.0(eslint@10.5.0)(typescript@6.0.3)
'@typescript-eslint/utils': 8.61.0(eslint@10.5.0)(typescript@6.0.3)
'@typescript-eslint/visitor-keys': 8.61.0
eslint: 10.4.1
eslint: 10.5.0
ignore: 7.0.5
natural-compare: 1.4.0
ts-api-utils: 2.5.0(typescript@6.0.3)
@@ -3647,14 +3647,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/parser@8.61.0(eslint@10.4.1)(typescript@6.0.3)':
'@typescript-eslint/parser@8.61.0(eslint@10.5.0)(typescript@6.0.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.61.0
'@typescript-eslint/types': 8.61.0
'@typescript-eslint/typescript-estree': 8.61.0(typescript@6.0.3)
'@typescript-eslint/visitor-keys': 8.61.0
debug: 4.4.3
eslint: 10.4.1
eslint: 10.5.0
typescript: 6.0.3
transitivePeerDependencies:
- supports-color
@@ -3677,13 +3677,13 @@ snapshots:
dependencies:
typescript: 6.0.3
'@typescript-eslint/type-utils@8.61.0(eslint@10.4.1)(typescript@6.0.3)':
'@typescript-eslint/type-utils@8.61.0(eslint@10.5.0)(typescript@6.0.3)':
dependencies:
'@typescript-eslint/types': 8.61.0
'@typescript-eslint/typescript-estree': 8.61.0(typescript@6.0.3)
'@typescript-eslint/utils': 8.61.0(eslint@10.4.1)(typescript@6.0.3)
'@typescript-eslint/utils': 8.61.0(eslint@10.5.0)(typescript@6.0.3)
debug: 4.4.3
eslint: 10.4.1
eslint: 10.5.0
ts-api-utils: 2.5.0(typescript@6.0.3)
typescript: 6.0.3
transitivePeerDependencies:
@@ -3706,13 +3706,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.61.0(eslint@10.4.1)(typescript@6.0.3)':
'@typescript-eslint/utils@8.61.0(eslint@10.5.0)(typescript@6.0.3)':
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@10.4.1)
'@eslint-community/eslint-utils': 4.9.1(eslint@10.5.0)
'@typescript-eslint/scope-manager': 8.61.0
'@typescript-eslint/types': 8.61.0
'@typescript-eslint/typescript-estree': 8.61.0(typescript@6.0.3)
eslint: 10.4.1
eslint: 10.5.0
typescript: 6.0.3
transitivePeerDependencies:
- supports-color
@@ -3784,7 +3784,7 @@ snapshots:
base64-js@1.5.1: {}
baseline-browser-mapping@2.10.36: {}
baseline-browser-mapping@2.10.37: {}
bin-build@3.0.0:
dependencies:
@@ -3845,7 +3845,7 @@ snapshots:
browserslist@4.28.2:
dependencies:
baseline-browser-mapping: 2.10.36
baseline-browser-mapping: 2.10.37
caniuse-lite: 1.0.30001799
electron-to-chromium: 1.5.372
node-releases: 2.0.47
@@ -4316,9 +4316,9 @@ snapshots:
escape-string-regexp@4.0.0: {}
eslint-config-prettier@10.1.8(eslint@10.4.1):
eslint-config-prettier@10.1.8(eslint@10.5.0):
dependencies:
eslint: 10.4.1
eslint: 10.5.0
eslint-scope@9.1.2:
dependencies:
@@ -4331,9 +4331,9 @@ snapshots:
eslint-visitor-keys@5.0.1: {}
eslint@10.4.1:
eslint@10.5.0:
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@10.4.1)
'@eslint-community/eslint-utils': 4.9.1(eslint@10.5.0)
'@eslint-community/regexpp': 4.12.2
'@eslint/config-array': 0.23.5
'@eslint/config-helpers': 0.6.0
@@ -5753,13 +5753,13 @@ snapshots:
dependencies:
typescript: 6.0.3
typescript-eslint@8.61.0(eslint@10.4.1)(typescript@6.0.3):
typescript-eslint@8.61.0(eslint@10.5.0)(typescript@6.0.3):
dependencies:
'@typescript-eslint/eslint-plugin': 8.61.0(@typescript-eslint/parser@8.61.0(eslint@10.4.1)(typescript@6.0.3))(eslint@10.4.1)(typescript@6.0.3)
'@typescript-eslint/parser': 8.61.0(eslint@10.4.1)(typescript@6.0.3)
'@typescript-eslint/eslint-plugin': 8.61.0(@typescript-eslint/parser@8.61.0(eslint@10.5.0)(typescript@6.0.3))(eslint@10.5.0)(typescript@6.0.3)
'@typescript-eslint/parser': 8.61.0(eslint@10.5.0)(typescript@6.0.3)
'@typescript-eslint/typescript-estree': 8.61.0(typescript@6.0.3)
'@typescript-eslint/utils': 8.61.0(eslint@10.4.1)(typescript@6.0.3)
eslint: 10.4.1
'@typescript-eslint/utils': 8.61.0(eslint@10.5.0)(typescript@6.0.3)
eslint: 10.5.0
typescript: 6.0.3
transitivePeerDependencies:
- supports-color

View File

@@ -4,9 +4,11 @@ import { toast } from 'react-toastify';
import AddIcon from '@mui/icons-material/Add';
import CancelIcon from '@mui/icons-material/Cancel';
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
import WarningIcon from '@mui/icons-material/Warning';
import { Box, Button, Typography } from '@mui/material';
import { Box, Button, IconButton, Typography } from '@mui/material';
import { callAction } from '@/api/app';
import {
Body,
Cell,
@@ -46,7 +48,7 @@ const DEFAULT_COMMAND_ITEM: Omit<CommandItem, 'id'> = {
const commandsTheme = {
Table: `
--data-table-library_grid-template-columns: repeat(1, minmax(100px, 1fr)) repeat(1, minmax(100px, 1fr)) 160px;
--data-table-library_grid-template-columns: repeat(1, minmax(100px, 1fr)) repeat(1, minmax(100px, 1fr)) 160px 32px;
`,
BaseRow: `
font-size: 14px;
@@ -81,7 +83,7 @@ const commandsTheme = {
`
};
const CommandsPage = () => {
const Commands = () => {
const { LL } = useI18nContext();
const [numChanges, setNumChanges] = useState<number>(0);
const blocker = useBlocker(numChanges !== 0);
@@ -141,6 +143,21 @@ const CommandsPage = () => {
}
};
const { send: executeCommand } = useRequest(
(id: string) => callAction({ action: 'executeCommand', param: id }),
{ immediate: false }
)
.onSuccess(() => {
toast.success(LL.EXECUTE_COMMAND_SENT());
})
.onError((error) => {
toast.error(String(error.error?.message || 'An error occurred'));
});
const execute = async (name: string) => {
await executeCommand(name);
};
const editItem = (ci: CommandItem) => {
setCreating(false);
setSelectedItem(ci);
@@ -205,6 +222,7 @@ const CommandsPage = () => {
<HeaderCell stiff>{LL.COMMAND(0)}</HeaderCell>
<HeaderCell stiff>{LL.VALUE(0)}</HeaderCell>
<HeaderCell stiff>{LL.NAME(0)}</HeaderCell>
<HeaderCell></HeaderCell>
</HeaderRow>
</Header>
<Body>
@@ -213,6 +231,16 @@ const CommandsPage = () => {
<Cell>{ci.cmd}</Cell>
<Cell>{ci.value}</Cell>
<Cell>{ci.name}</Cell>
<Cell>
{numChanges === 0 && (
<IconButton
onClick={() => execute(ci.name)}
style={{ backgroundColor: 'transparent' }}
>
<PlayArrowIcon color="primary" sx={{ fontSize: 16 }} />
</IconButton>
)}
</Cell>
</Row>
))}
</Body>
@@ -281,4 +309,4 @@ const CommandsPage = () => {
);
};
export default CommandsPage;
export default Commands;

View File

@@ -82,7 +82,7 @@ const CommandsDialog = ({
} catch (error) {
setFieldErrors((error as ValidationError).fieldErrors);
} finally {
setHasChanges(false);
// setHasChanges(false);
}
};

View File

@@ -336,6 +336,7 @@ const Dashboard = memo(() => {
size="small"
aria-label={LL.RUN_COMMAND()}
onClick={() => editDashboardValue(di)}
style={{ backgroundColor: 'transparent' }}
>
<PlayArrowIcon
color="primary"
@@ -349,6 +350,7 @@ const Dashboard = memo(() => {
LL.CHANGE_VALUE() + ' ' + LL.VALUE(0)
}
onClick={() => editDashboardValue(di)}
style={{ backgroundColor: 'transparent' }}
>
<EditIcon
color="primary"

View File

@@ -777,6 +777,7 @@ const Devices = memo(() => {
<IconButton
size="small"
onClick={() => showDeviceValue(dv)}
style={{ backgroundColor: 'transparent' }}
>
{dv.v === '' ? (
<PlayArrowIcon color="primary" sx={{ fontSize: 16 }} />

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.9.0-dev.12"
#define EMSESP_APP_VERSION "3.9.0-dev.13"