From 36ba4efd9f2a154c9d61b40574cf5250d80963b8 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Mon, 9 Sep 2024 21:43:57 +0200 Subject: [PATCH] Update general device information --- central_backend/src/energy/energy_actor.rs | 2 +- central_backend/src/server/servers.rs | 4 ++ .../src/server/web_api/devices_controller.rs | 11 +++++ central_frontend/src/api/DeviceApi.ts | 12 +++++ .../routes/DeviceRoute/DeviceInfoProperty.tsx | 15 +++++++ .../src/routes/DeviceRoute/DeviceRoute.tsx | 27 +++++++++--- .../routes/DeviceRoute/DeviceStateBlock.tsx | 44 +++++++++++++++++++ .../routes/DeviceRoute/GeneralDeviceInfo.tsx | 24 +--------- 8 files changed, 109 insertions(+), 30 deletions(-) create mode 100644 central_frontend/src/routes/DeviceRoute/DeviceInfoProperty.tsx create mode 100644 central_frontend/src/routes/DeviceRoute/DeviceStateBlock.tsx diff --git a/central_backend/src/energy/energy_actor.rs b/central_backend/src/energy/energy_actor.rs index 7528601..a6b7183 100644 --- a/central_backend/src/energy/energy_actor.rs +++ b/central_backend/src/energy/energy_actor.rs @@ -301,7 +301,7 @@ impl Handler for EnergyActor { #[derive(serde::Serialize)] pub struct ResDevState { - id: DeviceId, + pub id: DeviceId, last_ping: u64, online: bool, } diff --git a/central_backend/src/server/servers.rs b/central_backend/src/server/servers.rs index 1dd4b4d..2e331f8 100644 --- a/central_backend/src/server/servers.rs +++ b/central_backend/src/server/servers.rs @@ -152,6 +152,10 @@ pub async fn secure_server(energy_actor: EnergyActorAddr) -> anyhow::Result<()> "/web_api/device/{id}", web::get().to(devices_controller::get_single), ) + .route( + "/web_api/device/{id}/state", + web::get().to(devices_controller::state_single), + ) .route( "/web_api/device/{id}/validate", web::post().to(devices_controller::validate_device), diff --git a/central_backend/src/server/web_api/devices_controller.rs b/central_backend/src/server/web_api/devices_controller.rs index cb657c5..2131538 100644 --- a/central_backend/src/server/web_api/devices_controller.rs +++ b/central_backend/src/server/web_api/devices_controller.rs @@ -52,6 +52,17 @@ pub async fn get_single(actor: WebEnergyActor, id: web::Path) -> H Ok(HttpResponse::Ok().json(dev)) } +/// Get a single device state +pub async fn state_single(actor: WebEnergyActor, id: web::Path) -> HttpResult { + let states = actor.send(energy_actor::GetDevicesState).await?; + + let Some(state) = states.into_iter().find(|s| s.id == id.id) else { + return Ok(HttpResponse::NotFound().body("Requested device not found!")); + }; + + Ok(HttpResponse::Ok().json(state)) +} + /// Validate a device pub async fn validate_device(actor: WebEnergyActor, id: web::Path) -> HttpResult { actor diff --git a/central_frontend/src/api/DeviceApi.ts b/central_frontend/src/api/DeviceApi.ts index d019767..a63f811 100644 --- a/central_frontend/src/api/DeviceApi.ts +++ b/central_frontend/src/api/DeviceApi.ts @@ -120,6 +120,18 @@ export class DeviceApi { ).data; } + /** + * Get the current state of a single device + */ + static async GetSingleState(id: string): Promise { + return ( + await APIClient.exec({ + uri: `/device/${encodeURIComponent(id)}/state`, + method: "GET", + }) + ).data; + } + /** * Update a device general information */ diff --git a/central_frontend/src/routes/DeviceRoute/DeviceInfoProperty.tsx b/central_frontend/src/routes/DeviceRoute/DeviceInfoProperty.tsx new file mode 100644 index 0000000..cffd8a7 --- /dev/null +++ b/central_frontend/src/routes/DeviceRoute/DeviceInfoProperty.tsx @@ -0,0 +1,15 @@ +import { TableCell, TableRow } from "@mui/material"; + +export function DeviceInfoProperty(p: { + icon?: React.ReactElement; + label: string; + value: string; + color?: string; +}): React.ReactElement { + return ( + + {p.label} + {p.value} + + ); +} diff --git a/central_frontend/src/routes/DeviceRoute/DeviceRoute.tsx b/central_frontend/src/routes/DeviceRoute/DeviceRoute.tsx index 3e9ca9a..ff5977e 100644 --- a/central_frontend/src/routes/DeviceRoute/DeviceRoute.tsx +++ b/central_frontend/src/routes/DeviceRoute/DeviceRoute.tsx @@ -1,5 +1,7 @@ import DeleteIcon from "@mui/icons-material/Delete"; +import RefreshIcon from "@mui/icons-material/Refresh"; import { IconButton, Tooltip } from "@mui/material"; +import Grid from "@mui/material/Grid2"; import React from "react"; import { useNavigate, useParams } from "react-router-dom"; import { Device, DeviceApi } from "../../api/DeviceApi"; @@ -9,9 +11,9 @@ import { useLoadingMessage } from "../../hooks/context_providers/LoadingMessageP import { useSnackbar } from "../../hooks/context_providers/SnackbarProvider"; import { AsyncWidget } from "../../widgets/AsyncWidget"; import { SolarEnergyRouteContainer } from "../../widgets/SolarEnergyRouteContainer"; -import { GeneralDeviceInfo } from "./GeneralDeviceInfo"; import { DeviceRelays } from "./DeviceRelays"; -import Grid from "@mui/material/Grid2"; +import { DeviceStateBlock } from "./DeviceStateBlock"; +import { GeneralDeviceInfo } from "./GeneralDeviceInfo"; export function DeviceRoute(): React.ReactElement { const { id } = useParams(); @@ -70,15 +72,23 @@ function DeviceRouteInner(p: { loadingMessage.hide(); } }; + return ( - deleteDevice(p.device)}> - - - + + + + + + + + deleteDevice(p.device)}> + + + + } > @@ -88,6 +98,9 @@ function DeviceRouteInner(p: { + + + ); diff --git a/central_frontend/src/routes/DeviceRoute/DeviceStateBlock.tsx b/central_frontend/src/routes/DeviceRoute/DeviceStateBlock.tsx new file mode 100644 index 0000000..726c0e3 --- /dev/null +++ b/central_frontend/src/routes/DeviceRoute/DeviceStateBlock.tsx @@ -0,0 +1,44 @@ +import React from "react"; +import { Device, DeviceApi, DeviceState } from "../../api/DeviceApi"; +import { AsyncWidget } from "../../widgets/AsyncWidget"; +import { DeviceRouteCard } from "./DeviceRouteCard"; +import { Table, TableBody } from "@mui/material"; +import { DeviceInfoProperty } from "./DeviceInfoProperty"; +import { timeDiff } from "../../widgets/TimeWidget"; + +export function DeviceStateBlock(p: { device: Device }): React.ReactElement { + const [state, setState] = React.useState(); + + const load = async () => { + setState(await DeviceApi.GetSingleState(p.device.id)); + }; + + return ( + + } + /> + + ); +} + +function DeviceStateInner(p: { state: DeviceState }): React.ReactElement { + return ( + + + + + +
+ ); +} diff --git a/central_frontend/src/routes/DeviceRoute/GeneralDeviceInfo.tsx b/central_frontend/src/routes/DeviceRoute/GeneralDeviceInfo.tsx index 7c1ef6e..1a581ca 100644 --- a/central_frontend/src/routes/DeviceRoute/GeneralDeviceInfo.tsx +++ b/central_frontend/src/routes/DeviceRoute/GeneralDeviceInfo.tsx @@ -1,16 +1,10 @@ import EditIcon from "@mui/icons-material/Edit"; -import { - IconButton, - Table, - TableBody, - TableCell, - TableRow, - Tooltip, -} from "@mui/material"; +import { IconButton, Table, TableBody, Tooltip } from "@mui/material"; import React from "react"; import { Device } from "../../api/DeviceApi"; import { EditDeviceMetadataDialog } from "../../dialogs/EditDeviceMetadataDialog"; import { formatDate } from "../../widgets/TimeWidget"; +import { DeviceInfoProperty } from "./DeviceInfoProperty"; import { DeviceRouteCard } from "./DeviceRouteCard"; export function GeneralDeviceInfo(p: { @@ -78,17 +72,3 @@ export function GeneralDeviceInfo(p: { ); } - -function DeviceInfoProperty(p: { - icon?: React.ReactElement; - label: string; - value: string; - color?: string; -}): React.ReactElement { - return ( - - {p.label} - {p.value} - - ); -}