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