In­halts­ver­zeich­nis

Features

Muster der Seite

Seitenaufbau

Startseite "index.html"

Messskalen für Temperatur, rel. Luftfeuchtigkeit und Luftdruck

Verlaufskurven


Features

Im folgenden wird der Aufbau einer browser-fähigen Web-Site zur Anzeige aktueller und historischer Wetterdaten dokumentiert. Auf der Seite sollen dargestellt werden:

Es soll eine Seite mit grafischer Ausgabe und eine mit einer tabellarischen Ausgabe der Daten vorhanden sein.

Randbedingung: Der ESP8266 soll sowohl im Modus STA (Station) als auch AP (Access Point) betrieben werden. Letzteres impliziert, dass keine Verbindung zum Internet bestehen kann. Sämtliche Inhalte zum Aufbau der Seiten müssen also auf dem ESP8266 lokal zur Verfügung stehen.

Muster der Seite

Muster der Web-Site ToDo: Bild erneuern, %DateTime% hinzugefügt.

Seitenaufbau

Die Seite besteht aus acht Komponenten. Die Komponenten enthalten Platzhalter in der Form %template%, die beim Laden der Komponenten durch entsprechende aktuelle Werte ersetzt werden. Z.B. %DateTime% ->12.08.2017 08:12.

Startseite "index.html"

Die Datei "index.hmtl" legt den Aufbau der Seite fest:

<!DOCTYPE html>
<html lang="de">
  <head>
   <meta http-equiv="Content-type" content="text/html; charset=utf-8">
   <meta http-equiv="refresh" content="%pageRefresh%" >
   <link href="weather.ico" rel="shortcut icon" type="image/x-icon">
    <title>%location%</title>
    <style>
      div {position: absolute;}
    </style>
  </head>

  <body style="font-family: Helvetica, Arial, sans-serif">
    <div style="top:10px;left:0px;width:750px;text-align:center;color:#365F91">
      <!-- Überschrift -->
      <h2 style="text-decoration: underline">&nbsp;%location%&nbsp;</h2>
    </div>

    <div style="top:70px;left:200px;width:350px;Text-align:center;color:#4F81BD;">
      <!-- aktuelles Datum und aktuelle Uhrzeit -->
      <h1 style="border:4px red solid;">%CurrentDateTime%</h1>
    </div>

    <!-- Datum und Uhrzeit der Messwertnahme -->
    <div style="top:140px;left:20px; font-size: small;">Messwerte von: %DateTime%</div>

    <!-- Drei runde Anzeigen nebeneinander für aktuelle Werte -->
    <div id="t" style="top:150px;left:1px"><img alt="" src="1pixel.png"/></div>
    <div id="h" style="top:150px;left:252px"><img alt="" src="1pixel.png"/></div>
    <div id="p" style="top:150px;left:503px"><img alt="" src="1pixel.png"/></div>
    <!-- drei Verlaufsanzeigen untereinander -->
    <div id="vt" style="top:400px;left:-50px"><img alt="" src="1pixel.png"/></div>
    <div id="vh" style="top:650px;left:-50px"><img alt="" src="1pixel.png"/></div>
    <div id="vp" style="top:900px;left:-50px"><img alt="" src="1pixel.png"/></div>

    <script>
    function foo (id){
       document.getElementById(id).innerHTML =  '<img alt="" src="' + id + '.svg" />';
    }
    window.setTimeout("foo('t')", 100);
    window.setTimeout("foo('h')", 100);
    window.setTimeout("foo('p')", 200);
    window.setTimeout("foo('vt')", 200);
    window.setTimeout("foo('vh')", 300);
    window.setTimeout("foo('vp')", 300);
    </script>
  </body>
</html>

Die benutzten Platzhalter sind:

Platzhalter Wert Anmerkung
%pageRefresh% Anzahl Sekunden, nach denen ein automatischer Refresh der Seite durchgeführt werden soll. Der Wert ist konfigurierbar. (Paramter "pageRefresh" in "config.txt", s. Konfiguration ToDo!). Der Standardwert ist 300 ( 5 Minuten).
%location% Messort, im Seitentitel und als Überschrift Der Wert ist konfigurierbar. (Paramter "location" in "config.txt", s. Konfiguration ToDo!). Der Standardwert ist der Name der Applikation "ESP8266-Weather".
%CurrentDateTime% Aktuelles Datum und Uhrzeit Wenn kein Kontakt zu einer Zeitquelle besteht: "~"
%DateTime% Datum und Uhrzeit zu dem die angezeigten Messwerte erhoben wurden. Wenn kein Kontakt zu einer Zeitquelle besteht: "vor n Minuten".

Leider gibt es beim ESP8266 ein Problem mit der Anzahl der gleichzeitig möglichen Verbindungen. Deren Anzahl ist auf fünf beschränkt. Firefox und IE haben deshalb gelegentlich Aussetzer und Chrome hängt lange in einer Wiederholungschleife. Die Lösung ist, die Grafiken zeitverzögert zu laden. Die ersten beiden Dateien  werden per JavaScript mit einer Verzögerung von 100 ms, die nächsten nach 200 ms und die letzten nach 300 ms geladen.

Messskalen für Temperatur, rel. Luftfeuchtigkeit und Luftdruck

Die Skalen für die aktuellen Wetterdaten sind als SVG-Dateien abgelegt. Sie sind ähnlich aufgebaut. Hier das Beispiel für die Temperatur ("t.svg"):

<svg version="1.1" width="250" height="250" 
     xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs id="defs">
    <!-- Definition Zeiger -->
    <symbol id="Zeiger">
      <path d="M125,33 C132,125, 128,154, 125,154 C122,154,118,125,125,33"
            stroke="#c63310" stroke-width="1" fill-opacity="0.7" fill="#dc3912"></path>
    </symbol>
  </defs>
  <!-- Grauer Kreis mit schwarzem Rand -->
  <circle cx="125" cy="125" r="113" stroke="#333333" fill="#cccccc"></circle>
  <!-- Weißes Innenteil -->
  <circle cx="125" cy="125" r="101" stroke="#e0e0e0" stroke-width="2" fill="#f7f7f7"></circle>
  <!-- Blauer Bereich-->
  <path d="M56,194 A97,97,0,0,1,125,28 L125,52 A73,73,0,0,0,74,176 Z" stroke="none" fill="#6060ff"></path>
  <!-- Hellroter Bereich-->
  <path d="M125,28 A97,97,0,0,1,221,110 L197,114 A73,73,0,0,0,125,53 Z" stroke="none" fill="#ff5000"></path>
  <!-- Dunkelroter Bereich-->
  <path d="M221,110 A97,97,0,0,1,194,194 L176,176 A73,74,0,0,0,197,114 Z" stroke="none" fill="#dc3912"></path>
  <!-- Mittel-Text, Art des Messwertes -->
  <text text-anchor="middle" x="125" y="100" font-family="arial" font-size="14" stroke="none" 
        fill="#333333">Temperatur</text>
  <!-- Skalenbeschriftung -->
  <g font-family="arial" font-size="14" stroke="none" fill="#333333">
    <text text-anchor="start"  x="75"  y="180" >-50</text>
    <text text-anchor="start"  x="58"  y="152">-40</text>
    <text text-anchor="start"  x="68"  y="88">-20</text>
    <text text-anchor="middle" x="125" y="63">0</text>
    <text text-anchor="end"    x="182" y="88">20</text>
    <text text-anchor="end"    x="192" y="152">40</text>
    <text text-anchor="end"    x="175" y="180">50</text>
  </g>
  <!-- Scala, dünne Teilstriche -->
  <path d="M 58,181 L 50,187 M 53,174 L 45,180 M 48,167 L 40,172 M 45,160 L 36,164 
           M 40,144 L 30,146 M 38,136 L 29,137 M 38,128 L 28,128 M 38,120 L 28,119 
           M 40,103 L 31,101 M 43, 95 L 34, 92 M 46, 88 L 37, 84 M 50, 81 L 42, 76
           M 60, 67 L 52, 61 M 65, 61 L 59, 54 M 71, 56 L 66, 48 M 78, 51 L 73, 43 
           M 93, 44 L 89, 35 M101, 41 L 98 ,32 M109, 39 L107, 30 M117, 38 L116, 28
           M133, 38 L134, 28 M141, 39 L143, 30 M149, 41 L152, 32 M157, 44 L161, 35
           M172, 51 L177, 43 M179, 56 L184, 48 M185, 61 L191, 54 M190, 67 L198, 61
           M200, 81 L208, 76 M204, 88 L213, 84 M207, 95 L216, 92 M210,103 L219,101
           M212,120 L222,119 M212,128 L222,128 M212,136 L221,137 M210,144 L220,146
           M205,160 L214,164 M202,167 L210,172 M197,174 L205,180 M192,181 L200,187" 
           stroke="#666666" fill-opacity="1" fill="none">
  </path>
  <!-- Scala, fette Teilstriche -->
  <path d="M 70,180 L 56,194 M 51,149 L 33,155 M 48,113 L 29,110 M 62, 79 L 47, 68
           M 90, 56 L 81, 39 M125, 47 L125, 28 M160, 56 L169, 39 M188, 79 L203, 68
           M202,113 L221,110 M199,149 L217,155 M180,180 L194,194" 
           stroke="#333333" stroke-width="2" fill-opacity="1" fill="none">
  </path>
    <!-- Wertangabe -->
    <text text-anchor="middle" x="125" y="206.75" font-family="arial" font-size="22" stroke="none"
          fill="#000000">%wert%°C</text>
    <!-- Zeiger Senkrecht 
    <use xlink:href="#Zeiger" transform="rotate(45,125,125)"/>
    -->
	%zeiger%
    <!-- Mittelkreis (blau) -->
    <circle cx="125" cy="125" r="15" stroke="#666666" fill="#4684ee"></circle>
  </svg>

So sieht es aus:
Messskala Temperatur

Die benutzten Platzhalter sind:

Platzhalter Wert Anmerkung
%wert% Der Messwert. z.B. "17,5"
%zeiger% SVG-Code zur Positionierung des Zeigers. z.B. <use xlink:href="#Zeiger" transform="rotate(45,125,125"/>
oder "", wenn der Zeiger ausgeblendet werden soll.

Da der Zeiger ausgelassen werden soll, wenn kein Messwert vorliegt, muss der gesamte Code zur Darstellung des Zeigers eingefügt werden. Der Zeiger selbst ist als Symbol definiert, so dass nur eine Referenz ("#Zeiger") mit der entsprechendem Rotationswinkel ("rotate(α125,125)") angegeben werden muss. Einzufügen ist

<use xlink:href="#Zeiger" id="Zeiger" transform="rotate(α,125,125)"/>

Dabei ist α der Rotationswinkel in Grad, "125,125" der Punkt, um den rotiert werden soll. Dies ist der Mittelpunkt der Grafik (Ausmaße 125x125 Pixel²).

Der Rotationswinkel für einen senkrechten Zeiger ist 0. Die Maximalwerte sind ±135. Daraus ergibt sich die Umrechnungsformel (mit max = maximaler Messwert, min = minimaler Messwert, V = Messwert):

α = 270/(max-min) (V-(max+min)/2).

Messwert min, max Berechnung (int) Berechnung (float)
Temperatur -50, +50 27 * V / 10 2.7f * V
Luftfeuchtigkeit 0, 100 27 * (V - 50) / 10 2.7f * (V - 50)
Luftdruck 950, 1050 27 * (V - 1000) / 10 2.7f * (V-1000)

Verlaufskurven

Die Gestaltung der Verlaufskurven ist aufwändiger. Es ist nicht sinnvoll, die Skala über den gesamten Messbereich zu definieren. Man müsste entweder eine sehr große Grafik erstellen oder man sieht im wesentlichen nur eine gerade Linie. Die Änderung der Wetterdaten innerhalb von 24 Stunden ist einfach zu klein.

Um den gerecht zu werden, wird nur ein Ausschnitt des Messbereichs angezeigt. Dieser, d.h. der Minimal- und der Maximalwert müssen jedes mal neu bestimmt werden. Die Spanne, d.h. der Unterschied zwischen dem maximal und dem minimal angezeigten Wert, ist konstant: 20 °C für die Temperatur, 20 hPa für den Luftdruck. Lediglich für die relative Luftfeuchtigkeit wird die gesamte Spanne von 100 % angezeigt (ToDo: Ist das sinnvoll?).

Weiterhin sollen die Daten als glatte kurve dargestellt werden. Demzufolge ist die Berechnung von Spline-Funktionen notwendig.

Zuletzt muss noch die Zeitachse beschriftet werden.

Festlegung der Skala

Der DataServer liefert Daten der letzten 24 Stunden im Stundenabstand. Außerdem den Minimal- und den Maximalwert innerhalb dieser Zeit. Beide Werte werden auf ganze Skaleneinheiten ab- bzw. aufgerundet. Bei der Temperatur z.B. wird der Minimalwert auf ganze 5 °C ab- (17 → 15) und der Maximalwert auf ganze 5 °C aufgerundet (17 → 20). Ist der Unterschied kleiner als die mögliche Spanne, wird die Basisachse der Grafik auf den gerundeten Minimalwert gelegt.

Δ > Skala zeitlich letzter bestimmt die Skala

Zeitachse

Spline

 

Fortsetzung folgt