import {useState, useRef, useEffect} from 'react' import useMqtt from '../lib/useMqtt' import 'bootstrap/dist/css/bootstrap.min.css'; import {Accordion, Button, Card, Col, Row} from "react-bootstrap"; export default function Home() { const [currentDevices, setCurrentDevices] = useState([]) const addDevice = (message) => { console.log("adding " + message.payload.type) setCurrentDevices((currentDevices) => { const device = message.payload device.topic = message.topic let newDevices = [] let found = false; for(let i = 0; i < currentDevices.length; i++) { let oldDevice = currentDevices[i] if(oldDevice) { if(device.id === oldDevice.id) { oldDevice.time = device.time oldDevice.live = device.live found = true } newDevices.push(oldDevice) } } if(!found) { newDevices.push(device) } return newDevices }) } const removeDevice = (device) => { setCurrentDevices((currentDevices) => currentDevices.filter((oldDevice) => { return oldDevice.id !== device.id })) } useEffect(() => { const interval = setInterval(() => { let devicesToRemove = currentDevices.filter((oldDevice) => { return (Date.now() / 1000) - oldDevice.time > 60 }) devicesToRemove.forEach((device) => { console.log("removing " + device.type) removeDevice(device) }) }, 10000) return () => clearInterval(interval); }, [currentDevices]); const incomingMessageHandlers = useRef([ { topic: "login", handler: (msg) => { addDevice(msg) } }]) const mqttClientRef = useRef(null) const setMqttClient = (client) => { mqttClientRef.current = client client.publish("admin", "online") } useMqtt({ uri: process.env.NEXT_PUBLIC_MQTT_URI, options: { username: process.env.NEXT_PUBLIC_MQTT_USERNAME, password: process.env.NEXT_PUBLIC_MQTT_PASSWORD, clientId: process.env.NEXT_PUBLIC_MQTT_CLIENTID, }, topicHandlers: incomingMessageHandlers.current, onConnectedHandler: (client) => setMqttClient(client), }) const publishMessage = (client, topic, message) => { console.log("publishing") if (!client) { console.log('(publishMessages) Cannot publish, mqttClient: ', client) return } client.publish(topic, message) } let currentlyActive = currentDevices.filter((i) => i.live).map((i) => String(i.ip + i.port)) return ( <div className={"main"}> <div className={"title"}> <h2>SUPER SAFE "SECURITY" SYSTEM</h2> </div> <h3>Transmitters:</h3> <Row> {currentDevices.map((i) => i.type === "transmitter" && ( <Col key={i.ip + i.port} style={{margin: "2vh"}}> <Card className={"transmitterCard"} style={{display: "inline-block", margin: "auto" }}> <Card.Body> <Card.Title> <h4>{i.id + " - " + (i.live ? "LIVE" : "INACTIVE")}</h4> </Card.Title> {i.live && ( <iframe height={480} width={640} src={"http://pi:raspberry@" + i.ip.toString() + ":" + i.port.toString() + "/stream_simple.html"} /> )} <h5>Type: {i.subtype}</h5> <h5>Location: {i.location}</h5> <h5>Address: {i.ip + ":" + i.port}</h5> {!i.live && ( <div> <Button onClick={() => { console.log("clicked") publishMessage(mqttClientRef.current, "home/" + i.location + "/" + i.type, "activate") }}> Activate </Button> </div> )} </Card.Body> </Card> </Col> ))} </Row> <h3>Sensors:</h3> <Row> {currentDevices.map((i) => i.type === "sensor" && ( <Col key={i.id}> <Card style={{display: "inline-block", margin: "auto", padding: "1vh" }}> <Card.Title> {i.id + " - " + (i.live ? "ACTIVE" : "INACTIVE")} </Card.Title> <h5>Type: {i.type}</h5> <h5>Location: {i.location}</h5> <h5>Activates: {i.targets.join(", ")}</h5> </Card> </Col> ))} </Row> </div> ) }