127 lines
4.4 KiB
JavaScript
127 lines
4.4 KiB
JavaScript
const express = require('express');
|
|
const path = require('path');
|
|
const cors = require('cors');
|
|
const fs = require('fs');
|
|
const bodyParser = require('body-parser');
|
|
const mqtt = require('mqtt');
|
|
|
|
const app = express();
|
|
const port = process.env.PORT || 3000;
|
|
const mqttBroker = process.env.MQTT_BROKER || 'mqtt://192.168.1.100:1883';
|
|
const mqttTopic = process.env.MQTT_TOPIC || 'iobroker/pickupCheck/config';
|
|
const mqttUser = process.env.MQTT_USER || 'iobroker';
|
|
const mqttPassword = process.env.MQTT_PASSWORD || 'password';
|
|
const configPath = './config/pickup-config.json';
|
|
|
|
// Logger mit Timestamp
|
|
function logWithTimestamp(...args) {
|
|
const timestamp = new Date().toISOString();
|
|
console.log(`[${timestamp}]`, ...args);
|
|
}
|
|
|
|
function errorWithTimestamp(...args) {
|
|
const timestamp = new Date().toISOString();
|
|
console.error(`[${timestamp}]`, ...args);
|
|
}
|
|
|
|
// MQTT-Client mit Authentifizierung initialisieren
|
|
const mqttClient = mqtt.connect(mqttBroker, {
|
|
clientId: 'pickup-config-web-' + Math.random().toString(16).substring(2, 8),
|
|
clean: true,
|
|
username: mqttUser,
|
|
password: mqttPassword
|
|
});
|
|
|
|
// MQTT-Events
|
|
mqttClient.on('connect', () => {
|
|
logWithTimestamp('Verbunden mit MQTT-Broker:', mqttBroker);
|
|
|
|
mqttClient.subscribe(mqttTopic, (err) => {
|
|
if (!err) {
|
|
logWithTimestamp('Abonniert auf Topic:', mqttTopic);
|
|
mqttClient.publish(mqttTopic + '/get', 'true');
|
|
}
|
|
});
|
|
});
|
|
|
|
mqttClient.on('error', (error) => {
|
|
errorWithTimestamp('MQTT-Fehler:', error);
|
|
});
|
|
|
|
mqttClient.on('message', (topic, message) => {
|
|
logWithTimestamp('Nachricht erhalten auf Topic:', topic);
|
|
|
|
if (topic === mqttTopic) {
|
|
try {
|
|
const config = JSON.parse(message.toString());
|
|
logWithTimestamp('Konfiguration vom MQTT-Broker erhalten');
|
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
} catch (error) {
|
|
errorWithTimestamp('Fehler beim Verarbeiten der MQTT-Nachricht:', error);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Middleware
|
|
app.use(cors());
|
|
app.use(bodyParser.json());
|
|
app.use(express.static(path.join(__dirname, 'build')));
|
|
|
|
// Sicherstellen, dass Konfigurationsordner existiert
|
|
const configDir = path.dirname(configPath);
|
|
if (!fs.existsSync(configDir)) {
|
|
fs.mkdirSync(configDir, { recursive: true });
|
|
}
|
|
|
|
// Initiale Konfigurationsdatei erstellen, falls nicht vorhanden
|
|
if (!fs.existsSync(configPath)) {
|
|
const initialConfig = [
|
|
{ id: "63448", active: false, checkProfileId: true, onlyNotify: true, label: "Penny Baden-Oos" },
|
|
{ id: "44975", active: false, checkProfileId: true, onlyNotify: false, label: "Aldi Kuppenheim", desiredWeekday: "Samstag" },
|
|
{ id: "44972", active: false, checkProfileId: true, onlyNotify: false, label: "Aldi Biblisweg", desiredWeekday: "Dienstag" },
|
|
{ id: "44975", active: false, checkProfileId: true, onlyNotify: false, label: "Aldi Kuppenheim", desiredDate: "2025-05-18" },
|
|
{ id: "33875", active: false, checkProfileId: true, onlyNotify: false, label: "Cap Markt", desiredWeekday: "Donnerstag" },
|
|
{ id: "42322", active: false, checkProfileId: false, onlyNotify: false, label: "Edeka Haueneberstein" },
|
|
{ id: "51450", active: false, checkProfileId: true, onlyNotify: false, label: "Hornbach Grünwinkel" }
|
|
];
|
|
|
|
fs.writeFileSync(configPath, JSON.stringify(initialConfig, null, 2));
|
|
mqttClient.publish(mqttTopic, JSON.stringify(initialConfig));
|
|
logWithTimestamp('Initiale Konfiguration erstellt und an MQTT gesendet');
|
|
}
|
|
|
|
// API: Konfiguration abrufen
|
|
app.get('/api/iobroker/pickup-config', (req, res) => {
|
|
try {
|
|
const configData = fs.readFileSync(configPath, 'utf8');
|
|
res.json(JSON.parse(configData));
|
|
} catch (error) {
|
|
errorWithTimestamp('Error reading configuration:', error);
|
|
res.status(500).json({ error: 'Failed to read configuration' });
|
|
}
|
|
});
|
|
|
|
// API: Konfiguration speichern
|
|
app.post('/api/iobroker/pickup-config', (req, res) => {
|
|
try {
|
|
const newConfig = req.body;
|
|
fs.writeFileSync(configPath, JSON.stringify(newConfig, null, 2));
|
|
mqttClient.publish(mqttTopic, JSON.stringify(newConfig));
|
|
logWithTimestamp('Konfiguration über MQTT gesendet');
|
|
res.json({ success: true });
|
|
} catch (error) {
|
|
errorWithTimestamp('Error saving configuration:', error);
|
|
res.status(500).json({ error: 'Failed to save configuration' });
|
|
}
|
|
});
|
|
|
|
// React-App ausliefern
|
|
app.get('*', (req, res) => {
|
|
res.sendFile(path.join(__dirname, 'build', 'index.html'));
|
|
});
|
|
|
|
// Server starten
|
|
app.listen(port, () => {
|
|
logWithTimestamp(`Server läuft auf Port ${port}`);
|
|
});
|