Graph the sensor information of Raspberry Pi in Java and check it with a web browser

Introduction

I continuously recorded the information of the temperature / humidity sensor and barometric pressure sensor connected to Raspberry Pi 3 in the database, graphed it, and displayed it on the Web browser of another PC or smartphone. The programming language uses Java.

History Graph

DHT11 and BMP180 were used for the temperature / humidity sensor and barometric pressure sensor.

DHT11
(Temperature / humidity sensor)
BMP180
(Atmospheric pressure / temperature sensor)
DHT11 BMP180

Preparation

The hardware and software environment used are those introduced in the following articles.

Graph the sensor information of Raspberry Pi and prepare an environment that can be checked with a Web browser

When the environment is ready, install the sensor as shown in the wiring diagram below. The resistor was specified as 5KΩ in the data sheet, but I didn't have it, so I replaced it with 10KΩ (there seems to be no problem).

配線図

(Reference material) DHT11 datasheet / BMP180 datasheet -DS000-09.pdf)

Creating a database

All of the following operations are performed by the pi user.

First of all, create a database to record temperature / humidity and barometric pressure data. The database uses MySQL installed in the article linked above.

In the example below, raspberrypi is specified as the database name, but you can specify any name (some of the output is omitted).

$ mysql -p
Enter password:

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

Once the database is created, create the tables in it. In the following example, the table atmosphere is created, and the columns id, datetime, temperature, humidity, and pressure are created. You can also specify any name that is easy to understand.

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

Data recording

Under the webapps directory of Tomcat, create a directory for placing programs and servlets for recording data.

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

Create the following source code in this classes directory to read the information from the sensor and record it in the database.

The bottom three of the four files are for reading information from each sensor. Please copy each of these from the following introductory articles.

DHT11.java / DHT11Result.java Read temperature / humidity with Java from Raspberry Pi 3 & DHT11

BMP180.java Read barometric pressure and temperature from Raspberry Pi 3 & BMP180 with 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();
        }
    }
}

The value to be written to the database is specified in the following part. If you want to use another sensor, you can specify the read value as double type in the result.temperature, result.humidity, and pressure parts.

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

Also, create a property file atmosphere.properties in the same location. Register the names specified for the created database, table, and column in this file. Also specify the user and password to access 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

The final jfreechart.chartfile = specifies where and the filename to put the graph image created by the Servlet.

When you're ready, compile and run the source code.

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

After running the program, make sure that the information retrieved from the sensor is written to the database.

$ 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

If you want to delete the record created in the test, or if you want to delete the table or database itself, use the following SQL statement. Please note that the deletion will be deleted quickly without any confirmation.

function SQL statement
Delete all records in the table USE database_name
TRUNCATE TABLE table_name;
Delete table USE database_name
DROP TABLE table_name;
Delete database DROP DATABASE database_name;

Run this program from cron on a regular basis to store sensor information in the database. Create the following shell script atmosphere.sh in the directory ~ / apache-tomcat-9.0.6 / webapps / atmosphere and set the access right.

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

Set this shell script in crontab and you're ready to go. You will be asked which editor to use when you first start crontab, but nano is recommended unless you have a specific reason.

$ 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

Add the following to the end of the file opened in the editor: This setting launches a shell script at 0 minutes every hour. The program created this time is created on the assumption that data will be recorded at 0 minutes every hour.

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

You can check the settings with crontab -l.

Creating a graph

Go back to the classes directory and create the Servlet AtmosphereChart.java, which reads the data from the database and creates the graph image.

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

Compile the source code to create a class file.

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

For programming using JFreeChart, I referred to the following article.

(Reference article)

Create a graph with JFreeChart

Create the following file web.xml under ~ / apache-tomcat-9.0.6 / webapps / atmosphere / WEB-INF to define the name and calling method of this 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>

Finally, place the two HTML files index.html and result.html under ~ / 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>

This completes all the settings. The following files are created under ~ / 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

Graph display

Specify the following in the URL to display the graph.

http://[ip address or localhost]:8080/atmosphere/

The data for the past day is graphed from the latest data. If you want to change the display period, select the period from the radio buttons at the bottom of the page and click the OK button. Data is picked up and graphed according to the following rules according to the selected period so that the graph does not become complicated.

Selected period Data to be picked up
1 Day / 2 Days Hourly
3 Days Every 2 hours (even number)
7 Days Every 3 hours (0:00, 3:00, 6:00 ...)
30 Days 12:00 every day
90 Days Every other day (1st, 3rd, 5th ...) at 12:00
180 Days Every 4 days (1st, 5th, 9th ...) at 12:00
360 Days Every 8 days (1st, 9th, 17th ...) at 12:00

Therefore, even if you select 90 Days, for example, the line graph may not be displayed if there is not enough data for 90 days or if there is no data that meets the above conditions.

A known issue is that selecting a time period and clicking OK does not update the graph. This seems to be because the image that remains in the browser cache is displayed (the image file is updated correctly on the Raspberry Pi), but in this case, select the period again and click OK again.

Recommended Posts

Graph the sensor information of Raspberry Pi in Java and check it with a web browser
Socket communication with a web browser using Java and JavaScript ②
Socket communication with a web browser using Java and JavaScript ①
Process the motion detected by the motion sensor HC-SR501 with Raspberry Pi 3 & Java
Build a NAS with DLNA function at the speed of a second with Raspberry Pi and Docker Compose
Generate a serial number with Hibernate (JPA) TableGenerator and store it in the Id of String.
The story of forgetting to close a file in Java and failing
I wrote a Lambda function in Java and deployed it with SAM
[Java] Output the result of ffprobe -show_streams in JSON and map it to an object with Jackson
Create a CSR with extended information in Java
Measure the size of a folder in Java
Get YouTube video information with Retrofit and keep it in the Android app.
[Java] Is it unnecessary to check "identity" in the implementation of the equals () method?
Validate the identity token of a user authenticated with AWS Cognito in Java
Create a container image for arm64 of Kibana and register it in GitHub Container Registry. Start Elastic Stack with Docker Compose on Raspberry Pi 4 (64bit)
[Java] Integer information of characters in a text file acquired by the read () method
[Java] Cut out a part of the character string with Matcher and regular expression
Try scanning, analyzing, and transmitting the remote control of Mitsubishi's air conditioner with Raspberry Pi
A program (Java) that outputs the sum of odd and even numbers in an array
The story of building a Java version of Minecraft server with GCP (and also set a whitelist)
Until you build a project described in scala with Maven and execute it with the scala command.
Register a DLNA compatible TV in SORACOM Inventory and operate it from the Web console
A quick explanation of the five types of static in Java
Check the dependency of a specific maven artifact in Coursier
Window aggregation of sensor data with Apache Flink and Java 8
Command to check the number and status of Java threads
Check the operation of two roles with a chat application
Find the number of days in a month with Kotlin
[Rails] Get access_token at the time of Twitter authentication with Sorcery and save it in DB
Of the three Java embedded web servers, Tomcat, Jetty, and Undertow, which one worked with GraalVM?
Create a simple web server with the Java standard library com.sun.net.httpserver
Comparison of WEB application development with Rails and Java Servlet + JSP
Examine the system information of AWS Lambda operating environment in Java
[Java] Get the dates of the past Monday and Sunday in order
A story about hitting the League Of Legends API with JAVA
Get the public URL of a private Flickr file in Java
A story that struggled with the introduction of Web Apple Pay
Display user-defined characters on the I2C 1602 LCD with Raspberry Pi 3 & Java
Let's create a TODO application in Java 5 Switch the display of TODO
How to check for the contents of a java fixed-length string
Read barometric pressure and temperature with Java from Raspberry Pi 3 & BMP180
Now, put "InfluxDB + Telegraf + Chronograf" in CentOS8 and try to control the temperature of multiple Raspberry pi4.
Perform a large amount of csv export (output) of log information etc. on the WEB application with Rails application
[Swift] Rather, it is meaningful to avoid var and declare it with let only when there is a branch in the assignment of the initial value.
Web application structure by Java and processing flow in the presentation layer
Dynamically increase the number of elements in a Java 2D array (multidimensional array)
A collection of phrases that impresses the "different feeling" of Java and JavaScript
Make a daily build of the TOPPERS kernel with Gitlab and Docker
A note on the differences between interfaces and abstract classes in Java
The story of making a game launcher with automatic loading function [Java]
Let's express the result of analyzing Java bytecode with a class diagram
Draw a bar graph and a line graph at the same time with MPAndroidChart
Memo: [Java] If a file is in the monitored directory, process it.
This and that of the implementation of date judgment within the period in Java
Specify the favorite IP of the host network with docker-compose and start it
Sample program that returns the hash value of a file in Java
Find the maximum and minimum of the five numbers you entered in Java
Check the domain by checking the MX record of the email address with java
I tried to make a web application that searches tweets with vue-word cloud and examines the tendency of what is written in the associated profile
Get the result of POST in Java
Put Kanban in Docker of Raspberry Pi 3