mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-05-09 15:35:51 +00:00
Compare commits
67 Commits
b264a39780
...
v3.8.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28135c225b | ||
|
|
eaa277fef0 | ||
|
|
e418b7d8e7 | ||
|
|
a4e3be6a69 | ||
|
|
a1bc5bb055 | ||
|
|
f444ca31e0 | ||
|
|
1b70b55989 | ||
|
|
1487f30c43 | ||
|
|
e00eb8e64f | ||
|
|
f41bb3671c | ||
|
|
22c75e6df3 | ||
|
|
5ab10b7aa6 | ||
|
|
ee5fd4d0eb | ||
|
|
46f35bc67c | ||
|
|
ec85a7ec24 | ||
|
|
02f2389587 | ||
|
|
7f140021aa | ||
|
|
6796962c1e | ||
|
|
df6de21cf4 | ||
|
|
df9f75a5c9 | ||
|
|
7bd8710eb6 | ||
|
|
32f2c6d341 | ||
|
|
86919c1684 | ||
|
|
86e29515e7 | ||
|
|
46eb4185d7 | ||
|
|
8da6761a48 | ||
|
|
9233f0dfcc | ||
|
|
292f743b14 | ||
|
|
dd6dfffd57 | ||
|
|
ec705a5307 | ||
|
|
f45f071710 | ||
|
|
f3858546de | ||
|
|
d0ac0b7804 | ||
|
|
d8284ec09f | ||
|
|
6e982acde8 | ||
|
|
8c94ce99b2 | ||
|
|
fc057d18c9 | ||
|
|
18e9b99413 | ||
|
|
a47e0e8266 | ||
|
|
f412ddc716 | ||
|
|
29110e96e5 | ||
|
|
b65866217a | ||
|
|
611e3b1243 | ||
|
|
2ca0a0c634 | ||
|
|
7eb1f061b7 | ||
|
|
50459a23fe | ||
|
|
5bf53c3389 | ||
|
|
4b7aa95be3 | ||
|
|
70943f5758 | ||
|
|
3bc280b817 | ||
|
|
62b15a5319 | ||
|
|
8dd18802d6 | ||
|
|
57a516a83a | ||
|
|
a57fdaa4b3 | ||
|
|
4841e42286 | ||
|
|
8c2d2b06ed | ||
|
|
38c8b1b7f0 | ||
|
|
6fb5933a02 | ||
|
|
c0944433be | ||
|
|
478e6362c9 | ||
|
|
4d6354db78 | ||
|
|
beab0f0c77 | ||
|
|
c17749bd22 | ||
|
|
2bad769c5c | ||
|
|
8ad89ca64b | ||
|
|
9244d8daec | ||
|
|
02d01334b2 |
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -22,7 +22,7 @@ _Make sure your have performed every step and checked the applicable boxes befor
|
||||
- [ ] Searched the issue in [issues](https://github.com/emsesp/EMS-ESP32/issues)
|
||||
- [ ] Searched the issue in [discussions](https://github.com/emsesp/EMS-ESP32/discussions)
|
||||
- [ ] Searched the issue in the [docs](https://emsesp.org/Troubleshooting/)
|
||||
- [ ] Searched the issue in the [chat](https://discord.gg/GP9DPSgeJq)
|
||||
- [ ] Searched the issue in the [chat](https://discord.gg/3J3GgnzpyT)
|
||||
- [ ] Provide the System information in the area below, taken from `http://<IP>/api/system`
|
||||
|
||||
```json
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -7,5 +7,5 @@ contact_links:
|
||||
url: https://github.com/emsesp/EMS-ESP32/discussions
|
||||
about: EMS-ESP usage Questions, Feature Requests and Projects.
|
||||
- name: EMS-ESP Users Chat
|
||||
url: https://discord.gg/GP9DPSgeJq
|
||||
url: https://discord.gg/3J3GgnzpyT
|
||||
about: Chat for feedback, questions and troubleshooting.
|
||||
|
||||
36
CHANGELOG.md
36
CHANGELOG.md
@@ -5,36 +5,7 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [3.8.1] 11 January 2026
|
||||
|
||||
## Added
|
||||
|
||||
- update time saved in nvs
|
||||
- heatpump entities [#2883](https://github.com/emsesp/EMS-ESP32/issues/2883)
|
||||
- HA input number format (mode) selectable box/slider (slider for max range 100) [#2900](https://github.com/emsesp/EMS-ESP32/discussions/2900)
|
||||
|
||||
## Fixed
|
||||
|
||||
- fix EMS bus disconnected errors on some systems [#2881](https://github.com/emsesp/EMS-ESP32/issues/2881)
|
||||
- selflowtemp fix [#2876](https://github.com/emsesp/EMS-ESP32/issues/2876)
|
||||
- updated valid GPIOs for ESP32S2, ESP32S3 and ESP32 that caused custom systems to block gpios [#2887](https://github.com/emsesp/EMS-ESP32/issues/2887)
|
||||
- Junkers wwcharge offset [#2860](https://github.com/emsesp/EMS-ESP32/issues/2860)
|
||||
- fixed minflowtemp [#2890](https://github.com/emsesp/EMS-ESP32/issues/2890)
|
||||
- don't add HA uom/classes for bool values [#2885](https://github.com/emsesp/EMS-ESP32/issues/2885)
|
||||
- fixed missing progress bar on web firmware uploads
|
||||
|
||||
## Changed
|
||||
|
||||
- snapshot gpios stored in temporary ram
|
||||
- GPIOs stored along with the name and reported in log if conflicting
|
||||
- free GPIOs depend on board profile [#2901](https://github.com/emsesp/EMS-ESP32/issues/2901)
|
||||
- prefer PSram for mqtt queue [#2889](https://github.com/emsesp/EMS-ESP32/issues/2889)
|
||||
- day schedule defult to all days, no day selected is not allowed
|
||||
- board profile `CUSTOM` can only be selected in developer mode
|
||||
- mqtt sends round values without decimals (`28` instead of `28.0`)
|
||||
|
||||
|
||||
## [3.8.0] 31 December 2025
|
||||
## [3.8.0]
|
||||
|
||||
## Added
|
||||
|
||||
@@ -55,8 +26,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- FW200 display options [#2610](https://github.com/emsesp/EMS-ESP32/discussions/2610)
|
||||
- CR11 mode settings OFF/MANUAL depends on selTemp [#2437](https://github.com/emsesp/EMS-ESP32/issues/2437)
|
||||
- implemented eFuse settings for BBQKees boards to store model type and ESP chipset
|
||||
- analogsensors for pulse output [#2624](https://github.com/emsesp/EMS-ESP32/discussions/2624)
|
||||
- analogsensors frequency input [#2631](https://github.com/emsesp/EMS-ESP32/discussions/2631)
|
||||
- Analogsensors for pulse output [#2624](https://github.com/emsesp/EMS-ESP32/discussions/2624)
|
||||
- Analogsensors frequency input [#2631](https://github.com/emsesp/EMS-ESP32/discussions/2631)
|
||||
- SRC plus thermostats [#2636](https://github.com/emsesp/EMS-ESP32/issues/2636)
|
||||
- Greenstar 2000 [#2645](https://github.com/emsesp/EMS-ESP32/issues/2645)
|
||||
- RC3xx `dhw modetype` [#2659](https://github.com/emsesp/EMS-ESP32/discussions/2659)
|
||||
@@ -119,6 +90,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- added Home Assistant device details to MQTT Discovery for all devices
|
||||
- device_class and state_class changes for HA MQTT Discovery [#2825](https://github.com/emsesp/EMS-ESP32/issues/2825)
|
||||
|
||||
|
||||
## [3.7.2] 22 March 2025
|
||||
|
||||
## Added
|
||||
|
||||
@@ -1,33 +1,3 @@
|
||||
# Changelog
|
||||
|
||||
For more details go to [emsesp.org](https://emsesp.org/).
|
||||
|
||||
## [3.8.2]
|
||||
|
||||
## Added
|
||||
|
||||
- comfortpoint for BC400 [#2935](https://github.com/emsesp/EMS-ESP32/issues/2935)
|
||||
- customize device brand [#2784](https://github.com/emsesp/EMS-ESP32/issues/2784)
|
||||
- set model for ems-esp devices temperature, analog, etc. [#2958](https://github.com/emsesp/EMS-ESP32/discussions/2958)
|
||||
- prometheus metrics for temperature/analog/scheduler/custom [#2962](https://github.com/emsesp/EMS-ESP32/issues/2962)
|
||||
- boiler pumpkick [#2965](https://github.com/emsesp/EMS-ESP32/discussions/2965)
|
||||
- heatpump reset [#2933](https://github.com/emsesp/EMS-ESP32/issues/2933)
|
||||
- 2.nd freshwater module (dhw4, dhw5) [#2991](https://github.com/emsesp/EMS-ESP32/issues/2991)
|
||||
|
||||
## Fixed
|
||||
|
||||
- SRC climate creation [#2936](https://github.com/emsesp/EMS-ESP32/issues/2936) and [#2960](https://github.com/emsesp/EMS-ESP32/issues/2960)
|
||||
- missing translations [#3015](https://github.com/emsesp/EMS-ESP32/issues/3015)
|
||||
|
||||
## Changed
|
||||
|
||||
- weblogbuffer up to 1000 messages with PSRAM, mentioned in [#2933](https://github.com/emsesp/EMS-ESP32/issues/2933)
|
||||
- validate custom entity writes, [#2931](https://github.com/emsesp/EMS-ESP32/issues/2931)
|
||||
- remove wrong burnMinPower [#2918](https://github.com/emsesp/EMS-ESP32/issues/2918)
|
||||
- store scheduler active state to nvs [#2946](https://github.com/emsesp/EMS-ESP32/discussions/2946)
|
||||
- translated modes `heat` and `eco` for HA-climate mode-str-tpl
|
||||
- support `minflowtemp` and `baseflowtemp` [#2969](https://github.com/emsesp/EMS-ESP32/discussions/2969)
|
||||
- update version if it is 00.00 in first read [#2981](https://github.com/emsesp/EMS-ESP32/issues/2981)
|
||||
- device class for % values [#2980](https://github.com/emsesp/EMS-ESP32/issues/2980)
|
||||
- fetch telegrams: set length to fetch [#3017](https://github.com/emsesp/EMS-ESP32/issues/3017)
|
||||
- move http client from stack to heap
|
||||
|
||||
9
Makefile
9
Makefile
@@ -63,12 +63,11 @@ CXX_STANDARD := -std=gnu++17
|
||||
#----------------------------------------------------------------------
|
||||
# Defined Symbols
|
||||
#----------------------------------------------------------------------
|
||||
DEFINES += -DARDUINOJSON_ENABLE -DARDUINOJSON_ENABLE_ARDUINO_STRING -DARDUINOJSON_USE_DOUBLE=0
|
||||
DEFINES += -DARDUINOJSON_ENABLE -DARDUINOJSON_ENABLE_ARDUINO_STRING -DARDUINOJSON_USE_DOUBLE=0
|
||||
DEFINES += -DEMSESP_STANDALONE -DEMSESP_TEST -DEMSESP_DEBUG -DEMC_RX_BUFFER_SIZE=1500
|
||||
DEFINES += -DNO_TLS_SUPPORT
|
||||
DEFINES += $(ARGS)
|
||||
|
||||
DEFAULTS = -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32S3\"
|
||||
DEFAULTS = -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.8.0-dev.0\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32S3\"
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Sources & Files
|
||||
@@ -80,10 +79,6 @@ SYMBOLS := $(CURDIR)/$(BUILD)/$(TARGET).out
|
||||
CSOURCES := $(shell find $(SOURCES) -name "*.c" 2>/dev/null)
|
||||
CXXSOURCES := $(shell find $(SOURCES) -name "*.cpp" 2>/dev/null)
|
||||
|
||||
# Exclude files not needed for standalone build, if they exist
|
||||
CSOURCES := $(filter-out src/core/ModuleLibrary.c,$(CSOURCES))
|
||||
CXXSOURCES := $(filter-out src/core/ModuleLibrary.cpp,$(CXXSOURCES))
|
||||
|
||||
OBJS := $(patsubst %,$(BUILD)/%.o,$(basename $(CSOURCES)) $(basename $(CXXSOURCES)))
|
||||
DEPS := $(patsubst %,$(BUILD)/%.d,$(basename $(CSOURCES)) $(basename $(CXXSOURCES)))
|
||||
|
||||
|
||||
22
README.md
22
README.md
@@ -18,7 +18,7 @@
|
||||
<a href="https://emsesp.org">
|
||||
<img src="https://img.shields.io/badge/Documentation-0077b5?style=for-the-badge&logo=googledocs&logoColor=white" alt="Guides" />
|
||||
</a>
|
||||
<a href="https://discord.gg/GP9DPSgeJq">
|
||||
<a href="https://discord.gg/3J3GgnzpyT">
|
||||
<img src="https://img.shields.io/badge/Discord-7289da?style=for-the-badge&logo=discord&logoColor=white" alt="Discord" />
|
||||
</a>
|
||||
<a href="https://github.com/emsesp/EMS-ESP32/blob/main/CHANGELOG.md">
|
||||
@@ -32,8 +32,7 @@
|
||||
[](https://sonarcloud.io/summary/new_code?id=emsesp_EMS-ESP32)
|
||||
[](https://app.codacy.com/gh/emsesp/EMS-ESP32/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
||||
[](https://github.com/emsesp/EMS-ESP32/releases)
|
||||
[](https://discord.gg/GP9DPSgeJq)
|
||||
[](https://deepwiki.com/emsesp/EMS-ESP32)
|
||||
[](https://discord.gg/3J3GgnzpyT)
|
||||
|
||||
[](https://github.com/emsesp/EMS-ESP32/stargazers)
|
||||
[](https://github.com/emsesp/EMS-ESP32/network)
|
||||
@@ -41,8 +40,7 @@
|
||||
|
||||
**EMS-ESP** is an open-source firmware for the Espressif ESP32 microcontroller to communicate with **EMS** (Energy Management System) compatible equipment from manufacturers such as Bosch, Buderus, Nefit, Junkers, Worcester, Sieger, elm.leblanc and iVT.
|
||||
|
||||
It requires a small circuit to interface with the EMS bus which can be purchased from <https://bbqkees-electronics.nl>. These gateways are tested thoroughly and certified to work with EMS-ESP.
|
||||
|
||||
It requires a small circuit to interface with the EMS bus which can be purchased from <https://bbqkees-electronics.nl> or custom built.
|
||||
|
||||
## 📦 **Key Features**
|
||||
|
||||
@@ -66,27 +64,29 @@ Head over to the [Installation Guide](https://emsesp.org/Installing) section of
|
||||
|
||||
## 📋 **Documentation**
|
||||
|
||||
Visit [emsesp.org](https://emsesp.org) for more details on how to setup and configure EMS-ESP. You'll also find more a collection of example configuarations, Frequently Asked Questions and Troubleshooting tips.
|
||||
Visit [emsesp.org](https://emsesp.org) for more details on how to install and configure EMS-ESP. There is also a collection of Frequently Asked Questions and Troubleshooting tips with example customizations from the community.
|
||||
|
||||
## 💬 **Getting Support**
|
||||
|
||||
To chat with the community reach out on our [Discord Server](https://discord.gg/GP9DPSgeJq).
|
||||
To chat with the community reach out on our [Discord Server](https://discord.gg/3J3GgnzpyT).
|
||||
|
||||
If you find an issue or have a request, see the [Getting Support](https://emsesp.org/Support/) section of the documentation. Note if you are using a non-BBQKees EMS gateway, you may need to contact the manufacturer for support.
|
||||
If you find an issue or have a request, see [how to request support](https://emsesp.org/Support/) on how to submit a bug report or feature request.
|
||||
|
||||
## 🎥 **Live Demo**
|
||||
|
||||
To see a live demo go to [demo.emsesp.org](https://demo.emsesp.org). Pick a language and use any username and password to log in. Note whast you're seeing is static example data so not all features are operational.
|
||||
For a live demo go to [demo.emsesp.org](https://demo.emsesp.org). Pick a language from the sign on page and log in with any username or password. Note not all features are operational as it's based on static data.
|
||||
|
||||
## 💖 **Contributors**
|
||||
|
||||
EMS-ESP is a project originally created by [proddy](https://github.com/proddy) and maintained by the ems-esp community.
|
||||
EMS-ESP is a project created by [proddy](https://github.com/proddy) and owned and maintained by both [proddy](https://github.com/proddy) and [MichaelDvP](https://github.com/MichaelDvP) with support from [BBQKees Electronics](https://bbqkees-electronics.nl).
|
||||
|
||||
If you like **EMS-ESP**, please give it a ✨ on GitHub, or even better fork it and contribute. You can also offer a small donation. This is an open-source project maintained by volunteers, and your support is greatly appreciated.
|
||||
|
||||
## 📦 **Building**
|
||||
|
||||
See the [Building the firmware](https://emsesp.org/Building) guide in the documentation for instructions on how to build EMS-ESP from this source code.
|
||||
To build the web interface only, run `platformio run -e build_webUI`. This will install the necessary dependencies and build the web interface and also create the embedded code used need to build the firmware. You can run the web interface locally by going to the `interface` directory and running `pnpm standalone`.
|
||||
|
||||
To build the firmware, run `platformio run`. This will build the firmware for all ESP32 modules and place the binaries in the `build/firmware` folder. If you want to configure the build for a single platform create a local `pio_local.ni` file in the root directory (see example in `pio_local.ini_example`).
|
||||
|
||||
## 📢 **Libraries used**
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please report any security vulnerabilities using the [Contact Form](https://emsesp.org/About/#-contact).
|
||||
@@ -37,8 +37,8 @@
|
||||
"flash_size": "4MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 4194304,
|
||||
"use_1200bps_touch": false,
|
||||
"wait_for_upload_port": false,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
}
|
||||
],
|
||||
"dictionaries": ["project-words"],
|
||||
"caseSensitive": false,
|
||||
"ignorePaths": [
|
||||
"node_modules",
|
||||
"compile_commands.json",
|
||||
@@ -36,8 +35,6 @@
|
||||
"managed_components/**",
|
||||
"pnpm-*.yaml",
|
||||
"vite.config.ts",
|
||||
"lib/esp32-psram/**",
|
||||
"test/test_api/test_api.h",
|
||||
"lib_standalone/**"
|
||||
"lib/esp32-psram/**"
|
||||
]
|
||||
}
|
||||
@@ -1,228 +1,85 @@
|
||||
{
|
||||
"type": "systembackup",
|
||||
"version": "3.8.2",
|
||||
"date": "2026-03-29T13:28:15",
|
||||
"systembackup": [
|
||||
{
|
||||
"type": "settings",
|
||||
"Network": {
|
||||
"ssid": "",
|
||||
"bssid": "",
|
||||
"password": "",
|
||||
"hostname": "ems-esp",
|
||||
"static_ip_config": false,
|
||||
"bandwidth20": false,
|
||||
"nosleep": true,
|
||||
"enableMDNS": true,
|
||||
"enableCORS": false,
|
||||
"CORSOrigin": "*",
|
||||
"tx_power": 0
|
||||
},
|
||||
"AP": {
|
||||
"provision_mode": 2,
|
||||
"ssid": "ems-esp",
|
||||
"password": "ems-esp-neo",
|
||||
"channel": 1,
|
||||
"ssid_hidden": false,
|
||||
"max_clients": 4,
|
||||
"local_ip": "192.168.4.1",
|
||||
"gateway_ip": "192.168.4.1",
|
||||
"subnet_mask": "255.255.255.0"
|
||||
},
|
||||
"MQTT": {
|
||||
"enableTLS": false,
|
||||
"rootCA": "",
|
||||
"enabled": false,
|
||||
"host": "",
|
||||
"port": 1883,
|
||||
"base": "ems-esp",
|
||||
"username": "",
|
||||
"password": "",
|
||||
"client_id": "esp32-b8ffc9ec",
|
||||
"keep_alive": 60,
|
||||
"clean_session": false,
|
||||
"entity_format": 1,
|
||||
"publish_time_boiler": 10,
|
||||
"publish_time_thermostat": 10,
|
||||
"publish_time_solar": 10,
|
||||
"publish_time_mixer": 10,
|
||||
"publish_time_water": 10,
|
||||
"publish_time_other": 60,
|
||||
"publish_time_sensor": 10,
|
||||
"publish_time_heartbeat": 60,
|
||||
"mqtt_qos": 0,
|
||||
"mqtt_retain": false,
|
||||
"ha_enabled": false,
|
||||
"nested_format": 1,
|
||||
"discovery_prefix": "homeassistant",
|
||||
"discovery_type": 0,
|
||||
"ha_number_mode": 0,
|
||||
"publish_single": false,
|
||||
"publish_single2cmd": false,
|
||||
"send_response": false
|
||||
},
|
||||
"NTP": {
|
||||
"enabled": true,
|
||||
"server": "time.google.com",
|
||||
"tz_label": "Europe/Amsterdam",
|
||||
"tz_format": "CET-1CEST,M3.5.0,M10.5.0/3"
|
||||
},
|
||||
"Security": {
|
||||
"jwt_secret": "ems-esp-neo",
|
||||
"users": [
|
||||
{
|
||||
"username": "admin",
|
||||
"password": "admin",
|
||||
"admin": true
|
||||
},
|
||||
{
|
||||
"username": "guest",
|
||||
"password": "guest",
|
||||
"admin": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"Settings": {
|
||||
"version": "3.8.2",
|
||||
"board_profile": "E32V2_2",
|
||||
"platform": "ESP32",
|
||||
"locale": "en",
|
||||
"tx_mode": 1,
|
||||
"ems_bus_id": 11,
|
||||
"syslog_enabled": false,
|
||||
"syslog_level": 3,
|
||||
"trace_raw": false,
|
||||
"syslog_mark_interval": 0,
|
||||
"syslog_host": "",
|
||||
"syslog_port": 514,
|
||||
"boiler_heatingoff": false,
|
||||
"remote_timeout": 24,
|
||||
"remote_timeout_en": false,
|
||||
"shower_timer": false,
|
||||
"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": 32,
|
||||
"hide_led": false,
|
||||
"led_type": 1,
|
||||
"low_clock": false,
|
||||
"telnet_enabled": true,
|
||||
"notoken_api": false,
|
||||
"readonly_mode": false,
|
||||
"analog_enabled": true,
|
||||
"pbutton_gpio": 34,
|
||||
"solar_maxflow": 30,
|
||||
"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,
|
||||
"modbus_enabled": false,
|
||||
"modbus_port": 502,
|
||||
"modbus_max_clients": 10,
|
||||
"modbus_timeout": 300,
|
||||
"developer_mode": true,
|
||||
"email_enabled": false,
|
||||
"email_ssl": false,
|
||||
"email_starttls": true,
|
||||
"email_server": "smtp.example.net",
|
||||
"email_port": 587,
|
||||
"email_login": "",
|
||||
"email_pass": "",
|
||||
"email_sender": "ems-esp@example.net",
|
||||
"email_recp": "",
|
||||
"email_subject": "ems-esp notification"
|
||||
}
|
||||
"type": "settings",
|
||||
"Network": {
|
||||
"ssid": "my_wifi_ssid",
|
||||
"bssid": "",
|
||||
"password": "my_wifi_password",
|
||||
"hostname": "ems-esp"
|
||||
},
|
||||
{
|
||||
"type": "schedule",
|
||||
"Schedule": {
|
||||
"schedule": []
|
||||
}
|
||||
"AP": {
|
||||
"provision_mode": 2,
|
||||
"ssid": "ems-esp",
|
||||
"password": "ems-esp-neo",
|
||||
"channel": 1,
|
||||
"ssid_hidden": false,
|
||||
"max_clients": 4,
|
||||
"local_ip": "192.168.4.1",
|
||||
"gateway_ip": "192.168.4.1",
|
||||
"subnet_mask": "255.255.255.0"
|
||||
},
|
||||
{
|
||||
"type": "customizations",
|
||||
"Customizations": {
|
||||
"ts": [
|
||||
{
|
||||
"id": "28_1767_7B13_2502",
|
||||
"name": "gateway_temperature",
|
||||
"offset": 0,
|
||||
"is_system": true
|
||||
}
|
||||
],
|
||||
"as": [
|
||||
{
|
||||
"gpio": 39,
|
||||
"name": "core_voltage",
|
||||
"offset": 0,
|
||||
"factor": 0.003771,
|
||||
"uom": 23,
|
||||
"type": 3,
|
||||
"is_system": true
|
||||
},
|
||||
{
|
||||
"gpio": 36,
|
||||
"name": "supply_voltage",
|
||||
"offset": 0,
|
||||
"factor": 0.017,
|
||||
"uom": 23,
|
||||
"type": 3,
|
||||
"is_system": true
|
||||
},
|
||||
{
|
||||
"gpio": 2,
|
||||
"name": "led",
|
||||
"offset": 0,
|
||||
"factor": 1,
|
||||
"uom": 0,
|
||||
"type": 6,
|
||||
"is_system": true
|
||||
}
|
||||
],
|
||||
"masked_entities": []
|
||||
}
|
||||
"MQTT": {
|
||||
"enableTLS": false,
|
||||
"rootCA": "",
|
||||
"enabled": false,
|
||||
"host": "127.0.0.1",
|
||||
"port": 1883,
|
||||
"base": "ems-esp",
|
||||
"username": "username",
|
||||
"password": "password",
|
||||
"client_id": "ems-esp",
|
||||
"entity_format": 1,
|
||||
"publish_time_boiler": 10,
|
||||
"publish_time_thermostat": 10,
|
||||
"publish_time_solar": 10,
|
||||
"publish_time_mixer": 10,
|
||||
"publish_time_water": 10,
|
||||
"publish_time_other": 60,
|
||||
"publish_time_sensor": 10,
|
||||
"publish_time_heartbeat": 60,
|
||||
"mqtt_qos": 0,
|
||||
"mqtt_retain": false,
|
||||
"ha_enabled": false,
|
||||
"nested_format": 1,
|
||||
"discovery_prefix": "homeassistant",
|
||||
"discovery_type": 0,
|
||||
"publish_single": false,
|
||||
"publish_single2cmd": false,
|
||||
"send_response": false
|
||||
},
|
||||
{
|
||||
"type": "entities",
|
||||
"Entities": {
|
||||
"entities": []
|
||||
}
|
||||
"NTP": {
|
||||
"enabled": true,
|
||||
"server": "time.google.com",
|
||||
"tz_label": "Europe/Amsterdam",
|
||||
"tz_format": "CET-1CEST,M3.5.0,M10.5.0/3"
|
||||
},
|
||||
{
|
||||
"type": "modules",
|
||||
"Modules": {
|
||||
"modules": []
|
||||
}
|
||||
"Security": {
|
||||
"jwt_secret": "ems-esp-neo",
|
||||
"users": [
|
||||
{
|
||||
"username": "admin",
|
||||
"password": "admin",
|
||||
"admin": true
|
||||
},
|
||||
{
|
||||
"username": "guest",
|
||||
"password": "guest",
|
||||
"admin": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "customSupport",
|
||||
"Support": {
|
||||
"html": [
|
||||
"This product is installed and managed by:",
|
||||
"",
|
||||
"<b>Bosch Installer Example</b>",
|
||||
"",
|
||||
"Nefit Road 12",
|
||||
"1234 AB Amsterdam",
|
||||
"Phone: +31 123 456 789",
|
||||
"email: support@boschinstaller.nl",
|
||||
"",
|
||||
"For help and questions please <a target='_blank' href='https://emsesp.org'>contact</a> your installer."
|
||||
],
|
||||
"img_url": "https://emsesp.org/media/images/designer.png"
|
||||
}
|
||||
"Settings": {
|
||||
"board_profile": "S3",
|
||||
"locale": "en",
|
||||
"tx_mode": 1,
|
||||
"ems_bus_id": 11,
|
||||
"boiler_heatingoff": false,
|
||||
"hide_led": true,
|
||||
"telnet_enabled": true,
|
||||
"notoken_api": false,
|
||||
"analog_enabled": true,
|
||||
"fahrenheit": false,
|
||||
"bool_format": 1,
|
||||
"bool_dashboard": 1,
|
||||
"enum_format": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@ telegram_type_id,name,is_fetched
|
||||
0x19,UBAMonitorSlow,
|
||||
0x1A,UBASetPoints,
|
||||
0x1C,UBAMaintenanceStatus,
|
||||
0x1E,HydrTemp,
|
||||
0x1E,WM10TempMessage,
|
||||
0x23,JunkersSetMixer,fetched
|
||||
0x27,UBASettingsWW,fetched
|
||||
0x28,WeatherComp,fetched
|
||||
@@ -72,12 +72,11 @@ telegram_type_id,name,is_fetched
|
||||
0xE6,UBAParametersPlus,fetched
|
||||
0xE9,UBAMonitorWWPlus,
|
||||
0xEA,UBAParameterWWPlus,fetched
|
||||
0xEB,PumpKick,fetched
|
||||
0x0101,ISM1Set,fetched
|
||||
0x0103,ISM1StatusMessage,fetched
|
||||
0x0104,ISM2StatusMessage,
|
||||
0x010C,IPMStatusMessage,
|
||||
0x011E,IPMTempMessage,
|
||||
0x011E,JunkersDisp,fetched
|
||||
0x012E,HPEnergy1,
|
||||
0x013B,HPEnergy2,
|
||||
0x0165,JunkersSet,
|
||||
@@ -113,9 +112,9 @@ telegram_type_id,name,is_fetched
|
||||
0x02A1,RC300Curves,
|
||||
0x02A2,RC300Curves,
|
||||
0x02A5,RC300Monitor,fetched
|
||||
0x02A6,CRFMonitor,
|
||||
0x02A6,RC300Monitor,
|
||||
0x02A7,RC300Monitor,
|
||||
0x02A8,CRFMonitor,
|
||||
0x02A8,RC300Monitor,
|
||||
0x02A9,RC300Monitor,
|
||||
0x02AA,RC300Monitor,
|
||||
0x02AB,RC300Monitor,
|
||||
@@ -198,7 +197,7 @@ telegram_type_id,name,is_fetched
|
||||
0x04A2,HpInput,fetched
|
||||
0x04A5,HPFan,fetched
|
||||
0x04A7,HPPowerLimit,fetched
|
||||
0x04AA,HPPower,
|
||||
0x04AA,HPPower2,fetched
|
||||
0x04AE,HPEnergy,fetched
|
||||
0x04AF,HPMeters,fetched
|
||||
0x055C,VentilationSet,fetched
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"adapter": "react",
|
||||
"baseLocale": "pl",
|
||||
"$schema": "https://unpkg.com/typesafe-i18n@5.27.1/schema/typesafe-i18n.json"
|
||||
"$schema": "https://unpkg.com/typesafe-i18n@5.26.2/schema/typesafe-i18n.json"
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
// @ts-check
|
||||
import eslint from '@eslint/js';
|
||||
import prettierConfig from 'eslint-config-prettier';
|
||||
import { defineConfig } from 'eslint/config';
|
||||
import tseslint from 'typescript-eslint';
|
||||
|
||||
export default defineConfig(
|
||||
export default tseslint.config(
|
||||
eslint.configs.recommended,
|
||||
...tseslint.configs.recommendedTypeChecked,
|
||||
prettierConfig,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "EMS-ESP",
|
||||
"version": "3.8.2",
|
||||
"version": "3.8.0",
|
||||
"description": "EMS-ESP WebUI",
|
||||
"homepage": "https://emsesp.org",
|
||||
"author": "proddy, emsesp.org",
|
||||
@@ -12,7 +12,7 @@
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"build-hosted": "typesafe-i18n --no-watch && vite build --mode hosted",
|
||||
"build-hosted": "typesafe-i18n && vite build --mode hosted",
|
||||
"mock-rest": "bun --watch ../mock-api/restServer.ts",
|
||||
"preview-standalone": "typesafe-i18n --no-watch && vite build && concurrently -c \"auto\" \"pnpm:mock-rest\" \"vite preview\"",
|
||||
"standalone": "concurrently -c \"auto\" \"typesafe-i18n\" \"pnpm:mock-rest\" \"vite dev\"",
|
||||
@@ -26,46 +26,46 @@
|
||||
"@alova/adapter-xhr": "2.3.1",
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@emotion/styled": "^11.14.1",
|
||||
"@mui/icons-material": "^9.0.0",
|
||||
"@mui/material": "^9.0.0",
|
||||
"@preact/compat": "^18.3.2",
|
||||
"@mui/icons-material": "^7.3.6",
|
||||
"@mui/material": "^7.3.6",
|
||||
"@preact/compat": "^18.3.1",
|
||||
"@table-library/react-table-library": "4.1.15",
|
||||
"alova": "3.5.1",
|
||||
"alova": "3.4.1",
|
||||
"async-validator": "^4.2.5",
|
||||
"etag": "^1.8.1",
|
||||
"formidable": "^3.5.4",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"magic-string": "^0.30.21",
|
||||
"mime-types": "^3.0.2",
|
||||
"preact": "^10.29.1",
|
||||
"react": "^19.2.5",
|
||||
"react-dom": "^19.2.5",
|
||||
"react-icons": "^5.6.0",
|
||||
"react-router": "^7.14.1",
|
||||
"preact": "^10.28.1",
|
||||
"react": "^19.2.3",
|
||||
"react-dom": "^19.2.3",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-router": "^7.11.0",
|
||||
"react-toastify": "^11.0.5",
|
||||
"typesafe-i18n": "^5.27.1",
|
||||
"typescript": "^6.0.2"
|
||||
"typesafe-i18n": "^5.26.2",
|
||||
"typescript": "^5.9.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.29.0",
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@preact/compat": "^18.3.2",
|
||||
"@preact/preset-vite": "^2.10.5",
|
||||
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
|
||||
"@types/node": "^25.6.0",
|
||||
"@types/react": "^19.2.14",
|
||||
"@babel/core": "^7.28.5",
|
||||
"@eslint/js": "^9.39.2",
|
||||
"@preact/compat": "^18.3.1",
|
||||
"@preact/preset-vite": "^2.10.2",
|
||||
"@trivago/prettier-plugin-sort-imports": "^6.0.0",
|
||||
"@types/node": "^25.0.3",
|
||||
"@types/react": "^19.2.7",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"axe-core": "^4.11.3",
|
||||
"axe-core": "^4.11.0",
|
||||
"concurrently": "^9.2.1",
|
||||
"eslint": "^10.2.0",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"prettier": "^3.8.3",
|
||||
"rollup-plugin-visualizer": "^7.0.1",
|
||||
"terser": "^5.46.1",
|
||||
"typescript-eslint": "^8.58.2",
|
||||
"vite": "^8.0.8",
|
||||
"prettier": "^3.7.4",
|
||||
"rollup-plugin-visualizer": "^6.0.5",
|
||||
"terser": "^5.44.1",
|
||||
"typescript-eslint": "^8.51.0",
|
||||
"vite": "^7.3.0",
|
||||
"vite-plugin-imagemin": "^0.6.1",
|
||||
"vite-tsconfig-paths": "^6.1.1"
|
||||
"vite-tsconfig-paths": "^6.0.3"
|
||||
},
|
||||
"packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319"
|
||||
"packageManager": "pnpm@10.27.0+sha512.72d699da16b1179c14ba9e64dc71c9a40988cbdc65c264cb0e489db7de917f20dcf4d64d8723625f2969ba52d4b7e2a1170682d9ac2a5dcaeaab732b7e16f04a"
|
||||
}
|
||||
|
||||
6612
interface/pnpm-lock.yaml
generated
6612
interface/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,6 @@ import { toast } from 'react-toastify';
|
||||
|
||||
import ForwardIcon from '@mui/icons-material/Forward';
|
||||
import { Box, Button, Paper, Typography } from '@mui/material';
|
||||
import type { Theme } from '@mui/material/styles';
|
||||
|
||||
import * as AuthenticationApi from 'components/routing/authentication';
|
||||
import { useRequest } from 'alova/client';
|
||||
@@ -37,7 +36,7 @@ const SignIn = memo(() => {
|
||||
{
|
||||
immediate: false
|
||||
}
|
||||
).onSuccess((response: { data: { access_token: string } }) => {
|
||||
).onSuccess((response) => {
|
||||
if (response.data) {
|
||||
authenticationContext.signIn(response.data.access_token);
|
||||
}
|
||||
@@ -79,6 +78,7 @@ const SignIn = memo(() => {
|
||||
}
|
||||
}, [signInRequest, signIn, LL]);
|
||||
|
||||
// Memoize callback to prevent recreation on every render
|
||||
const submitOnEnter = useMemo(() => onEnterCallback(signIn), [signIn]);
|
||||
|
||||
// get rid of scrollbar
|
||||
@@ -92,15 +92,13 @@ const SignIn = memo(() => {
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={(theme: Theme) => ({
|
||||
display: 'flex',
|
||||
height: '100vh',
|
||||
margin: 'auto',
|
||||
padding: 2,
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'column',
|
||||
maxWidth: theme.breakpoints.values.sm
|
||||
})}
|
||||
display="flex"
|
||||
height="100vh"
|
||||
margin="auto"
|
||||
padding={2}
|
||||
justifyContent="center"
|
||||
flexDirection="column"
|
||||
maxWidth={(theme) => theme.breakpoints.values.sm}
|
||||
>
|
||||
<Paper
|
||||
sx={(theme) => ({
|
||||
@@ -113,18 +111,16 @@ const SignIn = memo(() => {
|
||||
width: '100%'
|
||||
})}
|
||||
>
|
||||
<Typography sx={{ mb: 1 }} variant="h4">
|
||||
<Typography mb={1} variant="h4">
|
||||
{PROJECT_NAME}
|
||||
</Typography>
|
||||
<LanguageSelector />
|
||||
<Box
|
||||
sx={{
|
||||
mt: 1,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 1,
|
||||
alignItems: 'center'
|
||||
}}
|
||||
mt={1}
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
gap={1}
|
||||
alignItems="center"
|
||||
>
|
||||
<ValidatedTextField
|
||||
fieldErrors={fieldErrors || {}}
|
||||
|
||||
@@ -310,15 +310,13 @@ const CustomEntities = () => {
|
||||
/>
|
||||
)}
|
||||
</Cell>
|
||||
<Cell>{ei.ram > 0 ? '' : showHex(ei.device_id as number, 2)}</Cell>
|
||||
<Cell>{ei.ram > 0 ? '' : showHex(ei.type_id as number, 3)}</Cell>
|
||||
<Cell>{ei.ram > 0 ? '' : ei.offset}</Cell>
|
||||
<Cell>
|
||||
{ei.ram === 1
|
||||
? 'RAM'
|
||||
: ei.ram === 2
|
||||
? 'NVS'
|
||||
: DeviceValueTypeNames[ei.value_type]}
|
||||
{ei.ram === 1 ? '' : showHex(ei.device_id as number, 2)}
|
||||
</Cell>
|
||||
<Cell>{ei.ram === 1 ? '' : showHex(ei.type_id as number, 3)}</Cell>
|
||||
<Cell>{ei.ram === 1 ? '' : ei.offset}</Cell>
|
||||
<Cell>
|
||||
{ei.ram === 1 ? 'RAM' : DeviceValueTypeNames[ei.value_type]}
|
||||
</Cell>
|
||||
<Cell>{formatValue(ei.value, ei.uom)}</Cell>
|
||||
</Row>
|
||||
@@ -343,9 +341,9 @@ const CustomEntities = () => {
|
||||
return (
|
||||
<SectionContent>
|
||||
{blocker ? <BlockNavigation blocker={blocker} /> : null}
|
||||
<Typography sx={{ mb: 2 }} color="warning" variant="body1">
|
||||
{LL.ENTITIES_HELP_1()}.
|
||||
</Typography>
|
||||
<Box mb={2} color="warning.main">
|
||||
<Typography variant="body1">{LL.ENTITIES_HELP_1()}.</Typography>
|
||||
</Box>
|
||||
|
||||
{renderEntity()}
|
||||
|
||||
@@ -361,8 +359,8 @@ const CustomEntities = () => {
|
||||
/>
|
||||
)}
|
||||
|
||||
<Box sx={{ mt: 2, display: 'flex', flexWrap: 'wrap' }}>
|
||||
<Box sx={{ flexGrow: 1 }}>
|
||||
<Box mt={2} display="flex" flexWrap="wrap">
|
||||
<Box flexGrow={1}>
|
||||
{numChanges > 0 && (
|
||||
<ButtonRow>
|
||||
<Button
|
||||
@@ -384,7 +382,7 @@ const CustomEntities = () => {
|
||||
</ButtonRow>
|
||||
)}
|
||||
</Box>
|
||||
<Box sx={{ flexWrap: 'nowrap', whiteSpace: 'nowrap' }}>
|
||||
<Box flexWrap="nowrap" whiteSpace="nowrap">
|
||||
<Button
|
||||
startIcon={<AddIcon />}
|
||||
variant="outlined"
|
||||
|
||||
@@ -7,7 +7,7 @@ import DoneIcon from '@mui/icons-material/Done';
|
||||
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
|
||||
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
|
||||
import InsertCommentOutlinedIcon from '@mui/icons-material/InsertCommentOutlined';
|
||||
import RemoveIcon from '@mui/icons-material/RemoveCircleOutlined';
|
||||
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -178,7 +178,7 @@ const CustomEntitiesDialog = ({
|
||||
onChange={updateFormValue}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid sx={{ mt: 3 }}>
|
||||
<Grid mt={3}>
|
||||
<BlockFormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
@@ -205,10 +205,9 @@ const CustomEntitiesDialog = ({
|
||||
>
|
||||
<MenuItem value={0}>EMS-{LL.VALUE(1)}</MenuItem>
|
||||
<MenuItem value={1}>RAM-{LL.VALUE(1)}</MenuItem>
|
||||
<MenuItem value={2}>NVS-{LL.VALUE(1)}</MenuItem>
|
||||
</TextField>
|
||||
</Grid>
|
||||
{editItem.ram > 0 && (
|
||||
{editItem.ram === 1 && (
|
||||
<>
|
||||
<Grid>
|
||||
<TextField
|
||||
@@ -238,7 +237,7 @@ const CustomEntitiesDialog = ({
|
||||
)}
|
||||
{editItem.ram === 0 && (
|
||||
<>
|
||||
<Grid sx={{ mt: 3 }}>
|
||||
<Grid mt={3}>
|
||||
<BlockFormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
@@ -404,7 +403,7 @@ const CustomEntitiesDialog = ({
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
{!creating && (
|
||||
<Box sx={{ flexGrow: 1 }}>
|
||||
<Box flexGrow={1}>
|
||||
<Button
|
||||
startIcon={<RemoveIcon />}
|
||||
variant="outlined"
|
||||
|
||||
@@ -111,14 +111,13 @@ const Customizations = () => {
|
||||
const [selectedDeviceTypeNameURL, setSelectedDeviceTypeNameURL] =
|
||||
useState<string>(''); // needed for API URL
|
||||
const [selectedDeviceName, setSelectedDeviceName] = useState<string>('');
|
||||
const [selectedDeviceBrand, setSelectedDeviceBrand] = useState<string>('');
|
||||
|
||||
const { send: sendResetCustomizations } = useRequest(resetCustomizations(), {
|
||||
immediate: false
|
||||
});
|
||||
|
||||
const { send: sendDeviceName } = useRequest(
|
||||
(data: { id: number; name: string; brand: string }) => writeDeviceName(data),
|
||||
(data: { id: number; name: string }) => writeDeviceName(data),
|
||||
{
|
||||
immediate: false
|
||||
}
|
||||
@@ -268,7 +267,6 @@ const Customizations = () => {
|
||||
if (device) {
|
||||
setSelectedDeviceTypeNameURL(device.url || '');
|
||||
setSelectedDeviceName(device.n);
|
||||
setSelectedDeviceBrand(device.b);
|
||||
}
|
||||
setNumChanges(0);
|
||||
setRestartNeeded(false);
|
||||
@@ -444,11 +442,7 @@ const Customizations = () => {
|
||||
}, [devices, deviceEntities, selectedDevice, sendCustomizationEntities, LL]);
|
||||
|
||||
const renameDevice = useCallback(async () => {
|
||||
await sendDeviceName({
|
||||
id: selectedDevice,
|
||||
name: selectedDeviceName,
|
||||
brand: selectedDeviceBrand
|
||||
})
|
||||
await sendDeviceName({ id: selectedDevice, name: selectedDeviceName })
|
||||
.then(() => {
|
||||
toast.success(LL.UPDATED_OF(LL.NAME(1)));
|
||||
})
|
||||
@@ -459,42 +453,24 @@ const Customizations = () => {
|
||||
setRename(false);
|
||||
await fetchCoreData();
|
||||
});
|
||||
}, [
|
||||
selectedDevice,
|
||||
selectedDeviceName,
|
||||
selectedDeviceBrand,
|
||||
sendDeviceName,
|
||||
LL,
|
||||
fetchCoreData
|
||||
]);
|
||||
}, [selectedDevice, selectedDeviceName, sendDeviceName, LL, fetchCoreData]);
|
||||
|
||||
const renderDeviceList = () => (
|
||||
<>
|
||||
<Typography sx={{ mb: 1 }} color="warning" variant="body1">
|
||||
{LL.CUSTOMIZATIONS_HELP_1()}.
|
||||
</Typography>
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 2 }}>
|
||||
<Box mb={1} color="warning.main">
|
||||
<Typography variant="body1">{LL.CUSTOMIZATIONS_HELP_1()}.</Typography>
|
||||
</Box>
|
||||
<Box display="flex" flexWrap="wrap" alignItems="center" gap={2}>
|
||||
{rename ? (
|
||||
<>
|
||||
<TextField
|
||||
name="device"
|
||||
label={LL.EMS_DEVICE()}
|
||||
style={{ minWidth: '48%' }}
|
||||
variant="outlined"
|
||||
value={selectedDeviceName}
|
||||
onChange={(e) => setSelectedDeviceName(e.target.value)}
|
||||
margin="normal"
|
||||
/>
|
||||
<TextField
|
||||
name="brand"
|
||||
label={LL.BRAND()}
|
||||
style={{ minWidth: '48%' }}
|
||||
variant="outlined"
|
||||
value={selectedDeviceBrand}
|
||||
onChange={(e) => setSelectedDeviceBrand(e.target.value)}
|
||||
margin="normal"
|
||||
/>
|
||||
</>
|
||||
<TextField
|
||||
name="device"
|
||||
label={LL.EMS_DEVICE()}
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={selectedDeviceName}
|
||||
onChange={(e) => setSelectedDeviceName(e.target.value)}
|
||||
margin="normal"
|
||||
/>
|
||||
) : (
|
||||
<TextField
|
||||
name="device"
|
||||
@@ -570,22 +546,27 @@ const Customizations = () => {
|
||||
const renderDeviceData = () => {
|
||||
return (
|
||||
<>
|
||||
<Typography sx={{ mt: 1, mb: 1 }} color="warning" variant="body2">
|
||||
<OptionIcon type="favorite" isSet={true} />={LL.CUSTOMIZATIONS_HELP_2()}
|
||||
|
||||
<OptionIcon type="readonly" isSet={true} />={LL.CUSTOMIZATIONS_HELP_3()}
|
||||
|
||||
<OptionIcon type="api_mqtt_exclude" isSet={true} />=
|
||||
{LL.CUSTOMIZATIONS_HELP_4()}
|
||||
<OptionIcon type="web_exclude" isSet={true} />={LL.CUSTOMIZATIONS_HELP_5()}
|
||||
|
||||
<OptionIcon type="deleted" isSet={true} />={LL.CUSTOMIZATIONS_HELP_6()}
|
||||
</Typography>
|
||||
<Box color="warning.main">
|
||||
<Typography variant="body2" mt={1} mb={1}>
|
||||
<OptionIcon type="favorite" isSet={true} />={LL.CUSTOMIZATIONS_HELP_2()}
|
||||
|
||||
<OptionIcon type="readonly" isSet={true} />={LL.CUSTOMIZATIONS_HELP_3()}
|
||||
|
||||
<OptionIcon type="api_mqtt_exclude" isSet={true} />=
|
||||
{LL.CUSTOMIZATIONS_HELP_4()}
|
||||
<OptionIcon type="web_exclude" isSet={true} />=
|
||||
{LL.CUSTOMIZATIONS_HELP_5()}
|
||||
<OptionIcon type="deleted" isSet={true} />={LL.CUSTOMIZATIONS_HELP_6()}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Grid
|
||||
container
|
||||
mb={1}
|
||||
mt={0}
|
||||
spacing={2}
|
||||
direction="row"
|
||||
sx={{ mb: 1, mt: 0, justifyContent: 'flex-start', alignItems: 'center' }}
|
||||
justifyContent="flex-start"
|
||||
alignItems="center"
|
||||
>
|
||||
<Grid>
|
||||
<TextField
|
||||
@@ -774,8 +755,8 @@ const Customizations = () => {
|
||||
</Button>
|
||||
</MessageBox>
|
||||
) : (
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap' }}>
|
||||
<Box sx={{ flexGrow: 1 }}>
|
||||
<Box display="flex" flexWrap="wrap">
|
||||
<Box flexGrow={1}>
|
||||
{numChanges !== 0 && (
|
||||
<ButtonRow>
|
||||
<Button
|
||||
@@ -807,12 +788,10 @@ const Customizations = () => {
|
||||
</>
|
||||
);
|
||||
|
||||
return restarting ? (
|
||||
<SystemMonitor />
|
||||
) : (
|
||||
return (
|
||||
<SectionContent>
|
||||
{blocker ? <BlockNavigation blocker={blocker} /> : null}
|
||||
{renderContent()}
|
||||
{restarting ? <SystemMonitor /> : renderContent()}
|
||||
{selectedDeviceEntity && (
|
||||
<SettingsCustomizationsDialog
|
||||
open={dialogOpen}
|
||||
|
||||
@@ -37,7 +37,7 @@ interface LabelValueProps {
|
||||
|
||||
const LabelValue = memo(({ label, value }: LabelValueProps) => (
|
||||
<Grid container direction="row">
|
||||
<Typography variant="body2" color="warning">
|
||||
<Typography variant="body2" color="warning.main">
|
||||
{label}:
|
||||
</Typography>
|
||||
<Typography variant="body2">{value}</Typography>
|
||||
@@ -131,7 +131,7 @@ const CustomizationsDialog = ({
|
||||
/>
|
||||
<LabelValue label={LL.WRITEABLE()} value={writeableIcon} />
|
||||
|
||||
<Box sx={{ mt: 1, mb: 2 }}>
|
||||
<Box mt={1} mb={2}>
|
||||
<EntityMaskToggle onUpdate={updateDeviceEntity} de={editItem} />
|
||||
</Box>
|
||||
|
||||
@@ -172,7 +172,7 @@ const CustomizationsDialog = ({
|
||||
</Grid>
|
||||
|
||||
{error && (
|
||||
<Typography sx={{ mt: 2 }} variant="body2" color="error">
|
||||
<Typography variant="body2" color="error" mt={2}>
|
||||
Error: Check min and max values
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { toast } from 'react-toastify';
|
||||
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
||||
import EditIcon from '@mui/icons-material/Edit';
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import HelpOutlineIcon from '@mui/icons-material/HelpOutlined';
|
||||
import HelpOutlineIcon from '@mui/icons-material/HelpOutline';
|
||||
import UnfoldLessIcon from '@mui/icons-material/UnfoldLess';
|
||||
import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore';
|
||||
import {
|
||||
@@ -262,8 +262,12 @@ const Dashboard = memo(() => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{!data.connected && (
|
||||
<MessageBox level="error" message={LL.EMS_BUS_WARNING()} />
|
||||
)}
|
||||
|
||||
{data.connected && data.nodes.length > 0 && !hasFavEntities && (
|
||||
<MessageBox sx={{ mb: 2 }} level="warning">
|
||||
<MessageBox mb={2} level="warning">
|
||||
<Typography>
|
||||
{LL.NO_DATA_1()}
|
||||
<Link to="/customizations" style={{ color: 'white' }}>
|
||||
@@ -280,12 +284,10 @@ const Dashboard = memo(() => {
|
||||
)}
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
flexWrap: 'nowrap',
|
||||
whiteSpace: 'nowrap'
|
||||
}}
|
||||
display="flex"
|
||||
justifyContent="flex-end"
|
||||
flexWrap="nowrap"
|
||||
whiteSpace="nowrap"
|
||||
>
|
||||
<ToggleButtonGroup
|
||||
size="small"
|
||||
@@ -308,7 +310,7 @@ const Dashboard = memo(() => {
|
||||
</Box>
|
||||
|
||||
{data.nodes.length > 0 ? (
|
||||
<Box sx={{ mt: 1, justifyContent: 'center', flexDirection: 'column' }}>
|
||||
<Box mt={1} justifyContent="center" flexDirection="column">
|
||||
<IconContext.Provider
|
||||
value={{
|
||||
color: 'lightblue',
|
||||
@@ -375,8 +377,13 @@ const Dashboard = memo(() => {
|
||||
</IconContext.Provider>
|
||||
</Box>
|
||||
) : (
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
<Typography sx={{ mt: 1 }} color="warning" variant="body1">
|
||||
<Box
|
||||
display="flex"
|
||||
// justifyContent="flex-end"
|
||||
// flexWrap="nowrap"
|
||||
// whiteSpace="nowrap"
|
||||
>
|
||||
<Typography mt={1} color="warning.main" variant="body1">
|
||||
no data
|
||||
</Typography>
|
||||
<Tooltip title={LL.DASHBOARD_1()}>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { memo } from 'react';
|
||||
import type { IconType } from 'react-icons';
|
||||
import { AiOutlineAlert, AiOutlineControl, AiOutlineGateway } from 'react-icons/ai';
|
||||
import { CgSmartHomeBoiler } from 'react-icons/cg';
|
||||
import { FaSolarPanel } from 'react-icons/fa';
|
||||
@@ -16,9 +15,14 @@ import { PiFan, PiGauge } from 'react-icons/pi';
|
||||
import { TiFlowSwitch, TiThermometer } from 'react-icons/ti';
|
||||
import { VscVmConnect } from 'react-icons/vsc';
|
||||
|
||||
import type { SvgIconProps } from '@mui/material';
|
||||
|
||||
import { DeviceType } from './types';
|
||||
|
||||
const deviceIconLookup: Record<DeviceType, IconType | null> = {
|
||||
const deviceIconLookup: Record<
|
||||
DeviceType,
|
||||
React.ComponentType<SvgIconProps> | null
|
||||
> = {
|
||||
[DeviceType.TEMPERATURESENSOR]: TiThermometer,
|
||||
[DeviceType.ANALOGSENSOR]: PiGauge,
|
||||
[DeviceType.BOILER]: CgSmartHomeBoiler,
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
useState
|
||||
} from 'react';
|
||||
import { IconContext } from 'react-icons';
|
||||
import { Link, useNavigate } from 'react-router';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
|
||||
@@ -534,19 +534,9 @@ const Devices = memo(() => {
|
||||
const renderCoreData = () => (
|
||||
<>
|
||||
{!coreData.connected ? (
|
||||
<MessageBox level="error" message={LL.EMS_BUS_WARNING() + '.'}>
|
||||
(
|
||||
<Link
|
||||
target="_blank"
|
||||
to="https://docs.emsesp.org/Troubleshooting#ems-bus-is-not-connecting"
|
||||
style={{ color: 'white' }}
|
||||
>
|
||||
{LL.ONLINE_HELP()}
|
||||
</Link>
|
||||
)
|
||||
</MessageBox>
|
||||
<MessageBox level="error" message={LL.EMS_BUS_WARNING()} />
|
||||
) : (
|
||||
<Box sx={{ justifyContent: 'center', flexDirection: 'column' }}>
|
||||
<Box justifyContent="center" flexDirection="column">
|
||||
<IconContext.Provider
|
||||
value={{
|
||||
color: 'lightblue',
|
||||
@@ -670,12 +660,12 @@ const Devices = memo(() => {
|
||||
}}
|
||||
>
|
||||
<Box sx={{ p: 1 }}>
|
||||
<Grid container sx={{ justifyContent: 'space-between' }}>
|
||||
<Typography noWrap variant="subtitle1" color="warning">
|
||||
<Grid container justifyContent="space-between">
|
||||
<Typography noWrap variant="subtitle1" color="warning.main">
|
||||
{deviceInfo.n} (
|
||||
{deviceInfo.tn})
|
||||
</Typography>
|
||||
<Grid sx={{ justifyContent: 'flex-end' }}>
|
||||
<Grid justifyContent="flex-end">
|
||||
<ButtonTooltip title={LL.CLOSE()}>
|
||||
<IconButton onClick={resetDeviceSelect} aria-label={LL.CLOSE()}>
|
||||
<HighlightOffIcon color="primary" sx={{ fontSize: 18 }} />
|
||||
|
||||
@@ -128,9 +128,9 @@ const DevicesDialog = ({
|
||||
<Dialog sx={dialogStyle} open={open} onClose={onClose}>
|
||||
<DialogTitle>{dialogTitle}</DialogTitle>
|
||||
<DialogContent dividers>
|
||||
<Typography sx={{ mb: 2 }} color="warning" variant="body2">
|
||||
{editItem.id.slice(2)}
|
||||
</Typography>
|
||||
<Box color="warning.main" mb={2}>
|
||||
<Typography variant="body2">{editItem.id.slice(2)}</Typography>
|
||||
</Box>
|
||||
<Grid container>
|
||||
<Grid size={12}>
|
||||
{editItem.l ? (
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
Box,
|
||||
Button,
|
||||
Divider,
|
||||
Grid,
|
||||
Link,
|
||||
List,
|
||||
ListItem,
|
||||
@@ -43,7 +42,7 @@ interface CustomSupport {
|
||||
html: string | null;
|
||||
}
|
||||
|
||||
const DEFAULT_IMAGE_URL = 'https://emsesp.org/media/images/installer.jpeg';
|
||||
const DEFAULT_IMAGE_URL = 'https://emsesp.org/_media/images/installer.jpeg';
|
||||
|
||||
const SUPPORT_BOX_STYLES: SxProps<Theme> = {
|
||||
borderRadius: 3,
|
||||
@@ -72,6 +71,7 @@ const HelpComponent = () => {
|
||||
});
|
||||
const [imgError, setImgError] = useState<boolean>(false);
|
||||
|
||||
// Memoize the request method to prevent re-creation on every render
|
||||
const getCustomSupportMethod = useMemo(
|
||||
() => callAction({ action: 'getCustomSupport' }),
|
||||
[]
|
||||
@@ -120,7 +120,7 @@ const HelpComponent = () => {
|
||||
label: () => LL.HELP_INFORMATION_1()
|
||||
},
|
||||
{
|
||||
href: 'https://discord.gg/GP9DPSgeJq',
|
||||
href: 'https://discord.gg/3J3GgnzpyT',
|
||||
icon: <CommentIcon />,
|
||||
label: () => LL.HELP_INFORMATION_2()
|
||||
},
|
||||
@@ -146,9 +146,11 @@ const HelpComponent = () => {
|
||||
<SectionContent>
|
||||
{customSupport.html && (
|
||||
<Stack
|
||||
padding={1}
|
||||
mb={2}
|
||||
direction="row"
|
||||
divider={<Divider orientation="vertical" flexItem />}
|
||||
sx={{ padding: 1, mb: 2, ...SUPPORT_BOX_STYLES }}
|
||||
sx={SUPPORT_BOX_STYLES}
|
||||
>
|
||||
<Typography variant="subtitle1">
|
||||
<div dangerouslySetInnerHTML={{ __html: customSupport.html }} />
|
||||
@@ -183,9 +185,9 @@ const HelpComponent = () => {
|
||||
</List>
|
||||
)}
|
||||
|
||||
<Grid container spacing={2} sx={{ mt: 2, alignItems: 'center' }}>
|
||||
<Typography sx={{ mb: 1 }} color="warning" variant="body1">
|
||||
{LL.HELP_INFORMATION_4()}:
|
||||
<Box p={2} color="warning.main">
|
||||
<Typography mb={1} variant="body1">
|
||||
{LL.HELP_INFORMATION_4()}.
|
||||
</Typography>
|
||||
<Button
|
||||
startIcon={<DownloadIcon />}
|
||||
@@ -195,11 +197,11 @@ const HelpComponent = () => {
|
||||
>
|
||||
{LL.SUPPORT_INFORMATION(0)}
|
||||
</Button>
|
||||
</Grid>
|
||||
</Box>
|
||||
|
||||
<Divider sx={{ mt: 4 }} />
|
||||
|
||||
<Typography color="white" variant="subtitle1" align="center" sx={{ mt: 1 }}>
|
||||
<Typography color="white" variant="subtitle1" align="center" mt={1}>
|
||||
©
|
||||
<Link
|
||||
target="_blank"
|
||||
|
||||
@@ -186,9 +186,9 @@ const Modules = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Typography sx={{ mb: 2 }} color="warning" variant="body1">
|
||||
{LL.MODULES_DESCRIPTION()}.
|
||||
</Typography>
|
||||
<Box mb={2} color="warning.main">
|
||||
<Typography variant="body1">{LL.MODULES_DESCRIPTION()}.</Typography>
|
||||
</Box>
|
||||
<Table
|
||||
data={{ nodes: modules }}
|
||||
theme={modules_theme}
|
||||
@@ -236,8 +236,8 @@ const Modules = () => {
|
||||
)}
|
||||
</Table>
|
||||
|
||||
<Box sx={{ mt: 1, display: 'flex', flexWrap: 'wrap' }}>
|
||||
<Box sx={{ flexGrow: 1 }}>
|
||||
<Box mt={1} display="flex" flexWrap="wrap">
|
||||
<Box flexGrow={1}>
|
||||
{numChanges !== 0 && (
|
||||
<ButtonRow>
|
||||
<Button
|
||||
|
||||
@@ -79,7 +79,7 @@ const ModulesDialog = ({
|
||||
label="Enabled"
|
||||
/>
|
||||
</Grid>
|
||||
<Box sx={{ mt: 2, mb: 1 }}>
|
||||
<Box mt={2} mb={1}>
|
||||
<TextField
|
||||
name="license"
|
||||
label="License Key"
|
||||
|
||||
@@ -2,12 +2,12 @@ import { memo } from 'react';
|
||||
|
||||
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
|
||||
import DeleteForeverIcon from '@mui/icons-material/DeleteForever';
|
||||
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutlined';
|
||||
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
|
||||
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
|
||||
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
|
||||
import InsertCommentOutlinedIcon from '@mui/icons-material/InsertCommentOutlined';
|
||||
import StarIcon from '@mui/icons-material/Star';
|
||||
import StarOutlineIcon from '@mui/icons-material/StarOutlined';
|
||||
import StarOutlineIcon from '@mui/icons-material/StarOutline';
|
||||
import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
|
||||
import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';
|
||||
import type { SvgIconProps } from '@mui/material';
|
||||
|
||||
@@ -41,7 +41,6 @@ const MIN_ID = -100;
|
||||
const MAX_ID = 100;
|
||||
const ICON_SIZE = 16;
|
||||
const SCHEDULE_FLAG_THRESHOLD = 127;
|
||||
const FLAG_ALL_DAYS = 127;
|
||||
const REFERENCE_YEAR = 2017;
|
||||
const REFERENCE_MONTH = '01';
|
||||
const LOG_2 = Math.log(2);
|
||||
@@ -52,7 +51,7 @@ const WEEK_DAYS = [1, 2, 3, 4, 5, 6, 7] as const;
|
||||
const DEFAULT_SCHEDULE_ITEM: Omit<ScheduleItem, 'id' | 'o_id'> = {
|
||||
active: false,
|
||||
deleted: false,
|
||||
flags: FLAG_ALL_DAYS,
|
||||
flags: ScheduleFlag.SCHEDULE_DAY,
|
||||
time: '',
|
||||
cmd: '',
|
||||
value: '',
|
||||
@@ -358,9 +357,9 @@ const Scheduler = () => {
|
||||
return (
|
||||
<SectionContent>
|
||||
{blocker ? <BlockNavigation blocker={blocker} /> : null}
|
||||
<Typography sx={{ mb: 2 }} color="warning" variant="body1">
|
||||
{LL.SCHEDULER_HELP_1()}.
|
||||
</Typography>
|
||||
<Box mb={2} color="warning.main">
|
||||
<Typography variant="body1">{LL.SCHEDULER_HELP_1()}.</Typography>
|
||||
</Box>
|
||||
{renderSchedule()}
|
||||
|
||||
{selectedScheduleItem && (
|
||||
@@ -375,8 +374,8 @@ const Scheduler = () => {
|
||||
/>
|
||||
)}
|
||||
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap' }}>
|
||||
<Box sx={{ flexGrow: 1 }}>
|
||||
<Box display="flex" flexWrap="wrap">
|
||||
<Box flexGrow={1}>
|
||||
{numChanges !== 0 && (
|
||||
<ButtonRow>
|
||||
<Button
|
||||
@@ -398,7 +397,7 @@ const Scheduler = () => {
|
||||
</ButtonRow>
|
||||
)}
|
||||
</Box>
|
||||
<Box sx={{ flexWrap: 'nowrap', whiteSpace: 'nowrap' }}>
|
||||
<Box flexWrap="nowrap" whiteSpace="nowrap">
|
||||
<ButtonRow>
|
||||
<Button
|
||||
startIcon={<AddIcon />}
|
||||
|
||||
@@ -4,7 +4,7 @@ import AddIcon from '@mui/icons-material/Add';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import DoneIcon from '@mui/icons-material/Done';
|
||||
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
|
||||
import RemoveIcon from '@mui/icons-material/RemoveCircleOutlined';
|
||||
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -33,8 +33,7 @@ import type { ScheduleItem } from './types';
|
||||
|
||||
// Constants
|
||||
const FLAG_MASK_127 = 127;
|
||||
const SCHEDULE_TYPE_THRESHOLD = 127;
|
||||
const FLAG_ALL_DAYS = 127;
|
||||
const SCHEDULE_TYPE_THRESHOLD = 128;
|
||||
const DEFAULT_TIME = '00:00';
|
||||
const TYPOGRAPHY_FONT_SIZE = 10;
|
||||
|
||||
@@ -105,7 +104,7 @@ const SchedulerDialog = ({
|
||||
// 130 is on condition
|
||||
// 132 is immediate
|
||||
setScheduleType(
|
||||
selectedItem.flags <= SCHEDULE_TYPE_THRESHOLD
|
||||
selectedItem.flags < SCHEDULE_TYPE_THRESHOLD
|
||||
? ScheduleFlag.SCHEDULE_DAY
|
||||
: selectedItem.flags
|
||||
);
|
||||
@@ -182,7 +181,7 @@ const SchedulerDialog = ({
|
||||
setScheduleType(flag);
|
||||
// wipe the time field when changing the schedule type
|
||||
// set the flags based on type
|
||||
const newFlags = flag === ScheduleFlag.SCHEDULE_DAY ? FLAG_ALL_DAYS : flag;
|
||||
const newFlags = flag === ScheduleFlag.SCHEDULE_DAY ? 0 : flag;
|
||||
setEditItem((prev) => ({ ...prev, time: '', flags: newFlags }));
|
||||
}
|
||||
},
|
||||
@@ -191,8 +190,7 @@ const SchedulerDialog = ({
|
||||
|
||||
const handleDOWChange = useCallback(
|
||||
(_event: React.SyntheticEvent<HTMLElement>, flags: string[]) => {
|
||||
const newFlags =
|
||||
getFlagDOWnumber(flags) === 0 ? FLAG_ALL_DAYS : getFlagDOWnumber(flags);
|
||||
const newFlags = getFlagDOWnumber(flags);
|
||||
setEditItem((prev) => ({ ...prev, flags: newFlags }));
|
||||
},
|
||||
[getFlagDOWnumber]
|
||||
@@ -338,13 +336,11 @@ const SchedulerDialog = ({
|
||||
onChange={updateFormValue}
|
||||
/>
|
||||
{isTimerSchedule && (
|
||||
<Typography
|
||||
sx={{ ml: 2, mt: 4 }}
|
||||
color="warning"
|
||||
variant="body2"
|
||||
>
|
||||
{LL.SCHEDULER_HELP_2()}
|
||||
</Typography>
|
||||
<Box color="warning.main" ml={2} mt={4}>
|
||||
<Typography variant="body2">
|
||||
{LL.SCHEDULER_HELP_2()}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
@@ -393,7 +389,7 @@ const SchedulerDialog = ({
|
||||
|
||||
<DialogActions>
|
||||
{!creating && (
|
||||
<Box sx={{ flexGrow: 1 }}>
|
||||
<Box flexGrow={1}>
|
||||
<Button
|
||||
startIcon={<RemoveIcon />}
|
||||
variant="outlined"
|
||||
|
||||
@@ -348,7 +348,7 @@ const Sensors = () => {
|
||||
|
||||
const addAnalogSensor = useCallback(() => {
|
||||
if (firstAvailableGPIO.current === undefined) {
|
||||
toast.error(LL.NO_GPIO());
|
||||
toast.error('No available GPIO found');
|
||||
return;
|
||||
}
|
||||
setCreating(true);
|
||||
@@ -591,14 +591,7 @@ const Sensors = () => {
|
||||
/>
|
||||
)}
|
||||
{sensorData?.analog_enabled === true && me.admin && (
|
||||
<Box
|
||||
sx={{
|
||||
mt: 2,
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
justifyContent: 'flex-end'
|
||||
}}
|
||||
>
|
||||
<Box mt={2} display="flex" flexWrap="wrap" justifyContent="flex-end">
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import DoneIcon from '@mui/icons-material/Done';
|
||||
import RemoveIcon from '@mui/icons-material/RemoveCircleOutlined';
|
||||
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import {
|
||||
Box,
|
||||
@@ -479,7 +479,7 @@ const SensorsAnalogDialog = ({
|
||||
)}
|
||||
</Grid>
|
||||
{fieldErrors && Object.keys(fieldErrors).length > 0 && (
|
||||
<Box sx={{ mt: 1 }}>
|
||||
<Box mt={1}>
|
||||
{Object.values(fieldErrors).map((errArr, idx) =>
|
||||
Array.isArray(errArr)
|
||||
? errArr.map((err, j) => (
|
||||
@@ -487,7 +487,7 @@ const SensorsAnalogDialog = ({
|
||||
key={`${idx}-${j}`}
|
||||
color="error"
|
||||
variant="caption"
|
||||
sx={{ display: 'block' }}
|
||||
display="block"
|
||||
>
|
||||
{err.message}
|
||||
</Typography>
|
||||
@@ -498,7 +498,7 @@ const SensorsAnalogDialog = ({
|
||||
)}
|
||||
{editItem.s && (
|
||||
<Grid>
|
||||
<Typography sx={{ mt: 1 }} color="warning" variant="body2">
|
||||
<Typography mt={1} color="warning.main" variant="body2">
|
||||
<WarningIcon
|
||||
fontSize="small"
|
||||
sx={{ mr: 1, verticalAlign: 'middle' }}
|
||||
@@ -511,7 +511,7 @@ const SensorsAnalogDialog = ({
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
{!creating && (
|
||||
<Box sx={{ flexGrow: 1, '& button': { mt: 0 } }}>
|
||||
<Box flexGrow={1} sx={{ '& button': { mt: 0 } }}>
|
||||
<Button
|
||||
startIcon={<RemoveIcon />}
|
||||
disabled={editItem.s}
|
||||
|
||||
@@ -4,6 +4,7 @@ import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import DoneIcon from '@mui/icons-material/Done';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
@@ -110,9 +111,11 @@ const SensorsTemperatureDialog = ({
|
||||
<Dialog sx={dialogStyle} open={open} onClose={handleClose}>
|
||||
<DialogTitle>{dialogTitle}</DialogTitle>
|
||||
<DialogContent dividers>
|
||||
<Typography sx={{ mb: 2 }} color="warning" variant="body2">
|
||||
{LL.ID_OF(LL.SENSOR(0))}: {editItem.id}
|
||||
</Typography>
|
||||
<Box color="warning.main" mb={2}>
|
||||
<Typography variant="body2">
|
||||
{LL.ID_OF(LL.SENSOR(0))}: {editItem.id}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Grid container spacing={2}>
|
||||
<Grid>
|
||||
<ValidatedTextField
|
||||
@@ -139,7 +142,7 @@ const SensorsTemperatureDialog = ({
|
||||
</Grid>
|
||||
{editItem.s && (
|
||||
<Grid>
|
||||
<Typography sx={{ mt: 1 }} color="warning" variant="body2">
|
||||
<Typography mt={1} color="warning.main" variant="body2">
|
||||
<WarningIcon
|
||||
fontSize="small"
|
||||
sx={{ mr: 1, verticalAlign: 'middle' }}
|
||||
|
||||
@@ -41,12 +41,8 @@ const UserProfileComponent = () => {
|
||||
/>
|
||||
</ListItem>
|
||||
</List>
|
||||
<Box sx={{ mt: 2, mb: 2, display: 'flex', alignItems: 'center' }}>
|
||||
<Typography
|
||||
sx={{ mr: 2, textAlign: 'center' }}
|
||||
color="warning"
|
||||
variant="body1"
|
||||
>
|
||||
<Box mt={2} mb={2} display="flex" alignItems="center">
|
||||
<Typography mr={2} variant="body1" align="center">
|
||||
{LL.LANGUAGE()}:
|
||||
</Typography>
|
||||
<LanguageSelector />
|
||||
|
||||
@@ -196,7 +196,7 @@ export enum DeviceValueUOM {
|
||||
MBAR,
|
||||
LH,
|
||||
CTKWH,
|
||||
HERTZ
|
||||
HZ
|
||||
}
|
||||
|
||||
export const DeviceValueUOM_s = [
|
||||
|
||||
@@ -489,25 +489,17 @@ const ApplicationSettings = () => {
|
||||
name="board_profile"
|
||||
label={LL.BOARD_PROFILE()}
|
||||
value={data.board_profile}
|
||||
disabled={processingBoard}
|
||||
disabled={processingBoard || hardwareData.model.startsWith('BBQKees')}
|
||||
variant="outlined"
|
||||
onChange={changeBoardProfile}
|
||||
margin="normal"
|
||||
select
|
||||
>
|
||||
{hardwareData.model.startsWith('BBQKees') ? (
|
||||
<MenuItem key={hardwareData.board} value={hardwareData.board}>
|
||||
{BOARD_PROFILES[hardwareData.board as BoardProfileKey]}
|
||||
</MenuItem>
|
||||
) : (
|
||||
boardProfileItems
|
||||
)}
|
||||
{(data.board_profile === 'CUSTOM' || data.developer_mode) && <Divider />}
|
||||
{(data.board_profile === 'CUSTOM' || data.developer_mode) && (
|
||||
<MenuItem key={'CUSTOM'} value={'CUSTOM'}>
|
||||
{LL.CUSTOM()}…
|
||||
</MenuItem>
|
||||
)}
|
||||
{boardProfileItems}
|
||||
<Divider />
|
||||
<MenuItem key={'CUSTOM'} value={'CUSTOM'}>
|
||||
{LL.CUSTOM()}…
|
||||
</MenuItem>
|
||||
</TextField>
|
||||
{data.board_profile === 'CUSTOM' && (
|
||||
<>
|
||||
@@ -771,7 +763,7 @@ const ApplicationSettings = () => {
|
||||
label={LL.REMOTE_TIMEOUT_EN()}
|
||||
/>
|
||||
{data.remote_timeout_en && (
|
||||
<Box sx={{ mt: 2 }}>
|
||||
<Box mt={2}>
|
||||
<ValidatedTextField
|
||||
fieldErrors={fieldErrors || {}}
|
||||
name="remote_timeout"
|
||||
@@ -904,12 +896,10 @@ const ApplicationSettings = () => {
|
||||
);
|
||||
};
|
||||
|
||||
return restarting ? (
|
||||
<SystemMonitor />
|
||||
) : (
|
||||
return (
|
||||
<SectionContent>
|
||||
{blocker ? <BlockNavigation blocker={blocker} /> : null}
|
||||
{content()}
|
||||
{restarting ? <SystemMonitor /> : content()}
|
||||
</SectionContent>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,23 +1,12 @@
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import DownloadIcon from '@mui/icons-material/GetApp';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
Grid,
|
||||
Typography
|
||||
} from '@mui/material';
|
||||
import { Box, Button, Grid, Typography } from '@mui/material';
|
||||
|
||||
import * as SystemApi from 'api/system';
|
||||
import { API, callAction } from 'api/app';
|
||||
|
||||
import { dialogStyle } from '@/CustomTheme';
|
||||
import { useRequest } from 'alova/client';
|
||||
import type { APIcall } from 'app/main/types';
|
||||
import SystemMonitor from 'app/status/SystemMonitor';
|
||||
@@ -30,11 +19,16 @@ import {
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { saveFile } from 'utils';
|
||||
|
||||
interface DownloadButton {
|
||||
key: string;
|
||||
type: string;
|
||||
label: string | number;
|
||||
isGridButton: boolean;
|
||||
}
|
||||
|
||||
const DownloadUpload = () => {
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
const [confirmBackup, setConfirmBackup] = useState<boolean>(false);
|
||||
|
||||
const [restarting, setRestarting] = useState<boolean>(false);
|
||||
|
||||
const { send: sendExportData } = useRequest(
|
||||
@@ -69,44 +63,40 @@ const DownloadUpload = () => {
|
||||
|
||||
useLayoutTitle(LL.DOWNLOAD_UPLOAD());
|
||||
|
||||
const handleCloseBackupDialog = useCallback(() => {
|
||||
setConfirmBackup(false);
|
||||
}, []);
|
||||
|
||||
const renderBackupDialog = useMemo(
|
||||
() => (
|
||||
<Dialog
|
||||
sx={dialogStyle}
|
||||
open={confirmBackup}
|
||||
onClose={handleCloseBackupDialog}
|
||||
>
|
||||
<DialogTitle>{LL.DOWNLOAD_SYSTEM_BACKUP()}</DialogTitle>
|
||||
<DialogContent dividers>
|
||||
<WarningIcon color="warning" sx={{ fontSize: 18 }} />
|
||||
|
||||
{LL.WARNING_SYSTEM_BACKUP()}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
startIcon={<CancelIcon />}
|
||||
variant="outlined"
|
||||
onClick={handleCloseBackupDialog}
|
||||
color="secondary"
|
||||
>
|
||||
{LL.CANCEL()}
|
||||
</Button>
|
||||
<Button
|
||||
startIcon={<DownloadIcon />}
|
||||
variant="outlined"
|
||||
onClick={() => handleDownload('systembackup')()}
|
||||
color="primary"
|
||||
>
|
||||
{LL.DOWNLOAD(0)}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
),
|
||||
[confirmBackup, handleCloseBackupDialog, LL]
|
||||
const downloadButtons: DownloadButton[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
key: 'settings',
|
||||
type: 'settings',
|
||||
label: LL.SETTINGS_OF(LL.APPLICATION()),
|
||||
isGridButton: true
|
||||
},
|
||||
{
|
||||
key: 'customizations',
|
||||
type: 'customizations',
|
||||
label: LL.CUSTOMIZATIONS(),
|
||||
isGridButton: true
|
||||
},
|
||||
{
|
||||
key: 'entities',
|
||||
type: 'entities',
|
||||
label: LL.CUSTOM_ENTITIES(0),
|
||||
isGridButton: true
|
||||
},
|
||||
{
|
||||
key: 'schedule',
|
||||
type: 'schedule',
|
||||
label: LL.SCHEDULE(0),
|
||||
isGridButton: true
|
||||
},
|
||||
{
|
||||
key: 'allvalues',
|
||||
type: 'allvalues',
|
||||
label: LL.ALLVALUES(),
|
||||
isGridButton: false
|
||||
}
|
||||
],
|
||||
[LL]
|
||||
);
|
||||
|
||||
const handleDownload = useCallback(
|
||||
@@ -128,57 +118,58 @@ const DownloadUpload = () => {
|
||||
);
|
||||
}
|
||||
|
||||
const gridButtons = downloadButtons.filter((btn) => btn.isGridButton);
|
||||
const standaloneButton = downloadButtons.find((btn) => !btn.isGridButton);
|
||||
|
||||
return (
|
||||
<SectionContent>
|
||||
{renderBackupDialog}
|
||||
|
||||
<Typography sx={{ pb: 2 }} variant="h6" color="primary">
|
||||
{LL.DOWNLOAD(0)}
|
||||
</Typography>
|
||||
|
||||
<Grid
|
||||
container
|
||||
spacing={2}
|
||||
sx={{
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography variant="body1" color="warning">
|
||||
{LL.DOWNLOAD_SETTINGS_TEXT()}:
|
||||
</Typography>
|
||||
<Button
|
||||
startIcon={<DownloadIcon />}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={() => setConfirmBackup(true)}
|
||||
>
|
||||
{LL.DOWNLOAD_SYSTEM_BACKUP()}
|
||||
</Button>
|
||||
<Typography mb={1} variant="body1" color="warning">
|
||||
{LL.DOWNLOAD_SETTINGS_TEXT()}.
|
||||
</Typography>
|
||||
|
||||
<Grid container spacing={2}>
|
||||
{gridButtons.map((button) => (
|
||||
<Grid key={button.key}>
|
||||
<Button
|
||||
startIcon={<DownloadIcon />}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={handleDownload(button.type)}
|
||||
>
|
||||
{button.label}
|
||||
</Button>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
|
||||
<Grid container spacing={2} sx={{ mt: 2, alignItems: 'center' }}>
|
||||
<Typography variant="body1" color="warning">
|
||||
{LL.DOWNLOAD_SETTINGS_TEXT2()}:
|
||||
</Typography>
|
||||
<Typography mt={2} mb={1} variant="body1" color="warning">
|
||||
{LL.DOWNLOAD_SETTINGS_TEXT2()}.
|
||||
</Typography>
|
||||
|
||||
{standaloneButton && (
|
||||
<Button
|
||||
startIcon={<DownloadIcon />}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={handleDownload('allvalues')}
|
||||
onClick={handleDownload(standaloneButton.type)}
|
||||
>
|
||||
{LL.ALLVALUES()}
|
||||
{standaloneButton.label}
|
||||
</Button>
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
<Typography sx={{ pt: 2, pb: 2 }} variant="h6" color="primary">
|
||||
{LL.UPLOAD()}
|
||||
</Typography>
|
||||
|
||||
<Typography sx={{ pb: 2 }} color="warning" variant="body1">
|
||||
{LL.UPLOAD_TEXT()}:
|
||||
</Typography>
|
||||
<Box color="warning.main" sx={{ pb: 2 }}>
|
||||
<Typography variant="body1">{LL.UPLOAD_TEXT()}.</Typography>
|
||||
</Box>
|
||||
|
||||
<SingleUpload doRestart={doRestart} />
|
||||
<SingleUpload text={LL.UPLOAD_DRAG()} doRestart={doRestart} />
|
||||
</SectionContent>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -129,7 +129,7 @@ const MqttSettings = () => {
|
||||
<SectionContent>
|
||||
{blocker ? <BlockNavigation blocker={blocker} /> : null}
|
||||
<>
|
||||
<Box sx={{ display: 'flex', gap: 2, mb: 1 }}>
|
||||
<Box display="flex" gap={2} mb={1}>
|
||||
<BlockFormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
@@ -345,91 +345,75 @@ const MqttSettings = () => {
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
{/* <Grid container spacing={2} rowSpacing={0}> */}
|
||||
<Grid>
|
||||
<BlockFormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
name="ha_enabled"
|
||||
checked={data.ha_enabled}
|
||||
onChange={updateFormValue}
|
||||
disabled={data.publish_single}
|
||||
/>
|
||||
}
|
||||
label={LL.MQTT_PUBLISH_TEXT_3()}
|
||||
/>
|
||||
</Grid>
|
||||
{data.ha_enabled && (
|
||||
<Grid container spacing={2} rowSpacing={0}>
|
||||
<Grid>
|
||||
<TextField
|
||||
name="discovery_type"
|
||||
label={LL.MQTT_PUBLISH_TEXT_5()}
|
||||
value={data.discovery_type}
|
||||
variant="outlined"
|
||||
onChange={updateFormValue}
|
||||
margin="normal"
|
||||
select
|
||||
>
|
||||
<MenuItem value={0}>Home Assistant</MenuItem>
|
||||
<MenuItem value={1}>Domoticz</MenuItem>
|
||||
<MenuItem value={2}>Domoticz (latest)</MenuItem>
|
||||
</TextField>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<TextField
|
||||
name="discovery_prefix"
|
||||
label={LL.MQTT_PUBLISH_TEXT_4()}
|
||||
variant="outlined"
|
||||
value={data.discovery_prefix}
|
||||
onChange={updateFormValue}
|
||||
margin="normal"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<TextField
|
||||
name="entity_format"
|
||||
label={LL.MQTT_ENTITY_FORMAT()}
|
||||
value={data.entity_format}
|
||||
variant="outlined"
|
||||
onChange={updateFormValue}
|
||||
margin="normal"
|
||||
select
|
||||
>
|
||||
<MenuItem value={0}>{LL.MQTT_ENTITY_FORMAT_0()}</MenuItem>
|
||||
<MenuItem value={3}>
|
||||
{LL.MQTT_ENTITY_FORMAT_1()} (v3.5)
|
||||
</MenuItem>
|
||||
<MenuItem value={4}>
|
||||
{LL.MQTT_ENTITY_FORMAT_2()} (v3.5)
|
||||
</MenuItem>
|
||||
<MenuItem value={1}>
|
||||
{LL.MQTT_ENTITY_FORMAT_1()} (latest)
|
||||
</MenuItem>
|
||||
<MenuItem value={2}>
|
||||
{LL.MQTT_ENTITY_FORMAT_2()} (latest)
|
||||
</MenuItem>
|
||||
</TextField>
|
||||
</Grid>
|
||||
<Grid>
|
||||
{data.discovery_type === 0 && (
|
||||
<Grid container spacing={2} rowSpacing={0}>
|
||||
<Grid>
|
||||
<BlockFormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
name="ha_enabled"
|
||||
checked={data.ha_enabled}
|
||||
onChange={updateFormValue}
|
||||
disabled={data.publish_single}
|
||||
/>
|
||||
}
|
||||
label={LL.MQTT_PUBLISH_TEXT_3()}
|
||||
/>
|
||||
</Grid>
|
||||
{data.ha_enabled && (
|
||||
<Grid container spacing={2} rowSpacing={0}>
|
||||
<Grid>
|
||||
<TextField
|
||||
name="ha_number_mode"
|
||||
label={LL.MQTT_INPUT_NUMBER_FORMAT()}
|
||||
value={data.ha_number_mode}
|
||||
name="discovery_type"
|
||||
label={LL.MQTT_PUBLISH_TEXT_5()}
|
||||
value={data.discovery_type}
|
||||
variant="outlined"
|
||||
onChange={updateFormValue}
|
||||
sx={{ width: '20ch' }}
|
||||
margin="normal"
|
||||
select
|
||||
>
|
||||
<MenuItem value={0}>Box</MenuItem>
|
||||
<MenuItem value={1}>Slider</MenuItem>
|
||||
<MenuItem value={0}>Home Assistant</MenuItem>
|
||||
<MenuItem value={1}>Domoticz</MenuItem>
|
||||
<MenuItem value={2}>Domoticz (latest)</MenuItem>
|
||||
</TextField>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid>
|
||||
<TextField
|
||||
name="discovery_prefix"
|
||||
label={LL.MQTT_PUBLISH_TEXT_4()}
|
||||
variant="outlined"
|
||||
value={data.discovery_prefix}
|
||||
onChange={updateFormValue}
|
||||
margin="normal"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<TextField
|
||||
name="entity_format"
|
||||
label={LL.MQTT_ENTITY_FORMAT()}
|
||||
value={data.entity_format}
|
||||
variant="outlined"
|
||||
onChange={updateFormValue}
|
||||
margin="normal"
|
||||
select
|
||||
>
|
||||
<MenuItem value={0}>{LL.MQTT_ENTITY_FORMAT_0()}</MenuItem>
|
||||
<MenuItem value={3}>
|
||||
{LL.MQTT_ENTITY_FORMAT_1()} (v3.5)
|
||||
</MenuItem>
|
||||
<MenuItem value={4}>
|
||||
{LL.MQTT_ENTITY_FORMAT_2()} (v3.5)
|
||||
</MenuItem>
|
||||
<MenuItem value={1}>
|
||||
{LL.MQTT_ENTITY_FORMAT_1()} (latest)
|
||||
</MenuItem>
|
||||
<MenuItem value={2}>
|
||||
{LL.MQTT_ENTITY_FORMAT_2()} (latest)
|
||||
</MenuItem>
|
||||
</TextField>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)}
|
||||
)}
|
||||
</Grid>
|
||||
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
|
||||
{LL.MQTT_PUBLISH_INTERVALS()} (0=auto)
|
||||
</Typography>
|
||||
|
||||
@@ -193,9 +193,9 @@ const NTPSettings = () => {
|
||||
{timeZoneItems}
|
||||
</ValidatedTextField>
|
||||
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap' }}>
|
||||
<Box display="flex" flexWrap="wrap">
|
||||
{!data.enabled && !dirtyFlags.length && (
|
||||
<Box sx={{ flexWrap: 'nowrap', whiteSpace: 'nowrap' }}>
|
||||
<Box flexWrap="nowrap" whiteSpace="nowrap">
|
||||
<ButtonRow>
|
||||
<Button
|
||||
onClick={openSetTime}
|
||||
@@ -259,9 +259,9 @@ const NTPSettings = () => {
|
||||
<Dialog sx={dialogStyle} open={settingTime} onClose={handleCloseSetTime}>
|
||||
<DialogTitle>{LL.SET_TIME(1)}</DialogTitle>
|
||||
<DialogContent dividers>
|
||||
<Typography color="warning" variant="body2">
|
||||
{LL.SET_TIME_TEXT()}
|
||||
</Typography>
|
||||
<Box color="warning.main" p={0} pl={0} pr={0} mt={0} mb={2}>
|
||||
<Typography variant="body2">{LL.SET_TIME_TEXT()}</Typography>
|
||||
</Box>
|
||||
<TextField
|
||||
label={LL.LOCAL_TIME(0)}
|
||||
type="datetime-local"
|
||||
|
||||
@@ -156,13 +156,11 @@ const Settings = () => {
|
||||
<Divider />
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
mt: 2,
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
flexWrap: 'nowrap',
|
||||
whiteSpace: 'nowrap'
|
||||
}}
|
||||
mt={2}
|
||||
display="flex"
|
||||
justifyContent="flex-end"
|
||||
flexWrap="nowrap"
|
||||
whiteSpace="nowrap"
|
||||
>
|
||||
<Button
|
||||
startIcon={<SettingsBackupRestoreIcon />}
|
||||
@@ -184,7 +182,7 @@ const Settings = () => {
|
||||
restarting
|
||||
]);
|
||||
|
||||
return restarting ? <SystemMonitor /> : <SectionContent>{content}</SectionContent>;
|
||||
return <SectionContent>{restarting ? <SystemMonitor /> : content}</SectionContent>;
|
||||
};
|
||||
|
||||
export default Settings;
|
||||
|
||||
@@ -397,12 +397,10 @@ const NetworkSettings = () => {
|
||||
);
|
||||
};
|
||||
|
||||
return restarting ? (
|
||||
<SystemMonitor />
|
||||
) : (
|
||||
return (
|
||||
<SectionContent>
|
||||
{blocker ? <BlockNavigation blocker={blocker} /> : null}
|
||||
{content()}
|
||||
{restarting ? <SystemMonitor /> : content()}
|
||||
</SectionContent>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -54,27 +54,19 @@ const GenerateToken = ({ username, onClose }: GenerateTokenProps) => {
|
||||
<DialogContent dividers>
|
||||
{token ? (
|
||||
<>
|
||||
<MessageBox
|
||||
message={LL.ACCESS_TOKEN_TEXT()}
|
||||
level="info"
|
||||
sx={{ mt: 2, mb: 2 }}
|
||||
/>
|
||||
<Box sx={{ mt: 2, mb: 2 }}>
|
||||
<MessageBox message={LL.ACCESS_TOKEN_TEXT()} level="info" my={2} />
|
||||
<Box mt={2} mb={2}>
|
||||
<TextField
|
||||
label="Token"
|
||||
multiline
|
||||
value={token.token}
|
||||
fullWidth
|
||||
slotProps={{
|
||||
input: {
|
||||
readOnly: true
|
||||
}
|
||||
}}
|
||||
contentEditable={false}
|
||||
/>
|
||||
</Box>
|
||||
</>
|
||||
) : (
|
||||
<Box sx={{ m: 4, textAlign: 'center' }}>
|
||||
<Box m={4} textAlign="center">
|
||||
<LinearProgress />
|
||||
<Typography variant="h6">{LL.GENERATING_TOKEN()}…</Typography>
|
||||
</Box>
|
||||
|
||||
@@ -240,16 +240,12 @@ const ManageUsers = () => {
|
||||
</Table>
|
||||
|
||||
{noAdminConfigured() && (
|
||||
<MessageBox
|
||||
level="warning"
|
||||
message={LL.USER_WARNING()}
|
||||
sx={{ mt: 2, mb: 2 }}
|
||||
/>
|
||||
<MessageBox level="warning" message={LL.USER_WARNING()} my={2} />
|
||||
)}
|
||||
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap' }}>
|
||||
<Box display="flex" flexWrap="wrap">
|
||||
{changed !== 0 && (
|
||||
<Box sx={{ flexGrow: 1, '& button': { mt: 2 } }}>
|
||||
<Box flexGrow={1} sx={{ '& button': { mt: 2 } }}>
|
||||
<ButtonRow>
|
||||
<Button
|
||||
startIcon={<CancelIcon />}
|
||||
@@ -274,7 +270,7 @@ const ManageUsers = () => {
|
||||
</ButtonRow>
|
||||
</Box>
|
||||
)}
|
||||
<Box sx={{ flexWrap: 'nowrap', whiteSpace: 'nowrap' }}>
|
||||
<Box flexWrap="nowrap" whiteSpace="nowrap">
|
||||
<ButtonRow>
|
||||
<Button
|
||||
startIcon={<PersonAddIcon />}
|
||||
|
||||
@@ -443,7 +443,7 @@ const SystemStatus = () => {
|
||||
renderRestartDialog
|
||||
]);
|
||||
|
||||
return restarting ? <SystemMonitor /> : <SectionContent>{content}</SectionContent>;
|
||||
return <SectionContent>{restarting ? <SystemMonitor /> : content}</SectionContent>;
|
||||
};
|
||||
|
||||
export default SystemStatus;
|
||||
|
||||
@@ -38,6 +38,8 @@ import type { LogEntry, LogSettings } from 'types';
|
||||
import { LogLevel } from 'types';
|
||||
import { updateValueDirty, useRest } from 'utils';
|
||||
|
||||
const MAX_LOG_ENTRIES = 1000; // Limit log entries to prevent memory issues
|
||||
|
||||
const TextColors: Record<LogLevel, string> = {
|
||||
[LogLevel.ERROR]: '#ff0000', // red
|
||||
[LogLevel.WARNING]: '#ff0000', // red
|
||||
@@ -198,6 +200,10 @@ const SystemLog = () => {
|
||||
}
|
||||
}
|
||||
const newLog = [...log, logentry];
|
||||
// Limit log entries to prevent memory issues - only slice when necessary
|
||||
if (newLog.length > MAX_LOG_ENTRIES) {
|
||||
return newLog.slice(-MAX_LOG_ENTRIES);
|
||||
}
|
||||
return newLog;
|
||||
});
|
||||
}, []);
|
||||
@@ -266,7 +272,7 @@ const SystemLog = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Grid container spacing={2} sx={{ alignItems: 'center' }}>
|
||||
<Grid container spacing={2} alignItems="center">
|
||||
<Grid>
|
||||
<TextField
|
||||
name="level"
|
||||
@@ -302,8 +308,6 @@ const SystemLog = () => {
|
||||
<MenuItem value={50}>50</MenuItem>
|
||||
<MenuItem value={75}>75</MenuItem>
|
||||
<MenuItem value={100}>100</MenuItem>
|
||||
<MenuItem value={500}>500</MenuItem>
|
||||
<MenuItem value={1000}>1000</MenuItem>
|
||||
</TextField>
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
@@ -60,16 +60,18 @@ const SystemMonitor = () => {
|
||||
const { statusMessage, isUploading, progressValue } = useMemo(() => {
|
||||
const status = data?.status;
|
||||
|
||||
const message =
|
||||
status && status >= SystemStatusCodes.SYSTEM_STATUS_UPLOADING
|
||||
? LL.WAIT_FIRMWARE()
|
||||
: status === SystemStatusCodes.SYSTEM_STATUS_PENDING_RESTART
|
||||
? LL.APPLICATION_RESTARTING()
|
||||
: status === SystemStatusCodes.SYSTEM_STATUS_NORMAL
|
||||
? LL.RESTARTING_PRE()
|
||||
: status === SystemStatusCodes.SYSTEM_STATUS_ERROR_UPLOAD
|
||||
? 'Upload Failed'
|
||||
: LL.RESTARTING_POST();
|
||||
let message = '';
|
||||
if (status && status >= SystemStatusCodes.SYSTEM_STATUS_UPLOADING) {
|
||||
message = LL.WAIT_FIRMWARE();
|
||||
} else if (status === SystemStatusCodes.SYSTEM_STATUS_PENDING_RESTART) {
|
||||
message = LL.APPLICATION_RESTARTING();
|
||||
} else if (status === SystemStatusCodes.SYSTEM_STATUS_NORMAL) {
|
||||
message = LL.RESTARTING_PRE();
|
||||
} else if (status === SystemStatusCodes.SYSTEM_STATUS_ERROR_UPLOAD) {
|
||||
message = 'Upload Failed';
|
||||
} else {
|
||||
message = LL.RESTARTING_POST();
|
||||
}
|
||||
|
||||
const uploading =
|
||||
status !== undefined && status >= SystemStatusCodes.SYSTEM_STATUS_UPLOADING;
|
||||
@@ -101,8 +103,8 @@ const SystemMonitor = () => {
|
||||
height: '100vh',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
// backdropFilter: 'blur(8px)'
|
||||
justifyContent: 'center',
|
||||
backdropFilter: 'blur(8px)'
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
@@ -118,15 +120,17 @@ const SystemMonitor = () => {
|
||||
p: 3
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', flexDirection: 'column' }}>
|
||||
<Box display="flex" alignItems="center" flexDirection="column">
|
||||
<img
|
||||
src="/app/icon.png"
|
||||
alt="EMS-ESP"
|
||||
style={{ width: '40px', height: '40px', marginBottom: '16px' }}
|
||||
/>
|
||||
<Typography
|
||||
sx={{ color: 'secondary', fontWeight: 400, textAlign: 'center' }}
|
||||
color="secondary"
|
||||
variant="h6"
|
||||
fontWeight={400}
|
||||
textAlign="center"
|
||||
>
|
||||
{statusMessage}
|
||||
</Typography>
|
||||
@@ -146,14 +150,11 @@ const SystemMonitor = () => {
|
||||
</MessageBox>
|
||||
) : (
|
||||
<>
|
||||
<Typography
|
||||
sx={{ mt: 2, fontWeight: 400, textAlign: 'center' }}
|
||||
variant="h6"
|
||||
>
|
||||
<Typography mt={2} variant="h6" fontWeight={400} textAlign="center">
|
||||
{LL.PLEASE_WAIT()}…
|
||||
</Typography>
|
||||
{isUploading && (
|
||||
<Box sx={{ width: '100%', pl: 2, pr: 2, py: 2 }}>
|
||||
<Box width="100%" pl={2} pr={2} py={2}>
|
||||
<LinearProgressWithLabel value={progressValue} />
|
||||
</Box>
|
||||
)}
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
useRef,
|
||||
useState
|
||||
} from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
@@ -25,6 +24,7 @@ import {
|
||||
DialogTitle,
|
||||
Grid,
|
||||
IconButton,
|
||||
Link,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
@@ -274,7 +274,6 @@ const InstallDialog = memo(
|
||||
fetchDevVersion,
|
||||
latestVersion,
|
||||
latestDevVersion,
|
||||
upgradeImportantMessageType,
|
||||
downloadOnly,
|
||||
platform,
|
||||
LL,
|
||||
@@ -285,7 +284,6 @@ const InstallDialog = memo(
|
||||
fetchDevVersion: boolean;
|
||||
latestVersion?: VersionInfo;
|
||||
latestDevVersion?: VersionInfo;
|
||||
upgradeImportantMessageType: number;
|
||||
downloadOnly: boolean;
|
||||
platform: string;
|
||||
LL: TranslationFunctions;
|
||||
@@ -309,33 +307,12 @@ const InstallDialog = memo(
|
||||
{`${LL.INSTALL()} ${fetchDevVersion ? LL.DEVELOPMENT() : LL.STABLE()} Firmware`}
|
||||
</DialogTitle>
|
||||
<DialogContent dividers>
|
||||
<Typography sx={{ mb: 2 }}>
|
||||
<Typography mb={2}>
|
||||
{LL.INSTALL_VERSION(
|
||||
downloadOnly ? LL.DOWNLOAD(1) : LL.INSTALL(),
|
||||
fetchDevVersion ? latestDevVersion?.name : latestVersion?.name
|
||||
)}
|
||||
</Typography>
|
||||
{upgradeImportantMessageType === 2 && LL.UPGRADE_IMPORTANT_MESSAGES_2()}
|
||||
{upgradeImportantMessageType === 1 && (
|
||||
<>
|
||||
{LL.UPGRADE_IMPORTANT_MESSAGES_1()}
|
||||
<Typography sx={{ mt: 2 }}>
|
||||
<Link to="/settings/downloadUpload" style={{ color: 'lightblue' }}>
|
||||
{LL.DOWNLOAD_SYSTEM_BACKUP()}
|
||||
</Link>
|
||||
</Typography>
|
||||
</>
|
||||
)}
|
||||
<Typography sx={{ mt: 2 }}>
|
||||
<Link
|
||||
to="https://docs.emsesp.org/FAQ#upgrading-the-firmware"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
style={{ color: 'lightblue' }}
|
||||
>
|
||||
{LL.ONLINE_HELP()}
|
||||
</Link>
|
||||
</Typography>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
@@ -352,12 +329,7 @@ const InstallDialog = memo(
|
||||
onClick={onClose}
|
||||
color="primary"
|
||||
>
|
||||
<Link
|
||||
to={binURL}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
style={{ color: 'lightblue', textDecoration: 'none' }}
|
||||
>
|
||||
<Link underline="none" target="_blank" href={binURL} color="primary">
|
||||
{LL.DOWNLOAD(0)}
|
||||
</Link>
|
||||
</Button>
|
||||
@@ -399,9 +371,7 @@ const InstallPartitionDialog = memo(
|
||||
{LL.INSTALL()} {LL.STORED_VERSIONS()}
|
||||
</DialogTitle>
|
||||
<DialogContent dividers>
|
||||
<Typography sx={{ mb: 2 }}>
|
||||
{LL.INSTALL_VERSION(LL.INSTALL(), version)}
|
||||
</Typography>
|
||||
<Typography mb={2}>{LL.INSTALL_VERSION(LL.INSTALL(), version)}</Typography>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
@@ -497,26 +467,6 @@ const Version = () => {
|
||||
immediate: false
|
||||
});
|
||||
|
||||
const [upgradeImportantMessageType, setUpgradeImportantMessageType] =
|
||||
useState<number>(0);
|
||||
|
||||
const { send: checkUpgradeImportantMessages } = useRequest(
|
||||
(version: string) =>
|
||||
callAction({ action: 'upgradeImportantMessages', param: version }),
|
||||
{
|
||||
immediate: false
|
||||
}
|
||||
)
|
||||
.onSuccess((event) => {
|
||||
const upgradeImportantMessageType_n = (
|
||||
event.data as { upgradeImportantMessageType: number }
|
||||
).upgradeImportantMessageType;
|
||||
setUpgradeImportantMessageType(upgradeImportantMessageType_n);
|
||||
})
|
||||
.onError((error) => {
|
||||
toast.error(String(error.error?.message || 'An error occurred'));
|
||||
});
|
||||
|
||||
// Memoized values
|
||||
const platform = useMemo(() => (data ? getPlatform(data) : ''), [data]);
|
||||
|
||||
@@ -582,16 +532,10 @@ const Version = () => {
|
||||
[]
|
||||
);
|
||||
|
||||
const showFirmwareDialog = useCallback(
|
||||
(useDevVersion: boolean) => {
|
||||
setFetchDevVersion(useDevVersion);
|
||||
void checkUpgradeImportantMessages(
|
||||
useDevVersion ? latestDevVersion?.name : latestVersion?.name
|
||||
);
|
||||
setOpenInstallDialog(true);
|
||||
},
|
||||
[latestDevVersion, latestVersion, fetchDevVersion]
|
||||
);
|
||||
const showFirmwareDialog = useCallback((useDevVersion: boolean) => {
|
||||
setFetchDevVersion(useDevVersion);
|
||||
setOpenInstallDialog(true);
|
||||
}, []);
|
||||
|
||||
const closeInstallDialog = useCallback(() => {
|
||||
setOpenInstallDialog(false);
|
||||
@@ -693,8 +637,8 @@ const Version = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box sx={{ p: 2, border: '1px solid #565656', borderRadius: 2 }}>
|
||||
<Typography sx={{ mb: 1 }} variant="h6" color="primary">
|
||||
<Box p={2} border="1px solid grey" borderRadius={2}>
|
||||
<Typography mb={1} variant="h6" color="primary">
|
||||
{LL.THIS_VERSION()}
|
||||
</Typography>
|
||||
|
||||
@@ -759,7 +703,7 @@ const Version = () => {
|
||||
|
||||
{internetLive ? (
|
||||
<>
|
||||
<Typography sx={{ mt: 4, mb: 1 }} variant="h6" color="primary">
|
||||
<Typography mt={4} mb={1} variant="h6" color="primary">
|
||||
{LL.AVAILABLE_VERSION()}
|
||||
</Typography>
|
||||
|
||||
@@ -781,7 +725,7 @@ const Version = () => {
|
||||
</Grid>
|
||||
<Grid size={{ xs: 8, md: 10 }}>
|
||||
{otherPartitions.map((partition) => (
|
||||
<Typography key={partition.partition} sx={{ mb: 1 }}>
|
||||
<Typography key={partition.partition} mb={1}>
|
||||
{partition.version}
|
||||
<IconButton
|
||||
onClick={() =>
|
||||
@@ -847,7 +791,7 @@ const Version = () => {
|
||||
</Grid>
|
||||
</>
|
||||
) : (
|
||||
<Typography sx={{ mt: 2 }} color="warning">
|
||||
<Typography mt={2} color="warning">
|
||||
<WarningIcon color="warning" sx={{ verticalAlign: 'middle', mr: 2 }} />
|
||||
{LL.INTERNET_CONNECTION_REQUIRED()}
|
||||
</Typography>
|
||||
@@ -871,7 +815,6 @@ const Version = () => {
|
||||
fetchDevVersion={fetchDevVersion}
|
||||
latestVersion={latestVersion}
|
||||
latestDevVersion={latestDevVersion}
|
||||
upgradeImportantMessageType={upgradeImportantMessageType}
|
||||
downloadOnly={downloadOnly}
|
||||
platform={platform}
|
||||
LL={LL}
|
||||
@@ -889,7 +832,7 @@ const Version = () => {
|
||||
<Typography sx={{ pt: 2, pb: 2 }} variant="h6" color="primary">
|
||||
{LL.UPLOAD()}
|
||||
</Typography>
|
||||
<SingleUpload doRestart={doRestart} />
|
||||
<SingleUpload text={LL.UPLOAD_DROP_TEXT()} doRestart={doRestart} />
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
@@ -925,7 +868,7 @@ const Version = () => {
|
||||
installPartitionFirmware
|
||||
]);
|
||||
|
||||
return restarting ? <SystemMonitor /> : <SectionContent>{content}</SectionContent>;
|
||||
return <SectionContent>{restarting ? <SystemMonitor /> : content}</SectionContent>;
|
||||
};
|
||||
|
||||
export default memo(Version);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { type FC, type PropsWithChildren, memo } from 'react';
|
||||
import { memo } from 'react';
|
||||
|
||||
import { Box } from '@mui/material';
|
||||
import type { BoxProps } from '@mui/material';
|
||||
|
||||
const ButtonRow: FC<PropsWithChildren<BoxProps>> = memo(({ children, ...rest }) => (
|
||||
const ButtonRow = memo<BoxProps>(({ children, ...rest }) => (
|
||||
<Box
|
||||
sx={{
|
||||
'& button, & a, & .MuiCard-root': {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { type FC, type PropsWithChildren, memo, useMemo } from 'react';
|
||||
import { type FC, memo, useMemo } from 'react';
|
||||
|
||||
import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined';
|
||||
import ErrorIcon from '@mui/icons-material/Error';
|
||||
@@ -12,7 +12,6 @@ type MessageBoxLevel = 'warning' | 'success' | 'info' | 'error';
|
||||
export interface MessageBoxProps extends BoxProps {
|
||||
level: MessageBoxLevel;
|
||||
message?: string;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
const LEVEL_ICONS: Record<MessageBoxLevel, React.ComponentType<SvgIconProps>> = {
|
||||
@@ -29,7 +28,7 @@ const LEVEL_PALETTE_PATHS: Record<MessageBoxLevel, string> = {
|
||||
error: 'error.dark'
|
||||
};
|
||||
|
||||
const MessageBox: FC<PropsWithChildren<MessageBoxProps>> = ({
|
||||
const MessageBox: FC<MessageBoxProps> = ({
|
||||
level,
|
||||
message,
|
||||
sx,
|
||||
@@ -53,16 +52,12 @@ const MessageBox: FC<PropsWithChildren<MessageBoxProps>> = ({
|
||||
|
||||
return (
|
||||
<Box
|
||||
p={2}
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
borderRadius={1}
|
||||
sx={{ backgroundColor, color: 'white', ...sx }}
|
||||
{...rest}
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
borderRadius: 1,
|
||||
backgroundColor,
|
||||
color: 'white',
|
||||
p: 2,
|
||||
...sx
|
||||
}}
|
||||
>
|
||||
<Icon />
|
||||
{(message || children) && (
|
||||
|
||||
@@ -29,7 +29,7 @@ const LayoutDrawerComponent = ({ mobileOpen, onClose }: LayoutDrawerProps) => {
|
||||
() => (
|
||||
<>
|
||||
<Toolbar disableGutters>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', p: 2 }}>
|
||||
<Box display="flex" alignItems="center" px={2}>
|
||||
<LayoutDrawerLogo src="/app/icon.png" alt={PROJECT_NAME} />
|
||||
<Typography variant="h6">{PROJECT_NAME}</Typography>
|
||||
</Box>
|
||||
|
||||
@@ -51,7 +51,9 @@ const LayoutMenuComponent = () => {
|
||||
sx={{ my: 0 }}
|
||||
slotProps={{
|
||||
primary: {
|
||||
sx: { fontWeight: 600, mb: '2px', color: 'lightblue' }
|
||||
fontWeight: '600',
|
||||
mb: '2px',
|
||||
color: 'lightblue'
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -39,8 +39,9 @@ const LayoutMenuItemComponent = ({
|
||||
left: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
width: selected ? '3px' : '0px',
|
||||
width: selected ? '4px' : '0px',
|
||||
backgroundColor: '#90caf9',
|
||||
borderRadius: '0 2px 2px 0',
|
||||
transition: 'width 0.05s cubic-bezier(0.55, 0.085, 0.68, 0.53)'
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -32,16 +32,8 @@ const FormLoaderComponent = ({ errorMessage, onRetry }: FormLoaderProps) => {
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
m: 2,
|
||||
py: 2,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexDirection: 'column'
|
||||
}}
|
||||
>
|
||||
<Box sx={{ p: 2 }}>
|
||||
<Box m={2} py={2} display="flex" alignItems="center" flexDirection="column">
|
||||
<Box py={2}>
|
||||
<CircularProgress size={100} />
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
@@ -15,14 +15,12 @@ const circularProgressStyles: SxProps<Theme> = (theme: Theme) => ({
|
||||
const LoadingSpinner = ({ height = '100%' }: LoadingSpinnerProps) => {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'column',
|
||||
padding: 2,
|
||||
height
|
||||
}}
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
flexDirection="column"
|
||||
padding={2}
|
||||
height={height}
|
||||
>
|
||||
<CircularProgress sx={circularProgressStyles} size={100} />
|
||||
</Box>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// drag/drop code inspired by Prince Azubuike from https://medium.com/@dprincecoder/creating-a-drag-and-drop-file-upload-component-in-react-a-step-by-step-guide-4d93b6cc21e0
|
||||
// Code inspired by Prince Azubuike from https://medium.com/@dprincecoder/creating-a-drag-and-drop-file-upload-component-in-react-a-step-by-step-guide-4d93b6cc21e0
|
||||
import {
|
||||
type ChangeEvent,
|
||||
type DragEvent,
|
||||
@@ -6,28 +6,12 @@ import {
|
||||
useRef,
|
||||
useState
|
||||
} from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import CloudUploadIcon from '@mui/icons-material/CloudUpload';
|
||||
import UploadIcon from '@mui/icons-material/Upload';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
Typography,
|
||||
styled
|
||||
} from '@mui/material';
|
||||
import { Box, Button, Typography, styled } from '@mui/material';
|
||||
|
||||
import { callAction } from 'api/app';
|
||||
|
||||
import { dialogStyle } from '@/CustomTheme';
|
||||
import { useRequest } from 'alova/client';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const DocumentUploader = styled(Box)<{ active?: boolean }>(({ theme, active }) => ({
|
||||
@@ -74,29 +58,6 @@ const DragNdrop = ({ text, onFileSelected }: DragNdropProps) => {
|
||||
const [dragged, setDragged] = useState(false);
|
||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||
const { LL } = useI18nContext();
|
||||
const [showUpgradeDialog, setShowUpgradeDialog] = useState(false);
|
||||
const [upgradeImportantMessageType, setUpgradeImportantMessageType] =
|
||||
useState<number>(0);
|
||||
|
||||
const { send: checkUpgradeImportantMessages } = useRequest(
|
||||
(version: string) =>
|
||||
callAction({ action: 'upgradeImportantMessages', param: version }),
|
||||
{
|
||||
immediate: false
|
||||
}
|
||||
)
|
||||
.onSuccess((event) => {
|
||||
const upgradeImportantMessageType_n = (
|
||||
event.data as { upgradeImportantMessageType: number }
|
||||
).upgradeImportantMessageType;
|
||||
setUpgradeImportantMessageType(upgradeImportantMessageType_n);
|
||||
if (upgradeImportantMessageType_n === 0) {
|
||||
onFileSelected(file);
|
||||
}
|
||||
})
|
||||
.onError((error) => {
|
||||
toast.error(String(error.error?.message || 'An error occurred'));
|
||||
});
|
||||
|
||||
const checkFileExtension = (file: File) => {
|
||||
const validExtensions = ['.json', '.bin', '.md5'];
|
||||
@@ -136,8 +97,9 @@ const DragNdrop = ({ text, onFileSelected }: DragNdropProps) => {
|
||||
|
||||
const handleUploadClick = (event: MouseEvent<HTMLButtonElement>) => {
|
||||
event.stopPropagation();
|
||||
void checkUpgradeImportantMessages(file?.name || '');
|
||||
setShowUpgradeDialog(true);
|
||||
if (file) {
|
||||
onFileSelected(file);
|
||||
}
|
||||
};
|
||||
|
||||
const handleBrowseClick = () => {
|
||||
@@ -196,67 +158,6 @@ const DragNdrop = ({ text, onFileSelected }: DragNdropProps) => {
|
||||
{LL.UPLOAD()}
|
||||
</Button>
|
||||
</Box>
|
||||
{showUpgradeDialog && upgradeImportantMessageType > 0 && (
|
||||
<Dialog
|
||||
sx={dialogStyle}
|
||||
open={showUpgradeDialog}
|
||||
onClose={() => setShowUpgradeDialog(false)}
|
||||
>
|
||||
<DialogTitle>
|
||||
<WarningIcon
|
||||
color="warning"
|
||||
sx={{ fontSize: 18, verticalAlign: 'middle' }}
|
||||
/>
|
||||
|
||||
{LL.UPGRADE_IMPORTANT_MESSAGES()}
|
||||
</DialogTitle>
|
||||
<DialogContent dividers>
|
||||
{upgradeImportantMessageType === 2 &&
|
||||
LL.UPGRADE_IMPORTANT_MESSAGES_2()}
|
||||
{upgradeImportantMessageType === 1 && (
|
||||
<>
|
||||
{LL.UPGRADE_IMPORTANT_MESSAGES_1()}
|
||||
<Typography sx={{ mt: 2 }}>
|
||||
<Link
|
||||
to="/settings/downloadUpload"
|
||||
style={{ color: 'lightblue' }}
|
||||
>
|
||||
{LL.DOWNLOAD_SYSTEM_BACKUP()}
|
||||
</Link>
|
||||
</Typography>
|
||||
</>
|
||||
)}{' '}
|
||||
<Typography sx={{ mt: 2 }}>
|
||||
<Link
|
||||
to="https://docs.emsesp.org/FAQ#upgrading-the-firmware"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
style={{ color: 'lightblue' }}
|
||||
>
|
||||
{LL.ONLINE_HELP()}
|
||||
</Link>
|
||||
</Typography>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
startIcon={<CancelIcon />}
|
||||
variant="outlined"
|
||||
onClick={() => setShowUpgradeDialog(false)}
|
||||
color="secondary"
|
||||
>
|
||||
{LL.CANCEL()}
|
||||
</Button>
|
||||
<Button
|
||||
startIcon={<UploadIcon />}
|
||||
variant="outlined"
|
||||
onClick={() => onFileSelected(file)}
|
||||
color="primary"
|
||||
>
|
||||
{LL.UPLOAD()}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</DocumentUploader>
|
||||
|
||||
@@ -13,10 +13,11 @@ import DragNdrop from './DragNdrop';
|
||||
import { LinearProgressWithLabel } from './LinearProgressWithLabel';
|
||||
|
||||
interface SingleUploadProps {
|
||||
text: string;
|
||||
doRestart: () => void;
|
||||
}
|
||||
|
||||
const SingleUpload = ({ doRestart }: SingleUploadProps) => {
|
||||
const SingleUpload = ({ text, doRestart }: SingleUploadProps) => {
|
||||
const [md5, setMd5] = useState<string>();
|
||||
const [file, setFile] = useState<File>();
|
||||
const { LL } = useI18nContext();
|
||||
@@ -57,7 +58,7 @@ const SingleUpload = ({ doRestart }: SingleUploadProps) => {
|
||||
<>
|
||||
{isUploading ? (
|
||||
<>
|
||||
<Box sx={{ width: '100%', pl: 2, pr: 2 }}>
|
||||
<Box width="100%" pl={2} pr={2}>
|
||||
<LinearProgressWithLabel
|
||||
value={
|
||||
progress.total === 0 || progress.loaded === 0
|
||||
@@ -80,11 +81,11 @@ const SingleUpload = ({ doRestart }: SingleUploadProps) => {
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<DragNdrop text={LL.UPLOAD_DROP_TEXT()} onFileSelected={setFile} />
|
||||
<DragNdrop text={text} onFileSelected={setFile} />
|
||||
)}
|
||||
|
||||
{md5 && (
|
||||
<Box sx={{ mt: 2 }}>
|
||||
<Box mt={2}>
|
||||
<Typography variant="body2">{'MD5: ' + md5}</Typography>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
@@ -186,8 +186,7 @@ const cz: Translation = {
|
||||
BUFFER_SIZE: 'Maximální velikost vyrovnávací paměti',
|
||||
COMPACT: 'Kompaktní',
|
||||
DOWNLOAD_SETTINGS_TEXT: 'Vytvořte zálohu svého nastavení a konfigurace',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Exportovat všechny hodnoty',
|
||||
DOWNLOAD_SYSTEM_BACKUP: 'Systémová záloha',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Exportovat všechna data',
|
||||
UPLOAD_TEXT: 'Nahrajte nový soubor firmwaru (.bin) nebo záložní soubor (.json)',
|
||||
UPLOAD_DROP_TEXT: 'Přetáhněte soubor sem nebo klikněte pro výběr',
|
||||
ERROR: 'Neočekávaná chyba, zkuste to prosím znovu',
|
||||
@@ -220,7 +219,6 @@ const cz: Translation = {
|
||||
MQTT_PUBLISH_TEXT_3: 'Povolit MQTT Discovery',
|
||||
MQTT_PUBLISH_TEXT_4: 'Prefix pro Discovery témata',
|
||||
MQTT_PUBLISH_TEXT_5: 'Typ Discovery',
|
||||
MQTT_INPUT_NUMBER_FORMAT: 'Formát čísla',
|
||||
MQTT_PUBLISH_INTERVALS: 'Intervaly publikování',
|
||||
MQTT_INT_BOILER: 'Kotle a tepelná čerpadla',
|
||||
MQTT_INT_THERMOSTATS: 'Termostaty',
|
||||
@@ -350,22 +348,15 @@ const cz: Translation = {
|
||||
NO_DATA_1: 'Nebyly nalezeny žádné oblíbené entity. Použijte modul',
|
||||
NO_DATA_2: 'pro jejich výběr.',
|
||||
NO_DATA_3: 'Pro zobrazení všech dostupných entit navštivte stránku',
|
||||
NO_GPIO:'Nebylo nalezeno žádné volné GPIO',
|
||||
THIS_VERSION: 'Tato verze',
|
||||
PLATFORM: 'Platforma',
|
||||
RELEASE_TYPE: 'Typ sestavení',
|
||||
INTERNET_CONNECTION_REQUIRED: 'Pro automatickou kontrolu a instalaci aktualizací je třeba internetové připojení',
|
||||
SWITCH_RELEASE_TYPE: 'Přepnout na {0} verzi',
|
||||
FIRMWARE_VERSION_INFO: 'Informace o verzi firmwaru',
|
||||
NO_DATA: 'žádné údaje',
|
||||
NO_DATA: 'Žádná data',
|
||||
USER_PROFILE: 'Uživatelský profil',
|
||||
STORED_VERSIONS: 'Uložené verze',
|
||||
ONLINE_HELP: 'online nápověda',
|
||||
UPGRADE_IMPORTANT_MESSAGES: 'Aktualizovat důležité zprávy',
|
||||
UPGRADE_IMPORTANT_MESSAGES_1: 'Tato aktualizace vyžaduje obnovení továrního nastavení. Ujistěte se, že jste vytvořili zálohu své konfigurace a nastavení před pokračováním a nahrajte ji po instalaci nové verze.',
|
||||
UPGRADE_IMPORTANT_MESSAGES_2: 'Aktualizujete se na novou hlavní verzi. Ujistěte se, že jste přečetli ChangeLog pro jakékoliv závažné změny.',
|
||||
WARNING_SYSTEM_BACKUP: 'Toto vytvoří zálohu vašich celých systémových konfigurací a nastavení. Všechna hesla budou v zálohovém souboru čitelná. Buďte opatrní při sdílení! Opravdu chcete pokračovat?'
|
||||
|
||||
STORED_VERSIONS: 'Uložené verze'
|
||||
};
|
||||
|
||||
export default cz;
|
||||
|
||||
@@ -186,8 +186,7 @@ const de: Translation = {
|
||||
BUFFER_SIZE: 'Max. Puffergröße',
|
||||
COMPACT: 'Kompakte Darstellung',
|
||||
DOWNLOAD_SETTINGS_TEXT: 'Erstellen Sie eine Sicherung Ihrer Konfigurationen und Einstellungen',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Exportiere alle Werte',
|
||||
DOWNLOAD_SYSTEM_BACKUP: 'System Sicherung',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Exportiere alle Daten',
|
||||
UPLOAD_TEXT: 'Laden Sie eine neue Firmware-Datei (.bin) oder eine Sicherungsdatei (.json) hoch',
|
||||
UPLOAD_DROP_TEXT: 'Legen Sie eine Firmware-Datei (.bin) ab oder klicken Sie hier',
|
||||
ERROR: 'Unerwarteter Fehler, bitte versuchen Sie es erneut.',
|
||||
@@ -220,7 +219,6 @@ const de: Translation = {
|
||||
MQTT_PUBLISH_TEXT_3: 'Aktiviere `MQTT Discovery`',
|
||||
MQTT_PUBLISH_TEXT_4: 'Prefix für die `Discovery`-Topics',
|
||||
MQTT_PUBLISH_TEXT_5: 'Discovery Typ',
|
||||
MQTT_INPUT_NUMBER_FORMAT: 'Zahlenformat',
|
||||
MQTT_PUBLISH_INTERVALS: 'Veröffentlichungs-Intervalle',
|
||||
MQTT_INT_BOILER: 'Boiler und Wärmepumpen',
|
||||
MQTT_INT_THERMOSTATS: 'Thermostate',
|
||||
@@ -350,7 +348,6 @@ const de: Translation = {
|
||||
NO_DATA_1: 'Keine favorisierten EMS-Entitäten gefunden! Verwenden Sie das Modul',
|
||||
NO_DATA_2: ', um sie zu markieren.',
|
||||
NO_DATA_3: 'Um alle verfügbaren Entitäten anzuzeigen, gehen Sie zu',
|
||||
NO_GPIO:'Keine freien GPIO gefunden',
|
||||
THIS_VERSION: 'Diese Version',
|
||||
PLATFORM: 'Plattform',
|
||||
RELEASE_TYPE: 'Release Typ',
|
||||
@@ -359,13 +356,7 @@ const de: Translation = {
|
||||
FIRMWARE_VERSION_INFO: 'Firmware-Versionsinformation',
|
||||
NO_DATA: 'Keine Daten',
|
||||
USER_PROFILE: 'Benutzerprofil',
|
||||
STORED_VERSIONS: 'Gespeicherte Versionen',
|
||||
ONLINE_HELP: 'Online-Hilfe',
|
||||
UPGRADE_IMPORTANT_MESSAGES: 'Wichtige Nachrichten aktualisieren',
|
||||
UPGRADE_IMPORTANT_MESSAGES_1: 'Diese Aktualisierung erfordert eine Werkseinstellung. Stellen Sie sicher, dass Sie eine Sicherung Ihrer Konfiguration und Einstellungen vor dem Fortfahren erstellt haben und diese nach der Installation der neuen Version hochladen.',
|
||||
UPGRADE_IMPORTANT_MESSAGES_2: 'Sie aktualisieren auf eine neue Hauptversion. Stellen Sie sicher, dass Sie den ChangeLog für alle wichtigen Änderungen gelesen haben.',
|
||||
WARNING_SYSTEM_BACKUP: 'Dies wird eine Sicherung Ihrer vollständigen Systemkonfiguration und -einstellungen erstellen. Alle Passwörter werden im Sicherungsdatei lesbar sein. Seien Sie vorsichtig beim Teilen! Möchten Sie fortfahren?'
|
||||
|
||||
STORED_VERSIONS: 'Gespeicherte Versionen'
|
||||
};
|
||||
|
||||
export default de;
|
||||
|
||||
@@ -186,8 +186,7 @@ const en: Translation = {
|
||||
BUFFER_SIZE: 'Max Buffer Size',
|
||||
COMPACT: 'Compact',
|
||||
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Export all values',
|
||||
DOWNLOAD_SYSTEM_BACKUP: 'System Backup',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Export all data',
|
||||
UPLOAD_TEXT: 'Upload a new firmware file (.bin) or a backup file (.json)',
|
||||
UPLOAD_DROP_TEXT: 'Drop a firmware .bin file or click here',
|
||||
ERROR: 'Unexpected Error, please try again',
|
||||
@@ -220,7 +219,6 @@ const en: Translation = {
|
||||
MQTT_PUBLISH_TEXT_3: 'Enable MQTT Discovery',
|
||||
MQTT_PUBLISH_TEXT_4: 'Prefix for the Discovery topics',
|
||||
MQTT_PUBLISH_TEXT_5: 'Discovery type',
|
||||
MQTT_INPUT_NUMBER_FORMAT: 'Input Number Fomat',
|
||||
MQTT_PUBLISH_INTERVALS: 'Publish Intervals',
|
||||
MQTT_INT_BOILER: 'Boilers and Heat Pumps',
|
||||
MQTT_INT_THERMOSTATS: 'Thermostats',
|
||||
@@ -350,7 +348,6 @@ const en: Translation = {
|
||||
NO_DATA_1: 'No favorite EMS entities found yet. Use the',
|
||||
NO_DATA_2: 'module to mark them.',
|
||||
NO_DATA_3: 'To see all available entities go to',
|
||||
NO_GPIO:'No available GPIO found',
|
||||
THIS_VERSION: 'This Version',
|
||||
PLATFORM: 'Platform',
|
||||
RELEASE_TYPE: 'Release Type',
|
||||
@@ -359,13 +356,7 @@ const en: Translation = {
|
||||
FIRMWARE_VERSION_INFO: 'Firmware Version Information',
|
||||
NO_DATA: 'No data',
|
||||
USER_PROFILE: 'User Profile',
|
||||
STORED_VERSIONS: 'Stored Versions',
|
||||
ONLINE_HELP: 'online help',
|
||||
UPGRADE_IMPORTANT_MESSAGES: 'Upgrade Important Messages',
|
||||
UPGRADE_IMPORTANT_MESSAGES_1: 'This upgrade requires a factory reset. Make sure you have made a backup of your configuration and settings before continuing, and upload this after the new version is installed.',
|
||||
UPGRADE_IMPORTANT_MESSAGES_2: 'You are upgrading to a new major version. Make sure you have read the ChangeLog for any breaking changes.',
|
||||
WARNING_SYSTEM_BACKUP: 'This will create a backup of your full system configuration and settings. All passwords will be readable in the backup file. Be careful with sharing! Do you want to continue?'
|
||||
|
||||
STORED_VERSIONS: 'Stored Versions'
|
||||
};
|
||||
|
||||
export default en;
|
||||
|
||||
@@ -186,8 +186,7 @@ const fr: Translation = {
|
||||
BUFFER_SIZE: 'Max taille du buffer',
|
||||
COMPACT: 'Compact',
|
||||
DOWNLOAD_SETTINGS_TEXT: 'Créer une sauvegarde de vos paramètres et configurations',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Exporter toutes les valeurs',
|
||||
DOWNLOAD_SYSTEM_BACKUP: 'Sauvegarde système',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Exporter toutes les données',
|
||||
UPLOAD_TEXT: 'Télécharger un nouveau fichier firmware (.bin) ou une sauvegarde (.json)',
|
||||
UPLOAD_DROP_TEXT: 'Drop a firmware .bin file or click here',
|
||||
ERROR: 'Erreur inattendue, veuillez réessayer',
|
||||
@@ -220,7 +219,6 @@ const fr: Translation = {
|
||||
MQTT_PUBLISH_TEXT_3: 'Activer la découverte MQTT',
|
||||
MQTT_PUBLISH_TEXT_4: 'Préfixe pour les topics découverte',
|
||||
MQTT_PUBLISH_TEXT_5: 'Type de découverte',
|
||||
MQTT_INPUT_NUMBER_FORMAT: 'Format des nombres',
|
||||
MQTT_PUBLISH_INTERVALS: 'Intervalles de publication',
|
||||
MQTT_INT_BOILER: 'Chaudières et pompes à chaleur',
|
||||
MQTT_INT_THERMOSTATS: 'Thermostats',
|
||||
@@ -350,7 +348,6 @@ const fr: Translation = {
|
||||
NO_DATA_1: 'Aucune entité EMS favorite trouvée. Utilisez le',
|
||||
NO_DATA_2: 'module pour les marquer.',
|
||||
NO_DATA_3: 'Pour voir toutes les entités disponibles, aller à',
|
||||
NO_GPIO:"Aucun GPIO disponible n'a été détecté",
|
||||
THIS_VERSION: 'Cette version',
|
||||
PLATFORM: 'Plateforme',
|
||||
RELEASE_TYPE: 'Type de version',
|
||||
@@ -359,13 +356,7 @@ const fr: Translation = {
|
||||
FIRMWARE_VERSION_INFO: 'Informations sur la version du firmware',
|
||||
NO_DATA: 'Aucune donnée',
|
||||
USER_PROFILE: 'Profil utilisateur',
|
||||
STORED_VERSIONS: 'Versions stockées',
|
||||
ONLINE_HELP: 'aide en ligne',
|
||||
UPGRADE_IMPORTANT_MESSAGES: 'Mettre à jour les messages importants',
|
||||
UPGRADE_IMPORTANT_MESSAGES_1: 'Cette mise à jour nécessite une réinitialisation de fabrique. Assurez-vous d\'avoir créé une sauvegarde de vos configurations et paramètres avant de continuer et de la charger après l\'installation de la nouvelle version.',
|
||||
UPGRADE_IMPORTANT_MESSAGES_2: 'Vous mettez à jour vers une nouvelle version majeure. Assurez-vous de lire le ChangeLog pour tout changement important.',
|
||||
WARNING_SYSTEM_BACKUP: 'Cela créera une sauvegarde de votre configuration et paramètres complets. Tous les mots de passe seront lisibles dans le fichier de sauvegarde. Soyez prudent avec le partage ! Voulez-vous continuer ?'
|
||||
|
||||
STORED_VERSIONS: 'Versions stockées'
|
||||
};
|
||||
|
||||
export default fr;
|
||||
|
||||
@@ -186,8 +186,7 @@ const it: Translation = {
|
||||
BUFFER_SIZE: 'Max Buffer Size',
|
||||
COMPACT: 'Compatto',
|
||||
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Esporta tutti i valori',
|
||||
DOWNLOAD_SYSTEM_BACKUP: 'Backup sistema',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Esporta tutti i dati',
|
||||
UPLOAD_TEXT: 'Upload a new firmware file (.bin) or a backup file (.json)',
|
||||
UPLOAD_DROP_TEXT: 'Drop a firmware .bin file or click here',
|
||||
ERROR: 'Errore Inaspettato, prego tenta ancora',
|
||||
@@ -220,7 +219,6 @@ const it: Translation = {
|
||||
MQTT_PUBLISH_TEXT_3: 'Abilita rilevamento MQTT (Home Assistant, Domoticz)',
|
||||
MQTT_PUBLISH_TEXT_4: 'Prefisso per gli argomenti di scoperta',
|
||||
MQTT_PUBLISH_TEXT_5: 'Discovery type',
|
||||
MQTT_INPUT_NUMBER_FORMAT: 'Formato numero di input',
|
||||
MQTT_PUBLISH_INTERVALS: 'Pubblica intervalli',
|
||||
MQTT_INT_BOILER: 'Caldaie e Pompe di Calore',
|
||||
MQTT_INT_THERMOSTATS: 'Termostati',
|
||||
@@ -350,7 +348,6 @@ const it: Translation = {
|
||||
NO_DATA_1: 'Nessuna entità EMS preferita trovata. Usa il',
|
||||
NO_DATA_2: 'modulo per marcarle.',
|
||||
NO_DATA_3: 'Per vedere tutte le entità disponibili vai a',
|
||||
NO_GPIO:'Non è stato trovato alcun GPIO disponibile',
|
||||
THIS_VERSION: 'Questa versione',
|
||||
PLATFORM: 'Piattaforma',
|
||||
RELEASE_TYPE: 'Tipo di rilascio',
|
||||
@@ -359,13 +356,7 @@ const it: Translation = {
|
||||
FIRMWARE_VERSION_INFO: 'Informazioni sulla versione del firmware',
|
||||
NO_DATA: 'Nessun dato',
|
||||
USER_PROFILE: 'Profilo utente',
|
||||
STORED_VERSIONS: 'Versioni memorizzate',
|
||||
ONLINE_HELP: 'aiuto online',
|
||||
UPGRADE_IMPORTANT_MESSAGES: 'Aggiorna Messaggi Importanti',
|
||||
UPGRADE_IMPORTANT_MESSAGES_1: 'Questa aggiornamento richiede un ripristino di fabbrica. Assicurati di aver creato un backup delle tue configurazioni e impostazioni prima di continuare e di caricarlo dopo l\'installazione della nuova versione.',
|
||||
UPGRADE_IMPORTANT_MESSAGES_2: 'Stai aggiornando a una nuova versione principale. Assicurati di aver letto il ChangeLog per qualsiasi cambiamento importante.',
|
||||
WARNING_SYSTEM_BACKUP: 'Questo creerà un backup delle tue configurazioni e impostazioni complete. Tutte le password saranno leggibili nel file di backup. Sei sicuro di voler continuare?'
|
||||
|
||||
STORED_VERSIONS: 'Versioni memorizzate'
|
||||
};
|
||||
|
||||
export default it;
|
||||
|
||||
@@ -27,7 +27,7 @@ const nl: Translation = {
|
||||
REFRESH: 'Ververs',
|
||||
EXPORT: 'Export',
|
||||
FAVORITES: "Favorieten",
|
||||
DEVICE_DETAILS: 'Apparaat Gegevens',
|
||||
DEVICE_DETAILS: 'Device Gegevens',
|
||||
ID_OF: '{0} ID',
|
||||
DEVICE: 'Apparaat',
|
||||
PRODUCT: 'Product',
|
||||
@@ -65,7 +65,7 @@ const nl: Translation = {
|
||||
TEMP_SENSOR: 'Temperatuur sensor',
|
||||
TEMP_SENSORS: 'Temperatuur Sensoren',
|
||||
WRITE_CMD_SENT: 'Schrijf commando gestuurd',
|
||||
EMS_BUS_WARNING: 'EMS bus niet gevonden. Als deze waarschuwing blijft staan na een paar seconden loop dan de instellingen na en in het bijzonder het apparaat type profiel.',
|
||||
EMS_BUS_WARNING: 'EMS bus niet gevonden. Als deze waarschuwing blijft staan na een paar seconden dan loop de instellingen na en in het bijzonder het apparaat type profiel na.',
|
||||
EMS_BUS_SCANNING: 'Scannen naar EMS apparaten...',
|
||||
CONNECTED: 'Verbonden',
|
||||
TX_ISSUES: 'Tx bus probleem. Probeer een andere Tx verzendmodus',
|
||||
@@ -75,7 +75,7 @@ const nl: Translation = {
|
||||
EMS_DEVICE: 'EMS Apparaat',
|
||||
SUCCESS: 'SUCCESS',
|
||||
FAIL: 'MISLUKT',
|
||||
QUALITY: 'KWALITEIT',
|
||||
QUALITY: 'QUALITEIT',
|
||||
SCAN: 'Scan',
|
||||
STATUS_NAMES: [
|
||||
'EMS Telegrammen ontvangen (Rx)',
|
||||
@@ -120,7 +120,7 @@ const nl: Translation = {
|
||||
ENABLE_SHOWER_TIMER: 'Activeer Douche Timer (tijdmeting)',
|
||||
ENABLE_SHOWER_ALERT: 'Activeer Douchemelding',
|
||||
TRIGGER_TIME: 'Trigger tijd',
|
||||
COLD_SHOT_DURATION: 'Lengte koud water puls',
|
||||
COLD_SHOT_DURATION: 'Tijd Shot koud water',
|
||||
FORMATTING_OPTIONS: 'Formatteringsopties',
|
||||
BOOLEAN_FORMAT_DASHBOARD: 'Boolean formaat web',
|
||||
BOOLEAN_FORMAT_API: 'Boolean formaat API/MQTT',
|
||||
@@ -143,7 +143,7 @@ const nl: Translation = {
|
||||
CUSTOMIZATIONS_FULL: 'Te veel entiteiten geselecteerd. Sla op in delen aub',
|
||||
CUSTOMIZATIONS_SAVED: 'Custom aanpassingen opgeslagen',
|
||||
CUSTOMIZATIONS_HELP_1: 'Selecteer een apparaat en pas de entiteiten aan door middel van de opties',
|
||||
CUSTOMIZATIONS_HELP_2: 'Markeer als favoriet',
|
||||
CUSTOMIZATIONS_HELP_2: 'Markeer as favoriet',
|
||||
CUSTOMIZATIONS_HELP_3: 'Zet schrijfacties uit',
|
||||
CUSTOMIZATIONS_HELP_4: 'Uitsluiten van MQTT en API',
|
||||
CUSTOMIZATIONS_HELP_5: 'verbergen voor apparaten',
|
||||
@@ -186,13 +186,12 @@ const nl: Translation = {
|
||||
BUFFER_SIZE: 'Max buffer grootte',
|
||||
COMPACT: 'Compact',
|
||||
DOWNLOAD_SETTINGS_TEXT: 'Maak een back-up van uw configuratie en instellingen',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Exporteer alle waarden',
|
||||
DOWNLOAD_SYSTEM_BACKUP: 'Systeem Backup',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Exporteer alle data',
|
||||
UPLOAD_TEXT: 'Upload een nieuw firmwarebestand (.bin) of een back-upbestand (.json)',
|
||||
UPLOAD_DROP_TEXT: 'Sleep en firmware .bin bestand hierheen of klik hier',
|
||||
ERROR: 'Onverwachte fout, probeer opnieuw',
|
||||
TIME_SET: 'Tijd ingesteld',
|
||||
MANAGE_USERS: 'Gebruikersbeheer',
|
||||
MANAGE_USERS: 'Beheer Gebruikers',
|
||||
IS_ADMIN: 'is Admin',
|
||||
USER_WARNING: 'U dient tenminste 1 admin gebruiker te configureren',
|
||||
ADD: 'Toevoegen',
|
||||
@@ -201,7 +200,7 @@ const nl: Translation = {
|
||||
GENERATING_TOKEN: 'Token aan het genereren',
|
||||
USER: 'Gebruiker',
|
||||
MODIFY: 'Aanpassen',
|
||||
SU_TEXT: 'Het su (super user) wachtwoord wordt gebruikt om authorisatie tokens te ondertekenen en ook om admin privileges te activeren in de console.',
|
||||
SU_TEXT: 'Het su (super user) wachtwoord wordt gebruikt om authorisatie tokens te signeren en ook om admin privileges te activeren in de console.',
|
||||
NOT_ENABLED: 'Niet geactiveerd',
|
||||
ERRORS_OF: '{0} Foutmeldingen',
|
||||
DISCONNECT_REASON: 'Verbinding verbroken vanwege',
|
||||
@@ -220,7 +219,6 @@ const nl: Translation = {
|
||||
MQTT_PUBLISH_TEXT_3: 'Activeer MQTT Discovery',
|
||||
MQTT_PUBLISH_TEXT_4: 'Prefix voor de Discovery topics',
|
||||
MQTT_PUBLISH_TEXT_5: 'Discovery type',
|
||||
MQTT_INPUT_NUMBER_FORMAT: 'Getalformaat',
|
||||
MQTT_PUBLISH_INTERVALS: 'Publicatie intervallen',
|
||||
MQTT_INT_BOILER: 'CV ketels en warmtepompen',
|
||||
MQTT_INT_THERMOSTATS: 'Thermostaten',
|
||||
@@ -350,7 +348,6 @@ const nl: Translation = {
|
||||
NO_DATA_1: 'Er zijn nog geen favoriete EMS-entiteiten gevonden. Gebruik de',
|
||||
NO_DATA_2: 'module om ze te markeren.',
|
||||
NO_DATA_3: 'Om alle beschikbare entiteiten te zien, ga naar',
|
||||
NO_GPIO:'Er is geen beschikbare GPIO gevonden',
|
||||
THIS_VERSION: 'Deze Versie',
|
||||
PLATFORM: 'Platform',
|
||||
RELEASE_TYPE: 'Release Typ',
|
||||
@@ -359,13 +356,7 @@ const nl: Translation = {
|
||||
FIRMWARE_VERSION_INFO: 'Informatie over firmwareversie',
|
||||
NO_DATA: 'Geen data',
|
||||
USER_PROFILE: 'Gebruikersprofiel',
|
||||
STORED_VERSIONS: 'Opgeslagen versies',
|
||||
ONLINE_HELP: 'online help',
|
||||
UPGRADE_IMPORTANT_MESSAGES: 'Upgrade Belangrijke Berichten',
|
||||
UPGRADE_IMPORTANT_MESSAGES_1: 'Deze upgrade vereist een fabrieksinstelling. Zorg ervoor dat u een back-up van uw configuratie en instellingen hebt gemaakt voordat u doorgaat en upload deze na de installatie van de nieuwe versie.',
|
||||
UPGRADE_IMPORTANT_MESSAGES_2: 'U updatet naar een nieuwe grote versie. Zorg ervoor dat u de ChangeLog hebt gelezen voor alle brekende wijzigingen.',
|
||||
WARNING_SYSTEM_BACKUP: 'Dit zal een back-up van uw volledige systeemconfiguratie en instellingen maken. Alle wachtwoorden zijn leesbaar in het back-upbestand. Wees voorzichtig bij delen! Wilt u doorgaan?'
|
||||
|
||||
STORED_VERSIONS: 'Opgeslagen versies'
|
||||
};
|
||||
|
||||
export default nl;
|
||||
export default nl;
|
||||
@@ -186,8 +186,7 @@ const no: Translation = {
|
||||
BUFFER_SIZE: 'Max Buffer Størrelse',
|
||||
COMPACT: 'Komprimere',
|
||||
DOWNLOAD_SETTINGS_TEXT: 'Lag en sikkerhetskopi av dine konfigurasjon og innstillinger',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Eksporter alle verdier',
|
||||
DOWNLOAD_SYSTEM_BACKUP: 'System Sikkerhetskopi',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Eksporter alle data',
|
||||
UPLOAD_TEXT: 'Last opp en ny firmware fil (.bin) eller en sikkerhetskopi fil (.json)',
|
||||
UPLOAD_DROP_TEXT: 'Dropp en firmware fil (.bin) eller klikk her',
|
||||
ERROR: 'Ukjent feil, prøv igjen',
|
||||
@@ -220,7 +219,6 @@ const no: Translation = {
|
||||
MQTT_PUBLISH_TEXT_3: 'Aktiver MQTT Discovery',
|
||||
MQTT_PUBLISH_TEXT_4: 'Prefiks for Discovery topics',
|
||||
MQTT_PUBLISH_TEXT_5: 'Discovery type',
|
||||
MQTT_INPUT_NUMBER_FORMAT: 'Nummerformat',
|
||||
MQTT_PUBLISH_INTERVALS: 'Publiseringsintervall',
|
||||
MQTT_INT_BOILER: 'Fyr/Varmepumpe',
|
||||
MQTT_INT_THERMOSTATS: 'Termostat',
|
||||
@@ -350,7 +348,6 @@ const no: Translation = {
|
||||
NO_DATA_1: 'Ingen favoritte EMS enheter funnet enda. Bruk',
|
||||
NO_DATA_2: 'modul for å markere dem.',
|
||||
NO_DATA_3: 'For å se alle tilgjengelige enheter, gå til',
|
||||
NO_GPIO:'Det ble ikke funnet noen tilgjengelige GPIO-porter',
|
||||
THIS_VERSION: 'Denne versjonen',
|
||||
PLATFORM: 'Plattform',
|
||||
RELEASE_TYPE: 'Utgivelses type',
|
||||
@@ -359,13 +356,7 @@ const no: Translation = {
|
||||
FIRMWARE_VERSION_INFO: 'Informasjon om firmwareversjon',
|
||||
NO_DATA: 'Ingen data',
|
||||
USER_PROFILE: 'Brukerprofil',
|
||||
STORED_VERSIONS: 'Lagret versjoner',
|
||||
ONLINE_HELP: 'online hjelp',
|
||||
UPGRADE_IMPORTANT_MESSAGES: 'Oppdater viktige meldinger',
|
||||
UPGRADE_IMPORTANT_MESSAGES_1: 'Denne oppdateringen krever en fabriksinstilling. Sørg for at du har laget en sikkerhetskopi av din konfigurasjon og innstillinger før du fortsetter, og last denne opp etter at den nye versjonen er installert.',
|
||||
UPGRADE_IMPORTANT_MESSAGES_2: 'Du oppdaterer til en ny hovedversjon. Sørg for at du har lest ChangeLog for eventuelle bruddende endringer.',
|
||||
WARNING_SYSTEM_BACKUP: 'Dette vil lage en sikkerhetskopi av din fullstendige systemkonfigurasjon og innstillinger. Alle passord vil være lesbare i sikkerhetskopien. Vær forsiktig med deling! Vil du fortsette?'
|
||||
|
||||
STORED_VERSIONS: 'Lagret versjoner'
|
||||
};
|
||||
|
||||
export default no;
|
||||
|
||||
@@ -186,8 +186,7 @@ const pl: BaseTranslation = {
|
||||
BUFFER_SIZE: 'Maksymalna pojemność bufora (ilość wpisów)',
|
||||
COMPACT: 'Kompaktowy',
|
||||
DOWNLOAD_SETTINGS_TEXT: 'Utwórz kopię swoich ustawień i konfiguracji',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Eksportuj wszystkie wartości',
|
||||
DOWNLOAD_SYSTEM_BACKUP: 'Kopia zapasowa systemu',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Eksportuj wszystkie dane',
|
||||
UPLOAD_TEXT: 'Wgraj nowy plik firmware (.bin) lub kopię ustawień (.json)',
|
||||
UPLOAD_DROP_TEXT: 'Upuść plik firmware .bin lub kliknij tutaj',
|
||||
ERROR: 'Nieoczekiwany błąd, spróbuj ponownie!',
|
||||
@@ -220,7 +219,6 @@ const pl: BaseTranslation = {
|
||||
MQTT_PUBLISH_TEXT_3: 'Włącz opcję "MQTT discovery"',
|
||||
MQTT_PUBLISH_TEXT_4: 'Prefiks dla "MQTT discovery"',
|
||||
MQTT_PUBLISH_TEXT_5: 'Typ "MQTT discovery"',
|
||||
MQTT_INPUT_NUMBER_FORMAT: 'Format liczby',
|
||||
MQTT_PUBLISH_INTERVALS: 'Interwały publikowania',
|
||||
MQTT_INT_BOILER: 'Kotły i pompy ciepła',
|
||||
MQTT_INT_THERMOSTATS: 'Termostaty',
|
||||
@@ -350,7 +348,6 @@ const pl: BaseTranslation = {
|
||||
NO_DATA_1: 'Brak ulubionych encji EMS. Użyj',
|
||||
NO_DATA_2: 'moduł do ich oznaczenia.',
|
||||
NO_DATA_3: 'Aby zobaczyć wszystkie dostępne encje przejdź do',
|
||||
NO_GPIO:'Nie znaleziono dostępnych pinów GPIO',
|
||||
THIS_VERSION: 'Ta wersja',
|
||||
PLATFORM: 'Platforma',
|
||||
RELEASE_TYPE: 'Typ wydania',
|
||||
@@ -359,13 +356,7 @@ const pl: BaseTranslation = {
|
||||
FIRMWARE_VERSION_INFO: 'Informacje o wersji firmware',
|
||||
NO_DATA: 'Brak danych',
|
||||
USER_PROFILE: 'Profil użytkownika',
|
||||
STORED_VERSIONS: 'Zapisane wersje',
|
||||
ONLINE_HELP: 'pomoc online',
|
||||
UPGRADE_IMPORTANT_MESSAGES: 'Aktualizuj ważne wiadomości',
|
||||
UPGRADE_IMPORTANT_MESSAGES_1: 'Ta aktualizacja wymaga resetu fabrycznego. Upewnij się, że masz utworzoną kopię swoich ustawień i konfiguracji przed kontynuowaniem i przesuń ją po zainstalowaniu nowej wersji.',
|
||||
UPGRADE_IMPORTANT_MESSAGES_2: 'Aktualizujesz się do nowej głównej wersji. Upewnij się, że przeczytałeś ChangeLog dla wszelkich istotnych zmian.',
|
||||
WARNING_SYSTEM_BACKUP: 'To spowoduje utworzenie kopii zapasowej całej konfiguracji i ustawień systemu. Wszystkie hasła będą widoczne w pliku kopii zapasowej. Bądź ostrożny przy udostępnianiu! Chcesz kontynuować?'
|
||||
|
||||
STORED_VERSIONS: 'Zapisane wersje'
|
||||
};
|
||||
|
||||
export default pl;
|
||||
|
||||
@@ -4,7 +4,7 @@ const sk: Translation = {
|
||||
LANGUAGE: 'Jazyk',
|
||||
RETRY: 'Opakovať',
|
||||
LOADING: 'Načítanie',
|
||||
IS_REQUIRED: '{0} je požadovaná',
|
||||
IS_REQUIRED: '{0} je požadovaných',
|
||||
SIGN_IN: 'Prihlásiť sa',
|
||||
SIGN_OUT: 'Odhlásiť sa',
|
||||
USERNAME: 'Užívateľské meno',
|
||||
@@ -186,8 +186,7 @@ const sk: Translation = {
|
||||
BUFFER_SIZE: 'Buffer-max. veľkosť',
|
||||
COMPACT: 'Kompaktné',
|
||||
DOWNLOAD_SETTINGS_TEXT: 'Vytvorte zálohu svojej konfigurácie a nastavení',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Exportovať všetky hodnoty',
|
||||
DOWNLOAD_SYSTEM_BACKUP: 'Systémová záloha',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Exportovať všetky dáta',
|
||||
UPLOAD_TEXT: 'Nahrajte nový súbor firmvéru (.bin) alebo súbor zálohy (.json)',
|
||||
UPLOAD_DROP_TEXT: 'Presuňte súbor .bin firmvéru alebo kliknite sem',
|
||||
ERROR: 'Neočakávaná chyba, prosím skúste to znova',
|
||||
@@ -220,7 +219,6 @@ const sk: Translation = {
|
||||
MQTT_PUBLISH_TEXT_3: 'Povolenie zisťovania MQTT',
|
||||
MQTT_PUBLISH_TEXT_4: 'Predpona tém Discovery',
|
||||
MQTT_PUBLISH_TEXT_5: 'Typ zistenia',
|
||||
MQTT_INPUT_NUMBER_FORMAT: 'Formát čísla',
|
||||
MQTT_PUBLISH_INTERVALS: 'Intervaly zverejňovania',
|
||||
MQTT_INT_BOILER: 'Kotly a tepelné čerpadlá',
|
||||
MQTT_INT_THERMOSTATS: 'Termostaty',
|
||||
@@ -276,11 +274,11 @@ const sk: Translation = {
|
||||
NETWORK_SUBNET: 'Maska podsiete',
|
||||
NETWORK_DNS: 'DNS servery',
|
||||
ADDRESS_OF: '{0} adresa',
|
||||
ADMINISTRATOR: 'Administrátor',
|
||||
ADMINISTRATOR: 'Administrator',
|
||||
GUEST: 'Hosť',
|
||||
NEW: 'Novú',
|
||||
NEW: 'Nová',
|
||||
NEW_NAME_OF: 'Nový názov {0}',
|
||||
ENTITY: 'entitu',
|
||||
ENTITY: 'entita',
|
||||
MIN: 'min',
|
||||
MAX: 'max',
|
||||
BLOCK_NAVIGATE_1: 'Máte neuložené zmeny',
|
||||
@@ -350,7 +348,6 @@ const sk: Translation = {
|
||||
NO_DATA_1: 'Nenašli sa žiadne obľúbené entity EMS. Použite',
|
||||
NO_DATA_2: 'modul na ich označenie.',
|
||||
NO_DATA_3: 'Ak chcete zobraziť všetky dostupné entity, prejdite na',
|
||||
NO_GPIO:'Nebol nájdený žiadny dostupný GPIO',
|
||||
THIS_VERSION: 'Táto verzia',
|
||||
PLATFORM: 'Platforma',
|
||||
RELEASE_TYPE: 'Typ vydania',
|
||||
@@ -359,13 +356,7 @@ const sk: Translation = {
|
||||
FIRMWARE_VERSION_INFO: 'Informácie o verzii firmware',
|
||||
NO_DATA: 'Žiadne dáta',
|
||||
USER_PROFILE: 'Profil používateľa',
|
||||
STORED_VERSIONS: 'Uložené verzie',
|
||||
ONLINE_HELP: 'online pomoc',
|
||||
UPGRADE_IMPORTANT_MESSAGES: 'Aktualizovať dôležité správy',
|
||||
UPGRADE_IMPORTANT_MESSAGES_1: 'Táto aktualizácia vyžaduje reštart základných nastavení. Uistite sa, že ste vytvorili zálohu svojich konfigurácií a nastavení pred pokračovaním a nahrajte ju po instalácii novej verzie.',
|
||||
UPGRADE_IMPORTANT_MESSAGES_2: 'Aktualizujete sa na novú hlavnú verziu. Uistite sa, že ste prečítali ChangeLog pre akékoľvek dôležité zmeny.',
|
||||
WARNING_SYSTEM_BACKUP: 'Toto vytvorí zálohu všetkých vašich celých systémových konfigurácií a nastavení. Všetky hesla budú čitateľné v zálohovom súbore. Buďte opatrní pri zdieľaní! Chcete pokračovať?'
|
||||
|
||||
STORED_VERSIONS: 'Uložené verzie'
|
||||
};
|
||||
|
||||
export default sk;
|
||||
|
||||
@@ -186,8 +186,7 @@ const sv: Translation = {
|
||||
BUFFER_SIZE: 'Max bufferstorlek',
|
||||
COMPACT: 'Komprimerad',
|
||||
DOWNLOAD_SETTINGS_TEXT: 'Skapa en säkerhetskopia av din konfiguration och inställningar',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Exportera alla värden',
|
||||
DOWNLOAD_SYSTEM_BACKUP: 'System säkerhetskopia',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Exportera alla data',
|
||||
UPLOAD_TEXT: 'Ladda upp en ny firmwarefil (.bin) eller en säkerhetskopiafil (.json)',
|
||||
UPLOAD_DROP_TEXT: 'Droppa en firmware .bin fil eller klicka här',
|
||||
ERROR: 'Okänt fel, var god försök igen',
|
||||
@@ -220,7 +219,6 @@ const sv: Translation = {
|
||||
MQTT_PUBLISH_TEXT_3: 'Aktivera MQTT Discovery',
|
||||
MQTT_PUBLISH_TEXT_4: 'Prefix för Discovery topics',
|
||||
MQTT_PUBLISH_TEXT_5: 'Discoverytyp',
|
||||
MQTT_INPUT_NUMBER_FORMAT: 'Nummerformat',
|
||||
MQTT_PUBLISH_INTERVALS: 'Publiceringsintervall',
|
||||
MQTT_INT_BOILER: 'Värmepump/panna',
|
||||
MQTT_INT_THERMOSTATS: 'Termostater',
|
||||
@@ -350,7 +348,6 @@ const sv: Translation = {
|
||||
NO_DATA_1: 'Inga favorit EMS enheter hittade än. Använd',
|
||||
NO_DATA_2: 'modul för att markera dem.',
|
||||
NO_DATA_3: 'För att se alla tillgängliga enheter, gå till',
|
||||
NO_GPIO:'Inga tillgängliga GPIO-portar hittades',
|
||||
THIS_VERSION: 'Denna version',
|
||||
PLATFORM: 'Plattform',
|
||||
RELEASE_TYPE: 'Utgivelsestyp',
|
||||
@@ -359,13 +356,7 @@ const sv: Translation = {
|
||||
FIRMWARE_VERSION_INFO: 'Information om firmwareversion',
|
||||
NO_DATA: 'Ingen data',
|
||||
USER_PROFILE: 'Användarprofil',
|
||||
STORED_VERSIONS: 'Lagrad versioner',
|
||||
ONLINE_HELP: 'online hjälp',
|
||||
UPGRADE_IMPORTANT_MESSAGES: 'Uppdatera viktiga meddelanden',
|
||||
UPGRADE_IMPORTANT_MESSAGES_1: 'Denna uppdatering kräver en fabriksåterställning. Se till att du har gjort en säkerhetskopia av din konfiguration och inställningar innan du fortsätter och ladda upp denna efter att den nya versionen är installerad.',
|
||||
UPGRADE_IMPORTANT_MESSAGES_2: 'Du uppdaterar till en ny huvudversion. Se till att du har läst ChangeLog för eventuella brkande ändringar.',
|
||||
WARNING_SYSTEM_BACKUP: 'Detta kommer att skapa en säkerhetskopia av din fullständiga systemkonfiguration och inställningar. Alla lösenord kommer att vara läsbara i säkerhetskopien. Var försiktig med att dela! Vill du fortsätta?'
|
||||
|
||||
STORED_VERSIONS: 'Lagrad versioner'
|
||||
};
|
||||
|
||||
export default sv;
|
||||
|
||||
@@ -186,8 +186,7 @@ const tr: Translation = {
|
||||
BUFFER_SIZE: 'En fazla bellek boyutu',
|
||||
COMPACT: 'Sıkışık',
|
||||
DOWNLOAD_SETTINGS_TEXT: 'Yapılandırma ve ayarlarınızın yedekleme yapın',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Tüm değerleri dışarı al',
|
||||
DOWNLOAD_SYSTEM_BACKUP: 'Sistem yedekleme',
|
||||
DOWNLOAD_SETTINGS_TEXT2: 'Tüm verileri dışarı al',
|
||||
UPLOAD_TEXT: 'Yeni bir firmware dosyası (.bin) veya yedek dosyası (.json) yükle',
|
||||
UPLOAD_DROP_TEXT: 'Bir firmware .bin dosyası veya buraya tıklayın',
|
||||
ERROR: 'Beklenemedik hata, lütfen tekrar deneyin.',
|
||||
@@ -220,7 +219,6 @@ const tr: Translation = {
|
||||
MQTT_PUBLISH_TEXT_3: 'MQTT keşfi etkinleştir (Home Assistant, Domoticz)',
|
||||
MQTT_PUBLISH_TEXT_4: 'Keşif konuları için ön ek',
|
||||
MQTT_PUBLISH_TEXT_5: 'Domoticz Format',
|
||||
MQTT_INPUT_NUMBER_FORMAT: 'Sayı Biçimi',
|
||||
MQTT_PUBLISH_INTERVALS: 'Yayınlama aralıkları',
|
||||
MQTT_INT_BOILER: 'Kazanlar ve Isı Pompaları',
|
||||
MQTT_INT_THERMOSTATS: 'Termostatlar',
|
||||
@@ -350,7 +348,6 @@ const tr: Translation = {
|
||||
NO_DATA_1: 'Henüz bir favori EMS varlığı bulunamadı. Kullanın',
|
||||
NO_DATA_2: 'modülünü kullanın.',
|
||||
NO_DATA_3: 'Tüm kullanılabilir varlıkları görmek için git',
|
||||
NO_GPIO:'Kullanılabilir GPIO bulunamadı',
|
||||
THIS_VERSION: 'Bu Sürüm',
|
||||
PLATFORM: 'Platforma',
|
||||
RELEASE_TYPE: 'Sürüm Tipi',
|
||||
@@ -359,13 +356,7 @@ const tr: Translation = {
|
||||
FIRMWARE_VERSION_INFO: 'Firmware Sürüm Bilgisi',
|
||||
NO_DATA: 'Hiçbir veri yok',
|
||||
USER_PROFILE: 'Kullanıcı Profili',
|
||||
STORED_VERSIONS: 'Kaydedilmiş Sürümler',
|
||||
ONLINE_HELP: 'online yardım',
|
||||
UPGRADE_IMPORTANT_MESSAGES: 'Önemli Mesajları Güncelle',
|
||||
UPGRADE_IMPORTANT_MESSAGES_1: 'Bu güncelleme továrnı ayarlarını gerektirir. Yapılandırmanızı ve ayarlarınızı önce yedekleyin ve ardından yeni sürüm yüklendikten sonra yükleyin.',
|
||||
UPGRADE_IMPORTANT_MESSAGES_2: 'Yeni bir büyük sürüme yükselteceksiniz. Değişiklikleri ChangeLogı okuduğunuzdan emin olun.',
|
||||
WARNING_SYSTEM_BACKUP: 'Bu, sistem yapılandırmanızı ve ayarlarınızın bir yedeklemesi oluşturacaktır. Tüm şifreler yedekleme dosyasında okunabilir olacaktır. Paylaşırken dikkatli olun! Devam etmek istediğinize emin misiniz?'
|
||||
|
||||
STORED_VERSIONS: 'Kaydedilmiş Sürümler'
|
||||
};
|
||||
|
||||
export default tr;
|
||||
|
||||
@@ -49,5 +49,4 @@ export interface MqttSettingsType {
|
||||
publish_single2cmd: boolean;
|
||||
discovery_prefix: string;
|
||||
discovery_type: number;
|
||||
ha_number_mode: number;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@ export interface SystemStatus {
|
||||
free_psram?: number;
|
||||
free_caps: number;
|
||||
model: string;
|
||||
board: string;
|
||||
has_loader: boolean;
|
||||
has_partition: boolean;
|
||||
partitions: {
|
||||
|
||||
@@ -23,8 +23,6 @@ export const saveFile = (
|
||||
}, 100);
|
||||
} catch (error) {
|
||||
console.error('Failed to save file:', error);
|
||||
throw new Error(`Unable to save file: ${filename}${extension}`, {
|
||||
cause: error
|
||||
});
|
||||
throw new Error(`Unable to save file: ${filename}${extension}`);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
const DEFAULT_DELAY = 5000;
|
||||
const DEFAULT_DELAY = 3000;
|
||||
|
||||
/**
|
||||
* Custom hook for setting up an interval with proper cleanup
|
||||
|
||||
@@ -2,8 +2,9 @@ import preact from '@preact/preset-vite';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { visualizer } from 'rollup-plugin-visualizer';
|
||||
import { Plugin, PluginOption, defineConfig } from 'vite';
|
||||
import { Plugin, defineConfig } from 'vite';
|
||||
import viteImagemin from 'vite-plugin-imagemin';
|
||||
import viteTsconfigPaths from 'vite-tsconfig-paths';
|
||||
import zlib from 'zlib';
|
||||
|
||||
// @ts-expect-error - mock server doesn't have type declarations
|
||||
@@ -98,31 +99,16 @@ const createPreactPlugin = (devToolsEnabled: boolean) =>
|
||||
prefreshEnabled: false
|
||||
});
|
||||
|
||||
// Patch preact/compat to export stub React 19 APIs (use, useOptimistic) so that
|
||||
// react-router v7 doesn't trigger IMPORT_IS_UNDEFINED warnings from Rolldown.
|
||||
const preactCompatPatchPlugin = (): Plugin => ({
|
||||
name: 'preact-compat-react19-patch',
|
||||
transform(code, id) {
|
||||
if (id.includes('preact') && id.includes('compat.module.js')) {
|
||||
return {
|
||||
code:
|
||||
code +
|
||||
'\nexport var use = undefined;\nexport var useOptimistic = undefined;\n',
|
||||
map: null
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
|
||||
// Common base plugins
|
||||
const createBasePlugins = (
|
||||
devToolsEnabled: boolean,
|
||||
includeBundleReporter = true
|
||||
): PluginOption[] => {
|
||||
const plugins: PluginOption[] = [
|
||||
) => {
|
||||
const plugins = [
|
||||
createPreactPlugin(devToolsEnabled),
|
||||
preactCompatPatchPlugin()
|
||||
viteTsconfigPaths({
|
||||
projects: ['./tsconfig.json']
|
||||
})
|
||||
];
|
||||
if (includeBundleReporter) {
|
||||
plugins.push(bundleSizeReporter());
|
||||
@@ -150,16 +136,9 @@ const createManualChunks = (detailed = false) => {
|
||||
return 'vendor';
|
||||
}
|
||||
if (detailed) {
|
||||
// Group circularly dependent modules together to avoid circular chunk warnings
|
||||
// components, app, and utils are tightly coupled, so combine them
|
||||
if (
|
||||
id.includes('components/') ||
|
||||
id.includes('app/') ||
|
||||
id.includes('utils/')
|
||||
) {
|
||||
return 'app';
|
||||
}
|
||||
// Keep api separate as it's typically more independent
|
||||
if (id.includes('components/')) return 'components';
|
||||
if (id.includes('app/')) return 'app';
|
||||
if (id.includes('utils/')) return 'utils';
|
||||
if (id.includes('api/')) return 'api';
|
||||
}
|
||||
return undefined;
|
||||
@@ -248,8 +227,7 @@ export default defineConfig(
|
||||
plugins: [...createBasePlugins(true, true), mockServer()],
|
||||
resolve: {
|
||||
alias: RESOLVE_ALIASES,
|
||||
extensions: RESOLVE_EXTENSIONS,
|
||||
tsconfigPaths: true
|
||||
extensions: RESOLVE_EXTENSIONS
|
||||
},
|
||||
server: {
|
||||
open: true,
|
||||
@@ -278,8 +256,7 @@ export default defineConfig(
|
||||
plugins: createBasePlugins(false, true),
|
||||
resolve: {
|
||||
alias: RESOLVE_ALIASES,
|
||||
extensions: RESOLVE_EXTENSIONS,
|
||||
tsconfigPaths: true
|
||||
extensions: RESOLVE_EXTENSIONS
|
||||
},
|
||||
build: {
|
||||
...createBaseBuildConfig(),
|
||||
@@ -313,8 +290,7 @@ export default defineConfig(
|
||||
],
|
||||
resolve: {
|
||||
alias: RESOLVE_ALIASES,
|
||||
extensions: RESOLVE_EXTENSIONS,
|
||||
tsconfigPaths: true
|
||||
extensions: RESOLVE_EXTENSIONS
|
||||
},
|
||||
build: {
|
||||
...createBaseBuildConfig(),
|
||||
@@ -323,7 +299,8 @@ export default defineConfig(
|
||||
rollupOptions: {
|
||||
treeshake: {
|
||||
moduleSideEffects: false,
|
||||
propertyReadSideEffects: false as const,
|
||||
propertyReadSideEffects: false,
|
||||
tryCatchDeoptimization: false,
|
||||
unknownGlobalSideEffects: false
|
||||
},
|
||||
output: {
|
||||
|
||||
@@ -148,7 +148,9 @@
|
||||
#elif defined(ARDUINO_ARCH_ESP32)
|
||||
#include <driver/rtc_io.h>
|
||||
#include <soc/gpio_struct.h>
|
||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
||||
#include "soc/gpio_periph.h"
|
||||
#endif // ESP_IDF_VERSION_MAJOR >= 5
|
||||
#define PIN_TO_BASEREG(pin) (0)
|
||||
#define PIN_TO_BITMASK(pin) (pin)
|
||||
#define IO_REG_TYPE uint32_t
|
||||
|
||||
@@ -52,7 +52,7 @@ ModbusClientTCPasync::~ModbusClientTCPasync() {
|
||||
}
|
||||
}
|
||||
// force close client
|
||||
MTA_client.close();
|
||||
MTA_client.close(true);
|
||||
}
|
||||
|
||||
// optionally manually connect to modbus server. Otherwise connection will be made upon first request
|
||||
@@ -79,7 +79,7 @@ void ModbusClientTCPasync::connect(IPAddress host, uint16_t port) {
|
||||
// manually disconnect from modbus server. Connection will also auto close after idle time
|
||||
void ModbusClientTCPasync::disconnect(bool force) {
|
||||
LOG_D("disconnecting\n");
|
||||
MTA_client.close();
|
||||
MTA_client.close(force);
|
||||
}
|
||||
|
||||
// Set timeout value
|
||||
|
||||
@@ -253,7 +253,7 @@ void ModbusServerTCPasync::onClientConnect(AsyncClient* client) {
|
||||
LOG_D("nr clients: %u\n", clients.size());
|
||||
} else {
|
||||
LOG_D("max number of clients reached, closing new\n");
|
||||
client->close();
|
||||
client->close(true);
|
||||
delete client;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,7 @@
|
||||
// Include all library components
|
||||
#include "esp32-psram/AllocatorPSRAM.h" // PSRAM-backed vector
|
||||
#include "esp32-psram/VectorPSRAM.h" // PSRAM-backed vector
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32-psram/VectorHIMEM.h" // HIMEM-backed vector (ESP32 only)
|
||||
#endif
|
||||
#include "esp32-psram/VectorHIMEM.h" // HIMEM-backed vector
|
||||
// #include "esp32-psram/InMemoryFile.h" // File interface using vectors
|
||||
// #include "esp32-psram/PSRAM.h" // PSRAM file system
|
||||
// #include "esp32-psram/HIMEM.h" // HIMEM file system
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
// HIMEM is only available on original ESP32
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
@@ -363,5 +360,3 @@ class HimemBlock {
|
||||
};
|
||||
|
||||
} // namespace esp32_psram
|
||||
|
||||
#endif // CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
@@ -238,9 +238,7 @@ using RingBufferStreamPSRAM = RingBufferStream<VectorPSRAM<uint8_t>>;
|
||||
/**
|
||||
* @brief Type alias for a RingBufferStream that uses HIMEM-backed vector storage
|
||||
*/
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
using RingBufferStreamHIMEM = RingBufferStream<VectorHIMEM<uint8_t>>;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Type alias for a RingBufferStream that uses std::vector storage
|
||||
|
||||
@@ -209,10 +209,8 @@ using TypedRingBufferRAM = TypedRingBuffer<T, std::vector<T>>;
|
||||
/**
|
||||
* @brief Type alias for a typed ring buffer that uses HIMEM-backed vector storage
|
||||
*/
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
template<typename T>
|
||||
using TypedRingBufferHIMEM = TypedRingBuffer<T, VectorHIMEM<T>>;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Type alias for a typed ring buffer that uses PSRAM-backed vector storage
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
// HIMEM is only available on original ESP32
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
#include "HimemBlock.h"
|
||||
|
||||
namespace esp32_psram {
|
||||
@@ -529,6 +526,4 @@ void swap(VectorHIMEM<T>& lhs, VectorHIMEM<T>& rhs) noexcept {
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
} // namespace esp32_psram
|
||||
|
||||
#endif // CONFIG_IDF_TARGET_ESP32
|
||||
} // namespace esp32_psram
|
||||
@@ -321,14 +321,7 @@ bool Packet::_allocate(size_t remainingLength, bool check) {
|
||||
#if EMC_USE_MEMPOOL
|
||||
_data = reinterpret_cast<uint8_t*>(_memPool.malloc(_size));
|
||||
#else
|
||||
#ifdef EMSESP_STANDALONE
|
||||
_data = reinterpret_cast<uint8_t*>(malloc(_size));
|
||||
#else
|
||||
_data = reinterpret_cast<uint8_t*>(ps_malloc(_size));
|
||||
if (!_data) {
|
||||
_data = reinterpret_cast<uint8_t*>(malloc(_size));
|
||||
}
|
||||
#endif
|
||||
_data = reinterpret_cast<uint8_t*>(malloc(_size));
|
||||
#endif
|
||||
if (!_data) {
|
||||
_size = 0;
|
||||
|
||||
@@ -42,7 +42,7 @@ int ClientAsync::read(uint8_t* buf, size_t size) {
|
||||
}
|
||||
|
||||
void ClientAsync::stop() {
|
||||
client.close();
|
||||
client.close(false);
|
||||
}
|
||||
|
||||
bool ClientAsync::connected() {
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <esp32-psram.h>
|
||||
#include <uuid/common.h>
|
||||
#include <uuid/log.h>
|
||||
|
||||
@@ -1646,22 +1645,22 @@ class Shell : public std::enable_shared_from_this<Shell>, public uuid::log::Hand
|
||||
uint8_t cursor_ = 0; /*!< cursor position from end of line */
|
||||
uint8_t esc_ = 0; /*!< esc sequence running */
|
||||
|
||||
Stream & stream_; /*!< Stream used for the input/output of this shell. @since 3.0.0 */
|
||||
std::shared_ptr<Commands> commands_; /*!< Commands available for execution in this shell. @since 0.1.0 */
|
||||
std::deque<unsigned int, AllocatorPSRAM<unsigned int>> context_; /*!< Context stack for this shell. Affects which commands are available. Should never be empty. @since 0.1.0 */
|
||||
unsigned int flags_ = 0; /*!< Current flags for this shell. Affects which commands are available. @since 0.1.0 */
|
||||
Stream & stream_; /*!< Stream used for the input/output of this shell. @since 3.0.0 */
|
||||
std::shared_ptr<Commands> commands_; /*!< Commands available for execution in this shell. @since 0.1.0 */
|
||||
std::deque<unsigned int> context_; /*!< Context stack for this shell. Affects which commands are available. Should never be empty. @since 0.1.0 */
|
||||
unsigned int flags_ = 0; /*!< Current flags for this shell. Affects which commands are available. @since 0.1.0 */
|
||||
#if UUID_CONSOLE_THREAD_SAFE
|
||||
mutable std::mutex mutex_; /*!< Mutex for queued log messages. @since 1.0.0 */
|
||||
#endif
|
||||
unsigned long log_message_id_ = 0; /*!< The next identifier to use for queued log messages. @since 0.1.0 */
|
||||
std::list<QueuedLogMessage, AllocatorPSRAM<QueuedLogMessage>> log_messages_; /*!< Queued log messages, in the order they were received. @since 0.1.0 */
|
||||
size_t maximum_log_messages_ = MAX_LOG_MESSAGES; /*!< Maximum command line length in bytes. @since 0.6.0 */
|
||||
std::string line_buffer_; /*!< Command line buffer. Limited to maximum_command_line_length() bytes. @since 0.1.0 */
|
||||
size_t maximum_command_line_length_ = MAX_COMMAND_LINE_LENGTH; /*!< Maximum command line length in bytes. @since 0.6.0 */
|
||||
unsigned char previous_ = 0; /*!< Previous character that was entered on the command line. Used to detect CRLF line endings. @since 0.1.0 */
|
||||
Mode mode_ = Mode::NORMAL; /*!< Current execution mode. @since 0.1.0 */
|
||||
std::unique_ptr<ModeData> mode_data_ = nullptr; /*!< Data associated with the current execution mode. @since 0.1.0 */
|
||||
bool stopped_ = false; /*!< Indicates that the shell has been stopped. @since 0.1.0 */
|
||||
unsigned long log_message_id_ = 0; /*!< The next identifier to use for queued log messages. @since 0.1.0 */
|
||||
std::list<QueuedLogMessage> log_messages_; /*!< Queued log messages, in the order they were received. @since 0.1.0 */
|
||||
size_t maximum_log_messages_ = MAX_LOG_MESSAGES; /*!< Maximum command line length in bytes. @since 0.6.0 */
|
||||
std::string line_buffer_; /*!< Command line buffer. Limited to maximum_command_line_length() bytes. @since 0.1.0 */
|
||||
size_t maximum_command_line_length_ = MAX_COMMAND_LINE_LENGTH; /*!< Maximum command line length in bytes. @since 0.6.0 */
|
||||
unsigned char previous_ = 0; /*!< Previous character that was entered on the command line. Used to detect CRLF line endings. @since 0.1.0 */
|
||||
Mode mode_ = Mode::NORMAL; /*!< Current execution mode. @since 0.1.0 */
|
||||
std::unique_ptr<ModeData> mode_data_ = nullptr; /*!< Data associated with the current execution mode. @since 0.1.0 */
|
||||
bool stopped_ = false; /*!< Indicates that the shell has been stopped. @since 0.1.0 */
|
||||
bool prompt_displayed_ = false; /*!< Indicates that a command prompt has been displayed, so that the output of invoke_command() is correct. @since 0.1.0 */
|
||||
uint64_t idle_time_ = 0; /*!< Time the shell became idle. @since 0.7.0 */
|
||||
uint64_t idle_timeout_ = 0; /*!< Idle timeout (in milliseconds). @since 0.7.0 */
|
||||
@@ -1787,7 +1786,7 @@ class CommandLine {
|
||||
* @return A reference to the parameters.
|
||||
* @since 0.6.0
|
||||
*/
|
||||
inline std::vector<std::string, AllocatorPSRAM<std::string>> & operator*() {
|
||||
inline std::vector<std::string> & operator*() {
|
||||
return parameters_;
|
||||
}
|
||||
/**
|
||||
@@ -1796,7 +1795,7 @@ class CommandLine {
|
||||
* @return A reference to the parameters.
|
||||
* @since 0.6.0
|
||||
*/
|
||||
inline const std::vector<std::string, AllocatorPSRAM<std::string>> & operator*() const {
|
||||
inline const std::vector<std::string> & operator*() const {
|
||||
return parameters_;
|
||||
}
|
||||
/**
|
||||
@@ -1805,7 +1804,7 @@ class CommandLine {
|
||||
* @return A pointer to the parameters.
|
||||
* @since 0.4.0
|
||||
*/
|
||||
inline std::vector<std::string, AllocatorPSRAM<std::string>> * operator->() {
|
||||
inline std::vector<std::string> * operator->() {
|
||||
return ¶meters_;
|
||||
}
|
||||
/**
|
||||
@@ -1814,7 +1813,7 @@ class CommandLine {
|
||||
* @return A pointer to the parameters.
|
||||
* @since 0.4.0
|
||||
*/
|
||||
inline const std::vector<std::string, AllocatorPSRAM<std::string>> * operator->() const {
|
||||
inline const std::vector<std::string> * operator->() const {
|
||||
return ¶meters_;
|
||||
}
|
||||
|
||||
@@ -1844,8 +1843,8 @@ class CommandLine {
|
||||
bool trailing_space = false; /*!< Command line has a trailing space. @since 0.4.0 */
|
||||
|
||||
private:
|
||||
std::vector<std::string, AllocatorPSRAM<std::string>> parameters_; /*!< Separate command line parameters. @since 0.4.0 */
|
||||
size_t escape_parameters_ = std::numeric_limits<size_t>::max(); /*!< Number of initial arguments to escape in output. @since 0.5.0 */
|
||||
std::vector<std::string> parameters_; /*!< Separate command line parameters. @since 0.4.0 */
|
||||
size_t escape_parameters_ = std::numeric_limits<size_t>::max(); /*!< Number of initial arguments to escape in output. @since 0.5.0 */
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -232,7 +232,7 @@ void Logger::vlog(Level level, const char * format, va_list ap) const {
|
||||
}
|
||||
|
||||
void Logger::vlog(Level level, Facility facility, const char * format, va_list ap) const {
|
||||
std::vector<char, AllocatorPSRAM<char>> text(MAX_LOG_LENGTH + 1);
|
||||
std::vector<char> text(MAX_LOG_LENGTH + 1);
|
||||
|
||||
if (vsnprintf(text.data(), text.size(), format, ap) <= 0) {
|
||||
return;
|
||||
@@ -241,7 +241,7 @@ void Logger::vlog(Level level, Facility facility, const char * format, va_list a
|
||||
dispatch(level, facility, text);
|
||||
}
|
||||
|
||||
void Logger::dispatch(Level level, Facility facility, std::vector<char, AllocatorPSRAM<char>> & text) const {
|
||||
void Logger::dispatch(Level level, Facility facility, std::vector<char> & text) const {
|
||||
std::shared_ptr<Message> message = std::make_shared<Message>(get_uptime_ms(), level, facility, name_, text.data());
|
||||
text.resize(0);
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <esp32-psram.h>
|
||||
#include <uuid/common.h>
|
||||
|
||||
#ifndef UUID_COMMON_THREAD_SAFE
|
||||
@@ -646,7 +645,7 @@ class Logger {
|
||||
* @param[in] text Log message text.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void dispatch(Level level, Facility facility, std::vector<char, AllocatorPSRAM<char>> & text) const;
|
||||
void dispatch(Level level, Facility facility, std::vector<char> & text) const;
|
||||
|
||||
static std::atomic<Level> global_level_; /*!< Minimum global log level across all handlers. @since 3.0.0 */
|
||||
#if UUID_LOG_THREAD_SAFE
|
||||
@@ -724,7 +723,7 @@ class PrintHandler : public uuid::log::Handler {
|
||||
mutable std::mutex mutex_; /*!< Mutex for configuration, state and queued log messages. @since 2.3.0 */
|
||||
#endif
|
||||
size_t maximum_log_messages_ = MAX_LOG_MESSAGES; /*!< Maximum number of log messages to buffer before they are output. @since 2.2.0 */
|
||||
std::list<std::shared_ptr<Message>, AllocatorPSRAM<std::shared_ptr<Message>>> log_messages_; /*!< Queued log messages, in the order they were received. @since 2.2.0 */
|
||||
std::list<std::shared_ptr<Message>> log_messages_; /*!< Queued log messages, in the order they were received. @since 2.2.0 */
|
||||
};
|
||||
|
||||
} // namespace log
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "../../src/core/emsesp.h"
|
||||
|
||||
#ifndef UUID_SYSLOG_HAVE_GETTIMEOFDAY
|
||||
#if defined(ARDUINO_ARCH_ESP8266)
|
||||
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
||||
// time() does not return UTC on the ESP8266: https://github.com/esp8266/Arduino/issues/4637
|
||||
#define UUID_SYSLOG_HAVE_GETTIMEOFDAY 1
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <esp32-psram.h>
|
||||
#include <uuid/log.h>
|
||||
|
||||
#ifndef UUID_LOG_THREAD_SAFE
|
||||
@@ -322,7 +321,7 @@ class SyslogService : public uuid::log::Handler {
|
||||
#endif
|
||||
size_t maximum_log_messages_ = MAX_LOG_MESSAGES; /*!< Maximum number of log messages to buffer before they are output. @since 1.0.0 */
|
||||
unsigned long log_message_id_ = 0; /*!< The next identifier to use for queued log messages. @since 1.0.0 */
|
||||
std::list<QueuedLogMessage, AllocatorPSRAM<QueuedLogMessage>> log_messages_; /*!< Queued log messages, in the order they were received. @since 1.0.0 */
|
||||
std::list<QueuedLogMessage> log_messages_; /*!< Queued log messages, in the order they were received. @since 1.0.0 */
|
||||
uint64_t mark_interval_ = 0; /*!< Mark interval in milliseconds. @since 2.0.0 */
|
||||
uint64_t last_message_ = 0; /*!< Last message/mark time. @since 2.0.0 */
|
||||
|
||||
|
||||
@@ -249,7 +249,7 @@ size_t TelnetStream::write(uint8_t data) {
|
||||
}
|
||||
|
||||
size_t TelnetStream::write(const uint8_t * buffer, size_t size) {
|
||||
std::vector<unsigned char, AllocatorPSRAM<unsigned char>> data;
|
||||
std::vector<unsigned char> data;
|
||||
data.reserve(size);
|
||||
|
||||
while (size-- > 0) {
|
||||
@@ -310,7 +310,7 @@ size_t TelnetStream::raw_write(unsigned char data) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t TelnetStream::raw_write(const std::vector<unsigned char, AllocatorPSRAM<unsigned char>> & data) {
|
||||
size_t TelnetStream::raw_write(const std::vector<unsigned char> & data) {
|
||||
return raw_write(reinterpret_cast<const unsigned char *>(data.data()), data.size());
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <esp32-psram.h>
|
||||
#include <uuid/console.h>
|
||||
|
||||
namespace uuid {
|
||||
@@ -204,7 +203,7 @@ class TelnetStream : public ::Stream {
|
||||
* @return The number of bytes that were output.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
size_t raw_write(const std::vector<unsigned char, AllocatorPSRAM<unsigned char>> & data);
|
||||
size_t raw_write(const std::vector<unsigned char> & data);
|
||||
/**
|
||||
* Write an array of bytes directly to the output stream.
|
||||
*
|
||||
@@ -223,7 +222,7 @@ class TelnetStream : public ::Stream {
|
||||
unsigned char previous_in_ = 0; /*!< Previous character that was received. Used to detect CR NUL. @since 0.1.0 */
|
||||
unsigned char previous_out_ = 0; /*!< Previous character that was sent. Used to insert NUL after CR without LF. @since 0.1.0 */
|
||||
int peek_ = -1; /*!< Previously read data cached by peek(). @since 0.1.0 */
|
||||
std::vector<char, AllocatorPSRAM<char>> output_buffer_; /*!< Buffer data to be output until a read function is called. @since 0.1.0 */
|
||||
std::vector<char> output_buffer_; /*!< Buffer data to be output until a read function is called. @since 0.1.0 */
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -426,7 +425,7 @@ class TelnetService {
|
||||
|
||||
WiFiServer server_; /*!< TCP server. @since 0.1.0 */
|
||||
size_t maximum_connections_ = MAX_CONNECTIONS; /*!< Maximum number of concurrent open connections. @since 0.1.0 */
|
||||
std::list<Connection, AllocatorPSRAM<Connection>> connections_; /*!< Open connections. @since 0.1.0 */
|
||||
std::list<Connection> connections_; /*!< Open connections. @since 0.1.0 */
|
||||
shell_factory_function shell_factory_; /*!< Function to create a shell. @since 0.1.0 */
|
||||
unsigned long initial_idle_timeout_ = DEFAULT_IDLE_TIMEOUT; /*!< Initial idle timeout (in seconds). @since 0.1.0 */
|
||||
unsigned long write_timeout_ = DEFAULT_WRITE_TIMEOUT; /*!< Write timeout (in milliseconds). @since 0.1.0 */
|
||||
|
||||
@@ -145,7 +145,6 @@ double ledcSetup(uint8_t chan, double freq, uint8_t bit_num) {
|
||||
return 0;
|
||||
};
|
||||
void ledcAttachPin(uint8_t pin, uint8_t chan) {};
|
||||
void ledcAttach(uint8_t pin, uint8_t chan, uint8_t bit_num) {};
|
||||
void ledcWrite(uint8_t chan, uint32_t duty) {};
|
||||
void neopixelWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val) {};
|
||||
void rgbLedWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val) {};
|
||||
|
||||
@@ -72,15 +72,10 @@ void analogSetAttenuation(adc_attenuation_t attenuation);
|
||||
void dacWrite(uint8_t pin, uint8_t value);
|
||||
double ledcSetup(uint8_t chan, double freq, uint8_t bit_num);
|
||||
void ledcAttachPin(uint8_t pin, uint8_t chan);
|
||||
void ledcAttach(uint8_t pin, uint8_t chan, uint8_t bit_num);
|
||||
void ledcWrite(uint8_t chan, uint32_t duty);
|
||||
void neopixelWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val);
|
||||
void rgbLedWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val);
|
||||
|
||||
inline int rtc_get_reset_reason(int cpu_no) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PROGMEM
|
||||
#define PGM_P const char *
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2026, Benoit BLANCHON
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
@@ -239,11 +239,11 @@
|
||||
#define ARDUINOJSON_BIN2ALPHA_1111() P
|
||||
#define ARDUINOJSON_BIN2ALPHA_(A, B, C, D) ARDUINOJSON_BIN2ALPHA_##A##B##C##D()
|
||||
#define ARDUINOJSON_BIN2ALPHA(A, B, C, D) ARDUINOJSON_BIN2ALPHA_(A, B, C, D)
|
||||
#define ARDUINOJSON_VERSION "7.4.3"
|
||||
#define ARDUINOJSON_VERSION "7.4.2"
|
||||
#define ARDUINOJSON_VERSION_MAJOR 7
|
||||
#define ARDUINOJSON_VERSION_MINOR 4
|
||||
#define ARDUINOJSON_VERSION_REVISION 3
|
||||
#define ARDUINOJSON_VERSION_MACRO V743
|
||||
#define ARDUINOJSON_VERSION_REVISION 2
|
||||
#define ARDUINOJSON_VERSION_MACRO V742
|
||||
#ifndef ARDUINOJSON_VERSION_NAMESPACE
|
||||
#define ARDUINOJSON_VERSION_NAMESPACE \
|
||||
ARDUINOJSON_CONCAT5(ARDUINOJSON_VERSION_MACRO, \
|
||||
@@ -1536,12 +1536,11 @@ template <typename T, size_t = sizeof(T)>
|
||||
struct FloatTraits {};
|
||||
template <typename T>
|
||||
struct FloatTraits<T, 8 /*64bits*/> {
|
||||
using mantissa_type = uint64_t;
|
||||
static const short mantissa_bits = 52;
|
||||
static const mantissa_type mantissa_max = (mantissa_type(1) << mantissa_bits) - 1;
|
||||
using exponent_type = int16_t;
|
||||
static const exponent_type exponent_max = 308;
|
||||
static const size_t binaryPowersOfTen = 9;
|
||||
using mantissa_type = uint64_t;
|
||||
static const short mantissa_bits = 52;
|
||||
static const mantissa_type mantissa_max = (mantissa_type(1) << mantissa_bits) - 1;
|
||||
using exponent_type = int16_t;
|
||||
static const exponent_type exponent_max = 308;
|
||||
static pgm_ptr<T> positiveBinaryPowersOfTen() {
|
||||
ARDUINOJSON_DEFINE_PROGMEM_ARRAY( //
|
||||
uint64_t,
|
||||
@@ -1602,12 +1601,11 @@ struct FloatTraits<T, 8 /*64bits*/> {
|
||||
};
|
||||
template <typename T>
|
||||
struct FloatTraits<T, 4 /*32bits*/> {
|
||||
using mantissa_type = uint32_t;
|
||||
static const short mantissa_bits = 23;
|
||||
static const mantissa_type mantissa_max = (mantissa_type(1) << mantissa_bits) - 1;
|
||||
using exponent_type = int8_t;
|
||||
static const exponent_type exponent_max = 38;
|
||||
static const size_t binaryPowersOfTen = 6;
|
||||
using mantissa_type = uint32_t;
|
||||
static const short mantissa_bits = 23;
|
||||
static const mantissa_type mantissa_max = (mantissa_type(1) << mantissa_bits) - 1;
|
||||
using exponent_type = int8_t;
|
||||
static const exponent_type exponent_max = 38;
|
||||
static pgm_ptr<T> positiveBinaryPowersOfTen() {
|
||||
ARDUINOJSON_DEFINE_PROGMEM_ARRAY(uint32_t,
|
||||
factors,
|
||||
@@ -1670,12 +1668,9 @@ template <typename TFloat, typename TExponent>
|
||||
inline TFloat make_float(TFloat m, TExponent e) {
|
||||
using traits = FloatTraits<TFloat>;
|
||||
auto powersOfTen = e > 0 ? traits::positiveBinaryPowersOfTen() : traits::negativeBinaryPowersOfTen();
|
||||
auto count = traits::binaryPowersOfTen;
|
||||
if (e <= 0)
|
||||
e = TExponent(-e);
|
||||
for (uint8_t index = 0; e != 0; index++) {
|
||||
if (index >= count)
|
||||
return traits::nan();
|
||||
if (e & 1)
|
||||
m *= powersOfTen[index];
|
||||
e >>= 1;
|
||||
@@ -2427,7 +2422,7 @@ class VariantData {
|
||||
return;
|
||||
var->removeMember(key, resources);
|
||||
}
|
||||
void reset() { // TODO: remove
|
||||
void reset() {
|
||||
type_ = VariantType::Null;
|
||||
}
|
||||
void setBoolean(bool value) {
|
||||
@@ -4219,7 +4214,7 @@ template <typename T, typename Enable = void>
|
||||
struct Comparer;
|
||||
template <typename T>
|
||||
struct Comparer<T, enable_if_t<IsString<T>::value>> : ComparerBase {
|
||||
T rhs; // TODO: store adapted string?
|
||||
T rhs;
|
||||
explicit Comparer(T value)
|
||||
: rhs(value) {
|
||||
}
|
||||
@@ -5303,7 +5298,7 @@ class StringBuilder {
|
||||
append(*s++);
|
||||
}
|
||||
void append(const char * s, size_t n) {
|
||||
while (n-- > 0) // TODO: memcpy
|
||||
while (n-- > 0)
|
||||
append(*s++);
|
||||
}
|
||||
void append(char c) {
|
||||
|
||||
@@ -19,164 +19,12 @@ class AsyncClient {
|
||||
class AsyncServer {
|
||||
public:
|
||||
AsyncServer(uint16_t port)
|
||||
: _port(port) {};
|
||||
~AsyncServer() {};
|
||||
: _port(port){};
|
||||
~AsyncServer(){};
|
||||
|
||||
protected:
|
||||
uint16_t _port;
|
||||
};
|
||||
|
||||
namespace asyncsrv {
|
||||
|
||||
static constexpr const char empty[] = "";
|
||||
|
||||
static constexpr const char T__opaque[] = "\", opaque=\"";
|
||||
static constexpr const char T_100_CONTINUE[] = "100-continue";
|
||||
static constexpr const char T_13[] = "13";
|
||||
static constexpr const char T_ACCEPT[] = "Accept";
|
||||
static constexpr const char T_Accept_Ranges[] = "Accept-Ranges";
|
||||
static constexpr const char T_attachment[] = "attachment; filename=\"";
|
||||
static constexpr const char T_AUTH[] = "Authorization";
|
||||
static constexpr const char T_auth_nonce[] = "\", qop=\"auth\", nonce=\"";
|
||||
static constexpr const char T_BASIC[] = "Basic";
|
||||
static constexpr const char T_BASIC_REALM[] = "Basic realm=\"";
|
||||
static constexpr const char T_BEARER[] = "Bearer";
|
||||
static constexpr const char T_BODY[] = "body";
|
||||
static constexpr const char T_Cache_Control[] = "Cache-Control";
|
||||
static constexpr const char T_chunked[] = "chunked";
|
||||
static constexpr const char T_close[] = "close";
|
||||
static constexpr const char T_cnonce[] = "cnonce";
|
||||
static constexpr const char T_Connection[] = "Connection";
|
||||
static constexpr const char T_Content_Disposition[] = "Content-Disposition";
|
||||
static constexpr const char T_Content_Encoding[] = "Content-Encoding";
|
||||
static constexpr const char T_Content_Length[] = "Content-Length";
|
||||
static constexpr const char T_Content_Type[] = "Content-Type";
|
||||
static constexpr const char T_Content_Location[] = "Content-Location";
|
||||
static constexpr const char T_Cookie[] = "Cookie";
|
||||
static constexpr const char T_CORS_ACAC[] = "Access-Control-Allow-Credentials";
|
||||
static constexpr const char T_CORS_ACAH[] = "Access-Control-Allow-Headers";
|
||||
static constexpr const char T_CORS_ACAM[] = "Access-Control-Allow-Methods";
|
||||
static constexpr const char T_CORS_ACAO[] = "Access-Control-Allow-Origin";
|
||||
static constexpr const char T_CORS_ACMA[] = "Access-Control-Max-Age";
|
||||
static constexpr const char T_CORS_O[] = "Origin";
|
||||
static constexpr const char T_data_[] = "data: ";
|
||||
static constexpr const char T_Date[] = "Date";
|
||||
static constexpr const char T_DIGEST[] = "Digest";
|
||||
static constexpr const char T_DIGEST_[] = "Digest ";
|
||||
static constexpr const char T_ETag[] = "ETag";
|
||||
static constexpr const char T_event_[] = "event: ";
|
||||
static constexpr const char T_EXPECT[] = "Expect";
|
||||
static constexpr const char T_FALSE[] = "false";
|
||||
static constexpr const char T_filename[] = "filename";
|
||||
static constexpr const char T_gzip[] = "gzip";
|
||||
static constexpr const char T_Host[] = "host";
|
||||
static constexpr const char T_HTTP_1_0[] = "HTTP/1.0";
|
||||
static constexpr const char T_HTTP_100_CONT[] = "HTTP/1.1 100 Continue\r\n\r\n";
|
||||
static constexpr const char T_id__[] = "id: ";
|
||||
static constexpr const char T_IMS[] = "If-Modified-Since";
|
||||
static constexpr const char T_INM[] = "If-None-Match";
|
||||
static constexpr const char T_inline[] = "inline";
|
||||
static constexpr const char T_keep_alive[] = "keep-alive";
|
||||
static constexpr const char T_Last_Event_ID[] = "Last-Event-ID";
|
||||
static constexpr const char T_Last_Modified[] = "Last-Modified";
|
||||
static constexpr const char T_LOCATION[] = "Location";
|
||||
static constexpr const char T_LOGIN_REQ[] = "Login Required";
|
||||
static constexpr const char T_MULTIPART_[] = "multipart/";
|
||||
static constexpr const char T_name[] = "name";
|
||||
static constexpr const char T_nc[] = "nc";
|
||||
static constexpr const char T_no_cache[] = "no-cache";
|
||||
static constexpr const char T_nonce[] = "nonce";
|
||||
static constexpr const char T_none[] = "none";
|
||||
static constexpr const char T_opaque[] = "opaque";
|
||||
static constexpr const char T_qop[] = "qop";
|
||||
static constexpr const char T_realm[] = "realm";
|
||||
static constexpr const char T_realm__[] = "realm=\"";
|
||||
static constexpr const char T_response[] = "response";
|
||||
static constexpr const char T_retry_[] = "retry: ";
|
||||
static constexpr const char T_retry_after[] = "Retry-After";
|
||||
static constexpr const char T_nn[] = "\n\n";
|
||||
static constexpr const char T_rn[] = "\r\n";
|
||||
static constexpr const char T_rnrn[] = "\r\n\r\n";
|
||||
static constexpr const char T_Server[] = "Server";
|
||||
static constexpr const char T_Transfer_Encoding[] = "Transfer-Encoding";
|
||||
static constexpr const char T_TRUE[] = "true";
|
||||
static constexpr const char T_UPGRADE[] = "Upgrade";
|
||||
static constexpr const char T_uri[] = "uri";
|
||||
static constexpr const char T_username[] = "username";
|
||||
static constexpr const char T_WS[] = "websocket";
|
||||
static constexpr const char T_WWW_AUTH[] = "WWW-Authenticate";
|
||||
|
||||
// HTTP Methods
|
||||
static constexpr const char T_ANY[] = "ANY";
|
||||
static constexpr const char T_GET[] = "GET";
|
||||
static constexpr const char T_POST[] = "POST";
|
||||
static constexpr const char T_PUT[] = "PUT";
|
||||
static constexpr const char T_DELETE[] = "DELETE";
|
||||
static constexpr const char T_PATCH[] = "PATCH";
|
||||
static constexpr const char T_HEAD[] = "HEAD";
|
||||
static constexpr const char T_OPTIONS[] = "OPTIONS";
|
||||
static constexpr const char T_UNKNOWN[] = "UNKNOWN";
|
||||
|
||||
// Req content types
|
||||
static constexpr const char T_RCT_NOT_USED[] = "RCT_NOT_USED";
|
||||
static constexpr const char T_RCT_DEFAULT[] = "RCT_DEFAULT";
|
||||
static constexpr const char T_RCT_HTTP[] = "RCT_HTTP";
|
||||
static constexpr const char T_RCT_WS[] = "RCT_WS";
|
||||
static constexpr const char T_RCT_EVENT[] = "RCT_EVENT";
|
||||
static constexpr const char T_ERROR[] = "ERROR";
|
||||
|
||||
// extensions & MIME-Types
|
||||
static constexpr const char T__avif[] = ".avif"; // AVIF: Highly compressed images. Compatible with all modern browsers.
|
||||
static constexpr const char T__csv[] = ".csv"; // CSV: Data logging and configuration
|
||||
static constexpr const char T__css[] = ".css"; // CSS: Styling for web interfaces
|
||||
static constexpr const char T__gif[] = ".gif"; // GIF: Simple animations. Legacy support
|
||||
static constexpr const char T__gz[] = ".gz"; // GZ: compressed files
|
||||
static constexpr const char T__htm[] = ".htm"; // HTM: Web interface files
|
||||
static constexpr const char T__html[] = ".html"; // HTML: Web interface files
|
||||
static constexpr const char T__ico[] = ".ico"; // ICO: Favicons, system icons. Legacy support
|
||||
static constexpr const char T__jpg[] = ".jpg"; // JPEG/JPG: Photos. Legacy support
|
||||
static constexpr const char T__js[] = ".js"; // JavaScript: Interactive functionality
|
||||
static constexpr const char T__json[] = ".json"; // JSON: Data exchange format
|
||||
static constexpr const char T__mp4[] = ".mp4"; // MP4: Proprietary format. Worse compression than WEBM.
|
||||
static constexpr const char T__mjs[] = ".mjs"; // MJS: JavaScript module format
|
||||
static constexpr const char T__opus[] = ".opus"; // OPUS: High compression audio format
|
||||
static constexpr const char T__pdf[] = ".pdf"; // PDF: Universal document format
|
||||
static constexpr const char T__png[] = ".png"; // PNG: Icons, logos, transparency. Legacy support
|
||||
static constexpr const char T__svg[] = ".svg"; // SVG: Vector graphics, icons (scalable, tiny file sizes)
|
||||
static constexpr const char T__ttf[] = ".ttf"; // TTF: Font file. Legacy support
|
||||
static constexpr const char T__txt[] = ".txt"; // TXT: Plain text files
|
||||
static constexpr const char T__webm[] = ".webm"; // WebM: Video. Open source, optimized for web. Compatible with all modern browsers.
|
||||
static constexpr const char T__webp[] = ".webp"; // WebP: Highly compressed images. Compatible with all modern browsers.
|
||||
static constexpr const char T__woff[] = ".woff"; // WOFF: Font file. Legacy support
|
||||
static constexpr const char T__woff2[] = ".woff2"; // WOFF2: Better compression. Compatible with all modern browsers.
|
||||
static constexpr const char T__xml[] = ".xml"; // XML: Configuration and data files
|
||||
static constexpr const char T_application_javascript[] = "application/javascript"; // Obsolete type for JavaScript
|
||||
static constexpr const char T_application_json[] = "application/json";
|
||||
static constexpr const char T_application_msgpack[] = "application/msgpack";
|
||||
static constexpr const char T_application_octet_stream[] = "application/octet-stream";
|
||||
static constexpr const char T_application_pdf[] = "application/pdf";
|
||||
static constexpr const char T_app_xform_urlencoded[] = "application/x-www-form-urlencoded";
|
||||
static constexpr const char T_audio_opus[] = "audio/opus";
|
||||
static constexpr const char T_font_ttf[] = "font/ttf";
|
||||
static constexpr const char T_font_woff[] = "font/woff";
|
||||
static constexpr const char T_font_woff2[] = "font/woff2";
|
||||
static constexpr const char T_image_avif[] = "image/avif";
|
||||
static constexpr const char T_image_gif[] = "image/gif";
|
||||
static constexpr const char T_image_jpeg[] = "image/jpeg";
|
||||
static constexpr const char T_image_png[] = "image/png";
|
||||
static constexpr const char T_image_svg_xml[] = "image/svg+xml";
|
||||
static constexpr const char T_image_webp[] = "image/webp";
|
||||
static constexpr const char T_image_x_icon[] = "image/x-icon";
|
||||
static constexpr const char T_text_css[] = "text/css";
|
||||
static constexpr const char T_text_csv[] = "text/csv";
|
||||
static constexpr const char T_text_event_stream[] = "text/event-stream";
|
||||
static constexpr const char T_text_html[] = "text/html";
|
||||
static constexpr const char T_text_javascript[] = "text/javascript";
|
||||
static constexpr const char T_text_plain[] = "text/plain";
|
||||
static constexpr const char T_text_xml[] = "text/xml";
|
||||
static constexpr const char T_video_mp4[] = "video/mp4";
|
||||
static constexpr const char T_video_webm[] = "video/webm";
|
||||
} // namespace asyncsrv
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,7 +36,6 @@ class DummySettings {
|
||||
uint8_t nested_format = 1; // 1=nested 2=single
|
||||
String discovery_prefix = "homeassistant";
|
||||
uint8_t discovery_type = 0; // HA
|
||||
uint8_t ha_number_mode = 0; // box
|
||||
bool ha_enabled = true;
|
||||
String base = "ems-esp";
|
||||
bool publish_single = false;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2025 emsesp.org
|
||||
* Copyright 2020-2025 emsesp.org - proddy, MichaelDvP
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2025 emsesp.org
|
||||
* Copyright 2020-2025 emsesp.org - proddy, MichaelDvP
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -67,9 +67,6 @@ class Preferences {
|
||||
size_t putString(const char * key, String value) {
|
||||
return 0;
|
||||
}
|
||||
bool isKey(const char * key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// unused....
|
||||
|
||||
@@ -87,6 +84,7 @@ class Preferences {
|
||||
// size_t putBool(const char * key, bool value);
|
||||
|
||||
// size_t putBytes(const char * key, const void * value, size_t len);
|
||||
// bool isKey(const char * key);
|
||||
// PreferenceType getType(const char * key);
|
||||
// int8_t getChar(const char * key, int8_t defaultValue = 0);
|
||||
// int16_t getShort(const char * key, int16_t defaultValue = 0);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2025 emsesp.org
|
||||
* Copyright 2020-2025 emsesp.org - proddy, MichaelDvP
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user