Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • 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. JavaScript
  5. Absolute Luftfeuchte Skript

NEWS

  • Jahresrückblick 2025 – unser neuer Blogbeitrag ist online! ✨
    BluefoxB
    Bluefox
    16
    1
    938

  • Neuer Blogbeitrag: Monatsrückblick - Dezember 2025 🎄
    BluefoxB
    Bluefox
    13
    1
    689

  • Weihnachtsangebot 2025! 🎄
    BluefoxB
    Bluefox
    25
    1
    2.0k

Absolute Luftfeuchte Skript

Geplant Angeheftet Gesperrt Verschoben JavaScript
4 Beiträge 2 Kommentatoren 1.1k Aufrufe 3 Watching
  • Ä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.
  • toniT Offline
    toniT Offline
    toni
    schrieb am zuletzt editiert von
    #1

    hallo ich habe dieses skript von iot-blog.net leider funktioniert es nicht. kann mir da vielleicht jemand helfen//

    Bildschirmfoto 2021-01-09 um 13.50.21.png

    Program Ventilation Check

    /*

    • @author Moritz Heusinger moritz.heusinger@gmail.com
    • The program checks the absolute humidity of an inside room and outside.
    • If the difference is above a specified threshold, a ventilation recommendation
    • is set as state. The absolute humidity values are set as state too.
    • The script also contains a datapoint, which triggers speech output of the
    • last used Amazon Alexa device.
    • Require: Instance of Alexa2 Adapter
    • Create your rooms in the rooms array with a name and the states which contain the desired values.
    • Humidity Threshold is used to only give a ventilate calculation if outside absolute humidity - the
    • threshold is less than inside absolute humidity. Min Humidity is used to make sure that you only get a
    • ventilation recommendation, if the relative inside humidity is above the min value.
    • You can additionally define a namespace, which will be appended to the states, e.g. '0_Userdata.0.Lueftungsempfehlung'
      */

    const logging = true;
    const namespace = ``;

    const rooms = [
    {
    roomName: sleepingRoom,
    outsideHumidityState: ***FILL IN YOUR STATE***,
    outsideTemperatureState: ***FILL IN YOUR STATE***,
    insideHumidityState: ***FILL IN YOUR STATE***,
    insideTemperatureState: ***FILL IN YOUR STATE***,
    humidityThreshold: 2, /* YOU ARE ALLOWED TO CHANGE IF YOU WANT /
    minHumidity: 45 /
    YOU ARE ALLOWED TO CHANGE IF YOU WANT */
    }
    ];

    const triggersInsideHumidity = [];
    const triggersAlexa = [];

    try {
    // create counter outside of rooms
    await createStateAsync(namespace ? ${namespace}.totalVentilationRecommendations : totalVentilationRecommendations, {
    type: number,
    read: true,
    write: false,
    name: Anzahl Lüftungsempfehlungen
    });
    } catch (e) {
    log(Could not create trigger dp for ventilation recommendations: ${e}, error);
    }

    for (const room of rooms) {
    try {
    await createStateAsync(${namespace ? ${namespace}. : ''}${room.roomName}.absoluteHumidity, {
    type: number,
    read: true,
    write: false,
    unit: g/m^3,
    name: ${room.roomName} Absolute Feuchtigkeit
    });

        await createStateAsync(`${namespace ? `${namespace}.` : ''}${room.roomName}.outsideAbsoluteHumidity`, {
            type: `number`,
            read: true,
            write: false,
            unit: `g/m^3`,
            name: `${room.roomName} Absolute Feuchtigkeit Außen`
        });
    
        await createStateAsync(`${namespace ? `${namespace}.` : ''}${room.roomName}.ventilationRecommendation`, {
            type: `boolean`,
            read: true,
            write: false,
            name: `${room.roomName} Lüftungsempfehlung`
        });
    
        const triggerId = await createStateAsync(`${namespace ? `${namespace}.` : ''}${room.roomName}.alexaTriggerLuftfeuchtigkeit`, {
            type: `boolean`,
            read: true,
            write: true,
            role: `button`,
            name: `${room.roomName} Alexa Trigger Luftfeuchtigkeit`,
            smartName: {
                de: `${room.roomName} Alexa Trigger Luftfeuchtigkeit`
            }
        });
    
        triggersAlexa.push(triggerId);
        triggersInsideHumidity.push(room.insideHumidityState);
    } catch (e) {
        log(`Could not create states for room ${room.roomName}: ${e}`, `error`);
    }
    

    } // endFor

    on({id: triggersAlexa, change: any}, obj => {
    if (logging) log(Alexa ventilation check triggered, info);
    const room = rooms[triggersAlexa.indexOf(obj.id)];
    const ventilate = getState(${namespace ? ${namespace}. : ''}${room.roomName}.ventilationRecommendation).val;
    const randomState = getRandomArbitrary(1, 2);
    let text;

    if (ventilate) {
        switch (randomState) {
            case 1:
                text = `Du solltest lüften, da es draußen trockener ist`;
                break;
            case 2:
                text = `Lüfte, es ist so feucht hier drin`;
                break;
        } // endSwitch
    } else {
        switch (randomState) {
            case 1:
                text = `Du solltest nicht lüften`;
                break;
            case 2:
                text = `Bitte nicht lüften`;
                break;
        } // endSwitch
    } // endElse
    
    // Get serial number of last used echo device, maybe timeout is unnecessary with new adapter version
    setTimeout(() => {
        const serialNumber = getState(`alexa2.0.History.serialNumber`).val;
        setState(`alexa2.0.Echo-Devices.${serialNumber}.Commands.speak`, text, false);
    }, 300);
    

    });

    on({id: triggersInsideHumidity, change: any}, obj => {
    const room = rooms[triggersInsideHumidity.indexOf(obj.id)];
    // Get inside and outside humidity and temperature
    const relHumidityOutdside = getState(room.outsideHumidityState).val;
    const temperatureOutside = getState(room.outsideTemperatureState).val;
    const relHumidityInside = getState(room.insideHumidityState).val;
    const temperatureInside = getState(room.insideTemperatureState).val;
    // Calc ventilation recommendation and absolute humidity inside and outside
    const jsonRes = ventilateRoom(relHumidityInside, temperatureInside, relHumidityOutdside,
    temperatureOutside, room.humidityThreshold, room.minHumidity);
    // Set states
    setState(${namespace ? ${namespace}. : ''}${room.roomName}.absoluteHumidity, jsonRes.insideAbsoluteHumidity, true);
    setState(${namespace ? ${namespace}. : ''}${room.roomName}.outsideAbsoluteHumidity, jsonRes.outsideAbsoluteHumidity, true);
    setState(${namespace ? ${namespace}. : ''}${room.roomName}.ventilationRecommendation, jsonRes.ventilate, true);

    // now update our counter by checking all rooms recommendation
    let counter = 0;
    for (const room of rooms) {
        const val = getState(`${namespace ? `${namespace}.` : ''}${room.roomName}.ventilationRecommendation`).val;
        counter = counter + +val;
    }
    setState(namespace ? `${namespace}.totalVentilationRecommendations` : `totalVentilationRecommendations`, counter, true);
    

    });

    /* Internals */

    function calcAbsoluteHumidity(relHumidity, temperature) {
    const res = ((6.112 * Math.pow(Math.E, ((17.67 * temperature) / (temperature + 243.5))) * relHumidity * 2.1674)) / (273.15 + temperature);
    return Math.round(res * 100) / 100;
    } // endCalcAbsoluteHumidity

    function ventilateRoom(relHumidityInside, tempInside, relHumidityOutside, tempOutside,
    threshold = 2.0, minHumidity = 50.0) {
    const res = {};
    res.insideAbsoluteHumidity = calcAbsoluteHumidity(relHumidityInside, tempInside);
    res.outsideAbsoluteHumidity = calcAbsoluteHumidity(relHumidityOutside, tempOutside);
    res.diff = Math.round((res.insideAbsoluteHumidity - res.outsideAbsoluteHumidity) * 100) / 100;

    res.ventilate = res.diff > threshold && relHumidityInside > minHumidity;
    return res;
    

    } // endVentilateRoom

    function getRandomArbitrary(min, max) {
    return Math.round(Math.random() * ((max + 0.4) - (min - 0.4)) + (min - 0.4));
    } // endGetRandomArbitrary

    AsgothianA 1 Antwort Letzte Antwort
    0
    • toniT toni

      hallo ich habe dieses skript von iot-blog.net leider funktioniert es nicht. kann mir da vielleicht jemand helfen//

      Bildschirmfoto 2021-01-09 um 13.50.21.png

      Program Ventilation Check

      /*

      • @author Moritz Heusinger moritz.heusinger@gmail.com
      • The program checks the absolute humidity of an inside room and outside.
      • If the difference is above a specified threshold, a ventilation recommendation
      • is set as state. The absolute humidity values are set as state too.
      • The script also contains a datapoint, which triggers speech output of the
      • last used Amazon Alexa device.
      • Require: Instance of Alexa2 Adapter
      • Create your rooms in the rooms array with a name and the states which contain the desired values.
      • Humidity Threshold is used to only give a ventilate calculation if outside absolute humidity - the
      • threshold is less than inside absolute humidity. Min Humidity is used to make sure that you only get a
      • ventilation recommendation, if the relative inside humidity is above the min value.
      • You can additionally define a namespace, which will be appended to the states, e.g. '0_Userdata.0.Lueftungsempfehlung'
        */

      const logging = true;
      const namespace = ``;

      const rooms = [
      {
      roomName: sleepingRoom,
      outsideHumidityState: ***FILL IN YOUR STATE***,
      outsideTemperatureState: ***FILL IN YOUR STATE***,
      insideHumidityState: ***FILL IN YOUR STATE***,
      insideTemperatureState: ***FILL IN YOUR STATE***,
      humidityThreshold: 2, /* YOU ARE ALLOWED TO CHANGE IF YOU WANT /
      minHumidity: 45 /
      YOU ARE ALLOWED TO CHANGE IF YOU WANT */
      }
      ];

      const triggersInsideHumidity = [];
      const triggersAlexa = [];

      try {
      // create counter outside of rooms
      await createStateAsync(namespace ? ${namespace}.totalVentilationRecommendations : totalVentilationRecommendations, {
      type: number,
      read: true,
      write: false,
      name: Anzahl Lüftungsempfehlungen
      });
      } catch (e) {
      log(Could not create trigger dp for ventilation recommendations: ${e}, error);
      }

      for (const room of rooms) {
      try {
      await createStateAsync(${namespace ? ${namespace}. : ''}${room.roomName}.absoluteHumidity, {
      type: number,
      read: true,
      write: false,
      unit: g/m^3,
      name: ${room.roomName} Absolute Feuchtigkeit
      });

          await createStateAsync(`${namespace ? `${namespace}.` : ''}${room.roomName}.outsideAbsoluteHumidity`, {
              type: `number`,
              read: true,
              write: false,
              unit: `g/m^3`,
              name: `${room.roomName} Absolute Feuchtigkeit Außen`
          });
      
          await createStateAsync(`${namespace ? `${namespace}.` : ''}${room.roomName}.ventilationRecommendation`, {
              type: `boolean`,
              read: true,
              write: false,
              name: `${room.roomName} Lüftungsempfehlung`
          });
      
          const triggerId = await createStateAsync(`${namespace ? `${namespace}.` : ''}${room.roomName}.alexaTriggerLuftfeuchtigkeit`, {
              type: `boolean`,
              read: true,
              write: true,
              role: `button`,
              name: `${room.roomName} Alexa Trigger Luftfeuchtigkeit`,
              smartName: {
                  de: `${room.roomName} Alexa Trigger Luftfeuchtigkeit`
              }
          });
      
          triggersAlexa.push(triggerId);
          triggersInsideHumidity.push(room.insideHumidityState);
      } catch (e) {
          log(`Could not create states for room ${room.roomName}: ${e}`, `error`);
      }
      

      } // endFor

      on({id: triggersAlexa, change: any}, obj => {
      if (logging) log(Alexa ventilation check triggered, info);
      const room = rooms[triggersAlexa.indexOf(obj.id)];
      const ventilate = getState(${namespace ? ${namespace}. : ''}${room.roomName}.ventilationRecommendation).val;
      const randomState = getRandomArbitrary(1, 2);
      let text;

      if (ventilate) {
          switch (randomState) {
              case 1:
                  text = `Du solltest lüften, da es draußen trockener ist`;
                  break;
              case 2:
                  text = `Lüfte, es ist so feucht hier drin`;
                  break;
          } // endSwitch
      } else {
          switch (randomState) {
              case 1:
                  text = `Du solltest nicht lüften`;
                  break;
              case 2:
                  text = `Bitte nicht lüften`;
                  break;
          } // endSwitch
      } // endElse
      
      // Get serial number of last used echo device, maybe timeout is unnecessary with new adapter version
      setTimeout(() => {
          const serialNumber = getState(`alexa2.0.History.serialNumber`).val;
          setState(`alexa2.0.Echo-Devices.${serialNumber}.Commands.speak`, text, false);
      }, 300);
      

      });

      on({id: triggersInsideHumidity, change: any}, obj => {
      const room = rooms[triggersInsideHumidity.indexOf(obj.id)];
      // Get inside and outside humidity and temperature
      const relHumidityOutdside = getState(room.outsideHumidityState).val;
      const temperatureOutside = getState(room.outsideTemperatureState).val;
      const relHumidityInside = getState(room.insideHumidityState).val;
      const temperatureInside = getState(room.insideTemperatureState).val;
      // Calc ventilation recommendation and absolute humidity inside and outside
      const jsonRes = ventilateRoom(relHumidityInside, temperatureInside, relHumidityOutdside,
      temperatureOutside, room.humidityThreshold, room.minHumidity);
      // Set states
      setState(${namespace ? ${namespace}. : ''}${room.roomName}.absoluteHumidity, jsonRes.insideAbsoluteHumidity, true);
      setState(${namespace ? ${namespace}. : ''}${room.roomName}.outsideAbsoluteHumidity, jsonRes.outsideAbsoluteHumidity, true);
      setState(${namespace ? ${namespace}. : ''}${room.roomName}.ventilationRecommendation, jsonRes.ventilate, true);

      // now update our counter by checking all rooms recommendation
      let counter = 0;
      for (const room of rooms) {
          const val = getState(`${namespace ? `${namespace}.` : ''}${room.roomName}.ventilationRecommendation`).val;
          counter = counter + +val;
      }
      setState(namespace ? `${namespace}.totalVentilationRecommendations` : `totalVentilationRecommendations`, counter, true);
      

      });

      /* Internals */

      function calcAbsoluteHumidity(relHumidity, temperature) {
      const res = ((6.112 * Math.pow(Math.E, ((17.67 * temperature) / (temperature + 243.5))) * relHumidity * 2.1674)) / (273.15 + temperature);
      return Math.round(res * 100) / 100;
      } // endCalcAbsoluteHumidity

      function ventilateRoom(relHumidityInside, tempInside, relHumidityOutside, tempOutside,
      threshold = 2.0, minHumidity = 50.0) {
      const res = {};
      res.insideAbsoluteHumidity = calcAbsoluteHumidity(relHumidityInside, tempInside);
      res.outsideAbsoluteHumidity = calcAbsoluteHumidity(relHumidityOutside, tempOutside);
      res.diff = Math.round((res.insideAbsoluteHumidity - res.outsideAbsoluteHumidity) * 100) / 100;

      res.ventilate = res.diff > threshold && relHumidityInside > minHumidity;
      return res;
      

      } // endVentilateRoom

      function getRandomArbitrary(min, max) {
      return Math.round(Math.random() * ((max + 0.4) - (min - 0.4)) + (min - 0.4));
      } // endGetRandomArbitrary

      AsgothianA Offline
      AsgothianA Offline
      Asgothian
      Developer
      schrieb am zuletzt editiert von
      #2

      @toni

      Bevor Dir da jemand helfen kann musst du das Skript erst einmal korrekt in Code tags packen. So wie es jetzt ist ist es unlesbar.

      Auch bitte die Warnmeldungen die du als Screenshot gepostet hast vollständig als Text posten, sprich mittels des Buttons "log herunterladen" die Text-Datei herunter laden und die relevanten Zeilen ausschneiden und als Text (auch wieder in code tags) posten.

      A.

      ioBroker auf RPi4 - Hardware soweit wie möglich via Zigbee.
      "Shit don't work" ist keine Fehlermeldung, sondern ein Fluch.

      toniT 1 Antwort Letzte Antwort
      0
      • AsgothianA Asgothian

        @toni

        Bevor Dir da jemand helfen kann musst du das Skript erst einmal korrekt in Code tags packen. So wie es jetzt ist ist es unlesbar.

        Auch bitte die Warnmeldungen die du als Screenshot gepostet hast vollständig als Text posten, sprich mittels des Buttons "log herunterladen" die Text-Datei herunter laden und die relevanten Zeilen ausschneiden und als Text (auch wieder in code tags) posten.

        A.

        toniT Offline
        toniT Offline
        toni
        schrieb am zuletzt editiert von
        #3

        @asgothian Hallo ich danke dir im Voraus das du mir bei der Sache helfen willst.
        Anbei das heruntergeladene Log-file und ein link zum Skript. Lg.

        2021-01-12 08:32:04.166 - info: javascript.0 (103218) Stop script script.js.common.Absolute_Luftfeuchte
        2021-01-12 08:32:04.180 - info: javascript.0 (103218) Start javascript script.js.common.Absolute_Luftfeuchte
        2021-01-12 08:32:04.184 - error: javascript.0 (103218) script.js.common.Absolute_Luftfeuchte compile failed:
        at script.js.common.Absolute_Luftfeuchte:40
        2021-01-12 08:32:04.184 - error: javascript.0 (103218) await createStateAsync(namespace ? ${namespace}.totalVentilationRecommendations : totalVentilationRecommendations, {
        2021-01-12 08:32:04.184 - error: javascript.0 (103218) ^^^^^
        2021-01-12 08:32:04.185 - error: javascript.0 (103218) SyntaxError: await is only valid in async function
        2021-01-12 08:32:04.185 - error: javascript.0 (103218) at new Script (vm.js:83:7)
        2021-01-12 08:32:04.185 - error: javascript.0 (103218) at Object.createScript (vm.js:277:10)
        2021-01-12 08:32:04.185 - error: javascript.0 (103218) at createVM (/opt/iobroker/node_modules/iobroker.javascript/main.js:1280:28)
        2021-01-12 08:32:04.186 - error: javascript.0 (103218) at prepareScript (/opt/iobroker/node_modules/iobroker.javascript/main.js:1503:37)
        2021-01-12 08:32:04.186 - error: javascript.0 (103218) at createProblemObject (/opt/iobroker/node_modules/iobroker.javascript/main.js:1559:17)
        2021-01-12 08:32:04.186 - error: javascript.0 (103218) at adapter.getForeignState (/opt/iobroker/node_modules/iobroker.javascript/main.js:1140:17)
        2021-01-12 08:32:04.186 - error: javascript.0 (103218) at client.get (/opt/iobroker/node_modules/iobroker.js-controller/lib/states/statesInRedis.js:616:17)
        2021-01-12 08:32:04.186 - error: javascript.0 (103218) at tryCatcher (/opt/iobroker/node_modules/standard-as-callback/built/utils.js:11:23)
        2021-01-12 08:32:04.186 - error: javascript.0 (103218) at promise.then (/opt/iobroker/node_modules/standard-as-callback/built/index.js:19:49)
        2021-01-12 08:32:04.187 - error: javascript.0 (103218) at process._tickCallback (internal/process/next_tick.js:68:7)

        https://github.com/foxriver76/iot-blog-scripts/blob/master/ventilationCheckMultiRoom.js

        AsgothianA 1 Antwort Letzte Antwort
        0
        • toniT toni

          @asgothian Hallo ich danke dir im Voraus das du mir bei der Sache helfen willst.
          Anbei das heruntergeladene Log-file und ein link zum Skript. Lg.

          2021-01-12 08:32:04.166 - info: javascript.0 (103218) Stop script script.js.common.Absolute_Luftfeuchte
          2021-01-12 08:32:04.180 - info: javascript.0 (103218) Start javascript script.js.common.Absolute_Luftfeuchte
          2021-01-12 08:32:04.184 - error: javascript.0 (103218) script.js.common.Absolute_Luftfeuchte compile failed:
          at script.js.common.Absolute_Luftfeuchte:40
          2021-01-12 08:32:04.184 - error: javascript.0 (103218) await createStateAsync(namespace ? ${namespace}.totalVentilationRecommendations : totalVentilationRecommendations, {
          2021-01-12 08:32:04.184 - error: javascript.0 (103218) ^^^^^
          2021-01-12 08:32:04.185 - error: javascript.0 (103218) SyntaxError: await is only valid in async function
          2021-01-12 08:32:04.185 - error: javascript.0 (103218) at new Script (vm.js:83:7)
          2021-01-12 08:32:04.185 - error: javascript.0 (103218) at Object.createScript (vm.js:277:10)
          2021-01-12 08:32:04.185 - error: javascript.0 (103218) at createVM (/opt/iobroker/node_modules/iobroker.javascript/main.js:1280:28)
          2021-01-12 08:32:04.186 - error: javascript.0 (103218) at prepareScript (/opt/iobroker/node_modules/iobroker.javascript/main.js:1503:37)
          2021-01-12 08:32:04.186 - error: javascript.0 (103218) at createProblemObject (/opt/iobroker/node_modules/iobroker.javascript/main.js:1559:17)
          2021-01-12 08:32:04.186 - error: javascript.0 (103218) at adapter.getForeignState (/opt/iobroker/node_modules/iobroker.javascript/main.js:1140:17)
          2021-01-12 08:32:04.186 - error: javascript.0 (103218) at client.get (/opt/iobroker/node_modules/iobroker.js-controller/lib/states/statesInRedis.js:616:17)
          2021-01-12 08:32:04.186 - error: javascript.0 (103218) at tryCatcher (/opt/iobroker/node_modules/standard-as-callback/built/utils.js:11:23)
          2021-01-12 08:32:04.186 - error: javascript.0 (103218) at promise.then (/opt/iobroker/node_modules/standard-as-callback/built/index.js:19:49)
          2021-01-12 08:32:04.187 - error: javascript.0 (103218) at process._tickCallback (internal/process/next_tick.js:68:7)

          https://github.com/foxriver76/iot-blog-scripts/blob/master/ventilationCheckMultiRoom.js

          AsgothianA Offline
          AsgothianA Offline
          Asgothian
          Developer
          schrieb am zuletzt editiert von Asgothian
          #4

          @toni
          Code tags sind Dein Freund. Auch logs gehören in Code tags.

          Im Editor werden code tags durch dieses Symbol </> dargestellt.

          Zum Fehler selber: Da das Script auf Github liegt gibt es da jemanden der sich (hoffentlich) drum kümmert. Daher bitte da einen issue aufmachen.

          A.

          ioBroker auf RPi4 - Hardware soweit wie möglich via Zigbee.
          "Shit don't work" ist keine Fehlermeldung, sondern ein Fluch.

          1 Antwort Letzte Antwort
          0
          Antworten
          • In einem neuen Thema antworten
          Anmelden zum Antworten
          • Älteste zuerst
          • Neuste zuerst
          • Meiste Stimmen


          Support us

          ioBroker
          Community Adapters
          Donate

          871

          Online

          32.6k

          Benutzer

          82.0k

          Themen

          1.3m

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

          • Du hast noch kein Konto? Registrieren

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