Blog der Heimetli Software AG

Raspberry: dynamische Anzeige der Chip-Temperatur

Nachdem ich mit flask und AJAX schon die Umgebungstemperatur eines Raspberry angezeigt hatte, war es einfach die CPU-Temperatur anzuzeigen.

Die Temperatur wird aus sysfs gelesen, dieses Programm kommt also ohne zusätzliche Hardware aus.

Webseite mit der CPU-Temperatur

Der Code ist nicht spezifisch für den Raspberry, er läuft unverändert auch auf einem Debian-Linux.

Software-Installation

Das aktuelle Buster kommt schon mit python und flask. Ausser der folgenden Webseite und dem Python-Programm muss also nichts installiert werden.

Das Markup der Webseite

<!DOCTYPE html>
<html lang="de">
 <head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Raspberry Teperatur aus sysfs</title>
 </head>
 <body>
  <h1>Raspberry Temperatur aus sysfs mit flask</h1>
  <p>Die aktuelle Temperatur ist <span id="temperature"></span> Grad</p>
  <script>
   function updateTemperature()
   {
      fetch( "/temperature" )
         .then( response => {
            if( !response.ok )
               throw new Error( "fetch failed" ) ;

            return response.json() ;
         } )
         .then( json => document.querySelector("#temperature").textContent = json.temperature )
         .catch( error => alert(error) ) ;
   }

   updateTemperature() ;

   setInterval( updateTemperature, 5000 ) ;
  </script>
 </body>
</html>

Die Temperatur wird mit fetch geholt und in die Webseite eingesetzt. setInterval sorgt dafür dass die Anzeige periodisch aktualisiert wird.

flask erwartet dieses File in ./templates unter dem Namen index.html.

Die flask-Applikation

Abgelegt als app.py.

from flask import Flask, render_template, jsonify

app   = Flask( __name__ )

@app.route( "/" )
def index():
    return render_template( "index.html" )

@app.route( "/temperature" )
def temperature():
    with open( "/sys/class/thermal/thermal_zone0/temp", "r" ) as input:
        temperature = float( input.readline() ) / 1000.0

    return jsonify( {"temperature": temperature} )

Starten von flask

Es ist empfehlenswert einen ausgewachsenen WSGI-Server für flask-Projekte einzusetzen. Für einen ersten Versuch kann man die Applikation direkt starten:

export FLASK_APP=app.py
flask run --host=0.0.0.0

In diesem Fall ist die Seite unter Port 5000 zu erreichen.

Update 20. März 2020, Zugriff von einem zweiten Raspberry

Kaum hatte ich diesen Post veröffentlicht, kam die Idee auf, die HTML-Seite auf einem zweiten Raspberry zu hosten, und dort die Temperatur vom ersten Raspberry anzuzeigen.

Mit eben gezeigten app.py funktioniert das aber nicht, weil jeder einigermassen moderne Browser den Zugriff verweigert. Nur wenn der Server dies explizit erlaubt, kann man aus einer HTML-Seite Daten von einem anderen System abrufen.

Diese Erlaubnis geben die CORS-Header, und die kann man ganz einfach in der App setzen:

from flask import Flask, render_template, jsonify

app   = Flask( __name__ )

@app.route( "/" )
def index():
    return render_template( "index.html" )

@app.route( "/temperature" )
def temperature():
    with open( "/sys/class/thermal/thermal_zone0/temp", "r" ) as input:
        temperature = float( input.readline() ) / 1000.0

    response = jsonify( {"temperature": temperature} )
    response.headers.add( "Access-Control-Allow-Origin", "*" )
    return response

Falls es keine lokale Webseite braucht, kann der Code für die Route "/" und die HTML-Seite auf dem abgefragten System weggelassen werden.

Im HTML muss in diesem Fall die komplette URL der Maschine mit der App angegeben werden:

  fetch( "http://192.168.1.38/temperature" )

Alles andere bleibt unverändert.