Hier ein geändertes Skript für die, die mehrere APs haben.
//
// #############################################
//
// Dieses Script ermöglicht die Buttonabfrage.
//
// In dem Script wird die Socket-Verbindung von Beowolf verwendet (https://forum.iobroker.net/topic/66380/e-ink-display-openepaperlink-displayanzeige-mit-batterie/809?_=1747419968864)
//
// Ein erweitertes Skript von Eisbaeeer ist hier (https://forum.iobroker.net/topic/81101/openepaperlink-script-für-tastenabfrage )
//
// Die Button-States werden unter dem konfigurierten basePathPrefix erzeugt.
//
// #############################################
// #############################################
//
// Konfigurierbare Variablen - Hier die Anpassungen vornehmen!
//
const rootPath = '0_userdata.0'; // Bei Bedarf anpassen
const controlRoot = 'EPaperControl'; // Oberordner für Steuerung
const buttonRoot = 'Buttons'; // Unterordner für Buttons
const accesspoints = [
{ location: 'Erdgeschoss', ip: '192.168.49.185' }, // Accesspoint IP Adresse
{ location: 'Obergeschoss', ip: '192.168.49.186' }, // Accesspoint IP Adresse
{ location: 'Dachgeschoss', ip: '192.168.49.187' }, // Accesspoint IP Adresse
{ location: 'Hühnerhaus', ip: '192.168.49.139' } // Accesspoint IP Adresse
];
//
// ENDE Anpassungen! Ab hier nichts mehr ändern!
// #############################################
//
// Automatisch generierte Pfade für jeden Accesspoint
accesspoints.forEach(ap => {
ap.name = `${ap.location}-AP`;
ap.controlState = `${rootPath}.${controlRoot}.${ap.location}.Start`;
ap.buttonPathPrefix = `${rootPath}.${controlRoot}.${ap.location}.${buttonRoot}`;
});
const WebSocket = require('ws');
let wsConnections = {};
let pingIntervals = {};
let scriptStatus = {};
// Initialisierung der Steuerobjekte
accesspoints.forEach(ap => {
scriptStatus[ap.name] = false;
setObject(ap.controlState, {
type: 'state',
common: {
name: `Start/Stop ${ap.name}`,
type: 'boolean',
role: 'switch',
read: true,
write: true,
def: false
},
native: {}
});
on({ id: ap.controlState, change: 'ne' }, (obj) => {
if (obj.state.val === true) {
scriptStatus[ap.name] = true;
connectWebSocket(ap.name, ap.ip);
} else {
scriptStatus[ap.name] = false;
disconnectWebSocket(ap.name);
}
});
getState(ap.controlState, (err, state) => {
if (!err && state && state.val === true) {
scriptStatus[ap.name] = true;
connectWebSocket(ap.name, ap.ip);
}
});
});
function connectWebSocket(name, ip) {
if (wsConnections[name]) return;
const url = `ws://${ip}/ws`;
const ws = new WebSocket(url);
wsConnections[name] = ws;
ws.on('open', () => {
console.log(`WebSocket ${name} verbunden (${ip})`);
pingIntervals[name] = setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.ping();
}
}, 10000);
});
ws.on('message', (data) => {
try {
const parsed = JSON.parse(data);
handleData(name, parsed);
} catch {
// Parsing-Fehler ignorieren
}
});
ws.on('close', () => {
clearInterval(pingIntervals[name]);
delete wsConnections[name];
if (scriptStatus[name]) {
setTimeout(() => connectWebSocket(name, ip), 5000);
}
});
ws.on('error', () => {
// Fehler ignorieren
});
}
function disconnectWebSocket(name) {
if (wsConnections[name]) {
wsConnections[name].close();
clearInterval(pingIntervals[name]);
delete wsConnections[name];
delete pingIntervals[name];
}
}
function handleData(apName, parsedData) {
const ap = accesspoints.find(a => a.name === apName);
if (!ap || !scriptStatus[ap.name]) return;
if (!parsedData.tags || !Array.isArray(parsedData.tags) || parsedData.tags.length === 0) return;
parsedData.tags.forEach(tag => {
if (!tag.mac) return;
const macClean = tag.mac.replace(/:/g, '');
const basePath = `${ap.buttonPathPrefix}.${macClean}`;
ensureChannelExists(basePath, tag.alias || tag.name || 'Unbenannt', () => {
if ('wakeupReason' in tag) {
const statePath = `${basePath}.wakeupReason`;
updateStateIfChanged(statePath, tag.wakeupReason);
}
});
});
}
function ensureChannelExists(id, name, callback) {
getObject(id, (err, obj) => {
if (!obj) {
setObject(id, {
type: 'channel',
common: { name: name },
native: {}
}, callback);
} else {
callback();
}
});
}
function updateStateIfChanged(id, value) {
if (value === null || value === undefined) return;
const isPrimitive = val => ['string', 'number', 'boolean'].includes(typeof val);
let storedValue = value;
let valueType = typeof value;
if (!isPrimitive(value)) {
try {
storedValue = JSON.stringify(value);
valueType = 'string';
} catch {
return;
}
}
getState(id, (err, state) => {
if (err || !state) {
setObject(id, {
type: 'state',
common: {
name: id.split('.').pop(),
type: valueType,
role: 'value',
read: true,
write: false
},
native: {}
}, () => setState(id, storedValue, true));
} else if (state.val !== storedValue) {
setState(id, storedValue, true);
}
});
}