Ich habe mir folgenden JS-Code mit Hilfe von ChatGPT erstellt:
const dgram = require('dgram');
const deviceIP = 'xxx.xxx.xxx.xxx'; // IP-Adresse der Zeitschaltuhr
const port = 30303; // UDP-Port der Zeitschaltuhr
const states = ['OUT1', 'OUT2', 'OUT3', 'OUT4']; // Zustände (ohne Temperatur)
const warnCooldown = {}; // Warnungstimer für Statusabweichungen
const retryAttempts = 3; // Anzahl der Wiederholungen bei Abfrageabweichungen
const warnLimit = 2; // Anzahl maximaler Warnungen pro Abweichung
// Datenpunkte im ioBroker erstellen
states.forEach(state => {
createState(`javascript.0.Zeitschaltuhr.${state}`, false, { name: `${state} Schalter`, type: 'boolean', def: false, read: true, write: true });
});
// Spezieller Datenpunkt für Temperatur
createState(`javascript.0.Zeitschaltuhr.Temperatur`, 0, { name: 'Temperatur Status', type: 'mixed', def: 0, read: true, write: false });
// Funktion, um UDP-Befehl zu senden und Antwort abzurufen
function sendUDPCommandAndReceive(command, callback) {
const message = Buffer.from(command);
const client = dgram.createSocket('udp4');
client.on('message', (msg, rinfo) => {
const response = msg.toString();
// Antwort analysieren und Datenpunkte aktualisieren
if (response.startsWith('T')) {
const parts = response.split('=');
if (parts.length > 1) {
const value = parseFloat(parts[1].trim());
if (!isNaN(value)) {
const currentState = getState(`javascript.0.Zeitschaltuhr.Temperatur`).val;
if (value === -27) {
if (currentState !== 'nicht angeschlossen') {
setState(`javascript.0.Zeitschaltuhr.Temperatur`, 'nicht angeschlossen', true);
}
} else {
if (currentState !== value) {
setState(`javascript.0.Zeitschaltuhr.Temperatur`, value, true);
}
}
}
}
} else {
states.forEach(state => {
if (response.startsWith(state)) {
const parts = response.split('=');
if (parts.length > 1) {
const value = parseInt(parts[1].trim(), 10);
if (value === 0 || value === 1) {
const currentState = getState(`javascript.0.Zeitschaltuhr.${state}`).val;
if (currentState !== (value === 1)) {
setState(`javascript.0.Zeitschaltuhr.${state}`, value === 1, true);
}
}
}
}
});
}
client.close();
if (callback) callback(response);
});
client.send(message, 0, message.length, port, deviceIP, (err) => {
if (err) {
console.error(`Fehler beim Senden: ${err.message}`);
client.close();
}
});
}
// Funktion zur Steuerung der Ports (ein- und ausschalten)
function controlPort(portNumber, state) {
if (portNumber < 1 || portNumber > 4) {
console.error('Ungültige Portnummer. Bitte 1 bis 4 angeben.');
return;
}
if (state !== 0 && state !== 1) {
console.error('Ungültiger Zustand. Bitte 0 (aus) oder 1 (ein) angeben.');
return;
}
const command = `OUT${portNumber} ${state}`;
sendUDPCommandAndReceive(command, () => {
let attempts = 0;
let warnings = 0;
function checkStatus() {
const queryCommand = `OUT${portNumber} ?`;
sendUDPCommandAndReceive(queryCommand, (response) => {
const parts = response.split('=');
if (parts.length > 1) {
const value = parseInt(parts[1].trim(), 10);
if (value === state) {
setState(`javascript.0.Zeitschaltuhr.OUT${portNumber}`, value === 1, true);
} else {
attempts++;
if (attempts < retryAttempts) {
setTimeout(checkStatus, 500); // Wiederholen nach 500ms
} else {
warnings++;
if (warnings <= warnLimit) {
console.warn(`Status von OUT${portNumber} stimmt nicht überein: Erwartet ${state}, erhalten ${value}`);
}
}
}
}
});
}
// Erste Statusprüfung nach 1 Sekunde
setTimeout(checkStatus, 1000);
});
}
// Listener für Schalter in ioBroker
states.forEach((state, index) => {
on({ id: `javascript.0.Zeitschaltuhr.${state}`, change: 'any' }, (obj) => {
const newState = obj.state.val ? 1 : 0;
controlPort(index + 1, newState);
});
});
// Funktion zur regelmäßigen Abfrage
function queryStates() {
states.concat('T').forEach((state) => {
const command = `${state} ?`;
sendUDPCommandAndReceive(command);
});
}
// Intervall für regelmäßige Abfragen (alle 10 Sekunden)
setInterval(queryStates, 10000);
// Initialer Aufruf
queryStates();
Der Code ließt den aktuellen Zustand der Ports 1-4 sowie der Temperatur (Ich besitze keinen Sensor und kann die Ausgabe der Temp. nicht testen) per UDP-Protokoll und erstellt in ioBroker passende Datenpunkte. Diese können dann aus ioBroker oder VIS geschaltet werden.