Update: 2020-11-12

Esp8266 Windsensor TX23 als Arduino Tab.

TX23.ino

// ****************************************************************
// Sketch Esp8266 TX23 Windgeschwindigkeit- und Richtung Modular(Tab)
// Include FIFO Puffer for Hour, Day, Week
// created: Jens Fleischer, 2019-12-09
// last mod: Jens Fleischer, 2020-11-12
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266, TX23
// Braun (Schwarz) DATA an D5 = GPIO14
// Red an Vcc
// Grün --
// Gelb an GND
// Software: Esp8266 Arduino Core 2.4.2 / 2.5.2 / 2.6.3 / 2.7.4
// Getestet auf: Nodemcu
/******************************************************************
  Copyright (c) 2019 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/
// Diese Version vom Windsensor sollte als Tab eingebunden werden.
// #include <WebServer.h> muss im Haupttab aufgerufen werden
// Die Funktionalität des ESP8266 Webservers ist erforderlich.
// Die Funktion "tx23();" muss im Setup aufgerufen werden.
// Die Funktion "tx23Read();" muss zum füllen der Fifo Puffer im loop(); aufgerufen werden.
/**************************************************************************************/

#include <LaCrosse_TX23.h>                                                  // https://github.com/egzumer/Arduino-LaCrosse-TX23-Library

LaCrosse_TX23 anemometer = LaCrosse_TX23(D5);                               // Pin anpassen

float fifoHour[60], fifoMaxHour[60], fifoDay[24], fifoMaxDay[24], fifoWeek[7], fifoMaxWeek[7];   // Fifo Puffer

template<typename T, size_t count>
T maxRead(const T (&arr)[count]) {                                          // max Wert aus Array ermitteln
  T maxValue {arr[0]};
  for (const auto &value : arr) maxValue = max(maxValue, value);
  return maxValue;
}

template<typename T, size_t count>
T averageRead(const T (&arr)[count]) {                                      // Durchschnitt aus Array berechnen
  double average {0};
  for (const auto &value : arr) average += static_cast<double>(value) / count;
  return std::numeric_limits<T>::is_integer ? round(average) : average;
}

template<typename T, size_t count>                                          // Array Größe zur Kompilezeit ermitteln
constexpr size_t arrayCount(const T (&)[count]) {
  return count;
}

constexpr byte hourSize = arrayCount(fifoHour);
constexpr byte daySize = arrayCount(fifoDay);
constexpr byte weekSize = arrayCount(fifoWeek);

void tx23() {                                                               // Funktionsaufruf "tx23();" muss im Setup eingebunden werden
  server.on("/tx23", []() {
    server.send(200, "application/json", tx23Read());
  });
}

const char* tx23Read() {                                                    // Funktionsaufruf "tx23Read();" muss im Loop eingebunden werden
  static char buf[63];
  static bool correct;
  static float maxSpeed, speedValue, speed;
  static uint8_t numberOfValue, indexHour, indexDay, indexWeek;             // Index Fifo Puffer
  static int32_t direction;
  static uint32_t previousMillis[2];
  uint32_t currentMillis {millis()};
  if (currentMillis - previousMillis[0] >= 3e3) {                           // aller 3 Sekunden
    previousMillis[0] = currentMillis;
    if ((correct = anemometer.read(speed, direction)) && speed < 52) {      // Sensor auslesen
      maxSpeed = max(maxSpeed, speed);                                      // max Wert ermitteln
      speedValue += speed;
      numberOfValue++;
    }
  }
  if (currentMillis - previousMillis[1] >= 6e4) {                           // jede Minute
    previousMillis[1] = currentMillis;
    fifoHour[indexHour] = speedValue / numberOfValue;                       // 60 Minuten Puffer Durchschnitt übergeben
    fifoMaxHour[indexHour] = maxSpeed;                                      // 60 Minuten Puffer max Wert übergeben
    ++indexHour, indexHour %= (hourSize);                                   // 60 Minuten Puffer Zeiger im Puffer vorrücken
    maxSpeed = 0;                                                           // maxSpeed zurücksetzen
    speedValue = 0;                                                         // Durchschnitt zurücksetzen
    numberOfValue = 0;                                                      // Zähler zurücksetzen
    if (indexHour == 0) {
      ++indexDay, indexDay %= (daySize);                                    // 24 Stunden Puffer Zeiger im Puffer vorrücken
    }
    fifoDay[indexDay] = averageRead(fifoHour);                              // 24 Stunden Puffer Durchschnitt übergeben
    fifoMaxDay[indexDay] = maxRead(fifoMaxHour);                            // 24 Stunden Puffer max Wert übergeben
    if (indexHour == 0 && indexDay == 0) {
      static byte fill {0};                                                 // In der ersten Woche das Array auffüllen
      if (fill < weekSize) for (byte i = fill++; i < weekSize; i++)fifoWeek[i] = averageRead(fifoDay);
      ++indexWeek, indexWeek %= weekSize;                                   // 7 Tage Puffer Zeiger im Puffer vorrücken
    }
    fifoWeek[indexWeek] = averageRead(fifoDay);                             // 7 Tage Puffer Durchschnitt übergeben
    fifoMaxWeek[indexWeek] = maxRead(fifoMaxDay);                           // 7 Tage Puffer max Wert übergeben
  }
  snprintf(buf, sizeof(buf), R"(["%d","%.1f","%.1f","%.1f","%.1f","%.1f","%.1f","%.1f"])",
           direction, speed, averageRead(fifoHour), maxRead(fifoMaxHour), averageRead(fifoDay), maxRead(fifoMaxDay), averageRead(fifoWeek), maxRead(fifoMaxWeek));
  return correct ? buf : "[\"nan\"]";
}

Die Webseite zum Esp8266 TX23 Windsensor.

tx23.html

<!DOCTYPE HTML> <!-- For more information visit: https://fipsok.de -->
<html lang="de">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="style.css">
  <title>Anemometer</title>
  <script>
    direction = ['m96.37 19 3.625-6.052 3.625 6.052-3.625 19.33z',
      'm127.6 23.78 5.665-4.204 1.033 6.978-10.75 16.47z',
      'm154.7 40.16 6.842-1.716-1.716 6.842-16.23 11.11z',
      'm173.4 65.65 6.978 1.033-4.204 5.665-19.25 4.049z',
      'm181 96.36 6.052 3.625-6.052 3.625-19.33-3.625z',
      'm176.2 127.6 4.204 5.665-6.978 1.033-16.47-10.75z',
      'm159.8 154.7 1.716 6.842-6.842-1.716-11.11-16.23z',
      'm134.3 173.4-1.033 6.978-5.665-4.204-4.049-19.25z',
      'm103.6 181-3.625 6.052-3.625-6.052 3.625-19.33z',
      'm72.34 176.2-5.665 4.204-1.033-6.978 10.75-16.47z',
      'm45.29 159.8-6.842 1.716 1.716-6.842 16.23-11.11z',
      'm26.56 134.3-6.978-1.033 4.204-5.665 19.25-4.049z',
      'm19.01 103.6-6.052-3.625 6.052-3.625 19.33 3.625z',
      'm23.79 72.33-4.204-5.665 6.978-1.033 16.47 10.75z',
      'm40.17 45.28-1.716-6.842 6.842 1.716 11.11 16.23z',
      'm65.66 26.55 1.033-6.978 5.665 4.204 4.049 19.25z'];
    function renew() {
      fetch('tx23').then(function (response) {
        return response.json();
      }).then(function (array) {
        var elem = document.querySelectorAll('b');
        if (array[0] != 'nan') {
          document.getElementById('arrow').setAttribute("d", direction[array[0]]);
		  elem[0].innerHTML = array[1];
		  elem[1].innerHTML = array[2];
		  elem[2].innerHTML = array[3];
		  elem[3].innerHTML = array[1];
		  elem[4].innerHTML = array[6];
		  elem[5].innerHTML = array[7];
		  elem[6].innerHTML = array[1];
		  elem[7].innerHTML = array[4];
		  elem[8].innerHTML = array[5];
        }
        else {
          elem[1].innerHTML = '----';
		  elem[3].innerHTML = '----';
		  elem[6].innerHTML = '----';
        }
      });
    }
    document.addEventListener('DOMContentLoaded', renew);
    setInterval(renew, 2000);
  </script>
  <style>
    svg {
      height: 22em;
	  z-index: 9;
	  pointer-events: none;
    }
    main {
      display: flex;
      flex-direction: column;
      align-items: center;
      position: absolute;
      top: 4em;
      font-size: 1.5em;
      font-weight: bold;
    }
    span {
	  display: block;
    }
	b {
	  font-size: 1.5em;
	}
	label {
	  position: absolute;
	  width: 9em;
	  padding: 4em 2.5em;
	  background-color: #87cefa;
	  text-align: center;
	  user-select: none;
	}
	:checked + label {
	  z-index: 8;
	  pointer-events: none;
	}
	:checked + label + input + label {
	  pointer-events: none;
	}
  </style>
</head>
<body>
  <h1>Windsensor</h1>
  <svg viewBox="0 0 200 200">
    <g font-family="Arial Rounded MT Bold" font-size="9.5px">
      <path d="m175.4 73.296c2.5652 7.2385 4.0786 14.849 4.4791 22.518m-20.446-49.341c5.14 5.7058 9.4505 12.157 12.755 19.09m-37.771-37.76c6.9323 3.3045 13.384 7.6155 19.09 12.755m-49.346-20.431c7.6692 0.40007 15.279 1.9141 22.518 4.479m-53.409 8e-3c7.2385-2.5652 14.849-4.0787 22.518-4.4791m-49.34 20.446c5.7058-5.14 12.157-9.4505 19.09-12.755m-37.76 37.771c3.3045-6.9323 7.6155-13.384 12.755-19.09m-20.431 49.346c0.40007-7.6692 1.9141-15.279 4.479-22.518m0.0078 53.408c-2.5652-7.2385-4.0787-14.849-4.4791-22.518m20.446 49.34c-5.14-5.7058-9.4505-12.157-12.755-19.09m37.771 37.76c-6.9323-3.3045-13.384-7.6155-19.09-12.755m49.346 20.43c-7.6692-0.40007-15.279-1.9141-22.518-4.479m53.409-8e-3c-7.2385 2.5652-14.849 4.0786-22.518 4.479m68.011-45.462c-3.3045 6.9323-7.6155 13.384-12.755 19.09m-5.9154 5.9264c-5.7058 5.14-12.157 9.4505-19.09 12.755m45.436-68.027c-0.40002 7.6692-1.9144 15.28-4.479 22.518" stroke="#666" stroke-width="3" />
      <path id="arrow" d="" />
      <text x="96" y="11">N</text>
      <text x="162" y="38">NO</text>
      <text x="161" y="169">SO</text>
      <text x="97" y="196">S</text>
      <text x="23" y="169">SW</text>
      <text x="3" y="102">W</text>
      <text x="23" y="38">NW</text>
      <text x="188" y="103">O</text>
    </g>
  </svg>
  <main>
	<input id="hour" type="radio" name="set" checked="checked">
	<label for="hour">
	  <span>
		<b>
		</b>
		m/s
	  </span>
	  <span>
		<b>
		</b>
		&#8960; hour
	  </span>
	  <span>
		<b>
		</b>
		max/h
	  </span>
	</label>
	<input id="week" type="radio" name="set">
	<label for="week">
	  <span>
		<b>
		</b>
		m/s
	  </span>
	  <span>
		<b>
		</b>
		&#8960; week
	  </span>
	  <span>
		<b>
		</b>
		max/w
	  </span>
	</label>
	<input id="day" type="radio" name="set">
	<label for="day">
	  <span>
		<b>
		</b>
		m/s
	  </span>
	  <span>
		<b>
		</b>
		&#8960; day
	  </span>
	  <span>
		<b>
		</b>
		max/d
	  </span>
	</label>
  </main>
</body>
</html>