Develop real-time environment monitoring with vert.x and echarts

This article aims to develop a real-time environment monitoring demo with vert.x and echarts.

vert.x see http://vertx.io

ehcars see http://echarts.baidu.com/index.html

The whole business process is relatively simple, that is, the page communicates with the back-end web server through sockJs, and then the back-end server pushes data to the page in real time.

The page code is as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript" src="/js/jquery-easyui-1.5.2/jquery.min.js"></script>
<script type="text/javascript" src="/js/sockjs.min.js"></script>
<script type="text/javascript" src="/js/vertx-eventbus.min.js"></script>
<script type="text/javascript" src="/js/baidu/echarts-all.js"></script>
</head>

<body>
	<div><b>Environmental real-time monitoring:</b></div>
	<br>
	<table width="800">
		<tr>
			<td><font color="blue">温度</font></td>
			<td><font color="blue">湿度</font></td>
			<td><font color="blue">CO2</font></td>
			<td><font color="blue">NH3</font></td>
		</tr>
		<tr>
			<td><div id="T"></div></td>
			<td><div id="H"></div></td>
			<td><div id="CO2"></div></td>
			<td><div id="NH3"></div></td>
		</tr>
	</table>
	<br>
	<table>
		<tr>
			<td><div id="T_chart" style="width: 250px;height:250px;"></div></td>
			<td><div id="T_chart_line" style="width: 500px;height:250px;"></div></td>
			<td><div id="H_chart" style="width: 250px;height:250px;"></div></td>
			<td><div id="H_chart_line" style="width: 500px;height:250px;"></div></td>
		</tr>
		<tr>
			<td><div id="CO2_chart" style="width: 250px;height:250px;"></div></td>
			<td><div id="CO2_chart_line" style="width: 500px;height:250px;"></div></td>
			<td><div id="NH3_chart" style="width: 250px;height:250px;"></div></td>
			<td><div id="NH3_chart_line" style="width: 500px;height:250px;"></div></td>
		</tr>
	</table>

	<script>
		// dash board---------------------------------------------- ---------------------
		var myChart_T = echarts.init(document.getElementById("T_chart"));
		var option_T = {
		    series : [
		        {
		            name:'temperature',
		            type:'gauge',
		            detail : {formatter:'{value}℃'},
		            data:[{value: 50, name: '温度'}],
		            min: 0,
		            max:50,
		            axisLine:{
	            	    show: true,
	            	    //Specify a color for each segment (in this example, the temperature is divided into three segments: low, suitable, and high), format: percentage, color.
	            	    lineStyle: {
	            	        color: [
	            	            [0.3, '#228b22'],
	            	            [0.7, '#48b'],
	            	            [1, '#ff4500']
	            	        ],
	            	        width: 20
	            	    }
		            },
		            splitLine:{
		            	length :20
		            }
		        }
		    ]
		};
		myChart_T.setOption(option_T);
		
		var myChart_H = echarts.init(document.getElementById("H_chart"));
		var option_H = {
		    series : [
		        {
		            name:'humidity',
		            type:'gauge',
		            detail : {formatter:'{value}%'},
		            data:[{value: 50, name: '湿度'}],
		            axisLine:{
	            	    show: true,
	            	    lineStyle: {
	            	        color: [
	            	            [0.4, '#228b22'],
	            	            [0.75, '#48b'],
	            	            [1, '#ff4500']
	            	        ],
	            	        width: 20
	            	    }
		            },
		            splitLine:{
		            	length :20
		            }
		        }
		    ]
		};
		myChart_H.setOption(option_H);
		
		var myChart_CO2 = echarts.init(document.getElementById("CO2_chart"));
		var option_CO2 = {
		    series : [
		        {
		            name:'CO2',
		            type:'gauge',
		            detail : {formatter:'{value}%'},
		            data:[{value: 0.05, name: 'CO2'}],
		            min: 0,
		            max:0.15,
		            splitNumber:5,
		            axisLine:{
	            	    show: true,
	            	    lineStyle: {
	            	        color: [
	            	            [0.33, '#228b22'],
	            	            [0.66, '#48b'],
	            	            [1, '#ff4500']
	            	        ],
	            	        width: 20
	            	    }
		            },
		            splitLine:{
		            	length :20
		            }
		        }
		    ]
		};
		myChart_CO2.setOption(option_CO2);
		
		var myChart_NH3 = echarts.init(document.getElementById("NH3_chart"));
		var option_NH3 = {
		    series : [
		        {
		            name:'NH3',
		            type:'gauge',
		            detail : {formatter:'{value}%'},
		            data:[{value: 0.05, name: 'NH3'}],
		            min: 0,
		            max:0.005,
		            splitNumber:10,
		            axisLine:{
	            	    show: true,
	            	    lineStyle: {
	            	        color: [
	            	            [0.9, '#48b'],
	            	            [1, '#ff4500']
	            	        ],
	            	        width: 20
	            	    }
		            },
		            splitLine:{
		            	length :20
		            }
		        }
		    ]
		};
		myChart_NH3.setOption(option_NH3);
		
		var count = 0;
		var date = [];
		
		// line chart---------------------------------------------- ------------------------------------
		var myChart_T_line = echarts.init(document.getElementById("T_chart_line"));
		var data_T = [];
		var option_T_line = {
		    xAxis: A
		        type: 'category',
		        boundaryGap: false,
		        date: date
		    },
		    yAxis: {
		        min: 0,
		        max:50,
		        type: 'value'
		    },
		    series: [
		        {
		            name:'meanRate',
		            type:'line',
		            smooth:true,
		            areaStyle: {
		                normal: {}
		            },
		            data: data_T
		        }
		    ]
		};
		myChart_T_line.setOption(option_T_line);
		myChart_T_line.hideLoading();
		
		var myChart_H_line = echarts.init(document.getElementById("H_chart_line"));
		var data_H = [];
		var option_H_line = {
		    xAxis: A
		        type: 'category',
		        boundaryGap: false,
		        date: date
		    },
		    yAxis: {
		        min: 0,
		        max:100,
		        type: 'value'
		    },
		    series: [
		        {
		            name:'meanRate',
		            type:'line',
		            smooth:true,
		            areaStyle: {
		                normal: {}
		            },
		            data: data_H
		        }
		    ]
		};
		myChart_H_line.setOption(option_H_line);
		myChart_H_line.hideLoading();
		
		var myChart_CO2_line = echarts.init(document.getElementById("CO2_chart_line"));
		var data_CO2 = [];
		var option_CO2_line = {
		    xAxis: A
		        type: 'category',
		        boundaryGap: false,
		        date: date
		    },
		    yAxis: {
		        min: 0,
		        max:0.20,
		        type: 'value'
		    },
		    series: [
		        {
		            name:'meanRate',
		            type:'line',
		            smooth:true,
		            areaStyle: {
		                normal: {}
		            },
		            data: data_CO2
		        }
		    ]
		};
		myChart_CO2_line.setOption(option_CO2_line);
		myChart_CO2_line.hideLoading();
		
		var myChart_NH3_line = echarts.init(document.getElementById("NH3_chart_line"));
		var data_NH3 = [];
		var option_NH3_line = {
		    xAxis: A
		        type: 'category',
		        boundaryGap: false,
		        date: date
		    },
		    yAxis: {
		        min: 0,
		        max:0.007,
		        type: 'value'
		    },
		    series: [
		        {
		            name:'meanRate',
		            type:'line',
		            smooth:true,
		            areaStyle: {
		                normal: {}
		            },
		            data: data_NH3
		        }
		    ]
		};
		myChart_NH3_line.setOption(option_NH3_line);
		myChart_NH3_line.hideLoading();
		
		// webSocket------------------------------------------------------------------------
		var eb = new EventBus("/eventbus/");
		eb.onopen = function() {
			eb.registerHandler("chartServer.to.client", function(err, msg) {
				$('#T').text(msg.body.T + "\n");
				$('#H').text(msg.body.H + "\n");
				$('#CO2').text(msg.body.CO2 + "\n");
				$('#NH3').text(msg.body.NH3 + "\n");
				
				
				option_T.series[0].data[0].value = msg.body.T;
			    myChart_T.setOption(option_T, true);
			    
			    option_H.series[0].data[0].value = msg.body.H;
			    myChart_H.setOption(option_H, true);
			    
			    option_CO2.series[0].data[0].value = msg.body.CO2;
			    myChart_CO2.setOption(option_CO2, true);
			    
			    option_NH3.series[0].data[0].value = msg.body.NH3;
			    myChart_NH3.setOption(option_NH3, true);

			    date.push(msg.body.time);
			    count = count + 1;
			    
			    if(count > 100){
			        date.shift();		        
			        data_T.shift();
			        data_H.shift();
			        data_CO2.shift();
			        data_NH3.shift();
			    }
			    
			    data_T.push(msg.body.T);
			    data_H.push(msg.body.H);
			    data_CO2.push(msg.body.CO2);
			    data_NH3.push(msg.body.NH3);
			    
			    myChart_T_line.setOption(option_T_line, true);	
			    myChart_H_line.setOption(option_H_line, true);	
			    myChart_CO2_line.setOption(option_CO2_line, true);
			    myChart_NH3_line.setOption(option_NH3_line, true);
			});
		};
		
	</script>
</body>
</html>

 The background code is as follows:

package com.wof.realtimesca.chart;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.handler.sockjs.BridgeEventType;
import io.vertx.ext.web.handler.sockjs.BridgeOptions;
import io.vertx.ext.web.handler.sockjs.PermittedOptions;
import io.vertx.rxjava.core.AbstractVerticle;
import io.vertx.rxjava.core.eventbus.EventBus;
import io.vertx.rxjava.core.eventbus.Message;
import io.vertx.rxjava.core.eventbus.MessageConsumer;
import io.vertx.rxjava.ext.web.Router;
import io.vertx.rxjava.ext.web.handler.StaticHandler;
import io.vertx.rxjava.ext.web.handler.sockjs.SockJSHandler;
import rx.Observable;
import rx.Subscription;


public class ChartVerticle extends AbstractVerticle {
	
	private static final Logger logger = LoggerFactory.getLogger(ChartVerticle.class);

	public void start() throws Exception {
		
		// router
		Router router = Router.router(vertx);

		// event bus
		BridgeOptions bridgeOptions = new BridgeOptions()
				.addInboundPermitted(new PermittedOptions().setAddress("tcpServer.to.chartServer"))
				.addOutboundPermitted(new PermittedOptions().setAddress("chartServer.to.client"));
				
		SockJSHandler sockJSHandler = SockJSHandler.create(vertx).bridge(bridgeOptions, event -> {
			if (event.type() == BridgeEventType.SOCKET_CREATED) {
				logger.info("created from socket.");
			} else if (event.type() == BridgeEventType.SOCKET_CLOSED){
				logger.info("a socket closed.");
			}
			event.complete(true);
		});
		
		sockJSHandler.socketHandler(sockJSSocket -> {
			sockJSSocket.exceptionHandler(handler -> {
				logger.error(handler.getCause().getMessage());
			});
		});
		
		router.route("/eventbus/*").handler(sockJSHandler);
		router.route().handler(StaticHandler.create());//This static resource handler without any prefix must be placed behind sockJSHandler; otherwise, jsSocket cannot communicate with the background.
		
		EventBus eventBus = vertx.eventBus();
		
		MessageConsumer<String> consumer = eventBus.consumer("tcpServer.to.chartServer");
		Observable<Message<String>> observable = consumer.toObservable();
		//message结构(json): {"type":"rec","address":"char.to.client.push","body":"welcome!"}
		Subscription sub = observable.subscribe(msg -> {
			eventBus.publish("chartServer.to.client", msg.body());
		});
		
		// http server
		vertx.createHttpServer().requestHandler(router::accept).listen(8090);
		
		// Simulate the sensor to send data to the server	
		SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
		vertx.setPeriodic (500, t -> {
			JsonObject jsonData = new JsonObject();
			String date = sdf.format(GregorianCalendar.getInstance().getTime());
			jsonData.put("time", date);
			
			String data = getDataValue(28, 30, 0, 1);//温度			
			jsonData.put("T", data);
			
			data = getDataValue(70, 75, 0, 1);//湿度
			jsonData.put("H", data);
			
			data = getDataValue(5, 10, 2, 2);//CO2 0.05—0.1%
			jsonData.put("CO2", data);
			
			data = getDataValue(1, 4, 3, 4);//NH3 < 0.004﹪
			jsonData.put("NH3", data);
			
			vertx.eventBus().publish("tcpServer.to.chartServer", jsonData);
		});
	}
	
	/**
	 * Generate random decimals
	 *
	 * @param min
	 * @param max
	 * @param count number of decimal places
	 * @param zeroCount the number of decimal places to keep
	 * @return
	 */
	private String getDataValue(int min, int max, int count, int zeroCount){
		double d = (Math.random() * (max - min + 1) + min);
		
		for(int i = 1; i <= count ; i++){
			d /= 10;
		}
		
		String zero = "0.";
		if(zeroCount < 1)
			zero = "0.0";
		else {
			for(int i = 1; i <= zeroCount; i++){
				zero += "0";
			}
		}
		
		DecimalFormat Dformat = new DecimalFormat(zero);
		String val = Dformat.format(d);
		
		return val;
	}
}

 

Effect picture:

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326250612&siteId=291194637