From 0edb5c0fd9190361fe66447a5a4aac1fdd8736d7 Mon Sep 17 00:00:00 2001 From: proddy Date: Sat, 27 Jul 2024 15:04:22 +0200 Subject: [PATCH] updates to scheduler for immediate commands #1893 --- interface/src/app/main/Scheduler.tsx | 4 +- interface/src/app/main/SchedulerDialog.tsx | 341 +++++++++--------- interface/src/app/main/types.ts | 13 +- .../src/app/settings/ApplicationSettings.tsx | 2 +- mock-api/rest_server.ts | 9 + src/command.cpp | 4 +- src/helpers.cpp | 3 +- src/version.h | 2 +- src/web/WebSchedulerService.cpp | 4 +- src/web/WebSchedulerService.h | 10 +- 10 files changed, 202 insertions(+), 190 deletions(-) diff --git a/interface/src/app/main/Scheduler.tsx b/interface/src/app/main/Scheduler.tsx index e91364988..168be4b36 100644 --- a/interface/src/app/main/Scheduler.tsx +++ b/interface/src/app/main/Scheduler.tsx @@ -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 = () => { - {si.flags === 0 ? ( + {si.flags === ScheduleFlag.SCHEDULE_IMMEDIATE ? ( <> ) : si.flags < ScheduleFlag.SCHEDULE_TIMER ? ( <> diff --git a/interface/src/app/main/SchedulerDialog.tsx b/interface/src/app/main/SchedulerDialog.tsx index 529c00f7a..59a293d45 100644 --- a/interface/src/app/main/SchedulerDialog.tsx +++ b/interface/src/app/main/SchedulerDialog.tsx @@ -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(selectedItem); const [fieldErrors, setFieldErrors] = useState(); + const [scheduleType, setScheduleType] = useState(); + 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) => ( - {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)]} ); @@ -171,124 +157,116 @@ const SchedulerDialog = ({ {LL.SCHEDULE(1)} - - - { - setEditItem({ ...editItem, flags: getFlagNumber(flag) & 127 }); - }} + { + 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 } + ); + }} + > + + - - {showFlag(editItem, ScheduleFlag.SCHEDULE_MON)} - - - {showFlag(editItem, ScheduleFlag.SCHEDULE_TUE)} - - - {showFlag(editItem, ScheduleFlag.SCHEDULE_WED)} - - - {showFlag(editItem, ScheduleFlag.SCHEDULE_THU)} - - - {showFlag(editItem, ScheduleFlag.SCHEDULE_FRI)} - - - {showFlag(editItem, ScheduleFlag.SCHEDULE_SAT)} - - - {showFlag(editItem, ScheduleFlag.SCHEDULE_SUN)} - - - - - {isTimer ? ( - - ) : ( - - )} - {isOnChange ? ( - - ) : ( - - )} - {isCondition ? ( - - ) : ( - - )} - - - {editItem.flags !== 0 && ( + {LL.SCHEDULE(0)} + + + + + {LL.TIMER(0)} + + + + + {/* TODO translate */} + On Change + + + + + {/* TODO translate */} + Condition + + + + + {/* TODO translate */} + Immediate + + + + + {scheduleType === ScheduleFlag.SCHEDULE_DAY && ( + { + setEditItem({ ...editItem, flags: getFlagDOWnumber(flag) }); + }} + > + + {showDOW(editItem, ScheduleFlag.SCHEDULE_MON)} + + + {showDOW(editItem, ScheduleFlag.SCHEDULE_TUE)} + + + {showDOW(editItem, ScheduleFlag.SCHEDULE_WED)} + + + {showDOW(editItem, ScheduleFlag.SCHEDULE_THU)} + + + {showDOW(editItem, ScheduleFlag.SCHEDULE_FRI)} + + + {showDOW(editItem, ScheduleFlag.SCHEDULE_SAT)} + + + {showDOW(editItem, ScheduleFlag.SCHEDULE_SUN)} + + + )} + + {scheduleType !== ScheduleFlag.SCHEDULE_IMMEDIATE && ( <> - {isCondition || isOnChange ? ( + {scheduleType === ScheduleFlag.SCHEDULE_DAY || + scheduleType === ScheduleFlag.SCHEDULE_TIMER ? ( + <> + + {scheduleType === ScheduleFlag.SCHEDULE_TIMER && ( + + + {LL.SCHEDULER_HELP_2()} + + + )} + + ) : ( - ) : ( - <> - - {isTimer && ( - - - {LL.SCHEDULER_HELP_2()} - - - )} - )} @@ -368,6 +358,7 @@ const SchedulerDialog = ({ onChange={updateFormValue} /> + {!creating && ( @@ -397,12 +388,12 @@ const SchedulerDialog = ({ > {creating ? LL.ADD(0) : LL.UPDATE()} - {editItem.flags === 0 && editItem.cmd !== '' && ( + {scheduleType === ScheduleFlag.SCHEDULE_IMMEDIATE && editItem.cmd !== '' && ( diff --git a/interface/src/app/main/types.ts b/interface/src/app/main/types.ts index f7a6edbf5..895082137 100644 --- a/interface/src/app/main/types.ts +++ b/interface/src/app/main/types.ts @@ -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 { diff --git a/interface/src/app/settings/ApplicationSettings.tsx b/interface/src/app/settings/ApplicationSettings.tsx index 28ba474ec..fc0dfae96 100644 --- a/interface/src/app/settings/ApplicationSettings.tsx +++ b/interface/src/app/settings/ApplicationSettings.tsx @@ -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 }); diff --git a/mock-api/rest_server.ts b/mock-api/rest_server.ts index 85478d33b..16ef11f18 100644 --- a/mock-api/rest_server.ts +++ b/mock-api/rest_server.ts @@ -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' } ] }; diff --git a/src/command.cpp b/src/command.cpp index 239a6a97c..c8e230964 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -148,8 +148,8 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec const char * device_p = device_s; const char * data_p = nullptr; strlcpy(device_s, d, device_end - d + 1); - data_p = device_end + 1; - int8_t id_d = -1; + data_p = device_end + 1; + int8_t id_d = -1; uint8_t device_type = EMSdevice::device_name_2_device_type(device_p); if (device_type > EMSdevice::DeviceType::BOILER) { data_p = parse_command_string(data_p, id_d); diff --git a/src/helpers.cpp b/src/helpers.cpp index 991a6e2a1..c36860fdf 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -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') diff --git a/src/version.h b/src/version.h index 9f72e133d..64ea5a498 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.7.0-dev.27" +#define EMSESP_APP_VERSION "3.7.0-dev.28" diff --git a/src/web/WebSchedulerService.cpp b/src/web/WebSchedulerService.cpp index 37657776e..db2e6dcdf 100644 --- a/src/web/WebSchedulerService.cpp +++ b/src/web/WebSchedulerService.cpp @@ -198,7 +198,7 @@ bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) { output["onchange"] = scheduleItem.time; } else if (scheduleItem.flags == SCHEDULEFLAG_SCHEDULE_TIMER) { output["timer"] = scheduleItem.time; - } else if (scheduleItem.flags != 0){ + } else if (scheduleItem.flags != 0) { output["time"] = scheduleItem.time; } output["command"] = scheduleItem.cmd; @@ -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; } diff --git a/src/web/WebSchedulerService.h b/src/web/WebSchedulerService.h index 7e5b060fd..f599b90ad 100644 --- a/src/web/WebSchedulerService.h +++ b/src/web/WebSchedulerService.h @@ -22,10 +22,18 @@ #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 MAX_STARTUP_RETRIES 3 // retry the start-up commands x times +#define SCHEDULEFLAG_SCHEDULE_IMMEDIATE 0x84 // 7th+3rd bit for Condition + +#define MAX_STARTUP_RETRIES 3 // retry the start-up commands x times namespace emsesp {