目录
前言
? ? ? ? ?单片机端
? ? ? ? ?服务器端?
? ? ? ? ?网页端
? ? ? ? ?成果展示
? ? ? ? ?源码下载
前言
作者:齐鲁师范学院18云计算孙浩
开发环境:win11, Linux,Arduino ide, PyCharm 2020.2 x64, IntelliJ IDEA 2021.1.1 x64,linux
软件:Tomcat,mysql,navicat,花生壳
硬件:esp8266单片机,dht11温湿度传感器,调试线
技术:jsp,echarts,ajax,udp,wlan,java,python.c,flask
实现思路:1.单片机将传感器数据读出,通过wlan网络使用udp协议发送至服务器端
? ? ? ? ? ? ? ? ? 2.服务器端对数据进行处理,将之写入mysql数据库中
? ? ? ? ? ? ? ? ?3.web端读取数据库中数据,使用ajax技术异步加载至前端页面,以图表形式展示
单片机端
环境:Arduino IDE,esp8266单片机,DHT11温湿度传感器,路由器,UDP
开发语言:C
硬件连线图
?
完整代码
将以下代码下载至ESP8266 NodeMCU,即可完成硬件端的udp通信。 代码大致过程:初始化串口通信,将开发板配入有网的WIFI或热点,开始监听udp端口8888,将连接DHT11温湿度传感器的那个引脚设为输出模式。后无限循环采集温湿度湿度,与监听端口是否有收到请求信息的命令,若收到请求信息,则返回温湿度信息给发送请求信息命令端。
烧录过程:
开发板那选择开发板为NodeMCU,型号根据自己的开发板选择,后选择端口,烧入程序。具体过程可以CSDN搜一下,此处略过 。
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
#include <SPI.h>
#include <Wire.h>
#include<stdlib.h>
#include <dht11.h> //DHT11的头文件
//连入自己的家里的WIFI、热点
const char *ssid = "HONOR";//WIFI名
const char *password ="19990815";//密码
unsigned int UDPPort = 8888; //本地端口号
char packetBuffer1[255]; //buffer to hold incoming packet
char packetBuffer2[255];
char ReplyBuffer1[255] ;
// a string to send back
char ReplyBuffer2[] = "";
WiFiUDP Udp;
//温度传感器加载
dht11 DHT11;
#define DHT11_PIN 2 //DHT11引脚,实际接线接入开发板的D4
int tempera=0; //存放温度的变量
int humidity=0; //存放湿度的变量
// 复位或上电后运行一次:
void setup() {
//在这里加入初始化相关代码,只运行一次:
Serial.begin(115200); //初始化串口通信,并将波特率设置为115200
WiFi.mode ( WIFI_AP );//WIFI设为AP模式
WiFi.begin ( ssid, password );//连接WIFI热点
//Wait for connection
while ( WiFi.status() != WL_CONNECTED ) { //WIFI的连接状态
delay ( 500 );
Serial.print ( "." );//如果没有连通向串口发送.....
}
Serial.println ( "" );
Serial.print ( "Connected to " );
Serial.println ( ssid );
Serial.print ( "IP address: " );
Serial.println ( WiFi.localIP() );//返回获得的本机ip地址
Udp.begin(UDPPort);// 开始UDP端口侦听
pinMode(DHT11_PIN,OUTPUT);
Serial.println();
Serial.println("本地IP地址: " + WiFi.localIP().toString());//串口打印本地IP地址
}
//一直循环执行:
void loop() {
// 在这里加入主要程序代码,重复执行:
int packetSize = Udp.parsePacket();
/**获取温湿度,后在串口打印出数据**/
/**一定要有chk,不然不显示内容**/
int chk1 = DHT11.read(DHT11_PIN); //将读取到的值赋给chk
tempera=DHT11.temperature;
humidity=DHT11.humidity;
Serial.print("Temperature: ");
Serial.println(tempera);//串口打印温度
Serial.print("humidity: ");
Serial.println(humidity); //串口打印湿度
itoa(tempera, ReplyBuffer1, 10);
itoa(humidity, ReplyBuffer2, 10);
delay(500);
Serial.println("本地IP地址: " + WiFi.localIP().toString()); //串口打印本地IP地址
Serial.println("端口号: " + UDPPort); //串口打印端口号
/**如果接收到上位机发来的信息,就返回采集到温湿度数据给上位机**/
//UDP广播数据到达处理
if (packetSize) {
Serial.print("Receivedpacket of size ");
Serial.println(packetSize);
Serial.print("From");
IPAddress remoteIp =Udp.remoteIP();//获取远程广播包发送IP
Serial.print(remoteIp);
Serial.print(", port");
Serial.println(Udp.remotePort());
// 将到达的数据包读入packetBufffer1,packetBufffer2
int len1 =Udp.read(packetBuffer1, 255);
int len2 = Udp.read(packetBuffer2, 255);
if (len1 > 0) {
packetBuffer1[len1] =0;
}
if (len2 > 0) {
packetBuffer2[len2] =0;
}
Serial.println("Contents:");
Serial.println(packetBuffer1);
Serial.println(packetBuffer2);
// 回复信息给广播发送IP
Udp.beginPacket(Udp.remoteIP(),Udp.remotePort());
// strcat(ReplyBuffer2,ReplyBuffer1);
Udp.write(ReplyBuffer1);
Udp.write(ReplyBuffer2);
Udp.endPacket();
}
}
服务器端?
环境:IDEA,mysql,linux
开发语言:java
项目结构:
在IDEA新建中新建一个JSP项目,具体过程可以CSDN搜一下,此处略过?,完成后启动insert.jsp文件,即可
insert.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="UTF-8" %>
<%@ page import="java.sql.*"%>
<%@ page import="java.io.*,java.util.List,java.util.ArrayList" %>
<%@ page import="com.example.JSP4.*" %>
<%@page import="java.util.Date"%>
<%@page import="java.text.SimpleDateFormat"%>
<!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">
<title>IOT</title>
</head>
<body >
<%/** 获取当前时间 **/
Date d = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String now = df.format(d);%>
<%/** 获取温湿度 **/
String str;
int temperature=0;
int humidity=0;
udpsend t=new udpsend();
str=t.udptest() ;
temperature=Integer.parseInt(str.substring(0, 1));
humidity=Integer.parseInt(str.substring(1, 3));
temperature=temperature+20;
System.out.println("温度:" + temperature);
%>
<%
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://192.168.43.100:3306/mysql1"; //数据库名
String username = "root"; //数据库用户名
String password = "123456"; //数据库用户密码
System.out.println("数据库连接成功" );
Connection conn = DriverManager.getConnection(url, username, password); //连接状态
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
//sql插入数据的语句
String sql_insert = "insert into iot(temperature, humidity, date) values ('" + temperature + "','" + humidity + "','" + now + "')";
PreparedStatement pst = conn.prepareStatement(sql_insert);
System.out.println("数据插入成功" );
int rs = pst.executeUpdate();
} catch (SQLException throwables) {
throwables.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
%>
if(rs!=0){
/** 跳转index.jsp **/
<jsp:forward page="index.jsp"></jsp:forward>
}
catch(Exception e){
/** 出现异常时,输出异常 **/
out.println(e);
}
</body>
</html>
网页端
环境:pycharm,mysql,echarts
开发语言:python,html
项目结构:
新建一个flask项目,项目主要包括三个文件:app.py,score.html.movie.html
?运行app.py
app.py
import json
import time
from flask import Flask, render_template
import pymysql
app = Flask(__name__)
@app.route('/')
def index():
return render_template("score.html")
# @app.route('/index')
# def home():
# #return render_template("index.html")
# return index()
@app.route('/movie')
def movie():
datalist = []
con = pymysql.connect(
host='192.168.43.100',
port=3306,
user='root',
passwd='123456',
db='mysql1',
charset='utf8'
)
cur = con.cursor()
sql = "select * from iot"
data = cur.execute(sql)
result = cur.fetchall()
for item in result:
datalist.append(item)
cur.close()
cur.close()
print(datalist)
return render_template("movie.html", movies=datalist)
@app.route('/score', methods=['GET', 'POST'])
def score():
score = [] # 评分
num = [] # 每个评分所统计出的电影数量
num1 = []
# 转换成JSON数据格式
jsonData = {}
xdays = []
yvalues = []
tvalues = []
conn = pymysql.Connect(
host='192.168.43.100',
port=3306,
user='root',
passwd='123456',
db='mysql1',
charset='utf8'
)
cur = conn.cursor()
sql = "select * from iot"
data = cur.execute(sql)
result = cur.fetchall()
for data in result:
# xdays.append(str(data[0]))
xdays.append(data[0])
yvalues.append(data[1])
tvalues.append(str(data[2]))
print(xdays)
print(yvalues)
print(tvalues)
jsonData['xdays'] = xdays
jsonData['yvalues'] = yvalues
jsonData['tvalues'] = tvalues
for item in result:
score.append(item[0])
num.append(item[1])
num1.append(str(item[2]))
# json.dumps()用于将dict类型的数据转成str,因为如果直接将dict类型的数据写入json会发生报错,因此将数据写入时需要用到该函数。
j = json.dumps(jsonData)
cur.close()
conn.close()
return render_template("score.html",score= score,num=num,num1=num1,)
score.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<script src="static/assets/js/echarts.min.js"></script>
<script src="/static/assets/vendor/jquery/jquery.min.js"></script>
<title>温湿度数据动态展示</title>
<meta content="" name="descriptison">
<meta content="" name="keywords">
<!-- Favicons -->
<link href="static/assets/img/favicon.png" rel="icon">
<link href="static/assets/img/apple-touch-icon.png" rel="apple-touch-icon">
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i|Raleway:300,300i,400,400i,600,600i,700,700i,900" rel="stylesheet">
<!-- Vendor CSS Files -->
<link href="static/assets/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="static/assets/vendor/icofont/icofont.min.css" rel="stylesheet">
<link href="static/assets/vendor/boxicons/css/boxicons.min.css" rel="stylesheet">
<link href="static/assets/vendor/animate.css/animate.min.css" rel="stylesheet">
<link href="static/assets/vendor/venobox/venobox.css" rel="stylesheet">
<link href="static/assets/vendor/aos/aos.css" rel="stylesheet">
<!-- Template Main CSS File -->
<link href="static/assets/css/style.css" rel="stylesheet">
</head>
<body>
<!-- ======= Header ======= -->
<header id="header">
<div class="container">
<div class="logo float-left">
<h1 class="text-light"><a href="temp.html"><span>孙浩</span></a></h1>
<!-- Uncomment below if you prefer to use an image logo -->
<!-- <a href="temp.html"><img src="static/assets/img/logo.png" alt="" class="img-fluid"></a>-->
</div>
<nav class="nav-menu float-right d-none d-lg-block">
<ul>
{# <li class="active"><a href="/index">首页<i class="la la-angle-down"></i></a></li>#}
<li><a href="/movie">详细数据</a></li>
{# <li><a href="/country">国家</a></li>#}
<li><a href="/score">可视化展示</a></li>
{# <li><a href="/peopletop10">评论人数top10</a></li>#}
{# <li><a href="/presstime">出版年份</a></li>#}
{# <li><a href="/publisher">出版社</a></li>#}
{# <li><a href="/word">词云</a></li>#}
{# <li><a href="/team">团队</a></li>#}
</ul>
</nav><!-- .nav-menu -->
</div>
</header><!-- End Header -->
<!-- ======= Our Team Section ======= -->
<section id="team" class="team">
<div class="container">
<div class="section-title">
<h2>单片机温度湿度数据动态展示</h2>
</div>
<!-- ======= Counts Section ======= -->
<section class="counts section-bg">
<div class="container">
<!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
<div id="main" style="width: 100%;height:300px"></div>
</div>
</section><!-- End Counts Section -->
</div>
</section><!-- End Our Team Section -->
<script type="text/javascript">
var dom = document.getElementById("main");
var myChart = echarts.init(dom);
option=null
var option = {
title: {
text: '温湿度数据动态展示'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['温度', '湿度']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: {{num1|tojson}}
// data: ['温度', '湿度']
},
yAxis: {
type: 'value'
},
series: [
{
name: '温度',
type: 'line',
stack: 'Total',
data: {{ score }}
},
{
name: '湿度',
type: 'line',
stack: 'Total',
data: {{num}}
}
]
}
if (option && typeof option === "object") {
myChart.setOption(option, true);
}
</script>
<!-- ======= Footer ======= -->
<footer id="footer">
<div class="container">
<div class="copyright">
© Copyright <strong><span>孙浩</span></strong>. All Rights Reserved
</div>
</div>
</footer><!-- End Footer -->
<a href="#" class="back-to-top"><i class="icofont-simple-up"></i></a>
<!-- Vendor JS Files -->
<script src="static/assets/vendor/jquery/jquery.min.js"></script>
<script src="static/assets/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="static/assets/vendor/jquery.easing/jquery.easing.min.js"></script>
<script src="static/assets/vendor/php-email-form/validate.js"></script>
<script src="static/assets/vendor/jquery-sticky/jquery.sticky.js"></script>
<script src="static/assets/vendor/venobox/venobox.min.js"></script>
<script src="static/assets/vendor/waypoints/jquery.waypoints.min.js"></script>
<script src="static/assets/vendor/counterup/counterup.min.js"></script>
<script src="static/assets/vendor/isotope-layout/isotope.pkgd.min.js"></script>
<script src="static/assets/vendor/aos/aos.js"></script>
<!-- Template Main JS File -->
<script src="static/assets/js/main.js"></script>
</body>
</html>
成果展示
?源码下载
链接:https://pan.baidu.com/s/1uUfIoJRScb9QsdRBoMRhRQ? ? ? ? ? ? ? ? ? ??
提取码:u9y3
|