关闭

【Android小练手】安卓端实时获取HttpUrl数据

标签: servletandroid物联网传感器数据分析
1342人阅读 评论(0) 收藏 举报
分类:

前言

关于上一篇文章中基于servlet的HttpUrl服务端,以时间为例的实时信息更新。

既然有写Server端,自然会要想如何应用这段信息,于是尝试着在安卓端想写一个demo,使用一个距离传感器,它们实时采集数据然后通过UART的方式把数据发送到PC端,然后PC端通过WIFI无线网络利用HttpUrl通信方式再将数据发送到手机,手机将数据按照一定的格式进行显示。


应用背景(实用性)

在解决了基础物质生活需求的今天,随着科技的不断进步,人们的生活受到了潜移默化的影响,生活质量也不断得到提高。促使人们开始追求家庭生活现代化、居住环境舒适化、安全化等,为此智能家居也随之而生,所谓的智能家居是以住宅为平台,利用综合布线技术、网络通信技术、安全防范技术、自动控制技术、音视频技术将家居生活有关的设施集成,构建高效的住宅设施与家庭日程事务的管理系统,提升家居安全性、便利性、舒适性、艺术性,并实现环保节能的居住环境。随着物联网络的出现,为智能家居系统的发展及应用加入了助推剂。物联网是指各类传感器与现有的互联网相互衔接的一种新技术。物联网让智能家居的功能产生了飞跃,它改变的将不仅仅是家电产品的功能,而是生活方式,给消费者带来的便捷令人向往。


需求分析

本次从实际出发,目的为实现使用手机应用通过无线对一个距离传感器实现监测和控制,是智能联网系统的基本需求。
获取传感器数值
通过串口传输数据
服务器端监听串口数据发送给手机端
手机端通过无线实时显示传感器数据


配置及环境

硬件配置

@ZoeCur 1只
Sharp GP2Y0A21YK距离传感器
Nokia 5110 屏幕
TM4C Lanchpad
USB数据线 (模拟串口)
PC机(ThinkPad T430)
Android系统智能手机

开发环境

Windows 8
Keil v4
JDK 1.8
Eclipse EE(javacomm20-win32/RXTX_win64)
ADT

运行环境

Windows 8
JRE 1.8
javacomm20-win32/RXTX_win64
Android 4.4.4 (三星N7100)


设计理念

Servlet设计


Method设计


Client-Android 设计





数据分析

为了得到传感器返回的电压值与实际距离的关系,需要获得这两者间的函数关系,于是用厘米尺量取几个点用以数据拟合。

T=[999,860,660,450,370,270,200,150,130];

D=[5,10,15,20,25,30,40,60,80];

使用Matlab进行拟合


General model Exp2:
     f(x) = a*exp(b*x) + c*exp(d*x)
Coefficients (with 95% confidence bounds):
       a =        1944  (-371.5, 4260)
       b =    -0.02985  (-0.03951, -0.02019)
       c =       51.71  (42.08, 61.33)
       d =   -0.002019  (-0.002434, -0.001603)
Goodness of fit:
  SSE: 7.813
  R-square: 0.9984
  Adjusted R-square: 0.9974
  RMSE: 1.25

选用函数为:f(x)=1944*exp(-0.02985*x)+51.71*exp(-0.002019*x)考虑到计算复杂度和计算精度的问题,放弃高斯拟合选用了契合度稍低但容易计算的自然对数拟合函数。

将其写作函数,用来对电压值转换为距离:

public String changeToDist(String str)
    {
    	double x=(double)Integer.parseInt(str);
		double val = 1944.0 * Math.exp(-0.02985*x) + 51.71 * Math.exp(-0.002019*x);
		String ret="";
		if(val>80.0)ret = " >80.00 cm";
			else if(val<5.0) ret = " <5.00 cm";
				else{
						ret = val + "";
						ret = ret.substring(0,6) + "cm";
					}
		System.out.println("[Log] Info_sensor="+ret);
		return ret;
    }



服务器实时传送数值如上,可见数值转换正常。


关于麻烦的安卓端

package com.example.sensor_app;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;


public class MainActivity extends Activity {
	private Button butt3 = null; 
	private TextView text1 = null;
	String value = null;
	private MyTask mTask;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    	 super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         
         butt3 = (Button) this.findViewById(R.id.button1);
         text1 = (TextView) this.findViewById(R.id.text1);
         
         butt3.setOnClickListener(new Button.OnClickListener()
     	{
 			@Override
 			public void onClick(View arg0) {
 				// TODO Auto-generated method stub
 				mTask = new MyTask();
 				mTask.execute("http://192.168.191.1:8080/SensorApp/ReadDemo?op=getValue");
 				butt3.setEnabled(false);
 			}			
     	});
    }
    
    private class MyTask extends AsyncTask<String,Integer,String>{
    	
    	
		@Override
		protected void onPreExecute() {
			//Log.i(TAG,"onPreExecute() called");
			text1.setText("loading");
			
		}

		@Override
		protected String doInBackground(String... params) {
			//Log.i(, "doInBackGround()call");
			
			try {  
                HttpClient client = new DefaultHttpClient();  
                HttpGet get = new HttpGet(params[0]);  
                HttpResponse response = null;
              
                while(true){
                	response = client.execute(get); 
	                if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {  
	                    HttpEntity entity = response.getEntity();  
	                    InputStream is = entity.getContent();  
	                    long total = entity.getContentLength();  
	                    ByteArrayOutputStream baos = new ByteArrayOutputStream();  
	                    byte[] buf = new byte[1024];  
	                    int count = 0;  
	                    int length = -1;  
	                    while ((length = is.read(buf)) != -1) {  
	                        baos.write(buf, 0, length);  
	                        count += length;  
	                        //调用publishProgress公布进度,最后onProgressUpdate方法将被执行  
	                       // publishProgress((int) ((count / (float) total) * 100));  
	                        //为了演示进度,休眠500毫秒 
	                       
	                        
	                    }  
	                    //更新当前值
	                    value = new String(baos.toByteArray(), "gb2312");
	                    //调用onProgressUpdate(Integer... values)
	                    publishProgress((int) ((count / (float) total) * 100));
	                   //一秒后继续更新
	                    Thread.sleep(1000); 
	                    //return new String(baos.toByteArray(), "gb2312");  
	                }
	                /*Thread.sleep(1000);  
	                i++;
	                publishProgress(i,5);*/
                }  
            } catch (Exception e) {  
                //Log.e(TAG, e.getMessage());  
            }  
            return null;  
		}

		@Override
		protected void onProgressUpdate(Integer... values) {
			// TODO Auto-generated method stub
			text1.setText(value);
		}

		@Override
		protected void onPostExecute(String result) {
			// TODO Auto-generated method stub
			text1.setText(result); 
		}
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    
}

难点在于开线程以及同步实时更新数值。

关于控件的信号槽问题是Android的通病,不过与本次实验尝试无关,就不在这里写这些的处理方法了。




调试完毕后,连接手机打开ADB调试,开始运行安卓客户端。


如图,此为在安卓OS中的APP图标及打开时的初始界面。
紧接着,在JavaEE中打开服务端,开始运行,上图为服务端控制台数据,也同时编写Log日志,实时向客户端传值。



电路板纹理的正六边形为启动按钮,安卓端接收到服务端确认后,将实时显示服务器传来的数据,

由于服务端的串口数据接收间隔为5秒,当接收到新数据时会显示<NEW>以作提示。


总结

此次课程设计中,我负责的主要是服务端与安卓客户端的部分,辅以对数据在Matlab中进行数据拟合。

过程中查阅了许多资料,为了新功能进行了若干次尝试,这是一次非常有收获的经历。


从串口获取数据之后,服务器需要持续地将串口数据读取到程序中,通过我拟合出的“传感器电压值-实际距离值”函数将String类型的信息转换成实际距离,加上传感器型号与服务器时间后传递给网络端口。另一个难点在于一次请求之后要无限实时信息传递,加上各类异常和新数据的判定,最终终于完成了之后,成就感和自豪油然而生。


Release

SourceCode: 

https://github.com/okcd00/Colorful_Projects/tree/master/J2EE_Projects/Android-Server-Sensor%20%E4%BF%A1%E6%81%AF%E4%BC%A0%E9%80%92

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:208351次
    • 积分:4718
    • 等级:
    • 排名:第6490名
    • 原创:267篇
    • 转载:19篇
    • 译文:1篇
    • 评论:81条
    My Info
    小提示
    【阅读全文】新版博客更新后装有AdBlock的浏览器将无法点开阅读全文,设置为不在此网域运行即可。
    专栏里,每道题的Codeforces原题链接,可以通过查看标题中的数字,访问 “http://codeforces.com/contest/数字” 来到原题阅读或提交~
    最近在Github上整理Codeforces的题目,但是发现代码凌乱目不忍视,于是开始从头打理,有实在看不下去的也重写一些,所以大家会发现专栏中以前发的题解会时不时的有点小改动o(∩_∩)o
    博客专栏
    最新评论