updates to scheduler for immediate commands #1893

This commit is contained in:
proddy
2024-07-27 15:04:22 +02:00
parent 008e2f0c7a
commit 0edb5c0fd9
10 changed files with 202 additions and 190 deletions

View File

@@ -200,7 +200,7 @@ const Scheduler: FC = () => {
id: Math.floor(Math.random() * (Math.floor(200) - 100) + 100),
active: false,
deleted: false,
flags: 0,
flags: ScheduleFlag.SCHEDULE_DAY,
time: '',
cmd: '',
value: '',
@@ -283,7 +283,7 @@ const Scheduler: FC = () => {
<Cell stiff>
<Stack spacing={0.5} direction="row">
<Divider orientation="vertical" flexItem />
{si.flags === 0 ? (
{si.flags === ScheduleFlag.SCHEDULE_IMMEDIATE ? (
<></>
) : si.flags < ScheduleFlag.SCHEDULE_TIMER ? (
<>

View File

@@ -3,6 +3,7 @@ import { useEffect, useState } from 'react';
import AddIcon from '@mui/icons-material/Add';
import CancelIcon from '@mui/icons-material/Cancel';
import DoneIcon from '@mui/icons-material/Done';
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
import {
Box,
@@ -53,12 +54,23 @@ const SchedulerDialog = ({
const [editItem, setEditItem] = useState<ScheduleItem>(selectedItem);
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
const [scheduleType, setScheduleType] = useState<ScheduleFlag>();
const updateFormValue = updateValue(setEditItem);
useEffect(() => {
if (open) {
setFieldErrors(undefined);
setEditItem(selectedItem);
// set the flags based on type when page is loaded...
// 0-127 is day schedule
// 128 is timer
// 129 is on change
// 130 is on condition
// 132 is immediate
setScheduleType(
selectedItem.flags < 128 ? ScheduleFlag.SCHEDULE_DAY : selectedItem.flags
);
}
}, [open, selectedItem]);
@@ -88,15 +100,15 @@ const SchedulerDialog = ({
onSave(editItem);
};
const getFlagNumber = (newFlag: string[]) => {
const getFlagDOWnumber = (newFlag: string[]) => {
let new_flag = 0;
for (const entry of newFlag) {
new_flag |= Number(entry);
}
return new_flag;
return new_flag & 127;
};
const getFlagString = (f: number) => {
const getFlagDOWstring = (f: number) => {
const new_flags: string[] = [];
if ((f & 129) === 1) {
new_flags.push('1');
@@ -119,42 +131,16 @@ const SchedulerDialog = ({
if ((f & 64) === 64) {
new_flags.push('64');
}
if ((f & 131) === 128) {
new_flags.push('128');
}
if ((f & 131) === 129) {
new_flags.push('129');
}
if ((f & 131) === 130) {
new_flags.push('130');
}
return new_flags;
};
const isTimer = editItem.flags === ScheduleFlag.SCHEDULE_TIMER;
const isCondition = editItem.flags === ScheduleFlag.SCHEDULE_CONDITION;
const isOnChange = editItem.flags === ScheduleFlag.SCHEDULE_ONCHANGE;
const showFlag = (si: ScheduleItem, flag: number) => (
const showDOW = (si: ScheduleItem, flag: number) => (
<Typography
variant="button"
sx={{ fontSize: 10 }}
color={
(isOnChange && flag !== ScheduleFlag.SCHEDULE_ONCHANGE) ||
(isCondition && flag !== ScheduleFlag.SCHEDULE_CONDITION)
? 'grey'
: (si.flags & flag) === flag
? 'primary'
: 'grey'
}
color={(si.flags & flag) === flag ? 'primary' : 'grey'}
>
{flag === ScheduleFlag.SCHEDULE_TIMER
? LL.TIMER(0)
: flag === ScheduleFlag.SCHEDULE_ONCHANGE
? 'On Change'
: flag === ScheduleFlag.SCHEDULE_CONDITION
? 'Condition'
: dow[Math.log(flag) / Math.log(2)]}
{dow[Math.log(flag) / Math.log(2)]}
</Typography>
);
@@ -171,124 +157,116 @@ const SchedulerDialog = ({
{LL.SCHEDULE(1)}
</DialogTitle>
<DialogContent dividers>
<Box display="flex" flexWrap="wrap" mb={1}>
<Box>
<ToggleButtonGroup
size="small"
color="secondary"
value={getFlagString(editItem.flags)}
value={scheduleType}
exclusive
disabled={!creating}
onChange={(_event, flag: ScheduleFlag) => {
setScheduleType(flag);
// wipe the time field when changing the schedule type
setEditItem({ ...editItem, time: '' });
// set the flags based on type
// 0-127 is day schedule
// 128 is timer
// 129 is on change
// 130 is on condition
// 132 is immediate
setEditItem(
flag === ScheduleFlag.SCHEDULE_DAY
? { ...editItem, flags: 0 }
: { ...editItem, flags: flag }
);
}}
>
<ToggleButton value={ScheduleFlag.SCHEDULE_DAY}>
<Typography
sx={{ fontSize: 10 }}
color={scheduleType === ScheduleFlag.SCHEDULE_DAY ? 'primary' : 'grey'}
>
{LL.SCHEDULE(0)}
</Typography>
</ToggleButton>
<ToggleButton value={ScheduleFlag.SCHEDULE_TIMER}>
<Typography
sx={{ fontSize: 10 }}
color={
scheduleType === ScheduleFlag.SCHEDULE_TIMER ? 'primary' : 'grey'
}
>
{LL.TIMER(0)}
</Typography>
</ToggleButton>
<ToggleButton value={ScheduleFlag.SCHEDULE_ONCHANGE}>
<Typography
sx={{ fontSize: 10 }}
color={
scheduleType === ScheduleFlag.SCHEDULE_ONCHANGE ? 'primary' : 'grey'
}
>
{/* TODO translate */}
On Change
</Typography>
</ToggleButton>
<ToggleButton value={ScheduleFlag.SCHEDULE_CONDITION}>
<Typography
sx={{ fontSize: 10 }}
color={
scheduleType === ScheduleFlag.SCHEDULE_CONDITION ? 'primary' : 'grey'
}
>
{/* TODO translate */}
Condition
</Typography>
</ToggleButton>
<ToggleButton value={ScheduleFlag.SCHEDULE_IMMEDIATE}>
<Typography
sx={{ fontSize: 10 }}
color={
scheduleType === ScheduleFlag.SCHEDULE_IMMEDIATE ? 'primary' : 'grey'
}
>
{/* TODO translate */}
Immediate
</Typography>
</ToggleButton>
</ToggleButtonGroup>
{scheduleType === ScheduleFlag.SCHEDULE_DAY && (
<ToggleButtonGroup
size="small"
color="secondary"
value={getFlagDOWstring(editItem.flags)}
onChange={(_event, flag: string[]) => {
setEditItem({ ...editItem, flags: getFlagNumber(flag) & 127 });
setEditItem({ ...editItem, flags: getFlagDOWnumber(flag) });
}}
>
<ToggleButton value="2">
{showFlag(editItem, ScheduleFlag.SCHEDULE_MON)}
{showDOW(editItem, ScheduleFlag.SCHEDULE_MON)}
</ToggleButton>
<ToggleButton value="4">
{showFlag(editItem, ScheduleFlag.SCHEDULE_TUE)}
{showDOW(editItem, ScheduleFlag.SCHEDULE_TUE)}
</ToggleButton>
<ToggleButton value="8">
{showFlag(editItem, ScheduleFlag.SCHEDULE_WED)}
{showDOW(editItem, ScheduleFlag.SCHEDULE_WED)}
</ToggleButton>
<ToggleButton value="16">
{showFlag(editItem, ScheduleFlag.SCHEDULE_THU)}
{showDOW(editItem, ScheduleFlag.SCHEDULE_THU)}
</ToggleButton>
<ToggleButton value="32">
{showFlag(editItem, ScheduleFlag.SCHEDULE_FRI)}
{showDOW(editItem, ScheduleFlag.SCHEDULE_FRI)}
</ToggleButton>
<ToggleButton value="64">
{showFlag(editItem, ScheduleFlag.SCHEDULE_SAT)}
{showDOW(editItem, ScheduleFlag.SCHEDULE_SAT)}
</ToggleButton>
<ToggleButton value="1">
{showFlag(editItem, ScheduleFlag.SCHEDULE_SUN)}
{showDOW(editItem, ScheduleFlag.SCHEDULE_SUN)}
</ToggleButton>
</ToggleButtonGroup>
</Box>
<Box sx={{ '& button, & a, & .MuiCard-root': { ml: 1 } }}>
{isTimer ? (
<Button
size="large"
sx={{ bgcolor: '#334f65' }}
variant="contained"
onClick={() => {
setEditItem({ ...editItem, flags: ScheduleFlag.SCHEDULE_TIMER });
}}
>
{showFlag(editItem, ScheduleFlag.SCHEDULE_TIMER)}
</Button>
) : (
<Button
size="large"
variant="outlined"
onClick={() => {
setEditItem({
...editItem,
flags: ScheduleFlag.SCHEDULE_TIMER
});
}}
>
{showFlag(editItem, ScheduleFlag.SCHEDULE_TIMER)}
</Button>
)}
{isOnChange ? (
<Button
size="large"
sx={{ bgcolor: '#334f65' }}
variant="contained"
onClick={() => {
setEditItem({
...editItem,
flags: ScheduleFlag.SCHEDULE_ONCHANGE
});
}}
>
{showFlag(editItem, ScheduleFlag.SCHEDULE_ONCHANGE)}
</Button>
) : (
<Button
size="large"
variant="outlined"
onClick={() => {
setEditItem({
...editItem,
flags: ScheduleFlag.SCHEDULE_ONCHANGE
});
}}
>
{showFlag(editItem, ScheduleFlag.SCHEDULE_ONCHANGE)}
</Button>
)}
{isCondition ? (
<Button
size="large"
sx={{ bgcolor: '#334f65' }}
variant="contained"
onClick={() => {
setEditItem({
...editItem,
flags: ScheduleFlag.SCHEDULE_CONDITION
});
}}
>
{showFlag(editItem, ScheduleFlag.SCHEDULE_CONDITION)}
</Button>
) : (
<Button
size="large"
variant="outlined"
onClick={() => {
setEditItem({
...editItem,
flags: ScheduleFlag.SCHEDULE_CONDITION
});
}}
>
{showFlag(editItem, ScheduleFlag.SCHEDULE_CONDITION)}
</Button>
)}
</Box>
</Box>
{editItem.flags !== 0 && (
{scheduleType !== ScheduleFlag.SCHEDULE_IMMEDIATE && (
<>
<Grid container>
<BlockFormControlLabel
@@ -303,10 +281,42 @@ const SchedulerDialog = ({
/>
</Grid>
<Grid container>
{isCondition || isOnChange ? (
{scheduleType === ScheduleFlag.SCHEDULE_DAY ||
scheduleType === ScheduleFlag.SCHEDULE_TIMER ? (
<>
<TextField
name="time"
label={isCondition ? 'Condition' : 'On Change Value'}
type="time"
label={
scheduleType === ScheduleFlag.SCHEDULE_TIMER
? LL.TIMER(1)
: LL.TIME(1)
}
value={
editItem.time == '' ? (editItem.time = '00:00') : editItem.time
}
margin="normal"
onChange={updateFormValue}
/>
{scheduleType === ScheduleFlag.SCHEDULE_TIMER && (
<Box color="warning.main" ml={2} mt={4}>
<Typography variant="body2">
{LL.SCHEDULER_HELP_2()}
</Typography>
</Box>
)}
</>
) : (
<TextField
name="time"
label={
// TODO translate
scheduleType === ScheduleFlag.SCHEDULE_CONDITION
? 'Condition'
: scheduleType === ScheduleFlag.SCHEDULE_ONCHANGE
? 'On Change Value'
: 'Immediate'
}
multiline
fullWidth
value={
@@ -315,26 +325,6 @@ const SchedulerDialog = ({
margin="normal"
onChange={updateFormValue}
/>
) : (
<>
<TextField
name="time"
type="time"
label={isTimer ? LL.TIMER(1) : LL.TIME(1)}
value={
editItem.time == '' ? (editItem.time = '00:00') : editItem.time
}
margin="normal"
onChange={updateFormValue}
/>
{isTimer && (
<Box color="warning.main" ml={2} mt={4}>
<Typography variant="body2">
{LL.SCHEDULER_HELP_2()}
</Typography>
</Box>
)}
</>
)}
</Grid>
</>
@@ -368,6 +358,7 @@ const SchedulerDialog = ({
onChange={updateFormValue}
/>
</DialogContent>
<DialogActions>
{!creating && (
<Box flexGrow={1}>
@@ -397,12 +388,12 @@ const SchedulerDialog = ({
>
{creating ? LL.ADD(0) : LL.UPDATE()}
</Button>
{editItem.flags === 0 && editItem.cmd !== '' && (
{scheduleType === ScheduleFlag.SCHEDULE_IMMEDIATE && editItem.cmd !== '' && (
<Button
startIcon={<DoneIcon />}
startIcon={<PlayArrowIcon />}
variant="outlined"
onClick={saveandactivate}
color="warning"
color="success"
>
{LL.EXECUTE()}
</Button>

View File

@@ -298,12 +298,12 @@ export enum DeviceEntityMask {
export interface ScheduleItem {
id: number; // unique index
active: boolean;
deleted?: boolean; // optional
deleted?: boolean;
flags: number;
time: string;
cmd: string;
value: string;
name: string; // optional
name: string; // is optional
o_id?: number;
o_active?: boolean;
o_deleted?: boolean;
@@ -344,9 +344,12 @@ export enum ScheduleFlag {
SCHEDULE_THU = 16,
SCHEDULE_FRI = 32,
SCHEDULE_SAT = 64,
SCHEDULE_TIMER = 128,
SCHEDULE_ONCHANGE = 129,
SCHEDULE_CONDITION = 130
// types...
SCHEDULE_DAY = 0, // no bits set
SCHEDULE_TIMER = 128, // bit 8
SCHEDULE_ONCHANGE = 129, // bit 1
SCHEDULE_CONDITION = 130, // bit 2
SCHEDULE_IMMEDIATE = 132 // bit 3
}
export interface EntityItem {

View File

@@ -50,7 +50,7 @@ export function boardProfileSelectItems() {
}
const ApplicationSettings: FC = () => {
const { data: hardwareData, error } = useRequest(SystemApi.readHardwareStatus, {
const { data: hardwareData } = useRequest(SystemApi.readHardwareStatus, {
force: true
});

View File

@@ -3946,6 +3946,15 @@ let emsesp_schedule = {
cmd: 'boiler/selflowtemp',
value: '(custom/setpoint - boiler/outdoortemp) * 2.8 + 3',
name: 'heatingcurve'
},
{
id: 7,
active: false,
flags: 132,
time: '',
cmd: 'system/message',
value: '\"hello world\"',
name: 'immediate'
}
]
};

View File

@@ -411,7 +411,8 @@ uint32_t Helpers::hextoint(const char * hex) {
// get current character then increment
char byte = *hex++;
// transform hex character to the 4bit equivalent number, using the ascii table indexes
if (byte == ' ') byte = *hex++; // skip spaces
if (byte == ' ')
byte = *hex++; // skip spaces
if (byte >= '0' && byte <= '9')
byte = byte - '0';
else if (byte >= 'a' && byte <= 'f')

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.7.0-dev.27"
#define EMSESP_APP_VERSION "3.7.0-dev.28"

View File

@@ -489,7 +489,7 @@ void WebSchedulerService::loop() {
}
for (ScheduleItem & scheduleItem : *scheduleItems_) {
if (scheduleItem.active && scheduleItem.flags == 0) {
if (scheduleItem.active && scheduleItem.flags == SCHEDULEFLAG_SCHEDULE_IMMEDIATE) {
command(scheduleItem.name.c_str(), scheduleItem.cmd, compute(scheduleItem.value));
scheduleItem.active = false;
}

View File

@@ -22,9 +22,17 @@
#define EMSESP_SCHEDULER_FILE "/config/emsespScheduler.json"
#define EMSESP_SCHEDULER_SERVICE_PATH "/rest/schedule" // GET and POST
// bit flags for the schedule items. Matches those in interface/src/app/main/SchedulerDialog.tsx
// 0-127 (0->0x7F) is day schedule
// 128/0x80 is timer
// 129/0x81 is on change
// 130/0x82 is on condition
// 132/0x84 is immediate
#define SCHEDULEFLAG_SCHEDULE_TIMER 0x80 // 7th bit for Timer
#define SCHEDULEFLAG_SCHEDULE_ONCHANGE 0x81 // 7th+1st bit for OnChange
#define SCHEDULEFLAG_SCHEDULE_CONDITION 0x82 // 7th+2nd bit for Condition
#define SCHEDULEFLAG_SCHEDULE_IMMEDIATE 0x84 // 7th+3rd bit for Condition
#define MAX_STARTUP_RETRIES 3 // retry the start-up commands x times
namespace emsesp {