diff --git a/ui/src/components/SystemControls.js b/ui/src/components/SystemControls.js index eeaab88..c94fdb3 100644 --- a/ui/src/components/SystemControls.js +++ b/ui/src/components/SystemControls.js @@ -5,6 +5,7 @@ import { Button } from 'react-bootstrap'; import { useWaterPumpAPI } from '../contexts/WaterPumpAPIContext'; import { useNotificationsSystem } from '../contexts/NotificationsContext.js'; +// TODO: convert handlers to redux actions. They should update the system status. export function SystemControlsComponent({ pouringTime, systemStatus }) { const waterPump = useWaterPumpAPI().API; const NotificationsSystem = useNotificationsSystem(); diff --git a/ui/src/contexts/WaterPumpAPIContext.js b/ui/src/contexts/WaterPumpAPIContext.js index 6f91141..aff1fac 100644 --- a/ui/src/contexts/WaterPumpAPIContext.js +++ b/ui/src/contexts/WaterPumpAPIContext.js @@ -1,6 +1,7 @@ import React from 'react'; import { useSelector } from 'react-redux'; import { CWaterPumpAPI } from '../api/CWaterPumpAPI.js'; +import WaterPumpStatusProvider from './WaterPumpStatusProvider.js'; const WaterPumpAPIContext = React.createContext(); @@ -18,7 +19,9 @@ export function WaterPumpAPIProvider({ children }) { const value = { API: apiObject, }; return ( - {children} + + {children} + ); } \ No newline at end of file diff --git a/ui/src/contexts/WaterPumpStatusProvider.js b/ui/src/contexts/WaterPumpStatusProvider.js new file mode 100644 index 0000000..915caa5 --- /dev/null +++ b/ui/src/contexts/WaterPumpStatusProvider.js @@ -0,0 +1,63 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import { updateSystemStatus } from '../store/slices/SystemStatus'; +import { useWaterPumpAPI } from './WaterPumpAPIContext'; +import { useNotificationsSystem } from './NotificationsContext'; + +const FETCH_INTERVAL = 5000; +const CHECK_INTERVAL = Math.round(FETCH_INTERVAL / 10); + +function WaterPumpStatusProviderComoponent({ children, updateStatus, systemStatus }) { + const { API } = useWaterPumpAPI(); + const NotificationsSystem = useNotificationsSystem(); + const nextFetchTime = React.useRef(0); + + // Function to fetch water pump status + const fetchStatus = React.useCallback(async () => { + const now = Date.now(); + if(now < nextFetchTime.current) return; + if(null == API) return; + + nextFetchTime.current = Number.MAX_SAFE_INTEGER; // prevent concurrent fetches + try { + const status = await API.status(); + updateStatus(status); + } catch (error) { + NotificationsSystem.alert('Error fetching system status: ' + error.message); + updateStatus(null); + } + nextFetchTime.current = Date.now() + FETCH_INTERVAL; + }, + [API, NotificationsSystem, updateStatus, nextFetchTime] + ); + + // Effect to start fetching periodically and when API changes + React.useEffect(() => { + const timer = setInterval(fetchStatus, CHECK_INTERVAL); + return () => { clearInterval(timer); }; + }, [fetchStatus]); + + // Effect to reset timer when system status changes + React.useEffect(() => { + // reset timer if not fetching + const now = Date.now(); + if(now < nextFetchTime.current) { + nextFetchTime.current = 0; + } + }, [API, systemStatus, nextFetchTime]); + + return ( + + {children} + + ); +} + +export default connect( + (state) => ({ + systemStatus: state.systemStatus + }), { + updateStatus: updateSystemStatus + + } +)(WaterPumpStatusProviderComoponent); \ No newline at end of file diff --git a/ui/src/store/slices/SystemStatus.js b/ui/src/store/slices/SystemStatus.js index 5c12a49..92abc88 100644 --- a/ui/src/store/slices/SystemStatus.js +++ b/ui/src/store/slices/SystemStatus.js @@ -14,19 +14,11 @@ function preprocessSystemStatus(systemStatus) { systemStatus.updated = Date.now(); return systemStatus; } -// TODO: Replace this with a real system status -const systemStatus = preprocessSystemStatus({ - "water threshold": 1234, - "pump": { - "running": false, - "time left": 0 - } -}); // slice for system status export const SystemStatusSlice = createSlice({ name: 'systemStatus', - initialState: systemStatus, + initialState: null, reducers: { updateSystemStatus(state, action) { return preprocessSystemStatus(action.payload);