mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-03-15 06:06:31 +03:00
Merge pull request #1834 from proddy/dev
Allow device name to be customized
This commit is contained in:
@@ -21,10 +21,11 @@
|
||||
- Added scripts for OTA (scripts/upload.py and upload_cli.py) [#1738](https://github.com/emsesp/EMS-ESP32/issues/1738)
|
||||
- timeout for remote thermostat emulation [#1680](https://github.com/emsesp/EMS-ESP32/discussions/1680), [#1774](https://github.com/emsesp/EMS-ESP32/issues/1774)
|
||||
- CR120 thermostat as own model() [#1779](https://github.com/emsesp/EMS-ESP32/discussions/1779)
|
||||
- Modules - external linkable module library [#1778](https://github.com/emsesp/EMS-ESP32/issues/1778)
|
||||
- Scheduler onChange and Conditions [#1806](https://github.com/emsesp/EMS-ESP32/issues/1806)
|
||||
- modules - external linkable module library [#1778](https://github.com/emsesp/EMS-ESP32/issues/1778)
|
||||
- scheduler onChange and Conditions [#1806](https://github.com/emsesp/EMS-ESP32/issues/1806)
|
||||
- make remote control timeout editable [#1774](https://github.com/emsesp/EMS-ESP32/issues/1774)
|
||||
- added extra pump characteristics (mode and pressure for EMS+) by @SLTKA [#1802](https://github.com/emsesp/EMS-ESP32/pull/1802)
|
||||
- allow device name to be customized [#1174](https://github.com/emsesp/EMS-ESP32/issues/1174)
|
||||
|
||||
## Fixed
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
"react-router-dom": "^6.24.0",
|
||||
"react-toastify": "^10.0.5",
|
||||
"typesafe-i18n": "^5.26.2",
|
||||
"typescript": "^5.5.2"
|
||||
"typescript": "^5.5.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.24.7",
|
||||
@@ -59,12 +59,12 @@
|
||||
"concurrently": "^8.2.2",
|
||||
"eslint": "^9.6.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"preact": "^10.22.0",
|
||||
"preact": "^10.22.1",
|
||||
"prettier": "^3.3.2",
|
||||
"rollup-plugin-visualizer": "^5.12.0",
|
||||
"terser": "^5.31.1",
|
||||
"typescript-eslint": "^7.14.1",
|
||||
"vite": "^5.3.2",
|
||||
"typescript-eslint": "^7.15.0",
|
||||
"vite": "^5.3.3",
|
||||
"vite-plugin-imagemin": "^0.6.1",
|
||||
"vite-tsconfig-paths": "^4.3.2"
|
||||
},
|
||||
|
||||
@@ -331,7 +331,8 @@ const de: Translation = {
|
||||
MODULES: 'Module', // TODO translate
|
||||
MODULES_UPDATED: 'Modules updated', // TODO translate
|
||||
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
|
||||
MODULES_NONE: 'No external modules detected' // TODO translate
|
||||
MODULES_NONE: 'No external modules detected', // TODO translate
|
||||
RENAME: 'Rename' // TODO translate
|
||||
};
|
||||
|
||||
export default de;
|
||||
|
||||
@@ -331,7 +331,8 @@ const en: Translation = {
|
||||
MODULES: 'Modules',
|
||||
MODULES_UPDATED: 'Modules updated',
|
||||
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules',
|
||||
MODULES_NONE: 'No external modules detected'
|
||||
MODULES_NONE: 'No external modules detected',
|
||||
RENAME: 'Rename'
|
||||
};
|
||||
|
||||
export default en;
|
||||
|
||||
@@ -331,7 +331,8 @@ const fr: Translation = {
|
||||
MODULES: 'Module', // TODO translate
|
||||
MODULES_UPDATED: 'Modules updated', // TODO translate
|
||||
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
|
||||
MODULES_NONE: 'No external modules detected' // TODO translate
|
||||
MODULES_NONE: 'No external modules detected', // TODO translate
|
||||
RENAME: 'Rename' // TODO translate
|
||||
};
|
||||
|
||||
export default fr;
|
||||
|
||||
@@ -331,7 +331,8 @@ const it: Translation = {
|
||||
MODULES: 'Module', // TODO translate
|
||||
MODULES_UPDATED: 'Modules updated', // TODO translate
|
||||
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
|
||||
MODULES_NONE: 'No external modules detected' // TODO translate
|
||||
MODULES_NONE: 'No external modules detected', // TODO translate
|
||||
RENAME: 'Rename' // TODO translate
|
||||
};
|
||||
|
||||
export default it;
|
||||
|
||||
@@ -331,7 +331,8 @@ const nl: Translation = {
|
||||
MODULES: 'Module',
|
||||
MODULES_UPDATED: 'Modules geüpdatet',
|
||||
MODULES_DESCRIPTION: 'Klik op de module om EMS-ESP library modules te activeren of te deactiveren',
|
||||
MODULES_NONE: 'Geen externe modules gedetecteerd'
|
||||
MODULES_NONE: 'Geen externe modules gedetecteerd',
|
||||
RENAME: 'Hernoemen'
|
||||
};
|
||||
|
||||
export default nl;
|
||||
|
||||
@@ -331,7 +331,8 @@ const no: Translation = {
|
||||
MODULES: 'Module', // TODO translate
|
||||
MODULES_UPDATED: 'Modules updated', // TODO translate
|
||||
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
|
||||
MODULES_NONE: 'No external modules detected' // TODO translate
|
||||
MODULES_NONE: 'No external modules detected', // TODO translate
|
||||
RENAME: 'Rename' // TODO translate
|
||||
};
|
||||
|
||||
export default no;
|
||||
|
||||
@@ -331,7 +331,8 @@ const pl: BaseTranslation = {
|
||||
MODULES: 'Module', // TODO translate
|
||||
MODULES_UPDATED: 'Modules updated', // TODO translate
|
||||
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
|
||||
MODULES_NONE: 'No external modules detected' // TODO translate
|
||||
MODULES_NONE: 'No external modules detected', // TODO translate
|
||||
RENAME: 'Rename' // TODO translate
|
||||
};
|
||||
|
||||
export default pl;
|
||||
|
||||
@@ -331,7 +331,7 @@ const sk: Translation = {
|
||||
MODULES: 'Module', // TODO translate
|
||||
MODULES_UPDATED: 'Modules updated', // TODO translate
|
||||
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
|
||||
MODULES_NONE: 'No external modules detected' // TODO translate
|
||||
MODULES_NONE: 'No external modules detected', // TODO translate
|
||||
RENAME: 'Rename' // TODO translate
|
||||
};
|
||||
|
||||
export default sk;
|
||||
|
||||
@@ -331,7 +331,8 @@ const sv: Translation = {
|
||||
MODULES: 'Module', // TODO translate
|
||||
MODULES_UPDATED: 'Modules updated', // TODO translate
|
||||
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
|
||||
MODULES_NONE: 'No external modules detected' // TODO translate
|
||||
MODULES_NONE: 'No external modules detected', // TODO translate
|
||||
RENAME: 'Rename' // TODO translate
|
||||
};
|
||||
|
||||
export default sv;
|
||||
|
||||
@@ -331,7 +331,8 @@ const tr: Translation = {
|
||||
MODULES: 'Module', // TODO translate
|
||||
MODULES_UPDATED: 'Modules updated', // TODO translate
|
||||
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
|
||||
MODULES_NONE: 'No external modules detected' // TODO translate
|
||||
MODULES_NONE: 'No external modules detected', // TODO translate
|
||||
RENAME: 'Rename' // TODO translate
|
||||
};
|
||||
|
||||
export default tr;
|
||||
|
||||
@@ -4,7 +4,9 @@ import { useBlocker, useLocation } from 'react-router-dom';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import EditIcon from '@mui/icons-material/Edit';
|
||||
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
|
||||
import SaveIcon from '@mui/icons-material/Save';
|
||||
import SearchIcon from '@mui/icons-material/Search';
|
||||
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
@@ -71,21 +73,31 @@ const Customization: FC = () => {
|
||||
const [search, setSearch] = useState('');
|
||||
const [selectedDeviceEntity, setSelectedDeviceEntity] = useState<DeviceEntity>();
|
||||
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
||||
const [rename, setRename] = useState<boolean>(false);
|
||||
|
||||
useLayoutTitle(LL.CUSTOMIZATIONS());
|
||||
|
||||
// fetch devices first
|
||||
const { data: devices } = useRequest(EMSESP.readDevices);
|
||||
const { data: devices, send: fetchDevices } = useRequest(EMSESP.readDevices);
|
||||
|
||||
const [selectedDevice, setSelectedDevice] = useState<number>(
|
||||
Number(useLocation().state) || -1
|
||||
);
|
||||
const [selectedDeviceTypeNameURL, setSelectedDeviceTypeNameURL] =
|
||||
useState<string>(''); // needed for API URL
|
||||
const [selectedDeviceName, setSelectedDeviceName] = useState<string>('');
|
||||
|
||||
const { send: resetCustomizations } = useRequest(EMSESP.resetCustomizations(), {
|
||||
immediate: false
|
||||
});
|
||||
|
||||
const { send: writeDeviceName } = useRequest(
|
||||
(data: { id: number; name: string }) => EMSESP.writeDeviceName(data),
|
||||
{
|
||||
immediate: false
|
||||
}
|
||||
);
|
||||
|
||||
const { send: writeCustomizationEntities } = useRequest(
|
||||
(data: { id: number; entity_ids: string[] }) =>
|
||||
EMSESP.writeCustomizationEntities(data),
|
||||
@@ -223,9 +235,10 @@ const Customization: FC = () => {
|
||||
const id = devices.devices.findIndex((d) => d.i === selectedDevice);
|
||||
if (id === -1) {
|
||||
setSelectedDevice(-1);
|
||||
setSelectedDeviceName('');
|
||||
setSelectedDeviceTypeNameURL('');
|
||||
} else {
|
||||
setSelectedDeviceName(devices.devices[id].tn || '');
|
||||
setSelectedDeviceTypeNameURL(devices.devices[id].url || '');
|
||||
setSelectedDeviceName(devices.devices[id].s);
|
||||
setNumChanges(0);
|
||||
setRestartNeeded(false);
|
||||
}
|
||||
@@ -388,31 +401,87 @@ const Customization: FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const renameDevice = async () => {
|
||||
await writeDeviceName({ id: selectedDevice, name: selectedDeviceName })
|
||||
.then(() => {
|
||||
toast.success(LL.UPDATED_OF(LL.NAME(1)));
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error(LL.UPDATE_OF(LL.NAME(1)) + ' ' + LL.FAILED(1));
|
||||
})
|
||||
.finally(async () => {
|
||||
setRename(false);
|
||||
await fetchDevices();
|
||||
});
|
||||
};
|
||||
|
||||
const renderDeviceList = () => (
|
||||
<>
|
||||
<Box mb={1} color="warning.main">
|
||||
<Typography variant="body2">{LL.CUSTOMIZATIONS_HELP_1()}.</Typography>
|
||||
</Box>
|
||||
<TextField
|
||||
name="device"
|
||||
label={LL.EMS_DEVICE()}
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
value={selectedDevice}
|
||||
disabled={numChanges !== 0}
|
||||
onChange={(e) => setSelectedDevice(parseInt(e.target.value))}
|
||||
margin="normal"
|
||||
select
|
||||
>
|
||||
<MenuItem disabled key={-1} value={-1}>
|
||||
{LL.SELECT_DEVICE()}...
|
||||
</MenuItem>
|
||||
{devices.devices.map((device: DeviceShort) => (
|
||||
<MenuItem key={device.i} value={device.i}>
|
||||
{device.s}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
<Box display="flex" flexWrap="wrap" alignItems="center" gap={2}>
|
||||
{rename ? (
|
||||
<TextField
|
||||
name="device"
|
||||
label={LL.EMS_DEVICE()}
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={selectedDeviceName}
|
||||
onChange={(e) => setSelectedDeviceName(e.target.value)}
|
||||
margin="normal"
|
||||
/>
|
||||
) : (
|
||||
<TextField
|
||||
name="device"
|
||||
label={LL.EMS_DEVICE()}
|
||||
variant="outlined"
|
||||
value={selectedDevice}
|
||||
disabled={numChanges !== 0}
|
||||
onChange={(e) => setSelectedDevice(parseInt(e.target.value))}
|
||||
margin="normal"
|
||||
style={{ minWidth: '50%' }}
|
||||
select
|
||||
>
|
||||
<MenuItem disabled key={-1} value={-1}>
|
||||
{LL.SELECT_DEVICE()}...
|
||||
</MenuItem>
|
||||
{devices.devices.map((device: DeviceShort) => (
|
||||
<MenuItem key={device.i} value={device.i}>
|
||||
{device.s} ({device.tn})
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
)}
|
||||
{selectedDevice !== -1 &&
|
||||
(rename ? (
|
||||
<ButtonRow>
|
||||
<Button
|
||||
startIcon={<SaveIcon />}
|
||||
variant="contained"
|
||||
onClick={() => renameDevice()}
|
||||
>
|
||||
{LL.UPDATE()}
|
||||
</Button>
|
||||
<Button
|
||||
startIcon={<CancelIcon />}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
onClick={() => setRename(false)}
|
||||
>
|
||||
{LL.CANCEL()}
|
||||
</Button>
|
||||
</ButtonRow>
|
||||
) : (
|
||||
<Button
|
||||
startIcon={<EditIcon />}
|
||||
variant="outlined"
|
||||
onClick={() => setRename(true)}
|
||||
>
|
||||
{LL.RENAME()}
|
||||
</Button>
|
||||
))}
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -545,7 +614,7 @@ const Customization: FC = () => {
|
||||
{formatName(de, false)} (
|
||||
<Link
|
||||
target="_blank"
|
||||
href={APIURL + selectedDeviceName + '/' + de.id}
|
||||
href={APIURL + selectedDeviceTypeNameURL + '/' + de.id}
|
||||
>
|
||||
{de.id}
|
||||
</Link>
|
||||
@@ -600,7 +669,7 @@ const Customization: FC = () => {
|
||||
const renderContent = () => (
|
||||
<>
|
||||
{devices && renderDeviceList()}
|
||||
{selectedDevice !== -1 && renderDeviceData()}
|
||||
{selectedDevice !== -1 && !rename && renderDeviceData()}
|
||||
{restartNeeded && (
|
||||
<MessageBox my={2} level="warning" message={LL.RESTART_TEXT(0)}>
|
||||
<Button
|
||||
|
||||
@@ -646,8 +646,8 @@ const Devices: FC = () => {
|
||||
>
|
||||
<Box sx={{ border: '1px solid #177ac9' }}>
|
||||
<Typography noWrap variant="subtitle1" color="warning.main" sx={{ ml: 1 }}>
|
||||
{coreData.devices[deviceIndex].tn} |
|
||||
{coreData.devices[deviceIndex].n}
|
||||
{coreData.devices[deviceIndex].n} (
|
||||
{coreData.devices[deviceIndex].tn})
|
||||
</Typography>
|
||||
|
||||
<Grid container justifyContent="space-between">
|
||||
|
||||
@@ -169,7 +169,6 @@ const Modules: FC = () => {
|
||||
|
||||
const colorStatus = (status: number) => {
|
||||
if (status === 1) {
|
||||
// TODO translate
|
||||
return <div style={{ color: 'red' }}>Pending Activation</div>;
|
||||
}
|
||||
return <div style={{ color: '#00FF7F' }}>Activated</div>;
|
||||
@@ -191,10 +190,8 @@ const Modules: FC = () => {
|
||||
<HeaderRow>
|
||||
<HeaderCell />
|
||||
<HeaderCell>{LL.NAME(0)}</HeaderCell>
|
||||
{/* TODO translate */}
|
||||
<HeaderCell>Author</HeaderCell>
|
||||
<HeaderCell>{LL.VERSION()}</HeaderCell>
|
||||
{/* TODO translate */}
|
||||
<HeaderCell>Message</HeaderCell>
|
||||
<HeaderCell>{LL.STATUS_OF('')}</HeaderCell>
|
||||
</HeaderRow>
|
||||
|
||||
@@ -66,7 +66,6 @@ const ModulesDialog = ({
|
||||
name="enabled"
|
||||
/>
|
||||
}
|
||||
// TODO translate
|
||||
label="Enabled"
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
@@ -24,7 +24,7 @@ export const readCoreData = () => alovaInstance.Get<CoreData>(`/rest/coreData`);
|
||||
export const readDeviceData = (id: number) =>
|
||||
alovaInstance.Get<DeviceData>('/rest/deviceData', {
|
||||
// alovaInstance.Get<DeviceData>(`/rest/deviceData/${id}`, {
|
||||
params: { id }, // TODO replace later with id
|
||||
params: { id },
|
||||
responseType: 'arraybuffer' // uses msgpack
|
||||
});
|
||||
export const writeDeviceValue = (data: { id: number; c: string; v: unknown }) =>
|
||||
@@ -66,7 +66,7 @@ export const getSchedule = () => alovaInstance.Get('/rest/getSchedule');
|
||||
export const readDeviceEntities = (id: number) =>
|
||||
// alovaInstance.Get<DeviceEntity[]>(`/rest/deviceEntities/${id}`, {
|
||||
alovaInstance.Get<DeviceEntity[]>(`/rest/deviceEntities`, {
|
||||
params: { id }, // TODO replace later with id
|
||||
params: { id },
|
||||
responseType: 'arraybuffer',
|
||||
transformData(data) {
|
||||
return (data as DeviceEntity[]).map((de: DeviceEntity) => ({
|
||||
@@ -85,6 +85,8 @@ export const writeCustomizationEntities = (data: {
|
||||
id: number;
|
||||
entity_ids: string[];
|
||||
}) => alovaInstance.Post('/rest/customizationEntities', data);
|
||||
export const writeDeviceName = (data: { id: number; name: string }) =>
|
||||
alovaInstance.Post('/rest/writeDeviceName', data);
|
||||
|
||||
// SettingsScheduler
|
||||
export const readSchedule = () =>
|
||||
|
||||
@@ -113,7 +113,8 @@ export interface DeviceShort {
|
||||
p?: number; // productid
|
||||
s: string; // shortname
|
||||
t?: number; // device type id
|
||||
tn?: string; // device type internal name
|
||||
tn?: string; // device type internal name (translated)
|
||||
url?: string; // lowercase type name used in API URL
|
||||
}
|
||||
|
||||
export interface Devices {
|
||||
|
||||
@@ -1861,15 +1861,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/eslint-plugin@npm:7.14.1":
|
||||
version: 7.14.1
|
||||
resolution: "@typescript-eslint/eslint-plugin@npm:7.14.1"
|
||||
"@typescript-eslint/eslint-plugin@npm:7.15.0":
|
||||
version: 7.15.0
|
||||
resolution: "@typescript-eslint/eslint-plugin@npm:7.15.0"
|
||||
dependencies:
|
||||
"@eslint-community/regexpp": "npm:^4.10.0"
|
||||
"@typescript-eslint/scope-manager": "npm:7.14.1"
|
||||
"@typescript-eslint/type-utils": "npm:7.14.1"
|
||||
"@typescript-eslint/utils": "npm:7.14.1"
|
||||
"@typescript-eslint/visitor-keys": "npm:7.14.1"
|
||||
"@typescript-eslint/scope-manager": "npm:7.15.0"
|
||||
"@typescript-eslint/type-utils": "npm:7.15.0"
|
||||
"@typescript-eslint/utils": "npm:7.15.0"
|
||||
"@typescript-eslint/visitor-keys": "npm:7.15.0"
|
||||
graphemer: "npm:^1.4.0"
|
||||
ignore: "npm:^5.3.1"
|
||||
natural-compare: "npm:^1.4.0"
|
||||
@@ -1880,44 +1880,44 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 10c0/7c2b9b98a38d78326b0ff7348fe001203eda10817ca7834a7a01f492ae7c2508469bbafaa933208d6459f8ff6685277685983cf6f6843e556a6ab2aa5c05080c
|
||||
checksum: 10c0/7ed4ef8355cb60f02ed603673ef749928a001931c534960d1f3f9f9b8092f4abd7ec1e80a33b4c38efb6e8e66c902583bd56a4c4d6ccbd870677a40680a7d1f5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/parser@npm:7.14.1":
|
||||
version: 7.14.1
|
||||
resolution: "@typescript-eslint/parser@npm:7.14.1"
|
||||
"@typescript-eslint/parser@npm:7.15.0":
|
||||
version: 7.15.0
|
||||
resolution: "@typescript-eslint/parser@npm:7.15.0"
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager": "npm:7.14.1"
|
||||
"@typescript-eslint/types": "npm:7.14.1"
|
||||
"@typescript-eslint/typescript-estree": "npm:7.14.1"
|
||||
"@typescript-eslint/visitor-keys": "npm:7.14.1"
|
||||
"@typescript-eslint/scope-manager": "npm:7.15.0"
|
||||
"@typescript-eslint/types": "npm:7.15.0"
|
||||
"@typescript-eslint/typescript-estree": "npm:7.15.0"
|
||||
"@typescript-eslint/visitor-keys": "npm:7.15.0"
|
||||
debug: "npm:^4.3.4"
|
||||
peerDependencies:
|
||||
eslint: ^8.56.0
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 10c0/db3169d4852685cfb27db741c557f58a3e52104bfacc7621beb7c94ec36ac2a08d4e410ac86745db52f482fbfc87e99fa0a26c1d7a10d37a215cce85e1661f0e
|
||||
checksum: 10c0/8dcad9b84e2cbf89afea97ee7f690f91b487eed21d01997126f98cb7dd56d3b6c98c7ecbdbeda35904af521c4ed746c47887e908f8a1e2148d47c05b491d7b9d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/scope-manager@npm:7.14.1":
|
||||
version: 7.14.1
|
||||
resolution: "@typescript-eslint/scope-manager@npm:7.14.1"
|
||||
"@typescript-eslint/scope-manager@npm:7.15.0":
|
||||
version: 7.15.0
|
||||
resolution: "@typescript-eslint/scope-manager@npm:7.15.0"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": "npm:7.14.1"
|
||||
"@typescript-eslint/visitor-keys": "npm:7.14.1"
|
||||
checksum: 10c0/f8c05a0d6f8de4cc19b90a4da308817c66e53f36f7ec48f6cc23e93c7399bc418643d8135933aaf5fc013199cbef0e1ea4223f5147db5ca401b239eaf087011e
|
||||
"@typescript-eslint/types": "npm:7.15.0"
|
||||
"@typescript-eslint/visitor-keys": "npm:7.15.0"
|
||||
checksum: 10c0/781ec31a07ab7f0bdfb07dd271ef6553aa98f8492f1b3a67c65d178c94d590f4fd2e0916450f2446f1da2fbe007f3454c360ccb25f4d69612f782eb499f400ab
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/type-utils@npm:7.14.1":
|
||||
version: 7.14.1
|
||||
resolution: "@typescript-eslint/type-utils@npm:7.14.1"
|
||||
"@typescript-eslint/type-utils@npm:7.15.0":
|
||||
version: 7.15.0
|
||||
resolution: "@typescript-eslint/type-utils@npm:7.15.0"
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree": "npm:7.14.1"
|
||||
"@typescript-eslint/utils": "npm:7.14.1"
|
||||
"@typescript-eslint/typescript-estree": "npm:7.15.0"
|
||||
"@typescript-eslint/utils": "npm:7.15.0"
|
||||
debug: "npm:^4.3.4"
|
||||
ts-api-utils: "npm:^1.3.0"
|
||||
peerDependencies:
|
||||
@@ -1925,23 +1925,23 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 10c0/bd1c4a8db6273e24156fb10da2cbeb52b4eb03f819da193d4b6bd5a95db3b5524c6fe00d088308d8855b9ae60a3b82afa3a06e89982a09a8573561da960758fd
|
||||
checksum: 10c0/06189eb05d741f05977bbc029c6ac46edd566e0136f2f2c22429fd5f2be1224e2d9135b7021bc686871bfaec9c05a5c9990a321762d3abd06e457486956326ba
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/types@npm:7.14.1":
|
||||
version: 7.14.1
|
||||
resolution: "@typescript-eslint/types@npm:7.14.1"
|
||||
checksum: 10c0/5b7bda83c47a9b386482e63447c6b0ed7bd4e82eb43f11a180c6e2f3d2e7a2828f57bcbed82196ad761c49e363cccf4c81a89f1fc976e9f5f0a79dcc928fa2d2
|
||||
"@typescript-eslint/types@npm:7.15.0":
|
||||
version: 7.15.0
|
||||
resolution: "@typescript-eslint/types@npm:7.15.0"
|
||||
checksum: 10c0/935387b21d9fdff65de86f6350cdda1f0614e269324f3a4f0a2ca1b0d72ef4b1d40c7de2f3a20a6f8c83edca6507bfbac3168c860625859e59fc455c80392bed
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/typescript-estree@npm:7.14.1":
|
||||
version: 7.14.1
|
||||
resolution: "@typescript-eslint/typescript-estree@npm:7.14.1"
|
||||
"@typescript-eslint/typescript-estree@npm:7.15.0":
|
||||
version: 7.15.0
|
||||
resolution: "@typescript-eslint/typescript-estree@npm:7.15.0"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": "npm:7.14.1"
|
||||
"@typescript-eslint/visitor-keys": "npm:7.14.1"
|
||||
"@typescript-eslint/types": "npm:7.15.0"
|
||||
"@typescript-eslint/visitor-keys": "npm:7.15.0"
|
||||
debug: "npm:^4.3.4"
|
||||
globby: "npm:^11.1.0"
|
||||
is-glob: "npm:^4.0.3"
|
||||
@@ -1951,31 +1951,31 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 10c0/a8da9bcc4de3334a225424946abd99374de05c42098455419224bc0f46bb1b66115f8bd6ae268461294b90943ed4a407bcd255c0fa60eb76ba4cdc5fc7c20855
|
||||
checksum: 10c0/0d6e61cb36c4612147ceea796c2bdbb65fca59170d9d768cff314146c5564253a058cbcb9e251722cd76c92a90c257e1210a69f8d4377c8002f211c574d18d24
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/utils@npm:7.14.1":
|
||||
version: 7.14.1
|
||||
resolution: "@typescript-eslint/utils@npm:7.14.1"
|
||||
"@typescript-eslint/utils@npm:7.15.0":
|
||||
version: 7.15.0
|
||||
resolution: "@typescript-eslint/utils@npm:7.15.0"
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils": "npm:^4.4.0"
|
||||
"@typescript-eslint/scope-manager": "npm:7.14.1"
|
||||
"@typescript-eslint/types": "npm:7.14.1"
|
||||
"@typescript-eslint/typescript-estree": "npm:7.14.1"
|
||||
"@typescript-eslint/scope-manager": "npm:7.15.0"
|
||||
"@typescript-eslint/types": "npm:7.15.0"
|
||||
"@typescript-eslint/typescript-estree": "npm:7.15.0"
|
||||
peerDependencies:
|
||||
eslint: ^8.56.0
|
||||
checksum: 10c0/c7f635a3c2c6c085e1d51a52088e55cad9d7e1257b1f60378e5eeb6eb0871db027d42747e9ef60a2f557cf9dd68b2ce014d488d795db8f771506290b164b0e5a
|
||||
checksum: 10c0/26aced17976cee0aa39a79201f68b384bbce1dc96e1c70d0e5f790e1e5655b1b1ddb2afd9eaf3fce9a48c0fb69daecd37a99fdbcdbf1cb58c65ae89ecac88a2c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/visitor-keys@npm:7.14.1":
|
||||
version: 7.14.1
|
||||
resolution: "@typescript-eslint/visitor-keys@npm:7.14.1"
|
||||
"@typescript-eslint/visitor-keys@npm:7.15.0":
|
||||
version: 7.15.0
|
||||
resolution: "@typescript-eslint/visitor-keys@npm:7.15.0"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": "npm:7.14.1"
|
||||
"@typescript-eslint/types": "npm:7.15.0"
|
||||
eslint-visitor-keys: "npm:^3.4.3"
|
||||
checksum: 10c0/39ac489990fcfdcee442f27658431a0eb44ccf694f701a45df2a108c47cea9582e0955bff0d449047549149385f72895a5d7e6c1622ece1fe32594b7cecb85f3
|
||||
checksum: 10c0/7509f01c8cd2126a38213bc735a77aa7e976340af0d664be5b2ccd01b8211724b2ea129e33bfd32fe5feac848b7b68ca55bb533f6ccfeec1d2f26a91240489b9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -2010,7 +2010,7 @@ __metadata:
|
||||
jwt-decode: "npm:^4.0.0"
|
||||
lodash-es: "npm:^4.17.21"
|
||||
mime-types: "npm:^2.1.35"
|
||||
preact: "npm:^10.22.0"
|
||||
preact: "npm:^10.22.1"
|
||||
prettier: "npm:^3.3.2"
|
||||
react: "npm:latest"
|
||||
react-dom: "npm:latest"
|
||||
@@ -2021,9 +2021,9 @@ __metadata:
|
||||
rollup-plugin-visualizer: "npm:^5.12.0"
|
||||
terser: "npm:^5.31.1"
|
||||
typesafe-i18n: "npm:^5.26.2"
|
||||
typescript: "npm:^5.5.2"
|
||||
typescript-eslint: "npm:^7.14.1"
|
||||
vite: "npm:^5.3.2"
|
||||
typescript: "npm:^5.5.3"
|
||||
typescript-eslint: "npm:^7.15.0"
|
||||
vite: "npm:^5.3.3"
|
||||
vite-plugin-imagemin: "npm:^0.6.1"
|
||||
vite-tsconfig-paths: "npm:^4.3.2"
|
||||
languageName: unknown
|
||||
@@ -5879,6 +5879,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"picocolors@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "picocolors@npm:1.0.1"
|
||||
checksum: 10c0/c63cdad2bf812ef0d66c8db29583802355d4ca67b9285d846f390cc15c2f6ccb94e8cb7eb6a6e97fc5990a6d3ad4ae42d86c84d3146e667c739a4234ed50d400
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"picomatch@npm:^2.2.2, picomatch@npm:^2.3.1":
|
||||
version: 2.3.1
|
||||
resolution: "picomatch@npm:2.3.1"
|
||||
@@ -5936,21 +5943,21 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"postcss@npm:^8.4.38":
|
||||
version: 8.4.38
|
||||
resolution: "postcss@npm:8.4.38"
|
||||
"postcss@npm:^8.4.39":
|
||||
version: 8.4.39
|
||||
resolution: "postcss@npm:8.4.39"
|
||||
dependencies:
|
||||
nanoid: "npm:^3.3.7"
|
||||
picocolors: "npm:^1.0.0"
|
||||
picocolors: "npm:^1.0.1"
|
||||
source-map-js: "npm:^1.2.0"
|
||||
checksum: 10c0/955407b8f70cf0c14acf35dab3615899a2a60a26718a63c848cf3c29f2467b0533991b985a2b994430d890bd7ec2b1963e36352b0774a19143b5f591540f7c06
|
||||
checksum: 10c0/16f5ac3c4e32ee76d1582b3c0dcf1a1fdb91334a45ad755eeb881ccc50318fb8d64047de4f1601ac96e30061df203f0f2e2edbdc0bfc49b9c57bc9fb9bedaea3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"preact@npm:^10.22.0":
|
||||
version: 10.22.0
|
||||
resolution: "preact@npm:10.22.0"
|
||||
checksum: 10c0/dc5466c5968c56997e917580c00983cec2f6486a89ea9ba29f1bb88dcfd2f9ff67c8d561a69a1b3acdab17f2bb36b311fef0c348b62e89c332d00c674f7871f0
|
||||
"preact@npm:^10.22.1":
|
||||
version: 10.22.1
|
||||
resolution: "preact@npm:10.22.1"
|
||||
checksum: 10c0/9163b97d6fc0ce6b945ed77695d00c4fa07e317d0723e7b9d10c748153d30596abab8b26861ae45591e47bff25515da91406ce7f1c9e66cd9cac7e7f6c927930
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -7160,39 +7167,39 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript-eslint@npm:^7.14.1":
|
||||
version: 7.14.1
|
||||
resolution: "typescript-eslint@npm:7.14.1"
|
||||
"typescript-eslint@npm:^7.15.0":
|
||||
version: 7.15.0
|
||||
resolution: "typescript-eslint@npm:7.15.0"
|
||||
dependencies:
|
||||
"@typescript-eslint/eslint-plugin": "npm:7.14.1"
|
||||
"@typescript-eslint/parser": "npm:7.14.1"
|
||||
"@typescript-eslint/utils": "npm:7.14.1"
|
||||
"@typescript-eslint/eslint-plugin": "npm:7.15.0"
|
||||
"@typescript-eslint/parser": "npm:7.15.0"
|
||||
"@typescript-eslint/utils": "npm:7.15.0"
|
||||
peerDependencies:
|
||||
eslint: ^8.56.0
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 10c0/93439aa50a814a2d7e117c7d9b54982292986e3c090950961d13dcb07b804ae31e43300e094fd5d27d1208c1647ebbb95fda4bc89163b1c0b2e36e8a777a6800
|
||||
checksum: 10c0/98293831f7557831b80143b0e717d2a61dca289d637ef464da524880fab2ea62fb61dd952707c571719914c1565942504db2b4ccfe7178a48971e69f270c1abc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@npm:^5.5.2":
|
||||
version: 5.5.2
|
||||
resolution: "typescript@npm:5.5.2"
|
||||
"typescript@npm:^5.5.3":
|
||||
version: 5.5.3
|
||||
resolution: "typescript@npm:5.5.3"
|
||||
bin:
|
||||
tsc: bin/tsc
|
||||
tsserver: bin/tsserver
|
||||
checksum: 10c0/8ca39b27b5f9bd7f32db795045933ab5247897660627251e8254180b792a395bf061ea7231947d5d7ffa5cb4cc771970fd4ef543275f9b559f08c9325cccfce3
|
||||
checksum: 10c0/f52c71ccbc7080b034b9d3b72051d563601a4815bf3e39ded188e6ce60813f75dbedf11ad15dd4d32a12996a9ed8c7155b46c93a9b9c9bad1049766fe614bbdd
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@patch:typescript@npm%3A^5.5.2#optional!builtin<compat/typescript>":
|
||||
version: 5.5.2
|
||||
resolution: "typescript@patch:typescript@npm%3A5.5.2#optional!builtin<compat/typescript>::version=5.5.2&hash=b45daf"
|
||||
"typescript@patch:typescript@npm%3A^5.5.3#optional!builtin<compat/typescript>":
|
||||
version: 5.5.3
|
||||
resolution: "typescript@patch:typescript@npm%3A5.5.3#optional!builtin<compat/typescript>::version=5.5.3&hash=b45daf"
|
||||
bin:
|
||||
tsc: bin/tsc
|
||||
tsserver: bin/tsserver
|
||||
checksum: 10c0/6721ac8933a70c252d7b640b345792e103d881811ff660355617c1836526dbb71c2044e2e77a8823fb3570b469f33276875a4cab6d3c4de4ae7d7ee1c3074ae4
|
||||
checksum: 10c0/5a437c416251334deeaf29897157032311f3f126547cfdc4b133768b606cb0e62bcee733bb97cf74c42fe7268801aea1392d8e40988cdef112e9546eba4c03c5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -7361,13 +7368,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"vite@npm:^5.3.2":
|
||||
version: 5.3.2
|
||||
resolution: "vite@npm:5.3.2"
|
||||
"vite@npm:^5.3.3":
|
||||
version: 5.3.3
|
||||
resolution: "vite@npm:5.3.3"
|
||||
dependencies:
|
||||
esbuild: "npm:^0.21.3"
|
||||
fsevents: "npm:~2.3.3"
|
||||
postcss: "npm:^8.4.38"
|
||||
postcss: "npm:^8.4.39"
|
||||
rollup: "npm:^4.13.0"
|
||||
peerDependencies:
|
||||
"@types/node": ^18.0.0 || >=20.0.0
|
||||
@@ -7397,7 +7404,7 @@ __metadata:
|
||||
optional: true
|
||||
bin:
|
||||
vite: bin/vite.js
|
||||
checksum: 10c0/3ed576d18c6c008ae92be68f9c79bf7556dae10978a3e8b4c4b42199424755e5c99836e6d4f81fb8b533b957d7f4e351abc60b8a93f4c4b5eb9890b5b6450926
|
||||
checksum: 10c0/a796872e1d11875d994615cd00da185c80eeb7753034d35c096050bf3c269c02004070cf623c5fe2a4a90ea2f12488e6f9d13933ec810f117f1b931e1b5e3385
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
@@ -4076,7 +4076,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) {
|
||||
}
|
||||
@@ -5143,7 +5143,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) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -38,6 +38,7 @@ unbuild_flags =
|
||||
${common.core_unbuild_flags}
|
||||
|
||||
[espressi32_base]
|
||||
; 6.7.0 = Arduino v2.0.16 (based on IDF v4.4.7). See https://github.com/platformio/platform-espressif32/releases/tag/v6.7.0
|
||||
platform = espressif32@6.7.0
|
||||
framework = arduino
|
||||
board_build.filesystem = littlefs
|
||||
@@ -51,7 +52,9 @@ extra_scripts =
|
||||
[espressi32_base_tasmota]
|
||||
; use Tasmota's library which removes some unused libs (like mbedtsl, so no WiFi_secure.h) and increases available heap
|
||||
; Tasmota Arduino Core 2.0.17 with IPv6 support, based on IDF 4.4.7
|
||||
platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.05.00/platform-espressif32.zip
|
||||
; platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.05.00/platform-espressif32.zip
|
||||
; Tasmota Arduino Core 2.0.18 with IPv6 support, based on IDF 4.4.8
|
||||
platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.06.00/platform-espressif32.zip
|
||||
; Tasmota Arduino Core 3.0.1.240605 based on IDF v5.1.4.240602
|
||||
; platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.06.10/platform-espressif32.zip
|
||||
framework = arduino
|
||||
|
||||
@@ -274,8 +274,13 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &pumpModMin_, DeviceValueType::UINT8, FL_(pumpModMin), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_min_pump));
|
||||
register_device_value(
|
||||
DeviceValueTAG::TAG_DEVICE_DATA, &pumpMode_, DeviceValueType::ENUM, FL_(enum_pumpMode), FL_(pumpMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_pumpMode));
|
||||
register_device_value(
|
||||
DeviceValueTAG::TAG_DEVICE_DATA, &pumpCharacter_, DeviceValueType::ENUM, FL_(enum_pumpCharacter), FL_(pumpCharacter), DeviceValueUOM::NONE, MAKE_CF_CB(set_pumpCharacter));
|
||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||
&pumpCharacter_,
|
||||
DeviceValueType::ENUM,
|
||||
FL_(enum_pumpCharacter),
|
||||
FL_(pumpCharacter),
|
||||
DeviceValueUOM::NONE,
|
||||
MAKE_CF_CB(set_pumpCharacter));
|
||||
register_device_value(
|
||||
DeviceValueTAG::TAG_DEVICE_DATA, &pumpDelay_, DeviceValueType::UINT8, FL_(pumpDelay), DeviceValueUOM::MINUTES, MAKE_CF_CB(set_pump_delay), 0, 60);
|
||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &setFlowTemp_, DeviceValueType::UINT8, FL_(setFlowTemp), DeviceValueUOM::DEGREES);
|
||||
|
||||
@@ -292,14 +292,14 @@ uint8_t EMSdevice::decode_brand(uint8_t value) {
|
||||
const std::string EMSdevice::to_string() {
|
||||
// for devices that haven't been lookup yet, don't show all details
|
||||
if (product_id_ == 0) {
|
||||
return std::string(name_) + " (DeviceID:" + Helpers::hextoa(device_id_) + ")";
|
||||
return std::string(name()) + " (DeviceID:" + Helpers::hextoa(device_id_) + ")";
|
||||
}
|
||||
|
||||
if (brand_ == Brand::NO_BRAND) {
|
||||
return std::string(name_) + " (DeviceID:" + Helpers::hextoa(device_id_) + ", ProductID:" + Helpers::itoa(product_id_) + ", Version:" + version_ + ")";
|
||||
return std::string(name()) + " (DeviceID:" + Helpers::hextoa(device_id_) + ", ProductID:" + Helpers::itoa(product_id_) + ", Version:" + version_ + ")";
|
||||
}
|
||||
|
||||
return std::string(brand_to_char()) + " " + name_ + " (DeviceID:" + Helpers::hextoa(device_id_) + ", ProductID:" + Helpers::itoa(product_id_)
|
||||
return std::string(brand_to_char()) + " " + name() + " (DeviceID:" + Helpers::hextoa(device_id_) + ", ProductID:" + Helpers::itoa(product_id_)
|
||||
+ ", Version:" + version_ + ")";
|
||||
}
|
||||
|
||||
@@ -307,10 +307,10 @@ const std::string EMSdevice::to_string() {
|
||||
// translated
|
||||
const std::string EMSdevice::to_string_short() {
|
||||
if (brand_ == Brand::NO_BRAND) {
|
||||
return std::string(device_type_2_device_name_translated()) + ": " + name_;
|
||||
return std::string(device_type_2_device_name_translated()) + ": " + name();
|
||||
}
|
||||
|
||||
return std::string(device_type_2_device_name_translated()) + ": " + brand_to_char() + " " + name_;
|
||||
return std::string(device_type_2_device_name_translated()) + ": " + brand_to_char() + " " + name();
|
||||
}
|
||||
|
||||
// for each telegram that has the fetch value set (true) do a read request
|
||||
@@ -1176,7 +1176,7 @@ void EMSdevice::setCustomizationEntity(const std::string & entity_id) {
|
||||
}
|
||||
}
|
||||
|
||||
// populate a string vector with entities that have masks set or have a custom name
|
||||
// populate a string vector with entities that have masks set or have a custom entity name
|
||||
void EMSdevice::getCustomizationEntities(std::vector<std::string> & entity_ids) {
|
||||
for (const auto & dv : devicevalues_) {
|
||||
char name[100];
|
||||
@@ -1215,7 +1215,7 @@ void EMSdevice::getCustomizationEntities(std::vector<std::string> & entity_ids)
|
||||
void EMSdevice::dump_value_info() {
|
||||
for (auto & dv : devicevalues_) {
|
||||
if (dv.fullname != nullptr) {
|
||||
Serial.print(name_);
|
||||
Serial.print(default_name());
|
||||
Serial.print(',');
|
||||
Serial.print(device_type_name());
|
||||
Serial.print(',');
|
||||
@@ -1782,7 +1782,7 @@ void EMSdevice::mqtt_ha_entity_config_create() {
|
||||
if (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) && dv.has_state(DeviceValueState::DV_ACTIVE)
|
||||
&& !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE)) {
|
||||
// create_device_config is only done once for the EMS device. It can added to any entity, so we take the first
|
||||
if (Mqtt::publish_ha_sensor_config(dv, name(), brand_to_char(), false, create_device_config)) {
|
||||
if (Mqtt::publish_ha_sensor_config(dv, name().c_str(), brand_to_char(), false, create_device_config)) {
|
||||
dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
||||
create_device_config = false; // only create the main config once
|
||||
count++;
|
||||
@@ -1893,4 +1893,12 @@ void EMSdevice::read_command(const uint16_t type_id, const uint8_t offset, const
|
||||
EMSESP::send_read_request(type_id, device_id(), offset, length);
|
||||
}
|
||||
|
||||
// returns either default or custom name
|
||||
std::string EMSdevice::name() {
|
||||
if (custom_name_.empty()) {
|
||||
return default_name_;
|
||||
}
|
||||
return custom_name_;
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -34,14 +34,15 @@ class EMSdevice {
|
||||
using process_function_p = std::function<void(std::shared_ptr<const Telegram>)>;
|
||||
|
||||
// device_type defines which derived class to use, e.g. BOILER, THERMOSTAT etc..
|
||||
EMSdevice(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
||||
EMSdevice(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * default_name, uint8_t flags, uint8_t brand)
|
||||
: device_type_(device_type)
|
||||
, device_id_(device_id)
|
||||
, product_id_(product_id)
|
||||
, name_(name)
|
||||
, default_name_(default_name)
|
||||
, flags_(flags)
|
||||
, brand_(brand) {
|
||||
strlcpy(version_, version, sizeof(version_));
|
||||
custom_name_ = ""; // init custom name to blank
|
||||
}
|
||||
|
||||
// static functions, used outside the class like in console.cpp, command.cpp, emsesp.cpp, mqtt.cpp
|
||||
@@ -111,12 +112,18 @@ class EMSdevice {
|
||||
return brand_;
|
||||
}
|
||||
|
||||
inline void name(const char * name) {
|
||||
name_ = name;
|
||||
// set custom device name
|
||||
inline void custom_name(std::string & custom_name) {
|
||||
custom_name_ = custom_name;
|
||||
}
|
||||
std::string name(); // returns either default or custom name if defined
|
||||
|
||||
inline const char * name() const {
|
||||
return name_;
|
||||
// default name
|
||||
inline void default_name(const char * default_name) {
|
||||
default_name_ = default_name;
|
||||
}
|
||||
inline const char * default_name() const {
|
||||
return default_name_;
|
||||
}
|
||||
|
||||
inline uint8_t unique_id() const {
|
||||
@@ -479,7 +486,8 @@ class EMSdevice {
|
||||
uint8_t device_id_ = 0;
|
||||
uint8_t product_id_ = 0;
|
||||
char version_[6];
|
||||
const char * name_; // the long name for the EMS model
|
||||
const char * default_name_; // the fixed name the EMS model taken from the device library
|
||||
std::string custom_name_; // custom name
|
||||
uint8_t flags_ = 0;
|
||||
uint8_t brand_ = Brand::NO_BRAND;
|
||||
|
||||
|
||||
106
src/emsesp.cpp
106
src/emsesp.cpp
@@ -359,7 +359,7 @@ void EMSESP::dump_all_values(uuid::console::Shell & shell) {
|
||||
// add the device and print out all the entities
|
||||
// for testing the mixer use ... if (device.product_id == 69) {
|
||||
emsdevices.push_back(
|
||||
EMSFactory::add(device.device_type, device_id, device.product_id, "1.0", device.name, device.flags, EMSdevice::Brand::NO_BRAND));
|
||||
EMSFactory::add(device.device_type, device_id, device.product_id, "1.0", device.default_name, device.flags, EMSdevice::Brand::NO_BRAND));
|
||||
emsdevices.back()->dump_value_info();
|
||||
}
|
||||
}
|
||||
@@ -400,7 +400,7 @@ void EMSESP::dump_all_telegrams(uuid::console::Shell & shell) {
|
||||
|
||||
// add the device and print out all the entities
|
||||
emsdevices.push_back(
|
||||
EMSFactory::add(device.device_type, device_id, device.product_id, "1.0", device.name, device.flags, EMSdevice::Brand::NO_BRAND));
|
||||
EMSFactory::add(device.device_type, device_id, device.product_id, "1.0", device.default_name, device.flags, EMSdevice::Brand::NO_BRAND));
|
||||
// add to our vector list
|
||||
emsdevices.back()->dump_telegram_info(telegram_functions_dump);
|
||||
}
|
||||
@@ -1167,17 +1167,20 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
||||
if (product_id == 0 || emsdevice->product_id() != 0) { // update only with valid product_id
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG_DEBUG("Updating details for already active deviceID 0x%02X", device_id);
|
||||
emsdevice->product_id(product_id);
|
||||
emsdevice->version(version);
|
||||
|
||||
// only set brand if it doesn't already exist
|
||||
if (emsdevice->brand() == EMSdevice::Brand::NO_BRAND) {
|
||||
emsdevice->brand(brand);
|
||||
}
|
||||
// find the name and flags in our database
|
||||
|
||||
// find the name and flags in our device library database
|
||||
for (const auto & device : device_library_) {
|
||||
if (device.product_id == product_id && device.device_type == emsdevice->device_type()) {
|
||||
emsdevice->name(device.name);
|
||||
emsdevice->default_name(device.default_name); // custom name is set later
|
||||
emsdevice->add_flags(device.flags);
|
||||
}
|
||||
}
|
||||
@@ -1192,7 +1195,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
||||
if (device.product_id == product_id) {
|
||||
// sometimes boilers share the same productID as controllers
|
||||
// so only add boilers if the device_id is 0x08
|
||||
// cascaded boilers with 0x70.., map to heatsources
|
||||
// cascaded boilers with 0x70..., map to heatsources
|
||||
if (device.device_type == DeviceType::BOILER) {
|
||||
if (device_id == EMSdevice::EMS_DEVICE_ID_BOILER) {
|
||||
device_p = &device;
|
||||
@@ -1204,7 +1207,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// it's not a boiler, but we have a match
|
||||
// it's not a boiler, but we still have a match
|
||||
device_p = &device;
|
||||
break;
|
||||
}
|
||||
@@ -1219,84 +1222,99 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
||||
return false; // not found
|
||||
}
|
||||
|
||||
auto name = device_p->name;
|
||||
auto device_type = device_p->device_type;
|
||||
auto flags = device_p->flags;
|
||||
auto default_name = device_p->default_name;
|
||||
auto device_type = device_p->device_type;
|
||||
auto flags = device_p->flags;
|
||||
|
||||
// check for integrated modules with same product id, but different function (device_id)
|
||||
// and force set the correct device type and hardcoded name
|
||||
if (device_type == DeviceType::HEATPUMP) {
|
||||
if (device_id == EMSdevice::EMS_DEVICE_ID_MODEM) {
|
||||
device_type = DeviceType::GATEWAY;
|
||||
name = "WiFi module";
|
||||
device_type = DeviceType::GATEWAY;
|
||||
default_name = "WiFi module";
|
||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_RFBASE) {
|
||||
device_type = DeviceType::CONNECT;
|
||||
name = "Wireless sensor base";
|
||||
device_type = DeviceType::CONNECT;
|
||||
default_name = "Wireless sensor base";
|
||||
}
|
||||
}
|
||||
|
||||
if (device_id >= EMSdevice::EMS_DEVICE_ID_DHW1 && device_id <= EMSdevice::EMS_DEVICE_ID_DHW8) {
|
||||
device_type = DeviceType::WATER;
|
||||
}
|
||||
|
||||
// CR120 have version 22.xx, RC400/CW100 uses version 42.xx, see https://github.com/emsesp/EMS-ESP32/discussions/1779
|
||||
if (product_id == 157 && version[0] == '2') {
|
||||
flags = DeviceFlags::EMS_DEVICE_FLAG_CR120;
|
||||
name = "CR120";
|
||||
flags = DeviceFlags::EMS_DEVICE_FLAG_CR120;
|
||||
default_name = "CR120";
|
||||
}
|
||||
|
||||
// empty reply to version, read a generic device from database
|
||||
if (product_id == 0) {
|
||||
// check for known device IDs
|
||||
if (device_id == EMSdevice::EMS_DEVICE_ID_RFSENSOR) {
|
||||
// see: https://github.com/emsesp/EMS-ESP32/issues/103#issuecomment-911717342 and https://github.com/emsesp/EMS-ESP32/issues/624
|
||||
name = "RF room temperature sensor";
|
||||
device_type = DeviceType::THERMOSTAT;
|
||||
default_name = "RF room temperature sensor";
|
||||
device_type = DeviceType::THERMOSTAT;
|
||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_ROOMTHERMOSTAT || device_id == EMSdevice::EMS_DEVICE_ID_TADO_OLD) {
|
||||
// see https://github.com/emsesp/EMS-ESP32/issues/174
|
||||
name = "Generic thermostat";
|
||||
device_type = DeviceType::THERMOSTAT;
|
||||
flags = DeviceFlags::EMS_DEVICE_FLAG_RC10 | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE;
|
||||
default_name = "Generic Thermostat";
|
||||
device_type = DeviceType::THERMOSTAT;
|
||||
flags = DeviceFlags::EMS_DEVICE_FLAG_RC10 | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE;
|
||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_RS232) {
|
||||
name = "RS232";
|
||||
device_type = DeviceType::CONNECT;
|
||||
default_name = "RS232";
|
||||
device_type = DeviceType::CONNECT;
|
||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_TERMINAL) {
|
||||
name = "Terminal";
|
||||
device_type = DeviceType::CONNECT;
|
||||
default_name = "Terminal";
|
||||
device_type = DeviceType::CONNECT;
|
||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_SERVICEKEY) {
|
||||
name = "Service Key";
|
||||
device_type = DeviceType::CONNECT;
|
||||
default_name = "Service Key";
|
||||
device_type = DeviceType::CONNECT;
|
||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_CASCADE) {
|
||||
name = "Cascade";
|
||||
device_type = DeviceType::CONNECT;
|
||||
default_name = "Cascade";
|
||||
device_type = DeviceType::CONNECT;
|
||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_EASYCOM
|
||||
|| (device_id >= EMSdevice::EMS_DEVICE_ID_MODEM && device_id <= EMSdevice::EMS_DEVICE_ID_MODEM + 5)) {
|
||||
// see https://github.com/emsesp/EMS-ESP/issues/460#issuecomment-709553012
|
||||
name = "Modem";
|
||||
device_type = DeviceType::CONNECT;
|
||||
default_name = "Modem";
|
||||
device_type = DeviceType::CONNECT;
|
||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_CONVERTER) {
|
||||
name = "Converter"; // generic
|
||||
default_name = "Converter"; // generic
|
||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_CLOCK) {
|
||||
name = "Clock"; // generic
|
||||
device_type = DeviceType::CONTROLLER;
|
||||
default_name = "Clock"; // generic
|
||||
device_type = DeviceType::CONTROLLER;
|
||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_CONTROLLER) {
|
||||
name = "Generic Controller";
|
||||
device_type = DeviceType::CONTROLLER;
|
||||
default_name = "Generic Controller";
|
||||
device_type = DeviceType::CONTROLLER;
|
||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_BOILER) {
|
||||
name = "Generic Boiler";
|
||||
device_type = DeviceType::BOILER;
|
||||
flags = DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP;
|
||||
default_name = "Generic Boiler";
|
||||
device_type = DeviceType::BOILER;
|
||||
flags = DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP;
|
||||
LOG_WARNING("Unknown EMS boiler. Using generic profile. Please report on GitHub.");
|
||||
} else if (device_id >= 0x68 && device_id <= 0x6F) {
|
||||
// test for https://github.com/emsesp/EMS-ESP32/issues/882
|
||||
name = "Cascaded Controller";
|
||||
device_type = DeviceType::CONTROLLER;
|
||||
default_name = "Cascaded Controller";
|
||||
device_type = DeviceType::CONTROLLER;
|
||||
} else {
|
||||
LOG_WARNING("Unrecognized EMS device (device ID 0x%02X, no product ID). Please report on GitHub.", device_id);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG("Adding new device %s (deviceID 0x%02X, productID %d, version %s)", name, device_id, product_id, version);
|
||||
emsdevices.push_back(EMSFactory::add(device_type, device_id, product_id, version, name, flags, brand));
|
||||
LOG_DEBUG("Adding new device %s (deviceID 0x%02X, productID %d, version %s)", default_name, device_id, product_id, version);
|
||||
emsdevices.push_back(EMSFactory::add(device_type, device_id, product_id, version, default_name, flags, brand));
|
||||
|
||||
// assign a unique ID. Note that this is not actual unique after a restart as it's dependent on the order that devices are found
|
||||
// see if we have a custom device name in our Customizations list, and if so set it
|
||||
webCustomizationService.read([&](WebCustomization & settings) {
|
||||
for (EntityCustomization e : settings.entityCustomizations) {
|
||||
if ((e.device_id == device_id) && (e.product_id == product_id)) {
|
||||
LOG_DEBUG("Have customizations for %s with deviceID 0x%02X productID %d", e.custom_name.c_str(), device_id, product_id);
|
||||
emsdevices.back()->custom_name(e.custom_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// assign a unique ID. Note that this is not actual remain unique after a restart as it's dependent on the order that devices are found
|
||||
// can't be 0 otherwise web won't work
|
||||
emsdevices.back()->unique_id(++unique_id_count_);
|
||||
|
||||
@@ -1305,7 +1323,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
||||
return a->device_type() < b->device_type();
|
||||
});
|
||||
|
||||
fetch_device_values(device_id); // go and fetch its data
|
||||
fetch_device_values(device_id); // go and fetch its device entity data
|
||||
|
||||
// Print to LOG showing we've added a new device
|
||||
LOG_INFO("Recognized new %s with deviceID 0x%02X", EMSdevice::device_type_2_device_name(device_type), device_id);
|
||||
|
||||
@@ -252,7 +252,7 @@ class EMSESP {
|
||||
struct Device_record {
|
||||
uint8_t product_id;
|
||||
EMSdevice::DeviceType device_type;
|
||||
const char * name;
|
||||
const char * default_name;
|
||||
uint8_t flags;
|
||||
};
|
||||
static std::vector<Device_record> device_library_;
|
||||
|
||||
@@ -55,9 +55,9 @@ class EMSFactory {
|
||||
}
|
||||
|
||||
// Construct derived class returning an unique ptr
|
||||
static auto add(const uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
||||
static auto add(const uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * default_name, uint8_t flags, uint8_t brand)
|
||||
-> std::unique_ptr<EMSdevice> {
|
||||
return std::unique_ptr<EMSdevice>(EMSFactory::makeRaw(device_type, device_id, product_id, version, name, flags, brand));
|
||||
return std::unique_ptr<EMSdevice>(EMSFactory::makeRaw(device_type, device_id, product_id, version, default_name, flags, brand));
|
||||
}
|
||||
|
||||
virtual auto construct(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand) const
|
||||
|
||||
@@ -1102,6 +1102,7 @@ bool System::check_restore() {
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
// see if we have a temp file, if so try and read it
|
||||
// TODO find a nicer way to see if a file exists without reporting an error
|
||||
File new_file = LittleFS.open(TEMP_FILENAME_PATH);
|
||||
if (new_file) {
|
||||
JsonDocument jsonDocument;
|
||||
@@ -1556,7 +1557,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject output
|
||||
if (emsdevice && (emsdevice->device_type() == device_class.first)) {
|
||||
JsonObject obj = devices.add<JsonObject>();
|
||||
obj["type"] = emsdevice->device_type_name(); // non translated name
|
||||
obj["name"] = emsdevice->name();
|
||||
obj["name"] = emsdevice->name(); // custom name
|
||||
obj["device id"] = Helpers::hextoa(emsdevice->device_id());
|
||||
obj["product id"] = emsdevice->product_id();
|
||||
obj["version"] = emsdevice->version();
|
||||
|
||||
@@ -611,8 +611,8 @@ bool TemperatureSensor::Sensor::apply_customization() {
|
||||
auto sensors = settings.sensorCustomizations;
|
||||
if (!sensors.empty()) {
|
||||
for (const auto & sensor : sensors) {
|
||||
LOG_DEBUG("Loading customization for temperature sensor %s", sensor.id.c_str());
|
||||
if (id_ == sensor.id) {
|
||||
LOG_DEBUG("Loading customization for temperature sensor %s", sensor.id.c_str());
|
||||
set_name(sensor.name);
|
||||
set_offset(sensor.offset);
|
||||
return true;
|
||||
|
||||
@@ -313,17 +313,20 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
|
||||
if (command == "general") {
|
||||
shell.printfln("Testing adding a boiler, thermostat, all sensors, scheduler and custom entities...");
|
||||
test("general");
|
||||
|
||||
// setup fake data
|
||||
EMSESP::webCustomizationService.test(); // set customizations
|
||||
EMSESP::temperaturesensor_.test(); // add temperature sensors
|
||||
EMSESP::webSchedulerService.test(); // add scheduler items
|
||||
EMSESP::webCustomEntityService.test(); // add custom entities
|
||||
EMSESP::webCustomizationService.test(); // set customizations - this will overwrite any settings in the file
|
||||
|
||||
// shell.invoke_command("show devices");
|
||||
// add devices
|
||||
test("general");
|
||||
|
||||
EMSESP::temperaturesensor_.test(); // add temperature sensors
|
||||
EMSESP::webSchedulerService.test(); // add scheduler items
|
||||
EMSESP::webCustomEntityService.test(); // add custom entities
|
||||
|
||||
shell.invoke_command("show devices");
|
||||
// shell.invoke_command("show values");
|
||||
shell.invoke_command("call system allvalues");
|
||||
// shell.invoke_command("call system allvalues");
|
||||
// shell.invoke_command("call system publish");
|
||||
// shell.invoke_command("show mqtt");
|
||||
ok = true;
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define EMSESP_APP_VERSION "3.7.0-dev.19"
|
||||
#define EMSESP_APP_VERSION "3.7.0-dev.20"
|
||||
|
||||
@@ -24,6 +24,7 @@ bool WebCustomization::_start = true;
|
||||
|
||||
WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
|
||||
: _fsPersistence(WebCustomization::read, WebCustomization::update, this, fs, EMSESP_CUSTOMIZATION_FILE) {
|
||||
// GET
|
||||
server->on(DEVICE_ENTITIES_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { device_entities(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
@@ -32,10 +33,15 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { devices(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
// POST
|
||||
server->on(RESET_CUSTOMIZATION_SERVICE_PATH,
|
||||
HTTP_POST,
|
||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { reset_customization(request); }, AuthenticationPredicates::IS_ADMIN));
|
||||
|
||||
server->on(WRITE_DEVICE_NAME_PATH,
|
||||
securityManager->wrapCallback([this](AsyncWebServerRequest * request, JsonVariant json) { writeDeviceName(request, json); },
|
||||
AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
server->on(CUSTOMIZATION_ENTITIES_PATH,
|
||||
securityManager->wrapCallback([this](AsyncWebServerRequest * request, JsonVariant json) { customization_entities(request, json); },
|
||||
AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
@@ -65,12 +71,13 @@ void WebCustomization::read(WebCustomization & customizations, JsonObject root)
|
||||
sensorJson["type"] = sensor.type; // t
|
||||
}
|
||||
|
||||
// Masked entities customization
|
||||
// Masked entities customization and custom device name (optional)
|
||||
JsonArray masked_entitiesJson = root["masked_entities"].to<JsonArray>();
|
||||
for (const EntityCustomization & entityCustomization : customizations.entityCustomizations) {
|
||||
JsonObject entityJson = masked_entitiesJson.add<JsonObject>();
|
||||
entityJson["product_id"] = entityCustomization.product_id;
|
||||
entityJson["device_id"] = entityCustomization.device_id;
|
||||
JsonObject entityJson = masked_entitiesJson.add<JsonObject>();
|
||||
entityJson["product_id"] = entityCustomization.product_id;
|
||||
entityJson["device_id"] = entityCustomization.device_id;
|
||||
entityJson["custom_name"] = entityCustomization.custom_name;
|
||||
|
||||
// entries are in the form <XX><shortname>[optional customname] e.g "08heatingactive|heating is on"
|
||||
JsonArray masked_entityJson = entityJson["entity_ids"].to<JsonArray>();
|
||||
@@ -120,9 +127,10 @@ StateUpdateResult WebCustomization::update(JsonObject root, WebCustomization & c
|
||||
customizations.entityCustomizations.clear();
|
||||
if (root["masked_entities"].is<JsonArray>()) {
|
||||
for (const JsonObject masked_entities : root["masked_entities"].as<JsonArray>()) {
|
||||
auto emsEntity = EntityCustomization();
|
||||
emsEntity.product_id = masked_entities["product_id"];
|
||||
emsEntity.device_id = masked_entities["device_id"];
|
||||
auto emsEntity = EntityCustomization();
|
||||
emsEntity.product_id = masked_entities["product_id"];
|
||||
emsEntity.device_id = masked_entities["device_id"];
|
||||
emsEntity.custom_name = masked_entities["custom_name"].as<std::string>();
|
||||
|
||||
for (const JsonVariant masked_entity_id : masked_entities["entity_ids"].as<JsonArray>()) {
|
||||
if (masked_entity_id.is<std::string>()) {
|
||||
@@ -163,10 +171,11 @@ void WebCustomizationService::devices(AsyncWebServerRequest * request) {
|
||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||
if (emsdevice->has_entities()) {
|
||||
JsonObject obj = devices.add<JsonObject>();
|
||||
obj["i"] = emsdevice->unique_id(); // its unique id
|
||||
obj["s"] = std::string(emsdevice->device_type_2_device_name_translated()) + " (" + emsdevice->name() + ")"; // shortname, is device type translated
|
||||
obj["tn"] = emsdevice->device_type_name(); // non-translated, lower-case
|
||||
obj["t"] = emsdevice->device_type(); // internal device type ID
|
||||
obj["i"] = emsdevice->unique_id(); // its unique id
|
||||
obj["s"] = emsdevice->name(); // custom name
|
||||
obj["t"] = emsdevice->device_type(); // internal device type ID
|
||||
obj["tn"] = std::string(emsdevice->device_type_2_device_name_translated()); // translated device type name
|
||||
obj["url"] = emsdevice->device_type_name(); // non-translated, lower-case, used for API URL
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,6 +220,58 @@ void WebCustomizationService::device_entities(AsyncWebServerRequest * request) {
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
// renames a device
|
||||
// takes the unique ID and the custom name
|
||||
void WebCustomizationService::writeDeviceName(AsyncWebServerRequest * request, JsonVariant json) {
|
||||
if (json.is<JsonObject>()) {
|
||||
// find the device using the unique_id
|
||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||
if (emsdevice) {
|
||||
uint8_t unique_device_id = json["id"];
|
||||
// find product id and device id using the unique id
|
||||
if (emsdevice->unique_id() == unique_device_id) {
|
||||
uint8_t product_id = emsdevice->product_id();
|
||||
uint8_t device_id = emsdevice->device_id();
|
||||
auto custom_name = json["name"].as<std::string>();
|
||||
|
||||
// emsesp::EMSESP::logger().info("Found Device ID: %d, Product ID: %d", device_id, product_id);
|
||||
|
||||
// updates current record or creates a new one
|
||||
bool entry_exists = false;
|
||||
update([&](WebCustomization & settings) {
|
||||
for (auto it = settings.entityCustomizations.begin(); it != settings.entityCustomizations.end();) {
|
||||
if ((*it).product_id == product_id && (*it).device_id == device_id) {
|
||||
(*it).custom_name = custom_name;
|
||||
entry_exists = true;
|
||||
break;
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
// if we don't have any customization for this device, create a new entry
|
||||
if (!entry_exists) {
|
||||
EntityCustomization new_entry;
|
||||
new_entry.product_id = product_id;
|
||||
new_entry.device_id = device_id;
|
||||
new_entry.custom_name = custom_name;
|
||||
settings.entityCustomizations.push_back(new_entry);
|
||||
}
|
||||
|
||||
return StateUpdateResult::CHANGED;
|
||||
});
|
||||
|
||||
// update the EMS Device record real-time
|
||||
emsdevice->custom_name(custom_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AsyncWebServerResponse * response = request->beginResponse(200);
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
// takes a list of updated entities with new masks from the web UI
|
||||
// saves it in the customization service
|
||||
// and updates the entity list real-time
|
||||
@@ -236,7 +297,6 @@ void WebCustomizationService::customization_entities(AsyncWebServerRequest * req
|
||||
} else {
|
||||
emsdevice->setCustomizationEntity(id_s);
|
||||
}
|
||||
// emsesp::EMSESP::logger().info(id.as<const char *>());
|
||||
}
|
||||
|
||||
// add deleted entities from file
|
||||
@@ -271,7 +331,7 @@ void WebCustomizationService::customization_entities(AsyncWebServerRequest * req
|
||||
|
||||
// Save the list to the customization file
|
||||
update([&](WebCustomization & settings) {
|
||||
// see if we already have a mask list for this device, if so remove it
|
||||
// see if we already have a mask list for this device, if so remove the entry
|
||||
for (auto it = settings.entityCustomizations.begin(); it != settings.entityCustomizations.end();) {
|
||||
if ((*it).product_id == product_id && (*it).device_id == device_id) {
|
||||
it = settings.entityCustomizations.erase(it);
|
||||
@@ -281,16 +341,14 @@ void WebCustomizationService::customization_entities(AsyncWebServerRequest * req
|
||||
}
|
||||
}
|
||||
|
||||
// create a new entry for this device if there are values
|
||||
// re-create a new entry
|
||||
EntityCustomization new_entry;
|
||||
new_entry.product_id = product_id;
|
||||
new_entry.device_id = device_id;
|
||||
|
||||
new_entry.entity_ids = entity_ids;
|
||||
|
||||
// add the record and save
|
||||
settings.entityCustomizations.push_back(new_entry);
|
||||
return StateUpdateResult::CHANGED;
|
||||
|
||||
return StateUpdateResult::CHANGED; // save the changes
|
||||
});
|
||||
|
||||
break;
|
||||
@@ -308,7 +366,6 @@ void WebCustomizationService::begin() {
|
||||
_fsPersistence.readFromFS();
|
||||
}
|
||||
|
||||
|
||||
// hard coded tests
|
||||
#ifdef EMSESP_TEST
|
||||
void WebCustomizationService::test() {
|
||||
@@ -321,11 +378,11 @@ void WebCustomizationService::test() {
|
||||
sensor.offset = 0;
|
||||
webCustomization.sensorCustomizations.push_back(sensor);
|
||||
|
||||
sensor = SensorCustomization();
|
||||
sensor.id = "0B-0C0D-0E0F-1011";
|
||||
sensor.name = "test_sensor2";
|
||||
sensor.offset = 4;
|
||||
webCustomization.sensorCustomizations.push_back(sensor);
|
||||
auto sensor2 = SensorCustomization();
|
||||
sensor2.id = "0B-0C0D-0E0F-1011";
|
||||
sensor2.name = "test_sensor2";
|
||||
sensor2.offset = 4;
|
||||
webCustomization.sensorCustomizations.push_back(sensor2);
|
||||
|
||||
// Analog sensors
|
||||
// This actually adds the sensors as we use customizations to store them
|
||||
@@ -350,9 +407,10 @@ void WebCustomizationService::test() {
|
||||
|
||||
// EMS entities
|
||||
webCustomization.entityCustomizations.clear();
|
||||
auto emsEntity = EntityCustomization();
|
||||
emsEntity.product_id = 123;
|
||||
emsEntity.device_id = 8;
|
||||
auto emsEntity = EntityCustomization();
|
||||
emsEntity.product_id = 123;
|
||||
emsEntity.device_id = 8;
|
||||
emsEntity.custom_name = "Custom Name!!";
|
||||
emsEntity.entity_ids.push_back("08heatingactive|is my heating on?");
|
||||
webCustomization.entityCustomizations.push_back(emsEntity);
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
// POST
|
||||
#define CUSTOMIZATION_ENTITIES_PATH "/rest/customizationEntities"
|
||||
#define RESET_CUSTOMIZATION_SERVICE_PATH "/rest/resetCustomizations"
|
||||
#define WRITE_DEVICE_NAME_PATH "/rest/writeDeviceName"
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
@@ -60,9 +61,10 @@ class AnalogCustomization {
|
||||
// we use product_id and device_id to make the device unique
|
||||
class EntityCustomization {
|
||||
public:
|
||||
uint8_t product_id; // device's product id
|
||||
uint8_t device_id; // device's device id
|
||||
std::vector<std::string> entity_ids; // array of entity ids with masks and optional custom fullname
|
||||
uint8_t product_id; // device's product id
|
||||
uint8_t device_id; // device's device id
|
||||
std::string custom_name; // custom device name
|
||||
std::vector<std::string> entity_ids; // array of entity ids with masks and optional custom fullname
|
||||
};
|
||||
|
||||
class WebCustomization {
|
||||
@@ -100,6 +102,7 @@ class WebCustomizationService : public StatefulService<WebCustomization> {
|
||||
|
||||
// POST
|
||||
void customization_entities(AsyncWebServerRequest * request, JsonVariant json);
|
||||
void writeDeviceName(AsyncWebServerRequest * request, JsonVariant json);
|
||||
void reset_customization(AsyncWebServerRequest * request); // command
|
||||
};
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ void WebDataService::core_data(AsyncWebServerRequest * request) {
|
||||
obj["tn"] = emsdevice->device_type_2_device_name_translated(); // translated device type name
|
||||
obj["t"] = emsdevice->device_type(); // device type number
|
||||
obj["b"] = emsdevice->brand_to_char(); // brand
|
||||
obj["n"] = emsdevice->name(); // name
|
||||
obj["n"] = emsdevice->name(); // custom name
|
||||
obj["d"] = emsdevice->device_id(); // deviceid
|
||||
obj["p"] = emsdevice->product_id(); // productid
|
||||
obj["v"] = emsdevice->version(); // version
|
||||
|
||||
Reference in New Issue
Block a user