• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Frage Synchronisierte Webseite die einen Zähler anzeigt

Wachhund

Neues Mitglied
Hallo Community,

ich habe mir eine Webseite zusammen gebaut, auf der durch klicken auf den Button ein Zähler gestartet wird. Durch wiederholtes klicken, wird ein weiterer Zähler gestartet. Jeder Zähler der die Zahl 10 erreicht hat, wird nach 5 weiteren Sekunden entfernt.
Wenn kein Zähler am hochlaufen ist, wird der Text "Niemand in der Umkleide" angezeigt.

Mein Umgebungsaufbau ist wie folgt:
Ich habe mehrere Raspberry Pis, an denen ein Monitor angeschlossen ist. Auf dem Monitor wird ein Informationsbildschirm angezeigt, wo ich ein iFrame einbinden kann.
An einem Raspberry Pi, wird ein physikalischer Druckknopf angeschlossen, mit dem der Zähler gestartet werden soll.

Mein Ziel ist es, dass mittels des physikalischen Druckknopf der Zähler auf der Seite gestartet werden soll, genauso wie es der virtuelle Button derzeit macht.
Weiteres Ziel ist es, dass an allen Bildschirmen auf dem die Seite angezeigt wird, die Zähler synchron angezeigt werden. Entweder weil diese die Information zentral beziehen oder weil alles gleichzeitig einen trigger oder so erhalten.

Erschwertes Problem, bei meinem Test konnte ich die derzeitige Seite in dem iFrame nur anzeigen, wenn ich die online gehostet habe, z.B. bei Strato. Habe ich einen apache server auf einen der Raspberry Pis laufen, kann ich die zwar mit einem Browser öffnen, aber leider nicht mit dem iFrame.


Mein vorhandens Skript:
Code:
<h1 id="timer-count"></h1>
<div id="timers"></div>
<button id="start-timer">Start Timer</button>
<p id="click-count">Button wurde 0 mal geklickt</p>
<script>
const timerCountHeading = document.querySelector('#timer-count');
const timersContainer = document.querySelector('#timers');
const startTimerButton = document.querySelector('#start-timer');
const clickCountDisplay = document.querySelector('#click-count');

let clickCount = 0;

startTimerButton.addEventListener('click', function() {
  clickCount++;
  clickCountDisplay.innerHTML = `Button wurde ${clickCount} mal geklickt`;
 
  if (timersContainer.innerHTML === '<div style="color: red; font-weight: bold; font-size: 20px;">Niemand in der Umkleide</div>') {
    timersContainer.innerHTML = '';
  }
 
  timerCountHeading.innerHTML = `Aktive Zähler: ${timersContainer.children.length + 1}`;
  timerCountHeading.style.display = "block";
 
  const timerDisplay = document.createElement('div');
  timerDisplay.innerHTML = '0 Sekunden';
  timersContainer.appendChild(timerDisplay);
 
  let timerValue = 0;
  const intervalId = setInterval(function() {
    timerValue++;
    timerDisplay.innerHTML = timerValue + ' Sekunden';
   
    if (timerValue === 10) {
      clearInterval(intervalId);
      setTimeout(function() {
        timerDisplay.remove();
        if (timersContainer.children.length === 0) {
          timersContainer.innerHTML = '<div style="color: red; font-weight: bold; font-size: 20px;">Niemand in der Umkleide</div>';
          timerCountHeading.style.display = "none";
        }
        else {
          timerCountHeading.innerHTML = `Aktive Zähler: ${timersContainer.children.length}`;
        }
      }, 5000);
    }
  }, 1000);
});

timerCountHeading.style.display = "none";
timersContainer.innerHTML = '<div style="color: red; font-weight: bold; font-size: 20px;">Niemand in der Umkleide</div>';
</script>

Ich hoffe das ich mein Problem ausreichend erklären konnte und vor allem das jemand eine Idee hat, die mir weiter hilft.

Gruß
 

Charly1410

Neues Mitglied
Hallo @Wachhund, ich denke schon, dass Du die Aufgabe ausreichend erklärt hast.

Weiteres Ziel ist es, dass an allen Bildschirmen auf dem die Seite angezeigt wird, die Zähler synchron angezeigt werden. Entweder weil diese die Information zentral beziehen oder weil alles gleichzeitig einen trigger oder so erhalten.
Dafür sehe ich zwei Möglichkeiten:

1. Die Zählerstände zyklisch mit fetch abfragen, dann bekommen auch die anderen mit wenn ein Zähler neu hinzu gekommen ist. Der Nachteil ist, dass eine Fülle von Anfragen beim Server auflaufen.

2. Websockets benutzen, dann ist der Server in der Lage, autonom Nachrichten an den Client bzw. Browser zu schicken.

Bisher hatte ich mich mit letzterem noch nicht beschäftigt aber weil diese Art von Frage relativ häufig gestellt wird habe ich diesen Thread mal zum Anlass genommen, dort einzusteigen. Ergebnis ist diese Demo:

HTML für den Client bzw. Browser:
Code:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebSockets</title>
</head>

<body>
    <!-- Simple HTML page for sending messages with input box and send button-->
    <h1>Hello WebSockets</h1>
    <div id="messages"></div>
    <input type="text" id="message">
    <button id="start-timer">Start Timer</button>
    <script src="script.js"></script>
</body>

</html>

script.js
Code:
//Websocekt variables
const url = "ws://localhost:9876/myWebsocket"
const mywsServer = new WebSocket(url);
//DOM Elements
const startBtn = document.getElementById("start-timer");
startBtn.addEventListener("click", startTimer, false)
//Sending message from client
function startTimer() {
    const data = { 'action': 'start' };
    mywsServer.send(JSON.stringify(data));
}

mywsServer.onopen = function () {
}
//handling message event
mywsServer.onmessage = function (event) {
    console.log(event);
}

Und das serverseitige Skript in nodejs:
Code:
// https://dev.to/codesphere/getting-started-with-web-sockets-in-nodejs-49n0
// https://www.patrykgalach.com/2019/10/14/setting-up-websocket-server-in-nodejs/
const
    WebSocket = require("ws"),
    express = require("express"),
    url = require('url'),
    app = express(),
    path = require("path"),
    endValue = 10,
    afterEnd = 5;
app.use("/", express.static(path.resolve(__dirname, "../client")))

// regular http server using node express which serves your webpage
const myServer = app.listen(9876);

const wsServer = new WebSocket.Server({
    noServer: true
});                                   // a websocket server

wsServer.on("connection", function (ws) {    // what should a websocket do on connection
    // what should a websocket do on connection
    ws.on("message", function (msgJson) {        // what to do on message event
        console.log('message')
        const msg = JSON.parse(msgJson);
        if (msg.action = 'start') {
            timers.push(0);
        }
    });
    ws.on('close', function (event) {
        wsServer.clients.forEach(function each(client) {
            if (client.readyState === WebSocket.OPEN) {     // check if client is ready
                client.close();
            }
        });
    });
});

let
    timers = [];
setInterval(() => {
    for (let i = 0; i < timers.length; i++) {
        if (timers[i] < endValue) {
            if (timers[i] == endValue - 1) {
                setTimeout(() => {
                    timers.splice(i, 1);
                }, (afterEnd + 1) * 1000);
            }
            timers[i]++;
        }
    }
    console.log(timers)
    wsServer.clients.forEach(function each(client) {
        if (client.readyState === WebSocket.OPEN) {     // check if client is ready
            client.send(JSON.stringify(timers));
        }
    });
}, 1000);


// HTTP Server ==> WebSocket upgrade handling:
myServer.on('upgrade', function upgrade(request, socket, head) {
    console.log(new Date() + ' | Upgrading http connection to wss: url = ' + request.url);
    // Parsing url from the request.
    var parsedUrl = url.parse(request.url, true, true);
    const pathname = parsedUrl.pathname
    console.log(new Date() + ' | Pathname = ' + pathname);
    // If path is valid connect to the websocket.
    if (pathname === '/myWebsocket') {
        wsServer.handleUpgrade(request, socket, head, function done(ws) {
            wsServer.emit('connection', ws, request);
        });
    } else {
        socket.destroy();
    }
});
Die beiden Links dort haben mir geholfen, den Code zu entwickeln. Damit er läuft, muss:
- nodejs installiert werden.
- Der clientseitige Code in einem Verzeichnis "client" liegen.
- Der serverseitige Code parallel dazu in einem Verzeichnis "server".
- Der Webserver gestartet werden.

Wenn die Zähler nur bis 10 laufen könnte man daran denken, sie autonom auf dem Client laufen zu lassen, um die Anzahl der Nachrichten zu reduzieren. Aber mir kam es zunächst primär darauf an, mich mit Websockets vertraut zu machen.

dass mittels des physikalischen Druckknopf der Zähler auf der Seite gestartet werden soll, genauso wie es der virtuelle Button derzeit macht.
Hier fehlt mir ein wenig die Erfahrung aber ich habe eine ganze Reihe von Threads in dieser Richtung verfolgt und meistens konnte man digitale Ein- und Ausgaben abfragen und setzen indem eine bestimmte URL aufgerufen wurde. In Javascript kann man das mit fetch erledigen.
 
Werbung:
Oben