MQTT Visualisierte Steuerung Sensor: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
 
(6 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 4: Zeile 4:
  
 
==== Neues Verzeichnis für den Steuerungsserver erstellen ====
 
==== Neues Verzeichnis für den Steuerungsserver erstellen ====
*'''mkdir /usr/local/control-switch'''
+
*mkdir /usr/local/control-switch
*'''cd /usr/local/control-switch'''
+
*cd /usr/local/control-switch
  
 
==== Initialisiere das Node.js-Projekt ====
 
==== Initialisiere das Node.js-Projekt ====
*'''npm init -y'''
+
*npm init -y
  
 
==== Installiere die benötigten Pakete ====
 
==== Installiere die benötigten Pakete ====
*'''npm install mqtt express'''
+
*npm install mqtt express
  
 
==== Konfiguration des Steuerungsservers ====
 
==== Konfiguration des Steuerungsservers ====
Zeile 18: Zeile 18:
 
<pre>
 
<pre>
 
const mqtt = require('mqtt');
 
const mqtt = require('mqtt');
const fs = require('fs');
 
 
const express = require('express');
 
const express = require('express');
 
const path = require('path');
 
const path = require('path');
 
const app = express();
 
const app = express();
 
const port = 3000;
 
const port = 3000;
 
+
const fs = require('fs');
 
let status = {
 
let status = {
   wohnzimmer: 'off',
+
   livingRoom: 'off',
   schlafzimmer: 'off',
+
   bedroom: 'off',
   kueche: 'off',
+
   kitchen: 'off',
   haustuer: 'geschlossen'
+
   frontDoor: 'closed'
 
};
 
};
  
// MQTT-Verbindung herstellen über TLS
+
// MQTT-Verbindung herstellen
 
const options = {
 
const options = {
 +
//  username: 'xinux',
 +
//  password: '123Start$',
 +
//  port: 8883,
 +
//  protocol: 'mqtts',
 +
//  ca: fs.readFileSync('./ca.crt'),
 
   port: 1883,
 
   port: 1883,
   host: 'mqtt.dkbi.int',
+
   host: 'mqtt.dkbi.int'
  //protocol: 'mqtts',
 
  //username: 'xinux',
 
  //password: 'geheim',
 
  //ca: fs.readFileSync('./ca.crt')  // Pfad zur ca.crt
 
 
};
 
};
  
Zeile 44: Zeile 44:
  
 
client.on('connect', () => {
 
client.on('connect', () => {
   console.log('Verbunden mit dem Broker');
+
   console.log('Connected to the broker');
 
   client.subscribe('home/+/status', (err) => {
 
   client.subscribe('home/+/status', (err) => {
 
     if (!err) {
 
     if (!err) {
       console.log('Alle Topics abonniert');
+
       console.log('Subscribed to all topics');
 
     }
 
     }
 
   });
 
   });
Zeile 55: Zeile 55:
 
   const room = topic.split('/')[1];
 
   const room = topic.split('/')[1];
 
   status[room] = message.toString();
 
   status[room] = message.toString();
   console.log(`Status von ${room}: ${status[room]}`);
+
   console.log(`Status of ${room}: ${status[room]}`);
 
});
 
});
  
// API-Route für den Status der Lichter und Haustür
+
// API route to get the status of the lights and front door
 
app.get('/status', (req, res) => {
 
app.get('/status', (req, res) => {
 
   res.send(status);
 
   res.send(status);
 
});
 
});
  
// Statisches Verzeichnis für die Webseite
+
// Serve static directory for the web interface
 
app.use(express.static(path.join(__dirname)));
 
app.use(express.static(path.join(__dirname)));
  
// Starte den Webserver
+
// Start the web server
 
app.listen(port, () => {
 
app.listen(port, () => {
   console.log(`Webserver läuft auf http://localhost:${port}`);
+
   console.log(`Control Center is running at http://0.0.0.0:${port}`);
 
});
 
});
 +
 
  
 
</pre>
 
</pre>
Zeile 75: Zeile 76:
 
==== Die HTML Datei index.html====
 
==== Die HTML Datei index.html====
 
<pre>
 
<pre>
 
 
 
<!DOCTYPE html>
 
<!DOCTYPE html>
<html lang="de">
+
<html lang="en">
 
<head>
 
<head>
 
   <meta charset="UTF-8">
 
   <meta charset="UTF-8">
 
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
 
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Haussteuerung</title>
+
   <title>Control Center</title>
 
   <style>
 
   <style>
 
     .device {
 
     .device {
Zeile 90: Zeile 89:
 
       text-align: center;
 
       text-align: center;
 
       font-size: 1.5em;
 
       font-size: 1.5em;
 +
      cursor: pointer;
 
     }
 
     }
 
     .on {
 
     .on {
       background-color: green;
+
       background-color: yellow;
       color: white;
+
       color: black;
 
     }
 
     }
 
     .off {
 
     .off {
       background-color: red;
+
       background-color: gray;
 
       color: white;
 
       color: white;
 
     }
 
     }
 
     .open {
 
     .open {
       background-color: blue;
+
       background-color: red;
 
       color: white;
 
       color: white;
 
     }
 
     }
Zeile 109: Zeile 109:
 
   </style>
 
   </style>
 
   <script>
 
   <script>
 +
    // Fetch and display the status of devices
 
     function fetchStatus() {
 
     function fetchStatus() {
 
       fetch('/status')
 
       fetch('/status')
 
         .then(response => response.json())
 
         .then(response => response.json())
 
         .then(data => {
 
         .then(data => {
           document.getElementById('wohnzimmer').className = 'device ' + (data.wohnzimmer === 'on' ? 'on' : 'off');
+
          // Update the class and text for each device
           document.getElementById('schlafzimmer').className = 'device ' + (data.schlafzimmer === 'on' ? 'on' : 'off');
+
           document.getElementById('livingRoom').className = 'device ' + (data.livingRoom === 'on' ? 'on' : 'off');
           document.getElementById('kueche').className = 'device ' + (data.kueche === 'on' ? 'on' : 'off');
+
           document.getElementById('livingRoom').textContent = 'Living Room Light: ' + (data.livingRoom === 'on' ? 'On' : 'Off');
           document.getElementById('haustuer').className = 'device ' + (data.haustuer === 'offen' ? 'open' : 'closed');
+
 
 +
          document.getElementById('bedroom').className = 'device ' + (data.bedroom === 'on' ? 'on' : 'off');
 +
           document.getElementById('bedroom').textContent = 'Bedroom Light: ' + (data.bedroom === 'on' ? 'On' : 'Off');
 +
 
 +
          document.getElementById('kitchen').className = 'device ' + (data.kitchen === 'on' ? 'on' : 'off');
 +
           document.getElementById('kitchen').textContent = 'Kitchen Light: ' + (data.kitchen === 'on' ? 'On' : 'Off');
 +
 
 +
          document.getElementById('frontDoor').className = 'device ' + (data.frontDoor === 'open' ? 'open' : 'closed');
 +
          document.getElementById('frontDoor').textContent = 'Front Door: ' + (data.frontDoor === 'open' ? 'Open' : 'Closed');
 
         });
 
         });
 
     }
 
     }
  
     setInterval(fetchStatus, 1000); // Alle 1 Sekunde den Status abrufen
+
    // Toggle a device and update its status
 +
    function toggleDevice(device) {
 +
      fetch(`/toggle/${device}`, { method: 'POST' })
 +
        .then(fetchStatus);
 +
    }
 +
 
 +
    // Fetch status every second
 +
     setInterval(fetchStatus, 1000);
 
   </script>
 
   </script>
 
</head>
 
</head>
 
<body>
 
<body>
   <h1>Haussteuerung</h1>
+
   <h1>Control Center</h1>
   <div id="wohnzimmer" class="device off">Wohnzimmer Licht: Aus</div>
+
   <div id="livingRoom" class="device off" onclick="toggleDevice('livingRoom')">Living Room Light: Off</div>
   <div id="schlafzimmer" class="device off">Schlafzimmer Licht: Aus</div>
+
   <div id="bedroom" class="device off" onclick="toggleDevice('bedroom')">Bedroom Light: Off</div>
   <div id="kueche" class="device off">Küchen Licht: Aus</div>
+
   <div id="kitchen" class="device off" onclick="toggleDevice('kitchen')">Kitchen Light: Off</div>
   <div id="haustuer" class="device closed">Haustür: Geschlossen</div>
+
   <div id="frontDoor" class="device closed" onclick="toggleDevice('frontDoor')">Front Door: Closed</div>
 
</body>
 
</body>
 
</html>
 
</html>
 +
  
  
Zeile 153: Zeile 170:
  
 
==== Steuerungsserver starten und beim Booten aktivieren ====
 
==== Steuerungsserver starten und beim Booten aktivieren ====
*'''systemctl start control-switch.service'''
+
*systemctl start control-switch.service
*'''systemctl enable control-switch.service'''
+
*systemctl enable control-switch.service
 
 
==== Steuerung der Geräte über HTTP ====
 
Nun können die Geräte über den separaten Server gesteuert werden:
 
 
 
- Wohnzimmerlicht einschalten: `http://localhost:3001/toggle/wohnzimmer`
 
- Schlafzimmerlicht einschalten: `http://localhost:3001/toggle/schlafzimmer`
 
- Küchenlicht einschalten: `http://localhost:3001/toggle/kueche`
 
- Haustür öffnen: `http://localhost:3001/toggle/haustuer`
 
 
 
Der Server ist für die Steuerung der Geräte per HTTP zuständig und sendet die entsprechenden MQTT-Nachrichten.
 

Aktuelle Version vom 4. November 2024, 14:21 Uhr

Voraussetzungen

Neues Verzeichnis für den Steuerungsserver erstellen

  • mkdir /usr/local/control-switch
  • cd /usr/local/control-switch

Initialisiere das Node.js-Projekt

  • npm init -y

Installiere die benötigten Pakete

  • npm install mqtt express

Konfiguration des Steuerungsservers

Erstelle die Datei switch-server.js im Verzeichnis /usr/local/control-switch mit folgendem Inhalt:

const mqtt = require('mqtt');
const express = require('express');
const path = require('path');
const app = express();
const port = 3000;
const fs = require('fs');
let status = {
  livingRoom: 'off',
  bedroom: 'off',
  kitchen: 'off',
  frontDoor: 'closed'
};

// MQTT-Verbindung herstellen
const options = {
 //  username: 'xinux',
 //  password: '123Start$',
 //  port: 8883,
 //  protocol: 'mqtts',
 //  ca: fs.readFileSync('./ca.crt'),
  port: 1883,
  host: 'mqtt.dkbi.int'
};

const client = mqtt.connect(options);

client.on('connect', () => {
  console.log('Connected to the broker');
  client.subscribe('home/+/status', (err) => {
    if (!err) {
      console.log('Subscribed to all topics');
    }
  });
});

client.on('message', (topic, message) => {
  const room = topic.split('/')[1];
  status[room] = message.toString();
  console.log(`Status of ${room}: ${status[room]}`);
});

// API route to get the status of the lights and front door
app.get('/status', (req, res) => {
  res.send(status);
});

// Serve static directory for the web interface
app.use(express.static(path.join(__dirname)));

// Start the web server
app.listen(port, () => {
  console.log(`Control Center is running at http://0.0.0.0:${port}`);
});
  

Die HTML Datei index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Control Center</title>
  <style>
    .device {
      margin: 20px;
      padding: 10px;
      border-radius: 10px;
      text-align: center;
      font-size: 1.5em;
      cursor: pointer;
    }
    .on {
      background-color: yellow;
      color: black;
    }
    .off {
      background-color: gray;
      color: white;
    }
    .open {
      background-color: red;
      color: white;
    }
    .closed {
      background-color: gray;
      color: white;
    }
  </style>
  <script>
    // Fetch and display the status of devices
    function fetchStatus() {
      fetch('/status')
        .then(response => response.json())
        .then(data => {
          // Update the class and text for each device
          document.getElementById('livingRoom').className = 'device ' + (data.livingRoom === 'on' ? 'on' : 'off');
          document.getElementById('livingRoom').textContent = 'Living Room Light: ' + (data.livingRoom === 'on' ? 'On' : 'Off');

          document.getElementById('bedroom').className = 'device ' + (data.bedroom === 'on' ? 'on' : 'off');
          document.getElementById('bedroom').textContent = 'Bedroom Light: ' + (data.bedroom === 'on' ? 'On' : 'Off');

          document.getElementById('kitchen').className = 'device ' + (data.kitchen === 'on' ? 'on' : 'off');
          document.getElementById('kitchen').textContent = 'Kitchen Light: ' + (data.kitchen === 'on' ? 'On' : 'Off');

          document.getElementById('frontDoor').className = 'device ' + (data.frontDoor === 'open' ? 'open' : 'closed');
          document.getElementById('frontDoor').textContent = 'Front Door: ' + (data.frontDoor === 'open' ? 'Open' : 'Closed');
        });
    }

    // Toggle a device and update its status
    function toggleDevice(device) {
      fetch(`/toggle/${device}`, { method: 'POST' })
        .then(fetchStatus);
    }

    // Fetch status every second
    setInterval(fetchStatus, 1000);
  </script>
</head>
<body>
  <h1>Control Center</h1>
  <div id="livingRoom" class="device off" onclick="toggleDevice('livingRoom')">Living Room Light: Off</div>
  <div id="bedroom" class="device off" onclick="toggleDevice('bedroom')">Bedroom Light: Off</div>
  <div id="kitchen" class="device off" onclick="toggleDevice('kitchen')">Kitchen Light: Off</div>
  <div id="frontDoor" class="device closed" onclick="toggleDevice('frontDoor')">Front Door: Closed</div>
</body>
</html>



systemd-Unit für den Steuerungsserver erstellen

Erstelle die Datei /etc/systemd/system/control-switch.service mit folgendem Inhalt:

[Unit]
Description=Home Control Switch Server

[Service]
Type=simple
WorkingDirectory=/usr/local/control-switch
ExecStart=/usr/bin/node server.js
ExecStartPost=/bin/echo "Schalt-Server gestartet"

[Install]
WantedBy=multi-user.target

Steuerungsserver starten und beim Booten aktivieren

  • systemctl start control-switch.service
  • systemctl enable control-switch.service