Display relays status
This commit is contained in:
		| @@ -360,3 +360,34 @@ impl Handler<GetDevicesState> for EnergyActor { | ||||
|             .collect() | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(serde::Serialize)] | ||||
| pub struct ResRelayState { | ||||
|     pub id: DeviceRelayID, | ||||
|     on: bool, | ||||
|     r#for: usize, | ||||
| } | ||||
|  | ||||
| /// Get the state of all relays | ||||
| #[derive(Message)] | ||||
| #[rtype(result = "Vec<ResRelayState>")] | ||||
| pub struct GetAllRelaysState; | ||||
|  | ||||
| impl Handler<GetAllRelaysState> for EnergyActor { | ||||
|     type Result = Vec<ResRelayState>; | ||||
|  | ||||
|     fn handle(&mut self, _msg: GetAllRelaysState, _ctx: &mut Context<Self>) -> Self::Result { | ||||
|         let mut list = vec![]; | ||||
|  | ||||
|         for d in &self.devices.relays_list() { | ||||
|             let state = self.engine.relay_state(d.id); | ||||
|             list.push(ResRelayState { | ||||
|                 id: d.id, | ||||
|                 on: state.is_on(), | ||||
|                 r#for: state.state_for(), | ||||
|             }) | ||||
|         } | ||||
|  | ||||
|         list | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -39,6 +39,10 @@ impl RelayState { | ||||
|     fn is_off(&self) -> bool { | ||||
|         !self.on | ||||
|     } | ||||
|  | ||||
|     pub fn state_for(&self) -> usize { | ||||
|         (time_secs() - self.since as u64) as usize | ||||
|     } | ||||
| } | ||||
|  | ||||
| type RelaysState = HashMap<DeviceRelayID, RelayState>; | ||||
|   | ||||
| @@ -185,6 +185,10 @@ pub async fn secure_server(energy_actor: EnergyActorAddr) -> anyhow::Result<()> | ||||
|                 "/web_api/relay/{id}", | ||||
|                 web::delete().to(relays_controller::delete), | ||||
|             ) | ||||
|             .route( | ||||
|                 "/web_api/relays/status", | ||||
|                 web::get().to(relays_controller::get_status_all), | ||||
|             ) | ||||
|             // Devices API | ||||
|             .route( | ||||
|                 "/devices_api/utils/time", | ||||
|   | ||||
| @@ -93,3 +93,10 @@ pub async fn delete(actor: WebEnergyActor, path: web::Path<RelayIDInPath>) -> Ht | ||||
|  | ||||
|     Ok(HttpResponse::Accepted().finish()) | ||||
| } | ||||
|  | ||||
| /// Get the status of all relays | ||||
| pub async fn get_status_all(actor: WebEnergyActor) -> HttpResult { | ||||
|     let list = actor.send(energy_actor::GetAllRelaysState).await?; | ||||
|  | ||||
|     Ok(HttpResponse::Ok().json(list)) | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,14 @@ | ||||
| import { APIClient } from "./ApiClient"; | ||||
| import { Device, DeviceRelay } from "./DeviceApi"; | ||||
|  | ||||
| export interface RelayStatus { | ||||
|   id: string; | ||||
|   on: boolean; | ||||
|   for: number; | ||||
| } | ||||
|  | ||||
| export type RelaysStatus = Map<string, RelayStatus>; | ||||
|  | ||||
| export class RelayApi { | ||||
|   /** | ||||
|    * Get the full list of relays | ||||
| @@ -49,4 +57,22 @@ export class RelayApi { | ||||
|       uri: `/relay/${relay.id}`, | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Get the status of all relays | ||||
|    */ | ||||
|   static async GetRelaysStatus(): Promise<RelaysStatus> { | ||||
|     const data: any[] = ( | ||||
|       await APIClient.exec({ | ||||
|         method: "GET", | ||||
|         uri: `/relays/status`, | ||||
|       }) | ||||
|     ).data; | ||||
|  | ||||
|     const map = new Map(); | ||||
|     for (let r of data) { | ||||
|       map.set(r.id, r); | ||||
|     } | ||||
|     return map; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -12,17 +12,20 @@ import { | ||||
| } from "@mui/material"; | ||||
| import React from "react"; | ||||
| import { DeviceRelay } from "../api/DeviceApi"; | ||||
| import { RelayApi } from "../api/RelayApi"; | ||||
| import { RelayApi, RelaysStatus } from "../api/RelayApi"; | ||||
| import { AsyncWidget } from "../widgets/AsyncWidget"; | ||||
| import { SolarEnergyRouteContainer } from "../widgets/SolarEnergyRouteContainer"; | ||||
| import { TimeWidget } from "../widgets/TimeWidget"; | ||||
|  | ||||
| export function RelaysListRoute(): React.ReactElement { | ||||
|   const loadKey = React.useRef(1); | ||||
|  | ||||
|   const [list, setList] = React.useState<DeviceRelay[] | undefined>(); | ||||
|   const [status, setStatus] = React.useState<RelaysStatus | undefined>(); | ||||
|  | ||||
|   const load = async () => { | ||||
|     setList(await RelayApi.GetList()); | ||||
|     setStatus(await RelayApi.GetRelaysStatus()); | ||||
|  | ||||
|     list?.sort((a, b) => b.priority - a.priority); | ||||
|   }; | ||||
| @@ -48,7 +51,9 @@ export function RelaysListRoute(): React.ReactElement { | ||||
|         ready={!!list} | ||||
|         errMsg="Failed to load the list of relays!" | ||||
|         load={load} | ||||
|         build={() => <RelaysList onReload={reload} list={list!} />} | ||||
|         build={() => ( | ||||
|           <RelaysList onReload={reload} list={list!} status={status!} /> | ||||
|         )} | ||||
|       /> | ||||
|     </SolarEnergyRouteContainer> | ||||
|   ); | ||||
| @@ -56,6 +61,7 @@ export function RelaysListRoute(): React.ReactElement { | ||||
|  | ||||
| function RelaysList(p: { | ||||
|   list: DeviceRelay[]; | ||||
|   status: RelaysStatus; | ||||
|   onReload: () => void; | ||||
| }): React.ReactElement { | ||||
|   return ( | ||||
| @@ -78,15 +84,18 @@ function RelaysList(p: { | ||||
|             > | ||||
|               <TableCell>{row.name}</TableCell> | ||||
|               <TableCell> | ||||
|                 {row.enabled ? ( | ||||
|                   <span style={{ color: "green" }}>YES</span> | ||||
|                 ) : ( | ||||
|                   <span style={{ color: "red" }}>NO</span> | ||||
|                 )} | ||||
|                 <BoolText val={row.enabled} positive="YES" negative="NO" /> | ||||
|               </TableCell> | ||||
|               <TableCell>{row.priority}</TableCell> | ||||
|               <TableCell>{row.consumption}</TableCell> | ||||
|               <TableCell>TODO</TableCell> | ||||
|               <TableCell> | ||||
|                 <BoolText | ||||
|                   val={p.status.get(row.id)!.on} | ||||
|                   positive="ON" | ||||
|                   negative="OFF" | ||||
|                 />{" "} | ||||
|                 for <TimeWidget diff time={p.status.get(row.id)!.for} /> | ||||
|               </TableCell> | ||||
|             </TableRow> | ||||
|           ))} | ||||
|         </TableBody> | ||||
| @@ -94,3 +103,15 @@ function RelaysList(p: { | ||||
|     </TableContainer> | ||||
|   ); | ||||
| } | ||||
|  | ||||
| function BoolText(p: { | ||||
|   val: boolean; | ||||
|   positive: string; | ||||
|   negative: string; | ||||
| }): React.ReactElement { | ||||
|   return p.val ? ( | ||||
|     <span style={{ color: "green" }}>{p.positive}</span> | ||||
|   ) : ( | ||||
|     <span style={{ color: "red" }}>{p.negative}</span> | ||||
|   ); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user