<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Recently Active Topics]]></title><description><![CDATA[A list of topics that have been active within the past 24 hours]]></description><link>https://forum.iobroker.net/recent</link><generator>RSS for Node</generator><lastBuildDate>Sat, 08 Aug 2026 19:29:11 GMT</lastBuildDate><atom:link href="https://forum.iobroker.net/recent.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 08 Aug 2026 18:50:29 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Test Adapter sun2000 v0.1.x - Huawei Wechselrichter]]></title><description><![CDATA[bei dem Tageswert muss der "type": "deltaReset" sein; bei dem Gesamtverbrauch sonst  "type": "delta"
]]></description><link>https://forum.iobroker.net/topic/71768/test-adapter-sun2000-v0.1.x-huawei-wechselrichter</link><guid isPermaLink="true">https://forum.iobroker.net/topic/71768/test-adapter-sun2000-v0.1.x-huawei-wechselrichter</guid><dc:creator><![CDATA[bolliy]]></dc:creator><pubDate>Sat, 08 Aug 2026 18:50:29 GMT</pubDate></item><item><title><![CDATA[ich brauche etwas Nachhilfe mit Node Red und RS232]]></title><description><![CDATA[
@andibr sagte:
beim auslesen der Victron Forcast aus dem VRM.

Wieder [OT]
Hängt die pytes bereits per CAN am BMS-CAN vom Cerbo?
Und zusätzlich gehst du an den rj45 für RS232?
Geht das problemlos?
Hab mich das nämlich noch nicht getraut.
]]></description><link>https://forum.iobroker.net/topic/85137/ich-brauche-etwas-nachhilfe-mit-node-red-und-rs232</link><guid isPermaLink="true">https://forum.iobroker.net/topic/85137/ich-brauche-etwas-nachhilfe-mit-node-red-und-rs232</guid><dc:creator><![CDATA[Homoran]]></dc:creator><pubDate>Sat, 08 Aug 2026 18:48:58 GMT</pubDate></item><item><title><![CDATA[Utility-Monitor v1.6.6]]></title><description><![CDATA[@Siggi0904
Sorry waren noch ein paar andere Sachen zutun 😅
]]></description><link>https://forum.iobroker.net/topic/83496/utility-monitor-v1.6.6</link><guid isPermaLink="true">https://forum.iobroker.net/topic/83496/utility-monitor-v1.6.6</guid><dc:creator><![CDATA[fischi87]]></dc:creator><pubDate>Sat, 08 Aug 2026 18:23:00 GMT</pubDate></item><item><title><![CDATA[Test Adapter Miner version v1.0.x Latest]]></title><description><![CDATA[Hi, nein passiert ab und zu. Ich habe noch nicht rausgefunden wann es genau passiert. Starte den Adapter dann neu und dann ist wieder alles ok.
Bin auch dank KI mit meiner PV Reglung ein Riesen Stück weiter, dass Blockly ist irgendwann ausgeartet :-D und KI hat dann vorgeschlagen ein Js Scrip zu erstellen. Und das Funktioniert seit Heute perfekt.
/**
 * PV-Miner-Regelung V2.17
 *
 * Funktionen:
 * - Sofortige Auswahl/Umschaltung zwischen S9 und S19 anhand der verfügbaren PV-Leistung
 * - powerTarget-Regelung höchstens alle 3 Minuten
 * - powerTarget wird nur bei tatsächlicher Änderung geschrieben
 * - Sollwertänderung stoppt den Miner NICHT
 * - Steckdosen werden bei Bedarf eingeschaltet
 * - Steckdosen werden nach 1 Stunde Leerlauf ausgeschaltet
 * - nach dem Einschalten der Steckdose 30 Sekunden warten
 * - danach enabled auf true setzen und bis zu 2 Minuten auf Bestätigung warten
 * - running erst setzen, wenn enabled tatsächlich true ist
 *
 * Netzleistung EVCC:
 *   negativ = Einspeisung
 *   positiv = Netzbezug
 */

// ------------------------------------------------------------
// Datenpunkte
// ------------------------------------------------------------

const GRID_POWER = 'mqtt.1.evcc_Neu.site.grid.power';
const BATTERY_POWER = 'mqtt.1.evcc_Neu.site.battery.power';

const S9 = {
    name: 'S9',
    socket: 'sonoff.0.Aktor_MinerS9.POWER',
    actualPower: 'sonoff.0.Aktor_MinerS9.ENERGY_Power',
    enabled: 'miner.0.miner.c3c555fb-7131-4676-99e1-d0f799ad8001.enabled',
    running: 'miner.0.miner.c3c555fb-7131-4676-99e1-d0f799ad8001.control.running',
    powerTarget: 'miner.0.miner.c3c555fb-7131-4676-99e1-d0f799ad8001.control.powerTarget',
    minPower: 500,
    maxPower: 1450
};

const S19 = {
    name: 'S19',
    socket: 'sonoff.0.Aktor_Miner.POWER',
    actualPower: 'sonoff.0.Aktor_Miner.ENERGY_Power',
    enabled: 'miner.0.miner.b7b9de41-7da9-4e8c-8469-e6fe4f16d5f1.enabled',
    running: 'miner.0.miner.b7b9de41-7da9-4e8c-8469-e6fe4f16d5f1.control.running',
    powerTarget: 'miner.0.miner.b7b9de41-7da9-4e8c-8469-e6fe4f16d5f1.control.powerTarget',
    minPower: 1500,
    maxPower: 2500
};

// ------------------------------------------------------------
// Einstellungen
// ------------------------------------------------------------

const POWER_REGULATION_INTERVAL_MS = 2 * 60 * 1000; // 2 Minuten
const SOCKET_IDLE_OFF_MS = 60 * 60 * 1000;         // 1 Stunde
const S9_ENABLE_CHECK_DELAY_MS = 10 * 1000;         // S9: 10 Sekunden Bootzeit
const S19_ENABLE_CHECK_DELAY_MS = 60 * 1000;        // S19: 60 Sekunden Bootzeit
const ENABLE_RETRY_INTERVAL_MS = 5 * 1000;          // danach alle 5 Sekunden prüfen
const ENABLE_WAIT_TIMEOUT_MS = 2 * 60 * 1000;       // maximal 2 Minuten warten
const START_PROTECTION_MS = 3 * 60 * 1000;
const S19_POWER_RESTART_MS = 3 * 60 * 1000;
const S19_UP_STABLE_MS = 3 * 60 * 1000;             // 3 Minuten stabiler Überschuss vor Erhöhung          // S19 braucht nach powerTarget 3 Minuten            // 3 Minuten Startschutz
const SWITCH_OVERLAP_MS = 10 * 1000;                 // 10 Sekunden Überlappung
const PV_RESERVE_W = 100;
const GRID_TARGET_W = -50;                           // Ziel: 50 W Einspeisung                            // Einspeisereserve
const S9_POWER_STEP_W = 100;   // Sollwert-Schritte S9
const S19_POWER_STEP_W = 200;  // Sollwert-Schritte S19
const RUNNING_POWER_THRESHOLD_W = 300;             // ab 300 W gilt Miner als laufend
const BATTERY_DISCHARGE_LIMIT_W = 100;               // Toleranz für Entladung

const S9_START_THRESHOLD_W = 600;
const S19_START_THRESHOLD_W = 1600;
const S19_KEEP_THRESHOLD_W = 1450;

// ------------------------------------------------------------
// Interne Variablen
// ------------------------------------------------------------

let lastPowerRegulation = 0;
let regulationTimer = null;

const socketOffTimers = {
    S9: null,
    S19: null
};

const startTimers = {
    S9: null,
    S19: null
};

const startedAt = {
    S9: 0,
    S19: 0
};

let switching = false;
let switchTimer = null;

const lastPowerChangeAt = {
    S9: 0,
    S19: 0
};

let s19UpCandidate = null;
let s19UpCandidateSince = 0;

const lastValidTarget = {
    S9: S9.minPower,
    S19: S19.minPower
};

// ------------------------------------------------------------
// Hilfsfunktionen
// ------------------------------------------------------------

function getNumber(id, fallback = 0) {
    const state = getState(id);
    const value = Number(state &amp;&amp; state.val);
    return Number.isFinite(value) ? value : fallback;
}

function getBoolean(id) {
    const state = getState(id);
    return Boolean(state &amp;&amp; state.val);
}

function clamp(value, min, max) {
    return Math.min(max, Math.max(min, value));
}

function roundToStep(value, step) {
    return Math.round(value / step) * step;
}

function isPowerRestartActive(miner) {
    if (miner.name !== 'S19') {
        return false;
    }

    return Date.now() - lastPowerChangeAt.S19 &lt; S19_POWER_RESTART_MS;
}

function isMinerActuallyRunning(miner) {
    const measuredPower = getNumber(miner.actualPower, 0);

    if (measuredPower &gt;= RUNNING_POWER_THRESHOLD_W) {
        return true;
    }

    if (isPowerRestartActive(miner)) {
        return true;
    }

    return getBoolean(miner.running);
}

function currentMinerPower() {
    if (isMinerActuallyRunning(S19)) {
        const measured = getNumber(S19.actualPower, 0);
        if (measured &gt;= RUNNING_POWER_THRESHOLD_W) {
            return measured;
        }

        const target = getNumber(S19.powerTarget, 0);
        if (target &gt;= S19.minPower) {
            lastValidTarget.S19 = target;
            return target;
        }

        return lastValidTarget.S19 || S19.minPower;
    }

    if (isMinerActuallyRunning(S9)) {
        const measured = getNumber(S9.actualPower, 0);
        if (measured &gt;= RUNNING_POWER_THRESHOLD_W) {
            return measured;
        }

        const target = getNumber(S9.powerTarget, 0);
        if (target &gt;= S9.minPower) {
            lastValidTarget.S9 = target;
            return target;
        }

        return lastValidTarget.S9 || S9.minPower;
    }

    return 0;
}

function availablePvPower() {
    const gridPower = getNumber(GRID_POWER, 0);
    const batteryPower = getNumber(BATTERY_POWER, 0);

    // Batterie: positiv = Entladen, negativ = Laden.
    // Entladung reduziert die für Miner verfügbare Leistung.
    return currentMinerPower() - gridPower - Math.max(0, batteryPower);
}

function clearStartTimer(miner) {
    if (startTimers[miner.name]) {
        clearTimeout(startTimers[miner.name]);
        startTimers[miner.name] = null;
    }
}

function cancelSocketOff(miner) {
    if (socketOffTimers[miner.name]) {
        clearTimeout(socketOffTimers[miner.name]);
        socketOffTimers[miner.name] = null;
        log(`${miner.name}: Leerlauf-Abschaltung abgebrochen`, 'debug');
    }
}

function scheduleSocketOff(miner) {
    cancelSocketOff(miner);

    socketOffTimers[miner.name] = setTimeout(() =&gt; {
    if (!getBoolean(S9.socket)) {
        handleSocketOff(S9);
    }
    if (!getBoolean(S19.socket)) {
        handleSocketOff(S19);
    }
        socketOffTimers[miner.name] = null;

        if (getBoolean(miner.running)) {
            return;
        }

        log(`${miner.name}: 1 Stunde Leerlauf erreicht, Abschaltsequenz startet`, 'info');

        let attempts = 0;
        const maxAttempts = 12;

        function disableAndSwitchOff() {
            if (getBoolean(miner.running)) {
                log(`${miner.name}: Abschaltsequenz abgebrochen, Miner läuft wieder`, 'info');
                return;
            }

            if (!getBoolean(miner.enabled)) {
                setState(miner.socket, false);
                log(`${miner.name}: enabled ist false, Steckdose ausgeschaltet`, 'info');
                return;
            }

            attempts += 1;
            setState(miner.enabled, false);
            log(`${miner.name}: enabled=false gesendet, Versuch ${attempts}/${maxAttempts}`, 'info');

            if (attempts &gt;= maxAttempts) {
                log(`${miner.name}: enabled wurde nicht false; Steckdose bleibt eingeschaltet`, 'warn');
                return;
            }

            setTimeout(disableAndSwitchOff, 5000);
        }

        disableAndSwitchOff();
    }, SOCKET_IDLE_OFF_MS);

    log(`${miner.name}: Steckdose wird bei weiterem Leerlauf in 1 Stunde ausgeschaltet`, 'debug');
}

function ensureSocket(miner) {
    cancelSocketOff(miner);

    if (!getBoolean(miner.socket)) {
        setState(miner.socket, true);
        log(`${miner.name}: Steckdose eingeschaltet`, 'info');
    }
}

function stopMiner(miner) {
    if (miner.name === 'S19') {
        s19UpCandidate = null;
        s19UpCandidateSince = 0;
    }
    clearStartTimer(miner);

    if (getBoolean(miner.running)) {
        setState(miner.running, false);
        log(`${miner.name}: Miner gestoppt`, 'info');
    }

    scheduleSocketOff(miner);
}

function startMiner(miner) {
    cancelSocketOff(miner);
    ensureSocket(miner);

    if (getBoolean(miner.running)) {
        return;
    }

    if (startTimers[miner.name]) {
        return;
    }

    const startAttemptAt = Date.now();

    function checkEnabledAndStart() {
        if (getBoolean(miner.running)) {
            clearStartTimer(miner);
            return;
        }

        if (getBoolean(miner.enabled)) {
            clearStartTimer(miner);
            setState(miner.running, true);
            startedAt[miner.name] = Date.now();
            log(`${miner.name}: enabled ist true, Miner gestartet`, 'info');
            return;
        }

        if (Date.now() - startAttemptAt &gt;= ENABLE_WAIT_TIMEOUT_MS) {
            clearStartTimer(miner);
            log(`${miner.name}: enabled wurde innerhalb von 2 Minuten nicht true`, 'warn');
            return;
        }

        startTimers[miner.name] = setTimeout(checkEnabledAndStart, ENABLE_RETRY_INTERVAL_MS);
    }

    const enableDelay =
        miner.name === 'S19'
            ? S19_ENABLE_CHECK_DELAY_MS
            : S9_ENABLE_CHECK_DELAY_MS;

    startTimers[miner.name] = setTimeout(() =&gt; {
        startTimers[miner.name] = null;

        if (!getBoolean(miner.enabled)) {
            setState(miner.enabled, true);
            log(`${miner.name}: enabled nach ${Math.round(enableDelay / 1000)} Sekunden auf true gesetzt`, 'info');
        }

        startTimers[miner.name] = setTimeout(checkEnabledAndStart, ENABLE_RETRY_INTERVAL_MS);
    }, enableDelay);
}

function setPowerTargetIfChanged(miner, target) {
    const powerStep = miner.name === 'S19' ? S19_POWER_STEP_W : S9_POWER_STEP_W;

    const roundedTarget = roundToStep(
        clamp(target, miner.minPower, miner.maxPower),
        powerStep
    );

    const currentTarget = getNumber(miner.powerTarget, 0);

    if (currentTarget === roundedTarget) {
        log(`${miner.name}: Sollwert unverändert bei ${roundedTarget} W`, 'debug');
        return false;
    }

    setState(miner.powerTarget, roundedTarget);
    lastValidTarget[miner.name] = roundedTarget;

    if (miner.name === 'S19') {
        lastPowerChangeAt.S19 = Date.now();
        log(`S19: powerTarget geändert – 3 Minuten Neustartschutz aktiv`, 'info');
    }
    log(`${miner.name}: powerTarget auf ${roundedTarget} W geändert`, 'info');
    return true;
}

function clearSwitchTimer() {
    if (switchTimer) {
        clearTimeout(switchTimer);
        switchTimer = null;
    }
}

function switchMiner(newMiner, oldMiner) {
    if (switching) {
        return;
    }

    switching = true;
    clearSwitchTimer();

    startMiner(newMiner);

    const started = Date.now();

    function waitForNewMiner() {
        if (getBoolean(newMiner.running)) {
            switchTimer = setTimeout(() =&gt; {
                switchTimer = null;
                stopMiner(oldMiner);
                switching = false;
                log(`${newMiner.name} läuft; ${oldMiner.name} wurde nach 10 Sekunden gestoppt`, 'info');
            }, SWITCH_OVERLAP_MS);
            return;
        }

        if (Date.now() - started &gt;= ENABLE_WAIT_TIMEOUT_MS + S19_ENABLE_CHECK_DELAY_MS) {
            switching = false;
            clearSwitchTimer();
            log(`${newMiner.name}: Umschaltung abgebrochen, Miner wurde nicht gestartet`, 'warn');
            return;
        }

        switchTimer = setTimeout(waitForNewMiner, ENABLE_RETRY_INTERVAL_MS);
    }

    switchTimer = setTimeout(waitForNewMiner, ENABLE_RETRY_INTERVAL_MS);
}

function protectBatteryImmediately() {
    const batteryPower = getNumber(BATTERY_POWER, 0);

    if (batteryPower &lt;= BATTERY_DISCHARGE_LIMIT_W) {
        return;
    }

    if (switching) {
        return;
    }

    const s19Running = getBoolean(S19.running);
    const s9Running = getBoolean(S9.running);

    if (s19Running) {
        if (isPowerRestartActive(S19)) {
            log('Batterieschutz S19 wartet: Neustart nach powerTarget läuft', 'debug');
            return;
        }

        const current = getNumber(S19.powerTarget, S19.minPower);
        const reduced = roundToStep(
            clamp(current - batteryPower, S19.minPower, S19.maxPower),
            S19_POWER_STEP_W
        );

        if (reduced &lt; S19.minPower || current - batteryPower &lt; S19.minPower) {
            log(`Batterie entlädt mit ${batteryPower} W: Wechsel vom S19 auf S9`, 'info');
            switchMiner(S9, S19);
            return;
        }

        if (reduced !== current) {
            setState(S19.powerTarget, reduced);
            lastValidTarget.S19 = reduced;
            log(`Batterieschutz: S19 powerTarget sofort auf ${reduced} W reduziert`, 'info');
        }
        return;
    }

    if (s9Running) {
        const current = getNumber(S9.powerTarget, S9.minPower);
        const rawReduced = current - batteryPower;

        if (rawReduced &lt; S9.minPower) {
            log(`Batterie entlädt mit ${batteryPower} W: S9 wird gestoppt`, 'info');
            stopMiner(S9);
            return;
        }

        const reduced = roundToStep(
            clamp(rawReduced, S9.minPower, S9.maxPower),
            S9_POWER_STEP_W
        );

        if (reduced !== current) {
            setState(S9.powerTarget, reduced);
            lastValidTarget.S9 = reduced;
            log(`Batterieschutz: S9 powerTarget sofort auf ${reduced} W reduziert`, 'info');
        }
    }
}

// ------------------------------------------------------------
// Sofortige Miner-Auswahl
// ------------------------------------------------------------

function selectMinerImmediately() {
    if (switching) {
        return;
    }

    const available = availablePvPower();
    const now = Date.now();
    const s9Running = isMinerActuallyRunning(S9);
    const s19Running = isMinerActuallyRunning(S19);

    if (isPowerRestartActive(S19)) {
        return;
    }

    // Während der ersten 3 Minuten nach einem Start nicht aufgrund
    // kurzzeitig unstabiler Adapter-/Netzwerte wieder abschalten.
    if (s19Running &amp;&amp; now - startedAt.S19 &lt; START_PROTECTION_MS) {
        return;
    }

    if (s9Running &amp;&amp; now - startedAt.S9 &lt; START_PROTECTION_MS) {
        return;
    }

    // S19 mit Hysterese beibehalten.
    if (s19Running &amp;&amp; available &gt;= S19_KEEP_THRESHOLD_W) {
        return;
    }

    // Ab 1900 W vom S9 auf den S19 wechseln.
    if (available &gt;= S19_START_THRESHOLD_W) {
        if (s19Running) {
            return;
        }

        if (s9Running) {
            switchMiner(S19, S9);
        } else {
            startMiner(S19);
        }
        return;
    }

    // Zwischen 600 W und 1899 W den S9 verwenden.
    if (available &gt;= S9_START_THRESHOLD_W) {
        if (s9Running) {
            return;
        }

        if (s19Running) {
            switchMiner(S9, S19);
        } else {
            startMiner(S9);
        }
        return;
    }

    // Zu wenig Überschuss: laufende Miner stoppen.
    stopMiner(S9);
    stopMiner(S19);
}

// ------------------------------------------------------------
// Leistungsregelung – höchstens alle 3 Minuten
// ------------------------------------------------------------

function regulatePower() {
    if (switching) {
        log('Regelzyklus übersprungen: Miner-Umschaltung läuft', 'debug');
        return;
    }

    const now = Date.now();
    const elapsed = now - lastPowerRegulation;

    if (elapsed &lt; POWER_REGULATION_INTERVAL_MS) {
        if (!regulationTimer) {
            regulationTimer = setTimeout(() =&gt; {
                regulationTimer = null;
                regulatePower();
            }, POWER_REGULATION_INTERVAL_MS - elapsed);
        }
        return;
    }

    lastPowerRegulation = now;

    const gridPower = getNumber(GRID_POWER, 0);
    const batteryPower = getNumber(BATTERY_POWER, 0);
    const batteryDischarge = Math.max(0, batteryPower);

    if (isMinerActuallyRunning(S19)) {
        if (isPowerRestartActive(S19)) {
            const rest = Math.ceil(
                (S19_POWER_RESTART_MS - (Date.now() - lastPowerChangeAt.S19)) / 1000
            );
            log(`REGELZYKLUS S19 übersprungen: Neustart nach Leistungsänderung, noch ca. ${rest} s`, 'info');
            return;
        }

        const currentTarget = getNumber(S19.powerTarget, S19.minPower);
        const correction = gridPower - GRID_TARGET_W + batteryDischarge;
        const rawTarget = currentTarget - correction;

        const newTarget = roundToStep(
            clamp(rawTarget, S19.minPower, S19.maxPower),
            S19_POWER_STEP_W
        );

        log(
            `REGELZYKLUS S19 | Netz=${gridPower} W | Ziel=${GRID_TARGET_W} W | ` +
            `Batterie=${batteryPower} W | Aktuell=${currentTarget} W | ` +
            `Korrektur=${Math.round(correction)} W | Neu=${newTarget} W`,
            'info'
        );

        // Reduzieren immer sofort.
        if (newTarget &lt; currentTarget) {
            s19UpCandidate = null;
            s19UpCandidateSince = 0;
            setPowerTargetIfChanged(S19, newTarget);
            return;
        }

        // Keine Änderung nötig.
        if (newTarget === currentTarget) {
            s19UpCandidate = null;
            s19UpCandidateSince = 0;
            return;
        }

        // Erhöhung: erst nach 3 Minuten stabiler Anforderung.
        if (s19UpCandidate !== newTarget) {
            s19UpCandidate = newTarget;
            s19UpCandidateSince = Date.now();
            log(`S19: höhere Stufe ${newTarget} W erkannt – 3-Minuten-Stabilitätszeit gestartet`, 'info');
            return;
        }

        const stableFor = Date.now() - s19UpCandidateSince;

        if (stableFor &gt;= S19_UP_STABLE_MS) {
            log(`S19: Überschuss 3 Minuten stabil – Erhöhung auf ${newTarget} W`, 'info');
            s19UpCandidate = null;
            s19UpCandidateSince = 0;
            setPowerTargetIfChanged(S19, newTarget);
            return;
        }

        const rest = Math.ceil((S19_UP_STABLE_MS - stableFor) / 1000);
        log(`S19: höhere Stufe ${newTarget} W noch nicht freigegeben – ca. ${rest} s stabil nötig`, 'info');
        return;
    }

    if (isMinerActuallyRunning(S9)) {
        const currentTarget = getNumber(S9.powerTarget, S9.minPower);
        const correction = gridPower - GRID_TARGET_W + batteryDischarge;
        const rawTarget = currentTarget - correction;

        const newTarget = roundToStep(
            clamp(rawTarget, S9.minPower, S9.maxPower),
            S9_POWER_STEP_W
        );

        log(
            `REGELZYKLUS S9 | Netz=${gridPower} W | Ziel=${GRID_TARGET_W} W | ` +
            `Batterie=${batteryPower} W | Aktuell=${currentTarget} W | ` +
            `Korrektur=${Math.round(correction)} W | Neu=${newTarget} W`,
            'info'
        );

        setPowerTargetIfChanged(S9, newTarget);
        return;
    }

    log(
        `REGELZYKLUS | kein Miner aktiv | Netz=${gridPower} W | Ziel=${GRID_TARGET_W} W | ` +
        `Batterie=${batteryPower} W`,
        'info'
    );
}

function handleSocketOff(miner) {
    if (getBoolean(miner.socket)) {
        return;
    }

    clearStartTimer(miner);
    cancelSocketOff(miner);

    if (getBoolean(miner.running)) {
        setState(miner.running, false);
        log(`${miner.name}: Steckdose ist AUS -&gt; running=false`, 'info');
    }

    if (getBoolean(miner.enabled)) {
        setState(miner.enabled, false);
        log(`${miner.name}: Steckdose ist AUS -&gt; enabled=false`, 'info');
    }
}

// ------------------------------------------------------------
// Trigger
// ------------------------------------------------------------

// Sofortige Reaktion auf Änderungen der Netzleistung.
on({ id: GRID_POWER, change: 'ne' }, () =&gt; {
    selectMinerImmediately();
    regulatePower();
});

// Sofortige Reaktion auf Batterieentladung.
on({ id: BATTERY_POWER, change: 'ne' }, () =&gt; {
    protectBatteryImmediately();
    selectMinerImmediately();
    regulatePower();
});

// Wenn eine Steckdose – auch durch eine andere Logik – ausgeschaltet wird,
// den Miner im Adapter sofort auf offline setzen.
on({ id: S9.socket, change: 'ne' }, obj =&gt; {
    if (!Boolean(obj.state.val)) {
        handleSocketOff(S9);
    }
});

on({ id: S19.socket, change: 'ne' }, obj =&gt; {
    if (!Boolean(obj.state.val)) {
        handleSocketOff(S19);
    }
});

// Leerlauftimer zuverlässig an running koppeln.
on({ id: S9.running, change: 'ne' }, obj =&gt; {
    if (Boolean(obj.state.val)) {
        startedAt.S9 = Date.now();
        cancelSocketOff(S9);
    } else {
        scheduleSocketOff(S9);
    }
});

on({ id: S19.running, change: 'ne' }, obj =&gt; {
    if (Boolean(obj.state.val)) {
        startedAt.S19 = Date.now();
        cancelSocketOff(S19);
    } else {
        scheduleSocketOff(S19);
    }
});

// ------------------------------------------------------------
// Startinitialisierung
// ------------------------------------------------------------

setTimeout(() =&gt; {
    const s9AlreadyRunning = isMinerActuallyRunning(S9);
    const s19AlreadyRunning = isMinerActuallyRunning(S19);

    if (s9AlreadyRunning) {
        startedAt.S9 = Date.now() - START_PROTECTION_MS;
        cancelSocketOff(S9);
        log(`STARTERKENNUNG: S9 läuft bereits | Leistung=${getNumber(S9.actualPower, 0)} W`, 'info');
    }

    if (s19AlreadyRunning) {
        startedAt.S19 = Date.now() - START_PROTECTION_MS;
        cancelSocketOff(S19);
        log(`STARTERKENNUNG: S19 läuft bereits | Leistung=${getNumber(S19.actualPower, 0)} W`, 'info');
    }

    selectMinerImmediately();
    regulatePower();

    if (!getBoolean(S9.running)) {
        scheduleSocketOff(S9);
    }

    if (!getBoolean(S19.running)) {
        scheduleSocketOff(S19);
    }

    log('PV-Miner-Regelung V2.17 gestartet', 'info');
}, 5000);


]]></description><link>https://forum.iobroker.net/topic/84420/test-adapter-miner-version-v1.0.x-latest</link><guid isPermaLink="true">https://forum.iobroker.net/topic/84420/test-adapter-miner-version-v1.0.x-latest</guid><dc:creator><![CDATA[MichaelF]]></dc:creator><pubDate>Sat, 08 Aug 2026 18:11:44 GMT</pubDate></item><item><title><![CDATA[[gelöst] VIS2.0 Einstell - Body overflow - Fire HD 10 Tablet]]></title><description><![CDATA[@Cyberraph
Schau mal mit den Web Developer Tools vom Browser mit F12 nach
Jedes Widget müsste eine einheitliche CSS Klasse haben.
Damit müsstest du mit einer Anweisung allen Widgets dies zuordnen können.
]]></description><link>https://forum.iobroker.net/topic/82410/gelöst-vis2-0-einstell-body-overflow-fire-hd-10-tablet</link><guid isPermaLink="true">https://forum.iobroker.net/topic/82410/gelöst-vis2-0-einstell-body-overflow-fire-hd-10-tablet</guid><dc:creator><![CDATA[OliverIO]]></dc:creator><pubDate>Sat, 08 Aug 2026 17:41:14 GMT</pubDate></item><item><title><![CDATA[Test Adapter VW Connect für VW, ID, Audi, Seat, Skoda]]></title><description><![CDATA[@tombox
Hallo, sind in der GitHub Version nur die Änderungen für Skoda?
]]></description><link>https://forum.iobroker.net/topic/26438/test-adapter-vw-connect-für-vw-id-audi-seat-skoda</link><guid isPermaLink="true">https://forum.iobroker.net/topic/26438/test-adapter-vw-connect-für-vw-id-audi-seat-skoda</guid><dc:creator><![CDATA[wibear]]></dc:creator><pubDate>Sat, 08 Aug 2026 17:34:01 GMT</pubDate></item><item><title><![CDATA[Test Adapter jetframe v1.2.0]]></title><description><![CDATA[ScreenRecording_08-08-2026 18-55-44_1.mov
]]></description><link>https://forum.iobroker.net/topic/85129/test-adapter-jetframe-v1.2.0</link><guid isPermaLink="true">https://forum.iobroker.net/topic/85129/test-adapter-jetframe-v1.2.0</guid><dc:creator><![CDATA[backfisch88]]></dc:creator><pubDate>Sat, 08 Aug 2026 16:56:40 GMT</pubDate></item><item><title><![CDATA[Ping Adapter und Iphone]]></title><description><![CDATA[Bin da schon ein paar Tage dran mit hilfe Gemini an einem Javascript zu basteln. Da dann natürlich auch immer Telegrammeldungen kamen ist offline ist online .....
Meine Geräte habe ich als Aliase angelegt und gerade im Moment scheint das script zu funktionieren. Zusätzlich zu Pingabfrage kommt nun auch noch ein check ob die Wohnungstür geöffnet und geschlossen wurde. Zudem hat das Script noch einen Puffer den man in Sekunden einstellen kann, der dann abläuft bevor man eine Meldung bekommt, wenn das Gerät in der zwischenzeit sich wieder verbindet ist alles gut.
Jetzt wurde noch automatsch unter userdata Datenpunkte für jedes Gerät angelegt (für Iqontrol) die werden erst dann auf true oder false geschalten wenn eine Telegrammeldung raus geht.
]]></description><link>https://forum.iobroker.net/topic/85139/ping-adapter-und-iphone</link><guid isPermaLink="true">https://forum.iobroker.net/topic/85139/ping-adapter-und-iphone</guid><dc:creator><![CDATA[Michael Schmitt]]></dc:creator><pubDate>Sat, 08 Aug 2026 16:31:14 GMT</pubDate></item><item><title><![CDATA[[Erledigt] backitup stellt nicht wieder her (?)]]></title><description><![CDATA[Das war ja einfach 
Danke, ich schließe das Thema
]]></description><link>https://forum.iobroker.net/topic/85138/erledigt-backitup-stellt-nicht-wieder-her</link><guid isPermaLink="true">https://forum.iobroker.net/topic/85138/erledigt-backitup-stellt-nicht-wieder-her</guid><dc:creator><![CDATA[amg_666]]></dc:creator><pubDate>Sat, 08 Aug 2026 16:17:25 GMT</pubDate></item><item><title><![CDATA[LaundryLens]]></title><description><![CDATA[@icebear
Sollte mit 0.4.5 behoben sein. So wie auch hoffentlich alle anderen genannten Dinge 🙂
]]></description><link>https://forum.iobroker.net/topic/85041/laundrylens</link><guid isPermaLink="true">https://forum.iobroker.net/topic/85041/laundrylens</guid><dc:creator><![CDATA[backfisch88]]></dc:creator><pubDate>Sat, 08 Aug 2026 15:59:35 GMT</pubDate></item><item><title><![CDATA[ALEXA Einkaufsliste mit Marktzuordnung und Laufrouten]]></title><description><![CDATA[@homoran
Da da kein Adapter veröffentlicht wird, bitte Beitrag  löschen.
Ohne Repo kann niemand checken was da dahinter steht. Außerdem muss bei allen Adaptern mit kommerzieller Lizenz @Bluefox sein OK geben.
EDIT:
Dev hat das Repo nun auf Github freigeschaltet. Mal sehen ob er es auch hier veröffentlicht.
]]></description><link>https://forum.iobroker.net/topic/85135/alexa-einkaufsliste-mit-marktzuordnung-und-laufrouten</link><guid isPermaLink="true">https://forum.iobroker.net/topic/85135/alexa-einkaufsliste-mit-marktzuordnung-und-laufrouten</guid><dc:creator><![CDATA[mcm1957]]></dc:creator><pubDate>Sat, 08 Aug 2026 13:42:57 GMT</pubDate></item><item><title><![CDATA[Adapter mihome-vacuum anpassungen]]></title><description><![CDATA[Okay, dank dir für die Info.
Aber du aktualisierst irgendwann den Adapter, der stable steht?
Mit der neuen Version 5.3.0 bekomme ich folgende Warnung:
TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received null

]]></description><link>https://forum.iobroker.net/topic/28615/adapter-mihome-vacuum-anpassungen</link><guid isPermaLink="true">https://forum.iobroker.net/topic/28615/adapter-mihome-vacuum-anpassungen</guid><dc:creator><![CDATA[Siggi0904]]></dc:creator><pubDate>Sat, 08 Aug 2026 13:40:39 GMT</pubDate></item><item><title><![CDATA[iobroker kann Datenbank nicht erreichen nach Komplettabsturz]]></title><description><![CDATA[@Schasa
Bitte vollständig. Ohne Änderungen von dir.
]]></description><link>https://forum.iobroker.net/topic/85130/iobroker-kann-datenbank-nicht-erreichen-nach-komplettabsturz</link><guid isPermaLink="true">https://forum.iobroker.net/topic/85130/iobroker-kann-datenbank-nicht-erreichen-nach-komplettabsturz</guid><dc:creator><![CDATA[Thomas Braun]]></dc:creator><pubDate>Sat, 08 Aug 2026 12:14:01 GMT</pubDate></item><item><title><![CDATA[{gelöst} Maxcul Adapter veraltet, bitte aktualisieren.]]></title><description><![CDATA[Der Maxcul-Adapter ist irgendwann Grün geworden.....
]]></description><link>https://forum.iobroker.net/topic/76077/gelöst-maxcul-adapter-veraltet-bitte-aktualisieren</link><guid isPermaLink="true">https://forum.iobroker.net/topic/76077/gelöst-maxcul-adapter-veraltet-bitte-aktualisieren</guid><dc:creator><![CDATA[ESP8266]]></dc:creator><pubDate>Sat, 08 Aug 2026 11:58:08 GMT</pubDate></item><item><title><![CDATA[Test Adapter Vaillant multiMatic&#x2F;senso und myVaillant]]></title><description><![CDATA[github erneut installieren
]]></description><link>https://forum.iobroker.net/topic/29221/test-adapter-vaillant-multimatic-senso-und-myvaillant</link><guid isPermaLink="true">https://forum.iobroker.net/topic/29221/test-adapter-vaillant-multimatic-senso-und-myvaillant</guid><dc:creator><![CDATA[tombox]]></dc:creator><pubDate>Sat, 08 Aug 2026 10:30:19 GMT</pubDate></item><item><title><![CDATA[Homematic IP Cloud Access Point Adapter]]></title><description><![CDATA[Gibt es eigentlich Aussagen von e3, ob der Support der Cloudfreien Anbindung z.B. über openccu nicht mehr unterstützt wird?
Ich mache mich nicht gerne von Cloud- Servern eines Smart-Home Herstellers abhängig, und gehe deshalb derzeit über openccu
]]></description><link>https://forum.iobroker.net/topic/27532/homematic-ip-cloud-access-point-adapter</link><guid isPermaLink="true">https://forum.iobroker.net/topic/27532/homematic-ip-cloud-access-point-adapter</guid><dc:creator><![CDATA[MartinP]]></dc:creator><pubDate>Sat, 08 Aug 2026 09:27:41 GMT</pubDate></item><item><title><![CDATA[Test Adapter public-transport v0.10.x @latest]]></title><description><![CDATA[Neue Beta-Version verfügbar
1.0.0 (2026-08-08)


Die Konfigurationsoberfläche wurde auf die neue Admin-UI umgestellt (React 19, MUI 9). Ab dieser Version wird Admin 8.0.1 oder neuer benötigt


Weil damit eine neue Mindestvoraussetzung dazukommt, ist es eine Major-Version. An der Funktion des Adapters selbst ändert sich nichts – Abfahrten, Verbindungen, Datenpunkte und Widgets verhalten sich wie in 0.10.2.


Wer noch auf Admin 7 ist, bleibt bitte zunächst auf 0.10.2 und aktualisiert den Adapter erst nach dem Admin-Update.
Diese Version wird ab morgen im Latest/Beta sein.
Vielen Dank fürs Testen und euer Feedback.
Bitte schreibt hier in den Thread oder besser noch erstellt ein Issue auf Github.
https://github.com/tt-tom17/ioBroker.public-transport/issues
PS: mobiData-BW und VRR haben sich zurückgemeldet, meine Zugänge haben ich bekommen. Damit sind wir wieder ein Step weiter. Alles weitere dann Ende August.
Was steht noch auf der ToDo:

Datenpunkte reduzieren (Auswahl)
Datenpunkte für nsPanel -Adapter seperat (Auswahl)
Einbinden von mobiData-BW und VRR
und eure Issue auf Github natürlich 

]]></description><link>https://forum.iobroker.net/topic/84426/test-adapter-public-transport-v0.10.x-@latest</link><guid isPermaLink="true">https://forum.iobroker.net/topic/84426/test-adapter-public-transport-v0.10.x-@latest</guid><dc:creator><![CDATA[TT-Tom]]></dc:creator><pubDate>Sat, 08 Aug 2026 08:44:13 GMT</pubDate></item><item><title><![CDATA[Iobroker start 5:04 und 22:56 abstellen Wie]]></title><description><![CDATA[Ich würde den Cron bei Telegram lassen und nur die Meldung ausschalten. Mache ich seit Jahren so.
[image: 1786178015687-bf5450f7-ce46-4dba-8056-21292469a556-image.jpeg]
[image: 1786178078384-9482aed6-91db-4f72-8ed0-379c1b63fe4a-image.jpeg]
]]></description><link>https://forum.iobroker.net/topic/85123/iobroker-start-5-04-und-22-56-abstellen-wie</link><guid isPermaLink="true">https://forum.iobroker.net/topic/85123/iobroker-start-5-04-und-22-56-abstellen-wie</guid><dc:creator><![CDATA[skvarel]]></dc:creator><pubDate>Sat, 08 Aug 2026 08:34:40 GMT</pubDate></item><item><title><![CDATA[Test Adapter Energiefluss-erweitert v0.8.x GitHub&#x2F;Latest]]></title><description><![CDATA[Ich bin immer wieder begeistert, wie gut der Adapter ist!
@skb .. vielen Dank für deine Arbeit.
Ich muss jetzt nur noch auf die gedrehten Rechtecke umbauen ;)
[image: 1786177667862-14817eca-2257-4db5-8ac2-aa55e893d44f-image.jpeg]
]]></description><link>https://forum.iobroker.net/topic/75485/test-adapter-energiefluss-erweitert-v0.8.x-github-latest</link><guid isPermaLink="true">https://forum.iobroker.net/topic/75485/test-adapter-energiefluss-erweitert-v0.8.x-github-latest</guid><dc:creator><![CDATA[skvarel]]></dc:creator><pubDate>Sat, 08 Aug 2026 08:28:16 GMT</pubDate></item><item><title><![CDATA[Test Adapter Creality - Alpha]]></title><description><![CDATA[[image: 1786176274051-e1fdcf22-8bb8-45be-8f71-1f9124338065-image.jpeg]
]]></description><link>https://forum.iobroker.net/topic/85082/test-adapter-creality-alpha</link><guid isPermaLink="true">https://forum.iobroker.net/topic/85082/test-adapter-creality-alpha</guid><dc:creator><![CDATA[skvarel]]></dc:creator><pubDate>Sat, 08 Aug 2026 08:04:36 GMT</pubDate></item></channel></rss>