Représentez graphiquement les informations du capteur de Raspberry Pi en Java et vérifiez-les avec un navigateur Web

introduction

J'ai enregistré en continu les informations du capteur de température / humidité et du capteur de pression connectés au Raspberry Pi 3 dans la base de données, je les ai graphiquement et affichées sur le navigateur Web d'un autre PC ou smartphone. Le langage de programmation utilise Java.

History Graph

DHT11 et BMP180 ont été utilisés pour le capteur de température / humidité et le capteur de pression.

DHT11
(Capteur de température / humidité)
BMP180
(Capteur de pression / température)
DHT11 BMP180

Préparation

Les environnements matériels et logiciels utilisés sont ceux présentés dans les articles suivants.

Représentez graphiquement les informations du capteur de Raspberry Pi et préparez un environnement qui peut être vérifié avec un navigateur Web

Lorsque l'environnement est prêt, installez le capteur comme indiqué dans le schéma de câblage ci-dessous. La résistance était spécifiée comme 5KΩ sur la fiche technique, mais je ne l'avais pas, alors je l'ai remplacée par 10KΩ (il ne semble y avoir aucun problème).

配線図

(Matériel de référence) Fiche technique DHT11 / Fiche technique BMP180 -DS000-09.pdf)

Créer une base de données

Toutes les opérations suivantes sont effectuées par l'utilisateur pi.

Tout d'abord, créez une base de données pour enregistrer les données de température / humidité et de pression. La base de données utilise MySQL installé dans l'article lié ci-dessus.

Dans l'exemple ci-dessous, raspberrypi est spécifié comme nom de base de données, mais vous pouvez spécifier n'importe quel nom (une partie de la sortie est omise).

$ mysql -p
Enter password:

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

Une fois la base de données créée, créez-y les tables. Dans l'exemple suivant, l'atmosphère de la table est créée et les colonnes id, datetime, température, humidité et pression sont créées. Vous pouvez également spécifier n'importe quel nom descriptif ici.

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

Enregistrement des données

Dans le répertoire webapps de Tomcat, créez un répertoire pour placer les programmes et les servlets pour l'enregistrement des données.

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

Créez le code source suivant dans ce répertoire de classes pour lire les informations du capteur et les enregistrer dans la base de données.

Les trois derniers des quatre fichiers servent à lire les informations de chaque capteur. Veuillez copier chacun de ces articles à partir des articles d'introduction suivants.

DHT11.java / DHT11Result.java Lire la température / l'humidité de Raspberry Pi 3 et DHT11 avec Java

BMP180.java Lecture de la pression et de la température depuis Raspberry Pi 3 et BMP180 avec 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();
        }
    }
}

La valeur à écrire dans la base de données est spécifiée dans la partie suivante. Si vous souhaitez utiliser un autre capteur, vous pouvez spécifier la valeur de lecture sous la forme d'un double type dans les parties résultat.température, résultat.humidité et pression.

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

Créez également un fichier de propriétés ambient.properties au même emplacement. Enregistrez les noms que vous spécifiez pour la base de données, la table et la colonne créées dans ce fichier. Spécifiez également l'utilisateur et le mot de passe pour accéder à MySQL.

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

Le dernier jfreechart.chartfile = spécifie où et le nom de fichier pour placer l'image graphique créée par le servlet.

Lorsque vous êtes prêt, compilez et exécutez le code source.

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

Après avoir exécuté le programme, assurez-vous que les informations extraites du capteur sont écrites dans la base de données.

$ 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

Si vous souhaitez supprimer l'enregistrement créé dans le test, ou si vous souhaitez supprimer la table ou la base de données elle-même, utilisez l'instruction SQL suivante. Veuillez noter que la suppression sera supprimée rapidement sans aucune confirmation.

une fonction Instruction SQL
Supprimer tous les enregistrements du tableau USE database_name
TRUNCATE TABLE table_name;
Supprimer la table USE database_name
DROP TABLE table_name;
Supprimer la base de données DROP DATABASE database_name;

Exécutez régulièrement ce programme à partir de cron pour stocker les informations du capteur dans la base de données. Créez le script shell suivant ambient.sh dans le répertoire ~ / apache-tomcat-9.0.6 / webapps / atmosphere et définissez les droits d'accès.

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

Définissez ce script shell dans crontab et vous êtes prêt à partir. On vous demandera quel éditeur utiliser la première fois que vous démarrez crontab, mais nano est recommandé sauf si vous avez une raison spécifique.

$ 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

Ajoutez ce qui suit à la fin du fichier ouvert dans l'éditeur. Ce paramètre lance le script shell à 0 minute toutes les heures. Le programme créé cette fois est créé en supposant que les données seront enregistrées à 0 minute toutes les heures.

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

Vous pouvez vérifier les paramètres avec crontab -l.

Créer un graphique

Revenez au répertoire des classes et créez le servlet AtmosphereChart.java, qui lit les données de la base de données et crée l'image graphique.

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 );
    }
}

Compilez le code source pour créer un fichier de classe.

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

Pour la programmation à l'aide de JFreeChart, je me suis référé à l'article suivant.

(Article de référence)

Créer un graphique avec JFreeChart

Créez le fichier suivant web.xml sous ~ / apache-tomcat-9.0.6 / webapps / atmosphere / WEB-INF pour définir le nom et la méthode d'appel de ce servlet.

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>

Enfin, placez les deux fichiers HTML index.html et result.html sous ~ / apache-tomcat-9.0.6 / webapps / atmosphere.

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>

Ceci termine tous les paramètres. Les fichiers suivants sont créés sous ~ / apache-tomcat-9.0.6 / webapps / atmosphere /.

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

Affichage du graphique

Spécifiez les éléments suivants dans l'URL pour afficher le graphique.

http://[adresse IP ou localhost]:8080/atmosphere/

Les données du jour précédent sont représentées graphiquement à partir des dernières données. Si vous souhaitez modifier la période d'affichage, sélectionnez la période dans les boutons radio en bas de la page et cliquez sur le bouton OK. Les données sont collectées et représentées graphiquement selon les règles suivantes en fonction de la période sélectionnée afin que le graphique ne soit pas compliqué.

Période sélectionnée Données à récupérer
1 Day / 2 Days À l'heure
3 Days Toutes les 2 heures (même heures)
7 Days Toutes les 3 heures (0:00, 3:00, 6:00 ...)
30 Days 12h00 tous les jours
90 Days Tous les deux jours (1er, 3, 5 ...) 12h00
180 Days Tous les 4 jours (1er, 5, 9 ...) à 12h00
360 Days Tous les 8 jours (1er, 9, 17 ...) à 12h00

Par conséquent, même si vous sélectionnez 90 jours, par exemple, le graphique linéaire peut ne pas s'afficher s'il n'y a pas suffisamment de données pour 90 jours ou si aucune donnée ne remplit les conditions ci-dessus.

Un problème connu est que la sélection d'une période et le fait de cliquer sur OK ne mettent pas à jour le graphique. Cela semble être dû au fait que l'image qui reste dans le cache du navigateur est affichée (le fichier image est correctement mis à jour sur Raspberry Pi), mais dans ce cas, sélectionnez à nouveau la période et cliquez à nouveau sur OK.

Recommended Posts

Représentez graphiquement les informations du capteur de Raspberry Pi en Java et vérifiez-les avec un navigateur Web
Communication socket avec un navigateur Web utilisant Java et JavaScript ②
Communication socket avec un navigateur Web utilisant Java et JavaScript ①
Traitez le mouvement détecté par le capteur humain HC-SR501 avec Raspberry Pi 3 et Java
Construisez un NAS avec la fonction DLNA à la vitesse d'une seconde avec Raspberry Pi et Docker Compose
Générez un numéro de série avec TableGenerator of Hibernate (JPA) et stockez-le dans l'ID de String.
L'histoire de l'oubli de fermer un fichier en Java et de l'échec
J'ai écrit une fonction Lambda en Java et l'ai déployée avec SAM
[Java] Affiche le résultat de ffprobe -show_streams dans JSON et mappe-le à un objet dans Jackson
Créer un CSR avec des informations étendues en Java
Mesurer la taille d'un dossier avec Java
Obtenez des informations vidéo YouTube avec Retrofit et conservez-les dans l'application Android.
[Java] Est-il inutile de vérifier "l'identité" dans l'implémentation de la méthode equals ()?
Valider le jeton d'ID d'un utilisateur authentifié par AWS Cognito en Java
Créez une image de conteneur pour l'arm64 de Kibana et enregistrez-la dans le registre de conteneurs GitHub. Démarrez Elastic Stack avec Docker Compose sur Raspberry Pi 4 (64 bits)
[Java] Informations entières des caractères du fichier texte acquises par la méthode read ()
[Java] Découpez une partie de la chaîne de caractères avec Matcher et des expressions régulières
Essayez de numériser, d'analyser et de transmettre la télécommande du climatiseur Mitsubishi avec Raspberry Pi
Un programme (Java) qui génère la somme des nombres pairs et impairs dans un tableau
L'histoire de la création d'une version Java du serveur Minecraft avec GCP (et également de la création d'une liste blanche)
Jusqu'à ce que vous construisiez un projet écrit scala avec Maven et que vous l'exécutiez avec la commande scala.
Enregistrez le téléviseur compatible DLNA dans l'inventaire SORACOM et utilisez la console Web
Une explication rapide des cinq types de statique Java
Vérifiez la dépendance d'un artefact maven spécifique dans Coursier
Agrégation de fenêtres de données de capteurs avec Apache Flink et Java 8
Commande pour vérifier le nombre et l'état des threads Java
Vérifier le fonctionnement de deux rôles avec une application de chat
Trouvez le nombre de jours dans un mois avec Kotlin
[Rails] Obtenez access_token au moment de l'authentification Twitter avec Sorcery et enregistrez-le dans la base de données
Parmi les trois serveurs Web embarqués Java, Tomcat, Jetty et Undertow, lequel fonctionnait sur GraalVM?
Créez un serveur Web simple avec la bibliothèque standard Java com.sun.net.httpserver
Comparaison du développement d'applications WEB avec Rails et Java Servlet + JSP
Examiner les informations système de l'environnement d'exploitation AWS Lambda en Java
[Java] Obtenez les dates des derniers lundi et dimanche dans l'ordre
Une histoire sur l'utilisation de l'API League Of Legends avec JAVA
Obtenez l'URL publique du fichier privé de Flickr en Java
Une histoire qui a eu du mal avec l'introduction de Web Apple Pay
Afficher les caractères définis par l'utilisateur sur l'écran LCD I2C 1602 avec Raspberry Pi 3 et Java
Créons une application TODO en Java 5 Changer l'affichage de TODO
Comment vérifier le contenu de la chaîne de caractères java de longueur fixe
Lire la pression et la température de Raspberry Pi 3 et BMP180 avec Java
Maintenant, mettez "InfluxDB + Telegraf + Chronograf" dans CentOS8 et essayez de contrôler la température de plusieurs Raspberry pi4.
Exporter (sortie) une grande quantité de csv comme les informations de journal sur l'application WEB avec l'application Rails
[Swift] Au contraire, il est significatif d'éviter var et de le déclarer avec let uniquement lorsqu'il y a une branche dans l'affectation de la valeur initiale.
Structure de l'application Web par Java et flux de traitement dans la couche de présentation
Augmenter dynamiquement le nombre d'éléments dans un tableau bidimensionnel Java (tableau multidimensionnel)
Une collection de phrases qui impressionne le "sentiment différent" de Java et de JavaScript
Une note sur les différences entre les interfaces et les classes abstraites en Java
L'histoire de la création d'un lanceur de jeu avec une fonction de chargement automatique [Java]
Exprimons le résultat de l'analyse du code d'octet Java dans un diagramme de classes
Dessinez un graphique à barres et un graphique linéaire en même temps avec MPAndroidChart
Mémo: [Java] Si un fichier se trouve dans le répertoire surveillé, traitez-le.
Ceci et cela de la mise en œuvre du jugement en temps réel des dates en Java
Utilisez docker-compose pour spécifier votre adresse IP préférée sur le réseau hôte et lancez-la.
Exemple de programme qui renvoie la valeur de hachage d'un fichier en Java
Trouvez le maximum et le minimum des cinq nombres saisis en Java
Vérifiez l'enregistrement MX de l'adresse e-mail avec java et vérifiez le domaine
J'ai essayé de créer une application Web qui recherche les tweets avec vue-word cloud et examine la tendance de ce qui est écrit dans le profil associé
Obtenez le résultat de POST en Java