Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Entwicklung
    4. Neuer Adapter: WS980wifi ELV direkt einlesen

    NEWS

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    Neuer Adapter: WS980wifi ELV direkt einlesen

    This topic has been deleted. Only users with topic management privileges can see it.
    • Martin Orasch
      Martin Orasch last edited by Martin Orasch

      Ist schon zufällig Jemand an diesem Adapter dran?
      https://raw.githubusercontent.com/RrPt/WS980/master/Dokumentation/WS980_protokoll.docx

      Die Wetterstation ist ja mittlerweile sehr beliebt und es gibt ja schon etliche Anbindungen zb an Homematic und dann in Iobroker oder via FHEM. Cool wärs natürlich direkt.

      https://www.elv.de/output/controller.aspx?cid=74&detail=10&detail2=62595

      Dank an Jeden ders programmiert 😊😜

      RaspiUser 1 Reply Last reply Reply Quote 0
      • M
        manu96 last edited by

        @Martin-Orasch
        Konntest du die Wetterstation mittlerweile in iobroker ohne Cloud einbinden?

        Wollte mir diese Wetterstation auch kaufen und bin auf deinen Artikel gestoßen.

        LG,
        Manuel

        1 Reply Last reply Reply Quote 0
        • W
          Wallauer last edited by

          Hi zusammen,

          habe auch die besagte Wetterstation und habe sie über ein kleines Python-Script an ioBroker über die simpleAPI angebunden.
          Ist nicht die schönste Lösung, funktioniert aber einwandfrei ohne irgendwelche Wetterdienste dazwischen. Hätte lieber einen
          ioBroker-Adapter geschrieben, aber dazu fehlt mir momentan die Zeit.

          Danke für die Links oben, damit war die Anbindung ein Kinderspiel !

          Voraussetzungen:

          • die Wetterstation muss sich bereits in Eurem Netzwerk befinden (wifi-Mode-B, Anleitung auf ELV-Seite)
          • simple-API ist in der web-Instanz aktiviert
          • folgende Python-libs sind installiert: socket, requests, json, time, syslog

          Installation:

          • wetterstation.js in ioBroker unter "Skripte" hinzufügen und starten

          /*
              Abfrage der Wetterstation mittels wetterstation.py. Daten landen hier --> 
              http://[ioBroker-IP]:8082/setValueFromBody/javascript.0.API.Wetterstation_Eingang
          */
          
          // Anlegen der Datenpunkte unter javascript.0.Wetterstation
          function createOnce(){
              createState("javascript.0.API.Wetterstation_Eingang", "n/a", {read: true, write: true, name: "API Eingang fuer die pythonscript-Daten", type: "string", def: "n/a"});
              var name = "javascript.0.Wetterstation";
              createState(name);
              createState(name + ".tempHitzeIndex", 0, {read: true, write: true, name: "Temp. Hitzeindex", type: "number", def: "0"});
              createState(name + ".windBoe", 0, {read: true, write: true, name: "Windboe", type: "number", def: "0"});
              createState(name + ".regenJahr", 0, {read: true, write: true, name: "Niederschlag pro Jahr", type: "number", def: "0"});
              createState(name + ".regen", 0, {read: true, write: true, name: "Niederschlag pro Stunde", type: "number", def: "0"});
              createState(name + ".uvWert", 0, {read: true, write: true, name: "UV-Wert", type: "number", def: "0"});
              createState(name + ".regenGesamt", 0, {read: true, write: true, name: "Regen gesamt", type: "number", def: "0"});
              createState(name + ".licht", 0, {read: true, write: true, name: "Lichtstärke", type: "number", def: "0"});
              createState(name + ".regenWoche", 0, {read: true, write: true, name: "Niederschlag pro Woche", type: "number", def: "0"});
              createState(name + ".regenMonat", 0, {read: true, write: true, name: "Niederschlag pro Monat", type: "number", def: "0"});
              createState(name + ".regenTag", 0, {read: true, write: true, name: "Niederschlag diesen Tag", type: "number", def: "0"});
              createState(name + ".tempTaupunkt", 0, {read: true, write: true, name: "Taupunkt", type: "number", def: "0"});
              createState(name + ".windGeschwindigkeit", 0, {read: true, write: true, name: "Wind Geschwindgkeit", type: "number", def: "0"});
              createState(name + ".windRichtung", 0, {read: true, write: true, name: "Windrichtung", type: "number", def: "0"});
              createState(name + ".tempAussen", 0, {read: true, write: true, name: "Temp. Aussen", type: "number", def: "0"});
              createState(name + ".tempGefuehlt", 0, {read: true, write: true, name: "Temp. gefuehlt", type: "number", def: "0"});
              createState(name + ".tempInnen", 0, {read: true, write: true, name: "Temp. Innen", type: "number", def: "0"});
              createState(name + ".humAussen", 0, {read: true, write: true, name: "Luftfeuchte Aussen", type: "number", def: "0"});
              createState(name + ".pressAbs", 0, {read: true, write: true, name: "Luftdruck abs.", type: "number", def: "0"});
              createState(name + ".uvIndex", 0, {read: true, write: true, name: "UV-Index", type: "number", def: "0"});
              createState(name + ".pressRel", 0, {read: true, write: true, name: "Luftdruck rel.", type: "number", def: "0"});
              createState(name + ".humInnen", 0, {read: true, write: true, name: "Luftfeuchte Innen", type: "number", def: "0"});        
          }
          
          // Bei jedem Eingang der Daten, die Datenpunkte aktualisieren
          on({id: "javascript.0.API.Wetterstation_Eingang", change: "any"}, function (obj) {
              var data = JSON.parse(obj.newState.val);
              for (var key in data){
                  setState("javascript.0.Wetterstation." + key, data[key]);  
              }
          });
          
          createOnce(); // muss nur beim ersten Start ausgeführt werden um Datenpunkte anzulegen, kann danach auskommentiert werden. 
          

          • wetterstation.py anlegen und ausführen (Hintergrunddienst bietet sich an)
          • ausführbar machen chmod +x wetterstation.py

          #!/usr/bin/env python
          
          """
              Programm holt die Daten einer WS980wifi-Wetterstation ab und sendet sie an simpleAPI von ioBroker
              Erstellt: 10.01.2020
          """
          
          import socket, requests, json, time, syslog
          
          ###################################################### Hier an Netzwerk anpassen #####################################################
          HOST = "10.0.30.26" # IP-Adresse der Wetterstation
          PORT = 45000        # Port der Wetterstatioin
          UPD_INTERVAL = 30   # Update-Intervall in Sekunden
          IOBROKER_API_URL = "http://10.0.10.10:8082/setValueFromBody/javascript.0.API.Wetterstation_Eingang" # API-URL von simpleAPI (ioBroker)
          ######################################################################################################################################
          
          # Diese Werte werden bei Aktuell-Anfrage in Bytestring zurueckgeliefert 
          WERTE = [
              {'name': 'tempInnen', 'start': 7, 'laenge': 2, 'div': 10},
              {'name': 'tempAussen', 'start': 10, 'laenge': 2, 'div': 10},
              {'name': 'tempTaupunkt', 'start': 13, 'laenge': 2, 'div': 10},
              {'name': 'tempGefuehlt', 'start': 16, 'laenge': 2, 'div': 10},
              {'name': 'tempHitzeIndex', 'start': 19, 'laenge': 2, 'div': 10},
              {'name': 'humInnen', 'start': 22, 'laenge': 1, 'div': 1},
              {'name': 'humAussen', 'start': 24, 'laenge': 1, 'div': 1},
              {'name': 'pressAbs', 'start': 26, 'laenge': 2, 'div': 10},
              {'name': 'pressRel', 'start': 29, 'laenge': 2, 'div': 10},
              {'name': 'windRichtung', 'start': 32, 'laenge': 2, 'div': 1},
              {'name': 'windGeschwindigkeit', 'start': 35, 'laenge': 2, 'div': 10},
              {'name': 'windBoe', 'start': 38, 'laenge': 2, 'div': 10},
              {'name': 'regen', 'start': 41, 'laenge': 4, 'div': 10},
              {'name': 'regenTag', 'start': 46, 'laenge': 4, 'div': 10},
              {'name': 'regenWoche', 'start': 51, 'laenge': 4, 'div': 10},
              {'name': 'regenMonat', 'start': 56, 'laenge': 4, 'div': 10},
              {'name': 'regenJahr', 'start': 61, 'laenge': 4, 'div': 10},
              {'name': 'regenGesamt', 'start': 66, 'laenge': 4, 'div': 10},
              {'name': 'licht', 'start': 71, 'laenge': 4, 'div': 10},
              {'name': 'uvWert', 'start': 76, 'laenge': 2, 'div': 10},
              {'name': 'uvIndex', 'start': 79, 'laenge': 1, 'div': 1},
          ]
          
          def sendeAnIoBroker(IOBROKER_API_URL, postdata):
              """
                  Sendet die Daten als json an simpleAPI von ioBroker, so dass ueber Datenpunkte darauf zugegriffen werden kann
                  postdata = dict
              """
              postdata = json.dumps(postdata)
              requests.post(IOBROKER_API_URL, postdata)
          
          def getValueFromResponse(response, name, start, laenge, div):
              """
                  Liefert den angefragten Wert aus Response-Array als float-Wert zurueck
              """
              wert = "".join(response[start:start+laenge])
              wert_float = float(int(wert,16)) / div
              # print "%s => %s => %s" %(name, wert, wert_float)
              return wert_float
          
          def getDataFromWS():
              """
                  Sendet eine Anfrage fuer aktuelle Daten an Server. Historische Daten werden nicht benoetigt, da ioBroker sich um Historie kuemmert.
                  Liefert array mit Response-Bytes zurueck
              """
              # Bytes die an Wetterstation gesendet werden, um die aktuellen Werte als Rueckgabe zu erhalten
              ANFRAGE = "\xff\xff\x0b\x00\x06\x04\x04\x19"
          
              s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
              s.connect((HOST,PORT))
              s.send(ANFRAGE)
              data = s.recv(1024)
              s.close()
              response = []
              for element in data:
                  response.append(element.encode('hex'))
              return response
          
          def generateDataForIobroker(resp, werte):
              """
                  Generiert ein dict mit Key/Values, die an ioBroker gesendet werden sollen
                  Liefert ein dict zurueck
              """
              ioBrokerDaten = {}
              for wert in werte:
                  ioBrokerDaten[wert['name']] = getValueFromResponse(resp,wert['name'], wert['start'], wert['laenge'], wert['div'])
              return ioBrokerDaten
          
          # Main
          while True:
              try:
                  resp = getDataFromWS()
                  daten = generateDataForIobroker(resp, WERTE)
                  sendeAnIoBroker(IOBROKER_API_URL, daten)
              except:
                  syslog.openlog(logoption=syslog.LOG_PID, facility=syslog.LOG_USER)
                  syslog.syslog('ioBroker - Fehler beim Abfragen der Wetterstation !!!')
          
              time.sleep(UPD_INTERVAL)
          

          Script wetterstation.py als Hintergrunddienst via systemd in Linux starten:

          Datei /etc/systemd/system/wetterstation.service anlegen und Pfad zur wetterstation.py unter ExecStart anpassen

          [Unit]
          Description=Wetterstation-Update-Service
          After=network.target
          
          [Service]
          Type=simple
          ExecStart=/usr/local/sbin/wetterstation.py
          
          [Install]
          WantedBy=multi-user.target
          

          Danach den Dienst noch aktivieren (so dass er nach reboot wieder automatisch startet) und erstmalig starten

          systemctl enable wetterstation.service
          systemctl start wetterstation.service
          

          Sonstiges zur WS980:
          Die Wetterstation pingt minütlich im Wechsel amazon.com / baidu.com, wahrscheinlich um die Netzwerkanbindung zu erkennen.
          Weitere Verbindungen nach außen konnte ich nicht erkennen.

          1 Reply Last reply Reply Quote 1
          • RaspiUser
            RaspiUser @Martin Orasch last edited by

            @Martin-Orasch said in Neuer Adapter: WS980wifi ELV direkt einlesen:

            https://www.elv.de/output/controller.aspx?cid=74&detail=10&detail2=62595

            ... ELV hat seine Website neu gestaltet. Der Link geht nur auf die Hauptseite. Ich komme da nicht weiter, kannst Du ihn bitte aktualisieren ?

            @Wallauer said in Neuer Adapter: WS980wifi ELV direkt einlesen:

            Hätte lieber einen
            ioBroker-Adapter geschrieben, aber dazu fehlt mir momentan die Zeit.

            Also wenn Du demnächst Zeit finden könntest ... ich hätte nix dagegen 😊 🙄

            Johannes Bauerstatter 1 Reply Last reply Reply Quote 1
            • Johannes Bauerstatter
              Johannes Bauerstatter @RaspiUser last edited by

              Hallo, gibt es hier bereits irgendwelche News? Danke schonmal für die vorhandene Lösung.

              1 Reply Last reply Reply Quote 0
              • First post
                Last post

              Support us

              ioBroker
              Community Adapters
              Donate

              659
              Online

              31.7k
              Users

              79.7k
              Topics

              1.3m
              Posts

              5
              5
              2419
              Loading More Posts
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes
              Reply
              • Reply as topic
              Log in to reply
              Community
              Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
              The ioBroker Community 2014-2023
              logo