mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@@ -93,9 +93,9 @@
|
|||||||
"makefile"
|
"makefile"
|
||||||
],
|
],
|
||||||
"typescript.preferences.preferTypeOnlyAutoImports": true,
|
"typescript.preferences.preferTypeOnlyAutoImports": true,
|
||||||
|
"sonarlint.pathToCompileCommands": "${workspaceFolder}/compile_commands.json",
|
||||||
"sonarlint.connectedMode.project": {
|
"sonarlint.connectedMode.project": {
|
||||||
"connectionId": "emsesp",
|
"connectionId": "emsesp",
|
||||||
"projectKey": "emsesp_EMS-ESP32"
|
"projectKey": "emsesp_EMS-ESP32"
|
||||||
},
|
}
|
||||||
"sonarlint.pathToCompileCommands": "${workspaceFolder}/compile_commands.json"
|
|
||||||
}
|
}
|
||||||
1392
dump_entities.csv
1392
dump_entities.csv
File diff suppressed because it is too large
Load Diff
@@ -107,7 +107,7 @@ telegram_type_id,name,is_fetched
|
|||||||
0x02A2,RC300Curves,
|
0x02A2,RC300Curves,
|
||||||
0x02A5,RC300Monitor,
|
0x02A5,RC300Monitor,
|
||||||
0x02A6,RC300Monitor,
|
0x02A6,RC300Monitor,
|
||||||
0x02A7,RC300Monitor,
|
0x02A7,CRFMonitor,
|
||||||
0x02A8,RC300Monitor,
|
0x02A8,RC300Monitor,
|
||||||
0x02A9,RC300Monitor,
|
0x02A9,RC300Monitor,
|
||||||
0x02AA,RC300Monitor,
|
0x02AA,RC300Monitor,
|
||||||
|
|||||||
|
@@ -16,7 +16,7 @@ export default tseslint.config(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ignores: ['dist/*', '*.js', '**/*.cjs', '**/unpack.ts', 'i18n*.*']
|
ignores: ['dist/*', 'build/*', '*.js', '**/*.cjs', '**/unpack.ts', 'i18n*.*']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
rules: {
|
rules: {
|
||||||
|
|||||||
@@ -24,14 +24,14 @@
|
|||||||
"@alova/adapter-xhr": "2.0.7",
|
"@alova/adapter-xhr": "2.0.7",
|
||||||
"@emotion/react": "^11.13.3",
|
"@emotion/react": "^11.13.3",
|
||||||
"@emotion/styled": "^11.13.0",
|
"@emotion/styled": "^11.13.0",
|
||||||
"@mui/icons-material": "^6.1.1",
|
"@mui/icons-material": "^6.1.2",
|
||||||
"@mui/material": "^6.1.1",
|
"@mui/material": "^6.1.2",
|
||||||
"@table-library/react-table-library": "4.1.7",
|
"@table-library/react-table-library": "4.1.7",
|
||||||
"alova": "3.0.17",
|
"alova": "3.0.17",
|
||||||
"async-validator": "^4.2.5",
|
"async-validator": "^4.2.5",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"mime-types": "^2.1.35",
|
"mime-types": "^2.1.35",
|
||||||
"preact": "^10.24.1",
|
"preact": "^10.24.2",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-icons": "^5.3.0",
|
"react-icons": "^5.3.0",
|
||||||
@@ -41,18 +41,18 @@
|
|||||||
"typescript": "^5.6.2"
|
"typescript": "^5.6.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.25.7",
|
||||||
"@eslint/js": "^9.11.1",
|
"@eslint/js": "^9.12.0",
|
||||||
"@preact/compat": "^18.3.1",
|
"@preact/compat": "^18.3.1",
|
||||||
"@preact/preset-vite": "^2.9.1",
|
"@preact/preset-vite": "^2.9.1",
|
||||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||||
"@types/formidable": "^3",
|
"@types/formidable": "^3",
|
||||||
"@types/node": "^22.7.4",
|
"@types/node": "^22.7.4",
|
||||||
"@types/react": "^18.3.10",
|
"@types/react": "^18.3.11",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"concurrently": "^9.0.1",
|
"concurrently": "^9.0.1",
|
||||||
"eslint": "^9.11.1",
|
"eslint": "^9.12.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"formidable": "^3.5.1",
|
"formidable": "^3.5.1",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
|
|||||||
@@ -277,7 +277,7 @@ const CustomEntitiesDialog = ({
|
|||||||
select
|
select
|
||||||
>
|
>
|
||||||
{DeviceValueUOM_s.map((val, i) => (
|
{DeviceValueUOM_s.map((val, i) => (
|
||||||
<MenuItem key={i} value={i}>
|
<MenuItem key={val} value={i}>
|
||||||
{val}
|
{val}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ const Devices = () => {
|
|||||||
}, [escFunction]);
|
}, [escFunction]);
|
||||||
|
|
||||||
const customize = () => {
|
const customize = () => {
|
||||||
if (selectedDevice == 99) {
|
if (selectedDevice === 99) {
|
||||||
navigate('/customentities');
|
navigate('/customentities');
|
||||||
} else {
|
} else {
|
||||||
navigate('/customizations', { state: selectedDevice });
|
navigate('/customizations', { state: selectedDevice });
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ const DevicesDialog = ({
|
|||||||
value={editItem.v}
|
value={editItem.v}
|
||||||
disabled={!writeable}
|
disabled={!writeable}
|
||||||
sx={{ width: '30ch' }}
|
sx={{ width: '30ch' }}
|
||||||
multiline={editItem.u ? false : true}
|
multiline={!editItem.u}
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import { useI18nContext } from 'i18n/i18n-react';
|
|||||||
|
|
||||||
import { readModules, writeModules } from '../../api/app';
|
import { readModules, writeModules } from '../../api/app';
|
||||||
import ModulesDialog from './ModulesDialog';
|
import ModulesDialog from './ModulesDialog';
|
||||||
import type { ModuleItem, Modules } from './types';
|
import type { ModuleItem } from './types';
|
||||||
|
|
||||||
const Modules = () => {
|
const Modules = () => {
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
@@ -39,6 +39,8 @@ const Modules = () => {
|
|||||||
const [selectedModuleItem, setSelectedModuleItem] = useState<ModuleItem>();
|
const [selectedModuleItem, setSelectedModuleItem] = useState<ModuleItem>();
|
||||||
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
||||||
|
|
||||||
|
useLayoutTitle(LL.MODULES());
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: modules,
|
data: modules,
|
||||||
send: fetchModules,
|
send: fetchModules,
|
||||||
@@ -155,8 +157,6 @@ const Modules = () => {
|
|||||||
return <FormLoader onRetry={fetchModules} errorMessage={error?.message} />;
|
return <FormLoader onRetry={fetchModules} errorMessage={error?.message} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
useLayoutTitle(LL.MODULES());
|
|
||||||
|
|
||||||
if (modules.length === 0) {
|
if (modules.length === 0) {
|
||||||
return (
|
return (
|
||||||
<Typography variant="body2" color="error">
|
<Typography variant="body2" color="error">
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ const Scheduler = () => {
|
|||||||
const [creating, setCreating] = useState<boolean>(false);
|
const [creating, setCreating] = useState<boolean>(false);
|
||||||
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
||||||
|
|
||||||
|
useLayoutTitle(LL.SCHEDULER());
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: schedule,
|
data: schedule,
|
||||||
send: fetchSchedule,
|
send: fetchSchedule,
|
||||||
@@ -243,8 +245,6 @@ const Scheduler = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|
||||||
useLayoutTitle(LL.SCHEDULER());
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table
|
<Table
|
||||||
data={{
|
data={{
|
||||||
|
|||||||
@@ -292,9 +292,7 @@ const SchedulerDialog = ({
|
|||||||
? LL.TIMER(1)
|
? LL.TIMER(1)
|
||||||
: LL.TIME(1)
|
: LL.TIME(1)
|
||||||
}
|
}
|
||||||
value={
|
value={editItem.time === '' ? '00:00' : editItem.time}
|
||||||
editItem.time == '' ? (editItem.time = '00:00') : editItem.time
|
|
||||||
}
|
|
||||||
margin="normal"
|
margin="normal"
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
/>
|
/>
|
||||||
@@ -318,9 +316,7 @@ const SchedulerDialog = ({
|
|||||||
}
|
}
|
||||||
multiline
|
multiline
|
||||||
fullWidth
|
fullWidth
|
||||||
value={
|
value={editItem.time === '00:00' ? '' : editItem.time}
|
||||||
editItem.time == '00:00' ? (editItem.time = '') : editItem.time
|
|
||||||
}
|
|
||||||
margin="normal"
|
margin="normal"
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -150,6 +150,56 @@ const Sensors = () => {
|
|||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const RenderTemperatureSensors = () => (
|
||||||
|
<Table
|
||||||
|
data={{ nodes: sensorData.ts }}
|
||||||
|
theme={temperature_theme}
|
||||||
|
sort={temperature_sort}
|
||||||
|
layout={{ custom: true }}
|
||||||
|
>
|
||||||
|
{(tableList: TemperatureSensor[]) => (
|
||||||
|
<>
|
||||||
|
<Header>
|
||||||
|
<HeaderRow>
|
||||||
|
<HeaderCell resize>
|
||||||
|
<Button
|
||||||
|
fullWidth
|
||||||
|
style={{ fontSize: '14px', justifyContent: 'flex-start' }}
|
||||||
|
endIcon={getSortIcon(temperature_sort.state, 'NAME')}
|
||||||
|
onClick={() =>
|
||||||
|
temperature_sort.fns.onToggleSort({ sortKey: 'NAME' })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{LL.NAME(0)}
|
||||||
|
</Button>
|
||||||
|
</HeaderCell>
|
||||||
|
<HeaderCell stiff>
|
||||||
|
<Button
|
||||||
|
fullWidth
|
||||||
|
style={{ fontSize: '14px', justifyContent: 'flex-end' }}
|
||||||
|
endIcon={getSortIcon(temperature_sort.state, 'VALUE')}
|
||||||
|
onClick={() =>
|
||||||
|
temperature_sort.fns.onToggleSort({ sortKey: 'VALUE' })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{LL.VALUE(0)}
|
||||||
|
</Button>
|
||||||
|
</HeaderCell>
|
||||||
|
</HeaderRow>
|
||||||
|
</Header>
|
||||||
|
<Body>
|
||||||
|
{tableList.map((ts: TemperatureSensor) => (
|
||||||
|
<Row key={ts.id} item={ts} onClick={() => updateTemperatureSensor(ts)}>
|
||||||
|
<Cell>{ts.n}</Cell>
|
||||||
|
<Cell>{formatValue(ts.t, ts.u)}</Cell>
|
||||||
|
</Row>
|
||||||
|
))}
|
||||||
|
</Body>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
|
|
||||||
const getSortIcon = (state: State, sortKey: unknown) => {
|
const getSortIcon = (state: State, sortKey: unknown) => {
|
||||||
if (state.sortKey === sortKey && state.reverse) {
|
if (state.sortKey === sortKey && state.reverse) {
|
||||||
return <KeyboardArrowDownOutlinedIcon />;
|
return <KeyboardArrowDownOutlinedIcon />;
|
||||||
@@ -332,56 +382,6 @@ const Sensors = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const RenderTemperatureSensors = () => (
|
|
||||||
<Table
|
|
||||||
data={{ nodes: sensorData.ts }}
|
|
||||||
theme={temperature_theme}
|
|
||||||
sort={temperature_sort}
|
|
||||||
layout={{ custom: true }}
|
|
||||||
>
|
|
||||||
{(tableList: TemperatureSensor[]) => (
|
|
||||||
<>
|
|
||||||
<Header>
|
|
||||||
<HeaderRow>
|
|
||||||
<HeaderCell resize>
|
|
||||||
<Button
|
|
||||||
fullWidth
|
|
||||||
style={{ fontSize: '14px', justifyContent: 'flex-start' }}
|
|
||||||
endIcon={getSortIcon(temperature_sort.state, 'NAME')}
|
|
||||||
onClick={() =>
|
|
||||||
temperature_sort.fns.onToggleSort({ sortKey: 'NAME' })
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{LL.NAME(0)}
|
|
||||||
</Button>
|
|
||||||
</HeaderCell>
|
|
||||||
<HeaderCell stiff>
|
|
||||||
<Button
|
|
||||||
fullWidth
|
|
||||||
style={{ fontSize: '14px', justifyContent: 'flex-end' }}
|
|
||||||
endIcon={getSortIcon(temperature_sort.state, 'VALUE')}
|
|
||||||
onClick={() =>
|
|
||||||
temperature_sort.fns.onToggleSort({ sortKey: 'VALUE' })
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{LL.VALUE(0)}
|
|
||||||
</Button>
|
|
||||||
</HeaderCell>
|
|
||||||
</HeaderRow>
|
|
||||||
</Header>
|
|
||||||
<Body>
|
|
||||||
{tableList.map((ts: TemperatureSensor) => (
|
|
||||||
<Row key={ts.id} item={ts} onClick={() => updateTemperatureSensor(ts)}>
|
|
||||||
<Cell>{ts.n}</Cell>
|
|
||||||
<Cell>{formatValue(ts.t, ts.u)}</Cell>
|
|
||||||
</Row>
|
|
||||||
))}
|
|
||||||
</Body>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Table>
|
|
||||||
);
|
|
||||||
|
|
||||||
const RenderAnalogSensors = () => (
|
const RenderAnalogSensors = () => (
|
||||||
<Table
|
<Table
|
||||||
data={{ nodes: sensorData.as }}
|
data={{ nodes: sensorData.as }}
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ const SensorsAnalogDialog = ({
|
|||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
>
|
>
|
||||||
{AnalogTypeNames.map((val, i) => (
|
{AnalogTypeNames.map((val, i) => (
|
||||||
<MenuItem key={i} value={i}>
|
<MenuItem key={val} value={i}>
|
||||||
{val}
|
{val}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
@@ -143,7 +143,7 @@ const SensorsAnalogDialog = ({
|
|||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
>
|
>
|
||||||
{DeviceValueUOM_s.map((val, i) => (
|
{DeviceValueUOM_s.map((val, i) => (
|
||||||
<MenuItem key={i} value={i}>
|
<MenuItem key={val} value={i}>
|
||||||
{val}
|
{val}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -206,15 +206,15 @@ export const DeviceValueUOM_s = [
|
|||||||
export enum AnalogType {
|
export enum AnalogType {
|
||||||
REMOVED = -1,
|
REMOVED = -1,
|
||||||
NOTUSED = 0,
|
NOTUSED = 0,
|
||||||
DIGITAL_IN,
|
DIGITAL_IN = 1,
|
||||||
COUNTER,
|
COUNTER = 2,
|
||||||
ADC,
|
ADC = 3,
|
||||||
TIMER,
|
TIMER = 4,
|
||||||
RATE,
|
RATE = 5,
|
||||||
DIGITAL_OUT,
|
DIGITAL_OUT = 6,
|
||||||
PWM_0,
|
PWM_0 = 7,
|
||||||
PWM_1,
|
PWM_1 = 8,
|
||||||
PWM_2
|
PWM_2 = 9
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AnalogTypeNames = [
|
export const AnalogTypeNames = [
|
||||||
@@ -296,7 +296,7 @@ export interface ScheduleItem {
|
|||||||
active: boolean;
|
active: boolean;
|
||||||
deleted?: boolean;
|
deleted?: boolean;
|
||||||
flags: number;
|
flags: number;
|
||||||
time: string;
|
time: string; // also used for Condition and On Change
|
||||||
cmd: string;
|
cmd: string;
|
||||||
value: string;
|
value: string;
|
||||||
name: string; // is optional
|
name: string; // is optional
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export const apStatusHighlight = ({ status }: APStatusType, theme: Theme) => {
|
|||||||
|
|
||||||
const APStatus = () => {
|
const APStatus = () => {
|
||||||
const {
|
const {
|
||||||
data: data,
|
data,
|
||||||
send: loadData,
|
send: loadData,
|
||||||
error
|
error
|
||||||
} = useAutoRequest(APApi.readAPStatus, { pollingTime: 5000 });
|
} = useAutoRequest(APApi.readAPStatus, { pollingTime: 5000 });
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import type { Stat } from '../main/types';
|
|||||||
|
|
||||||
const SystemActivity = () => {
|
const SystemActivity = () => {
|
||||||
const {
|
const {
|
||||||
data: data,
|
data,
|
||||||
send: loadData,
|
send: loadData,
|
||||||
error
|
error
|
||||||
} = useAutoRequest(readActivity, { pollingTime: 2000 });
|
} = useAutoRequest(readActivity, { pollingTime: 2000 });
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const HardwareStatus = () => {
|
|||||||
useLayoutTitle(LL.STATUS_OF(LL.HARDWARE()));
|
useLayoutTitle(LL.STATUS_OF(LL.HARDWARE()));
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: data,
|
data,
|
||||||
send: loadData,
|
send: loadData,
|
||||||
error
|
error
|
||||||
} = useAutoRequest(SystemApi.readSystemStatus, { pollingTime: 2000 });
|
} = useAutoRequest(SystemApi.readSystemStatus, { pollingTime: 2000 });
|
||||||
@@ -50,6 +50,7 @@ const HardwareStatus = () => {
|
|||||||
{data.model ? (
|
{data.model ? (
|
||||||
<Avatar sx={{ bgcolor: '#003289', color: 'white' }}>
|
<Avatar sx={{ bgcolor: '#003289', color: 'white' }}>
|
||||||
<img
|
<img
|
||||||
|
alt="BBQKees"
|
||||||
src={BBQKeesIcon}
|
src={BBQKeesIcon}
|
||||||
style={{ width: 16, verticalAlign: 'middle' }}
|
style={{ width: 16, verticalAlign: 'middle' }}
|
||||||
/>
|
/>
|
||||||
@@ -93,7 +94,7 @@ const HardwareStatus = () => {
|
|||||||
' (rev.' +
|
' (rev.' +
|
||||||
data.cpu_rev +
|
data.cpu_rev +
|
||||||
', ' +
|
', ' +
|
||||||
(data.cpu_cores == 1 ? 'single-core)' : 'dual-core)') +
|
(data.cpu_cores === 1 ? 'single-core)' : 'dual-core)') +
|
||||||
' @ ' +
|
' @ ' +
|
||||||
data.cpu_freq_mhz +
|
data.cpu_freq_mhz +
|
||||||
' Mhz'
|
' Mhz'
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export const mqttQueueHighlight = (
|
|||||||
|
|
||||||
const MqttStatus = () => {
|
const MqttStatus = () => {
|
||||||
const {
|
const {
|
||||||
data: data,
|
data,
|
||||||
send: loadData,
|
send: loadData,
|
||||||
error
|
error
|
||||||
} = useAutoRequest(MqttApi.readMqttStatus, { pollingTime: 5000 });
|
} = useAutoRequest(MqttApi.readMqttStatus, { pollingTime: 5000 });
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ import { formatDateTime, formatLocalDateTime } from 'utils';
|
|||||||
|
|
||||||
const NTPStatus = () => {
|
const NTPStatus = () => {
|
||||||
const {
|
const {
|
||||||
data: data,
|
data,
|
||||||
send: loadData,
|
send: loadData,
|
||||||
error
|
error
|
||||||
} = useAutoRequest(NTPApi.readNTPStatus, { pollingTime: 5000 });
|
} = useAutoRequest(NTPApi.readNTPStatus, { pollingTime: 5000 });
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ const IPs = (status: NetworkStatusType) => {
|
|||||||
|
|
||||||
const NetworkStatus = () => {
|
const NetworkStatus = () => {
|
||||||
const {
|
const {
|
||||||
data: data,
|
data,
|
||||||
send: loadData,
|
send: loadData,
|
||||||
error
|
error
|
||||||
} = useAutoRequest(NetworkApi.readNetworkStatus, { pollingTime: 5000 });
|
} = useAutoRequest(NetworkApi.readNetworkStatus, { pollingTime: 5000 });
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ const SystemStatus = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: data,
|
data,
|
||||||
send: loadData,
|
send: loadData,
|
||||||
error
|
error
|
||||||
} = useAutoRequest(readSystemStatus, {
|
} = useAutoRequest(readSystemStatus, {
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ const SystemLog = () => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{logEntries.map((e) => (
|
{logEntries.map((e) => (
|
||||||
<div style={{ font: '14px monospace', whiteSpace: 'nowrap' }}>
|
<div key={e.i} style={{ font: '14px monospace', whiteSpace: 'nowrap' }}>
|
||||||
<span>{e.t}</span>
|
<span>{e.t}</span>
|
||||||
<span>{paddedLevelLabel(e.l)} </span>
|
<span>{paddedLevelLabel(e.l)} </span>
|
||||||
<span>{paddedIDLabel(e.i)} </span>
|
<span>{paddedIDLabel(e.i)} </span>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const ValidatedTextField: FC<ValidatedTextFieldProps> = ({
|
|||||||
const errors = fieldErrors && fieldErrors[rest.name];
|
const errors = fieldErrors && fieldErrors[rest.name];
|
||||||
const renderErrors = () =>
|
const renderErrors = () =>
|
||||||
errors &&
|
errors &&
|
||||||
errors.map((e, i) => <FormHelperText key={i}>{e.message}</FormHelperText>);
|
errors.map((e) => <FormHelperText key={e.message}>{e.message}</FormHelperText>);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TextField error={!!errors} {...rest} />
|
<TextField error={!!errors} {...rest} />
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ const Layout: FC<RequiredChildrenProps> = ({ children }) => {
|
|||||||
useEffect(() => setMobileOpen(false), [pathname]);
|
useEffect(() => setMobileOpen(false), [pathname]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
// TODO wrap title/setTitle in a useMemo()
|
||||||
<LayoutContext.Provider value={{ title, setTitle }}>
|
<LayoutContext.Provider value={{ title, setTitle }}>
|
||||||
<LayoutAppBar title={title} onToggleDrawer={handleDrawerToggle} />
|
<LayoutAppBar title={title} onToggleDrawer={handleDrawerToggle} />
|
||||||
<LayoutDrawer mobileOpen={mobileOpen} onClose={handleDrawerToggle} />
|
<LayoutDrawer mobileOpen={mobileOpen} onClose={handleDrawerToggle} />
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ const Authentication: FC<RequiredChildrenProps> = ({ children }) => {
|
|||||||
|
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
return (
|
return (
|
||||||
|
// TODO useMemo?
|
||||||
<AuthenticationContext.Provider
|
<AuthenticationContext.Provider
|
||||||
value={{
|
value={{
|
||||||
signIn,
|
signIn,
|
||||||
|
|||||||
@@ -7,17 +7,13 @@ export const validate = <T extends object>(
|
|||||||
options?: ValidateOption
|
options?: ValidateOption
|
||||||
): Promise<T> =>
|
): Promise<T> =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
void validator.validate(
|
void validator.validate(source, options || {}, (errors, fieldErrors) => {
|
||||||
source,
|
if (errors) {
|
||||||
options ? options : {},
|
reject(fieldErrors as Error);
|
||||||
(errors, fieldErrors) => {
|
} else {
|
||||||
if (errors) {
|
resolve(source as T);
|
||||||
reject(fieldErrors as Error);
|
|
||||||
} else {
|
|
||||||
resolve(source as T);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// updated to support both IPv4 and IPv6
|
// updated to support both IPv4 and IPv6
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
|||||||
import formidable from 'formidable';
|
import formidable from 'formidable';
|
||||||
|
|
||||||
function pad(number) {
|
function pad(number) {
|
||||||
var r = String(number);
|
let r = String(number);
|
||||||
if (r.length === 1) {
|
if (r.length === 1) {
|
||||||
r = '0' + r;
|
r = '0' + r;
|
||||||
}
|
}
|
||||||
|
|||||||
117
src/console.cpp
117
src/console.cpp
@@ -39,10 +39,6 @@ static inline EMSESPShell & to_shell(Shell & shell) {
|
|||||||
return static_cast<EMSESPShell &>(shell);
|
return static_cast<EMSESPShell &>(shell);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline EMSESP & to_app(Shell & shell) {
|
|
||||||
return to_shell(shell).emsesp_;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define NO_ARGUMENTS \
|
#define NO_ARGUMENTS \
|
||||||
std::vector<std::string> { \
|
std::vector<std::string> { \
|
||||||
}
|
}
|
||||||
@@ -67,7 +63,7 @@ static std::vector<std::string> log_level_autocomplete(Shell & shell, const std:
|
|||||||
return uuid::log::levels_lowercase();
|
return uuid::log::levels_lowercase();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_commands(std::shared_ptr<Commands> & commands) {
|
static void setup_commands(std::shared_ptr<Commands> const & commands) {
|
||||||
// exit, help, log
|
// exit, help, log
|
||||||
commands->add_command(ShellContext::MAIN, CommandFlags::USER, {F_(exit)}, EMSESPShell::main_exit_function);
|
commands->add_command(ShellContext::MAIN, CommandFlags::USER, {F_(exit)}, EMSESPShell::main_exit_function);
|
||||||
commands->add_command(ShellContext::MAIN, CommandFlags::USER, {F_(help)}, EMSESPShell::main_help_function);
|
commands->add_command(ShellContext::MAIN, CommandFlags::USER, {F_(help)}, EMSESPShell::main_help_function);
|
||||||
@@ -81,35 +77,35 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
{F_(show)},
|
{F_(show)},
|
||||||
{F_(show_commands)},
|
{F_(show_commands)},
|
||||||
[=](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
if (arguments.empty()) {
|
if (arguments.empty()) {
|
||||||
to_app(shell).system_.show_system(shell);
|
EMSESP::system_.show_system(shell);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto command = arguments.front();
|
auto const & command = arguments.front();
|
||||||
if (command == F_(commands)) {
|
if (command == F_(commands)) {
|
||||||
Command::show_all(shell);
|
Command::show_all(shell);
|
||||||
} else if (command == F_(system)) {
|
} else if (command == F_(system)) {
|
||||||
to_app(shell).system_.show_system(shell);
|
EMSESP::system_.show_system(shell);
|
||||||
} else if (command == F_(users) && (shell.has_flags(CommandFlags::ADMIN))) {
|
} else if (command == F_(users) && (shell.has_flags(CommandFlags::ADMIN))) {
|
||||||
to_app(shell).system_.show_users(shell); // admin only
|
EMSESP::system_.show_users(shell); // admin only
|
||||||
} else if (command == F_(devices)) {
|
} else if (command == F_(devices)) {
|
||||||
to_app(shell).show_devices(shell);
|
EMSESP::show_devices(shell);
|
||||||
} else if (command == F_(log)) {
|
} else if (command == F_(log)) {
|
||||||
to_app(shell).webLogService.show(shell);
|
EMSESP::webLogService.show(shell);
|
||||||
} else if (command == F_(ems)) {
|
} else if (command == F_(ems)) {
|
||||||
to_app(shell).show_ems(shell);
|
EMSESP::show_ems(shell);
|
||||||
} else if (command == F_(values)) {
|
} else if (command == F_(values)) {
|
||||||
to_app(shell).show_device_values(shell);
|
EMSESP::show_device_values(shell);
|
||||||
to_app(shell).show_sensor_values(shell);
|
EMSESP::show_sensor_values(shell);
|
||||||
} else if (command == F_(mqtt)) {
|
} else if (command == F_(mqtt)) {
|
||||||
Mqtt::show_mqtt(shell);
|
Mqtt::show_mqtt(shell);
|
||||||
} else {
|
} else {
|
||||||
shell.printfln("Unknown show command");
|
shell.printfln("Unknown show command");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[](Shell & shell, const std::vector<std::string> & current_arguments, const std::string & next_argument) -> std::vector<std::string> {
|
[](Shell const & shell, const std::vector<std::string> & current_arguments, const std::string & next_argument) -> std::vector<std::string> {
|
||||||
return std::vector<std::string>{"system", "users", "devices", "log", "ems", "values", "mqtt", "commands"};
|
return std::vector<std::string>{"system", "users", "devices", "log", "ems", "values", "mqtt", "commands"};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -154,7 +150,7 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
if (completed) {
|
if (completed) {
|
||||||
uint64_t now = uuid::get_uptime_ms();
|
uint64_t now = uuid::get_uptime_ms();
|
||||||
|
|
||||||
to_app(shell).esp8266React.getSecuritySettingsService()->read([&](SecuritySettings & securitySettings) {
|
EMSESP::esp8266React.getSecuritySettingsService()->read([&](SecuritySettings & securitySettings) {
|
||||||
if (!password.empty() && (securitySettings.jwtSecret.equals(password.c_str()))) {
|
if (!password.empty() && (securitySettings.jwtSecret.equals(password.c_str()))) {
|
||||||
become_admin(shell);
|
become_admin(shell);
|
||||||
} else {
|
} else {
|
||||||
@@ -178,7 +174,7 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
shell.enter_password(F_(new_password_prompt2), [password1](Shell & shell, bool completed, const std::string & password2) {
|
shell.enter_password(F_(new_password_prompt2), [password1](Shell & shell, bool completed, const std::string & password2) {
|
||||||
if (completed) {
|
if (completed) {
|
||||||
if (password1 == password2) {
|
if (password1 == password2) {
|
||||||
to_app(shell).esp8266React.getSecuritySettingsService()->update([&](SecuritySettings & securitySettings) {
|
EMSESP::esp8266React.getSecuritySettingsService()->update([&](SecuritySettings & securitySettings) {
|
||||||
securitySettings.jwtSecret = password2.c_str();
|
securitySettings.jwtSecret = password2.c_str();
|
||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
});
|
});
|
||||||
@@ -198,16 +194,16 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
{F_(partitionname_optional)},
|
{F_(partitionname_optional)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
if (arguments.size()) {
|
if (arguments.size()) {
|
||||||
to_app(shell).system_.system_restart(arguments.front().c_str());
|
EMSESP::system_.system_restart(arguments.front().c_str());
|
||||||
} else {
|
} else {
|
||||||
to_app(shell).system_.system_restart();
|
EMSESP::system_.system_restart();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
commands->add_command(ShellContext::MAIN,
|
commands->add_command(ShellContext::MAIN,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
string_vector{F_(wifi), F_(reconnect)},
|
string_vector{F_(wifi), F_(reconnect)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments) { to_app(shell).system_.wifi_reconnect(); });
|
[](Shell & shell, const std::vector<std::string> & arguments) { EMSESP::system_.wifi_reconnect(); });
|
||||||
|
|
||||||
//
|
//
|
||||||
// SET commands
|
// SET commands
|
||||||
@@ -221,13 +217,13 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
shell.enter_password(F_(new_password_prompt2), [password1](Shell & shell, bool completed, const std::string & password2) {
|
shell.enter_password(F_(new_password_prompt2), [password1](Shell & shell, bool completed, const std::string & password2) {
|
||||||
if (completed) {
|
if (completed) {
|
||||||
if (password1 == password2) {
|
if (password1 == password2) {
|
||||||
to_app(shell).esp8266React.getNetworkSettingsService()->updateWithoutPropagation(
|
EMSESP::esp8266React.getNetworkSettingsService()->updateWithoutPropagation(
|
||||||
[&](NetworkSettings & networkSettings) {
|
[&](NetworkSettings & networkSettings) {
|
||||||
networkSettings.password = password2.c_str();
|
networkSettings.password = password2.c_str();
|
||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
});
|
});
|
||||||
shell.println("WiFi password updated. Reconnecting...");
|
shell.println("WiFi password updated. Reconnecting...");
|
||||||
to_app(shell).system_.wifi_reconnect();
|
EMSESP::system_.wifi_reconnect();
|
||||||
} else {
|
} else {
|
||||||
shell.println("Passwords do not match");
|
shell.println("Passwords do not match");
|
||||||
}
|
}
|
||||||
@@ -245,7 +241,7 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
shell.println("The network connection will be reset...");
|
shell.println("The network connection will be reset...");
|
||||||
Shell::loop_all();
|
Shell::loop_all();
|
||||||
delay(1000); // wait a second
|
delay(1000); // wait a second
|
||||||
to_app(shell).esp8266React.getNetworkSettingsService()->update([&](NetworkSettings & networkSettings) {
|
EMSESP::esp8266React.getNetworkSettingsService()->update([&](NetworkSettings & networkSettings) {
|
||||||
networkSettings.hostname = arguments.front().c_str();
|
networkSettings.hostname = arguments.front().c_str();
|
||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
});
|
});
|
||||||
@@ -256,12 +252,12 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
string_vector{F_(set), F_(wifi), F_(ssid)},
|
string_vector{F_(set), F_(wifi), F_(ssid)},
|
||||||
{F_(name_mandatory)},
|
{F_(name_mandatory)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
to_app(shell).esp8266React.getNetworkSettingsService()->updateWithoutPropagation([&](NetworkSettings & networkSettings) {
|
EMSESP::esp8266React.getNetworkSettingsService()->updateWithoutPropagation([&](NetworkSettings & networkSettings) {
|
||||||
networkSettings.ssid = arguments.front().c_str();
|
networkSettings.ssid = arguments.front().c_str();
|
||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
});
|
});
|
||||||
shell.println("WiFi ssid updated. Reconnecting...");
|
shell.println("WiFi ssid updated. Reconnecting...");
|
||||||
to_app(shell).system_.wifi_reconnect();
|
EMSESP::system_.wifi_reconnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -273,12 +269,12 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
std::vector<int8_t> data; // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode
|
std::vector<int8_t> data; // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode
|
||||||
std::string board_profile = Helpers::toUpper(arguments.front());
|
std::string board_profile = Helpers::toUpper(arguments.front());
|
||||||
if (!to_app(shell).system_.load_board_profile(data, board_profile)) {
|
if (!EMSESP::system_.load_board_profile(data, board_profile)) {
|
||||||
shell.println("Invalid board profile (S32, E32, E32V2, MH-ET, NODEMCU, LOLIN, OLIMEX, OLIMEXPOE, C3MINI, S2MINI, S3MINI, S32S3, CUSTOM)");
|
shell.println("Invalid board profile (S32, E32, E32V2, MH-ET, NODEMCU, LOLIN, OLIMEX, OLIMEXPOE, C3MINI, S2MINI, S3MINI, S32S3, CUSTOM)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
to_app(shell).webSettingsService.update([&](WebSettings & settings) {
|
EMSESP::webSettingsService.update([&](WebSettings & settings) {
|
||||||
settings.board_profile = board_profile.c_str();
|
settings.board_profile = board_profile.c_str();
|
||||||
settings.led_gpio = data[0];
|
settings.led_gpio = data[0];
|
||||||
settings.dallas_gpio = data[1];
|
settings.dallas_gpio = data[1];
|
||||||
@@ -292,7 +288,7 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
});
|
});
|
||||||
shell.printfln("Loaded board profile %s", board_profile.c_str());
|
shell.printfln("Loaded board profile %s", board_profile.c_str());
|
||||||
to_app(shell).system_.network_init(true);
|
EMSESP::system_.network_init(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
commands->add_command(
|
commands->add_command(
|
||||||
@@ -303,7 +299,7 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
uint8_t device_id = Helpers::hextoint(arguments.front().c_str());
|
uint8_t device_id = Helpers::hextoint(arguments.front().c_str());
|
||||||
if ((device_id == 0x0B) || (device_id == 0x0D) || (device_id == 0x0A) || (device_id == 0x0F) || (device_id == 0x12)) {
|
if ((device_id == 0x0B) || (device_id == 0x0D) || (device_id == 0x0A) || (device_id == 0x0F) || (device_id == 0x12)) {
|
||||||
to_app(shell).webSettingsService.update([&](WebSettings & settings) {
|
EMSESP::webSettingsService.update([&](WebSettings & settings) {
|
||||||
settings.ems_bus_id = device_id;
|
settings.ems_bus_id = device_id;
|
||||||
shell.printfln(F_(bus_id_fmt), settings.ems_bus_id);
|
shell.printfln(F_(bus_id_fmt), settings.ems_bus_id);
|
||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
@@ -323,12 +319,12 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
uint8_t tx_mode = std::strtol(arguments[0].c_str(), nullptr, 10);
|
uint8_t tx_mode = std::strtol(arguments[0].c_str(), nullptr, 10);
|
||||||
// save the tx_mode
|
// save the tx_mode
|
||||||
to_app(shell).webSettingsService.update([&](WebSettings & settings) {
|
EMSESP::webSettingsService.update([&](WebSettings & settings) {
|
||||||
settings.tx_mode = tx_mode;
|
settings.tx_mode = tx_mode;
|
||||||
shell.printfln(F_(tx_mode_fmt), settings.tx_mode);
|
shell.printfln(F_(tx_mode_fmt), settings.tx_mode);
|
||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
});
|
});
|
||||||
to_app(shell).uart_init();
|
EMSESP::uart_init();
|
||||||
});
|
});
|
||||||
|
|
||||||
commands->add_command(ShellContext::MAIN,
|
commands->add_command(ShellContext::MAIN,
|
||||||
@@ -339,17 +335,17 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
if (arguments.back() == "enable" || arguments.back() == "disable") {
|
if (arguments.back() == "enable" || arguments.back() == "disable") {
|
||||||
bool enable = arguments.back() == "enable";
|
bool enable = arguments.back() == "enable";
|
||||||
if (arguments.front() == "mqtt") {
|
if (arguments.front() == "mqtt") {
|
||||||
to_app(shell).esp8266React.getMqttSettingsService()->update([&](MqttSettings & Settings) {
|
EMSESP::esp8266React.getMqttSettingsService()->update([&](MqttSettings & Settings) {
|
||||||
Settings.enabled = enable;
|
Settings.enabled = enable;
|
||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
});
|
});
|
||||||
} else if (arguments.front() == "ntp") {
|
} else if (arguments.front() == "ntp") {
|
||||||
to_app(shell).esp8266React.getNTPSettingsService()->update([&](NTPSettings & Settings) {
|
EMSESP::esp8266React.getNTPSettingsService()->update([&](NTPSettings & Settings) {
|
||||||
Settings.enabled = enable;
|
Settings.enabled = enable;
|
||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
});
|
});
|
||||||
} else if (arguments.front() == "ap") {
|
} else if (arguments.front() == "ap") {
|
||||||
to_app(shell).esp8266React.getAPSettingsService()->update([&](APSettings & Settings) {
|
EMSESP::esp8266React.getAPSettingsService()->update([&](APSettings & Settings) {
|
||||||
Settings.provisionMode = enable ? 0 : 2;
|
Settings.provisionMode = enable ? 0 : 2;
|
||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
});
|
});
|
||||||
@@ -368,17 +364,17 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
//
|
//
|
||||||
|
|
||||||
commands->add_command(ShellContext::MAIN, CommandFlags::ADMIN, {F_(scan)}, {F_(deep_optional)}, [](Shell & shell, const std::vector<std::string> & arguments) {
|
commands->add_command(ShellContext::MAIN, CommandFlags::ADMIN, {F_(scan)}, {F_(deep_optional)}, [](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
if (arguments.size() == 0) {
|
if (arguments.empty()) {
|
||||||
to_app(shell).scan_devices();
|
EMSESP::scan_devices();
|
||||||
} else {
|
} else {
|
||||||
shell.printfln("Performing a deep scan...");
|
shell.printfln("Performing a deep scan...");
|
||||||
to_app(shell).clear_all_devices();
|
EMSESP::clear_all_devices();
|
||||||
// device IDs taken from device_library.h
|
// device IDs taken from device_library.h
|
||||||
// send the read command with Version command
|
// send the read command with Version command
|
||||||
const std::vector<uint8_t> Device_Ids = {0x02, 0x08, 0x09, 0x10, 0x11, 0x12, 0x15, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x20, 0x21, 0x22, 0x23,
|
const std::vector<uint8_t> Device_Ids = {0x02, 0x08, 0x09, 0x10, 0x11, 0x12, 0x15, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x20, 0x21, 0x22, 0x23,
|
||||||
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x30, 0x38, 0x40, 0x41, 0x48, 0x50, 0x51, 0x60};
|
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x30, 0x38, 0x40, 0x41, 0x48, 0x50, 0x51, 0x60};
|
||||||
for (const uint8_t device_id : Device_Ids) {
|
for (const uint8_t device_id : Device_Ids) {
|
||||||
to_app(shell).send_read_request(EMSdevice::EMS_TYPE_VERSION, device_id);
|
EMSESP::send_read_request(EMSdevice::EMS_TYPE_VERSION, device_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -390,7 +386,7 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
[=](Shell & shell, const std::vector<std::string> & arguments) {
|
[=](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
uint8_t device_id = Helpers::hextoint(arguments.front().c_str());
|
uint8_t device_id = Helpers::hextoint(arguments.front().c_str());
|
||||||
|
|
||||||
if (!to_app(shell).valid_device(device_id)) {
|
if (!EMSESP::valid_device(device_id)) {
|
||||||
shell.printfln("Invalid deviceID");
|
shell.printfln("Invalid deviceID");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -399,14 +395,14 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
if (arguments.size() == 4) {
|
if (arguments.size() == 4) {
|
||||||
uint16_t offset = Helpers::hextoint(arguments[2].c_str());
|
uint16_t offset = Helpers::hextoint(arguments[2].c_str());
|
||||||
uint8_t length = Helpers::hextoint(arguments.back().c_str());
|
uint8_t length = Helpers::hextoint(arguments.back().c_str());
|
||||||
to_app(shell).send_read_request(type_id, device_id, offset, length, true);
|
EMSESP::send_read_request(type_id, device_id, offset, length, true);
|
||||||
} else if (arguments.size() == 3) {
|
} else if (arguments.size() == 3) {
|
||||||
uint16_t offset = Helpers::hextoint(arguments.back().c_str());
|
uint16_t offset = Helpers::hextoint(arguments.back().c_str());
|
||||||
to_app(shell).send_read_request(type_id, device_id, offset, 0, true);
|
EMSESP::send_read_request(type_id, device_id, offset, 0, true);
|
||||||
} else {
|
} else {
|
||||||
to_app(shell).send_read_request(type_id, device_id, 0, 0, true);
|
EMSESP::send_read_request(type_id, device_id, 0, 0, true);
|
||||||
}
|
}
|
||||||
to_app(shell).set_read_id(type_id);
|
EMSESP::set_read_id(type_id);
|
||||||
});
|
});
|
||||||
|
|
||||||
commands->add_command(ShellContext::MAIN,
|
commands->add_command(ShellContext::MAIN,
|
||||||
@@ -419,22 +415,21 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
// only use english commands, not the translations
|
// only use english commands, not the translations
|
||||||
if (!arguments.empty()) {
|
if (!arguments.empty()) {
|
||||||
// get raw/pretty
|
// get raw/pretty
|
||||||
if (arguments[0] == (F_(raw))) {
|
if (arguments[0] == F_(raw)) {
|
||||||
to_app(shell).watch(to_app(shell).WATCH_RAW); // raw
|
EMSESP::watch(EMSESP::WATCH_RAW); // raw
|
||||||
} else if (arguments[0] == (FL_(on)[0])) {
|
} else if (arguments[0] == (FL_(on)[0])) {
|
||||||
to_app(shell).watch(to_app(shell).WATCH_ON); // on
|
EMSESP::watch(EMSESP::WATCH_ON); // on
|
||||||
} else if (arguments[0] == (FL_(off)[0])) {
|
} else if (arguments[0] == (FL_(off)[0])) {
|
||||||
to_app(shell).watch(to_app(shell).WATCH_OFF); // off
|
EMSESP::watch(EMSESP::WATCH_OFF); // off
|
||||||
} else if (arguments[0] == (FL_(unknown)[0])) {
|
} else if (arguments[0] == (FL_(unknown)[0])) {
|
||||||
to_app(shell).watch(to_app(shell).WATCH_UNKNOWN); // unknown
|
EMSESP::watch(EMSESP::WATCH_UNKNOWN); // unknown
|
||||||
watch_id = WATCH_ID_NONE;
|
watch_id = WATCH_ID_NONE;
|
||||||
} else {
|
} else {
|
||||||
watch_id = Helpers::hextoint(arguments[0].c_str());
|
watch_id = Helpers::hextoint(arguments[0].c_str());
|
||||||
if (watch_id > 0
|
if (watch_id > 0 && ((EMSESP::watch() == EMSESP::WATCH_OFF) || (EMSESP::watch() == EMSESP::WATCH_UNKNOWN))) {
|
||||||
&& ((to_app(shell).watch() == to_app(shell).WATCH_OFF) || (to_app(shell).watch() == to_app(shell).WATCH_UNKNOWN))) {
|
EMSESP::watch(EMSESP::WATCH_ON); // on
|
||||||
to_app(shell).watch(to_app(shell).WATCH_ON); // on
|
|
||||||
} else if (watch_id == 0) {
|
} else if (watch_id == 0) {
|
||||||
to_app(shell).watch(to_app(shell).WATCH_OFF); // off
|
EMSESP::watch(EMSESP::WATCH_OFF); // off
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -444,14 +439,14 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
watch_id = Helpers::hextoint(arguments[1].c_str());
|
watch_id = Helpers::hextoint(arguments[1].c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
to_app(shell).watch_id(watch_id);
|
EMSESP::watch_id(watch_id);
|
||||||
} else {
|
} else {
|
||||||
shell.printfln("Invalid: use watch raw|on|off|unknown|id [id]");
|
shell.printfln("Invalid: use watch raw|on|off|unknown|id [id]");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t watch = to_app(shell).watch();
|
uint8_t watch = EMSESP::watch();
|
||||||
if (watch == to_app(shell).WATCH_OFF) {
|
if (watch == EMSESP::WATCH_OFF) {
|
||||||
shell.printfln("Watching telegrams is off");
|
shell.printfln("Watching telegrams is off");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -462,15 +457,15 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
shell.printfln("Setting log level to Notice");
|
shell.printfln("Setting log level to Notice");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (watch == to_app(shell).WATCH_ON) {
|
if (watch == EMSESP::WATCH_ON) {
|
||||||
shell.printfln("Watching incoming telegrams, displayed in decoded format");
|
shell.printfln("Watching incoming telegrams, displayed in decoded format");
|
||||||
} else if (watch == to_app(shell).WATCH_RAW) {
|
} else if (watch == EMSESP::WATCH_RAW) {
|
||||||
shell.printfln("Watching incoming telegrams, displayed as raw bytes"); // WATCH_RAW
|
shell.printfln("Watching incoming telegrams, displayed as raw bytes"); // WATCH_RAW
|
||||||
} else {
|
} else {
|
||||||
shell.printfln("Watching unknown telegrams"); // WATCH_UNKNOWN
|
shell.printfln("Watching unknown telegrams"); // WATCH_UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
watch_id = to_app(shell).watch_id();
|
watch_id = EMSESP::watch_id();
|
||||||
if (watch_id > 0x80) {
|
if (watch_id > 0x80) {
|
||||||
shell.printfln("Filtering only telegrams that match a telegram type of 0x%02X", watch_id);
|
shell.printfln("Filtering only telegrams that match a telegram type of 0x%02X", watch_id);
|
||||||
} else if (watch_id != WATCH_ID_NONE) {
|
} else if (watch_id != WATCH_ID_NONE) {
|
||||||
@@ -571,7 +566,7 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
[](Shell & shell, const std::vector<std::string> & current_arguments, const std::string & next_argument) -> std::vector<std::string> {
|
[](Shell & shell, const std::vector<std::string> & current_arguments, const std::string & next_argument) -> std::vector<std::string> {
|
||||||
if (current_arguments.size() == 0) {
|
if (current_arguments.empty()) {
|
||||||
std::vector<std::string> devices_list;
|
std::vector<std::string> devices_list;
|
||||||
devices_list.emplace_back(EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM));
|
devices_list.emplace_back(EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM));
|
||||||
devices_list.emplace_back(EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::TEMPERATURESENSOR));
|
devices_list.emplace_back(EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::TEMPERATURESENSOR));
|
||||||
@@ -600,7 +595,7 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Commands> EMSESPShell::commands_ = [] {
|
std::shared_ptr<Commands> EMSESPShell::commands_ = [] {
|
||||||
std::shared_ptr<Commands> commands = std::make_shared<Commands>();
|
auto commands = std::make_shared<Commands>();
|
||||||
setup_commands(commands);
|
setup_commands(commands);
|
||||||
return commands;
|
return commands;
|
||||||
}();
|
}();
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Boilers - 0x08
|
// Boilers - 0x08
|
||||||
{ 8, DeviceType::BOILER, "CS5800i/CS6800i/WLW176i", DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP},
|
{ 8, DeviceType::BOILER, "CS5800i/CS6800i/WLW1x6i", DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP},
|
||||||
{ 12, DeviceType::BOILER, "C1200W", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{ 12, DeviceType::BOILER, "C1200W", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{ 64, DeviceType::BOILER, "BK13/BK15/Smartline/GB1x2", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{ 64, DeviceType::BOILER, "BK13/BK15/Smartline/GB1x2", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{ 72, DeviceType::BOILER, "GB125/GB135/MC10", DeviceFlags::EMS_DEVICE_FLAG_EMS},
|
{ 72, DeviceType::BOILER, "GB125/GB135/MC10", DeviceFlags::EMS_DEVICE_FLAG_EMS},
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
{210, DeviceType::BOILER, "Cascade MC400", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{210, DeviceType::BOILER, "Cascade MC400", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{211, DeviceType::BOILER, "EasyControl Adapter", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{211, DeviceType::BOILER, "EasyControl Adapter", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{219, DeviceType::BOILER, "Greenstar HIU/Logamax kompakt WS170", DeviceFlags::EMS_DEVICE_FLAG_HIU},
|
{219, DeviceType::BOILER, "Greenstar HIU/Logamax kompakt WS170", DeviceFlags::EMS_DEVICE_FLAG_HIU},
|
||||||
{234, DeviceType::BOILER, "Logamax Plus GB122/Condense 2300", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{234, DeviceType::BOILER, "Logamax Plus GB122/Condense 2300/Junkers Cerapur GC2200W 20/25C", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|
||||||
// Controllers - 0x09 / 0x10 / 0x50
|
// Controllers - 0x09 / 0x10 / 0x50
|
||||||
{ 68, DeviceType::CONTROLLER, "BC10/RFM20", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{ 68, DeviceType::CONTROLLER, "BC10/RFM20", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
@@ -100,7 +100,7 @@
|
|||||||
{215, DeviceType::THERMOSTAT, "Comfort RF", DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
|
{215, DeviceType::THERMOSTAT, "Comfort RF", DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
|
||||||
{216, DeviceType::THERMOSTAT, "CRF200S", DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
|
{216, DeviceType::THERMOSTAT, "CRF200S", DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
|
||||||
{246, DeviceType::THERMOSTAT, "Comfort+2RF", DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
|
{246, DeviceType::THERMOSTAT, "Comfort+2RF", DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
|
||||||
{253, DeviceType::THERMOSTAT, "Rego 3000/UI800/WSW196i/BC400", DeviceFlags::EMS_DEVICE_FLAG_BC400}, // 0x10
|
{253, DeviceType::THERMOSTAT, "Rego 3000/UI800/WSW1x6i/BC400", DeviceFlags::EMS_DEVICE_FLAG_BC400}, // 0x10
|
||||||
|
|
||||||
// Thermostat - Sieger - 0x10 / 0x17
|
// Thermostat - Sieger - 0x10 / 0x17
|
||||||
{ 66, DeviceType::THERMOSTAT, "ES72/RC20", DeviceFlags::EMS_DEVICE_FLAG_RC20_N}, // 0x17 or remote
|
{ 66, DeviceType::THERMOSTAT, "ES72/RC20", DeviceFlags::EMS_DEVICE_FLAG_RC20_N}, // 0x17 or remote
|
||||||
|
|||||||
10
src/mqtt.cpp
10
src/mqtt.cpp
@@ -95,7 +95,8 @@ void Mqtt::subscribe(const uint8_t device_type, const std::string & topic, mqtt_
|
|||||||
|
|
||||||
// register in our libary with the callback function.
|
// register in our libary with the callback function.
|
||||||
// We store the original topic string without base
|
// We store the original topic string without base
|
||||||
mqtt_subfunctions_.emplace_back(device_type, std::move(topic), std::move(cb));
|
// removed std::move(topic) in 3.7.0-dev.43
|
||||||
|
mqtt_subfunctions_.emplace_back(device_type, topic, cb);
|
||||||
|
|
||||||
if (!enabled() || !connected()) {
|
if (!enabled() || !connected()) {
|
||||||
return;
|
return;
|
||||||
@@ -135,7 +136,7 @@ void Mqtt::loop() {
|
|||||||
uint32_t currentMillis = uuid::get_uptime();
|
uint32_t currentMillis = uuid::get_uptime();
|
||||||
|
|
||||||
// send heartbeat
|
// send heartbeat
|
||||||
if ((currentMillis - last_publish_heartbeat_ > publish_time_heartbeat_)) {
|
if (currentMillis - last_publish_heartbeat_ > publish_time_heartbeat_) {
|
||||||
last_publish_heartbeat_ = currentMillis;
|
last_publish_heartbeat_ = currentMillis;
|
||||||
EMSESP::system_.send_heartbeat(); // send heartbeat
|
EMSESP::system_.send_heartbeat(); // send heartbeat
|
||||||
}
|
}
|
||||||
@@ -265,7 +266,8 @@ void Mqtt::on_message(const char * topic, const uint8_t * payload, size_t len) {
|
|||||||
|
|
||||||
JsonDocument input_doc;
|
JsonDocument input_doc;
|
||||||
JsonDocument output_doc;
|
JsonDocument output_doc;
|
||||||
JsonObject input, output;
|
JsonObject input;
|
||||||
|
JsonObject output;
|
||||||
|
|
||||||
// convert payload into a json doc
|
// convert payload into a json doc
|
||||||
// if the payload doesn't not contain the key 'value' or 'data', treat the whole payload as the 'value'
|
// if the payload doesn't not contain the key 'value' or 'data', treat the whole payload as the 'value'
|
||||||
@@ -524,8 +526,6 @@ void Mqtt::on_connect() {
|
|||||||
|
|
||||||
// publish to the last will topic (see Mqtt::start() function) to say we're alive
|
// publish to the last will topic (see Mqtt::start() function) to say we're alive
|
||||||
queue_publish_retain("status", "online", false); // with retain off
|
queue_publish_retain("status", "online", false); // with retain off
|
||||||
|
|
||||||
// mqtt_publish_fails_ = 0; // reset fail count to 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Home Assistant Discovery - the main master Device called EMS-ESP
|
// Home Assistant Discovery - the main master Device called EMS-ESP
|
||||||
|
|||||||
@@ -256,7 +256,8 @@ class Mqtt {
|
|||||||
const std::string topic_; // short topic name
|
const std::string topic_; // short topic name
|
||||||
mqtt_sub_function_p mqtt_subfunction_; // can be empty
|
mqtt_sub_function_p mqtt_subfunction_; // can be empty
|
||||||
|
|
||||||
MQTTSubFunction(uint8_t device_type, const std::string && topic, mqtt_sub_function_p mqtt_subfunction)
|
// replaced &&topic with &topic in 3.7.0-dev.43, so we prevent the std:move later
|
||||||
|
MQTTSubFunction(uint8_t device_type, const std::string & topic, mqtt_sub_function_p mqtt_subfunction)
|
||||||
: device_type_(device_type)
|
: device_type_(device_type)
|
||||||
, topic_(topic)
|
, topic_(topic)
|
||||||
, mqtt_subfunction_(mqtt_subfunction) {
|
, mqtt_subfunction_(mqtt_subfunction) {
|
||||||
@@ -265,7 +266,6 @@ class Mqtt {
|
|||||||
|
|
||||||
static std::vector<MQTTSubFunction> mqtt_subfunctions_; // list of mqtt subscribe callbacks for all devices
|
static std::vector<MQTTSubFunction> mqtt_subfunctions_; // list of mqtt subscribe callbacks for all devices
|
||||||
|
|
||||||
// uint32_t last_mqtt_poll_ = 0;
|
|
||||||
uint32_t last_publish_boiler_ = 0;
|
uint32_t last_publish_boiler_ = 0;
|
||||||
uint32_t last_publish_thermostat_ = 0;
|
uint32_t last_publish_thermostat_ = 0;
|
||||||
uint32_t last_publish_solar_ = 0;
|
uint32_t last_publish_solar_ = 0;
|
||||||
|
|||||||
@@ -8,19 +8,12 @@
|
|||||||
// https://ideone.com/VocUTq
|
// https://ideone.com/VocUTq
|
||||||
//
|
//
|
||||||
// License:
|
// License:
|
||||||
// If you use this code in binary / compiled / un-commented (removing all text comments) form,
|
// This code uses the following materials.
|
||||||
// you can use it under CC0 license.
|
|
||||||
//
|
|
||||||
// But if you use this code as source code / readable text, since main content of this code is
|
|
||||||
// their notes, I recommend you to indicate notices which conform CC-BY-SA. For example,
|
|
||||||
//
|
|
||||||
// --- ---
|
|
||||||
// YOUR-CONTENT uses the following materials.
|
|
||||||
// (1) Wikipedia article [Shunting-yard algorithm](https://en.wikipedia.org/wiki/Shunting-yard_algorithm),
|
// (1) Wikipedia article [Shunting-yard algorithm](https://en.wikipedia.org/wiki/Shunting-yard_algorithm),
|
||||||
// which is released under the [Creative Commons Attribution-Share-Alike License 3.0](https://creativecommons.org/licenses/by-sa/3.0/).
|
// which is released under the [Creative Commons Attribution-Share-Alike License 3.0](https://creativecommons.org/licenses/by-sa/3.0/).
|
||||||
// (2) [Implementation notes for unary operators in Shunting-Yard algorithm](https://stackoverflow.com/a/5240912) by Austin Taylor
|
// (2) [Implementation notes for unary operators in Shunting-Yard algorithm](https://stackoverflow.com/a/5240912) by Austin Taylor
|
||||||
// which is released under the [Creative Commons Attribution-Share-Alike License 2.5](https://creativecommons.org/licenses/by-sa/2.5/).
|
// which is released under the [Creative Commons Attribution-Share-Alike License 2.5](https://creativecommons.org/licenses/by-sa/2.5/).
|
||||||
// --- ---
|
//
|
||||||
// copy from https://gist.github.com/t-mat/b9f681b7591cdae712f6
|
// copy from https://gist.github.com/t-mat/b9f681b7591cdae712f6
|
||||||
// modified MDvP, 06.2024
|
// modified MDvP, 06.2024
|
||||||
//
|
//
|
||||||
@@ -75,7 +68,7 @@ std::deque<Token> exprToTokens(const std::string & expr) {
|
|||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
const auto s = std::string(b, p);
|
const auto s = std::string(b, p);
|
||||||
tokens.push_back(Token{Token::Type::String, s, -3});
|
tokens.emplace_back(Token::Type::String, s, -3);
|
||||||
if (*p == '\0') {
|
if (*p == '\0') {
|
||||||
--p;
|
--p;
|
||||||
}
|
}
|
||||||
@@ -85,7 +78,7 @@ std::deque<Token> exprToTokens(const std::string & expr) {
|
|||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
const auto s = std::string(b, p);
|
const auto s = std::string(b, p);
|
||||||
tokens.push_back(Token{Token::Type::String, s, -2});
|
tokens.emplace_back(Token::Type::String, s, -2);
|
||||||
--p;
|
--p;
|
||||||
} else if (*p == '"') {
|
} else if (*p == '"') {
|
||||||
++p;
|
++p;
|
||||||
@@ -94,7 +87,7 @@ std::deque<Token> exprToTokens(const std::string & expr) {
|
|||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
const auto s = std::string(b, p);
|
const auto s = std::string(b, p);
|
||||||
tokens.push_back(Token{Token::Type::String, s, -3});
|
tokens.emplace_back(Token::Type::String, s, -3);
|
||||||
if (*p == '\0') {
|
if (*p == '\0') {
|
||||||
--p;
|
--p;
|
||||||
}
|
}
|
||||||
@@ -105,7 +98,7 @@ std::deque<Token> exprToTokens(const std::string & expr) {
|
|||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
const auto s = std::string(b, p);
|
const auto s = std::string(b, p);
|
||||||
tokens.push_back(Token{Token::Type::String, s, -3});
|
tokens.emplace_back(Token::Type::String, s, -3);
|
||||||
if (*p == '\0') {
|
if (*p == '\0') {
|
||||||
--p;
|
--p;
|
||||||
}
|
}
|
||||||
@@ -115,7 +108,7 @@ std::deque<Token> exprToTokens(const std::string & expr) {
|
|||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
const auto s = std::string(b, p);
|
const auto s = std::string(b, p);
|
||||||
tokens.push_back(Token{Token::Type::Number, s, -4});
|
tokens.emplace_back(Token::Type::Number, s, -4);
|
||||||
--p;
|
--p;
|
||||||
} else {
|
} else {
|
||||||
Token::Type token = Token::Type::Operator;
|
Token::Type token = Token::Type::Operator;
|
||||||
@@ -214,7 +207,7 @@ std::deque<Token> exprToTokens(const std::string & expr) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const auto s = std::string(1, c);
|
const auto s = std::string(1, c);
|
||||||
tokens.push_back(Token{token, s, precedence, rightAssociative});
|
tokens.emplace_back(token, s, precedence, rightAssociative);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +220,7 @@ std::deque<Token> shuntingYard(const std::deque<Token> & tokens) {
|
|||||||
std::vector<Token> stack;
|
std::vector<Token> stack;
|
||||||
|
|
||||||
// While there are tokens to be read:
|
// While there are tokens to be read:
|
||||||
for (auto token : tokens) {
|
for (auto const & token : tokens) {
|
||||||
// Read a token
|
// Read a token
|
||||||
switch (token.type) {
|
switch (token.type) {
|
||||||
case Token::Type::Number:
|
case Token::Type::Number:
|
||||||
@@ -302,7 +295,6 @@ std::deque<Token> shuntingYard(const std::deque<Token> & tokens) {
|
|||||||
case Token::Type::Unknown:
|
case Token::Type::Unknown:
|
||||||
default:
|
default:
|
||||||
return {};
|
return {};
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,7 +347,8 @@ std::string commands(std::string & expr, bool quotes = true) {
|
|||||||
if (strstr(cmd, "/value") == nullptr) {
|
if (strstr(cmd, "/value") == nullptr) {
|
||||||
strlcat(cmd, "/value", sizeof(cmd) - 6);
|
strlcat(cmd, "/value", sizeof(cmd) - 6);
|
||||||
}
|
}
|
||||||
JsonDocument doc_out, doc_in;
|
JsonDocument doc_out;
|
||||||
|
JsonDocument doc_in;
|
||||||
JsonObject output = doc_out.to<JsonObject>();
|
JsonObject output = doc_out.to<JsonObject>();
|
||||||
JsonObject input = doc_in.to<JsonObject>();
|
JsonObject input = doc_in.to<JsonObject>();
|
||||||
std::string cmd_s = "api/" + std::string(cmd);
|
std::string cmd_s = "api/" + std::string(cmd);
|
||||||
@@ -589,7 +582,6 @@ std::string calculate(const std::string & expr) {
|
|||||||
result += s;
|
result += s;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
// return stack.back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for multiple instances of <cond> ? <expr1> : <expr2>
|
// check for multiple instances of <cond> ? <expr1> : <expr2>
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ void RxService::add_empty(const uint8_t src, const uint8_t dest, const uint16_t
|
|||||||
// send out request to EMS bus for all devices
|
// send out request to EMS bus for all devices
|
||||||
void TxService::start() {
|
void TxService::start() {
|
||||||
// grab the bus ID and tx_mode
|
// grab the bus ID and tx_mode
|
||||||
EMSESP::webSettingsService.read([&](WebSettings & settings) {
|
EMSESP::webSettingsService.read([&](WebSettings const & settings) {
|
||||||
ems_bus_id(settings.ems_bus_id);
|
ems_bus_id(settings.ems_bus_id);
|
||||||
tx_mode(settings.tx_mode);
|
tx_mode(settings.tx_mode);
|
||||||
});
|
});
|
||||||
@@ -418,30 +418,6 @@ void TxService::send_telegram(const QueuedTxTelegram & tx_telegram) {
|
|||||||
tx_state(telegram->operation); // tx now in a wait state
|
tx_state(telegram->operation); // tx now in a wait state
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// send an array of bytes as a telegram
|
|
||||||
// we need to calculate the CRC and append it before sending
|
|
||||||
// this function is fire-and-forget. there are no checks or post-send validations
|
|
||||||
void TxService::send_telegram(const uint8_t * data, const uint8_t length) {
|
|
||||||
uint8_t telegram_raw[EMS_MAX_TELEGRAM_LENGTH];
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < length; i++) {
|
|
||||||
telegram_raw[i] = data[i];
|
|
||||||
}
|
|
||||||
telegram_raw[length] = calculate_crc(telegram_raw, length); // append CRC
|
|
||||||
|
|
||||||
tx_state(Telegram::Operation::NONE); // no post validation needed
|
|
||||||
|
|
||||||
// send the telegram to the UART Tx
|
|
||||||
uint16_t status = EMSuart::transmit(telegram_raw, length);
|
|
||||||
|
|
||||||
if (status == EMS_TX_STATUS_ERR) {
|
|
||||||
LOG_ERROR("Failed to transmit Tx via UART.");
|
|
||||||
increment_telegram_fail_count(); // another Tx fail
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void TxService::add(const uint8_t operation,
|
void TxService::add(const uint8_t operation,
|
||||||
const uint8_t dest,
|
const uint8_t dest,
|
||||||
const uint16_t type_id,
|
const uint16_t type_id,
|
||||||
@@ -547,10 +523,8 @@ void TxService::add(uint8_t operation, const uint8_t * data, const uint8_t lengt
|
|||||||
LOG_DEBUG("New Tx [#%d] telegram, length %d", tx_telegram_id_, message_length);
|
LOG_DEBUG("New Tx [#%d] telegram, length %d", tx_telegram_id_, message_length);
|
||||||
|
|
||||||
if (front && (operation != Telegram::Operation::TX_RAW || EMSESP::response_id() == 0)) {
|
if (front && (operation != Telegram::Operation::TX_RAW || EMSESP::response_id() == 0)) {
|
||||||
// tx_telegrams_.push_front(qtxt); // add to front of queue
|
|
||||||
tx_telegrams_.emplace_front(tx_telegram_id_++, std::move(telegram), false, validate_id); // add to front of queue
|
tx_telegrams_.emplace_front(tx_telegram_id_++, std::move(telegram), false, validate_id); // add to front of queue
|
||||||
} else {
|
} else {
|
||||||
// tx_telegrams_.push_back(qtxt); // add to back of queue
|
|
||||||
tx_telegrams_.emplace_back(tx_telegram_id_++, std::move(telegram), false, validate_id); // add to back of queue
|
tx_telegrams_.emplace_back(tx_telegram_id_++, std::move(telegram), false, validate_id); // add to back of queue
|
||||||
}
|
}
|
||||||
if (validate_id != 0) {
|
if (validate_id != 0) {
|
||||||
|
|||||||
@@ -285,7 +285,8 @@ class RxService : public EMSbus {
|
|||||||
const std::shared_ptr<const Telegram> telegram_;
|
const std::shared_ptr<const Telegram> telegram_;
|
||||||
|
|
||||||
~QueuedRxTelegram() = default;
|
~QueuedRxTelegram() = default;
|
||||||
QueuedRxTelegram(uint16_t id, std::shared_ptr<Telegram> && telegram)
|
// removed && from telegram in 3.7.0-dev.43
|
||||||
|
QueuedRxTelegram(uint16_t id, std::shared_ptr<Telegram> telegram)
|
||||||
: id_(id)
|
: id_(id)
|
||||||
, telegram_(std::move(telegram)) {
|
, telegram_(std::move(telegram)) {
|
||||||
}
|
}
|
||||||
@@ -414,7 +415,8 @@ class TxService : public EMSbus {
|
|||||||
const uint16_t validateid_;
|
const uint16_t validateid_;
|
||||||
|
|
||||||
~QueuedTxTelegram() = default;
|
~QueuedTxTelegram() = default;
|
||||||
QueuedTxTelegram(uint16_t id, std::shared_ptr<Telegram> && telegram, bool retry, uint16_t validateid)
|
// replaced && im std::shared_ptr<Telegram> telegram in 3.7.0-dev.43
|
||||||
|
QueuedTxTelegram(uint16_t id, std::shared_ptr<Telegram> telegram, bool retry, uint16_t validateid)
|
||||||
: id_(id)
|
: id_(id)
|
||||||
, telegram_(std::move(telegram))
|
, telegram_(std::move(telegram))
|
||||||
, retry_(retry)
|
, retry_(retry)
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define EMSESP_APP_VERSION "3.7.0-dev.42"
|
#define EMSESP_APP_VERSION "3.7.0-dev.43"
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ bool WebStatusService::exportData(JsonObject root, std::string & type) {
|
|||||||
} else if (type == "entities") {
|
} else if (type == "entities") {
|
||||||
System::extractSettings(EMSESP_CUSTOMENTITY_FILE, "Entities", root);
|
System::extractSettings(EMSESP_CUSTOMENTITY_FILE, "Entities", root);
|
||||||
} else if (type == "allvalues") {
|
} else if (type == "allvalues") {
|
||||||
root.clear(); // don't need the "type" key
|
root.clear(); // don't need the "type" key added to the output
|
||||||
allvalues(root);
|
allvalues(root);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user