Perfekte Lüftungsempfehlung

Hallo zusammen,

ich möchte diesem Forum gerne etwas zurück geben, nachdem ich bereits so oft hier Hilfe und Unterstützung bekommen habe.
Ich habe mich schon lange gefragt, wie eine gut und korrekte Lüftungsempfehlung aussehen kann. dabei bin ich über diese Seite gestolpert:

https://www.sarahandrobin.com/ingo/luftfeuchtigkeit.php

hier wird das Thema wirklich sehr umfassend behandelt und ein Rechner zu verfügung gestellt. Ich bin sehr dankbar, dass ich dieses nutzen durfte und hier auch teilen darf. Ich haben diesen für homey angepasst.

Zunächst braucht ihr dieses Homey Script:


const searchname = "Luft Bad";

async function findDeviceByName(searchname) {
    try {
        // Abrufen aller Geräte
        const devices = await Homey.devices.getDevices();
        
        // Filtern der Geräte basierend auf dem Namen
        const matchedDevices = Object.values(devices)
            .filter(device => device.name.toLowerCase().includes(searchname.toLowerCase()))
            .map(device => ({ id: device.id, name: device.name }));
        
        // Überprüfen, ob Geräte gefunden wurden
        if (matchedDevices.length > 0) {
            console.log('Gefundene Geräte:', matchedDevices);
        } else {
            console.log('Keine Geräte gefunden, die den Namen enthalten:', searchname);
        }
        
        return matchedDevices;
    } catch (error) {
        console.error('Fehler beim Abrufen der Geräte:', error);
    }
}

// Skript ausführen
findDeviceByName(searchname);

Bei “Luft Bad” gebt ihr bitte den Namen eure Gerätes ein, dass die Luftfeuchtigkeit und Temperatur im Raum misst.

Dieses Script Startet ihr in Homey und erhaltet die ID eures Gerätes.
Das selbe mach ihr für euren Sensor draußen. Auch hier die ID notieren.

Dann erstellt ihr eine neue Text Variable z.B. mit dem Namen “2. Lüften Bad”

Dann nehmt ihr dieses Script:

// IDs der Sensoren
const innenSensorId = 'hier ID eingeben'; // Innen-Sensor-ID
const aussenSensorId = 'hier ID eingeben'; // Außen-Sensor-ID

// Funktion, um den Wert eines Sensors zu holen
async function getCapabilityValue(deviceId, capability) {
    try {
        let device = await Homey.devices.getDevice({ id: deviceId });
        return device.capabilitiesObj[capability].value;
    } catch (error) {
        console.error(`Fehler beim Abrufen des Werts für Gerät ${deviceId} und Fähigkeit ${capability}:`, error);
        return null;
    }
}

// Berechnung der absoluten Feuchtigkeit
function absoluteFeuchte(r, t) {
    let a, b;
    if (t >= 0) {
        a = 7.5;
        b = 237.3;
    } else {
        a = 7.6;
        b = 240.7;
    }
    return (Math.pow(10, 5) * 18.016 / 8314.3 * r / 100.0 * 6.1078 * Math.pow(10, (a * t) / (b + t))) / (t + 273.15);
}

// Berechnung der umgerechneten Innenfeuchte
function umgerechneteInnenFeuchte(aussenTemp, aussenFeuchte, innenTemp) {
    let a1, b1, a2, b2;
    if (aussenTemp >= 0) {
        a1 = 7.5;
        b1 = 237.3;
    } else {
        a1 = 7.6;
        b1 = 240.7;
    }
    if (innenTemp >= 0) {
        a2 = 7.5;
        b2 = 237.3;
    } else {
        a2 = 7.6;
        b2 = 240.7;
    }
    return aussenFeuchte * Math.pow(10, (a1 * aussenTemp) / (b1 + aussenTemp)) / Math.pow(10, (a2 * innenTemp) / (b2 + innenTemp)) * (innenTemp + 273.15) / (aussenTemp + 273.15);
}

async function main() {
    // Innenwerte (Temperatur und Feuchtigkeit)
    const innenTemp = await getCapabilityValue(innenSensorId, 'measure_temperature');
    const innenFeuchte = await getCapabilityValue(innenSensorId, 'measure_humidity');

    // Außenwerte (Temperatur und Feuchtigkeit)
    const aussenTemp = await getCapabilityValue(aussenSensorId, 'measure_temperature');
    const aussenFeuchte = await getCapabilityValue(aussenSensorId, 'measure_humidity');

    // Überprüfen, ob Werte erfolgreich abgerufen wurden
    if (innenTemp === null || innenFeuchte === null || aussenTemp === null || aussenFeuchte === null) {
        console.error('Nicht alle Sensorwerte konnten abgerufen werden.');
        return;
    }

    // Ausgabe der Werte in der Konsole
    console.log(`Innen-Temperatur: ${innenTemp}`);
    console.log(`Innen-Feuchtigkeit: ${innenFeuchte}`);
    console.log(`Außen-Temperatur: ${aussenTemp}`);
    console.log(`Außen-Feuchtigkeit: ${aussenFeuchte}`);

    // Berechnungen
    const innenAbsFeuchte = round(absoluteFeuchte(innenFeuchte, innenTemp), 1);
    const aussenAbsFeuchte = round(absoluteFeuchte(aussenFeuchte, aussenTemp), 1);

    console.log(`Absolute Feuchtigkeit Innen: ${innenAbsFeuchte} g/m³`);
    console.log(`Absolute Feuchtigkeit Außen: ${aussenAbsFeuchte} g/m³`);

    const innenFeuchteI = round(umgerechneteInnenFeuchte(aussenTemp, aussenFeuchte, innenTemp), 0);

    // Näherung
    const deltaTemp = innenTemp - aussenTemp;
    const innenFeuchteN = round(aussenFeuchte - 3.0 * deltaTemp, 0);

    console.log(`Auf die Innentemperatur umgerechnete Außenluftfeuchtigkeit: ${innenFeuchteI} %`);
    console.log(`Näherungsformel: Außenfeuchte - 3*Δt = ${aussenFeuchte} - 3 * ${deltaTemp} = ${innenFeuchteN} %`);

    const neueInnenRelFeuchte = round(0.25 * innenFeuchte + 0.75 * innenFeuchteI, 0);

    let lueftungsergebnis = '';

    // Ergebnisse interpretieren
    if (Math.abs(innenAbsFeuchte - aussenAbsFeuchte) <= 0.5) {
        lueftungsergebnis = 'Etwa gleiche Feuchtigkeiten innen und außen';
    } else if (innenAbsFeuchte > aussenAbsFeuchte && innenTemp > aussenTemp) {
        lueftungsergebnis = 'Lüften!!';
    } else if (innenAbsFeuchte > aussenAbsFeuchte && innenTemp <= aussenTemp) {  // Korrigiert
        lueftungsergebnis = 'Lüften möglich, aber es wird dadurch wärmer!!';
    } else if (neueInnenRelFeuchte <= 55) {
        lueftungsergebnis = 'Kurzes Lüften möglich, aber es wird dadurch etwas feuchter (ist aber bis 50-60 % OK)';
    } else if (neueInnenRelFeuchte <= 65) {
        lueftungsergebnis = 'Sehr kurzes Lüften möglich, aber es wird dadurch viel feuchter (ist aber bis 60 % noch akzeptabel)';
    } else {
        lueftungsergebnis = 'NICHT lüften!';
    }

    console.log(lueftungsergebnis);

    // Lüftungsergebnis als Variable in Homey speichern
    const variableName = "2. Lüften Bad";
    try {
        let variables = await Homey.logic.getVariables();
        let variable = Object.values(variables).find(v => v.name === variableName);

        if (variable) {
            // Variable existiert, Wert aktualisieren
            await Homey.logic.updateVariable({ id: variable.id, variable: { value: lueftungsergebnis } });
            console.log(`Variable '${variableName}' aktualisiert: ${lueftungsergebnis}`);
        } else {
            // Variable existiert nicht, neue Variable erstellen
            await Homey.logic.createVariable({ name: variableName, type: 'string', value: lueftungsergebnis });
            console.log(`Variable '${variableName}' erstellt und gesetzt: ${lueftungsergebnis}`);
        }
    } catch (error) {
        console.error(`Fehler beim Speichern der Variable '${variableName}':`, error);
    }
}

// Hilfsfunktion zum Runden auf eine bestimmte Anzahl von Dezimalstellen
function round(value, decimals) {
    return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);
}

// Skript ausführen
main();

tragt nun bitte ganz oben bei “hier ID eingeben” die ID der beiden Geräte ein.
Dann bitte bei Zeile 108 den Namen der Variable eingeben.

nun könnt ihr das Script das erste ma testen.

Dann einen Flow erstellen.

Ich habe das so gelöst:

Dann könnt ihr mit der Variable in euren Flows weiter arbeiten.

Bei Fragen meldet euch gerne. Ich hoffe es kann jemandem weiterhelfen!

6 Likes

Super! Ich werde damit spielen.

Hallo Peter,
das freut mich sehr! Deine Flow hat mich auf die Idee gebracht.
Ich habe diesen heute auch noch etwas weiter entwickelt.
Wenn du interesse hast, melde dich gerne.

1 Like

Vielen Dank für Deine Mühen und fürs Teilen! :+1:t2:

Kannst Deinen Flow auch gerne direkt allen zur Verfügung stellen… :wink:

Moin zusammen,
hier ist das Script noch mal etwas überarbeitet.
Es kann nun eine weitere Variable vorher angelegt werden, die dann zusätzlich mit den Daten befüllt wird, wie sich die Luftfeuchtigkeit voraussichtlich nach dem Lüften verhalten wird.

// IDs der Sensoren
const innenSensorId = 'IDGerät1'; // Innen-Sensor-ID
const aussenSensorId = 'IDGerät2'; // Außen-Sensor-ID

// Name der Info-Variable
const infoVariableName = "weiterVariablefürmehrInfos";

// Funktion, um den Wert eines Sensors zu holen
async function getCapabilityValue(deviceId, capability) {
    try {
        let device = await Homey.devices.getDevice({ id: deviceId });
        return device.capabilitiesObj[capability].value;
    } catch (error) {
        console.error(`Fehler beim Abrufen des Werts für Gerät ${deviceId} und Fähigkeit ${capability}:`, error);
        return null;
    }
}

// Berechnung der absoluten Feuchtigkeit
function absoluteFeuchte(r, t) {
    let a, b;
    if (t >= 0) {
        a = 7.5;
        b = 237.3;
    } else {
        a = 7.6;
        b = 240.7;
    }
    return (Math.pow(10, 5) * 18.016 / 8314.3 * r / 100.0 * 6.1078 * Math.pow(10, (a * t) / (b + t))) / (t + 273.15);
}

// Berechnung der umgerechneten Innenfeuchte
function umgerechneteInnenFeuchte(aussenTemp, aussenFeuchte, innenTemp) {
    let a1, b1, a2, b2;
    if (aussenTemp >= 0) {
        a1 = 7.5;
        b1 = 237.3;
    } else {
        a1 = 7.6;
        b1 = 240.7;
    }
    if (innenTemp >= 0) {
        a2 = 7.5;
        b2 = 237.3;
    } else {
        a2 = 7.6;
        b2 = 240.7;
    }
    return aussenFeuchte * Math.pow(10, (a1 * aussenTemp) / (b1 + aussenTemp)) / Math.pow(10, (a2 * innenTemp) / (b2 + innenTemp)) * (innenTemp + 273.15) / (aussenTemp + 273.15);
}

async function main() {
    // Innenwerte (Temperatur und Feuchtigkeit)
    const innenTemp = await getCapabilityValue(innenSensorId, 'measure_temperature');
    const innenFeuchte = await getCapabilityValue(innenSensorId, 'measure_humidity');

    // Außenwerte (Temperatur und Feuchtigkeit)
    const aussenTemp = await getCapabilityValue(aussenSensorId, 'measure_temperature');
    const aussenFeuchte = await getCapabilityValue(aussenSensorId, 'measure_humidity');

    // Überprüfen, ob Werte erfolgreich abgerufen wurden
    if (innenTemp === null || innenFeuchte === null || aussenTemp === null || aussenFeuchte === null) {
        console.error('Nicht alle Sensorwerte konnten abgerufen werden.');
        return;
    }

    // Berechnungen
    const innenFeuchteI = round(umgerechneteInnenFeuchte(aussenTemp, aussenFeuchte, innenTemp), 0);
    const deltaTemp = innenTemp - aussenTemp;
    const neueInnenRelFeuchte = round(0.25 * innenFeuchte + 0.75 * innenFeuchteI, 0);

    let lueftungsergebnis = '';

    // Ergebnisse interpretieren
    if (Math.abs(absoluteFeuchte(innenFeuchte, innenTemp) - absoluteFeuchte(aussenFeuchte, aussenTemp)) <= 0.5) {
        lueftungsergebnis = 'Etwa gleiche Feuchtigkeiten innen und außen';
    } else if (absoluteFeuchte(innenFeuchte, innenTemp) > absoluteFeuchte(aussenFeuchte, aussenTemp) && innenTemp > aussenTemp) {
        lueftungsergebnis = 'Lüften!!';
    } else if (absoluteFeuchte(innenFeuchte, innenTemp) > absoluteFeuchte(aussenFeuchte, aussenTemp) && innenTemp <= aussenTemp) {
        lueftungsergebnis = 'Lüften möglich, aber es wird dadurch wärmer!!';
    } else if (neueInnenRelFeuchte <= 55) {
        lueftungsergebnis = 'Kurzes Lüften möglich, aber es wird dadurch etwas feuchter (ist aber bis 50-60 % OK)';
    } else if (neueInnenRelFeuchte <= 65) {
        lueftungsergebnis = 'Sehr kurzes Lüften möglich, aber es wird dadurch viel feuchter (ist aber bis 60 % noch akzeptabel)';
    } else {
        lueftungsergebnis = 'NICHT lüften!';
    }

    // Bestimmen, ob die Feuchtigkeit steigt oder fällt
    let feuchteVeränderung = 'bleibt unverändert';
    if (neueInnenRelFeuchte > innenFeuchte) {
        feuchteVeränderung = `steigt von ${innenFeuchte}% auf ${neueInnenRelFeuchte}%`;
    } else if (neueInnenRelFeuchte < innenFeuchte) {
        feuchteVeränderung = `fällt von ${innenFeuchte}% auf ${neueInnenRelFeuchte}%`;
    }

    // Zusammenstellung der Infos für die Variable
    const schlafzimmerInfo = `Erwartende Werte: ${feuchteVeränderung}`;

    // Lüftungsergebnis als Variable in Homey speichern
    const lueftungVariableName = "1. Lüften HWR";

    try {
        let variables = await Homey.logic.getVariables();
        let lueftungVariable = Object.values(variables).find(v => v.name === lueftungVariableName);
        let infoVariable = Object.values(variables).find(v => v.name === infoVariableName);

        if (lueftungVariable) {
            // Lüftungsvariable existiert, Wert aktualisieren
            await Homey.logic.updateVariable({ id: lueftungVariable.id, variable: { value: lueftungsergebnis } });
            console.log(`Variable '${lueftungVariableName}' aktualisiert: ${lueftungsergebnis}`);
        } else {
            // Lüftungsvariable existiert nicht, neue Variable erstellen
            await Homey.logic.createVariable({ name: lueftungVariableName, type: 'string', value: lueftungsergebnis });
            console.log(`Variable '${lueftungVariableName}' erstellt und gesetzt: ${lueftungsergebnis}`);
        }

        if (infoVariable) {
            // Info-Variable existiert, Wert aktualisieren
            await Homey.logic.updateVariable({ id: infoVariable.id, variable: { value: schlafzimmerInfo } });
            console.log(`Variable '${infoVariableName}' aktualisiert: ${schlafzimmerInfo}`);
        } else {
            // Info-Variable existiert nicht, neue Variable erstellen
            await Homey.logic.createVariable({ name: infoVariableName, type: 'string', value: schlafzimmerInfo });
            console.log(`Variable '${infoVariableName}' erstellt und gesetzt: ${schlafzimmerInfo}`);
        }
    } catch (error) {
        console.error(`Fehler beim Speichern der Variablen:`, error);
    }
}

// Hilfsfunktion zum Runden auf eine bestimmte Anzahl von Dezimalstellen
function round(value, decimals) {
    return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);
}

// Skript ausführen
main();

Wichtig ist: Die Variablen müssen beiden selbst angelegt werden. Mir ist es leider nicht gelungen, dass dieses durch das Script angelegt werden.

2 Likes

Danke!
Ich kann auch nicht in bestehende Variablen schreiben.
Ich bevorzuge die Verwendung von ‘Tags’.
Funktioniert gut, mit 1 Zeile Code (siehe Skriptbeispiele in homeyscript).

Wie funktioniert das mit Tags? Das habe ich noch nie probiert.

Aber ich denke dieses Script betrachtet das Thema sehr umfassen. Das ganze kann dann gut genutzt werden um an das lüften zu erinnern oder auch daran das Fenster zu schließen, damit es nicht noch feuchter wird.

Hallo Simon,

Lasst mich euch das erklären.

Code (dies funktioniert auch bei neuen Tags, der Tag wird dann sofort erstellt):

    // Lüftungsergebnis als HS Variable in Homey speichern
    await tag('Ventilation results', lueftungsergebnis);


Tag in eine Flow Karte einfügen:
Suche auf den Tagname oder die Überschrift „Homeyscript“, unter der alle in HS erstellten Tags aufgeführt sind:
Screenshot from 2024-09-05 17-52-49

1 Like

Ah cool … fast schöner als tausend variablen

Seht, was ihr mich machen lasst :wink: :crazy_face:
Ich habe ein advanced virtuelles Gerät erstellt, das alles und jeden anzeigt. Dies steuert auch den Lüfter.

Flow:

AVD:

Betrifft das 2. Skript.

Ein Vorschlag um es den Nutzern etwas leichter zu machen die sich mit HomeyScripts nicht auskennen, wenn das mit den Variablen beibehalten werden soll.
Man könnte z.B. alle Einträge direkt zu Beginn des Scripts auflisten, in denen der Benutzer seine persönliche Daten eintragen muss:

// IDs der Sensoren
const innenSensorId = 'hier ID eingeben'; // Innen-Sensor-ID
const aussenSensorId = 'hier ID eingeben'; // Außen-Sensor-ID

// Name der Ergebnis-Variable
const lueftungVariableName = "hier Variable für das Ergebnis eingeben"; // Text-Variable

// Name der Info-Variable
const infoVariableName = "hier Variable für die Info eingeben"; // Text-Variable

// Ab hier keine Änderungen am Script mehr vornehmen!
...

Bei dem überarbeiteten Script muss die Ergebnis-Variable nämlich auch nicht mehr in Zeile 108, sondern in Zeile 101 eingetragen werden. Wer sich damit nicht auskennt, wird eventuell Schwierigkeiten haben das Script ans Laufen zu bekommen.


Beim Suchen der Zeile in der die Ergebnis-Variable eingetragen werden muss, bin ich auf 5 Einträge namens const schlafzimmerInfo gestoßen. Durch versuchsweises Umbenennen dieses Parameters in const vorhersageInfo habe ich feststellen können, dass das Script trotzdem ordnungsgemäß funktioniert. Eventuell macht es Sinn diesen Parameter entsprechend umzubennen.


Was mir zwischen den beiden Scripts noch aufgefallen ist, dass die Ausgabe der Ergebnisse in der Konsole unterschiedlich ist, natürlich abgesehen von der neuen Info-Variable im neuen Script.

Altes Script:

———————————————————
✅ Script Success
↩️ Returned: undefined
Innen-Temperatur: 23.1
Innen-Feuchtigkeit: 59
Außen-Temperatur: 23.5
Außen-Feuchtigkeit: 75
Absolute Feuchtigkeit Innen: 12.2 g/m³
Absolute Feuchtigkeit Außen: 15.9 g/m³
Auf die Innentemperatur umgerechnete Außenluftfeuchtigkeit: 77 %
Näherungsformel: Außenfeuchte - 3*Δt = 75 - 3 * -0.3999999999999986 = 76 %
Nicht lüften
Variable 'LüftenBad' aktualisiert: Nicht lüften

Neues Script:

———————————————————
✅ Script Success
↩️ Returned: undefined
Variable 'LüftenBad' aktualisiert: NICHT lüften!
Variable 'LüftenBadInfo' aktualisiert: Erwartende Werte: steigt von 59% auf 73%

Ist das so gewollt, dass bei dem neuen Script die ganzen Zusatzinfos nicht mehr ausgegeben werden?
Spielt für die Funktion letztlich keine Rolle, würde mich nur interessieren.

Sehr gute Hinweise Dirk,

ich wollte eigentlich auch so haben, dass alles oben eingetragen werden kann, habe es aber nicht hinbekommen :wink:

Die Einträge namens const schlafzimmerInfo sind bestimmt noch relikte aus meinen vielen versuchen. Dabei habe ich das ganze auch für anderen Räume getestet.

Genau die Ergebnisse in der Konsole sind unterschiedlich. Ich wollte bestimmte Infromationen für die zweite Variable ausblenden. Habe sie aber dann nur ganz ausgeblendet bekommen.

Es ist vielleichte die “perfekte Lüftungsempfehlung” aber nicht das perfekte Script. Ich lerne gerne dazu.

Kein Problem. Ich wäre ja froh wenn ich so ein Script selber programmieren könnte.

Hallo Simon,

Interessanterweise unterscheiden sich die Ergebnisse der von mir verwendeten Berechnung jetzt nicht so sehr von deiner Berechnung.
Oder glaubst du, dass es große Unterschiede sind? Ich bin kein Experte :crazy_face:
Vielleicht ändert sich das bei größeren Temperaturunterschieden?

Hallo Peter,

Nach dem ich diesen Artikel noch mal etwas genauer studiert habe, ist es sehr wahrscheinlich, dass du recht hast. Schön finde ich dennoch die Info, dass es deutlich kälter oder wärmer wird.

https://www.sarahandrobin.com/ingo/luftfeuchtigkeit.php

Was denkst du ist Ressourcen schonender? Das Script oder dein Flow?