基于ESP8266和javaweb服务器实现温湿度自动和手动更新数据的电路方案

系列文章目录

第一章ESP8266的java软件仿真测试
第二章ESP8266硬件与软件测试
第三章ESP8266客户端与Java后台服务器联调
第四章ESP8266客户端与JavaWeb服务器联调
第五章ESP8266客户端与JavaWeb服务器网页联调
第六章ESP8266客户端与JavaWeb服务器网页实现数据的自动上传和下传联调


前言

daodanjishui物联网核心原创技术之物联网服务器网站部署


一、这次要实现的功能是什么?

在上一期ESP8266上传DHT11数据给私人javaweb服务器实现网页查询数据实现了服务器的主页手动更新单片机采集的温湿度数据。但是缺点也明显,就是不能自动更新和刷新数据,网页是静态的网页,没办法动起来。国内有些程序开发者用的是用websocket进行长连接抓取单片机的数据,其实这样有一些不方便的地方:比如一些浏览器不支持websocket技术、长链接就意味着长期占用资源、有些老的开发者不会用这个websocket技术等等,而本项目的网页打开才自动刷新数据的,不打开就不刷新不占用资源。如果硬要用WebSock来开发物联网控制我也会,小菜一碟。
在这一期代码中,利用传统jsp技术和java技术,用eclipse集成开发环境去实现动态更新单片机采集的温湿度数据显示在主页上,代码相当精妙和精简,服务器代码绝对原创,同时保留了手动更新的方式,增加了服务器详细的注释并且多增加了一个教程3,也修复了前面的教程1和2,形成一个教程体系。
教程下载地址:https://www.cirmall.com/circuit/18951/
点我跳转

为了更加形象生动地观察系统的运行机制,daodanjishui亲自拍摄了优酷视频,你会发现网页上的数据真的会自己动起来的
下面是视频入口:https://v.youku.com/v_show/id_XNDgxMTM3MDc4OA==.ht…

ESP8266上传DHT11温湿度给前台+后台的javaweb服务器实现网页自动和手动更新数据

二、系统逻辑设计说明

1.服务器前端设计

先看下面的服务器主页
服务器主页
相信读者根据图片显示网页数据的时间可以看出数据是不同的。CSDN目前好像还没有类似jsp网页动态更新单片机数据的项目吧?在浏览器输入服务器的地址就可以查询到单片机采集的数据了,这里采用的是谷歌浏览器远程查询环境温湿度数据。

手动查询部分前端JS代码如下(示例):
     $(document).ready(function(){
   	  $("#send").click(function(){
   		  if($("#user").val()==""){
   			 //alert("请输入昵称!");
   		  }
   		  if($("#speak").val()==""){
   			  //alert("说话内容不可以为空!");
   			  $("speak").focus();//让说话内容文本框获得焦点
   		  }
   		
   		    $.ajax({
           // url: 'ChatServlet',//这个是网址,注意的是组合成什么格式的网址
            url:'ChatServlet',
          // data:{action:"sendMessage",user:$("#user").val(),speak:$("#speak").val(),nocathe:new Date().getTime()},
            data:{action:"getMessages",signname:$("#user").val(),speak:$("#speak").val(),nocathe:new Date().getTime()},
           // type: 'post',//post请求
            type: 'get',//get请求
            cache:false,//不缓存数据
            dataType: 'html', //数据格式:json,html,xml,txt
            error:function(){//请求失败的处理函数
            	alert("请求失败");
            },
            success: function (data) {
            	//alert("请求成功");
              var result = document.getElementById("result1");	          
     	     result.innerHTML = "<font color=red>"+data+"</font>";
            }
        });  
  
   	  
   	  });
     });

自动查询部分前端JS代码如下(示例):

    //下面是增加自动刷新查询温湿度的代码
     function getContent(){	
	 $.get("ChatServlet?action=getMessages&signname=daodanjishui&speak=hello&nocathe="+new Date().getTime(),
			 function(data){
		       var result = document.getElementById("result2");	          
 	           result.innerHTML = "<font color=red>"+data+"</font>";		  
	         });
	   	  
     } 
         
     $(document).ready(function(){//网页框架加载完毕之后就调用这个函数
	  getContent();//调用上面定义的函数
	  window.setInterval("getContent()",1000);//每间隔1秒再调用上面的函数
     });

2.服务器后端设计

服务器接收网页JS发送的请求部分代码如下(示例):
try {
				out = response.getWriter();
				//获取输出流对象
				if(application.getAttribute("message")==null){
					msg="no data";
				}else{
					msg=(String) application.getAttribute("message");//已经存有值了,再存进去
				}
				//out.print(name+msg+"\n");//输出最新的信息给浏览器
				out.print(name+msg+"----"+new SimpleDateFormat("yyy.MM.dd HH:mm:ss").format(new Date())+"\n");//输出最新的信息给单片机
				out.close();//关闭输出流
			} catch (IOException e) {
				e.printStackTrace();
			}	

服务器接收单片机发送环境参数请求部分代码如下(示例):

response.setContentType("text/html;charset=UTF-8");//设置响应内容和编码方式
		String user=request.getParameter("user");//昵称
		String speak=request.getParameter("speak");//说话内容		
		mymessage="["+user+"]say:"+speak;//给单片机的
		System.out.println(mymessage);		
		String message="["+user+"]say:"+speak;//组合说话内容		
		application.setAttribute("message", mymessage);//将聊天内容保存到application
		try {
			response.getWriter().println(mymessage);
		} catch (IOException e) {
			e.printStackTrace();
		}

3.客户端单片机采集数据设计

其实采集DHT数据是属于STM32单片机驱动程序的开发,可以借鉴别人的驱动的。

/*
 * 一次完整的数据传输为40bit,高位先出
 * 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和 
 */
uint8_t Read_DHT11(DHT11_Data_TypeDef *DHT11_Data)
{  
	/*输出模式*/
	DHT11_Mode_Out_PP();
	/*主机拉低*/
	DHT11_DATA_OUT(LOW);
	/*延时18ms*/
	//Delay_ms(18);
  delay_ms(18);
	/*总线拉高 主机延时30us*/
	DHT11_DATA_OUT(HIGH); 

	delay_us(30);   //延时30us

	/*主机设为输入 判断从机响应信号*/ 
	DHT11_Mode_IPU();

	/*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/   
	if(DHT11_DATA_IN()==Bit_RESET)     
	{
		/*轮询直到从机发出 的80us 低电平 响应信号结束*/  
		while(DHT11_DATA_IN()==Bit_RESET);

		/*轮询直到从机发出的 80us 高电平 标置信号结束*/
		while(DHT11_DATA_IN()==Bit_SET);

		/*开始接收数据*/   
		DHT11_Data->humi_int= Read_Byte();

		DHT11_Data->humi_deci= Read_Byte();

		DHT11_Data->temp_int= Read_Byte();

		DHT11_Data->temp_deci= Read_Byte();

		DHT11_Data->check_sum= Read_Byte();


		/*读取结束,引脚改为输出模式*/
		DHT11_Mode_Out_PP();
		/*主机拉高*/
		DHT11_DATA_OUT(HIGH);

		/*检查读取的数据是否正确*/
		if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)
			return SUCCESS;
		else 
			return ERROR;
	}
	else
	{		
		return ERROR;
	}   
}

4.客户端ESP8266与服务器通信设计

这是本文中比较关键的地方,与服务器通信是否成功或者通信是否稳定决定了该系统的可靠性,2018年刚开始流行ESP8266的时候,daodanjishui通过逛遍ESP8266的开源论坛相关帖子寻求开发之道,终于在前人的基础上写出了这套STM32库函数AT指令联网代码,程序的核心思想就是控制STM32的串口发送AT指令来控制ESP8266链接服务器和收发消息。

为什么客户端只能主动发消息呢,而服务器只能被动发消息呢?因为我说过Servlet服务器只能响应客户端的请求而不能请求客户端响应,只能等客户端来请求之后顺便给客户端一个响应。

下面就是客户端部分的示例代码:


	while(1)
	{

						/*调用Read_DHT11读取温湿度,若成功则输出该信息*/
	if( Read_DHT11(&DHT11_Data)==SUCCESS)
	{
		printf("\r\n读取DHT11成功!\r\n\r\n湿度为%d.%d %RH ,温度为 %d.%d℃ \r\n",\
		DHT11_Data.humi_int,DHT11_Data.humi_deci,DHT11_Data.temp_int,DHT11_Data.temp_deci);
		//printf("\r\n 湿度:%d,温度:%d \r\n" ,DHT11_Data.humi_int,DHT11_Data.temp_int);
	  //sprintf((char*)p,"\r\n读取DHT11成功!\r\n\r\n湿度为%d.%d %RH ,温度为 %d.%d℃ \r\n",\
		DHT11_Data.humi_int,DHT11_Data.humi_deci,DHT11_Data.temp_int,DHT11_Data.temp_deci);
		//sprintf((char*)p,"hello,Temperature=%d.%d'C ,Humidity=%d.%d RH\r\n",DHT11_Data.temp_int,DHT11_Data.temp_deci,DHT11_Data.humi_int,DHT11_Data.humi_deci);//返回温湿度给服务器
		//sprintf((char*)p,"GET http://192.168.253.1:8080/test_TCP/ChatServlet?action=getMessages&signname=%d.%d %RH HTTP/1.1\r\nHost:192.168.253.1:8080\r\nConnection: keep-alive\r\n\r\n",DHT11_Data.humi_int,DHT11_Data.humi_deci);//测试数据
		
		//sprintf((char*)p,"GET http://192.168.253.1:8080/test_TCP/ChatServlet?action=getMessages&signname=%d HTTP/1.1\r\nHost:192.168.253.1:8080\r\nConnection: keep-alive\r\n\r\n",DHT11_Data.humi_int);//测试数据	
		sprintf((char*)p,"POST http://192.168.253.1:8080/test_TCP/ChatServlet?action=sendMessage&user=Robot1&speak=Humidity:%d.%dRH---Temperature:%d.%d'C HTTP/1.1\r\nHost:192.168.253.1:8080\r\nConnection: keep-alive\r\n\r\n",DHT11_Data.humi_int,DHT11_Data.humi_deci,DHT11_Data.temp_int,DHT11_Data.temp_deci);//测试数据
	
	  //sprintf((char*)p,"GET http://192.168.253.1:8080/test_TCP/ChatServlet?signname=%d HTTP/1.1\r\nHost:192.168.253.1:8080\r\nConnection: keep-alive\r\n\r\n",DHT11_Data.humi_int);//测试数据	
		//sprintf((char*)p,"POST http://192.168.253.1:8080/test_TCP/ChatServlet?action=sendMessage&user=Robot1&speak=Humidity:%d.%dRH---Temperature:%d.%d'C HTTP/1.1\r\nHost:192.168.253.1:8080\r\nConnection: keep-alive\r\n\r\n",DHT11_Data.humi_int,DHT11_Data.humi_deci,DHT11_Data.temp_int,DHT11_Data.temp_deci);//测试数据
	
	}
	else
	{
		printf("Read DHT11 ERROR!\r\n");
		sprintf((char*)p,"hello,T=0 ,H=0\r\n");//返回温湿度给服务器
	}
		

		
		//测试发送一个字符串
	 // sprintf((char*)p,"hello\r\n");
		//DHT11_Read_Data(&temperature,&humidity);	//读取温湿度值
		//sprintf((char*)p,"hello,T= ,H=\r\n");//返回温湿度给服务器
		  //sizeof反回的是总容量的大小,而strlen是返回实际使用的大小
		  //但是要注意的是strlen函数必须是用char类型的指针,所以此处需要进行强制转换
			 u2_printf("AT+CIPSEND=0,%d\r\n",strlen((char*)p));//发送数据的AT指令,先写指令后发送数据
			// delay_ms(200);
			// u2_printf("%s\r\n",p);   //发送指定长度的数据		
		  delay_ms(200);
		  atk_8266_send_data(p,"OK",100);  //发送指定长度的数据		  
	
	 t++;
	 //delay_ms(10);
	delay_ms(1000);
	 if(USART2_RX_STA&0X8000)		//接收到一次数据了
	{ 
		rlen=USART2_RX_STA&0X7FFF;	//得到本次接收到的数据长度
		USART2_RX_BUF[rlen]=0;		//添加结束符 
		//printf("%s",USART2_RX_BUF);	//发送到串口   
		printf("收到%d字节,内容如下\r\n",rlen);
		printf("---%s\r\n",USART2_RX_BUF);
		//sprintf((char*)p,"收到%d字节,内容如下",rlen);//接收到的字节数 
		USART2_RX_STA=0;
		//receive_flag=1;
		//if(constate!='+')t=1000;		//状态为还未连接,立即更新连接状态
		//if(constate!='+')t=300;		//状态为还未连接,立即更新连接状态
		if(constate!='+')t=3;		//状态为还未连接,立即更新连接状态
		else t=0;                   //状态为已经连接了,10秒后再检查
		
		

		
		
		
	}  
  //printf("测试t=%d,constate=%c,receive_flag=%d\r\n",t,constate,receive_flag);
	//if(t==1000)//连续10秒钟没有收到任何数据,检查连接是不是还存在.
	//if(t==300)//连续3秒钟没有收到任何数据,检查连接是不是还存在.
	if(t==3)//连续3秒钟没有收到任何数据,检查连接是不是还存在.
	{
		printf("测试连接状态\r\n");
		constate=atk_8266_consta_check();//得到连接状态
		if(constate=='+'){
			printf("连接成功\r\n");
		}else{
			printf("连接失败\r\n");
			
			atk_8266_apsta_test();//断线重连
			
		}
		t=0;
	}
//	if(t>1000)t=0;
	if(t>3)t=0;
	//if((t%20)==0)LED0=!LED0;
	atk_8266_at_response(1);
 }

5.仿真与调试

(1)首先展示的是单片机源码截图:
单片机源码
(2)单片机代码运行串口打印
串口打印
(3)服务器运行打印截图,javaweb服务器的代码是Eclipse编写的,单片机是用MDK 5写的,单片机用AT指令驱动ESP8266链接笔记本热点,从而达到客户端与服务器以无线的方式通信。
服务器前端代码
(4)服务器主页显示温湿度参数
全部就绪的效果


总结

本文实现了单片机采集温湿度数据通过wifi传输给物联网私人服务器,在浏览器登录服务器的主页可以自动查询到温湿度数据。具体的效果可以看看优酷视频更加形象和直观了,系统功能强大值得参考和学习。

文章到这里就结束了,代码量还是不少的,没有三五年功力是不可能写出这样一个客户端与服务器配合形成一个环境参数采集网站的,代码不可能在这个博客上全部展现的,从博客里面可以看出我这个系统构造完善功能齐全、设计思路明确就达到目的了,如果你用百度云阿里云腾讯云可以做出更好的效果,但是你绝对不可能学会这些云平台的后代源码的,人家也不会放出来给你学,你只是普通使用者而不是开发者,从我的服务器代码来看,绝对是实打实的后台代码,绝对不玩虚的!我可以人品保证这个代码绝对是我自己核心原创的,绝对可以完美运行的,绝对是学习物联网监控的技术的好选择

详细资料传送地址:https://www.cirmall.com/circuit/18951/
点我直接跳转获取资料

下载资料之前可以看看资料传送的地方别人的评论和下载量就知道了,好东西一切尽在不言中。

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

daodanjishui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值