Stellen Sie die Sensorinformationen von Raspberry Pi in Java grafisch dar und überprüfen Sie sie mit einem Webbrowser

Einführung

Ich habe die Informationen des an Raspberry Pi 3 angeschlossenen Temperatur- / Feuchtigkeitssensors und Drucksensors kontinuierlich in der Datenbank aufgezeichnet, grafisch dargestellt und im Webbrowser eines anderen PCs oder Smartphones angezeigt. Die Programmiersprache verwendet Java.

History Graph

DHT11 und BMP180 wurden für den Temperatur- / Feuchtigkeitssensor und den Drucksensor verwendet.

DHT11
(Temperatur- / Feuchtigkeitssensor)
BMP180
(Druck- / Temperatursensor)
DHT11 BMP180

Vorbereitung

Die verwendete Hardware- und Softwareumgebung ist die in den folgenden Artikeln vorgestellte.

Stellen Sie die Sensorinformationen von Raspberry Pi grafisch dar und bereiten Sie eine Umgebung vor, die mit einem Webbrowser überprüft werden kann

Wenn die Umgebung bereit ist, installieren Sie den Sensor wie im folgenden Schaltplan gezeigt. Der Widerstand wurde im Datenblatt als 5 kΩ angegeben, aber ich hatte ihn nicht, also habe ich ihn durch 10 kΩ ersetzt (es scheint kein Problem zu geben).

配線図

(Referenzmaterial) DHT11-Datenblatt / BMP180-Datenblatt -DS000-09.pdf)

Datenbank erstellen

Alle folgenden Operationen werden vom pi-Benutzer ausgeführt.

Erstellen Sie zunächst eine Datenbank, um Temperatur-, Feuchtigkeits- und Druckdaten aufzuzeichnen. Die Datenbank verwendet MySQL, das in dem oben verlinkten Artikel installiert ist.

Im folgenden Beispiel wird raspberrypi als Datenbankname angegeben, Sie können jedoch einen beliebigen Namen angeben (ein Teil der Ausgabe wird weggelassen).

$ mysql -p
Enter password:

MariaDB [(none)]> CREATE DATABASE raspberrypi CHARACTER SET utf8;
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| raspberrypi        |
+--------------------+

Erstellen Sie nach dem Erstellen der Datenbank die darin enthaltenen Tabellen. Im folgenden Beispiel wird die Tabellenatmosphäre erstellt und die Spalten-ID, Datum / Uhrzeit, Temperatur, Luftfeuchtigkeit und Druck werden erstellt. Sie können hier auch einen beliebigen beschreibenden Namen angeben.

MariaDB [(none)]> use raspberrypi
MariaDB [raspberrypi]> CREATE TABLE atmosphere( id INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY, datetime DATETIME NOT NULL, temperature FLOAT(4,1), humidity FLOAT(4,1), pressure FLOAT(5,1) );

MariaDB [raspberrypi]> show tables;
+-----------------------+
| Tables_in_raspberrypi |
+-----------------------+
| atmosphere            |
+-----------------------+

MariaDB [raspberrypi]> desc atmosphere;
+-------------+------------+------+-----+---------+----------------+
| Field       | Type       | Null | Key | Default | Extra          |
+-------------+------------+------+-----+---------+----------------+
| id          | int(10)    | NO   | PRI | NULL    | auto_increment |
| datetime    | datetime   | NO   |     | NULL    |                |
| temperature | float(4,1) | YES  |     | NULL    |                |
| humidity    | float(4,1) | YES  |     | NULL    |                |
| pressure    | float(5,1) | YES  |     | NULL    |                |
+-------------+------------+------+-----+---------+----------------+

MariaDB [raspberrypi]> exit

Datenaufzeichnung

Erstellen Sie unter dem Webanwendungsverzeichnis von Tomcat ein Verzeichnis zum Platzieren von Programmen und Servlets zum Aufzeichnen von Daten.

mkdir -p ~/apache-tomcat-9.0.6/webapps/atmosphere/WEB-INF/classes

Erstellen Sie den folgenden Quellcode in diesem Klassenverzeichnis, um Informationen vom Sensor zu lesen und in der Datenbank aufzuzeichnen.

Die unteren drei der vier Dateien dienen zum Lesen von Informationen von jedem Sensor. Bitte kopieren Sie diese aus den folgenden einleitenden Artikeln.

DHT11.java / DHT11Result.java Temperatur / Luftfeuchtigkeit von Raspberry Pi 3 & DHT11 mit Java lesen

BMP180.java Lesen von Druck und Temperatur von Raspberry Pi 3 & BMP180 mit Java </ dd>

RecordingTask.java


import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.Properties;

import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.SQLException;

public class RecordingTask {

    private static String sqlDataBase      ;
    private static String sqlTable         ;
    private static String sqlColDateTime   ;
    private static String sqlColTemperature;
    private static String sqlColHumidity   ;
    private static String sqlColPressure   ;

    private static String sqlUser    ;
    private static String sqlPassword;

    // {0} table name
    // {1} column name(datetime)
    // {2} column name(temperature)
    // {3} column name(humidity)
    // {4} column name(pressuer)
    // {5} temperature
    // {6} humidity
    // {7} puressure
    private static final String sqlTemplate =
        "INSERT INTO {0} ( {1}, {2}, {3}, {4} ) VALUES ( NOW(), {5,number,#0.0}, {6,number,#0.0}, {7,number,#0.00} );";

    public static void main( String... args ) {

        getProperties();

        Connection conn = null;
        String url = "jdbc:mysql://localhost/" + sqlDataBase;

        try {
            Class.forName( "com.mysql.jdbc.Driver" ).newInstance();
            conn = DriverManager.getConnection( url, sqlUser, sqlPassword );

            Statement stmt = conn.createStatement();

            // DHT11 ---

            DHT11 dht11 = new DHT11( 15 ); // use GPIO pin 15

            DHT11Result result;
            while ( true ) {
                result = dht11.read();

                if ( result.isValid() ) {
                    // System.out.printf("Temperature: %.1f C\n" , result.temperature );
                    // System.out.printf("Humidity:    %.1f %%\n", result.humidity);
                    break;
                }
            }

            // BMP180 ---

            BMP180 bmp180 = new BMP180( BMP180.ULTRAHIGHRES );

            double pressure = bmp180.readPressure();
            // System.out.printf( "Pressure   : %.2f hPa\n", pressure );

            // write data to database
            String sql = MessageFormat.format( sqlTemplate,
                             sqlTable, sqlColDateTime, sqlColTemperature, sqlColHumidity, sqlColPressure,
                             result.temperature, result.humidity, pressure );
            // System.out.println( sql );

            int num = stmt.executeUpdate( sql );

            stmt.close();
        } catch ( ClassNotFoundException e ) {
            e.printStackTrace();
        } catch ( SQLException e ) {
            e.printStackTrace();
        } catch ( Exception e ) {
            e.printStackTrace();
        } finally {
            try {
                if ( conn != null ) {
                    conn.close();
                }
            } catch ( SQLException e ) {
                e.printStackTrace();
            }
        }
    }

    static void getProperties() {
        Path path = Paths.get( "atmosphere.properties" );
        try ( BufferedReader reader = Files.newBufferedReader( path, StandardCharsets.UTF_8 ) ) {
            Properties properties = new Properties();
            properties.load( reader );

            sqlDataBase       = properties.getProperty( "mysql.db" );
            sqlTable          = properties.getProperty( "mysql.db.table" );
            sqlColDateTime    = properties.getProperty( "mysql.db.table.datetime" );
            sqlColTemperature = properties.getProperty( "mysql.db.table.temperature" );
            sqlColHumidity    = properties.getProperty( "mysql.db.table.humidity" );
            sqlColPressure    = properties.getProperty( "mysql.db.table.puressure" );
            sqlUser           = properties.getProperty( "mysql.user" );
            sqlPassword       = properties.getProperty( "mysql.password" );
        } catch ( IOException e ) {
            e.printStackTrace();
        }
    }
}

Der Wert, der in die Datenbank geschrieben werden soll, wird im folgenden Teil angegeben. Wenn Sie einen anderen Sensor verwenden möchten, können Sie den Lesewert als Doppeltyp in den Teilen result.temperature, result.humidity und druck angeben.

            String sql = MessageFormat.format( sqlTemplate,
                             sqlTable, sqlColDateTime, sqlColTemperature, sqlColHumidity, sqlColPressure,
                             result.temperature, result.humidity, pressure );

Erstellen Sie außerdem eine Eigenschaftendatei atmosphäre.properties am selben Speicherort. Registrieren Sie die Namen, die Sie für die erstellte Datenbank, Tabelle und Spalte in dieser Datei angegeben haben. Geben Sie außerdem den Benutzer und das Kennwort für den Zugriff auf MySQL an.

atmosphere.properties


mysql.db=raspberrypi
mysql.db.table=atmosphere
mysql.db.table.datetime=datetime
mysql.db.table.temperature=temperature
mysql.db.table.humidity=humidity
mysql.db.table.puressure=pressure
mysql.user=pi
mysql.password=raspberry
jfreechart.chartfile=/home/pi/apache-tomcat-9.0.6/webapps/atmosphere/atmosphere.png

Das endgültige jfreechart.chartfile = gibt an, wo und mit welchem Dateinamen das vom Servlet erstellte Diagrammbild abgelegt werden soll.

Wenn Sie bereit sind, kompilieren Sie den Quellcode und führen Sie ihn aus.

$ cd ~/apache-tomcat-9.0.6/webapps/atmosphere/WEB-INF/classes
$ javac RecordingTask.java
$ sudo java -classpath $CLASSPATH RecordingTask

Stellen Sie nach dem Ausführen des Programms sicher, dass die vom Sensor abgerufenen Informationen in die Datenbank geschrieben werden.

$ mysql -p
Enter password:

MariaDB [(none)]> use raspberrypi

MariaDB [raspberrypi]> select * from atmosphere;
+----+---------------------+-------------+----------+----------+
| id | datetime            | temperature | humidity | pressure |
+----+---------------------+-------------+----------+----------+
|  1 | 2018-04-07 19:26:15 |        24.2 |     50.0 |    994.4 |
+----+---------------------+-------------+----------+----------+

MariaDB [raspberrypi]> exit

Wenn Sie den im Test erstellten Datensatz löschen möchten oder wenn Sie die Tabelle oder Datenbank selbst löschen möchten, verwenden Sie die folgende SQL-Anweisung. Bitte beachten Sie, dass der Löschvorgang ohne Bestätigung schnell gelöscht wird.

Funktion SQL-Anweisung
Löschen Sie alle Datensätze in der Tabelle USE database_name
TRUNCATE TABLE table_name;
Tabelle löschen USE database_name
DROP TABLE table_name;
Datenbank löschen DROP DATABASE database_name;

Führen Sie dieses Programm regelmäßig von cron aus, um Sensorinformationen in der Datenbank zu speichern. Erstellen Sie das folgende Shell-Skript atmosphäre.sh im Verzeichnis ~ / apache-tomcat-9.0.6 / webapps / atmosphäre und legen Sie die Zugriffsrechte fest.

atmosphere.sh


#!/bin/sh

CATALINA_HOME="/home/pi/apache-tomcat-9.0.6"
export CLASSPATH=.:/opt/pi4j/lib/*:$CATALINA_HOME/lib/*

cd $CATALINA_HOME/webapps/atmosphere/WEB-INF/classes
sudo java -classpath $CLASSPATH RecordingTask
$ cd ~/apache-tomcat-9.0.6/webapps/atmosphere
$ chmod 755 atmosphere.sh

Setzen Sie dieses Shell-Skript in crontab und Sie können loslegen. Sie werden gefragt, welchen Editor Sie verwenden sollen, wenn Sie crontab zum ersten Mal starten. Nano wird jedoch empfohlen, es sei denn, Sie haben einen bestimmten Grund.

$ crontab -e
no crontab for pi - using an empty one

Select an editor.  To change later, run 'select-editor'.
  1. /bin/ed
  2. /bin/nano        <---- easiest
  3. /usr/bin/vim.tiny

Choose 1-3 [2]: 2

Fügen Sie am Ende der im Editor geöffneten Datei Folgendes hinzu. Diese Einstellung startet das Shell-Skript stündlich um 0 Minuten. Das diesmal erstellte Programm wird unter der Annahme erstellt, dass die Daten stündlich mit 0 Minuten aufgezeichnet werden.

0 * * * * /bin/bash /home/pi/apache-tomcat-9.0.6/webapps/atmosphere/atmosphere.sh

Sie können die Einstellungen mit crontab -l überprüfen.

Diagramm erstellen

Gehen Sie zurück zum Klassenverzeichnis und erstellen Sie das Servlet AtmosphereChart.java, das die Daten aus der Datenbank liest und das Diagrammbild erstellt.

AtmosphereChart.java


import java.io.File;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Properties;
import java.text.MessageFormat;
import java.awt.BasicStroke;
import java.awt.Font;
import java.awt.Color;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.RequestDispatcher;

import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.title.TextTitle;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.CategoryMarker;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.Layer;

public class AtmosphereChart extends HttpServlet {

    private String sqlDataBase      ;
    private String sqlTable         ;
    private String sqlColDateTime   ;
    private String sqlColTemperature;
    private String sqlColHumidity   ;
    private String sqlColPressure   ;

    private String sqlUser    ;
    private String sqlPassword;

    private String chartFile;

    private static final String PERIOD_1_DAY    = "1";
    private static final String PERIOD_2_DAYS   = "2";
    private static final String PERIOD_3_DAYS   = "3";
    private static final String PERIOD_7_DAYS   = "7";
    private static final String PERIOD_30_DAYS  = "30";
    private static final String PERIOD_90_DAYS  = "90";
    private static final String PERIOD_180_DAYS = "180";
    private static final String PERIOD_360_DAYS = "360";

    // {0} table name {1} column name(datetime) {2} period(minute)
    private static final String sqlTemplate =
        "SELECT * FROM {0} WHERE {1} > ( SELECT MAX( {1} ) FROM {0} ) - INTERVAL {2,number,#} - 1 MINUTE ";

    private static final HashMap<String, String> sqlConditions;
    static {
        sqlConditions = new HashMap<>();
        sqlConditions.put( PERIOD_1_DAY   , ";" );
        sqlConditions.put( PERIOD_2_DAYS  , ";" );
        sqlConditions.put( PERIOD_3_DAYS  , "AND MOD( HOUR( {1} ), 2 ) = 0;" );
        sqlConditions.put( PERIOD_7_DAYS  , "AND MOD( HOUR( {1} ), 3 ) = 0;" );
        sqlConditions.put( PERIOD_30_DAYS , "AND HOUR( {1} ) = 12;" );
        sqlConditions.put( PERIOD_90_DAYS , "AND MOD( DAYOFMONTH( {1} ), 2 ) = 1 AND HOUR( {1} ) = 12;" );
        sqlConditions.put( PERIOD_180_DAYS, "AND MOD( DAYOFMONTH( {1} ), 4 ) = 1 AND HOUR( {1} ) = 12;" );
        sqlConditions.put( PERIOD_360_DAYS, "AND MOD( DAYOFMONTH( {1} ), 8 ) = 1 AND HOUR( {1} ) = 12;" );
    }

    private static final String path = Thread.currentThread().getContextClassLoader().getResource( "" ).getPath();
    private static final Font labelFont     = new Font( Font.SANS_SERIF, Font.PLAIN, 12 );
    private static final Font tickLabelFont = new Font( Font.SANS_SERIF, Font.PLAIN, 10 );

    private java.util.logging.Logger logger;

    @Override
    protected void doGet( HttpServletRequest request, HttpServletResponse response )
                   throws ServletException, IOException {
        /*
            logger = java.util.logging.Logger.getLogger( "debug" );
            try {
                java.util.logging.FileHandler fh = new java.util.logging.FileHandler( "/home/pi/debug.log" );
                fh.setFormatter( new java.util.logging.SimpleFormatter() );
                logger.addHandler( fh );
            } catch ( IOException e ) {
            }
        */

        String[] datetime    = null;
        double[] temperature = null;
        double[] humidity    = null;
        double[] pressure    = null;
        ArrayList<String> markerLabels = new ArrayList<>();

        int size = 0;

        String period = request.getParameter( "period" );
        if ( period == null ) period = PERIOD_1_DAY;

        getProperties();

        // Read data from database

        Connection conn = null;
        String url = "jdbc:mysql://localhost/" + sqlDataBase;

        try {
            Class.forName( "com.mysql.jdbc.Driver" ).newInstance();
            conn = DriverManager.getConnection( url, sqlUser, sqlPassword );

            Statement stmt = conn.createStatement();

            String sql = makeSQLStatement( period );
            // logger.log( java.util.logging.Level.INFO, "SQL statement : " + sql );

            ResultSet rs = stmt.executeQuery( sql );

            rs.last();
            size = rs.getRow();
            rs.beforeFirst();

            datetime    = new String[ size ];
            temperature = new double[ size ];
            humidity    = new double[ size ];
            pressure    = new double[ size ];

            int i = 0;
            while( rs.next() ) {
                datetime   [ i ] = MessageFormat.format(
                                       "{0,date,MM-dd} {1,time,HH:mm}",
                                       rs.getDate( sqlColDateTime ), rs.getTime( sqlColDateTime ) );
                temperature[ i ] = rs.getDouble( sqlColTemperature );
                humidity   [ i ] = rs.getDouble( sqlColHumidity );
                pressure   [ i ] = rs.getDouble( sqlColPressure );

                if ( isMarkerLabel( period, datetime[ i ] ) ) {
                    markerLabels.add( datetime[ i ] );
                }

                i ++ ;
            }

            rs.close();
            stmt.close();
        } catch ( ClassNotFoundException e ) {
            logger.log( java.util.logging.Level.WARNING, "", e );
        } catch ( SQLException e ) {
            logger.log( java.util.logging.Level.WARNING, "", e );
        } catch ( Exception e ) {
            logger.log( java.util.logging.Level.WARNING, "", e );
        } finally {
            try {
                if ( conn != null ) {
                    conn.close();
                }
            } catch ( SQLException e ) {
                logger.log( java.util.logging.Level.WARNING, "", e );
            }
        }

        // Draw Chart

        LineAndShapeRenderer renderer;
        CategoryAxis cAxis;
        NumberAxis   nAxis;

        DefaultCategoryDataset dataT = new DefaultCategoryDataset();
        DefaultCategoryDataset dataH = new DefaultCategoryDataset();
        DefaultCategoryDataset dataP = new DefaultCategoryDataset();

        for( int i = 0; i < size; i ++ ) {
            dataT.addValue( ( Number )temperature[ i ], "Temperature", datetime[ i ] );
            dataH.addValue( ( Number )humidity   [ i ], "Humidity"   , datetime[ i ] );
            dataP.addValue( ( Number )pressure   [ i ], "Pressure"   , datetime[ i ] );
        }

        // Temperature
        JFreeChart chart = ChartFactory.createLineChart(
            "Sensor Data History Graph - " + period + ( period.equals( "1" ) ? " day" : " days" ),
            "Time",
            "Temperature (C)",
            dataT,
            PlotOrientation.VERTICAL,
            true,
            false,
            false
        );
        chart.setBackgroundPaint( Color.WHITE );
        TextTitle subtitle = new TextTitle(
            size != 0 ?
            MessageFormat.format( "Last data({0})  Temperature: {1} C  Humidity: {2} %  Pressure: {3} hPa",
                                  datetime   [ size - 1 ],
                                  temperature[ size - 1 ],
                                  humidity   [ size - 1 ],
                                  pressure   [ size - 1 ] ) :
            "No data to plot on the graph."
        );
        chart.addSubtitle( subtitle );

        CategoryPlot plot = chart.getCategoryPlot();

        cAxis = plot.getDomainAxis();
        cAxis.setCategoryLabelPositions( CategoryLabelPositions.UP_90 );
        cAxis.setLabelFont( labelFont );
        cAxis.setTickLabelFont( tickLabelFont );

        renderer = ( LineAndShapeRenderer )plot.getRenderer();
        nAxis = ( NumberAxis )plot.getRangeAxis();

        customizeChart( renderer, nAxis, 0.0, 50.0, Color.RED );

        // Add Humidity
        renderer = new LineAndShapeRenderer();
        nAxis = new NumberAxis( "Humidity (%)" );

        customizeChart( renderer, nAxis, 0.0, 100.0, Color.BLUE );

        plot.setRenderer( 1, renderer );    // renderer #1
        plot.setDataset( 1, dataH );        // dataset  #1
        plot.setRangeAxis( 1, nAxis );      // range axis #1
        plot.mapDatasetToRangeAxis( 1, 1 ); // map dataset #1 to range axis #1

        // Add Pressure
        renderer = new LineAndShapeRenderer();
        nAxis = new NumberAxis( "Pressure (hPa)" );

        customizeChart( renderer, nAxis, 950.0, 1050.0, Color.GREEN );

        plot.setRenderer( 2, renderer );    // renderer #2
        plot.setDataset( 2, dataP );        // dataset  #2
        plot.setRangeAxis( 2, nAxis );      // range axis #2
        plot.mapDatasetToRangeAxis( 2, 2 ); // map dataset #2 to range axis #2

        for ( String markerLabel : markerLabels ) {
            CategoryMarker marker = new CategoryMarker( markerLabel );
            marker.setPaint( Color.WHITE );
            marker.setDrawAsLine( true );
            marker.setStroke( new BasicStroke( 1.0f ) );
            plot.addDomainMarker( marker, Layer.BACKGROUND );
        }

        try {
            ChartUtilities.saveChartAsPNG( new File( chartFile ), chart, 800, 600 );
        } catch ( IOException e ) {
            logger.log( java.util.logging.Level.WARNING, "", e );
        }

        RequestDispatcher disp = request.getRequestDispatcher( "/result.html" );
        disp.forward( request, response );
    }

    void getProperties() {
        Path propPath = Paths.get( path + "atmosphere.properties" );
        try ( BufferedReader reader = Files.newBufferedReader( propPath, StandardCharsets.UTF_8 ) ) {
            Properties properties = new Properties();
            properties.load( reader );

            sqlDataBase       = properties.getProperty( "mysql.db" );
            sqlTable          = properties.getProperty( "mysql.db.table" );
            sqlColDateTime    = properties.getProperty( "mysql.db.table.datetime" );
            sqlColTemperature = properties.getProperty( "mysql.db.table.temperature" );
            sqlColHumidity    = properties.getProperty( "mysql.db.table.humidity" );
            sqlColPressure    = properties.getProperty( "mysql.db.table.puressure" );
            sqlUser           = properties.getProperty( "mysql.user" );
            sqlPassword       = properties.getProperty( "mysql.password" );
            chartFile         = properties.getProperty( "jfreechart.chartfile" );
        } catch ( IOException e ) {
            logger.log( java.util.logging.Level.WARNING, "", e );
        }
    }

    String makeSQLStatement( String period ) {
        String conditions = sqlConditions.get( period );
        if ( conditions == null ) conditions = ";";

        return MessageFormat.format( sqlTemplate + conditions,
                                     sqlTable, sqlColDateTime, Integer.parseInt( period ) * 24 * 60 );
    }

    boolean isMarkerLabel( String period, String datetime ) {

        switch ( period ) {
            case PERIOD_2_DAYS:
            case PERIOD_3_DAYS:
            case PERIOD_7_DAYS:
                return datetime.indexOf( "00:00" ) >= 0;

            case PERIOD_30_DAYS:
                return datetime.indexOf( "-01" ) >= 0 || datetime.indexOf( "-11" ) >= 0 ||
                       datetime.indexOf( "-21" ) >= 0;

            case PERIOD_90_DAYS:
            case PERIOD_180_DAYS:
            case PERIOD_360_DAYS:
                return datetime.indexOf( "-01" ) >= 0;

            default: // assume "1"
                return datetime.indexOf( "00:00" ) >= 0 || datetime.indexOf( "12:00" ) >= 0;
        }
    }

    void customizeChart( LineAndShapeRenderer renderer, NumberAxis axis,
                         double lower, double upper, Color color ) {

        renderer.setSeriesPaint( 0, color );
        renderer.setSeriesStroke( 0, new BasicStroke( 1.0f ) );
        renderer.setSeriesShapesVisible( 0, true );

        axis.setRange( lower, upper);
        axis.setLabelFont( labelFont );
        axis.setTickLabelFont( tickLabelFont );
        axis.setTickLabelPaint( color );
    }
}

Kompilieren Sie den Quellcode, um eine Klassendatei zu erstellen.

$ cd ~/apache-tomcat-9.0.6/webapps/atmosphere/WEB-INF/classes
$ javac AtmosphereChart.java

Für die Programmierung mit JFreeChart habe ich auf den folgenden Artikel verwiesen.

(Referenzartikel)

Diagramm mit JFreeChart erstellen

Erstellen Sie die folgende Datei web.xml unter ~ / apache-tomcat-9.0.6 / webapps / atmosphäre / WEB-INF, um den Namen und die aufrufende Methode dieses Servlets zu definieren.

web.xml


<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0">

  <!-- servlet definition -->
  <servlet>
    <servlet-name>AtmosphereChart</servlet-name>
    <servlet-class>AtmosphereChart</servlet-class>
  </servlet>

  <!-- mapping between servlet and UTL -->
  <servlet-mapping>
    <servlet-name>AtmosphereChart</servlet-name>
    <url-pattern>/AtmosphereChart</url-pattern>
  </servlet-mapping>

</web-app>

Zum Schluss platzieren Sie die beiden HTML-Dateien index.html und result.html unter ~ / apache-tomcat-9.0.6 / webapps / atmosphäre.

index.html


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="refresh" content="0; URL='./AtmosphereChart'">
</head>
</html>

result.html


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-Control" content="no-cache">
    <meta http-equiv="Expires" content="0">
    <style>
        .period {
            font-family:sans-serif;
            padding: 20px;
        }
        .period .form-title {
            font-weight: bold;
            font-size:14px;
        }
        .period label {
            font-size:12px;
        }
        .period input[type=submit] {
            appearance: none;
            outline: none;
            border: none;
            color: #fff;
            background-color: #7294f2;
            height: 24px;
            width: 52px;
            margin-left: 20px;
        }
        .period input[type=submit]:hover{
            background-color: #8af;
            cursor:pointer;
        }
    </style>
    <title>History Graph</title>
</head>
<body><center>
    <table border="0">
    <tr><td><img src="./atmosphere.png "></td></tr>
    <tr><td>
        <form class="period" method="get" action="./AtmosphereChart">
            <fieldset>
            <legend class="form-title">
            Select period to drow graph for Temperature, Humidity and Pressure.
            </legend>
            <center>
            <label><input type="radio" name="period" value="1" checked> 1 day</label>
            <label><input type="radio" name="period" value="2"> 2 days</label>
            <label><input type="radio" name="period" value="3"> 3 days</label>
            <label><input type="radio" name="period" value="7"> 7 days</label>
            <label><input type="radio" name="period" value="30"> 30 days</label>
            <label><input type="radio" name="period" value="90"> 90 days</label>
            <label><input type="radio" name="period" value="180"> 180 days</label>
            <label><input type="radio" name="period" value="360"> 360 days</label>
            <input type="submit" value="OK">
            </center>
            </fieldset>
        </form>
    </td></tr>
    </table>
</center></body>
</html>

Damit sind alle Einstellungen abgeschlossen. Die folgenden Dateien werden unter ~ / apache-tomcat-9.0.6 / webapps / atmosphäre / erstellt.

atmosphere
├── atmosphere.sh
├── index.html
├── result.html
└── WEB-INF
    ├── classes
    │   ├── AtmosphereChart.class
    │   ├── AtmosphereChart.java
    │   ├── atmosphere.properties
    │   ├── BMP180.class
    │   ├── BMP180.java
    │   ├── DHT11$1.class
    │   ├── DHT11.class
    │   ├── DHT11.java
    │   ├── DHT11Result.class
    │   ├── DHT11Result.java
    │   ├── DHT11$SignalTransition.class
    │   ├── RecordingTask.class
    │   └── RecordingTask.java
    └── web.xml

Grafik anzeigen

Geben Sie in der URL Folgendes an, um das Diagramm anzuzeigen.

http://[IP-Adresse oder localhost]:8080/atmosphere/

Die Daten für den letzten Tag werden aus den neuesten Daten grafisch dargestellt. Wenn Sie den Anzeigezeitraum ändern möchten, wählen Sie den Zeitraum aus den Optionsfeldern unten auf der Seite aus und klicken Sie auf die Schaltfläche OK. Die Daten werden gemäß den folgenden Regeln entsprechend dem ausgewählten Zeitraum erfasst und grafisch dargestellt, damit die Grafik nicht kompliziert wird.

Ausgewählter Zeitraum Daten zum Abholen
1 Day / 2 Days Stündlich
3 Days Alle 2 Stunden (sogar Stunden)
7 Days Alle 3 Stunden (0:00, 3:00, 6:00 ...)
30 Days Jeden Tag 12:00 Uhr
90 Days Jeden zweiten Tag (1., 3., 5. ...) 12:00
180 Days Alle 4 Tage (1., 5., 9. ...) um 12:00 Uhr
360 Days Alle 8 Tage (1., 9., 17. ...) um 12:00 Uhr

Selbst wenn Sie beispielsweise 90 Tage auswählen, wird das Liniendiagramm möglicherweise nicht angezeigt, wenn 90 Tage lang nicht genügend Daten vorhanden sind oder wenn keine Daten vorhanden sind, die die oben genannten Bedingungen erfüllen.

Ein bekanntes Problem ist, dass durch Auswahl eines Zeitraums und Klicken auf OK das Diagramm nicht aktualisiert wird. Dies scheint darauf zurückzuführen zu sein, dass das im Cache des Browsers verbleibende Bild angezeigt wird (die Bilddatei wurde auf dem Raspberry Pi korrekt aktualisiert). Wählen Sie in diesem Fall den Zeitraum erneut aus und klicken Sie erneut auf OK.

Recommended Posts

Stellen Sie die Sensorinformationen von Raspberry Pi in Java grafisch dar und überprüfen Sie sie mit einem Webbrowser
Socket-Kommunikation mit einem Webbrowser über Java und JavaScript ②
Socket-Kommunikation mit einem Webbrowser über Java und JavaScript ①
Verarbeiten Sie die vom menschlichen Sensor HC-SR501 erkannte Bewegung mit Raspberry Pi 3 & Java
Erstellen Sie mit Raspberry Pi und Docker Compose im Handumdrehen ein NAS mit DLNA-Funktion
Generieren Sie mit TableGenerator of Hibernate (JPA) eine Seriennummer und speichern Sie diese in der ID von String.
Die Geschichte, zu vergessen, eine Datei in Java zu schließen und zu scheitern
Ich habe eine Lambda-Funktion in Java geschrieben und mit SAM bereitgestellt
[Java] Geben Sie das Ergebnis von ffprobe -show_streams in JSON aus und ordnen Sie es einem Objekt in Jackson zu
Erstellen Sie eine CSR mit erweiterten Informationen in Java
Messen Sie die Größe eines Ordners mit Java
Holen Sie sich Youtube-Videoinformationen mit Retrofit und behalten Sie sie in der Android-App.
[Java] Ist es nicht erforderlich, "Identität" bei der Implementierung der equals () -Methode zu überprüfen?
Überprüfen Sie das ID-Token eines von AWS Cognito in Java authentifizierten Benutzers
Erstellen Sie ein Container-Image für Kibanas arm64 und registrieren Sie es in der GitHub-Container-Registrierung. Starten Sie Elastic Stack mit Docker Compose auf Raspberry Pi 4 (64 Bit).
[Java] Ganzzahlige Informationen von Zeichen in der Textdatei, die mit der Methode read () erfasst wurden
[Java] Schneiden Sie einen Teil der Zeichenfolge mit Matcher und regulären Ausdrücken aus
Versuchen Sie, die Fernbedienung der Mitsubishi-Klimaanlage mit Raspberry Pi zu scannen, zu analysieren und zu übertragen
Ein Programm (Java), das die Summe von ungeraden und geraden Zahlen in einem Array ausgibt
Die Geschichte des Erstellens einer Java-Version des Minecraft-Servers mit GCP (und dem Festlegen einer weißen Liste)
Bis Sie mit Maven ein von Scala geschriebenes Projekt erstellen und es mit dem Befehl scala ausführen.
Registrieren Sie DLNA-kompatibles Fernsehgerät in SORACOM Inventory und arbeiten Sie über die Webkonsole
Eine kurze Erklärung der fünf Arten von Java Static
Überprüfen Sie die Abhängigkeit eines bestimmten Maven-Artefakts in Coursier
Fensteraggregation von Sensordaten mit Apache Flink und Java 8
Befehl zum Überprüfen der Anzahl und des Status von Java-Threads
Überprüfen Sie die Funktion von zwei Rollen mit einer Chat-Anwendung
Finden Sie mit Kotlin die Anzahl der Tage in einem Monat
[Rails] Erhalten Sie access_token zum Zeitpunkt der Twitter-Authentifizierung mit Sorcery und speichern Sie es in der Datenbank
Welcher der drei in Java eingebetteten Webserver Tomcat, Jetty und Undertow arbeitete an GraalVM?
Erstellen Sie einen einfachen Webserver mit der Java-Standardbibliothek com.sun.net.httpserver
Vergleich der WEB-Anwendungsentwicklung mit Rails und Java Servlet + JSP
Untersuchen Sie die Systeminformationen der AWS Lambda-Betriebsumgebung in Java
[Java] Ordnen Sie die Daten des vergangenen Montags und Sonntags der Reihe nach an
Eine Geschichte über das Erreichen der League Of Legends-API mit JAVA
Rufen Sie die öffentliche URL der privaten Datei von Flickr in Java ab
Eine Geschichte, die mit der Einführung von Web Apple Pay zu kämpfen hatte
Zeigen Sie benutzerdefinierte Zeichen auf dem I2C 1602 LCD mit Raspberry Pi 3 und Java an
Lassen Sie uns eine TODO-App in Java 5 erstellen. Schalten Sie die Anzeige von TODO um
So überprüfen Sie den Inhalt der Java-Zeichenfolge mit fester Länge
Lesen Sie Druck und Temperatur von Raspberry Pi 3 & BMP180 mit Java ab
Fügen Sie nun "InfluxDB + Telegraf + Chronograf" in CentOS8 ein und versuchen Sie, die Temperatur mehrerer Raspberry pi4 zu steuern.
Exportieren (Ausgeben) einer großen Menge von CSVs, z. B. Protokollinformationen in der WEB-Anwendung, mit der Rails-Anwendung
[Swift] Vielmehr ist es sinnvoll, var zu vermeiden und nur dann mit let zu deklarieren, wenn die Zuweisung des Anfangswertes einen Zweig enthält.
Webanwendungsstruktur nach Java und Verarbeitungsablauf in der Präsentationsschicht
Erhöhen Sie dynamisch die Anzahl der Elemente in einem zweidimensionalen Java-Array (mehrdimensionales Array).
Eine Sammlung von Phrasen, die das "unterschiedliche Gefühl" von Java und JavaScript beeindruckt
Ein Hinweis zu den Unterschieden zwischen Schnittstellen und abstrakten Klassen in Java
Die Geschichte eines Game Launcher mit automatischer Ladefunktion [Java]
Lassen Sie uns das Ergebnis der Analyse von Java-Bytecode in einem Klassendiagramm ausdrücken
Zeichnen Sie mit MPAndroidChart gleichzeitig Balkendiagramm und Liniendiagramm
Anmerkung: [Java] Wenn sich eine Datei im überwachten Verzeichnis befindet, verarbeiten Sie sie.
Dies und das der Implementierung der zeitlichen Beurteilung von Daten in Java
Verwenden Sie Docker-Compose, um Ihre Lieblings-IP im Host-Netzwerk anzugeben und zu starten.
Beispielprogramm, das den Hashwert einer Datei in Java zurückgibt
Finden Sie das Maximum und Minimum der fünf in Java eingegebenen Zahlen
Überprüfen Sie den MX-Eintrag der E-Mail-Adresse mit Java und die Domain
Ich habe versucht, eine Webanwendung zu erstellen, die Tweets mit einer Vue-Word-Cloud durchsucht und die Tendenz untersucht, was im zugehörigen Profil geschrieben steht
Holen Sie sich das Ergebnis von POST in Java