Merge branch 'idf4' into idf4_no_master

This commit is contained in:
MichaelDvP
2022-05-29 19:12:58 +02:00
26 changed files with 1004 additions and 773 deletions

View File

@@ -9,9 +9,10 @@ jobs:
build: build:
name: Build name: Build
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository_owner == 'emsesp'
# if: github.repository == 'emsesp/EMS-ESP32'
env: env:
# https://binaries.sonarsource.com/?prefix=Distribution/sonar-scanner-cli/ # https://binaries.sonarsource.com/?prefix=Distribution/sonar-scanner-cli/
# SONAR_SCANNER_VERSION: 4.6.1.2450
SONAR_SCANNER_VERSION: 4.7.0.2747 SONAR_SCANNER_VERSION: 4.7.0.2747
SONAR_SERVER_URL: "https://sonarcloud.io" SONAR_SERVER_URL: "https://sonarcloud.io"
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory

View File

@@ -5,6 +5,108 @@ 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/), 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). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
# [3.4.1] May 29 2022
## Fixed
- Fix memory leak in api [#524](https://github.com/emsesp/EMS-ESP32/issues/524)
## Changed
- Controller data in web-ui only for IVT [#522](https://github.com/emsesp/EMS-ESP32/issues/522)
- Rename hidden `climate` to a more explaining name [#523](https://github.com/emsesp/EMS-ESP32/issues/523)
- Minor changes to the Customizations web page [#527](https://github.com/emsesp/EMS-ESP32/pull/527)
# [3.4.0] May 23 2022
## Added
- WebUI optimizations, updated look&feel and better performance [#124](https://github.com/emsesp/EMS-ESP32/issues/124)
- Auto refresh of WebUI after successful firmware upload [#178](https://github.com/emsesp/EMS-ESP32/issues/178)
- New Customization Service in WebUI. First feature is the ability to enable/disabled Enitites (device values) from EMS devices [#206](https://github.com/emsesp/EMS-ESP32/issues/206)
- Option to disable Telnet Console [#209](https://github.com/emsesp/EMS-ESP32/issues/209)
- Added Hide SSID, Max Clients and Preferred Channel to Access Point
- Merged in MichaelDvP's changes like Fahrenheit conversion, publish single (for IOBroker) and a few other critical optimizations
- Enabled bi-directional read/write with Home Assistant, so values can be changed automatically from the UI without scripting [#265](https://github.com/emsesp/EMS-ESP32/issues/265)
- Added GC7000F Boiler [#270](https://github.com/emsesp/EMS-ESP32/issues/270)
- Revised LED flash sequence on boot up to show system health (1 flash=no ems, 2 flashes=no wifi) [#224](https://github.com/emsesp/EMS-ESP32/issues/224)
- Analog Sensor support [#271](https://github.com/emsesp/EMS-ESP32/issues/271)
- Solar cylinder priority [#247](https://github.com/emsesp/EMS-ESP32/issues/247)
- Read only mode in Settings, where EMS Tx/Write commands are blocked [#286](https://github.com/emsesp/EMS-ESP32/issues/286)
- Added 8700i Boiler device
- Added Cascade CM10 Controller device
- Add Olimex ESP32-POE-ISO to board profiles plus settings to customize Ethernet modules [#301](https://github.com/emsesp/EMS-ESP32/issues/301)
- Help text for string commands in WebUI [#320](https://github.com/emsesp/EMS-ESP32/issues/320)
- Germany translations (at compile time)
- #entities added to system/info` endpoint [#322](https://github.com/emsesp/EMS-ESP32/issues/322)
- analog outputs digital/pwm/dac
- remove MQTT retained configs if discovery is disabled
- timeout 10 min for MQTT-QoS wait
- Moduline 300 auto-temperatures T1-T4, RC300 romminfluencefactor
- RC35 parameters [#392](https://github.com/emsesp/EMS-ESP32/issues/392), [#398](https://github.com/emsesp/EMS-ESP32/issues/398)
- sync time with thermostat [#386](https://github.com/emsesp/EMS-ESP32/issues/386), [#408](https://github.com/emsesp/EMS-ESP32/issues/408)
- set mode has immediate effect [#395](https://github.com/emsesp/EMS-ESP32/issues/395)
- min/max in web value setting
- Extend customization to select if an entity is to be shown in the WebUI or forced as read-only [#317](https://github.com/emsesp/EMS-ESP32/issues/317)
- Added Moduline 400 installation parameters [PR #449 by @kwertie01](https://github.com/emsesp/EMS-ESP32/pull/449)
- Read time from IVT-controller [#439](https://github.com/emsesp/EMS-ESP32/issues/439)
- Hybrid Heatpump product-id 168 [#459](https://github.com/emsesp/EMS-ESP32/issues/459), thermostat settings
- Junkers ISM2 and IPM in warm water mode [#437](https://github.com/emsesp/EMS-ESP32/issues/437)
- Added Shower Alert trigger time and cold shot time [#436](https://github.com/emsesp/EMS-ESP32/issues/436)
- Improved Table layout in Web UI (searching, filtering, sorting, exporting to CSV)
- API fetch individual attributes from an entity [#462](https://github.com/emsesp/EMS-ESP32/issues/462)
- Option to disable mDNS
- Option for rendering booleans on dashboard [#456](https://github.com/emsesp/EMS-ESP32/issues/456)
- Upload customization settings from a file [#256](https://github.com/emsesp/EMS-ESP32/issues/256)
## Fixed
- lastcode broke MQTT JSON structure [#228](https://github.com/emsesp/EMS-ESP32/issues/228)
- fixed issue with overlapping while reading sequence of EMS1.0 telegrams
- fixed redundant telegram readings (because of offset overflow)
- added missing RC30/Moduline 400 [#243](https://github.com/emsesp/EMS-ESP32/issues/243)
- Correct modes for RC25 [#106](https://github.com/emsesp/EMS-ESP32/issues/106)
- Clean up old HA config's in MQTT before publishing data. This will prevent HA giving the 'dict' warnings [#229](https://github.com/emsesp/EMS-ESP32/issues/229)
- RC25 temperature setting [#272](https://github.com/emsesp/EMS-ESP32/issues/272)
- Buderus RC25 - "hc1 mode type" incorrect value [#273](https://github.com/emsesp/EMS-ESP32/issues/273)
- Increased number of Mixers and Heating Circuits [#294](https://github.com/emsesp/EMS-ESP32/issues/294)
- Check receive status before removing a telegram fetch [#268](https://github.com/emsesp/EMS-ESP32/issues/268), [#282](https://github.com/emsesp/EMS-ESP32/issues/282)
- Fix uploading firmware on OSX [#345](https://github.com/emsesp/EMS-ESP32/issues/345)
- Non-nested MQTT would corrupt the json [#354](https://github.com/emsesp/EMS-ESP32/issues/354)
- Burner selected max power can have a value higher than 100% [#314](https://github.com/emsesp/EMS-ESP32/issues/314)
- some missing fahrenheit calculations
- limited number of exclusions [#339](https://github.com/emsesp/EMS-ESP32/issues/339)
- MQTT sometimes would not reconnect after a WiFi outage
## Changed
- Use flash system to show system health (1 flash=no ems, 2 flashes=no wifi) [#224](https://github.com/emsesp/EMS-ESP32/issues/224)
- Renamed Dallas Sensor to Temperature Sensor in UI
- Dallas Format removed. Use the name to give each sensor an alias
- No longer MQTT subscribes to topic `/thermostat_hc<n>` as it supports a path similar to the API endpoint construct
- Show Sensors quality in WebUI
- Controller not shown in WebUI dashboard
- renamed "Home Assistant Integration" to "MQTT Discovery" in MQTT Settings [#290](https://github.com/emsesp/EMS-ESP32/issues/290)
- Show ems tx reads and writes separately
- Show ems device handlers separated for received, fetched and pending handlers.
- Wired renamed to Ethernet
- removed system/pin command, new commands in analogsensors
- system/info device-info split to name/version/brand
- exclude list uses short-names, possible flags for web/api/mqtt excludes, readonly and favorite (selection not yet implemented)
- thermostat clock formate date-time: dd.mm.yyyy hh:mm
- RC300 summermode as other thermostats `winter/summer` instead of `off/on`
## **BREAKING CHANGES:**
- Settings:
- order of Boolean Format has changed in Application Settings - check your settings
- Dallas Format setting removed. Now customize name of each Dallas sensor via the UI
- MQTT/API
- Boiler `wwheat` renamed to `ww3wayon` [#211](https://github.com/emsesp/EMS-ESP32/issues/211)
- Boiler `ww` tag renamed to `dhw`. Any custom Home Assistant lovelace dashboards will need updating.
- Renamed description of `wwtapactivated` to "turn on/off DHW". Otherwise would have looked like "boiler_dhw_turn_on_off_dhw" in HA.
- `/api/system/info` endpoint has updated keys. Now lowercase, no underscores and not capitalized. Replace "handlers" with "handlers received", "handlers fetched" and "handlers pending".
# [3.3.1] January 20 2022 # [3.3.1] January 20 2022
- lastcode broke MQTT JSON structure [#228](https://github.com/emsesp/EMS-ESP32/issues/228) - lastcode broke MQTT JSON structure [#228](https://github.com/emsesp/EMS-ESP32/issues/228)

View File

@@ -1,92 +1,19 @@
# Changelog # Changelog
## [3.4.0] # [3.4.2]
### Added ## Added
- WebUI optimizations, updated look&feel and better performance [#124](https://github.com/emsesp/EMS-ESP32/issues/124) - RC310 additions [#520](https://github.com/emsesp/EMS-ESP32/pull/520)
- Auto refresh of WebUI after successful firmware upload [#178](https://github.com/emsesp/EMS-ESP32/issues/178) - damping
- New Customization Service in WebUI. First feature is the ability to enable/disabled Enitites (device values) from EMS devices [#206](https://github.com/emsesp/EMS-ESP32/issues/206) - wwprio for RC310 heating circuits
- Option to disable Telnet Console [#209](https://github.com/emsesp/EMS-ESP32/issues/209) - switchonoptimization for RC310 heating circuits
- Added Hide SSID, Max Clients and Preferred Channel to Access Point - enum_controlmode for RC310 (new enum list)
- Merged in MichaelDvP's changes like Fahrenheit conversion, publish single (for IOBroker) and a few other critical optimizations - nofrostmode, reducemode, reducetemp & noreducetemp for RC310
- Enabled bi-directional read/write with Home Assistant, so values can be changed automatically from the UI without scripting [#265](https://github.com/emsesp/EMS-ESP32/issues/265) - emergencyops and emergencytemp, wwmaxtemp, wwflowtempoffset and wwcomfort1 for RC310
- Added GC7000F Boiler [#270](https://github.com/emsesp/EMS-ESP32/issues/270)
- Revised LED flash sequence on boot up to show system health (1 flash=no ems, 2 flashes=no wifi) [#224](https://github.com/emsesp/EMS-ESP32/issues/224)
- Analog Sensor support [#271](https://github.com/emsesp/EMS-ESP32/issues/271)
- Solar cylinder priority [#247](https://github.com/emsesp/EMS-ESP32/issues/247)
- Read only mode in Settings, where EMS Tx/Write commands are blocked [#286](https://github.com/emsesp/EMS-ESP32/issues/286)
- Added 8700i Boiler device
- Added Cascade CM10 Controller device
- Add Olimex ESP32-POE-ISO to board profiles plus settings to customize Ethernet modules [#301](https://github.com/emsesp/EMS-ESP32/issues/301)
- Help text for string commands in WebUI [#320](https://github.com/emsesp/EMS-ESP32/issues/320)
- Germany translations (at compile time)
- #entities added to system/info` endpoint [#322](https://github.com/emsesp/EMS-ESP32/issues/322)
- analog outputs digital/pwm/dac
- remove MQTT retained configs if discovery is disabled
- timeout 10 min for MQTT-QoS wait
- Moduline 300 auto-temperatures T1-T4, RC300 romminfluencefactor
- RC35 parameters [#392](https://github.com/emsesp/EMS-ESP32/issues/392), [#398](https://github.com/emsesp/EMS-ESP32/issues/398)
- sync time with thermostat [#386](https://github.com/emsesp/EMS-ESP32/issues/386), [#408](https://github.com/emsesp/EMS-ESP32/issues/408)
- set mode has immediate effect [#395](https://github.com/emsesp/EMS-ESP32/issues/395)
- min/max in web value setting
- Extend customization to select if an entity is to be shown in the WebUI or forced as read-only [#317](https://github.com/emsesp/EMS-ESP32/issues/317)
- Added Moduline 400 installation parameters [PR #449 by @kwertie01](https://github.com/emsesp/EMS-ESP32/pull/449)
- Read time from IVT-controller [#439](https://github.com/emsesp/EMS-ESP32/issues/439)
- Hybrid Heatpump product-id 168 [#459](https://github.com/emsesp/EMS-ESP32/issues/459), thermostat settings
- Junkers ISM2 and IPM in warm water mode [#437](https://github.com/emsesp/EMS-ESP32/issues/437)
- Added Shower Alert trigger time and cold shot time [#436](https://github.com/emsesp/EMS-ESP32/issues/436)
- Improved Table layout in Web UI (searching, filtering, sorting, exporting to CSV)
- API fetch individual attributes from an entity [#462](https://github.com/emsesp/EMS-ESP32/issues/462)
- Option to disable mDNS
- Option for rendering booleans on dashboard [#456](https://github.com/emsesp/EMS-ESP32/issues/456)
- Upload customization settings from a file [#256](https://github.com/emsesp/EMS-ESP32/issues/256)
### Fixed ## Fixed
- lastcode broke MQTT JSON structure [#228](https://github.com/emsesp/EMS-ESP32/issues/228) ## Changed
- fixed issue with overlapping while reading sequence of EMS1.0 telegrams
- fixed redundant telegram readings (because of offset overflow)
- added missing RC30/Moduline 400 [#243](https://github.com/emsesp/EMS-ESP32/issues/243)
- Correct modes for RC25 [#106](https://github.com/emsesp/EMS-ESP32/issues/106)
- Clean up old HA config's in MQTT before publishing data. This will prevent HA giving the 'dict' warnings [#229](https://github.com/emsesp/EMS-ESP32/issues/229)
- RC25 temperature setting [#272](https://github.com/emsesp/EMS-ESP32/issues/272)
- Buderus RC25 - "hc1 mode type" incorrect value [#273](https://github.com/emsesp/EMS-ESP32/issues/273)
- Increased number of Mixers and Heating Circuits [#294](https://github.com/emsesp/EMS-ESP32/issues/294)
- Check receive status before removing a telegram fetch [#268](https://github.com/emsesp/EMS-ESP32/issues/268), [#282](https://github.com/emsesp/EMS-ESP32/issues/282)
- Fix uploading firmware on OSX [#345](https://github.com/emsesp/EMS-ESP32/issues/345)
- Non-nested MQTT would corrupt the json [#354](https://github.com/emsesp/EMS-ESP32/issues/354)
- Burner selected max power can have a value higher than 100% [#314](https://github.com/emsesp/EMS-ESP32/issues/314)
- some missing fahrenheit calculations
- limited number of exclusions [#339](https://github.com/emsesp/EMS-ESP32/issues/339)
- MQTT sometimes would not reconnect after a WiFi outage
### Changed
- Use flash system to show system health (1 flash=no ems, 2 flashes=no wifi) [#224](https://github.com/emsesp/EMS-ESP32/issues/224)
- Renamed Dallas Sensor to Temperature Sensor in UI
- Dallas Format removed. Use the name to give each sensor an alias
- No longer MQTT subscribes to topic `/thermostat_hc<n>` as it supports a path similar to the API endpoint construct
- Show Sensors quality in WebUI
- Controller not shown in WebUI dashboard
- renamed "Home Assistant Integration" to "MQTT Discovery" in MQTT Settings [#290](https://github.com/emsesp/EMS-ESP32/issues/290)
- Show ems tx reads and writes separately
- Show ems device handlers separated for received, fetched and pending handlers.
- Wired renamed to Ethernet
- removed system/pin command, new commands in analogsensors
- system/info device-info split to name/version/brand
- remove master-thermostat
- exclude list uses short-names, possible flags for web/api/mqtt excludes, readonly and favorite (selection not yet implemented)
- thermostat clock formate date-time: dd.mm.yyyy hh:mm
- RC300 summermode as other thermostats `winter/summer` instead of `off/on`
## **BREAKING CHANGES:** ## **BREAKING CHANGES:**
- Settings:
- order of Boolean Format has changed in Application Settings - check your settings
- Dallas Format setting removed. Now customize name of each Dallas sensor via the UI
- MQTT/API
- Boiler `wwheat` renamed to `ww3wayon` [#211](https://github.com/emsesp/EMS-ESP32/issues/211)
- Boiler `ww` tag renamed to `dhw`. Any custom Home Assistant lovelace dashboards will need updating.
- Renamed description of `wwtapactivated` to "turn on/off DHW". Otherwise would have looked like "boiler_dhw_turn_on_off_dhw" in HA.
- `/api/system/info` endpoint has updated keys. Now lowercase, no underscores and not capitalized. Replace "handlers" with "handlers received", "handlers fetched" and "handlers pending".

File diff suppressed because it is too large Load Diff

View File

@@ -9,9 +9,9 @@
"@msgpack/msgpack": "^2.7.2", "@msgpack/msgpack": "^2.7.2",
"@mui/icons-material": "^5.8.0", "@mui/icons-material": "^5.8.0",
"@mui/material": "^5.8.1", "@mui/material": "^5.8.1",
"@table-library/react-table-library": "^3.1.2", "@table-library/react-table-library": "^3.1.4",
"@types/lodash": "^4.14.182", "@types/lodash": "^4.14.182",
"@types/node": "^17.0.35", "@types/node": "^17.0.36",
"@types/react": "^18.0.9", "@types/react": "^18.0.9",
"@types/react-dom": "^18.0.5", "@types/react-dom": "^18.0.5",
"@types/react-router-dom": "^5.3.3", "@types/react-router-dom": "^5.3.3",
@@ -30,7 +30,7 @@
"react-router-dom": "^6.3.0", "react-router-dom": "^6.3.0",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",
"sockette": "^2.0.6", "sockette": "^2.0.6",
"typescript": "^4.6.4" "typescript": "^4.7.2"
}, },
"scripts": { "scripts": {
"start": "react-app-rewired start", "start": "react-app-rewired start",

View File

@@ -1,15 +1,15 @@
import React from 'react'; import { StrictMode } from 'react';
import ReactDOM from 'react-dom'; import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom'; import { BrowserRouter } from 'react-router-dom';
import App from './App'; import App from './App';
ReactDOM.render( const root = createRoot(document.getElementById('root') as HTMLElement);
<React.StrictMode>
root.render(
<StrictMode>
<BrowserRouter> <BrowserRouter>
<App /> <App />
</BrowserRouter> </BrowserRouter>
</React.StrictMode>, </StrictMode>
document.getElementById('root')
); );

View File

@@ -384,7 +384,10 @@ const DashboardData: FC = () => {
const handleDownloadCsv = () => { const handleDownloadCsv = () => {
const columns = [ const columns = [
{ accessor: (dv: any) => dv.id.slice(2), name: 'Entity' }, { accessor: (dv: any) => dv.id.slice(2), name: 'Entity' },
{ accessor: (dv: any) => (typeof dv.v === 'number') ? new Intl.NumberFormat().format(dv.v) : dv.v, name: 'Value' }, {
accessor: (dv: any) => (typeof dv.v === 'number' ? new Intl.NumberFormat().format(dv.v) : dv.v),
name: 'Value'
},
{ accessor: (dv: any) => DeviceValueUOM_s[dv.u], name: 'UoM' } { accessor: (dv: any) => DeviceValueUOM_s[dv.u], name: 'UoM' }
]; ];
downloadAsCsv( downloadAsCsv(
@@ -449,7 +452,7 @@ const DashboardData: FC = () => {
} }
}; };
const isCmdOnly = (dv: DeviceValue) => dv.v === undefined && dv.c; const isCmdOnly = (dv: DeviceValue) => dv.v === '' && dv.c;
function formatValue(value: any, uom: number) { function formatValue(value: any, uom: number) {
if (value === undefined) { if (value === undefined) {

View File

@@ -0,0 +1,39 @@
import { FC } from 'react';
import { SvgIconProps } from '@mui/material';
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
import StarIcon from '@mui/icons-material/Star';
import StarOutlineIcon from '@mui/icons-material/StarOutline';
import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
import InsertCommentOutlinedIcon from '@mui/icons-material/InsertCommentOutlined';
type OptionType = 'readonly' | 'web_exclude' | 'api_mqtt_exclude' | 'favorite';
const OPTION_ICONS: { [type in OptionType]: [React.ComponentType<SvgIconProps>, React.ComponentType<SvgIconProps>] } = {
readonly: [EditOffOutlinedIcon, EditOutlinedIcon],
web_exclude: [VisibilityOffOutlinedIcon, VisibilityOutlinedIcon],
api_mqtt_exclude: [CommentsDisabledOutlinedIcon, InsertCommentOutlinedIcon],
favorite: [StarIcon, StarOutlineIcon]
};
interface OptionIconProps {
type: OptionType;
isSet: boolean;
}
const OptionIcon: FC<OptionIconProps> = ({ type, isSet }) => {
const Icon = OPTION_ICONS[type][isSet ? 0 : 1];
return isSet ? (
<Icon color="primary" sx={{ fontSize: 14, verticalAlign: 'middle' }} />
) : (
<Icon sx={{ fontSize: 14, verticalAlign: 'middle' }} />
);
};
export default OptionIcon;

View File

@@ -25,10 +25,12 @@ import { useSnackbar } from 'notistack';
import SaveIcon from '@mui/icons-material/Save'; import SaveIcon from '@mui/icons-material/Save';
import CancelIcon from '@mui/icons-material/Cancel'; import CancelIcon from '@mui/icons-material/Cancel';
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
import StarIcon from '@mui/icons-material/Star'; // import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined'; // import StarIcon from '@mui/icons-material/Star';
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined'; // import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
// import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore'; import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore';
import KeyboardArrowUpOutlinedIcon from '@mui/icons-material/KeyboardArrowUpOutlined'; import KeyboardArrowUpOutlinedIcon from '@mui/icons-material/KeyboardArrowUpOutlined';
import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined'; import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined';
@@ -36,6 +38,8 @@ import UnfoldMoreOutlinedIcon from '@mui/icons-material/UnfoldMoreOutlined';
import SearchIcon from '@mui/icons-material/Search'; import SearchIcon from '@mui/icons-material/Search';
import FilterListIcon from '@mui/icons-material/FilterList'; import FilterListIcon from '@mui/icons-material/FilterList';
import OptionIcon from './OptionIcon';
import { ButtonRow, FormLoader, ValidatedTextField, SectionContent } from '../components'; import { ButtonRow, FormLoader, ValidatedTextField, SectionContent } from '../components';
import * as EMSESP from './api'; import * as EMSESP from './api';
@@ -47,7 +51,7 @@ import { DeviceShort, Devices, DeviceEntity, DeviceEntityMask } from './types';
const SettingsCustomization: FC = () => { const SettingsCustomization: FC = () => {
const { enqueueSnackbar } = useSnackbar(); const { enqueueSnackbar } = useSnackbar();
const [deviceEntities, setDeviceEntities] = useState<DeviceEntity[]>([{ id: '', v: 0, s: '', m: 0, w: false }]); const [deviceEntities, setDeviceEntities] = useState<DeviceEntity[]>([{ id: '', v: 0, n: '', m: 0, w: false }]);
const [devices, setDevices] = useState<Devices>(); const [devices, setDevices] = useState<Devices>();
const [errorMessage, setErrorMessage] = useState<string>(); const [errorMessage, setErrorMessage] = useState<string>();
const [selectedDevice, setSelectedDevice] = useState<number>(0); const [selectedDevice, setSelectedDevice] = useState<number>(0);
@@ -199,6 +203,15 @@ const SettingsCustomization: FC = () => {
return value; return value;
} }
function formatName(de: DeviceEntity) {
if (de.n === undefined || de.n === de.id) {
return de.id;
} else if (de.n === '') {
return 'Command: ' + de.id;
}
return de.n + ' (' + de.id + ')';
}
const getMaskNumber = (newMask: string[]) => { const getMaskNumber = (newMask: string[]) => {
var new_mask = 0; var new_mask = 0;
for (let entry of newMask) { for (let entry of newMask) {
@@ -272,7 +285,7 @@ const SettingsCustomization: FC = () => {
if (deviceEntities && selectedDevice) { if (deviceEntities && selectedDevice) {
const masked_entities = deviceEntities const masked_entities = deviceEntities
.filter((de) => de.m !== de.om) .filter((de) => de.m !== de.om)
.map((new_de) => new_de.m.toString(16).padStart(2, '0') + new_de.s); .map((new_de) => new_de.m.toString(16).padStart(2, '0') + new_de.id);
if (masked_entities.length > 60) { if (masked_entities.length > 60) {
enqueueSnackbar('Selected entities exceeded limit of 60. Please Save in batches', { variant: 'warning' }); enqueueSnackbar('Selected entities exceeded limit of 60. Please Save in batches', { variant: 'warning' });
@@ -303,8 +316,18 @@ const SettingsCustomization: FC = () => {
return ( return (
<> <>
<Box color="warning.main"> <Box mb={2} color="warning.main">
<Typography variant="body2">Select a device and customize each of its entities using the options.</Typography> <Typography variant="body2">Select a device and customize each of its entities using the options:</Typography>
<Typography variant="body2">
<OptionIcon type="favorite" isSet={true} />
=mark as a favorite&nbsp;&nbsp;
<OptionIcon type="readonly" isSet={true} />
=disable write action&nbsp;&nbsp;
<OptionIcon type="api_mqtt_exclude" isSet={true} />
=exclude from MQTT and API outputs&nbsp;&nbsp;
<OptionIcon type="web_exclude" isSet={true} />
=hide from Web Dashboard
</Typography>
</Box> </Box>
<ValidatedTextField <ValidatedTextField
name="device" name="device"
@@ -363,9 +386,11 @@ const SettingsCustomization: FC = () => {
}} }}
/> />
</Grid> </Grid>
<Tooltip arrow placement="top" title="apply filter">
<Grid item> <Grid item>
<FilterListIcon color="primary" sx={{ fontSize: 14, verticalAlign: 'middle' }} />: <FilterListIcon color="primary" sx={{ fontSize: 14, verticalAlign: 'middle' }} />:
</Grid> </Grid>
</Tooltip>
<Grid item> <Grid item>
<ToggleButtonGroup <ToggleButtonGroup
size="small" size="small"
@@ -376,34 +401,22 @@ const SettingsCustomization: FC = () => {
}} }}
> >
<ToggleButton value="8"> <ToggleButton value="8">
<Tooltip arrow placement="top" title="filter favorites"> <OptionIcon type="favorite" isSet={true} />
<StarIcon sx={{ fontSize: 14 }} />
</Tooltip>
</ToggleButton> </ToggleButton>
<ToggleButton value="4"> <ToggleButton value="4">
<Tooltip arrow placement="top" title="filter entities with write action disabled"> <OptionIcon type="readonly" isSet={true} />
<EditOffOutlinedIcon sx={{ fontSize: 14 }} />
</Tooltip>
</ToggleButton> </ToggleButton>
<ToggleButton value="2"> <ToggleButton value="2">
<Tooltip arrow placement="top" title="filter entities excluded from MQTT and API outputs"> <OptionIcon type="api_mqtt_exclude" isSet={true} />
<CommentsDisabledOutlinedIcon sx={{ fontSize: 14 }} />
</Tooltip>
</ToggleButton> </ToggleButton>
<ToggleButton value="1"> <ToggleButton value="1">
<Tooltip arrow placement="top" title="filter entities hidden from Web Dashboard"> <OptionIcon type="web_exclude" isSet={true} />
<VisibilityOffOutlinedIcon sx={{ fontSize: 14 }} />
</Tooltip>
</ToggleButton> </ToggleButton>
</ToggleButtonGroup> </ToggleButtonGroup>
</Grid> </Grid>
<Grid item> <Grid item>
<CommentsDisabledOutlinedIcon color="primary" sx={{ fontSize: 14, verticalAlign: 'middle' }} /> <Tooltip arrow placement="top" title="set selected entities to be both visible and output">
<VisibilityOffOutlinedIcon color="primary" sx={{ fontSize: 14, verticalAlign: 'middle' }} />:
</Grid>
<Grid item>
<Tooltip arrow placement="top" title="mark shown entities to be all visible and output ">
<Button <Button
size="small" size="small"
sx={{ fontSize: 10 }} sx={{ fontSize: 10 }}
@@ -411,12 +424,14 @@ const SettingsCustomization: FC = () => {
color="inherit" color="inherit"
onClick={() => maskDisabled(false)} onClick={() => maskDisabled(false)}
> >
enable set all&nbsp;
<OptionIcon type="api_mqtt_exclude" isSet={false} />
<OptionIcon type="web_exclude" isSet={false} />
</Button> </Button>
</Tooltip> </Tooltip>
</Grid> </Grid>
<Grid item> <Grid item>
<Tooltip arrow placement="top" title="mark shown entities to be not visible or output "> <Tooltip arrow placement="top" title="set selected entities to be not visible and not output">
<Button <Button
size="small" size="small"
sx={{ fontSize: 10 }} sx={{ fontSize: 10 }}
@@ -424,7 +439,9 @@ const SettingsCustomization: FC = () => {
color="inherit" color="inherit"
onClick={() => maskDisabled(true)} onClick={() => maskDisabled(true)}
> >
disable set all&nbsp;
<OptionIcon type="api_mqtt_exclude" isSet={true} />
<OptionIcon type="web_exclude" isSet={true} />
</Button> </Button>
</Tooltip> </Tooltip>
</Grid> </Grid>
@@ -458,29 +475,44 @@ const SettingsCustomization: FC = () => {
value={getMaskString(de.m)} value={getMaskString(de.m)}
onChange={(event, mask) => { onChange={(event, mask) => {
de.m = getMaskNumber(mask); de.m = getMaskNumber(mask);
if (de.n === '' && de.m & DeviceEntityMask.DV_READONLY) {
de.m = de.m | DeviceEntityMask.DV_WEB_EXCLUDE;
}
if (de.m & DeviceEntityMask.DV_WEB_EXCLUDE) { if (de.m & DeviceEntityMask.DV_WEB_EXCLUDE) {
de.m = de.m & ~DeviceEntityMask.DV_FAVORITE; de.m = de.m & ~DeviceEntityMask.DV_FAVORITE;
} }
setMasks(['']); setMasks(['']);
}} }}
> >
<ToggleButton value="8" disabled={(de.m & 1) !== 0 || de.id === ''}> <ToggleButton value="8" disabled={(de.m & 1) !== 0 || de.n === undefined}>
<StarIcon sx={{ fontSize: 14 }} /> <OptionIcon
type="favorite"
isSet={(de.m & DeviceEntityMask.DV_FAVORITE) === DeviceEntityMask.DV_FAVORITE}
/>
</ToggleButton> </ToggleButton>
<ToggleButton value="4" disabled={!de.w || (de.m & 3) === 3}> <ToggleButton value="4" disabled={!de.w || (de.m & 3) === 3}>
<EditOffOutlinedIcon sx={{ fontSize: 14 }} /> <OptionIcon
type="readonly"
isSet={(de.m & DeviceEntityMask.DV_READONLY) === DeviceEntityMask.DV_READONLY}
/>
</ToggleButton> </ToggleButton>
<ToggleButton value="2"> <ToggleButton value="2" disabled={de.n === ''}>
<CommentsDisabledOutlinedIcon sx={{ fontSize: 14 }} /> <OptionIcon
type="api_mqtt_exclude"
isSet={
(de.m & DeviceEntityMask.DV_API_MQTT_EXCLUDE) === DeviceEntityMask.DV_API_MQTT_EXCLUDE
}
/>
</ToggleButton> </ToggleButton>
<ToggleButton value="1"> <ToggleButton value="1" disabled={de.n === undefined}>
<VisibilityOffOutlinedIcon sx={{ fontSize: 14 }} /> <OptionIcon
type="web_exclude"
isSet={(de.m & DeviceEntityMask.DV_WEB_EXCLUDE) === DeviceEntityMask.DV_WEB_EXCLUDE}
/>
</ToggleButton> </ToggleButton>
</ToggleButtonGroup> </ToggleButtonGroup>
</Cell> </Cell>
<Cell> <Cell>{formatName(de)}</Cell>
{de.id}&nbsp;({de.s})
</Cell>
<Cell>{formatValue(de.v)}</Cell> <Cell>{formatValue(de.v)}</Cell>
</Row> </Row>
))} ))}

View File

@@ -131,9 +131,9 @@ export interface DeviceData {
} }
export interface DeviceEntity { export interface DeviceEntity {
id: string; // name id: string; // shortname
v: any; // value, in any format v?: any; // value, in any format, optional
s: string; // shortname n?: string; // fullname, optional
m: number; // mask m: number; // mask
om?: number; // original mask before edits om?: number; // original mask before edits
w: boolean; // writeable w: boolean; // writeable

View File

@@ -14,7 +14,7 @@
"express": "^4.18.1", "express": "^4.18.1",
"express-sse": "^0.5.3", "express-sse": "^0.5.3",
"nodemon": "^2.0.16", "nodemon": "^2.0.16",
"ws": "^8.6.0" "ws": "^8.7.0"
} }
}, },
"node_modules/@msgpack/msgpack": { "node_modules/@msgpack/msgpack": {
@@ -1811,9 +1811,9 @@
} }
}, },
"node_modules/ws": { "node_modules/ws": {
"version": "8.6.0", "version": "8.7.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz",
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==", "integrity": "sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg==",
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"
}, },
@@ -3169,9 +3169,9 @@
} }
}, },
"ws": { "ws": {
"version": "8.6.0", "version": "8.7.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz",
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==", "integrity": "sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg==",
"requires": {} "requires": {}
}, },
"xdg-basedir": { "xdg-basedir": {

View File

@@ -16,6 +16,6 @@
"express": "^4.18.1", "express": "^4.18.1",
"express-sse": "^0.5.3", "express-sse": "^0.5.3",
"nodemon": "^2.0.16", "nodemon": "^2.0.16",
"ws": "^8.6.0" "ws": "^8.7.0"
} }
} }

View File

@@ -336,6 +336,7 @@ settings = {
pbutton_gpio: 0, pbutton_gpio: 0,
board_profile: 'S32', board_profile: 'S32',
bool_format: 1, bool_format: 1,
bool_dashboard: 1,
enum_format: 1, enum_format: 1,
} }
@@ -472,7 +473,7 @@ const emsesp_devicedata_1 = {
const emsesp_devicedata_2 = { const emsesp_devicedata_2 = {
label: 'Boiler: Nefit GBx72/Trendline/Cerapur/Greenstar Si/27i', label: 'Boiler: Nefit GBx72/Trendline/Cerapur/Greenstar Si/27i',
data: [ data: [
{ v: 0, u: 0, id: '08reset', c: 'reset', l: ['-', 'maintenance', 'error'] }, { v: '', u: 0, id: '08reset', c: 'reset', l: ['-', 'maintenance', 'error'] },
{ v: 'false', u: 0, id: '08heating active' }, { v: 'false', u: 0, id: '08heating active' },
{ v: 'false', u: 0, id: '04tapwater active' }, { v: 'false', u: 0, id: '04tapwater active' },
{ v: 5, u: 1, id: '04selected flow temperature', c: 'selflowtemp' }, { v: 5, u: 1, id: '04selected flow temperature', c: 'selflowtemp' },
@@ -574,145 +575,161 @@ const emsesp_devicedata_4 = {
], ],
} }
// CUSTOMIZATION
const emsesp_deviceentities_1 = [ const emsesp_deviceentities_1 = [
{ {
v: '(0)', v: '(0)',
n: 'error code',
id: 'errorcode', id: 'errorcode',
s: 'errorcode',
m: 0, m: 0,
w: false, w: false,
}, },
{ {
v: '14:54:39 06/06/2021', v: '14:54:39 06/06/2021',
id: 'date/time', n: 'date/time',
s: 'datetime', id: 'datetime',
m: 0,
w: false,
},
{
v: 'test data',
n: 'test',
id: 'test',
m: 0,
w: false,
},
{
v: 'roomTemp',
id: 'hc1/HA climate config creation',
m: 0, m: 0,
w: false, w: false,
}, },
{ {
v: 18.2, v: 18.2,
id: 'hc1 selected room temperature', n: 'hc1 selected room temperature',
s: 'hc1/seltemp', id: 'hc1/seltemp',
m: 0, m: 0,
w: true, w: true,
}, },
{ {
v: 22.6, v: 22.6,
id: 'hc1 current room temperature', n: 'hc1 current room temperature',
s: 'hc1/curtemp', id: 'hc1/curtemp',
m: 0, m: 0,
w: false, w: false,
}, },
{ {
v: 'auto', v: 'auto',
id: 'hc1 mode', n: 'hc1 mode',
s: 'hc1/mode', id: 'hc1/mode',
m: 0, m: 0,
w: true, w: true,
}, },
] ]
const emsesp_deviceentities_2 = [ const emsesp_deviceentities_2 = [
{ v: false, id: 'heating active', s: 'heatingactive', m: 0, w: false }, { u: 0, n: '', id: 'reset', m: 8, w: false },
{ v: false, id: 'tapwater active', s: 'tapwateractive', m: 0, w: false }, { v: false, n: 'heating active', id: 'heatingactive', m: 8, w: false },
{ v: 5, id: 'selected flow temperature', s: 'selflowtemp', m: 0, w: true }, { v: false, n: 'tapwater active', id: 'tapwateractive', m: 4, w: false },
{ v: 0, id: 'burner selected max power', s: 'selburnpow', m: 0, w: true }, { v: 5, n: 'selected flow temperature', id: 'selflowtemp', m: 4, w: true },
{ v: 0, id: 'heating pump modulation', s: 'heatingpumpmod', m: 0, w: false }, { v: 0, n: 'burner selected max power', id: 'selburnpow', m: 14, w: true },
{ id: 'heating pump 2 modulation', s: 'heatingpump2mod', m: 0, w: false }, { v: 0, n: 'heating pump modulation', id: 'heatingpumpmod', m: 0, w: false },
{ id: 'outside temperature', s: 'outdoortemp', m: 0, w: false }, { n: 'heating pump 2 modulation', id: 'heatingpump2mod', m: 0, w: false },
{ v: 53, id: 'current flow temperature', s: 'curflowtemp', m: 0, w: false }, { n: 'outside temperature', id: 'outdoortemp', m: 0, w: false },
{ v: 51.8, id: 'return temperature', s: 'rettemp', m: 0, w: false }, { v: 53, n: 'current flow temperature', id: 'curflowtemp', m: 0, w: false },
{ id: 'mixing switch temperature', s: 'switchtemp', m: 0, w: false }, { v: 51.8, n: 'return temperature', id: 'rettemp', m: 0, w: false },
{ v: 1.3, id: 'system pressure', s: 'syspress', m: 0, w: false }, { n: 'mixing switch temperature', id: 'switchtemp', m: 0, w: false },
{ v: 54.6, id: 'actual boiler temperature', s: 'boiltemp', m: 0, w: false }, { v: 1.3, n: 'system pressure', id: 'syspress', m: 0, w: false },
{ id: 'exhaust temperature', s: 'exhausttemp', m: 0, w: false }, { v: 54.6, n: 'actual boiler temperature', id: 'boiltemp', m: 0, w: false },
{ v: false, id: 'gas', s: 'burngas', m: 0, w: false }, { n: 'exhaust temperature', id: 'exhausttemp', m: 0, w: false },
{ v: false, id: 'gas stage 2', s: 'burngas2', m: 0, w: false }, { v: false, n: 'gas', id: 'burngas', m: 0, w: false },
{ v: 0, id: 'flame current', s: 'flamecurr', m: 0, w: false }, { v: false, n: 'gas stage 2', id: 'burngas2', m: 0, w: false },
{ v: false, id: 'heating pump', s: 'heatingpump', m: 0, w: false }, { v: 0, n: 'flame current', id: 'flamecurr', m: 0, w: false },
{ v: false, id: 'fan', s: 'fanwork', m: 0, w: false }, { v: false, n: 'heating pump', id: 'heatingpump', m: 0, w: false },
{ v: false, id: 'ignition', s: 'ignwork', m: 0, w: false }, { v: false, n: 'fan', id: 'fanwork', m: 0, w: false },
{ v: false, id: 'oil preheating', s: 'oilpreheat', m: 0, w: false }, { v: false, n: 'ignition', id: 'ignwork', m: 0, w: false },
{ v: true, id: 'heating activated', s: 'heatingactivated', m: 0, w: false }, { v: false, n: 'oil preheating', id: 'oilpreheat', m: 0, w: false },
{ v: 80, id: 'heating temperature', s: 'heatingtemp', m: 0, w: false }, { v: true, n: 'heating activated', id: 'heatingactivated', m: 0, w: false },
{ v: 70, id: 'burner pump max power', s: 'pumpmodmax', m: 0, w: false }, { v: 80, n: 'heating temperature', id: 'heatingtemp', m: 0, w: false },
{ v: 30, id: 'burner pump min power', s: 'pumpmodmin', m: 0, w: false }, { v: 70, n: 'burner pump max power', id: 'pumpmodmax', m: 0, w: false },
{ v: 1, id: 'pump delay', s: 'pumpdelay', m: 0, w: false }, { v: 30, n: 'burner pump min power', id: 'pumpmodmin', m: 0, w: false },
{ v: 10, id: 'burner min period', s: 'burnminperiod', m: 0, w: false }, { v: 1, n: 'pump delay', id: 'pumpdelay', m: 0, w: false },
{ v: 0, id: 'burner min power', s: 'burnminpower', m: 0, w: false }, { v: 10, n: 'burner min period', id: 'burnminperiod', m: 0, w: false },
{ v: 50, id: 'burner max power', s: 'burnmaxpower', m: 0, w: false }, { v: 0, n: 'burner min power', id: 'burnminpower', m: 0, w: false },
{ v: -6, id: 'hysteresis on temperature', s: 'boilhyston', m: 0, w: false }, { v: 50, n: 'burner max power', id: 'burnmaxpower', m: 0, w: false },
{ v: 6, id: 'hysteresis off temperature', s: 'boilhystoff', m: 0, w: false }, { v: -6, n: 'hysteresis on temperature', id: 'boilhyston', m: 0, w: false },
{ v: 0, id: 'set flow temperature', s: 'setflowtemp', m: 0, w: true }, { v: 6, n: 'hysteresis off temperature', id: 'boilhystoff', m: 0, w: false },
{ v: 0, id: 'burner set power', s: 'setburnpow', m: 0, w: false }, { v: 0, n: 'set flow temperature', id: 'setflowtemp', m: 0, w: true },
{ v: 0, id: 'burner current power', s: 'curburnpow', m: 0, w: false }, { v: 0, n: 'burner set power', id: 'setburnpow', m: 0, w: false },
{ v: 326323, id: 'burner starts', s: 'burnstarts', m: 0, w: false }, { v: 0, n: 'burner current power', id: 'curburnpow', m: 0, w: false },
{ v: 553437, id: 'total burner operating time', s: 'burnworkmin', m: 0, w: false }, { v: 326323, n: 'burner starts', id: 'burnstarts', m: 0, w: false },
{ v: 451286, id: 'total heat operating time', s: 'heatworkmin', m: 0, w: false }, { v: 553437, n: 'total burner operating time', id: 'burnworkmin', m: 0, w: false },
{ v: 4672175, id: 'total UBA operating time', s: 'ubauptime', m: 0, w: false }, { v: 451286, n: 'total heat operating time', id: 'heatworkmin', m: 0, w: false },
{ v: '1C(210) 06.06.2020 12:07 (0 min)', id: 'last error code', s: 'lastcode', m: 0, w: false }, { v: 4672175, n: 'total UBA operating time', id: 'ubauptime', m: 0, w: false },
{ v: '0H', id: 'service code', s: 'servicecode', m: 0, w: false }, { v: '1C(210) 06.06.2020 12:07 (0 min)', n: 'last error code', id: 'lastcode', m: 0, w: false },
{ v: 203, id: 'service code number', s: 'servicecodenumber', m: 0, w: false }, { v: '0H', n: 'service code', id: 'servicecode', m: 0, w: false },
{ v: 'H00', id: 'maintenance message', s: 'maintenancemessage', m: 0, w: false }, { v: 203, n: 'service code number', id: 'servicecodenumber', m: 0, w: false },
{ v: 'manual', id: 'maintenance scheduled', s: 'maintenance', m: 0, w: false }, { v: 'H00', n: 'maintenance message', id: 'maintenancemessage', m: 0, w: false },
{ v: 6000, id: 'time to next maintenance', s: 'maintenancetime', m: 0, w: false }, { v: 'manual', n: 'maintenance scheduled', id: 'maintenance', m: 0, w: false },
{ v: '01.01.2012', id: 'next maintenance date', s: 'maintenancedate', m: 0, w: false }, { v: 6000, n: 'time to next maintenance', id: 'maintenancetime', m: 0, w: false },
{ v: true, id: 'dhw turn on/off', s: 'wwtapactivated', m: 0, w: false }, { v: '01.01.2012', n: 'next maintenance date', id: 'maintenancedate', m: 0, w: false },
{ v: 62, id: 'dhw set temperature', s: 'wwsettemp', m: 0, w: false }, { v: true, n: 'dhw turn on/off', id: 'wwtapactivated', m: 0, w: false },
{ v: 60, id: 'dhw selected temperature', s: 'wwseltemp', m: 0, w: true }, { v: 62, n: 'dhw set temperature', id: 'wwsettemp', m: 0, w: false },
{ id: 'dhw selected lower temperature', s: 'wwseltemplow', m: 2 }, { v: 60, n: 'dhw selected temperature', id: 'wwseltemp', m: 0, w: true },
{ id: 'dhw selected temperature for off', s: 'wwseltempoff', m: 2 }, { n: 'dhw selected lower temperature', id: 'wwseltemplow', m: 2 },
{ id: 'dhw single charge temperature', s: 'wwseltempsingle', m: 2 }, { n: 'dhw selected temperature for off', id: 'wwseltempoff', m: 2 },
{ v: 'flow', id: 'dhw type', s: 'wwtype', m: 0, w: false }, { n: 'dhw single charge temperature', id: 'wwseltempsingle', m: 2 },
{ v: 'hot', id: 'dhw comfort', s: 'wwcomfort', m: 0, w: false }, { v: 'flow', n: 'dhw type', id: 'wwtype', m: 0, w: false },
{ v: 40, id: 'dhw flow temperature offset', s: 'wwflowtempoffset', m: 0, w: false }, { v: 'hot', n: 'dhw comfort', id: 'wwcomfort', m: 0, w: false },
{ v: 100, id: 'dhw max power', s: 'wwmaxpower', m: 0, w: false }, { v: 40, n: 'dhw flow temperature offset', id: 'wwflowtempoffset', m: 0, w: false },
{ v: false, id: 'dhw circulation pump available', s: 'wwcircpump', m: 0, w: false }, { v: 100, n: 'dhw max power', id: 'wwmaxpower', m: 0, w: false },
{ v: '3-way valve', id: 'dhw charging type', s: 'wwchargetype', m: 0, w: false }, { v: false, n: 'dhw circulation pump available', id: 'wwcircpump', m: 0, w: false },
{ v: -5, id: 'dhw hysteresis on temperature', s: 'wwhyston', m: 0, w: false }, { v: '3-way valve', n: 'dhw charging type', id: 'wwchargetype', m: 0, w: false },
{ v: 0, id: 'dhw hysteresis off temperature', s: 'wwhystoff', m: 0, w: false }, { v: -5, n: 'dhw hysteresis on temperature', id: 'wwhyston', m: 0, w: false },
{ v: 70, id: 'dhw disinfection temperature', s: 'wwdisinfectiontemp', m: 0, w: false }, { v: 0, n: 'dhw hysteresis off temperature', id: 'wwhystoff', m: 0, w: false },
{ v: 'off', id: 'dhw circulation pump mode', s: 'wwcircmode', m: 0, w: false }, { v: 70, n: 'dhw disinfection temperature', id: 'wwdisinfectiontemp', m: 0, w: false },
{ v: false, id: 'dhw circulation active', s: 'wwcirc', m: 0, w: false }, { v: 'off', n: 'dhw circulation pump mode', id: 'wwcircmode', m: 0, w: false },
{ v: 46.4, id: 'dhw current intern temperature', s: 'wwcurtemp', m: 0, w: false }, { v: false, n: 'dhw circulation active', id: 'wwcirc', m: 0, w: false },
{ id: 'dhw current extern temperature', s: 'wwcurtemp2', m: 2 }, { v: 46.4, n: 'dhw current intern temperature', id: 'wwcurtemp', m: 0, w: false },
{ v: 0, id: 'dhw current tap water flow', s: 'wwcurflow', m: 0, w: false }, { n: 'dhw current extern temperature', id: 'wwcurtemp2', m: 2 },
{ v: 46.3, id: 'dhw storage intern temperature', s: 'wwstoragetemp1', m: 0, w: false }, { v: 0, n: 'dhw current tap water flow', id: 'wwcurflow', m: 0, w: false },
{ id: 'dhw storage extern temperature', s: 'wwstoragetemp2', m: 2 }, { v: 46.3, n: 'dhw storage intern temperature', id: 'wwstoragetemp1', m: 0, w: false },
{ v: true, id: 'dhw activated', s: 'wwactivated', m: 0, w: false }, { n: 'dhw storage extern temperature', id: 'wwstoragetemp2', m: 2 },
{ v: false, id: 'dhw one time charging', s: 'wwonetime', m: 0, w: false }, { v: true, n: 'dhw activated', id: 'wwactivated', m: 0, w: false },
{ v: false, id: 'dhw disinfecting', s: 'wwdisinfecting', m: 0, w: false }, { v: false, n: 'dhw one time charging', id: 'wwonetime', m: 0, w: false },
{ v: false, id: 'dhw charging', s: 'wwcharging', m: 0, w: false }, { v: false, n: 'dhw disinfecting', id: 'wwdisinfecting', m: 0, w: false },
{ v: false, id: 'dhw recharging', s: 'wwrecharging', m: 0, w: false }, { v: false, n: 'dhw charging', id: 'wwcharging', m: 0, w: false },
{ v: true, id: 'dhw temperature ok', s: 'wwtempok', m: 0, w: false }, { v: false, n: 'dhw recharging', id: 'wwrecharging', m: 0, w: false },
{ v: false, id: 'dhw active', s: 'wwactive', m: 0, w: false }, { v: true, n: 'dhw temperature ok', id: 'wwtempok', m: 0, w: false },
{ v: true, id: 'dhw 3way valve active', s: 'ww3wayvalve', m: 0, w: false }, { v: false, n: 'dhw active', id: 'wwactive', m: 0, w: false },
{ v: 0, id: 'dhw set pump power', s: 'wwsetpumppower', m: 0, w: true }, { v: true, n: 'dhw 3way valve active', id: 'ww3wayvalve', m: 0, w: false },
{ id: 'dhw mixer temperature', s: 'wwmixertemp', m: 2 }, { v: 0, n: 'dhw set pump power', id: 'wwsetpumppower', m: 0, w: true },
{ id: 'dhw cylinder middle temperature (TS3)', s: 'wwcylmiddletemp', m: 2 }, { n: 'dhw mixer temperature', id: 'wwmixertemp', m: 2 },
{ v: 288768, id: 'dhw starts', s: 'wwstarts', m: 0, w: false }, { n: 'dhw cylinder middle temperature (TS3)', id: 'wwcylmiddletemp', m: 2 },
{ v: 102151, id: 'dhw active time', s: 'wwworkm', m: 0, w: false }, { v: 288768, n: 'dhw starts', id: 'wwstarts', m: 0, w: false },
{ v: 102151, n: 'dhw active time', id: 'wwworkm', m: 0, w: false },
] ]
const emsesp_deviceentities_4 = [ const emsesp_deviceentities_4 = [
{ {
v: 16, v: 16,
id: 'hc2 selected room temperature', n: 'hc2 selected room temperature',
s: 'hc2/seltemp', id: 'hc2/seltemp',
m: 8, m: 8,
w: true, w: true,
}, },
{ {
v: 18.5, v: 18.5,
id: 'hc2 current room temperature', n: 'hc2 current room temperature',
s: 'hc2/curtemp', id: 'hc2/curtemp',
m: 2, m: 2,
w: false, w: false,
}, },
{ {
v: 'off', v: 'off',
id: 'hc2 mode', n: 'hc2 mode',
s: 'hc2/mode', id: 'hc2/mode',
m: 2, m: 2,
w: true, w: true,
}, },
@@ -911,13 +928,13 @@ rest_server.post(EMSESP_DEVICEENTITIES_ENDPOINT, (req, res) => {
}) })
function updateMask(entity, de, dd) { function updateMask(entity, de, dd) {
const name = entity.slice(2) const shortname = entity.slice(2)
const new_mask = parseInt(entity.slice(0, 2), 16) const new_mask = parseInt(entity.slice(0, 2), 16)
objIndex = de.findIndex((obj) => obj.s == name) objIndex = de.findIndex((obj) => obj.id == shortname)
if (objIndex !== -1) { if (objIndex !== -1) {
de[objIndex].m = new_mask de[objIndex].m = new_mask
const fullname = de[objIndex].id const fullname = de[objIndex].n
objIndex = dd.data.findIndex((obj) => obj.id.slice(2) == fullname) objIndex = dd.data.findIndex((obj) => obj.id.slice(2) == fullname)
if (objIndex !== -1) { if (objIndex !== -1) {
// see if the mask has changed // see if the mask has changed
@@ -929,7 +946,7 @@ function updateMask(entity, de, dd) {
} }
} }
} else { } else {
console.log("can't locate record for id " + id) console.log("can't locate record for name " + shortname)
} }
} }

View File

@@ -32,5 +32,5 @@ build_type = debug
monitor_filters = esp32_exception_decoder monitor_filters = esp32_exception_decoder
debug_tool = esp-prog debug_tool = esp-prog
debug_init_break = tbreak setup debug_init_break = tbreak setup
build_flags = ${factory_settings.build_flags} ${common.debug_flags} -DONEWIRE_CRC16=0 -DNO_GLOBAL_ARDUINOOTA -DARDUINOJSON_ENABLE_STD_STRING=1 -DESP32=1 -DARDUINO_ARCH_ESP32=1 build_flags = ${factory_settings.build_flags} -DONEWIRE_CRC16=0 -DNO_GLOBAL_ARDUINOOTA -DARDUINOJSON_ENABLE_STD_STRING=1 -DESP32=1 -DARDUINO_ARCH_ESP32=1
extra_scripts = pre:scripts/build_interface.py extra_scripts = pre:scripts/build_interface.py

View File

@@ -62,8 +62,7 @@ extra_scripts =
pre:scripts/build_interface.py pre:scripts/build_interface.py
scripts/rename_fw.py scripts/rename_fw.py
board = esp32dev board = esp32dev
; platform = espressif32 platform = espressif32
platform = https://github.com/platformio/platform-espressif32.git ; develop
board_build.partitions = esp32_partition_app1984k_spiffs64k.csv board_build.partitions = esp32_partition_app1984k_spiffs64k.csv
build_flags = ${common.build_flags} build_flags = ${common.build_flags}
build_unflags = ${common.unbuild_flags} build_unflags = ${common.unbuild_flags}

View File

@@ -68,7 +68,7 @@
{224, DeviceType::CONTROLLER, F("9000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 {224, DeviceType::CONTROLLER, F("9000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{229, DeviceType::CONTROLLER, F("8700i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 {229, DeviceType::CONTROLLER, F("8700i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{230, DeviceType::CONTROLLER, F("BC Base"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 {230, DeviceType::CONTROLLER, F("BC Base"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{240, DeviceType::CONTROLLER, F("Rego 3000"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 {240, DeviceType::CONTROLLER, F("Rego 3000"), DeviceFlags::EMS_DEVICE_FLAG_IVT}, // 0x09
{241, DeviceType::CONTROLLER, F("Condens 5000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 {241, DeviceType::CONTROLLER, F("Condens 5000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
// Thermostat - not currently supporting write operations, like the Easy/100 types - 0x18 // Thermostat - not currently supporting write operations, like the Easy/100 types - 0x18

View File

@@ -25,9 +25,11 @@ REGISTER_FACTORY(Controller, EMSdevice::DeviceType::CONTROLLER);
Controller::Controller(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand) Controller::Controller(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) { : EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
// IVT broadcasts Thermostat time from controller (0x09) if display is off. // IVT broadcasts Thermostat time from controller (0x09) if display is off.
if ((flags & 0x0F) == EMS_DEVICE_FLAG_IVT) {
register_telegram_type(0x06, F("RCTime"), false, MAKE_PF_CB(process_dateTime)); register_telegram_type(0x06, F("RCTime"), false, MAKE_PF_CB(process_dateTime));
register_device_value(DeviceValueTAG::TAG_NONE, &dateTime_, DeviceValueType::STRING, nullptr, FL_(dateTime), DeviceValueUOM::NONE); register_device_value(DeviceValueTAG::TAG_NONE, &dateTime_, DeviceValueType::STRING, nullptr, FL_(dateTime), DeviceValueUOM::NONE);
} }
}
// process_dateTime - type 0x06 - date and time from a thermostat - 14 bytes long, IVT only // process_dateTime - type 0x06 - date and time from a thermostat - 14 bytes long, IVT only
void Controller::process_dateTime(std::shared_ptr<const Telegram> telegram) { void Controller::process_dateTime(std::shared_ptr<const Telegram> telegram) {
@@ -35,7 +37,7 @@ void Controller::process_dateTime(std::shared_ptr<const Telegram> telegram) {
return; return;
} }
char newdatetime[sizeof(dateTime_)]; char newdatetime[sizeof(dateTime_)];
// publich as dd.mm.yyyy hh:mmF // publish as dd.mm.yyyy hh:mm
snprintf(newdatetime, snprintf(newdatetime,
sizeof(dateTime_), sizeof(dateTime_),
"%02d.%02d.%04d %02d:%02d", "%02d.%02d.%04d %02d:%02d",
@@ -47,5 +49,4 @@ void Controller::process_dateTime(std::shared_ptr<const Telegram> telegram) {
has_update(dateTime_, newdatetime, sizeof(dateTime_)); has_update(dateTime_, newdatetime, sizeof(dateTime_));
} }
} // namespace emsesp } // namespace emsesp

View File

@@ -114,6 +114,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
} else if ((model == EMSdevice::EMS_DEVICE_FLAG_RC300) || (model == EMSdevice::EMS_DEVICE_FLAG_RC100)) { } else if ((model == EMSdevice::EMS_DEVICE_FLAG_RC300) || (model == EMSdevice::EMS_DEVICE_FLAG_RC100)) {
monitor_typeids = {0x02A5, 0x02A6, 0x02A7, 0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC}; monitor_typeids = {0x02A5, 0x02A6, 0x02A7, 0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC};
set_typeids = {0x02B9, 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, 0x02BF, 0x02C0}; set_typeids = {0x02B9, 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, 0x02BF, 0x02C0};
set2_typeids = {0x02CC, 0x02CE, 0x02D0, 0x02D2}; // max. 4 heating circuits supported ny RC310
summer_typeids = {0x02AF, 0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6}; summer_typeids = {0x02AF, 0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6};
curve_typeids = {0x029B, 0x029C, 0x029D, 0x029E, 0x029F, 0x02A0, 0x02A1, 0x02A2}; curve_typeids = {0x029B, 0x029C, 0x029D, 0x029E, 0x029F, 0x02A0, 0x02A1, 0x02A2};
summer2_typeids = {0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0476, 0x0477, 0x0478}; summer2_typeids = {0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0476, 0x0477, 0x0478};
@@ -124,6 +125,9 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
register_telegram_type(curve_typeids[i], F("RC300Curves"), false, MAKE_PF_CB(process_RC300Curve)); register_telegram_type(curve_typeids[i], F("RC300Curves"), false, MAKE_PF_CB(process_RC300Curve));
register_telegram_type(summer2_typeids[i], F("RC300Summer2"), false, MAKE_PF_CB(process_RC300Summer2)); register_telegram_type(summer2_typeids[i], F("RC300Summer2"), false, MAKE_PF_CB(process_RC300Summer2));
} }
for (uint8_t i = 0; i < set2_typeids.size(); i++) {
register_telegram_type(set2_typeids[i], F("RC300Set2"), false, MAKE_PF_CB(process_RC300Set2));
}
register_telegram_type(0x2F5, F("RC300WWmode"), true, MAKE_PF_CB(process_RC300WWmode)); register_telegram_type(0x2F5, F("RC300WWmode"), true, MAKE_PF_CB(process_RC300WWmode));
register_telegram_type(0x31B, F("RC300WWtemp"), true, MAKE_PF_CB(process_RC300WWtemp)); register_telegram_type(0x31B, F("RC300WWtemp"), true, MAKE_PF_CB(process_RC300WWtemp));
register_telegram_type(0x31D, F("RC300WWmode2"), false, MAKE_PF_CB(process_RC300WWmode2)); register_telegram_type(0x31D, F("RC300WWmode2"), false, MAKE_PF_CB(process_RC300WWmode2));
@@ -221,6 +225,16 @@ std::shared_ptr<Thermostat::HeatingCircuit> Thermostat::heating_circuit(std::sha
} }
} }
// not found, search set2 types
if (hc_num == 0) {
for (uint8_t i = 0; i < set2_typeids.size(); i++) {
if (set2_typeids[i] == telegram->type_id) {
hc_num = i + 1;
break;
}
}
}
// not found, search summer message types // not found, search summer message types
if (hc_num == 0) { if (hc_num == 0) {
for (uint8_t i = 0; i < summer_typeids.size(); i++) { for (uint8_t i = 0; i < summer_typeids.size(); i++) {
@@ -328,6 +342,9 @@ std::shared_ptr<Thermostat::HeatingCircuit> Thermostat::heating_circuit(std::sha
if (set_typeids.size()) { if (set_typeids.size()) {
toggle_fetch(set_typeids[hc_num - 1], toggle_); toggle_fetch(set_typeids[hc_num - 1], toggle_);
} }
if (hc_num <= set2_typeids.size()) {
toggle_fetch(set2_typeids[hc_num - 1], toggle_);
}
if (summer_typeids.size()) { if (summer_typeids.size()) {
toggle_fetch(summer_typeids[hc_num - 1], toggle_); toggle_fetch(summer_typeids[hc_num - 1], toggle_);
} }
@@ -922,6 +939,10 @@ void Thermostat::process_RC300Set(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, hc->manualtemp, 10); // is * 2 has_update(telegram, hc->manualtemp, 10); // is * 2
has_enumupdate(telegram, hc->program, 11, 1); // timer program 1 or 2 has_enumupdate(telegram, hc->program, 11, 1); // timer program 1 or 2
has_enumupdate(telegram, hc->reducemode, 5, 1); // 1-outdoor temp threshold, 2-room temp threshold, 3-reduced mode
has_update(telegram, hc->reducetemp, 9);
has_update(telegram, hc->noreducetemp, 12);
} }
// types 0x2AF ff // types 0x2AF ff
@@ -967,8 +988,10 @@ void Thermostat::process_RC300Curve(std::shared_ptr<const Telegram> telegram) {
return; return;
} }
has_update(telegram, hc->controlmode, 0); // 1-outdoor, 2-simple, 3-MPC, 4-room, 5-power, 6-const has_enumupdate(telegram, hc->controlmode, 0, 1); // 1-weather_compensated, 2-outside_footpoint,3-n/a, 4-room -- RC310
has_update(telegram, hc->heatingtype, 1); // 1=radiator, 2=convector, 3=floor has_update(telegram, hc->heatingtype, 1); // 1=radiator, 2=convector, 3=floor
has_update(telegram, hc->switchonoptimization, 4);
has_enumupdate(telegram, hc->nofrostmode, 5, 1); // 1-room, 2-outdoor, 3- room & outdoor
has_update(telegram, hc->nofrosttemp, 6); has_update(telegram, hc->nofrosttemp, 6);
if (hc->heatingtype < 3) { if (hc->heatingtype < 3) {
@@ -1022,10 +1045,24 @@ void Thermostat::process_RC300OutdoorTemp(std::shared_ptr<const Telegram> telegr
// 0x240 RC300 parameter // 0x240 RC300 parameter
void Thermostat::process_RC300Settings(std::shared_ptr<const Telegram> telegram) { void Thermostat::process_RC300Settings(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, ibaDamping_, 8);
has_enumupdate(telegram, ibaBuildingType_, 9, 1); // 1=light, 2=medium, 3=heavy has_enumupdate(telegram, ibaBuildingType_, 9, 1); // 1=light, 2=medium, 3=heavy
has_update(telegram, ibaMinExtTemperature_, 10); has_update(telegram, ibaMinExtTemperature_, 10);
} }
// 0x2CC - e.g. wwprio for RC310 hcx parameter
void Thermostat::process_RC300Set2(std::shared_ptr<const Telegram> telegram) {
// typeids are not in a raw. hc:0x2CC, hc2: 0x2CE for RC310
// telegram is either offset 3 with data lenght of 1 and values 0/1 (radiators) - 10 0B FF 03 01 CC 01 F6
// or offset 0 with data lenght of 6 bytes - offset 3 values are 0x00 or 0xFF - 10 0B FF 00 01 CE FF 13 0A FF 1E 00 20
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(telegram);
if (hc == nullptr) {
return;
}
has_update(telegram, hc->wwprio, 3);
}
// 0x267 RC300 floordrying // 0x267 RC300 floordrying
void Thermostat::process_RC300Floordry(std::shared_ptr<const Telegram> telegram) { void Thermostat::process_RC300Floordry(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, floordrystatus_, 0); has_update(telegram, floordrystatus_, 0);
@@ -1597,14 +1634,20 @@ bool Thermostat::set_heatingpid(const char * value, const int8_t id) {
return true; return true;
} }
// 0xA5 - Set the damping settings // 0xA5 and 0x0240- Set the damping settings
bool Thermostat::set_damping(const char * value, const int8_t id) { bool Thermostat::set_damping(const char * value, const int8_t id) {
bool dmp; bool dmp;
if (model() == EMS_DEVICE_FLAG_RC300) {
if (Helpers::value2bool(value, dmp)) {
write_command(0x240, 8, dmp ? 0xFF : 0, 0x240);
return true;
}
} else {
if (Helpers::value2bool(value, dmp)) { if (Helpers::value2bool(value, dmp)) {
write_command(EMS_TYPE_IBASettings, 21, dmp ? 0xFF : 0, EMS_TYPE_IBASettings); write_command(EMS_TYPE_IBASettings, 21, dmp ? 0xFF : 0, EMS_TYPE_IBASettings);
return true; return true;
} }
}
return false; return false;
} }
@@ -1750,12 +1793,16 @@ bool Thermostat::set_wwprio(const char * value, const int8_t id) {
if (!Helpers::value2bool(value, b)) { if (!Helpers::value2bool(value, b)) {
return false; return false;
} }
if ((model() == EMS_DEVICE_FLAG_RC300)) {
write_command(set2_typeids[hc->hc()], 3, b ? 0xFF : 0x00, set2_typeids[hc->hc()]);
} else {
write_command(set_typeids[hc->hc()], 21, b ? 0xFF : 0x00, set_typeids[hc->hc()]); write_command(set_typeids[hc->hc()], 21, b ? 0xFF : 0x00, set_typeids[hc->hc()]);
}
return true; return true;
} }
// sets the thermostat ww circulation working mode, where mode is a string // sets the thermostat ww circulation working mode, where mode is a string
bool Thermostat::set_wwcircmode(const char * value, const int8_t id) { bool Thermostat::set_wwcircmode(const char * value, const int8_t id) {
uint8_t set = 0xFF; uint8_t set = 0xFF;
@@ -2344,7 +2391,25 @@ bool Thermostat::set_fastheatup(const char * value, const int8_t id) {
return true; return true;
} }
// sets the thermostat reducemode for RC35 // Set switchonoptimization RC310
bool Thermostat::set_switchonoptimization(const char * value, const int8_t id) {
uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id;
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(hc_num);
if (hc == nullptr) {
return false;
}
bool b = false;
if (!Helpers::value2bool(value, b)) {
return false;
}
write_command(curve_typeids[hc->hc()], 4, b ? 0xFF : 0x00, curve_typeids[hc->hc()]);
return true;
}
// sets the thermostat reducemode for RC35 and RC310
bool Thermostat::set_reducemode(const char * value, const int8_t id) { bool Thermostat::set_reducemode(const char * value, const int8_t id) {
uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id; uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id;
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(hc_num); std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(hc_num);
@@ -2353,13 +2418,19 @@ bool Thermostat::set_reducemode(const char * value, const int8_t id) {
} }
uint8_t set = 0xFF; uint8_t set = 0xFF;
if (!Helpers::value2enum(value, set, FL_(enum_reducemode))) { if (model() == EMS_DEVICE_FLAG_RC300) {
return false; if (Helpers::value2enum(value, set, FL_(enum_reducemode1))) {
write_command(set_typeids[hc->hc()], 5, set + 1, set_typeids[hc->hc()]);
} }
} else {
if (Helpers::value2enum(value, set, FL_(enum_reducemode))) {
write_command(set_typeids[hc->hc()], EMS_OFFSET_RC35Set_reducemode, set, set_typeids[hc->hc()]); write_command(set_typeids[hc->hc()], EMS_OFFSET_RC35Set_reducemode, set, set_typeids[hc->hc()]);
return true; return true;
} }
}
return true;
}
// sets the thermostat reducemode for RC35 vacations // sets the thermostat reducemode for RC35 vacations
bool Thermostat::set_vacreducemode(const char * value, const int8_t id) { bool Thermostat::set_vacreducemode(const char * value, const int8_t id) {
@@ -2378,22 +2449,27 @@ bool Thermostat::set_vacreducemode(const char * value, const int8_t id) {
return true; return true;
} }
// sets the thermostat nofrost mode for RC35 // sets the thermostat nofrost mode for RC35, RC300/RC310
bool Thermostat::set_nofrostmode(const char * value, const int8_t id) { bool Thermostat::set_nofrostmode(const char * value, const int8_t id) {
uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id; uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id;
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(hc_num); std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(hc_num);
if (hc == nullptr) { if (hc == nullptr) {
return false; return false;
} }
uint8_t set = 0xFF; uint8_t set = 0xFF;
if (!Helpers::value2enum(value, set, FL_(enum_nofrostmode))) { if (model() == EMS_DEVICE_FLAG_RC300) {
return false; if (Helpers::value2enum(value, set, FL_(enum_nofrostmode1))) {
write_command(curve_typeids[hc->hc()], 5, set + 1, curve_typeids[hc->hc()]);
return true;
} }
} else {
if (Helpers::value2enum(value, set, FL_(enum_nofrostmode))) {
write_command(set_typeids[hc->hc()], EMS_OFFSET_RC35Set_nofrostmode, set, set_typeids[hc->hc()]); write_command(set_typeids[hc->hc()], EMS_OFFSET_RC35Set_nofrostmode, set, set_typeids[hc->hc()]);
return true; return true;
} }
}
return true;
}
// sets the thermostat heatingtype for RC35, RC300 // sets the thermostat heatingtype for RC35, RC300
bool Thermostat::set_heatingtype(const char * value, const int8_t id) { bool Thermostat::set_heatingtype(const char * value, const int8_t id) {
@@ -2429,11 +2505,16 @@ bool Thermostat::set_controlmode(const char * value, const int8_t id) {
} }
uint8_t set = 0xFF; uint8_t set = 0xFF;
if (model() == EMS_DEVICE_FLAG_RC300 || model() == EMS_DEVICE_FLAG_RC100) { if (model() == EMS_DEVICE_FLAG_RC100) {
if (Helpers::value2enum(value, set, FL_(enum_controlmode))) { if (Helpers::value2enum(value, set, FL_(enum_controlmode))) {
write_command(curve_typeids[hc->hc()], 0, set, curve_typeids[hc->hc()]); write_command(curve_typeids[hc->hc()], 0, set, curve_typeids[hc->hc()]);
return true; return true;
} }
} else if (model() == EMS_DEVICE_FLAG_RC300) {
if (Helpers::value2enum(value, set, FL_(enum_controlmode1))) {
write_command(curve_typeids[hc->hc()], 0, set + 1, curve_typeids[hc->hc()]);
return true;
}
} else if (model() == EMS_DEVICE_FLAG_RC30) { } else if (model() == EMS_DEVICE_FLAG_RC30) {
if (Helpers::value2enum(value, set, FL_(enum_controlmode2))) { if (Helpers::value2enum(value, set, FL_(enum_controlmode2))) {
write_command(curve_typeids[hc->hc()], 1, set, curve_typeids[hc->hc()]); write_command(curve_typeids[hc->hc()], 1, set, curve_typeids[hc->hc()]);
@@ -2856,6 +2937,16 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
offset = 0; offset = 0;
factor = 1; factor = 1;
break; break;
case HeatingCircuit::Mode::NOREDUCE:
validate_typeid = set_typeid;
offset = 12;
factor = 1;
break;
case HeatingCircuit::Mode::REDUCE:
validate_typeid = set_typeid;
offset = 9;
factor = 1;
break;
default: default:
// HeatingCircuit::Mode::AUTO: // HeatingCircuit::Mode::AUTO:
uint8_t mode_ = hc->get_mode(); uint8_t mode_ = hc->get_mode();
@@ -3224,6 +3315,8 @@ void Thermostat::register_device_values() {
FL_(ibaMinExtTemperature), FL_(ibaMinExtTemperature),
DeviceValueUOM::DEGREES, DeviceValueUOM::DEGREES,
MAKE_CF_CB(set_minexttemp)); MAKE_CF_CB(set_minexttemp));
register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA, &ibaDamping_, DeviceValueType::BOOL, nullptr, FL_(damping), DeviceValueUOM::NONE, MAKE_CF_CB(set_damping));
register_device_value( register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA_WW, &wwSetTemp_, DeviceValueType::UINT, nullptr, FL_(wwSetTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwtemp)); DeviceValueTAG::TAG_DEVICE_DATA_WW, &wwSetTemp_, DeviceValueType::UINT, nullptr, FL_(wwSetTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwtemp));
register_device_value( register_device_value(
@@ -3769,6 +3862,8 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
register_device_value( register_device_value(
tag, &hc->roominfl_factor, DeviceValueType::UINT, FL_(div10), FL_(roominfl_factor), DeviceValueUOM::NONE, MAKE_CF_CB(set_roominfl_factor)); tag, &hc->roominfl_factor, DeviceValueType::UINT, FL_(div10), FL_(roominfl_factor), DeviceValueUOM::NONE, MAKE_CF_CB(set_roominfl_factor));
register_device_value(tag, &hc->curroominfl, DeviceValueType::SHORT, FL_(div10), FL_(curroominfl), DeviceValueUOM::DEGREES_R); register_device_value(tag, &hc->curroominfl, DeviceValueType::SHORT, FL_(div10), FL_(curroominfl), DeviceValueUOM::DEGREES_R);
register_device_value(
tag, &hc->nofrostmode, DeviceValueType::ENUM, FL_(enum_nofrostmode1), FL_(nofrostmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_nofrostmode));
register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT, nullptr, FL_(nofrosttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nofrosttemp)); register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT, nullptr, FL_(nofrosttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nofrosttemp));
register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT, nullptr, FL_(targetflowtemp), DeviceValueUOM::DEGREES); register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT, nullptr, FL_(targetflowtemp), DeviceValueUOM::DEGREES);
register_device_value( register_device_value(
@@ -3784,11 +3879,22 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
MAKE_CF_CB(set_summermode)); MAKE_CF_CB(set_summermode));
register_device_value(tag, &hc->summermode, DeviceValueType::ENUM, FL_(enum_summer), FL_(summermode), DeviceValueUOM::NONE); register_device_value(tag, &hc->summermode, DeviceValueType::ENUM, FL_(enum_summer), FL_(summermode), DeviceValueUOM::NONE);
register_device_value( register_device_value(
tag, &hc->controlmode, DeviceValueType::ENUM, FL_(enum_controlmode), FL_(controlmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_controlmode)); tag, &hc->controlmode, DeviceValueType::ENUM, FL_(enum_controlmode1), FL_(controlmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_controlmode));
register_device_value(tag, &hc->program, DeviceValueType::ENUM, FL_(enum_progMode), FL_(program), DeviceValueUOM::NONE, MAKE_CF_CB(set_program)); register_device_value(tag, &hc->program, DeviceValueType::ENUM, FL_(enum_progMode), FL_(program), DeviceValueUOM::NONE, MAKE_CF_CB(set_program));
register_device_value( register_device_value(
tag, &hc->tempautotemp, DeviceValueType::INT, FL_(div2), FL_(tempautotemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_tempautotemp), -1, 30); tag, &hc->tempautotemp, DeviceValueType::INT, FL_(div2), FL_(tempautotemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_tempautotemp), -1, 30);
register_device_value(tag, &hc->fastHeatup, DeviceValueType::UINT, nullptr, FL_(fastheatup), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_fastheatup)); register_device_value(tag, &hc->fastHeatup, DeviceValueType::UINT, nullptr, FL_(fastheatup), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_fastheatup));
register_device_value(tag,
&hc->switchonoptimization,
DeviceValueType::BOOL,
nullptr,
FL_(switchonoptimization),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_switchonoptimization));
register_device_value(tag, &hc->reducemode, DeviceValueType::ENUM, FL_(enum_reducemode1), FL_(reducemode), DeviceValueUOM::NONE, MAKE_CF_CB(set_reducemode));
register_device_value(tag, &hc->noreducetemp, DeviceValueType::INT, nullptr, FL_(noreducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_noreducetemp));
register_device_value(tag, &hc->reducetemp, DeviceValueType::INT, nullptr, FL_(reducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_reducetemp));
register_device_value(tag, &hc->wwprio, DeviceValueType::BOOL, nullptr, FL_(wwprio), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwprio));
break; break;
case EMS_DEVICE_FLAG_CRF: case EMS_DEVICE_FLAG_CRF:
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode5), FL_(mode), DeviceValueUOM::NONE); register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode5), FL_(mode), DeviceValueUOM::NONE);

View File

@@ -80,6 +80,7 @@ class Thermostat : public EMSdevice {
char switchtime1[16]; char switchtime1[16];
char switchtime2[16]; char switchtime2[16];
uint8_t climate; uint8_t climate;
uint8_t switchonoptimization;
// RC 10 // RC 10
uint8_t reducehours; // night reduce duration uint8_t reducehours; // night reduce duration
@@ -160,6 +161,7 @@ class Thermostat : public EMSdevice {
// each thermostat has a list of heating controller type IDs for reading and writing // each thermostat has a list of heating controller type IDs for reading and writing
std::vector<uint16_t> monitor_typeids; std::vector<uint16_t> monitor_typeids;
std::vector<uint16_t> set_typeids; std::vector<uint16_t> set_typeids;
std::vector<uint16_t> set2_typeids;
std::vector<uint16_t> timer_typeids; std::vector<uint16_t> timer_typeids;
std::vector<uint16_t> timer2_typeids; std::vector<uint16_t> timer2_typeids;
std::vector<uint16_t> summer_typeids; std::vector<uint16_t> summer_typeids;
@@ -357,6 +359,7 @@ class Thermostat : public EMSdevice {
void process_CRFMonitor(std::shared_ptr<const Telegram> telegram); void process_CRFMonitor(std::shared_ptr<const Telegram> telegram);
void process_RC300Monitor(std::shared_ptr<const Telegram> telegram); void process_RC300Monitor(std::shared_ptr<const Telegram> telegram);
void process_RC300Set(std::shared_ptr<const Telegram> telegram); void process_RC300Set(std::shared_ptr<const Telegram> telegram);
void process_RC300Set2(std::shared_ptr<const Telegram> telegram);
void process_RC300Summer(std::shared_ptr<const Telegram> telegram); void process_RC300Summer(std::shared_ptr<const Telegram> telegram);
void process_RC300Summer2(std::shared_ptr<const Telegram> telegram); void process_RC300Summer2(std::shared_ptr<const Telegram> telegram);
void process_RC300WWmode(std::shared_ptr<const Telegram> telegram); void process_RC300WWmode(std::shared_ptr<const Telegram> telegram);
@@ -412,7 +415,6 @@ class Thermostat : public EMSdevice {
bool set_vacreducetemp(const char * value, const int8_t id); bool set_vacreducetemp(const char * value, const int8_t id);
bool set_vacreducemode(const char * value, const int8_t id); bool set_vacreducemode(const char * value, const int8_t id);
bool set_nofrostmode(const char * value, const int8_t id); bool set_nofrostmode(const char * value, const int8_t id);
bool set_remotetemp(const char * value, const int8_t id); bool set_remotetemp(const char * value, const int8_t id);
bool set_roominfluence(const char * value, const int8_t id); bool set_roominfluence(const char * value, const int8_t id);
bool set_roominfl_factor(const char * value, const int8_t id); bool set_roominfl_factor(const char * value, const int8_t id);
@@ -426,6 +428,7 @@ class Thermostat : public EMSdevice {
bool set_controlmode(const char * value, const int8_t id); bool set_controlmode(const char * value, const int8_t id);
bool set_wwprio(const char * value, const int8_t id); bool set_wwprio(const char * value, const int8_t id);
bool set_fastheatup(const char * value, const int8_t id); bool set_fastheatup(const char * value, const int8_t id);
bool set_switchonoptimization(const char * value, const int8_t id);
// set functions - these don't use the id/hc, the parameters are ignored // set functions - these don't use the id/hc, the parameters are ignored
bool set_wwmode(const char * value, const int8_t id); bool set_wwmode(const char * value, const int8_t id);

View File

@@ -726,11 +726,9 @@ void EMSdevice::generate_values_web(JsonObject & output) {
auto mask = Helpers::hextoa((uint8_t)(dv.state >> 4), false); // create mask to a 2-char string auto mask = Helpers::hextoa((uint8_t)(dv.state >> 4), false); // create mask to a 2-char string
// add name, prefixing the tag if it exists. This is the id used for the table sorting // add name, prefixing the tag if it exists. This is the id used in the WebUI table and must be unique
if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) { if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) {
obj["id"] = mask + read_flash_string(dv.full_name); obj["id"] = mask + read_flash_string(dv.full_name);
} else if (dv.tag < DeviceValueTAG::TAG_HC1) {
obj["id"] = mask + tag_to_string(dv.tag) + " " + read_flash_string(dv.full_name);
} else { } else {
obj["id"] = mask + tag_to_string(dv.tag) + " " + read_flash_string(dv.full_name); obj["id"] = mask + tag_to_string(dv.tag) + " " + read_flash_string(dv.full_name);
} }
@@ -785,7 +783,7 @@ void EMSdevice::generate_values_web(JsonObject & output) {
// as generate_values_web() but stripped down to only show all entities and their state // as generate_values_web() but stripped down to only show all entities and their state
// this is used only for WebCustomizationService::device_entities() // this is used only for WebCustomizationService::device_entities()
void EMSdevice::generate_values_web_all(JsonArray & output) { void EMSdevice::generate_values_web_customization(JsonArray & output) {
for (const auto & dv : devicevalues_) { for (const auto & dv : devicevalues_) {
// also show commands and entities that have an empty full name // also show commands and entities that have an empty full name
JsonObject obj = output.createNestedObject(); JsonObject obj = output.createNestedObject();
@@ -841,29 +839,29 @@ void EMSdevice::generate_values_web_all(JsonArray & output) {
obj["v"] = (divider > 0) ? time_value / divider : time_value * factor; // sometimes we need to divide by 60 obj["v"] = (divider > 0) ? time_value / divider : time_value * factor; // sometimes we need to divide by 60
} }
} }
} else {
// must always have v for sorting to work in web
obj["v"] = "";
} }
// add name, prefixing the tag if it exists as the id (key for table sorting) // id holds the shortname and must always have a value for the WebUI table to work
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
obj["id"] = tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name);
} else {
obj["id"] = read_flash_string(dv.short_name);
}
// n is the fullname, and can be optional
// don't add the fullname if its a command
if (dv.type != DeviceValueType::CMD) {
if (dv.full_name) { if (dv.full_name) {
if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) { if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) {
obj["id"] = dv.full_name; obj["n"] = dv.full_name;
} else { } else {
char name[50]; char name[50];
snprintf(name, sizeof(name), "%s %s", tag_to_string(dv.tag).c_str(), read_flash_string(dv.full_name).c_str()); snprintf(name, sizeof(name), "%s %s", tag_to_string(dv.tag).c_str(), read_flash_string(dv.full_name).c_str());
obj["id"] = name; obj["n"] = name;
}
} }
} else { } else {
obj["id"] = ""; obj["n"] = "";
}
// shortname
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
obj["s"] = tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name);
} else {
obj["s"] = dv.short_name;
} }
obj["m"] = dv.state >> 4; // send back the mask state. We're only interested in the high nibble obj["m"] = dv.state >> 4; // send back the mask state. We're only interested in the high nibble

View File

@@ -202,7 +202,7 @@ class EMSdevice {
enum OUTPUT_TARGET : uint8_t { API_VERBOSE, API_SHORTNAMES, MQTT, CONSOLE }; enum OUTPUT_TARGET : uint8_t { API_VERBOSE, API_SHORTNAMES, MQTT, CONSOLE };
bool generate_values(JsonObject & output, const uint8_t tag_filter, const bool nested, const uint8_t output_target); bool generate_values(JsonObject & output, const uint8_t tag_filter, const bool nested, const uint8_t output_target);
void generate_values_web(JsonObject & output); void generate_values_web(JsonObject & output);
void generate_values_web_all(JsonArray & output); void generate_values_web_customization(JsonArray & output);
void register_device_value(uint8_t tag, void register_device_value(uint8_t tag,
void * value_p, void * value_p,
@@ -317,6 +317,9 @@ class EMSdevice {
// device flags: The lower 4 bits hold the unique identifier, the upper 4 bits are used for specific flags // device flags: The lower 4 bits hold the unique identifier, the upper 4 bits are used for specific flags
static constexpr uint8_t EMS_DEVICE_FLAG_NONE = 0; static constexpr uint8_t EMS_DEVICE_FLAG_NONE = 0;
// Controller
static constexpr uint8_t EMS_DEVICE_FLAG_IVT = 1;
// Boiler // Boiler
static constexpr uint8_t EMS_DEVICE_FLAG_EMS = 1; static constexpr uint8_t EMS_DEVICE_FLAG_EMS = 1;
static constexpr uint8_t EMS_DEVICE_FLAG_EMSPLUS = 2; static constexpr uint8_t EMS_DEVICE_FLAG_EMSPLUS = 2;

View File

@@ -311,6 +311,7 @@ MAKE_PSTR_WORD(winter)
MAKE_PSTR_WORD(outdoor) MAKE_PSTR_WORD(outdoor)
MAKE_PSTR_WORD(mpc) MAKE_PSTR_WORD(mpc)
MAKE_PSTR_WORD(room) MAKE_PSTR_WORD(room)
MAKE_PSTR_WORD(room_outdoor)
MAKE_PSTR_WORD(power) MAKE_PSTR_WORD(power)
MAKE_PSTR_WORD(constant) MAKE_PSTR_WORD(constant)
MAKE_PSTR_WORD(simple) MAKE_PSTR_WORD(simple)
@@ -381,9 +382,12 @@ MAKE_PSTR_LIST(enum_modetype4, F_(nofrost), F_(eco), F_(heat))
MAKE_PSTR_LIST(enum_modetype5, F_(off), F_(on)) MAKE_PSTR_LIST(enum_modetype5, F_(off), F_(on))
MAKE_PSTR_LIST(enum_reducemode, F_(nofrost), F_(reduce), F_(room), F_(outdoor)) MAKE_PSTR_LIST(enum_reducemode, F_(nofrost), F_(reduce), F_(room), F_(outdoor))
MAKE_PSTR_LIST(enum_reducemode1, F_(outdoor), F_(room), F_(reduce)) // RC310 values: 1-3
MAKE_PSTR_LIST(enum_nofrostmode, F_(off), F_(room), F_(outdoor)) MAKE_PSTR_LIST(enum_nofrostmode, F_(off), F_(room), F_(outdoor))
MAKE_PSTR_LIST(enum_nofrostmode1, F_(room), F_(outdoor), F_(room_outdoor))
MAKE_PSTR_LIST(enum_controlmode, F_(off), F_(optimized), F_(simple), F_(mpc), F_(room), F_(power), F_(constant)) MAKE_PSTR_LIST(enum_controlmode, F_(off), F_(optimized), F_(simple), F_(mpc), F_(room), F_(power), F_(constant))
MAKE_PSTR_LIST(enum_controlmode1, F("weather-compensated"), F("outside-basepoint"), F("n/a"), F_(room)) // RC310 1-4
MAKE_PSTR_LIST(enum_controlmode2, F_(outdoor), F_(room)) MAKE_PSTR_LIST(enum_controlmode2, F_(outdoor), F_(room))
// MAKE_PSTR_LIST(enum_controlmode3, F_(off), F_(room), F_(outdoor), F("room+outdoor")) // MAKE_PSTR_LIST(enum_controlmode3, F_(off), F_(room), F_(outdoor), F("room+outdoor"))
MAKE_PSTR_LIST(enum_control, F_(off), F_(rc20), F_(rc3x)) MAKE_PSTR_LIST(enum_control, F_(off), F_(rc20), F_(rc3x))
@@ -614,7 +618,7 @@ MAKE_PSTR_LIST(wwDailyHeating, F("wwdailyheating"), F("daily heating"))
MAKE_PSTR_LIST(wwDailyHeatTime, F("wwdailyheattime"), F("daily heating time")) MAKE_PSTR_LIST(wwDailyHeatTime, F("wwdailyheattime"), F("daily heating time"))
MAKE_PSTR_LIST(wwWhenModeOff, F("wwwhenmodeoff"), F("when thermostat mode off")) MAKE_PSTR_LIST(wwWhenModeOff, F("wwwhenmodeoff"), F("when thermostat mode off"))
// thermostat hc // thermostat hc
MAKE_PSTR_LIST(climate, F("climate")) MAKE_PSTR_LIST(climate, F("HA climate config creation")) // no full-name, hidden, only for creation
MAKE_PSTR_LIST(selRoomTemp, F("seltemp"), F("selected room temperature")) MAKE_PSTR_LIST(selRoomTemp, F("seltemp"), F("selected room temperature"))
MAKE_PSTR_LIST(roomTemp, F("currtemp"), F("current room temperature")) MAKE_PSTR_LIST(roomTemp, F("currtemp"), F("current room temperature"))
MAKE_PSTR_LIST(mode, F("mode"), F("mode")) MAKE_PSTR_LIST(mode, F("mode"), F("mode"))
@@ -662,9 +666,11 @@ MAKE_PSTR_LIST(reducetemp, F("reducetemp"), F("off/reduce switch temperature"))
MAKE_PSTR_LIST(vacreducetemp, F("vacreducetemp"), F("vacations off/reduce switch temperature")) MAKE_PSTR_LIST(vacreducetemp, F("vacreducetemp"), F("vacations off/reduce switch temperature"))
MAKE_PSTR_LIST(vacreducemode, F("vacreducemode"), F("vacations reduce mode")) MAKE_PSTR_LIST(vacreducemode, F("vacreducemode"), F("vacations reduce mode"))
MAKE_PSTR_LIST(nofrostmode, F("nofrostmode"), F("nofrost mode")) MAKE_PSTR_LIST(nofrostmode, F("nofrostmode"), F("nofrost mode"))
MAKE_PSTR_LIST(nofrostmode1, F("nofrostmode1"), F("nofrost mode")) // RC310
MAKE_PSTR_LIST(remotetemp, F("remotetemp"), F("room temperature from remote")) MAKE_PSTR_LIST(remotetemp, F("remotetemp"), F("room temperature from remote"))
MAKE_PSTR_LIST(reducehours, F("reducehours"), F("duration for nighttemp")) MAKE_PSTR_LIST(reducehours, F("reducehours"), F("duration for nighttemp"))
MAKE_PSTR_LIST(reduceminutes, F("reduceminutes"), F("remaining time for nightmode")) MAKE_PSTR_LIST(reduceminutes, F("reduceminutes"), F("remaining time for nightmode"))
MAKE_PSTR_LIST(switchonoptimization, F("switchonoptimization"), F("switch-on optimization"))
// heatpump // heatpump
MAKE_PSTR_LIST(airHumidity, F("airhumidity"), F("relative air humidity")) MAKE_PSTR_LIST(airHumidity, F("airhumidity"), F("relative air humidity"))

View File

@@ -418,7 +418,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
// emsdevice->generate_values_web(root); // emsdevice->generate_values_web(root);
JsonArray output = doc.to<JsonArray>(); JsonArray output = doc.to<JsonArray>();
emsdevice->generate_values_web_all(output); emsdevice->generate_values_web_customization(output);
Serial.print(COLOR_BRIGHT_MAGENTA); Serial.print(COLOR_BRIGHT_MAGENTA);
serializeJson(doc, Serial); serializeJson(doc, Serial);

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.4.1b0idf4" #define EMSESP_APP_VERSION "3.4.2b1"

View File

@@ -132,6 +132,7 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject & input) {
JsonVariant data = output["api_data"]; JsonVariant data = output["api_data"];
request->send(200, "text/plain; charset=utf-8", data.as<String>()); request->send(200, "text/plain; charset=utf-8", data.as<String>());
api_count_++; api_count_++;
delete response;
return; return;
} }

View File

@@ -196,7 +196,7 @@ void WebCustomizationService::device_entities(AsyncWebServerRequest * request, J
if (emsdevice->unique_id() == json["id"]) { if (emsdevice->unique_id() == json["id"]) {
#ifndef EMSESP_STANDALONE #ifndef EMSESP_STANDALONE
JsonArray output = response->getRoot(); JsonArray output = response->getRoot();
emsdevice->generate_values_web_all(output); emsdevice->generate_values_web_customization(output);
#endif #endif
response->setLength(); response->setLength();
request->send(response); request->send(response);