Weiter zum Inhalt
  • Home
  • Aktuell
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Hell
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dunkel
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. verschiedene Skripte

NEWS

  • Monatsrückblick Juli / August 2026 ist online!
    BluefoxB
    Bluefox
    9
    1
    378

  • Der neue Monatsrückblick für Mai und Juni 2026 ist online!
    BluefoxB
    Bluefox
    8
    1
    1.3k

  • wichtiges UPDATE für controller 7.2.2 im stable
    HomoranH
    Homoran
    10
    1
    3.8k

verschiedene Skripte

Geplant Angeheftet Gesperrt Verschoben Skripten / Logik
javascript
10 Beiträge 2 Kommentatoren 424 Aufrufe 4 Beobachtet
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • H Online
    H Online
    helfi9999
    schrieb am zuletzt editiert von helfi9999
    #1

    Hallo zusammen,
    habe mal bei mir aufgeräumt und habe eine ganze Menge an Skripten die ich von hier habe und stellenweise auch umgebaut habe die ich jetzt gerne mit euch teilen möchte:

    z.B.
    Musikstatus je Raum mit Alexa und/oder Sonos mit States Erstellung.Voraussetzung ist der Alexa Adapter und der Sonos Adapter:
    884f31a3-f1c5-4988-9e9c-7e4f0f68c5d3-image.jpeg
    Ihr müsst nur die Geräte im Skript ändern.

    
    /*************************************************
    * Musikstatus je Raum
    * mit State-Erstellung + Provider-Erkennung
    *************************************************/
    
    const rooms = [
       {
           name: "Wohnzimmer",
           target: "0_userdata.0.Status_Musikboxen.Wohnzimmer_Status",
           alexaState: "Deine Alexa.Player.currentState",
           alexaProvider: "Deine Alexa.Player.providerName",
           sonosState: "sonos.0.root.192_168_178_XXX.state_simple",
           sonosType: "sonos.0.root.192_168_178_XXX.current_type",
           delayMs: 0,
           config: { alexaDirectProvider: false, sonosMap: {0:"Musik von Platte",1:"TuneIn-Liveradio",2:"Fernseher"} }
       },
       {
           name: "Esszimmer",
           target: "0_userdata.0.Status_Musikboxen.Esszimmer_Status",
           alexaState: "Deine Alexa.Player.currentState",
           alexaProvider: "Deine Alexa.Player.providerName",
           sonosState: "sonos.0.root.192_168_178_XXX.state_simple",
           sonosType: "sonos.0.root.192_168_178_XXX.current_type",
           delayMs: 0,
           config: { alexaDirectProvider: false, sonosMap: {0:"Musik von Platte",1:"TuneIn-Liveradio"} }
       },
       {
           name: "Küche",
           target: "0_userdata.0.Status_Musikboxen.Küche_Status",
           alexaState: "Deine Alexa.Player.currentState",
           alexaProvider: "Deine Alexa.Player.providerName",
           sonosState: "sonos.0.root.192_168_178_XXX.state_simple",
           sonosType: "sonos.0.root.192_168_178_XXX.current_type",
           delayMs: 0,
           config: { alexaDirectProvider: false, sonosMap: {0:"Musik von Platte",1:"TuneIn-Liveradio"} }
       },
       {
           name: "Garten",
           target: "0_userdata.0.Status_Musikboxen.Garten_Status",
           alexaState: "Deine Alexa.Player.currentState",
           alexaProvider: "Deine Alexa.Player.providerName",
           delayMs: 2000,
           config: { alexaDirectProvider: true }
       },
       {
           name: "Schlafzimmer",
           target: "0_userdata.0.Status_Musikboxen.Schlafzimmer_Status",
           alexaState: "Deine Alexa.Player.currentState",
           alexaProvider: "Deine Alexa.Player.providerName",
           delayMs: 2000,
           config: { alexaDirectProvider: true }
       },
       {
           name: "Spielzimmer",
           target: "0_userdata.0.Status_Musikboxen.Spielzimmer_Status",
           alexaState: "Deine Alexa.Player.currentState",
           alexaProvider: "Deine Alexa.Player.providerName",
           delayMs: 0,
           config: { alexaDirectProvider: true }
       },
       {
           name: "Kinderzimmer",
           target: "0_userdata.0.Status_Musikboxen.Kinderzimmer_Status",
           alexaState: "Deine Alexa.Player.currentState",
           alexaProvider: "Deine Alexa.Player.providerName",
           delayMs: 2000,
           config: { alexaDirectProvider: true }
       },
       {
           name: "Gäste WC",
           target: "0_userdata.0.Status_Musikboxen.Gaeste_WC",
           alexaState: "Deine Alexa.Player.currentState",
           alexaProvider: "Deine Alexa.Player.providerName",
           delayMs: 0,
           config: { alexaDirectProvider: true }
       },
       {
           name: "Badezimmer",
           target: "0_userdata.0.Status_Musikboxen.Badezimmer_Status",
           alexaState: "Deine Alexa.Player.currentState",
           alexaProvider: "Deine Alexa.Player.providerName",
           sonosState: "sonos.0.root.192_168_178_XXX.state_simple",
           sonosType: "sonos.0.root.192_168_178_XXX.current_type",
           delayMs: 0,
           config: { alexaDirectProvider: false, sonosMap: {0:"Musik von Platte",1:"TuneIn-Liveradio"} }
       },
       {
           name: "Hobbyraum",
           target: "0_userdata.0.Status_Musikboxen.Hobbyraum_Status",
           alexaState: "Deine Alexa.Player.currentState",
           alexaProvider: "Deine Alexa.Player.providerName",
           sonosState: "sonos.0.root.192_168_178_XXX.state_simple",
           sonosType: "sonos.0.root.192_168_178_XXX.current_type",
           delayMs: 0,
           config: { alexaDirectProvider: false, sonosMap: {0:"Musik von Platte",1:"TuneIn-Liveradio"} }
       }
    ];
    
    /*********************** STATES ERSTELLEN ***********************/
    
    function createTargetState(room) {
       createState(room.target, "nichts", {
           name: `Musikstatus ${room.name}`,
           type: "string",
           role: "text",
           read: true,
           write: true
       });
    }
    
    /*********************** LOGIK ***********************/
    
    function readVal(id, def = null) {
       if (!id) return def;
       const s = getState(id);
       return s ? s.val : def;
    }
    
    function normalizeProvider(p) {
       if (!p) return "";
    
       const raw = String(p).trim();
       const t = raw.toLowerCase();
    
       if (t.includes("amazon")) return "Amazon Music";
       if (t.includes("spotify")) return "Spotify";
       if (t.includes("tunein") || t.includes("radio")) return "TuneIn-Liveradio";
       if (t.includes("audible")) return "Audible";
       if (t.includes("apple")) return "Apple Music";
       if (t.includes("deezer")) return "Deezer";
       if (t.includes("youtube")) return "YouTube";
       if (t.includes("podcast")) return "Podcast";
       if (t.includes("bluetooth") || t.includes("aux") || t.includes("line")) return "Externe Quelle";
    
       return raw;
    }
    
    function writeStatus(room, val) {
       if (room.delayMs > 0) {
           setStateDelayed(room.target, val, true, room.delayMs, true);
       } else {
           setState(room.target, val, true);
       }
    }
    
    function evalRoom(room) {
       const alexaPlaying = readVal(room.alexaState, false) === true;
       const alexaProvider = normalizeProvider(readVal(room.alexaProvider, ""));
       const sonosPlaying = readVal(room.sonosState, false) === true;
       const sonosType = readVal(room.sonosType, null);
    
       if (room.config.alexaDirectProvider) {
           if (alexaPlaying) {
               writeStatus(room, alexaProvider || "Andere Quelle");
               log(`+++ ${room.name}: ${alexaProvider || "Andere Quelle"} +++`, "debug");
           } else {
               writeStatus(room, "nichts");
           }
           return;
       }
    
       if (alexaPlaying && alexaProvider) {
           writeStatus(room, alexaProvider);
           return;
       }
    
       if (
           sonosPlaying &&
           room.config.sonosMap &&
           room.config.sonosMap[sonosType] !== undefined
       ) {
           writeStatus(room, room.config.sonosMap[sonosType]);
           return;
       }
    
       writeStatus(room, "nichts");
    }
    
    function initRoom(room) {
       createTargetState(room);
    
       const ids = [];
    
       if (room.alexaState) ids.push(room.alexaState);
       if (room.alexaProvider) ids.push(room.alexaProvider);
       if (room.sonosState) ids.push(room.sonosState);
       if (room.sonosType) ids.push(room.sonosType);
    
       if (ids.length === 0) {
           log(`Keine Trigger für ${room.name} konfiguriert`, "warn");
           return;
       }
    
       on({ id: ids, change: "ne" }, () => evalRoom(room));
    
       setTimeout(() => {
           evalRoom(room);
       }, 1000);
    }
    
    /*********************** START ***********************/
    
    rooms.forEach(initRoom);
    


    Lautstärken Reset in Verbindung mit dem Skript Musikstatus
    Funktionen:

      • Reagiert auf Statusänderung eines Raums
      • Prüft auf Zielstatus "nichts"
      • Setzt Lautstärke definierter Geräte nach optionaler Verzögerung
      • Verhindert Mehrfach-Timer pro Raum
      • Optionales Debug-Logging
      • Alexa notificationVolume wird explizit über notificationId gesetzt
      • Sonderfall Kinderzimmer: nur notificationVolume, kein Player.volume

    /**
     * Echo Stati / Lautstärke-Reset
     *
     * Funktionen:
     * - Reagiert auf Statusänderung eines Raums
     * - Prüft auf Zielstatus "nichts"
     * - Setzt Lautstärke definierter Geräte nach optionaler Verzögerung
     * - Verhindert Mehrfach-Timer pro Raum
     * - Optionales Debug-Logging
     * - Alexa notificationVolume wird explizit über notificationId gesetzt
     * - Sonderfall Kinderzimmer: nur notificationVolume, kein Player.volume
     */
    
    const CONFIG = {
        targetStatus: 'nichts',
        defaultDelayMs: 5000,
        debug: true,
        logPrefix: '[Musikboxen]',
        minNotificationVolume: 0,
        maxNotificationVolume: 100,
        defaultNotificationOffset: 5
    };
    
    const rooms = [
        {
            name: 'Küche',
            enabled: true,
            statusId: '0_userdata.0.Status_Musikboxen.Küche_Status',
            delayMs: 0,
            trigger: 'ne',
            devices: [
                {
                    id: 'alexa2.0.Echo-Devices.661b5e9aa0b24161a4ec52b340173846.Player.volume',
                    notificationId: 'alexa2.0.Echo-Devices.661b5e9aa0b24161a4ec52b340173846.Preferences.notificationVolume',
                    volume: 10,
                    notificationOffset: 5
                },
                {
                    id: 'alexa2.0.Echo-Devices.4879f7942cdb42d596f4e24aac81e908.Player.volume',
                    notificationId: 'alexa2.0.Echo-Devices.661b5e9aa0b24161a4ec52b340173846.Preferences.notificationVolume',
                    volume: 10,
                    notificationOffset: 5
                },
                {
                    id: 'sonos.0.root.192_168_178_18.volume',
                    volume: 10
                }
            ]
        },
        {
            name: 'Wohnzimmer',
            enabled: true,
            statusId: '0_userdata.0.Status_Musikboxen.Wohnzimmer_Status',
            delayMs: CONFIG.defaultDelayMs,
            trigger: 'any',
            devices: [
                {
                    id: 'alexa2.0.Echo-Devices.025b455db7bb4720ad941b7139bcc805.Player.volume',
                    notificationId: 'alexa2.0.Echo-Devices.d5794400dafd4c2cb0c8889fc15f0653.Preferences.notificationVolume',
                    volume: 10,
                    notificationOffset: 5
                },
                {
                    id: 'alexa2.0.Echo-Devices.d5794400dafd4c2cb0c8889fc15f0653.Player.volume',
                    notificationId: 'alexa2.0.Echo-Devices.d5794400dafd4c2cb0c8889fc15f0653.Preferences.notificationVolume',
                    volume: 10,
                    notificationOffset: 5
                },
                {
                    id: 'sonos.0.root.192_168_178_21.volume',
                    volume: 10
                }
            ]
        },
        {
            name: 'Esszimmer',
            enabled: true,
            statusId: '0_userdata.0.Status_Musikboxen.Esszimmer_Status',
            delayMs: CONFIG.defaultDelayMs,
            trigger: 'any',
            devices: [
                {
                    id: 'alexa2.0.Echo-Devices.084e4de76a484be18aeda245e8f3f4d4.Player.volume',
                    notificationId: 'alexa2.0.Echo-Devices.c31ec0fc26584e078ca0555aecfc9188.Preferences.notificationVolume',
                    volume: 10,
                    notificationOffset: 5
                },
                {
                    id: 'alexa2.0.Echo-Devices.c31ec0fc26584e078ca0555aecfc9188.Player.volume',
                    notificationId: 'alexa2.0.Echo-Devices.c31ec0fc26584e078ca0555aecfc9188.Preferences.notificationVolume',
                    volume: 10,
                    notificationOffset: 5
                },
                {
                    id: 'sonos.0.root.192_168_178_20.volume',
                    volume: 10
                }
            ]
        },
        {
            name: 'Schlafzimmer',
            enabled: true,
            statusId: '0_userdata.0.Status_Musikboxen.Schlafzimmer_Status',
            delayMs: CONFIG.defaultDelayMs,
            trigger: 'ne',
            devices: [
                {
                    id: 'alexa2.0.Echo-Devices.G091MK0614730BNS.Player.volume',
                    notificationId: 'alexa2.0.Echo-Devices.G091MK0614730BNS.Preferences.notificationVolume',
                    volume: 18,
                    notificationOffset: 12
                }
            ]
        },
        {
            name: 'Hobbyraum',
            enabled: true,
            statusId: '0_userdata.0.Status_Musikboxen.Hobbyraum_Status',
            delayMs: CONFIG.defaultDelayMs,
            trigger: 'ne',
            devices: [
                {
                    id: 'alexa2.0.Echo-Devices.d3127dcdc8bc4158807fcab2fcfe7fba.Player.volume',
                    notificationId: 'alexa2.0.Echo-Devices.c9d487971e914e939baad79585dd7b2e.Preferences.notificationVolume',
                    volume: 10,
                    notificationOffset: 5
                }
            ]
        },
        {
            name: 'Gäste WC',
            enabled: true,
            statusId: '0_userdata.0.Status_Musikboxen.Gaeste_WC',
            delayMs: CONFIG.defaultDelayMs,
            trigger: 'ne',
            devices: [
                {
                    id: 'alexa2.0.Echo-Devices.G090LF10718513KQ.Player.volume',
                    notificationId: 'alexa2.0.Echo-Devices.G090LF10718513KQ.Preferences.notificationVolume',
                    volume: 15,
                    notificationOffset: 8
                }
            ]
        },
        {
            name: 'Badezimmer',
            enabled: true,
            statusId: '0_userdata.0.Status_Musikboxen.Badezimmer_Status',
            delayMs: CONFIG.defaultDelayMs,
            trigger: 'any',
            devices: [
                {
                    id: 'alexa2.0.Echo-Devices.828b54738e2a44a29d9331868a046c38.Player.volume',
                    notificationId: 'alexa2.0.Echo-Devices.eba89b7180384792a24f92847baea082.Preferences.notificationVolume',
                    volume: 10,
                    notificationOffset: 5
                },
                {
                    id: 'alexa2.0.Echo-Devices.eba89b7180384792a24f92847baea082.Player.volume',
                    notificationId: 'alexa2.0.Echo-Devices.eba89b7180384792a24f92847baea082.Preferences.notificationVolume',
                    volume: 10,
                    notificationOffset: 5
                },
                {
                    id: 'sonos.0.root.192_168_178_17.volume',
                    volume: 10
                }
            ]
        },
        {
            name: 'Spielzimmer',
            enabled: true,
            statusId: '0_userdata.0.Status_Musikboxen.Spielzimmer_Status',
            delayMs: CONFIG.defaultDelayMs,
            trigger: 'any',
            devices: [
                {
                    id: 'alexa2.0.Echo-Devices.G2A0P3077407031K.Player.volume',
                    notificationId: 'alexa2.0.Echo-Devices.G2A0P3077407031K.Preferences.notificationVolume',
                    volume: 25,
                    notificationOffset: 15
                }
            ]
        },
        {
            name: 'Kinderzimmer',
            enabled: true,
            statusId: '0_userdata.0.Status_Musikboxen.Kinderzimmer_Status',
            delayMs: CONFIG.defaultDelayMs,
            trigger: 'any',
            devices: [
                {
                    notificationId: 'alexa2.0.Echo-Devices.G0911B05926204Q7.Preferences.notificationVolume',
                    volume: 11,
                    notificationOffset: 6,
                    notificationOnly: true
                }
            ]
        },
        {
            name: 'Garten',
            enabled: true,
            statusId: '0_userdata.0.Status_Musikboxen.Garten_Status',
            delayMs: CONFIG.defaultDelayMs,
            trigger: 'any',
            devices: [
                {
                    id: 'alexa2.0.Echo-Devices.G091AA08052203UL.Player.volume',
                    notificationId: 'alexa2.0.Echo-Devices.G091AA08052203UL.Preferences.notificationVolume',
                    volume: 15,
                    notificationOffset: 8
                }
            ]
        }
    ];
    
    const activeTimers = {};
    
    function logInfo(msg) {
        log(`${CONFIG.logPrefix} ${msg}`, 'info');
    }
    
    function logDebug(msg) {
        if (CONFIG.debug) {
            log(`${CONFIG.logPrefix} ${msg}`, 'debug');
        }
    }
    
    function logWarn(msg) {
        log(`${CONFIG.logPrefix} ${msg}`, 'warn');
    }
    
    function logError(msg) {
        log(`${CONFIG.logPrefix} ${msg}`, 'error');
    }
    
    function isTargetStatus(value) {
        if (value === null || value === undefined) return false;
        return String(value).trim() === CONFIG.targetStatus;
    }
    
    function isValidVolume(volume) {
        return typeof volume === 'number' && isFinite(volume) && volume >= 0 && volume <= 100;
    }
    
    function stateExists(id) {
        try {
            return !!getObject(id);
        } catch (e) {
            return false;
        }
    }
    
    function clamp(value, min, max) {
        return Math.max(min, Math.min(max, value));
    }
    
    function getNotificationVolume(volume, notificationOffset) {
        const offset = typeof notificationOffset === 'number'
            ? notificationOffset
            : CONFIG.defaultNotificationOffset;
    
        return clamp(
            volume - offset,
            CONFIG.minNotificationVolume,
            CONFIG.maxNotificationVolume
        );
    }
    
    function clearRoomTimer(roomName) {
        if (activeTimers[roomName]) {
            clearTimeout(activeTimers[roomName]);
            activeTimers[roomName] = null;
            logDebug(`${roomName}: vorhandener Timer gelöscht`);
        }
    }
    
    function setDeviceVolume(device, roomName) {
        if (!device) {
            logWarn(`${roomName}: ungültiges Gerät übersprungen`);
            return;
        }
    
        if (!isValidVolume(device.volume)) {
            logWarn(`${roomName}: ungültige Lautstärke ${device.volume}`);
            return;
        }
    
        if (!device.notificationOnly) {
            if (!device.id) {
                logWarn(`${roomName}: Gerät ohne ID übersprungen`);
                return;
            }
    
            if (!stateExists(device.id)) {
                logWarn(`${roomName}: Datenpunkt nicht gefunden: ${device.id}`);
                return;
            }
    
            try {
                setState(device.id, device.volume);
                logInfo(`${roomName}: Volume ${device.volume} gesetzt -> ${device.id}`);
            } catch (e) {
                logError(`${roomName}: Fehler beim Setzen von ${device.id}: ${e}`);
                return;
            }
        }
    
        if (device.notificationId) {
            if (!stateExists(device.notificationId)) {
                logWarn(`${roomName}: notificationVolume-Datenpunkt nicht gefunden: ${device.notificationId}`);
                return;
            }
    
            const notificationVolume = getNotificationVolume(device.volume, device.notificationOffset);
    
            try {
                setState(device.notificationId, notificationVolume);
                logInfo(`${roomName}: notificationVolume ${notificationVolume} gesetzt -> ${device.notificationId}`);
            } catch (e) {
                logError(`${roomName}: Fehler beim Setzen von ${device.notificationId}: ${e}`);
            }
        }
    }
    
    function resetRoomVolume(room) {
        if (!room || !Array.isArray(room.devices) || room.devices.length === 0) {
            logWarn(`${room && room.name ? room.name : 'Unbekannter Raum'}: keine Geräte konfiguriert`);
            activeTimers[room && room.name ? room.name : 'unknown'] = null;
            return;
        }
    
        room.devices.forEach(device => setDeviceVolume(device, room.name));
        activeTimers[room.name] = null;
    }
    
    function scheduleReset(room) {
        clearRoomTimer(room.name);
    
        const delayMs = typeof room.delayMs === 'number' && room.delayMs >= 0
            ? room.delayMs
            : CONFIG.defaultDelayMs;
    
        if (delayMs === 0) {
            logDebug(`${room.name}: sofortiger Reset`);
            resetRoomVolume(room);
            return;
        }
    
        logDebug(`${room.name}: Reset in ${delayMs} ms geplant`);
    
        activeTimers[room.name] = setTimeout(() => {
            activeTimers[room.name] = null;
            resetRoomVolume(room);
        }, delayMs);
    }
    
    function registerRoom(room) {
        if (!room || !room.name || !room.statusId) {
            logWarn('Ungültige Raum-Konfiguration übersprungen');
            return;
        }
    
        if (!room.enabled) {
            logDebug(`${room.name}: deaktiviert`);
            return;
        }
    
        if (!stateExists(room.statusId)) {
            logWarn(`${room.name}: Status-Datenpunkt nicht gefunden: ${room.statusId}`);
            return;
        }
    
        const trigger = room.trigger || 'ne';
    
        on({ id: room.statusId, change: trigger }, obj => {
            try {
                if (!obj || !obj.state) {
                    logDebug(`${room.name}: Event ohne state erhalten`);
                    return;
                }
    
                const newValue = obj.state.val;
                const oldValue = obj.oldState ? obj.oldState.val : undefined;
                const ack = obj.state.ack;
    
                logDebug(`${room.name}: Event | alt="${oldValue}" neu="${newValue}" ack=${ack}`);
    
                if (!isTargetStatus(newValue)) {
                    logDebug(`${room.name}: Status ist nicht "${CONFIG.targetStatus}", kein Reset`);
                    return;
                }
    
                scheduleReset(room);
            } catch (e) {
                logError(`${room.name}: Fehler im Event-Handler: ${e}`);
            }
        });
    
        logInfo(`${room.name}: Trigger registriert (${trigger}) auf ${room.statusId}`);
    }
    
    rooms.forEach(registerRoom);
    logInfo('Lautstärke-Reset-Skript mit expliziten notificationIds gestartet');
    
    


    es werden noch weitere folgen

    Intel NUC mit Iobroker

    1 Antwort Letzte Antwort
    0
    • H Online
      H Online
      helfi9999
      schrieb am zuletzt editiert von
      #2

      Blink Kamera im Wechsel:

      Vorraussetzung ist der Blink Adapter und das von mir entworfene Skript:

      // ===============================
      // Blink aktive Kamera / Bild / Zeit
      // Version: 1.2.0
      // ===============================
      
      const VERSION = '1.2.0';
      
      const aktiveKamera = '0_userdata.0.Blink.aktive_Kamera';
      const aktivesBild  = '0_userdata.0.Blink.aktives_Bild';
      const aktiveZeit   = '0_userdata.0.Blink.aktive_Zeit';
      
      // Gemeinsame Blink-Sperre für alle Blink-Scripts
      const blinkBusyUntil = '0_userdata.0.Blink.busy_until';
      const blinkBusyInfo  = '0_userdata.0.Blink.busy_info';
      
      const kamera1 = 'blink.0.cameras.706479.live.image_base64';
      const kamera2 = 'blink.0.cameras.1327710.live.image_base64';
      
      const zeit1 = 'blink.0.cameras.706479.live.timestamp';
      const zeit2 = 'blink.0.cameras.1327710.live.timestamp';
      
      const snapshot1 = 'blink.0.cameras.706479.commands.snapshot';
      const snapshot2 = 'blink.0.cameras.1327710.commands.snapshot';
      
      const DEFAULT_KAMERA = '706479';
      
      // Blink ist empfindlich bei zu vielen Befehlen
      const BLINK_SPERRE_MS       = 90000;  // 90 Sekunden Pause nach Snapshot
      const SNAPSHOT_TIMEOUT_MS   = 30000;  // 30 Sekunden auf neuen Timestamp warten
      const DEBOUNCE_MS           = 1500;   // Kamerawechsel entprellen
      
      let letzterTimestamp706479 = '';
      let letzterTimestamp1327710 = '';
      
      let snapshotLaeuft = false;
      let pendingSnapshot = false;
      let debounceTimer = null;
      let waitTimer = null;
      let pollTimer = null;
      
      function ensureState(id, def, common) {
         if (!existsState(id)) {
             createState(id, def, common);
         }
      }
      
      ensureState(aktiveKamera, DEFAULT_KAMERA, {
         type: 'string',
         role: 'text',
         name: 'Aktive Blink Kamera',
         read: true,
         write: true
      });
      
      ensureState(aktivesBild, '', {
         type: 'string',
         role: 'text',
         name: 'Aktives Blink Bild',
         read: true,
         write: true
      });
      
      ensureState(aktiveZeit, '', {
         type: 'string',
         role: 'text',
         name: 'Aktive Blink Zeit',
         read: true,
         write: true
      });
      
      ensureState(blinkBusyUntil, 0, {
         type: 'number',
         role: 'value',
         name: 'Blink busy until timestamp',
         read: true,
         write: true
      });
      
      ensureState(blinkBusyInfo, '', {
         type: 'string',
         role: 'text',
         name: 'Blink busy info',
         read: true,
         write: true
      });
      
      function getBusyUntil() {
         const state = getState(blinkBusyUntil);
      
         if (!state || state.val === null || state.val === undefined) {
             return 0;
         }
      
         const value = Number(state.val);
         return isNaN(value) ? 0 : value;
      }
      
      function istBlinkBusy() {
         return Date.now() < getBusyUntil();
      }
      
      function getRestzeitMs() {
         return Math.max(0, getBusyUntil() - Date.now());
      }
      
      function setBlinkBusy(ms, info) {
         const until = Date.now() + ms;
      
         setState(blinkBusyUntil, until, true);
         setState(blinkBusyInfo, info, true);
      
         log(`[v${VERSION}] Blink gesperrt für ${Math.ceil(ms / 1000)}s: ${info}`, 'info');
      }
      
      function getKameraWert() {
         const state = getState(aktiveKamera);
      
         if (!state || state.val === null || state.val === undefined || state.val === '') {
             return DEFAULT_KAMERA;
         }
      
         const cam = String(state.val).replace(/"/g, '');
      
         if (cam !== '706479' && cam !== '1327710') {
             log(`[v${VERSION}] Blink: Ungültige Kamera "${cam}", verwende ${DEFAULT_KAMERA}`, 'warn');
             return DEFAULT_KAMERA;
         }
      
         return cam;
      }
      
      function getBildQuelle(cam) {
         return cam === '1327710' ? kamera2 : kamera1;
      }
      
      function getZeitQuelle(cam) {
         return cam === '1327710' ? zeit2 : zeit1;
      }
      
      function getSnapshotQuelle(cam) {
         return cam === '1327710' ? snapshot2 : snapshot1;
      }
      
      function getLetztenTimestamp(cam) {
         return cam === '1327710' ? letzterTimestamp1327710 : letzterTimestamp706479;
      }
      
      function setLetztenTimestamp(cam, value) {
         if (cam === '1327710') {
             letzterTimestamp1327710 = value;
         } else {
             letzterTimestamp706479 = value;
         }
      }
      
      function formatZeitBerlin(timestamp) {
         const datum = new Date(timestamp);
      
         if (isNaN(datum.getTime())) {
             return String(timestamp);
         }
      
         return datum.toLocaleString('de-DE', {
             timeZone: 'Europe/Berlin',
             day: '2-digit',
             month: '2-digit',
             year: 'numeric',
             hour: '2-digit',
             minute: '2-digit'
         }).replace(',', '');
      }
      
      function updateBild(cam) {
         const quelle = getBildQuelle(cam);
         const bildState = getState(quelle);
      
         if (!bildState || !bildState.val) {
             log(`[v${VERSION}] Blink: Kein Bild vorhanden von ${quelle}`, 'warn');
             return false;
         }
      
         if (getKameraWert() === cam) {
             setState(aktivesBild, String(bildState.val), true);
         }
      
         return true;
      }
      
      function updateZeit(cam) {
         const quelle = getZeitQuelle(cam);
         const zeitState = getState(quelle);
      
         if (!zeitState || !zeitState.val) {
             log(`[v${VERSION}] Blink: Keine Zeit vorhanden von ${quelle}`, 'warn');
             return false;
         }
      
         const formatiert = formatZeitBerlin(zeitState.val);
      
         if (getKameraWert() === cam) {
             setState(aktiveZeit, formatiert, true);
         }
      
         return true;
      }
      
      function updateAlles(cam) {
         cam = cam || getKameraWert();
      
         updateBild(cam);
         updateZeit(cam);
      }
      
      function snapshotAusloesen(cam) {
         const snapshot = getSnapshotQuelle(cam);
      
         log(`[v${VERSION}] Blink: Snapshot auslösen: ${cam}`, 'info');
      
         // Befehl aktiv auslösen
         setState(snapshot, true, false);
      }
      
      function planeSnapshotNachSperre() {
         if (waitTimer) {
             clearTimeout(waitTimer);
         }
      
         const wait = getRestzeitMs() + 1000;
      
         log(`[v${VERSION}] Blink ist busy. Snapshot wird in ${Math.ceil(wait / 1000)}s erneut versucht.`, 'warn');
      
         waitTimer = setTimeout(function () {
             waitTimer = null;
      
             if (pendingSnapshot && !snapshotLaeuft) {
                 pendingSnapshot = false;
                 updateNachSnapshot();
             }
         }, wait);
      }
      
      function updateNachSnapshot() {
         const cam = getKameraWert();
      
         if (snapshotLaeuft) {
             pendingSnapshot = true;
             log(`[v${VERSION}] Blink: Snapshot läuft bereits, neuer Wunsch wird gemerkt: ${cam}`, 'warn');
             return;
         }
      
         if (istBlinkBusy()) {
             pendingSnapshot = true;
             planeSnapshotNachSperre();
             return;
         }
      
         snapshotLaeuft = true;
         pendingSnapshot = false;
      
         const zeitQuelle = getZeitQuelle(cam);
         const alterTimestampState = getState(zeitQuelle);
         const alterTimestamp = alterTimestampState && alterTimestampState.val ? String(alterTimestampState.val) : '';
      
         setLetztenTimestamp(cam, alterTimestamp);
      
         setBlinkBusy(BLINK_SPERRE_MS, `Snapshot Kamera ${cam}`);
         snapshotAusloesen(cam);
      
         let vergangen = 0;
      
         if (pollTimer) {
             clearInterval(pollTimer);
             pollTimer = null;
         }
      
         pollTimer = setInterval(function () {
             vergangen += 1000;
      
             const aktuelleCam = getKameraWert();
             const neuerTimestampState = getState(zeitQuelle);
             const neuerTimestamp = neuerTimestampState && neuerTimestampState.val ? String(neuerTimestampState.val) : '';
      
             if (neuerTimestamp && neuerTimestamp !== getLetztenTimestamp(cam)) {
                 setLetztenTimestamp(cam, neuerTimestamp);
      
                 if (aktuelleCam === cam) {
                     updateAlles(cam);
                 }
      
                 clearInterval(pollTimer);
                 pollTimer = null;
                 snapshotLaeuft = false;
      
                 log(`[v${VERSION}] Blink: Snapshot erfolgreich aktualisiert: ${cam}`, 'info');
      
                 if (pendingSnapshot) {
                     planeSnapshotNachSperre();
                 }
      
                 return;
             }
      
             if (vergangen >= SNAPSHOT_TIMEOUT_MS) {
                 if (aktuelleCam === cam) {
                     updateAlles(cam);
                 }
      
                 clearInterval(pollTimer);
                 pollTimer = null;
                 snapshotLaeuft = false;
      
                 log(`[v${VERSION}] Blink: Snapshot hat nach ${SNAPSHOT_TIMEOUT_MS / 1000}s keinen neuen Timestamp geliefert: ${cam}`, 'warn');
      
                 if (pendingSnapshot) {
                     planeSnapshotNachSperre();
                 }
             }
         }, 1000);
      }
      
      function kameraWechselEntprellt() {
         if (debounceTimer) {
             clearTimeout(debounceTimer);
         }
      
         debounceTimer = setTimeout(function () {
             debounceTimer = null;
             updateNachSnapshot();
         }, DEBOUNCE_MS);
      }
      
      // Nur bei echter Änderung reagieren
      on({ id: aktiveKamera, change: 'ne' }, function () {
         kameraWechselEntprellt();
      });
      
      on({ id: kamera1, change: 'ne' }, function () {
         if (getKameraWert() === '706479') {
             updateBild('706479');
         }
      });
      
      on({ id: kamera2, change: 'ne' }, function () {
         if (getKameraWert() === '1327710') {
             updateBild('1327710');
         }
      });
      
      on({ id: zeit1, change: 'ne' }, function () {
         if (getKameraWert() === '706479') {
             updateZeit('706479');
         }
      });
      
      on({ id: zeit2, change: 'ne' }, function () {
         if (getKameraWert() === '1327710') {
             updateZeit('1327710');
         }
      });
      
      log(`[v${VERSION}] Blink aktive Kamera Script gestartet`, 'info');
      
      setTimeout(function () {
         updateAlles();
      }, 1000);
      


      Habe an der Terrassentür ein Türkontakt wenn die Tür auf ist nimmt die Kamera im Garten nicht auf das gleiche ist auch bei der Haustür.

      f0ad6a37-62ee-486d-86c0-a1ba28cb2530-image.jpeg

      Intel NUC mit Iobroker

      1 Antwort Letzte Antwort
      0
      • H Online
        H Online
        helfi9999
        schrieb am zuletzt editiert von helfi9999
        #3

        ECOVACS ioBroker UNIVERSAL – KOMPLETTPAKET v6.4

        Dieses Paket ist universell aufgebaut.

        Es ist NICHT fest auf Namen wie Luna oder Sky programmiert.
        Es erkennt alle eingebundenen Instanzen nach dem Muster:

        ecovacs-deebot.x
        

        und legt pro erkanntem Sauger eine eigene Struktur an:

        0_userdata.0.Sauger.<Gerätename>
        

        Beispiel:

        0_userdata.0.Sauger.Luna
        0_userdata.0.Sauger.Sky
        

        Bei einem anderen Benutzer entstehen automatisch dessen eigene Gerätenamen.
        ENTHALTENE SKRIPTE

        1. 01_Ecovacs_Universal_Setup_v6.0.js
          Aufgabe:
        • erkennt alle ecovacs-deebot.* Instanzen
        • versucht den Gerätenamen automatisch zu lesen
        • erkennt die Map-ID
        • erkennt alle spotAreas / Räume
        • legt die benötigten 0_userdata-Datenpunkte an

        Betrieb:

        • EINMAL starten
        • danach wieder AUS

        Wenn später ein neuer Sauger hinzukommt:

        • Setup erneut kurz starten
        • danach wieder AUS
        1. 02_Ecovacs_Universal_MapSource_v6.1.js
          Aufgabe:
        • sucht pro Sauger automatisch nach einer Kartenquelle

        • bevorzugt:
          ecovacs-deebot.x.map.<mapId>.map64

        • versucht bei vorhandenem loadMapImage die Karte regelmäßig neu anzufordern

        • schreibt die erkannte Quelle nach:

          0_userdata.0.Sauger.<Name>.Map.Source.type
          0_userdata.0.Sauger.<Name>.Map.Source.state
          0_userdata.0.Sauger.<Name>.Map.Source.image
          0_userdata.0.Sauger.<Name>.Map.Source.status

        Betrieb:

        • dauerhaft AN

        Hinweis:
        Die aktuelle VIS v6.4 verwendet das Kartenbild nicht mehr als Hintergrund.
        Der MapSource kann trotzdem aktiv bleiben, weil er weiterhin universell die
        Kartenquelle ermittelt und für Diagnose / spätere Erweiterungen verfügbar hält.

        1. 03_Ecovacs_Universal_Position_Fahrspur_v6.0.js

        Aufgabe:

        • liest pro Sauger:

          ecovacs-deebot.x.map.deebotPosition

        • berechnet daraus die Position auf der Karte

        • aktualisiert:
          Map.pixelXcss
          Map.pixelYcss
          Map.rotateCss

        • zeichnet eine Fahrspur

        • setzt die Fahrspur bei einem neuen Reinigungsvorgang zurück

        • übernimmt Status und Positionsname, sofern vorhanden

        Betrieb:

        • dauerhaft AN
        1. 04_Ecovacs_Universal_RaumSync_v6.0.js

        Aufgabe:

        • synchronisiert pro Raum:

          markForNextSpotAreaCleaning

        mit:

        0_userdata.0.Sauger.<Name>.Rooms.<id>.selected
        

        Dadurch weiß die VIS, ob ein Raum ausgewählt ist.

        Betrieb:

        • dauerhaft AN
        1. 05_Ecovacs_Universal_Raumflaechen_Detektor_v6.2.js
          Aufgabe:
        • durchsucht jeden automatisch erkannten Raum nach Geometriedaten

        • sucht unter anderem nach:
          polygon
          boundary
          boundaries
          coordinates
          coords
          points
          vertices
          outline
          contour
          rect
          bounds

        • wandelt gefundene Raumgeometrien in SVG-Punkte um

        • speichert pro Raum:

          Rooms.<id>.geometryState
          Rooms.<id>.geometryType
          Rooms.<id>.polygonPoints
          Rooms.<id>.geometryStatus

        Betrieb:

        • dauerhaft AN

        Wenn ein Sauger keine Raumgeometrie bereitstellt:

        • polygonPoints bleibt leer
        • die VIS kann dann keine Raumfläche zeichnen
        1. 06_Ecovacs_Universal_VIS_Raumflaechen_v6.4.js

        Aufgabe:

        • erzeugt die komplette VIS-Darstellung
        • dunkler Hintergrund
        • automatisch erkannte farbige Raumflächen
        • Raumflächen direkt anklickbar
        • Fahrspur
        • Roboterposition
        • KEINE zusätzlichen Raum-Buttons mehr

        Betrieb:

        • dauerhaft AN

        INSTALLATION:

        1. In ioBroker unter JavaScript für jede .js-Datei ein eigenes Skript anlegen.

        2. Den Inhalt der jeweiligen .js-Datei komplett in das entsprechende
          JavaScript-Skript kopieren.

        EMPFOHLENE REIHENFOLGE
        Schritt 1:
        01_Ecovacs_Universal_Setup_v6.0.js
        kurz AN

        Warten, bis die Struktur unter:

        0_userdata.0.Sauger
        

        angelegt wurde.

        Danach:
        01 Setup AUS

        Schritt 2:
        Folgende Skripte dauerhaft AN:

        02_Ecovacs_Universal_MapSource_v6.1.js
        03_Ecovacs_Universal_Position_Fahrspur_v6.0.js
        04_Ecovacs_Universal_RaumSync_v6.0.js
        05_Ecovacs_Universal_Raumflaechen_Detektor_v6.2.js
        06_Ecovacs_Universal_VIS_Raumflaechen_v6.4.js
        

        WELCHE SKRIPTE SIND AN / AUS?
        01 Setup:
        AUS
        Nur bei Erstinstallation oder neuem Sauger kurz AN.

        02 MapSource:
        AN

        03 Position/Fahrspur:
        AN

        04 RaumSync:
        AN

        05 Raumflächen-Detektor:
        AN

        06 VIS:
        AN

        VIS EINRICHTEN

        In VIS ein Widget verwenden:

        Basic -> String (unescaped)
        

        Als Objekt-ID:

        0_userdata.0.Sauger.<Gerätename>.VIS.html
        

        Beispiel:

        0_userdata.0.Sauger.Luna.VIS.html
        

        Keine geschweiften Klammern verwenden.

        Also NICHT:

        {0_userdata.0.Sauger.Luna.VIS.html}
        

        sondern direkt:

        0_userdata.0.Sauger.Luna.VIS.html
        

        BEDIENUNG

        RAUM AUSWÄHLEN

        Einfach direkt auf die farbige Raumfläche in der Karte klicken.

        Beim Klick wird der zugehörige Adapter-State geschaltet:

        ecovacs-deebot.x.map.<mapId>.spotAreas.<id>.markForNextSpotAreaCleaning
        

        Der RaumSync übernimmt den Zustand anschließend nach:

        0_userdata.0.Sauger.<Name>.Rooms.<id>.selected
        

        Ein ausgewählter Raum wird in der VIS stärker hervorgehoben.

        MEHRERE RÄUME

        Mehrere Raumflächen können nacheinander angeklickt werden.

        Die Auswahl wird direkt über die Adapter-States vorgenommen.

        FAHRSPUR

        Die Fahrspur wird aus deebotPosition erzeugt.

        Sie liegt in:

        0_userdata.0.Sauger.<Name>.Map.trailPoints
        

        Beim Beginn eines neuen Reinigungsvorgangs wird sie zurückgesetzt.

        ROBOTERPOSITION

        Die Position wird aus:

        ecovacs-deebot.x.map.deebotPosition
        

        ermittelt.

        Die VIS verwendet:

        Map.pixelXcss
        Map.pixelYcss
        Map.rotateCss
        

        RAUMFLÄCHEN-DIAGNOSE

        Wenn ein Raum nicht gezeichnet wird, prüfen:

        0_userdata.0.Sauger.<Name>.Rooms.<id>.geometryStatus
        

        und:

        0_userdata.0.Sauger.<Name>.Rooms.<id>.geometryState
        

        und:

        0_userdata.0.Sauger.<Name>.Rooms.<id>.polygonPoints
        

        Wenn geometryStatus meldet:

        Keine Raumgeometrie im Adapter gefunden
        

        dann liefert dieses Modell / diese Adapterversion für diesen Raum keine
        verwertbaren Polygon- oder Boundary-Daten.

        KARTENQUELLEN-DIAGNOSE

        Prüfen:

        0_userdata.0.Sauger.<Name>.Map.Source.status
        

        und:

        0_userdata.0.Sauger.<Name>.Map.Source.state
        

        POSITION PASST NICHT ZUR KARTE

        Die Koordinatenumrechnung verwendet pro Sauger:

        Map.Config.minX
        Map.Config.maxX
        Map.Config.minY
        Map.Config.maxY
        Map.Config.imgW
        Map.Config.imgH
        

        Standard:

        minX = -250
        maxX = 10700
        minY = -4350
        maxY = 400
        imgW = 540
        imgH = 231
        

        Diese Werte können pro Sauger angepasst werden.

        Wichtig:
        Die Raumflächen-Erkennung versucht selbst zu unterscheiden, ob Raumkoordinaten
        bereits Pixelwerte sind oder Weltkoordinaten umgerechnet werden müssen.

        NEUER SAUGER

        Wenn später eine weitere ecovacs-deebot.* Instanz installiert wird:

        1. Setup v6.0 kurz AN.
        2. Warten, bis der neue Sauger unter 0_userdata.0.Sauger erscheint.
        3. Setup wieder AUS.
        4. Die dauerhaft laufenden Skripte einmal neu starten.

        Danach wird der neue Sauger automatisch mit verarbeitet.

        MEHRERE SAUGER

        Alle dauerhaft laufenden Skripte suchen automatisch nach:

        0_userdata.0.Sauger.*.deebotPrefix
        

        Dadurch wird nicht nur ein einzelner Sauger verarbeitet.

        Jeder Sauger besitzt:

        • eigene Map-ID
        • eigene Räume
        • eigene Raumflächen
        • eigene Position
        • eigene Fahrspur
        • eigenes VIS.html

        WICHTIGE GRENZEN

        Das Paket kann nur Daten verwenden, die der Ecovacs-Adapter für das jeweilige
        Modell bereitstellt.

        Wenn ein Modell:

        • keine deebotPosition liefert -> keine Live-Position/Fahrspur
        • keine spotAreas liefert -> keine automatische Raumauswahl
        • keine Geometrie für spotAreas liefert -> keine gezeichneten Raumflächen

        Das Paket versucht diese Funktionen automatisch zu erkennen und ist nicht
        auf einen bestimmten Sauger oder Grundriss fest programmiert.

        Die Buttons muss man selbst erstellen wie hier:
        c42a3904-8b6b-4077-ba10-9b0379503363-image.jpeg

        Viel Spass beim ausprobieren !!

        Intel NUC mit Iobroker

        sigi234S H 3 Antworten Letzte Antwort
        1
        • H helfi9999

          ECOVACS ioBroker UNIVERSAL – KOMPLETTPAKET v6.4

          Dieses Paket ist universell aufgebaut.

          Es ist NICHT fest auf Namen wie Luna oder Sky programmiert.
          Es erkennt alle eingebundenen Instanzen nach dem Muster:

          ecovacs-deebot.x
          

          und legt pro erkanntem Sauger eine eigene Struktur an:

          0_userdata.0.Sauger.<Gerätename>
          

          Beispiel:

          0_userdata.0.Sauger.Luna
          0_userdata.0.Sauger.Sky
          

          Bei einem anderen Benutzer entstehen automatisch dessen eigene Gerätenamen.
          ENTHALTENE SKRIPTE

          1. 01_Ecovacs_Universal_Setup_v6.0.js
            Aufgabe:
          • erkennt alle ecovacs-deebot.* Instanzen
          • versucht den Gerätenamen automatisch zu lesen
          • erkennt die Map-ID
          • erkennt alle spotAreas / Räume
          • legt die benötigten 0_userdata-Datenpunkte an

          Betrieb:

          • EINMAL starten
          • danach wieder AUS

          Wenn später ein neuer Sauger hinzukommt:

          • Setup erneut kurz starten
          • danach wieder AUS
          1. 02_Ecovacs_Universal_MapSource_v6.1.js
            Aufgabe:
          • sucht pro Sauger automatisch nach einer Kartenquelle

          • bevorzugt:
            ecovacs-deebot.x.map.<mapId>.map64

          • versucht bei vorhandenem loadMapImage die Karte regelmäßig neu anzufordern

          • schreibt die erkannte Quelle nach:

            0_userdata.0.Sauger.<Name>.Map.Source.type
            0_userdata.0.Sauger.<Name>.Map.Source.state
            0_userdata.0.Sauger.<Name>.Map.Source.image
            0_userdata.0.Sauger.<Name>.Map.Source.status

          Betrieb:

          • dauerhaft AN

          Hinweis:
          Die aktuelle VIS v6.4 verwendet das Kartenbild nicht mehr als Hintergrund.
          Der MapSource kann trotzdem aktiv bleiben, weil er weiterhin universell die
          Kartenquelle ermittelt und für Diagnose / spätere Erweiterungen verfügbar hält.

          1. 03_Ecovacs_Universal_Position_Fahrspur_v6.0.js

          Aufgabe:

          • liest pro Sauger:

            ecovacs-deebot.x.map.deebotPosition

          • berechnet daraus die Position auf der Karte

          • aktualisiert:
            Map.pixelXcss
            Map.pixelYcss
            Map.rotateCss

          • zeichnet eine Fahrspur

          • setzt die Fahrspur bei einem neuen Reinigungsvorgang zurück

          • übernimmt Status und Positionsname, sofern vorhanden

          Betrieb:

          • dauerhaft AN
          1. 04_Ecovacs_Universal_RaumSync_v6.0.js

          Aufgabe:

          • synchronisiert pro Raum:

            markForNextSpotAreaCleaning

          mit:

          0_userdata.0.Sauger.<Name>.Rooms.<id>.selected
          

          Dadurch weiß die VIS, ob ein Raum ausgewählt ist.

          Betrieb:

          • dauerhaft AN
          1. 05_Ecovacs_Universal_Raumflaechen_Detektor_v6.2.js
            Aufgabe:
          • durchsucht jeden automatisch erkannten Raum nach Geometriedaten

          • sucht unter anderem nach:
            polygon
            boundary
            boundaries
            coordinates
            coords
            points
            vertices
            outline
            contour
            rect
            bounds

          • wandelt gefundene Raumgeometrien in SVG-Punkte um

          • speichert pro Raum:

            Rooms.<id>.geometryState
            Rooms.<id>.geometryType
            Rooms.<id>.polygonPoints
            Rooms.<id>.geometryStatus

          Betrieb:

          • dauerhaft AN

          Wenn ein Sauger keine Raumgeometrie bereitstellt:

          • polygonPoints bleibt leer
          • die VIS kann dann keine Raumfläche zeichnen
          1. 06_Ecovacs_Universal_VIS_Raumflaechen_v6.4.js

          Aufgabe:

          • erzeugt die komplette VIS-Darstellung
          • dunkler Hintergrund
          • automatisch erkannte farbige Raumflächen
          • Raumflächen direkt anklickbar
          • Fahrspur
          • Roboterposition
          • KEINE zusätzlichen Raum-Buttons mehr

          Betrieb:

          • dauerhaft AN

          INSTALLATION:

          1. In ioBroker unter JavaScript für jede .js-Datei ein eigenes Skript anlegen.

          2. Den Inhalt der jeweiligen .js-Datei komplett in das entsprechende
            JavaScript-Skript kopieren.

          EMPFOHLENE REIHENFOLGE
          Schritt 1:
          01_Ecovacs_Universal_Setup_v6.0.js
          kurz AN

          Warten, bis die Struktur unter:

          0_userdata.0.Sauger
          

          angelegt wurde.

          Danach:
          01 Setup AUS

          Schritt 2:
          Folgende Skripte dauerhaft AN:

          02_Ecovacs_Universal_MapSource_v6.1.js
          03_Ecovacs_Universal_Position_Fahrspur_v6.0.js
          04_Ecovacs_Universal_RaumSync_v6.0.js
          05_Ecovacs_Universal_Raumflaechen_Detektor_v6.2.js
          06_Ecovacs_Universal_VIS_Raumflaechen_v6.4.js
          

          WELCHE SKRIPTE SIND AN / AUS?
          01 Setup:
          AUS
          Nur bei Erstinstallation oder neuem Sauger kurz AN.

          02 MapSource:
          AN

          03 Position/Fahrspur:
          AN

          04 RaumSync:
          AN

          05 Raumflächen-Detektor:
          AN

          06 VIS:
          AN

          VIS EINRICHTEN

          In VIS ein Widget verwenden:

          Basic -> String (unescaped)
          

          Als Objekt-ID:

          0_userdata.0.Sauger.<Gerätename>.VIS.html
          

          Beispiel:

          0_userdata.0.Sauger.Luna.VIS.html
          

          Keine geschweiften Klammern verwenden.

          Also NICHT:

          {0_userdata.0.Sauger.Luna.VIS.html}
          

          sondern direkt:

          0_userdata.0.Sauger.Luna.VIS.html
          

          BEDIENUNG

          RAUM AUSWÄHLEN

          Einfach direkt auf die farbige Raumfläche in der Karte klicken.

          Beim Klick wird der zugehörige Adapter-State geschaltet:

          ecovacs-deebot.x.map.<mapId>.spotAreas.<id>.markForNextSpotAreaCleaning
          

          Der RaumSync übernimmt den Zustand anschließend nach:

          0_userdata.0.Sauger.<Name>.Rooms.<id>.selected
          

          Ein ausgewählter Raum wird in der VIS stärker hervorgehoben.

          MEHRERE RÄUME

          Mehrere Raumflächen können nacheinander angeklickt werden.

          Die Auswahl wird direkt über die Adapter-States vorgenommen.

          FAHRSPUR

          Die Fahrspur wird aus deebotPosition erzeugt.

          Sie liegt in:

          0_userdata.0.Sauger.<Name>.Map.trailPoints
          

          Beim Beginn eines neuen Reinigungsvorgangs wird sie zurückgesetzt.

          ROBOTERPOSITION

          Die Position wird aus:

          ecovacs-deebot.x.map.deebotPosition
          

          ermittelt.

          Die VIS verwendet:

          Map.pixelXcss
          Map.pixelYcss
          Map.rotateCss
          

          RAUMFLÄCHEN-DIAGNOSE

          Wenn ein Raum nicht gezeichnet wird, prüfen:

          0_userdata.0.Sauger.<Name>.Rooms.<id>.geometryStatus
          

          und:

          0_userdata.0.Sauger.<Name>.Rooms.<id>.geometryState
          

          und:

          0_userdata.0.Sauger.<Name>.Rooms.<id>.polygonPoints
          

          Wenn geometryStatus meldet:

          Keine Raumgeometrie im Adapter gefunden
          

          dann liefert dieses Modell / diese Adapterversion für diesen Raum keine
          verwertbaren Polygon- oder Boundary-Daten.

          KARTENQUELLEN-DIAGNOSE

          Prüfen:

          0_userdata.0.Sauger.<Name>.Map.Source.status
          

          und:

          0_userdata.0.Sauger.<Name>.Map.Source.state
          

          POSITION PASST NICHT ZUR KARTE

          Die Koordinatenumrechnung verwendet pro Sauger:

          Map.Config.minX
          Map.Config.maxX
          Map.Config.minY
          Map.Config.maxY
          Map.Config.imgW
          Map.Config.imgH
          

          Standard:

          minX = -250
          maxX = 10700
          minY = -4350
          maxY = 400
          imgW = 540
          imgH = 231
          

          Diese Werte können pro Sauger angepasst werden.

          Wichtig:
          Die Raumflächen-Erkennung versucht selbst zu unterscheiden, ob Raumkoordinaten
          bereits Pixelwerte sind oder Weltkoordinaten umgerechnet werden müssen.

          NEUER SAUGER

          Wenn später eine weitere ecovacs-deebot.* Instanz installiert wird:

          1. Setup v6.0 kurz AN.
          2. Warten, bis der neue Sauger unter 0_userdata.0.Sauger erscheint.
          3. Setup wieder AUS.
          4. Die dauerhaft laufenden Skripte einmal neu starten.

          Danach wird der neue Sauger automatisch mit verarbeitet.

          MEHRERE SAUGER

          Alle dauerhaft laufenden Skripte suchen automatisch nach:

          0_userdata.0.Sauger.*.deebotPrefix
          

          Dadurch wird nicht nur ein einzelner Sauger verarbeitet.

          Jeder Sauger besitzt:

          • eigene Map-ID
          • eigene Räume
          • eigene Raumflächen
          • eigene Position
          • eigene Fahrspur
          • eigenes VIS.html

          WICHTIGE GRENZEN

          Das Paket kann nur Daten verwenden, die der Ecovacs-Adapter für das jeweilige
          Modell bereitstellt.

          Wenn ein Modell:

          • keine deebotPosition liefert -> keine Live-Position/Fahrspur
          • keine spotAreas liefert -> keine automatische Raumauswahl
          • keine Geometrie für spotAreas liefert -> keine gezeichneten Raumflächen

          Das Paket versucht diese Funktionen automatisch zu erkennen und ist nicht
          auf einen bestimmten Sauger oder Grundriss fest programmiert.

          Die Buttons muss man selbst erstellen wie hier:
          c42a3904-8b6b-4077-ba10-9b0379503363-image.jpeg

          Viel Spass beim ausprobieren !!

          sigi234S Online
          sigi234S Online
          sigi234
          Forum Testing Most Active
          schrieb am zuletzt editiert von
          #4

          @helfi9999
          So ganz begreife ich nicht wo ich was ersetzen muss, werden die DP automatisch angelegt?

          Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
          Immer Daten sichern!

          H 2 Antworten Letzte Antwort
          0
          • sigi234S sigi234

            @helfi9999
            So ganz begreife ich nicht wo ich was ersetzen muss, werden die DP automatisch angelegt?

            H Online
            H Online
            helfi9999
            schrieb am zuletzt editiert von
            #5

            @sigi234 Hallo werde am Wochenende es umändern zum vereinfachen.

            Intel NUC mit Iobroker

            1 Antwort Letzte Antwort
            1
            • sigi234S sigi234

              @helfi9999
              So ganz begreife ich nicht wo ich was ersetzen muss, werden die DP automatisch angelegt?

              H Online
              H Online
              helfi9999
              schrieb zuletzt editiert von
              #6

              @sigi234 das Ecovacs Skript habe ich geändert so das man nichts ersetzen muss.

              Intel NUC mit Iobroker

              sigi234S 1 Antwort Letzte Antwort
              1
              • H helfi9999

                ECOVACS ioBroker UNIVERSAL – KOMPLETTPAKET v6.4

                Dieses Paket ist universell aufgebaut.

                Es ist NICHT fest auf Namen wie Luna oder Sky programmiert.
                Es erkennt alle eingebundenen Instanzen nach dem Muster:

                ecovacs-deebot.x
                

                und legt pro erkanntem Sauger eine eigene Struktur an:

                0_userdata.0.Sauger.<Gerätename>
                

                Beispiel:

                0_userdata.0.Sauger.Luna
                0_userdata.0.Sauger.Sky
                

                Bei einem anderen Benutzer entstehen automatisch dessen eigene Gerätenamen.
                ENTHALTENE SKRIPTE

                1. 01_Ecovacs_Universal_Setup_v6.0.js
                  Aufgabe:
                • erkennt alle ecovacs-deebot.* Instanzen
                • versucht den Gerätenamen automatisch zu lesen
                • erkennt die Map-ID
                • erkennt alle spotAreas / Räume
                • legt die benötigten 0_userdata-Datenpunkte an

                Betrieb:

                • EINMAL starten
                • danach wieder AUS

                Wenn später ein neuer Sauger hinzukommt:

                • Setup erneut kurz starten
                • danach wieder AUS
                1. 02_Ecovacs_Universal_MapSource_v6.1.js
                  Aufgabe:
                • sucht pro Sauger automatisch nach einer Kartenquelle

                • bevorzugt:
                  ecovacs-deebot.x.map.<mapId>.map64

                • versucht bei vorhandenem loadMapImage die Karte regelmäßig neu anzufordern

                • schreibt die erkannte Quelle nach:

                  0_userdata.0.Sauger.<Name>.Map.Source.type
                  0_userdata.0.Sauger.<Name>.Map.Source.state
                  0_userdata.0.Sauger.<Name>.Map.Source.image
                  0_userdata.0.Sauger.<Name>.Map.Source.status

                Betrieb:

                • dauerhaft AN

                Hinweis:
                Die aktuelle VIS v6.4 verwendet das Kartenbild nicht mehr als Hintergrund.
                Der MapSource kann trotzdem aktiv bleiben, weil er weiterhin universell die
                Kartenquelle ermittelt und für Diagnose / spätere Erweiterungen verfügbar hält.

                1. 03_Ecovacs_Universal_Position_Fahrspur_v6.0.js

                Aufgabe:

                • liest pro Sauger:

                  ecovacs-deebot.x.map.deebotPosition

                • berechnet daraus die Position auf der Karte

                • aktualisiert:
                  Map.pixelXcss
                  Map.pixelYcss
                  Map.rotateCss

                • zeichnet eine Fahrspur

                • setzt die Fahrspur bei einem neuen Reinigungsvorgang zurück

                • übernimmt Status und Positionsname, sofern vorhanden

                Betrieb:

                • dauerhaft AN
                1. 04_Ecovacs_Universal_RaumSync_v6.0.js

                Aufgabe:

                • synchronisiert pro Raum:

                  markForNextSpotAreaCleaning

                mit:

                0_userdata.0.Sauger.<Name>.Rooms.<id>.selected
                

                Dadurch weiß die VIS, ob ein Raum ausgewählt ist.

                Betrieb:

                • dauerhaft AN
                1. 05_Ecovacs_Universal_Raumflaechen_Detektor_v6.2.js
                  Aufgabe:
                • durchsucht jeden automatisch erkannten Raum nach Geometriedaten

                • sucht unter anderem nach:
                  polygon
                  boundary
                  boundaries
                  coordinates
                  coords
                  points
                  vertices
                  outline
                  contour
                  rect
                  bounds

                • wandelt gefundene Raumgeometrien in SVG-Punkte um

                • speichert pro Raum:

                  Rooms.<id>.geometryState
                  Rooms.<id>.geometryType
                  Rooms.<id>.polygonPoints
                  Rooms.<id>.geometryStatus

                Betrieb:

                • dauerhaft AN

                Wenn ein Sauger keine Raumgeometrie bereitstellt:

                • polygonPoints bleibt leer
                • die VIS kann dann keine Raumfläche zeichnen
                1. 06_Ecovacs_Universal_VIS_Raumflaechen_v6.4.js

                Aufgabe:

                • erzeugt die komplette VIS-Darstellung
                • dunkler Hintergrund
                • automatisch erkannte farbige Raumflächen
                • Raumflächen direkt anklickbar
                • Fahrspur
                • Roboterposition
                • KEINE zusätzlichen Raum-Buttons mehr

                Betrieb:

                • dauerhaft AN

                INSTALLATION:

                1. In ioBroker unter JavaScript für jede .js-Datei ein eigenes Skript anlegen.

                2. Den Inhalt der jeweiligen .js-Datei komplett in das entsprechende
                  JavaScript-Skript kopieren.

                EMPFOHLENE REIHENFOLGE
                Schritt 1:
                01_Ecovacs_Universal_Setup_v6.0.js
                kurz AN

                Warten, bis die Struktur unter:

                0_userdata.0.Sauger
                

                angelegt wurde.

                Danach:
                01 Setup AUS

                Schritt 2:
                Folgende Skripte dauerhaft AN:

                02_Ecovacs_Universal_MapSource_v6.1.js
                03_Ecovacs_Universal_Position_Fahrspur_v6.0.js
                04_Ecovacs_Universal_RaumSync_v6.0.js
                05_Ecovacs_Universal_Raumflaechen_Detektor_v6.2.js
                06_Ecovacs_Universal_VIS_Raumflaechen_v6.4.js
                

                WELCHE SKRIPTE SIND AN / AUS?
                01 Setup:
                AUS
                Nur bei Erstinstallation oder neuem Sauger kurz AN.

                02 MapSource:
                AN

                03 Position/Fahrspur:
                AN

                04 RaumSync:
                AN

                05 Raumflächen-Detektor:
                AN

                06 VIS:
                AN

                VIS EINRICHTEN

                In VIS ein Widget verwenden:

                Basic -> String (unescaped)
                

                Als Objekt-ID:

                0_userdata.0.Sauger.<Gerätename>.VIS.html
                

                Beispiel:

                0_userdata.0.Sauger.Luna.VIS.html
                

                Keine geschweiften Klammern verwenden.

                Also NICHT:

                {0_userdata.0.Sauger.Luna.VIS.html}
                

                sondern direkt:

                0_userdata.0.Sauger.Luna.VIS.html
                

                BEDIENUNG

                RAUM AUSWÄHLEN

                Einfach direkt auf die farbige Raumfläche in der Karte klicken.

                Beim Klick wird der zugehörige Adapter-State geschaltet:

                ecovacs-deebot.x.map.<mapId>.spotAreas.<id>.markForNextSpotAreaCleaning
                

                Der RaumSync übernimmt den Zustand anschließend nach:

                0_userdata.0.Sauger.<Name>.Rooms.<id>.selected
                

                Ein ausgewählter Raum wird in der VIS stärker hervorgehoben.

                MEHRERE RÄUME

                Mehrere Raumflächen können nacheinander angeklickt werden.

                Die Auswahl wird direkt über die Adapter-States vorgenommen.

                FAHRSPUR

                Die Fahrspur wird aus deebotPosition erzeugt.

                Sie liegt in:

                0_userdata.0.Sauger.<Name>.Map.trailPoints
                

                Beim Beginn eines neuen Reinigungsvorgangs wird sie zurückgesetzt.

                ROBOTERPOSITION

                Die Position wird aus:

                ecovacs-deebot.x.map.deebotPosition
                

                ermittelt.

                Die VIS verwendet:

                Map.pixelXcss
                Map.pixelYcss
                Map.rotateCss
                

                RAUMFLÄCHEN-DIAGNOSE

                Wenn ein Raum nicht gezeichnet wird, prüfen:

                0_userdata.0.Sauger.<Name>.Rooms.<id>.geometryStatus
                

                und:

                0_userdata.0.Sauger.<Name>.Rooms.<id>.geometryState
                

                und:

                0_userdata.0.Sauger.<Name>.Rooms.<id>.polygonPoints
                

                Wenn geometryStatus meldet:

                Keine Raumgeometrie im Adapter gefunden
                

                dann liefert dieses Modell / diese Adapterversion für diesen Raum keine
                verwertbaren Polygon- oder Boundary-Daten.

                KARTENQUELLEN-DIAGNOSE

                Prüfen:

                0_userdata.0.Sauger.<Name>.Map.Source.status
                

                und:

                0_userdata.0.Sauger.<Name>.Map.Source.state
                

                POSITION PASST NICHT ZUR KARTE

                Die Koordinatenumrechnung verwendet pro Sauger:

                Map.Config.minX
                Map.Config.maxX
                Map.Config.minY
                Map.Config.maxY
                Map.Config.imgW
                Map.Config.imgH
                

                Standard:

                minX = -250
                maxX = 10700
                minY = -4350
                maxY = 400
                imgW = 540
                imgH = 231
                

                Diese Werte können pro Sauger angepasst werden.

                Wichtig:
                Die Raumflächen-Erkennung versucht selbst zu unterscheiden, ob Raumkoordinaten
                bereits Pixelwerte sind oder Weltkoordinaten umgerechnet werden müssen.

                NEUER SAUGER

                Wenn später eine weitere ecovacs-deebot.* Instanz installiert wird:

                1. Setup v6.0 kurz AN.
                2. Warten, bis der neue Sauger unter 0_userdata.0.Sauger erscheint.
                3. Setup wieder AUS.
                4. Die dauerhaft laufenden Skripte einmal neu starten.

                Danach wird der neue Sauger automatisch mit verarbeitet.

                MEHRERE SAUGER

                Alle dauerhaft laufenden Skripte suchen automatisch nach:

                0_userdata.0.Sauger.*.deebotPrefix
                

                Dadurch wird nicht nur ein einzelner Sauger verarbeitet.

                Jeder Sauger besitzt:

                • eigene Map-ID
                • eigene Räume
                • eigene Raumflächen
                • eigene Position
                • eigene Fahrspur
                • eigenes VIS.html

                WICHTIGE GRENZEN

                Das Paket kann nur Daten verwenden, die der Ecovacs-Adapter für das jeweilige
                Modell bereitstellt.

                Wenn ein Modell:

                • keine deebotPosition liefert -> keine Live-Position/Fahrspur
                • keine spotAreas liefert -> keine automatische Raumauswahl
                • keine Geometrie für spotAreas liefert -> keine gezeichneten Raumflächen

                Das Paket versucht diese Funktionen automatisch zu erkennen und ist nicht
                auf einen bestimmten Sauger oder Grundriss fest programmiert.

                Die Buttons muss man selbst erstellen wie hier:
                c42a3904-8b6b-4077-ba10-9b0379503363-image.jpeg

                Viel Spass beim ausprobieren !!

                sigi234S Online
                sigi234S Online
                sigi234
                Forum Testing Most Active
                schrieb zuletzt editiert von sigi234
                #7

                @helfi9999 sagte:

                01_Ecovacs_Universal_Setup_v6.0.js

                javascript.0
                2026-08-28 20:08:38.599	info	script.js.Ecovacs.Skript_1: Stopping script
                
                javascript.0
                2026-08-28 20:08:10.334	info	script.js.Ecovacs.Skript_1: registered 0 subscriptions, 0 schedules, 0 messages, 0 logs and 0 file subscriptions
                
                javascript.0
                2026-08-28 20:08:10.334	info	script.js.Ecovacs.Skript_1: Universal Setup 6.0.0Name: ChepettoBasis: 0_userdata.0.Sauger.ChepettoAdapter: ecovacs-deebot.0Map-ID: 88846xxxxRäume: 50: A1: B2: C3: D4: E
                
                javascript.0
                2026-08-28 20:08:10.334	warn	at script.js.Ecovacs.Skript_1:368:3
                
                javascript.0
                2026-08-28 20:08:10.334	warn	at script.js.Ecovacs.Skript_1:359:9
                
                javascript.0
                2026-08-28 20:08:10.334	warn	at setState (C:\SmartHome\node_modules\iobroker.javascript\build\lib\sandbox.js:2240:20)
                
                javascript.0
                2026-08-28 20:08:10.333	warn	State "0_userdata.0.Sauger.Chepetto.lastSetupReport" not found
                
                javascript.0
                2026-08-28 20:08:10.324	info	script.js.Ecovacs.Skript_1: start JavaScript (Javascript/js)
                

                EDIT:

                javascript.0
                2026-08-28 20:17:08.182	info	script.js.Ecovacs.Skript_6: registered 14 subscriptions, 0 schedules, 0 messages, 0 logs and 0 file subscriptions
                
                javascript.0
                2026-08-28 20:17:08.182	info	script.js.Ecovacs.Skript_6: Universal VIS Raumflächen v6.4: 1 Sauger geladen.
                
                javascript.0
                2026-08-28 20:17:08.177	info	script.js.Ecovacs.Skript_6: start JavaScript (Javascript/js)
                
                javascript.0
                2026-08-28 20:16:23.593	info	script.js.Ecovacs.Skript_5: registered 5 subscriptions, 1 schedule, 0 messages, 0 logs and 0 file subscriptions
                
                javascript.0
                2026-08-28 20:16:23.593	info	script.js.Ecovacs.Skript_5: Universal Raumflächen-Detektor v6.2: 1 Sauger geladen.
                
                javascript.0
                2026-08-28 20:16:23.567	info	script.js.Ecovacs.Skript_5: start JavaScript (Javascript/js)
                
                javascript.0
                2026-08-28 20:15:39.803	info	script.js.Ecovacs.Skript_4: registered 5 subscriptions, 0 schedules, 0 messages, 0 logs and 0 file subscriptions
                
                javascript.0
                2026-08-28 20:15:39.803	info	script.js.Ecovacs.Skript_4: Chepetto: Raum-Sync aktiv
                
                javascript.0
                2026-08-28 20:15:39.794	info	script.js.Ecovacs.Skript_4: start JavaScript (Javascript/js)
                
                javascript.0
                2026-08-28 20:14:46.691	info	script.js.Ecovacs.Skript_3: registered 3 subscriptions, 0 schedules, 0 messages, 0 logs and 0 file subscriptions
                
                javascript.0
                2026-08-28 20:14:46.690	info	script.js.Ecovacs.Skript_3: Chepetto: Position/Fahrspur aktiv (ecovacs-deebot.0.map.deebotPosition)
                
                javascript.0
                2026-08-28 20:14:46.685	info	script.js.Ecovacs.Skript_3: start JavaScript (Javascript/js)
                
                javascript.0
                2026-08-28 20:13:51.524	info	script.js.Ecovacs.Skript_2: registered 1 subscription, 1 schedule, 0 messages, 0 logs and 0 file subscriptions
                
                javascript.0
                2026-08-28 20:13:51.524	info	script.js.Ecovacs.Skript_2: Universal Map Source v6.1: 1 Sauger geladen.
                
                javascript.0
                2026-08-28 20:13:51.516	info	script.js.Ecovacs.Skript_2: start JavaScript (Javascript/js)
                

                Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
                Immer Daten sichern!

                1 Antwort Letzte Antwort
                0
                • H helfi9999

                  @sigi234 das Ecovacs Skript habe ich geändert so das man nichts ersetzen muss.

                  sigi234S Online
                  sigi234S Online
                  sigi234
                  Forum Testing Most Active
                  schrieb zuletzt editiert von sigi234
                  #8

                  @helfi9999

                  Schaut nicht schlecht aus, läuft , Karte wirkt ein wenig abgeschnitten.
                  Hier die der App und vom Adapter:

                  3da0df37-1795-40e3-902f-9f4fc1aad65d-image.jpeg

                  Screenshot_20260828_205410_ECOVACS HOME.jpg

                  Hier die vom Skript:

                  94942ee2-859c-4412-9fe7-34212487f98f-image.jpeg

                  94345895-3a3f-4f78-9880-6ea8523a22fe-image.jpeg

                  Edit2:

                  Dein DP:

                  fa9b1c51-fc62-46a8-a9cd-46ed9d15169f-image.jpeg

                  Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
                  Immer Daten sichern!

                  H 1 Antwort Letzte Antwort
                  0
                  • sigi234S sigi234

                    @helfi9999

                    Schaut nicht schlecht aus, läuft , Karte wirkt ein wenig abgeschnitten.
                    Hier die der App und vom Adapter:

                    3da0df37-1795-40e3-902f-9f4fc1aad65d-image.jpeg

                    Screenshot_20260828_205410_ECOVACS HOME.jpg

                    Hier die vom Skript:

                    94942ee2-859c-4412-9fe7-34212487f98f-image.jpeg

                    94345895-3a3f-4f78-9880-6ea8523a22fe-image.jpeg

                    Edit2:

                    Dein DP:

                    fa9b1c51-fc62-46a8-a9cd-46ed9d15169f-image.jpeg

                    H Online
                    H Online
                    helfi9999
                    schrieb zuletzt editiert von
                    #9

                    @sigi234 das abgeschittene hängt damit zusammen das es die Außenkante des Raumes ist wo der Sauger läuft. Das heißt er nimmt die Daten des Saugers. Wenn es keine Verbindung zum nächsten Raum gibt steht da irgendetwas wie z.B. ein Schrank wo der Sauger nicht drunter herfahren kann. Ich weiß noch nicht wie ich dieses ändern kann.

                    Intel NUC mit Iobroker

                    1 Antwort Letzte Antwort
                    0
                    • H helfi9999

                      ECOVACS ioBroker UNIVERSAL – KOMPLETTPAKET v6.4

                      Dieses Paket ist universell aufgebaut.

                      Es ist NICHT fest auf Namen wie Luna oder Sky programmiert.
                      Es erkennt alle eingebundenen Instanzen nach dem Muster:

                      ecovacs-deebot.x
                      

                      und legt pro erkanntem Sauger eine eigene Struktur an:

                      0_userdata.0.Sauger.<Gerätename>
                      

                      Beispiel:

                      0_userdata.0.Sauger.Luna
                      0_userdata.0.Sauger.Sky
                      

                      Bei einem anderen Benutzer entstehen automatisch dessen eigene Gerätenamen.
                      ENTHALTENE SKRIPTE

                      1. 01_Ecovacs_Universal_Setup_v6.0.js
                        Aufgabe:
                      • erkennt alle ecovacs-deebot.* Instanzen
                      • versucht den Gerätenamen automatisch zu lesen
                      • erkennt die Map-ID
                      • erkennt alle spotAreas / Räume
                      • legt die benötigten 0_userdata-Datenpunkte an

                      Betrieb:

                      • EINMAL starten
                      • danach wieder AUS

                      Wenn später ein neuer Sauger hinzukommt:

                      • Setup erneut kurz starten
                      • danach wieder AUS
                      1. 02_Ecovacs_Universal_MapSource_v6.1.js
                        Aufgabe:
                      • sucht pro Sauger automatisch nach einer Kartenquelle

                      • bevorzugt:
                        ecovacs-deebot.x.map.<mapId>.map64

                      • versucht bei vorhandenem loadMapImage die Karte regelmäßig neu anzufordern

                      • schreibt die erkannte Quelle nach:

                        0_userdata.0.Sauger.<Name>.Map.Source.type
                        0_userdata.0.Sauger.<Name>.Map.Source.state
                        0_userdata.0.Sauger.<Name>.Map.Source.image
                        0_userdata.0.Sauger.<Name>.Map.Source.status

                      Betrieb:

                      • dauerhaft AN

                      Hinweis:
                      Die aktuelle VIS v6.4 verwendet das Kartenbild nicht mehr als Hintergrund.
                      Der MapSource kann trotzdem aktiv bleiben, weil er weiterhin universell die
                      Kartenquelle ermittelt und für Diagnose / spätere Erweiterungen verfügbar hält.

                      1. 03_Ecovacs_Universal_Position_Fahrspur_v6.0.js

                      Aufgabe:

                      • liest pro Sauger:

                        ecovacs-deebot.x.map.deebotPosition

                      • berechnet daraus die Position auf der Karte

                      • aktualisiert:
                        Map.pixelXcss
                        Map.pixelYcss
                        Map.rotateCss

                      • zeichnet eine Fahrspur

                      • setzt die Fahrspur bei einem neuen Reinigungsvorgang zurück

                      • übernimmt Status und Positionsname, sofern vorhanden

                      Betrieb:

                      • dauerhaft AN
                      1. 04_Ecovacs_Universal_RaumSync_v6.0.js

                      Aufgabe:

                      • synchronisiert pro Raum:

                        markForNextSpotAreaCleaning

                      mit:

                      0_userdata.0.Sauger.<Name>.Rooms.<id>.selected
                      

                      Dadurch weiß die VIS, ob ein Raum ausgewählt ist.

                      Betrieb:

                      • dauerhaft AN
                      1. 05_Ecovacs_Universal_Raumflaechen_Detektor_v6.2.js
                        Aufgabe:
                      • durchsucht jeden automatisch erkannten Raum nach Geometriedaten

                      • sucht unter anderem nach:
                        polygon
                        boundary
                        boundaries
                        coordinates
                        coords
                        points
                        vertices
                        outline
                        contour
                        rect
                        bounds

                      • wandelt gefundene Raumgeometrien in SVG-Punkte um

                      • speichert pro Raum:

                        Rooms.<id>.geometryState
                        Rooms.<id>.geometryType
                        Rooms.<id>.polygonPoints
                        Rooms.<id>.geometryStatus

                      Betrieb:

                      • dauerhaft AN

                      Wenn ein Sauger keine Raumgeometrie bereitstellt:

                      • polygonPoints bleibt leer
                      • die VIS kann dann keine Raumfläche zeichnen
                      1. 06_Ecovacs_Universal_VIS_Raumflaechen_v6.4.js

                      Aufgabe:

                      • erzeugt die komplette VIS-Darstellung
                      • dunkler Hintergrund
                      • automatisch erkannte farbige Raumflächen
                      • Raumflächen direkt anklickbar
                      • Fahrspur
                      • Roboterposition
                      • KEINE zusätzlichen Raum-Buttons mehr

                      Betrieb:

                      • dauerhaft AN

                      INSTALLATION:

                      1. In ioBroker unter JavaScript für jede .js-Datei ein eigenes Skript anlegen.

                      2. Den Inhalt der jeweiligen .js-Datei komplett in das entsprechende
                        JavaScript-Skript kopieren.

                      EMPFOHLENE REIHENFOLGE
                      Schritt 1:
                      01_Ecovacs_Universal_Setup_v6.0.js
                      kurz AN

                      Warten, bis die Struktur unter:

                      0_userdata.0.Sauger
                      

                      angelegt wurde.

                      Danach:
                      01 Setup AUS

                      Schritt 2:
                      Folgende Skripte dauerhaft AN:

                      02_Ecovacs_Universal_MapSource_v6.1.js
                      03_Ecovacs_Universal_Position_Fahrspur_v6.0.js
                      04_Ecovacs_Universal_RaumSync_v6.0.js
                      05_Ecovacs_Universal_Raumflaechen_Detektor_v6.2.js
                      06_Ecovacs_Universal_VIS_Raumflaechen_v6.4.js
                      

                      WELCHE SKRIPTE SIND AN / AUS?
                      01 Setup:
                      AUS
                      Nur bei Erstinstallation oder neuem Sauger kurz AN.

                      02 MapSource:
                      AN

                      03 Position/Fahrspur:
                      AN

                      04 RaumSync:
                      AN

                      05 Raumflächen-Detektor:
                      AN

                      06 VIS:
                      AN

                      VIS EINRICHTEN

                      In VIS ein Widget verwenden:

                      Basic -> String (unescaped)
                      

                      Als Objekt-ID:

                      0_userdata.0.Sauger.<Gerätename>.VIS.html
                      

                      Beispiel:

                      0_userdata.0.Sauger.Luna.VIS.html
                      

                      Keine geschweiften Klammern verwenden.

                      Also NICHT:

                      {0_userdata.0.Sauger.Luna.VIS.html}
                      

                      sondern direkt:

                      0_userdata.0.Sauger.Luna.VIS.html
                      

                      BEDIENUNG

                      RAUM AUSWÄHLEN

                      Einfach direkt auf die farbige Raumfläche in der Karte klicken.

                      Beim Klick wird der zugehörige Adapter-State geschaltet:

                      ecovacs-deebot.x.map.<mapId>.spotAreas.<id>.markForNextSpotAreaCleaning
                      

                      Der RaumSync übernimmt den Zustand anschließend nach:

                      0_userdata.0.Sauger.<Name>.Rooms.<id>.selected
                      

                      Ein ausgewählter Raum wird in der VIS stärker hervorgehoben.

                      MEHRERE RÄUME

                      Mehrere Raumflächen können nacheinander angeklickt werden.

                      Die Auswahl wird direkt über die Adapter-States vorgenommen.

                      FAHRSPUR

                      Die Fahrspur wird aus deebotPosition erzeugt.

                      Sie liegt in:

                      0_userdata.0.Sauger.<Name>.Map.trailPoints
                      

                      Beim Beginn eines neuen Reinigungsvorgangs wird sie zurückgesetzt.

                      ROBOTERPOSITION

                      Die Position wird aus:

                      ecovacs-deebot.x.map.deebotPosition
                      

                      ermittelt.

                      Die VIS verwendet:

                      Map.pixelXcss
                      Map.pixelYcss
                      Map.rotateCss
                      

                      RAUMFLÄCHEN-DIAGNOSE

                      Wenn ein Raum nicht gezeichnet wird, prüfen:

                      0_userdata.0.Sauger.<Name>.Rooms.<id>.geometryStatus
                      

                      und:

                      0_userdata.0.Sauger.<Name>.Rooms.<id>.geometryState
                      

                      und:

                      0_userdata.0.Sauger.<Name>.Rooms.<id>.polygonPoints
                      

                      Wenn geometryStatus meldet:

                      Keine Raumgeometrie im Adapter gefunden
                      

                      dann liefert dieses Modell / diese Adapterversion für diesen Raum keine
                      verwertbaren Polygon- oder Boundary-Daten.

                      KARTENQUELLEN-DIAGNOSE

                      Prüfen:

                      0_userdata.0.Sauger.<Name>.Map.Source.status
                      

                      und:

                      0_userdata.0.Sauger.<Name>.Map.Source.state
                      

                      POSITION PASST NICHT ZUR KARTE

                      Die Koordinatenumrechnung verwendet pro Sauger:

                      Map.Config.minX
                      Map.Config.maxX
                      Map.Config.minY
                      Map.Config.maxY
                      Map.Config.imgW
                      Map.Config.imgH
                      

                      Standard:

                      minX = -250
                      maxX = 10700
                      minY = -4350
                      maxY = 400
                      imgW = 540
                      imgH = 231
                      

                      Diese Werte können pro Sauger angepasst werden.

                      Wichtig:
                      Die Raumflächen-Erkennung versucht selbst zu unterscheiden, ob Raumkoordinaten
                      bereits Pixelwerte sind oder Weltkoordinaten umgerechnet werden müssen.

                      NEUER SAUGER

                      Wenn später eine weitere ecovacs-deebot.* Instanz installiert wird:

                      1. Setup v6.0 kurz AN.
                      2. Warten, bis der neue Sauger unter 0_userdata.0.Sauger erscheint.
                      3. Setup wieder AUS.
                      4. Die dauerhaft laufenden Skripte einmal neu starten.

                      Danach wird der neue Sauger automatisch mit verarbeitet.

                      MEHRERE SAUGER

                      Alle dauerhaft laufenden Skripte suchen automatisch nach:

                      0_userdata.0.Sauger.*.deebotPrefix
                      

                      Dadurch wird nicht nur ein einzelner Sauger verarbeitet.

                      Jeder Sauger besitzt:

                      • eigene Map-ID
                      • eigene Räume
                      • eigene Raumflächen
                      • eigene Position
                      • eigene Fahrspur
                      • eigenes VIS.html

                      WICHTIGE GRENZEN

                      Das Paket kann nur Daten verwenden, die der Ecovacs-Adapter für das jeweilige
                      Modell bereitstellt.

                      Wenn ein Modell:

                      • keine deebotPosition liefert -> keine Live-Position/Fahrspur
                      • keine spotAreas liefert -> keine automatische Raumauswahl
                      • keine Geometrie für spotAreas liefert -> keine gezeichneten Raumflächen

                      Das Paket versucht diese Funktionen automatisch zu erkennen und ist nicht
                      auf einen bestimmten Sauger oder Grundriss fest programmiert.

                      Die Buttons muss man selbst erstellen wie hier:
                      c42a3904-8b6b-4077-ba10-9b0379503363-image.jpeg

                      Viel Spass beim ausprobieren !!

                      H Online
                      H Online
                      helfi9999
                      schrieb zuletzt editiert von
                      #10

                      @mrbungle64 wäre das nicht etwas was man eventuell in deinen Adapter einbauen könnte

                      Intel NUC mit Iobroker

                      1 Antwort Letzte Antwort
                      0

                      Hey! Du scheinst an dieser Unterhaltung interessiert zu sein, hast aber noch kein Konto.

                      Hast du es satt, bei jedem Besuch durch die gleichen Beiträge zu scrollen? Wenn du dich für ein Konto anmeldest, kommst du immer genau dorthin zurück, wo du zuvor warst, und kannst dich über neue Antworten benachrichtigen lassen (entweder per E-Mail oder Push-Benachrichtigung). Du kannst auch Lesezeichen speichern und Beiträge positiv bewerten, um anderen Community-Mitgliedern deine Wertschätzung zu zeigen.

                      Mit deinem Input könnte dieser Beitrag noch besser werden 💗

                      Registrieren Anmelden
                      Antworten
                      • In einem neuen Thema antworten
                      Anmelden zum Antworten
                      • Älteste zuerst
                      • Neuste zuerst
                      • Meiste Stimmen


                      Support us

                      ioBroker
                      Community Adapters
                      Donate

                      189

                      Online

                      33.0k

                      Benutzende

                      83.7k

                      Themen

                      1.3m

                      Beiträge
                      Community
                      Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                      ioBroker Community 2014-2026
                      logo
                      • Anmelden

                      • Du hast noch kein Konto? Registrieren

                      • Anmelden oder registrieren, um zu suchen
                      • Erster Beitrag
                        Letzter Beitrag
                      0
                      • Home
                      • Aktuell
                      • Ungelesen 0
                      • Kategorien
                      • Unreplied
                      • Beliebt
                      • GitHub
                      • Docu
                      • Hilfe