MQTT Visualisierte Steuerung Aktor: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
 
(4 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 16: Zeile 16:
 
Erstelle die Datei server.js im Verzeichnis /usr/local/control mit folgendem Inhalt:
 
Erstelle die Datei server.js im Verzeichnis /usr/local/control mit folgendem Inhalt:
 
<pre>
 
<pre>
 +
 
const mqtt = require('mqtt');
 
const mqtt = require('mqtt');
 
const express = require('express');
 
const express = require('express');
Zeile 21: Zeile 22:
 
const app = express();
 
const app = express();
 
const port = 3000;
 
const port = 3000;
 +
const fs = require('fs');
  
 
let status = {
 
let status = {
Zeile 29: Zeile 31:
 
};
 
};
  
// MQTT-Verbindung herstellen
+
// MQTT connection options (without TLS for unencrypted communication)
const client = mqtt.connect('mqtt://mqtt.dkbi.int:1883', {
+
const options = {
  // username: 'xinux',
+
// username: 'xinux',
   // password: 'secret'
+
// 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', () => {
 
client.on('connect', () => {
   console.log('Connected to the broker');
+
   console.log('Connected to the MQTT broker');
 
   client.subscribe('home/+/status', (err) => {
 
   client.subscribe('home/+/status', (err) => {
 
     if (!err) {
 
     if (!err) {
Zeile 50: Zeile 59:
 
});
 
});
  
// API route to get the status of the lights and front door
+
// 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);
 
});
 
});
  
// Serve static directory for the web interface
+
// Route to toggle a device
 +
app.post('/toggle/:device', (req, res) => {
 +
  const device = req.params.device;
 +
  const currentStatus = status[device];
 +
 
 +
  if (!currentStatus) {
 +
    res.status(400).send({ error: 'Invalid device' });
 +
    return;
 +
  }
 +
 
 +
  // Toggle the status (for front door: closed/open)
 +
  let newStatus;
 +
  if (device === 'frontDoor') {
 +
    newStatus = currentStatus === 'closed' ? 'open' : 'closed';
 +
  } else {
 +
    newStatus = currentStatus === 'on' ? 'off' : 'on';
 +
  }
 +
  status[device] = newStatus;
 +
 
 +
  // Send MQTT message
 +
  const topic = `home/${device}/status`;
 +
  client.publish(topic, newStatus, (err) => {
 +
    if (err) {
 +
      console.log(`Error sending message to ${device}: ${err.message}`);
 +
      res.status(500).send({ success: false, message: 'Error sending message' });
 +
    } else {
 +
      console.log(`Message sent: ${device} is now ${newStatus}`);
 +
      res.send({ success: true, message: `Device ${device} successfully toggled` });
 +
    }
 +
  });
 +
});
 +
 
 +
// Serve the static directory for the web interface
 
app.use(express.static(path.join(__dirname)));
 
app.use(express.static(path.join(__dirname)));
  
 
// Start the web server
 
// Start the web server
 
app.listen(port, () => {
 
app.listen(port, () => {
   console.log(`Control Center is running at http://0.0.0.0:${port}`);
+
   console.log(`Control Center is running at http://localhost:${port}`);
 
});
 
});
 
</pre>
 
</pre>
Zeile 154: Zeile 195:
 
* http://aktor.dkbi.com:3000
 
* http://aktor.dkbi.com:3000
  
==== MQTT-Nachrichten senden ====
 
 
Zuerst definieren wir die Variable für den MQTT-Server:
 
  
==== Definiere die Variable für den MQTT-Server ====
+
=== MQTT-Nachrichten senden ===
* export MQTTSERVER=mqtt.dkbi.int
 
  
 
==== Licht im Wohnzimmer einschalten ====
 
==== Licht im Wohnzimmer einschalten ====
* mosquitto_pub -h $MQTTSERVER -t home/wohnzimmer/status -m "on"
+
* mosquitto_pub -h mqtt.dkbi.int -t home/livingRoom/status -m "on"
  
 
==== Licht im Wohnzimmer ausschalten ====
 
==== Licht im Wohnzimmer ausschalten ====
* mosquitto_pub -h $MQTTSERVER -t home/wohnzimmer/status -m "off"  
+
* mosquitto_pub -h mqtt.dkbi.int -t home/livingRoom/status -m "off"
  
 
==== Haustür öffnen ====
 
==== Haustür öffnen ====
* mosquitto_pub -h $MQTTSERVER -t home/haustuer/status -m "offen"  
+
* mosquitto_pub -h mqtt.dkbi.int -t home/frontDoor/status -m "open"
  
 
==== Haustür schließen ====
 
==== Haustür schließen ====
* mosquitto_pub -h $MQTTSERVER -t home/haustuer/status -m "geschlossen"
+
* mosquitto_pub -h mqtt.dkbi.int -t home/frontDoor/status -m "closed"

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

Voraussetzungen

Neues Verzeichnis für das Projekt erstellen

  • mkdir /usr/local/control
  • cd /usr/local/control

Initialisiere das Node.js-Projekt

  • npm init -y

Installiere die benötigten Pakete

  • npm install mqtt express

Konfiguration des Node.js-Servers

Erstelle die Datei server.js im Verzeichnis /usr/local/control 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 connection options (without TLS for unencrypted communication)
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 MQTT 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]}`);
});

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

// Route to toggle a device
app.post('/toggle/:device', (req, res) => {
  const device = req.params.device;
  const currentStatus = status[device];

  if (!currentStatus) {
    res.status(400).send({ error: 'Invalid device' });
    return;
  }

  // Toggle the status (for front door: closed/open)
  let newStatus;
  if (device === 'frontDoor') {
    newStatus = currentStatus === 'closed' ? 'open' : 'closed';
  } else {
    newStatus = currentStatus === 'on' ? 'off' : 'on';
  }
  status[device] = newStatus;

  // Send MQTT message
  const topic = `home/${device}/status`;
  client.publish(topic, newStatus, (err) => {
    if (err) {
      console.log(`Error sending message to ${device}: ${err.message}`);
      res.status(500).send({ success: false, message: 'Error sending message' });
    } else {
      console.log(`Message sent: ${device} is now ${newStatus}`);
      res.send({ success: true, message: `Device ${device} successfully toggled` });
    }
  });
});

// Serve the 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://localhost:${port}`);
});

HTML-Datei erstellen

Erstelle eine Datei index.html im selben Verzeichnis, die den Status der Lichter und des Haustüröffners anzeigt und eine visuelle Darstellung mit Farben bietet:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Devices</title>
  <style>
    .device {
      margin: 20px;
      padding: 10px;
      border-radius: 10px;
      text-align: center;
      font-size: 1.5em;
    }
    .lamp-on {
      background-color: yellow;
      color: black;
    }
    .lamp-off {
      background-color: gray;
      color: white;
    }
    .door-open {
      background-color: red;
      color: white;
    }
    .door-closed {
      background-color: gray;
      color: white;
    }
  </style>
  <script>
    function fetchStatus() {
      fetch('/status')
        .then(response => response.json())
        .then(data => {
          document.getElementById('livingRoom').className = 'device ' + (data.livingRoom === 'on' ? 'lamp-on' : 'lamp-off');
          document.getElementById('bedroom').className = 'device ' + (data.bedroom === 'on' ? 'lamp-on' : 'lamp-off');
          document.getElementById('kitchen').className = 'device ' + (data.kitchen === 'on' ? 'lamp-on' : 'lamp-off');
          document.getElementById('frontDoor').className = 'device ' + (data.frontDoor === 'open' ? 'door-open' : 'door-closed');
        });
    }

    setInterval(fetchStatus, 1000); // Fetch status every second
  </script>
</head>
<body>
  <h1>Devices</h1>
  <div id="livingRoom" class="device lamp-off">Living Room Light</div>
  <div id="bedroom" class="device lamp-off">Bedroom Light</div>
  <div id="kitchen" class="device lamp-off">Kitchen Light</div>
  <div id="frontDoor" class="device door-closed">Front Door</div>
</body>
</html>

systemd-Unit erstellen

Erstelle eine Datei /etc/systemd/system/control.service mit folgendem Inhalt:

[Unit]
Description=Home Control Center

[Service]
Type=simple
WorkingDirectory=/usr/local/control
ExecStart=/usr/bin/node server.js
ExecStartPost=/bin/echo "Home Control Center Start"

[Install]
WantedBy=multi-user.target

Server starten

systemd-Service starten

  • systemctl start control.service

systemd-Service beim Booten starten lassen

  • systemctl enable control.service

Öffne deinen Browser und gehe zu


MQTT-Nachrichten senden

Licht im Wohnzimmer einschalten

  • mosquitto_pub -h mqtt.dkbi.int -t home/livingRoom/status -m "on"

Licht im Wohnzimmer ausschalten

  • mosquitto_pub -h mqtt.dkbi.int -t home/livingRoom/status -m "off"

Haustür öffnen

  • mosquitto_pub -h mqtt.dkbi.int -t home/frontDoor/status -m "open"

Haustür schließen

  • mosquitto_pub -h mqtt.dkbi.int -t home/frontDoor/status -m "closed"