From 870b2f4919459e3ee282c49336abf24a7a276568 Mon Sep 17 00:00:00 2001 From: ElMoribond Date: Wed, 14 Jul 2021 14:22:35 +0200 Subject: [PATCH] Improve restart from UI --- frigate/mqtt.py | 2 +- frigate/util.py | 11 +++++- web/src/AppBar.jsx | 35 ++--------------- web/src/api/mqtt.jsx | 2 +- web/src/components/Dialog.jsx | 2 +- web/src/components/DialogRestart.jsx | 59 ++++++++++++++++++++++++++++ 6 files changed, 74 insertions(+), 37 deletions(-) create mode 100644 web/src/components/DialogRestart.jsx diff --git a/frigate/mqtt.py b/frigate/mqtt.py index ee8aee6cb..d606721ed 100644 --- a/frigate/mqtt.py +++ b/frigate/mqtt.py @@ -90,7 +90,7 @@ def create_mqtt_client(config: FrigateConfig, camera_metrics): client.publish(state_topic, payload, retain=True) def on_restart_command(client, userdata, message): - restart_frigate() + restart_frigate(client, mqtt_config.topic_prefix) def on_connect(client, userdata, flags, rc): threading.current_thread().name = "mqtt" diff --git a/frigate/util.py b/frigate/util.py index dae3845f2..14821daf6 100755 --- a/frigate/util.py +++ b/frigate/util.py @@ -519,8 +519,15 @@ def clipped(obj, frame_shape): return False -def restart_frigate(): - os.kill(os.getpid(), signal.SIGTERM) +def restart_frigate(mqtt_client, topic_prefix, from_ui = 1): + + def on_publish(client,userdata,result): + time.sleep(0.67) + logger.info("Restart requested.") + os.kill(os.getpid(), signal.SIGTERM) + + mqtt_client.on_publish = on_publish + mqtt_client.publish(f"{topic_prefix}/restarted", int(from_ui)) class EventsPerSecond: diff --git a/web/src/AppBar.jsx b/web/src/AppBar.jsx index 8a8183e00..27c8c182c 100644 --- a/web/src/AppBar.jsx +++ b/web/src/AppBar.jsx @@ -6,17 +6,14 @@ import AutoAwesomeIcon from './icons/AutoAwesome'; import LightModeIcon from './icons/LightMode'; import DarkModeIcon from './icons/DarkMode'; import FrigateRestartIcon from './icons/FrigateRestart'; -import Dialog from './components/Dialog'; +import DialogRestart from './components/DialogRestart'; import { useDarkMode } from './context'; import { useCallback, useRef, useState } from 'preact/hooks'; -import { useRestart } from './api/mqtt'; export default function AppBar() { const [showMoreMenu, setShowMoreMenu] = useState(false); - const [showDialog, setShowDialog] = useState(false); - const [showDialogWait, setShowDialogWait] = useState(false); + const [showDialogRestart, setShowDialogRestart] = useState(false); const { setDarkMode } = useDarkMode(); - const { send: sendRestart } = useRestart(); const handleSelectDarkMode = useCallback( (value, label) => { @@ -36,16 +33,6 @@ export default function AppBar() { setShowMoreMenu(false); }, [setShowMoreMenu]); - const handleClickRestartDialog = useCallback(() => { - setShowDialog(false); - setShowDialogWait(true); - sendRestart(); - }, [setShowDialog]); // eslint-disable-line react-hooks/exhaustive-deps - - const handleDismissRestartDialog = useCallback(() => { - setShowDialog(false); - }, [setShowDialog]); - const handleRestart = useCallback(() => { setShowMoreMenu(false); setShowDialog(true); @@ -64,23 +51,7 @@ export default function AppBar() { ) : null}, - {showDialog ? ( - - ) : null}, - {showDialogWait ? ( - - ) : null} + ); } diff --git a/web/src/api/mqtt.jsx b/web/src/api/mqtt.jsx index b4b15d6fa..9743a7d62 100644 --- a/web/src/api/mqtt.jsx +++ b/web/src/api/mqtt.jsx @@ -124,6 +124,6 @@ export function useRestart() { value: { payload }, send, connected, - } = useMqtt('restart', 'restart'); + } = useMqtt('restarted', 'restart'); return { payload, send, connected }; } diff --git a/web/src/components/Dialog.jsx b/web/src/components/Dialog.jsx index aefc323b4..8838a4afe 100644 --- a/web/src/components/Dialog.jsx +++ b/web/src/components/Dialog.jsx @@ -28,7 +28,7 @@ export default function Dialog({ actions = [], portalRootID = 'dialogs', title, }`} >
- {title} + {title}

{text}

diff --git a/web/src/components/DialogRestart.jsx b/web/src/components/DialogRestart.jsx new file mode 100644 index 000000000..ac320df3e --- /dev/null +++ b/web/src/components/DialogRestart.jsx @@ -0,0 +1,59 @@ +import { h, Fragment } from 'preact'; +import Dialog from './Dialog'; +import { useCallback, useEffect, useState } from 'preact/hooks'; +import { useRestart } from '../api/mqtt'; + +export default function DialogRestart({ show, setShow }) { + const { payload: detectRestarted = null, send: sendRestart } = useRestart(); + const [dialogTitle, setDialogTitle] = useState('Restart in progress'); + + useEffect(() => { + if (detectRestarted != null && Number.isInteger(detectRestarted)) { + if (!detectRestarted) + setDialogTitle('Server-initiated startup'); + setShow(false); + } + }, [detectRestarted]); // eslint-disable-line react-hooks/exhaustive-deps + + const waitPlease = async () => { + const delay = ms => new Promise(res => setTimeout(res, ms)); + await delay(3456); + /* eslint-disable no-constant-condition */ + while (true) { + try { + const response = await fetch('/api/config', { method: 'GET' }); + if (await response.status === 200) + window.location.reload(); + } + catch (e) {} + await delay(987); + } + }; + + const handleClick = useCallback(() => { + sendRestart(); + setShow(false); + waitPlease(); + }, [show]); // eslint-disable-line react-hooks/exhaustive-deps + + const handleDismiss = useCallback(() => { + setShow(false); + }, [show]); // eslint-disable-line react-hooks/exhaustive-deps + + return ( + + {show ? ( + + ) : detectRestarted != null && ( + + )} + + ); +}