目前我们已经把运行整个项目的最小框架搭建好了,下面我按照开发顺序,把一些内容贴上来,以及后期要改进和注意的问题。
需要注意的是,别以为这里面原理很简单就可以轻视了,部署过程中有哪一点弄不好就足够你调半天了。这是我跟候志的共同看法。
数据库部分
先是建表:
1 -- 创建一个名为sensor的数据库 2 CREATE DATABASE sensor; 3 4 USE sensor; 5 6 -- 老人的帐号 7 CREATE TABLE ancestor 8 ( 9 ancName VARCHAR(20) PRIMARY KEY, 10 ancPwd VARCHAR(20) NOT NULL 11 ); 12 13 -- 子女的帐号 14 CREATE TABLE descendant 15 ( 16 desName VARCHAR(20) PRIMARY KEY, 17 desPwd VARCHAR(20) NOT NULL 18 ); 19 20 -- 两者的映射 21 CREATE TABLE relation_map 22 ( 23 ancName VARCHAR(20) REFERENCES ancestor(ancName), 24 desName VARCHAR(20) REFERENCES descendant(desName), 25 PRIMARY KEY(ancName, desName) 26 ); 27 28 -- 最原始的传感器数据表,假定所有数据类型均为int 29 -- 在后面还要通过触发器,存储统计数据来减少数据量 30 CREATE TABLE sensor_data 31 ( 32 cur_time DATETIME PRIMARY KEY, 33 belonger VARCHAR(20) REFERENCES ancestor(ansName), 34 35 -- 手指穿戴的模块 36 -- 加速度传感器 37 finger_jiasudu_x int, 38 finger_jiasudu_y int, 39 finger_jiasudu_z int, 40 -- 角速度传感器 41 finger_jiaosudu_x int, 42 finger_jiaosudu_y int, 43 finger_jiaosudu_z int, 44 -- 磁力传感器 45 finger_cili_x int, 46 finger_cili_y int, 47 finger_cili_z int, 48 -- 温度和气压传感器 49 finger_wendu int, 50 finger_qiya int, 51 52 -- 脖子上穿戴的模块 53 -- 加速度传感器 54 chest_jiasudu_x int, 55 chest_jiasudu_y int, 56 chest_jiasudu_z int, 57 -- 角速度传感器 58 chest_jiaosudu_x int, 59 chest_jiaosudu_y int, 60 chest_jiaosudu_z int, 61 -- 磁力传感器 62 chest_cili_x int, 63 chest_cili_y int, 64 chest_cili_z int, 65 -- 温度和气压传感器 66 chest_wendu int, 67 chest_qiya int, 68 69 -- 脚上穿戴的模块 70 -- 加速度传感器 71 ankle_jiasudu_x int, 72 ankle_jiasudu_y int, 73 ankle_jiasudu_z int, 74 -- 角速度传感器 75 ankle_jiaosudu_x int, 76 ankle_jiaosudu_y int, 77 ankle_jiaosudu_z int, 78 -- 磁力传感器 79 ankle_cili_x int, 80 ankle_cili_y int, 81 ankle_cili_z int, 82 -- 温度和气压传感器 83 ankle_wendu int, 84 ankle_qiya int, 85 86 -- 手机GPS导航部分 87 latitude DOUBLE, -- 纬度 88 is_north int DEFAULT 1, -- 判断是否为北半球 89 longitude DOUBLE, -- 经度 90 is_east int DEFAULT 1 -- 判断是否为东半球 91 );
注意:
1、目前这里只是简单地建表,按照10s发送一次数据的频率,很快数据库就会爆的。解决办法可能就是按照项目书里面提到的。但目前的替代方案是:建立一个作业,每天凌晨自动清空数据。
2、由于候志传送数据部分用户名设置为纯数字,所以目前用户名字段只能用纯数字。
3、建立数据源连接池。由于我们所有的部署都迁移到eclipse内部,所以配置数据源连接池也在里面弄:
在eclipse启动一个Servers服务后,在server.xml文件的</host>前插入如下代码:
1 <Context docBase="SensorServer" path="/SensorServer" reloadable="true" source="org.eclipse.jst.jee.server:SensorServer"> 2 <Resource name="JDBC/SensorServer" 3 auth="Container" 4 type="javax.sql.DataSource" 5 maxActive="100" 6 maxIdle="30" 7 maxWait="10000" 8 username="root" 9 password="123456" 10 driverClassName="com.mysql.jdbc.Driver" 11 url="jdbc:mysql://localhost:3306/sensor"/> 12 </Context>
然后要在web项目的web.xml里面做如下配置:
1 <resource-ref> 2 <description>DB Connection</description> 3 <res-ref-name>JDBC/SensorServer</res-ref-name> 4 <res-type>javax.sql.DataSource</res-type> 5 <res-auth>Container</res-auth> 6 </resource-ref>
4、由于操作jdbc很容易语句出错,所以对数据库做了如下封装:
1 package com.sensor; 2 3 import java.sql.Connection; 4 import java.sql.ResultSet; 5 import java.sql.SQLException; 6 import java.sql.Statement; 7 import java.util.TreeMap; 8 9 import javax.naming.Context; 10 import javax.naming.InitialContext; 11 import javax.sql.DataSource; 12 13 public class DB 14 { 15 /** 16 * 得到数据库连接的方法,采用数据源连接池 17 */ 18 public static Connection getConn() 19 { 20 Connection conn=null; 21 try{ 22 Context initial = new InitialContext();//得到上下文引用 23 DataSource ds = (DataSource)initial.lookup("java:comp/env/JDBC/SensorServer"); //得到DataSource引用 24 conn = ds.getConnection();//得到数据库连接 25 } 26 catch(Exception e) 27 { 28 e.printStackTrace(); 29 } 30 return conn;//返回数据库连接 31 } 32 33 public static Statement getStatement(Connection conn) 34 { 35 Statement stmt = null; 36 try 37 { 38 if(conn != null) 39 stmt = conn.createStatement(); 40 } catch (SQLException e) 41 { 42 e.printStackTrace(); 43 } 44 return stmt; 45 } 46 47 /** 48 * 该方法为查询时使用 49 */ 50 public static ResultSet getResultSet(Statement stmt, String sql) 51 { 52 ResultSet rs = null; 53 try { 54 if(stmt != null) { 55 rs = stmt.executeQuery(sql); 56 } 57 } catch (SQLException e) { 58 e.printStackTrace(); 59 } 60 return rs; 61 } 62 63 /** 64 * 该方法执行一般的增、删、改 65 */ 66 public static void doUpdate(Statement stmt, String sql) 67 { 68 try { 69 if(stmt != null) { 70 stmt.executeUpdate(sql); 71 } 72 } catch (SQLException e) { 73 e.printStackTrace(); 74 } 75 } 76 77 public static void closeResultSet(ResultSet rs) 78 { 79 try { 80 if(rs != null) { 81 rs.close(); 82 rs = null; 83 } 84 } catch (SQLException e) { 85 e.printStackTrace(); 86 } 87 } 88 89 public static void closeStmt(Statement stmt) 90 { 91 try { 92 if(stmt != null) 93 { 94 stmt.close(); 95 stmt = null; 96 } 97 } catch (SQLException e) { 98 e.printStackTrace(); 99 } 100 } 101 102 public static void closeConn(Connection conn) 103 { 104 try { 105 if(conn != null) 106 { 107 conn.close(); 108 conn = null; 109 } 110 } catch (SQLException e) { 111 e.printStackTrace(); 112 } 113 } 114 115 /** 116 * 注册老人帐号,如果已经存在则返回false 117 */ 118 public static boolean regAncAccount(String name,String pwd) 119 { 120 Connection conn=getConn(); 121 Statement stmt=getStatement(conn); 122 String sql="select * from ancestor where ancName='"+name+"'"; 123 ResultSet rs=getResultSet(stmt,sql); 124 try 125 { 126 if(rs.next()) 127 return false; 128 else 129 { 130 sql="insert into ancestor values ('" + name + "', '"+ pwd + "')"; 131 doUpdate(stmt,sql); 132 return true; 133 } 134 } catch(Exception e) 135 { 136 e.printStackTrace(); 137 return false; 138 } finally 139 { 140 closeResultSet(rs); 141 closeStmt(stmt); 142 closeConn(conn); 143 } 144 } 145 146 /** 147 * 使用老人的帐号登录,如果表中存在对应行,则返回true 148 */ 149 public static boolean loginAncAccount(String name,String pwd) 150 { 151 Connection conn=getConn(); 152 Statement stmt=getStatement(conn); 153 String sql="select * from ancestor where ancName='"+name+"' and ancPwd='"+pwd+"'"; 154 ResultSet rs=getResultSet(stmt,sql); 155 try 156 { 157 if(rs.next()) 158 return true; 159 else 160 return false; 161 } catch(Exception e) 162 { 163 e.printStackTrace(); 164 return false; 165 } finally 166 { 167 closeResultSet(rs); 168 closeStmt(stmt); 169 closeConn(conn); 170 } 171 } 172 173 /** 174 * 创建子女帐号,如果已经存在则返回false 175 */ 176 public static boolean regDesAccount(String name,String pwd) 177 { 178 Connection conn=getConn(); 179 Statement stmt=getStatement(conn); 180 String sql="select * from descendant where desName='"+name+"'"; 181 ResultSet rs=getResultSet(stmt,sql); 182 try 183 { 184 if(rs.next()) 185 return false; 186 else 187 { 188 sql="insert into descendant values ('" + name + "', '"+ pwd + "')"; 189 doUpdate(stmt,sql); 190 return true; 191 } 192 } catch(Exception e) 193 { 194 e.printStackTrace(); 195 return false; 196 } finally 197 { 198 closeResultSet(rs); 199 closeStmt(stmt); 200 closeConn(conn); 201 } 202 } 203 204 /** 205 * 为表relation_map添加一条映射关系 206 */ 207 public static boolean addSon(String parent,String son) 208 { 209 Connection conn=getConn(); 210 Statement stmt=getStatement(conn); 211 String sql="select * from relation_map where ancName='"+parent+"' and desName='"+son+"'"; 212 //System.out.println(sql); 213 ResultSet rs=getResultSet(stmt,sql); 214 try 215 { 216 if(rs.next()) 217 return true; 218 else 219 { 220 sql="select * from descendant where desName='"+son+"'"; 221 //System.out.println(sql); 222 rs=getResultSet(stmt,sql); 223 if(rs.next()) 224 { 225 sql="insert into relation_map values ('" + parent + "', '"+ son + "')"; 226 //System.out.println(sql); 227 doUpdate(stmt,sql); 228 return true; 229 } else 230 return false; 231 } 232 } catch(Exception e) 233 { 234 e.printStackTrace(); 235 return false; 236 } finally 237 { 238 closeResultSet(rs); 239 closeStmt(stmt); 240 closeConn(conn); 241 } 242 } 243 244 /** 245 * 插入一行传感器数据 246 */ 247 public static void insertSensorData(TreeMap<String, Integer> tm, String name) 248 { 249 Connection conn=getConn(); 250 Statement stmt=getStatement(conn); 251 252 //具体映射要到后期确定下来 253 String sql="insert into sensor_data values ( now(), '"+name+"', " 254 +tm.get(""); 255 256 doUpdate(stmt,sql); 257 closeStmt(stmt); 258 closeConn(conn); 259 } 260 261 /** 262 * 返回多行传感器数据,用于进行分析,返回类型是一个ArrayList 263 */ 264 public static void getSensorData() 265 { 266 267 } 268 }
发送客户端部分
1、首先要在编译路径里加入候志编写的数据传送模块:transfer.jar。
2、登录、注册、添加监控用户是3个联系比较密切的模块,后期开发接收客户端的时候,也可以按照这种写法。下面做简要介绍。
主要是向服务器传送用户名和密码两个参数,这里的数据传送用了另外一种封装。下面是两个封装类:
1 package com.sensor; 2 import java.io.ByteArrayOutputStream; 3 import java.io.InputStream; 4 import java.util.*; 5 6 import org.apache.http.HttpResponse; 7 import org.apache.http.NameValuePair; 8 import org.apache.http.client.HttpClient; 9 import org.apache.http.client.entity.UrlEncodedFormEntity; 10 import org.apache.http.client.methods.HttpPost; 11 import org.apache.http.impl.client.DefaultHttpClient; 12 import org.apache.http.message.BasicNameValuePair; 13 14 /** 15 * 通过Http协议发送带文件或不带文件的请求的工具类 16 * @author 林培东 17 */ 18 public class HttpUploadUtil 19 { 20 21 //不带文件的请求发送方法 22 public static String postWithoutFile 23 ( 24 String actionUrl, //请求的URL 25 Map<String, String> params //请求的参数序列 26 ) 27 { 28 HttpClient httpclient = new DefaultHttpClient(); 29 //你的URL 30 HttpPost httppost = new HttpPost(actionUrl); 31 try { 32 List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(params.size()); 33 34 for (Map.Entry<String, String> entry : params.entrySet()) 35 {//构建表单字段内容 36 nameValuePairs.add(new BasicNameValuePair(entry.getKey(),MyConverter.escape(entry.getValue()))); 37 } 38 httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); 39 HttpResponse response; 40 response=httpclient.execute(httppost); 41 InputStream in=response.getEntity().getContent(); 42 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 43 int ch=0; 44 while((ch=in.read())!=-1) 45 { 46 baos.write(ch); 47 } 48 byte[] data=baos.toByteArray(); 49 baos.close(); 50 return MyConverter.unescape(new String(data).trim()); 51 } catch (Exception e) 52 { 53 e.printStackTrace(); 54 return "error"; 55 } 56 } 57 }
1 package com.sensor; 2 3 /** 4 * 一个工具类,转换器 5 * @author 林培东 6 * 7 */ 8 public class MyConverter 9 { 10 private final static String[] hex = 11 { 12 "00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f", 13 "10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f", 14 "20","21","22","23","24","25","26","27","28","29","2a","2b","2c","2d","2e","2f", 15 "30","31","32","33","34","35","36","37","38","39","3a","3b","3c","3d","3e","3f", 16 "40","41","42","43","44","45","46","47","48","49","4a","4b","4c","4d","4e","4f", 17 "50","51","52","53","54","55","56","57","58","59","5a","5b","5c","5d","5e","5f", 18 "60","61","62","63","64","65","66","67","68","69","6a","6b","6c","6d","6e","6f", 19 "70","71","72","73","74","75","76","77","78","79","7a","7b","7c","7d","7e","7f", 20 "80","81","82","83","84","85","86","87","88","89","8a","8b","8c","8d","8e","8f", 21 "90","91","92","93","94","95","96","97","98","99","9a","9b","9c","9d","9e","9f", 22 "a0","a1","a2","a3","a4","a5","a6","a7","a8","a9","aa","ab","ac","ad","ae","af", 23 "b0","b1","b2","b3","b4","b5","b6","b7","b8","b9","ba","bb","bc","bd","be","bf", 24 "c0","c1","c2","c3","c4","c5","c6","c7","c8","c9","ca","cb","cc","cd","ce","cf", 25 "d0","d1","d2","d3","d4","d5","d6","d7","d8","d9","da","db","dc","dd","de","df", 26 "e0","e1","e2","e3","e4","e5","e6","e7","e8","e9","ea","eb","ec","ed","ee","ef", 27 "f0","f1","f2","f3","f4","f5","f6","f7","f8","f9","fa","fb","fc","fd","fe","ff" 28 }; 29 private final static byte[] val = 30 { 31 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, 32 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, 33 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, 34 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, 35 0x3f,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, 36 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, 37 0x3f,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, 38 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, 39 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, 40 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, 41 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, 42 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, 43 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, 44 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, 45 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, 46 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f 47 }; 48 49 50 public static String escape(String s) 51 { 52 StringBuffer sbuf = new StringBuffer(); 53 int len = s.length(); 54 for (int i = 0; i < len; i++) 55 { 56 int ch = s.charAt(i); 57 if ('A' <= ch && ch <= 'Z') 58 { 59 sbuf.append((char) ch); 60 } 61 else if ('a' <= ch && ch <= 'z') 62 { 63 sbuf.append((char) ch); 64 } 65 else if ('0' <= ch && ch <= '9') 66 { 67 sbuf.append((char) ch); 68 } 69 else if (ch == '-' || ch == '_' 70 || ch == '.' || ch == '!' || ch == '~' || ch == '*' 71 || ch == '\'' || ch == '(' || ch == ')') 72 { 73 sbuf.append((char) ch); 74 } else if (ch <= 0x007F) 75 { 76 sbuf.append('%'); 77 sbuf.append(hex[ch]); 78 } else 79 { 80 sbuf.append('%'); 81 sbuf.append('u'); 82 sbuf.append(hex[(ch >>> 8)]); 83 sbuf.append(hex[(0x00FF & ch)]); 84 } 85 } 86 return sbuf.toString(); 87 } 88 89 90 public static String unescape(String s) 91 { 92 StringBuffer sbuf = new StringBuffer(); 93 int i = 0; 94 int len = s.length(); 95 while (i < len) 96 { 97 int ch = s.charAt(i); 98 if ('A' <= ch && ch <= 'Z') 99 { 100 sbuf.append((char) ch); 101 } 102 else if ('a' <= ch && ch <= 'z') 103 { 104 sbuf.append((char) ch); 105 } else if ('0' <= ch && ch <= '9') 106 { 107 sbuf.append((char) ch); 108 } 109 else if (ch == '-' || ch == '_'|| ch == '.' 110 || ch == '!' || ch == '~' || ch == '*' 111 || ch == '\'' || ch == '(' || ch == ')') 112 { 113 sbuf.append((char) ch); 114 } 115 else if (ch == '%') 116 { 117 int cint = 0; 118 if ('u' != s.charAt(i + 1)) 119 { 120 cint = (cint << 4) | val[s.charAt(i + 1)]; 121 cint = (cint << 4) | val[s.charAt(i + 2)]; 122 i += 2; 123 } else 124 { 125 cint = (cint << 4) | val[s.charAt(i + 2)]; 126 cint = (cint << 4) | val[s.charAt(i + 3)]; 127 cint = (cint << 4) | val[s.charAt(i + 4)]; 128 cint = (cint << 4) | val[s.charAt(i + 5)]; 129 i += 5; 130 } 131 sbuf.append((char) cint); 132 } else 133 { 134 sbuf.append((char) ch); 135 } 136 i++; 137 } 138 return sbuf.toString(); 139 } 140 141 public static void main(String[] args) 142 { 143 String stest = "1234 abcd[]()<+>,.~\\"; 144 System.out.println(stest); 145 System.out.println(escape(stest)); 146 System.out.println(unescape(escape(stest))); 147 } 148 149 }
下面是封装后的用法,仅介绍登录模块。
1 1、获取用户名和密码 2 3 loginButton.setOnClickListener(new Button.OnClickListener() { 4 @Override 5 public void onClick(View v) 6 { 7 LayoutInflater factory = LayoutInflater.from(MainActivity.this); 8 //得到自定义对话框 9 final View DialogView = factory.inflate(R.layout.logindialog, null); 10 11 //创建登录框 12 AlertDialog dlg = new AlertDialog.Builder(MainActivity.this) 13 .setTitle("登录") 14 .setView(DialogView)//设置自定义对话框的样式 15 .setPositiveButton("确定", //设置“确定"按钮 16 new DialogInterface.OnClickListener() 17 { 18 @Override 19 public void onClick(DialogInterface dialog, int whichButton) 20 { 21 m_username = (EditText) DialogView.findViewById(R.id.username); 22 m_password = (EditText) DialogView.findViewById(R.id.password); 23 24 username = m_username.getText().toString(); 25 password = m_password.getText().toString(); 26 connectServer("loginAncAccount.jsp"); 27 } 28 } 29 ) 30 .setNegativeButton("取消", //设置“取消”按钮 31 new DialogInterface.OnClickListener() 32 { 33 @Override 34 public void onClick(DialogInterface dialog, int whichButton) 35 { 36 dialog.dismiss(); 37 } 38 }) 39 .create(); 40 41 42 dlg.show(); 43 } 44 }); 45 46 47 2、进行连接 48 49 private void connectServer(String style) 50 { 51 final String url=getResources().getString(R.string.default_url)+style; 52 //保存参数 53 final Map<String,String> params=new HashMap<String,String>(); 54 params.put("params1", username); 55 params.put("params2", password); 56 57 //获取SharedPreferences,将用户名保存起来,方便以后使用 58 SharedPreferences sp=MainActivity.this.getSharedPreferences("actm", Context.MODE_PRIVATE); 59 SharedPreferences.Editor editor=sp.edit(); 60 editor.putString("uname",username); 61 editor.commit(); 62 63 /** 64 * 发送数据,这里最好用多线程来处理 65 * 因为如果发生错误的话整个界面就没有响应 66 */ 67 try 68 { 69 String msgStr=HttpUploadUtil.postWithoutFile(url, params);//将url和参数传给jsp 70 Toast.makeText(MainActivity.this, msgStr, Toast.LENGTH_LONG).show(); 71 System.out.println(msgStr);//测试用 72 //登录或者注册成功则跳转到另一个界面 73 if(msgStr.equals("登录成功") || msgStr.equals("注册成功")) 74 { 75 //跳转 76 Intent intent=new Intent(); 77 intent.setClass(this, OperateActivity.class); 78 startActivity(intent); 79 MainActivity.this.finish(); 80 } 81 } catch(Exception e){ 82 e.printStackTrace(); 83 } 84 } 85 86 87 3、在服务器,用相应的jsp文件来进行响应 88 89 <%@ page 90 contentType="text/html;charset=gbk" 91 import="java.io.*,javax.servlet.*,com.sensor.*" 92 %> 93 94 <% 95 String param1=request.getParameter("params1").trim(); 96 String param2=request.getParameter("params2").trim(); 97 98 String uname=MyConverter.unescape(param1); 99 String pwd=MyConverter.unescape(param2); 100 101 if(DB.loginAncAccount(uname, pwd)) 102 out.println(MyConverter.escape("登录成功")); 103 else 104 out.println(MyConverter.escape("登录失败,请重试")); 105 106 %>
3、登录后,就可以开始进行传感器数据传输了。对于这部分,我们在客户端里面开启了一个service,这样就算程序退出了,service依然能够运行。
关于service,可以参考:http://android.blog.51cto.com/268543/527314
在LocalService类里面,我们又开启了一个线程,用一个while循环,使其每隔10秒钟采集并发送一次数据。通过running这个全局变量来控制启停。
1 package com.sensor; 2 3 import java.util.TreeMap; 4 5 import com.transfer.DataTransIn; 6 7 import android.app.Service; 8 import android.content.Context; 9 import android.content.Intent; 10 import android.content.SharedPreferences; 11 import android.os.IBinder; 12 13 14 /** 15 * Service类,用于传感器数据 16 * @author 林培东 17 */ 18 public class LocalService extends Service 19 { 20 public boolean running;//全局控制变量 21 public String username=null;//该用户名保存在SharePreferences中 22 23 @Override 24 public IBinder onBind(Intent arg0) 25 { 26 return null; 27 } 28 29 @Override 30 public void onCreate() 31 { 32 running=true; 33 34 //获取SharedPreferences,将用户名保存起来,方便以后使用 35 SharedPreferences sp=getSharedPreferences("actm", Context.MODE_PRIVATE); 36 username=sp.getString("uname", null); 37 38 /** 39 * 开启一个线程,每间隔一段时间则向蓝牙请求数据,然后发送数据 40 * 要停止线程,只需要把running设置为false 41 */ 42 new Thread() 43 { 44 @Override 45 public void run() 46 { 47 while(running) 48 { 49 /** 50 * 在这里获取蓝牙数据和gps数据 51 * 经纬度要先乘以10000 52 */ 53 54 DataTransIn trans=new DataTransIn("sensor_byte.xml", true);//传送类 55 String url=getResources().getString(R.string.default_url)+"ReceiveData";//准备好URL 56 57 TreeMap<String,Integer> map=new TreeMap<String,Integer>(); 58 //--------------------------------在这里先使用测试数据---------------------- 59 map.put("finger_jiasudu_x", 1); 60 map.put("finger_jiasudu_y", 2); 61 map.put("finger_jiasudu_z", 3); 62 map.put("finger_jiaosudu_x", 4); 63 map.put("finger_jiaosudu_y", 5); 64 map.put("finger_jiaosudu_z", 6); 65 map.put("finger_cili_x", 7); 66 map.put("finger_cili_y", 8); 67 map.put("finger_cili_z", 9); 68 map.put("finger_wendu", 10); 69 map.put("finger_qiya", 11); 70 71 map.put("chest_jiasudu_x", 1); 72 map.put("chest_jiasudu_y", 2); 73 map.put("chest_jiasudu_z", 3); 74 map.put("chest_jiaosudu_x", 4); 75 map.put("chest_jiaosudu_y", 5); 76 map.put("chest_jiaosudu_z", 6); 77 map.put("chest_cili_x", 7); 78 map.put("chest_cili_y", 8); 79 map.put("chest_cili_z", 9); 80 map.put("chest_wendu", 10); 81 map.put("chest_qiya", 11); 82 83 map.put("ankle_jiasudu_x", 1); 84 map.put("ankle_jiasudu_y", 2); 85 map.put("ankle_jiasudu_z", 3); 86 map.put("ankle_jiaosudu_x", 4); 87 map.put("ankle_jiaosudu_y", 5); 88 map.put("ankle_jiaosudu_z", 6); 89 map.put("ankle_cili_x", 7); 90 map.put("ankle_cili_y", 8); 91 map.put("ankle_cili_z", 9); 92 map.put("ankle_wendu", 10); 93 map.put("ankle_qiya", 11); 94 95 map.put("latitude", 100000); 96 map.put("is_north", 1); 97 map.put("longitude", 200000); 98 map.put("is_east", 1); 99 //--------------------------------------------------------------------------- 100 try{ 101 trans.syncDataToServer(map, username, url); //提交数据 102 sleep(10000); //休眠10秒钟 103 } catch(Exception e){ 104 e.printStackTrace(); 105 } 106 } 107 } 108 }.start(); //启动 109 110 super.onCreate(); 111 } 112 113 @Override 114 public void onDestroy() 115 { 116 running=false; 117 super.onDestroy(); 118 } 119 120 }
4、这里面比较关键的是候志的数据传送部分。其原理是:传感器数据范围是0~65535,如果按照一般传送的话,即使数据是int类型,在传送时都要先转换为String,比如说传输65500要占用5个字节。所以他做了一个优化,使得像65500只需要占用2个字节。
注意:要导入transfer.jar包(服务器端非常诡异地,要放在tomcat目录下的lib),sensor_byte.xml的路径要配置好,最好用全局路径。
在客户端往服务器发送数据使用的是DataTransIn类,代码如下:
1 DataTransIn trans=new DataTransIn("sensor_byte.xml", true);//传送类 2 String url=getResources().getString(R.string.default_url)+"ReceiveData";//准备好URL 3 4 TreeMap<String,Integer> map=new TreeMap<String,Integer>(); 5 //--------------------------------在这里先使用测试数据---------------------- 6 map.put("finger_jiasudu_x", 1); 7 map.put("finger_jiasudu_y", 2); 8 map.put("finger_jiasudu_z", 3); 9 map.put("finger_jiaosudu_x", 4); 10 map.put("finger_jiaosudu_y", 5); 11 map.put("finger_jiaosudu_z", 6); 12 map.put("finger_cili_x", 7); 13 map.put("finger_cili_y", 8); 14 map.put("finger_cili_z", 9); 15 map.put("finger_wendu", 10); 16 map.put("finger_qiya", 11); 17 18 map.put("chest_jiasudu_x", 1); 19 map.put("chest_jiasudu_y", 2); 20 map.put("chest_jiasudu_z", 3); 21 map.put("chest_jiaosudu_x", 4); 22 map.put("chest_jiaosudu_y", 5); 23 map.put("chest_jiaosudu_z", 6); 24 map.put("chest_cili_x", 7); 25 map.put("chest_cili_y", 8); 26 map.put("chest_cili_z", 9); 27 map.put("chest_wendu", 10); 28 map.put("chest_qiya", 11); 29 30 map.put("ankle_jiasudu_x", 1); 31 map.put("ankle_jiasudu_y", 2); 32 map.put("ankle_jiasudu_z", 3); 33 map.put("ankle_jiaosudu_x", 4); 34 map.put("ankle_jiaosudu_y", 5); 35 map.put("ankle_jiaosudu_z", 6); 36 map.put("ankle_cili_x", 7); 37 map.put("ankle_cili_y", 8); 38 map.put("ankle_cili_z", 9); 39 map.put("ankle_wendu", 10); 40 map.put("ankle_qiya", 11); 41 42 map.put("latitude", 100000); 43 map.put("is_north", 1); 44 map.put("longitude", 200000); 45 map.put("is_east", 1); 46 //--------------------------------------------------------------------------- 47 try{ 48 trans.syncDataToServer(map, username, url); //提交数据 49 sleep(10000); //休眠10秒钟 50 } catch(Exception e){ 51 e.printStackTrace(); 52 }
在服务器用DataTransOut类接收数据,然后存入数据库,代码如下:
1 public void doPost(HttpServletRequest request, HttpServletResponse response) 2 throws ServletException, IOException 3 { 4 DataTransOut t=new DataTransOut(path,false); 5 t.runResult(request.getInputStream()); 6 7 //----------------------在此处将数据插入到数据库------------------------------- 8 Connection conn=DB.getConn(); 9 Statement stmt=DB.getStatement(conn); 10 String sql="insert into sensor_data values ( now(), '"+t.getId()+"', " 11 +t.getSensorData("finger_jiasudu_x")+", " 12 +t.getSensorData("finger_jiasudu_y")+", " 13 +t.getSensorData("finger_jiasudu_z")+", " 14 +t.getSensorData("finger_jiaosudu_x")+", " 15 +t.getSensorData("finger_jiaosudu_y")+", " 16 +t.getSensorData("finger_jiaosudu_z")+", " 17 +t.getSensorData("finger_cili_x")+", " 18 +t.getSensorData("finger_cili_y")+", " 19 +t.getSensorData("finger_cili_z")+", " 20 +t.getSensorData("finger_wendu")+", " 21 +t.getSensorData("finger_qiya")+", " 22 23 +t.getSensorData("chest_jiasudu_x")+", " 24 +t.getSensorData("chest_jiasudu_y")+", " 25 +t.getSensorData("chest_jiasudu_z")+", " 26 +t.getSensorData("chest_jiaosudu_x")+", " 27 +t.getSensorData("chest_jiaosudu_y")+", " 28 +t.getSensorData("chest_jiaosudu_z")+", " 29 +t.getSensorData("chest_cili_x")+", " 30 +t.getSensorData("chest_cili_y")+", " 31 +t.getSensorData("chest_cili_z")+", " 32 +t.getSensorData("chest_wendu")+", " 33 +t.getSensorData("chest_qiya")+", " 34 35 +t.getSensorData("ankle_jiasudu_x")+", " 36 +t.getSensorData("ankle_jiasudu_y")+", " 37 +t.getSensorData("ankle_jiasudu_z")+", " 38 +t.getSensorData("ankle_jiaosudu_x")+", " 39 +t.getSensorData("ankle_jiaosudu_y")+", " 40 +t.getSensorData("ankle_jiaosudu_z")+", " 41 +t.getSensorData("ankle_cili_x")+", " 42 +t.getSensorData("ankle_cili_y")+", " 43 +t.getSensorData("ankle_cili_z")+", " 44 +t.getSensorData("ankle_wendu")+", " 45 +t.getSensorData("ankle_qiya")+", " 46 47 +((double)t.getSensorData("latitude")/10000)+", " 48 +t.getSensorData("is_north")+", " 49 +((double)t.getSensorData("longitude")/10000)+", " 50 +t.getSensorData("is_east")+")"; 51 52 System.out.println(sql);//test 53 try{ 54 DB.doUpdate(stmt, sql); 55 }catch(Exception e){ 56 e.printStackTrace(); 57 }finally{ 58 DB.closeStmt(stmt); 59 DB.closeConn(conn); 60 } 61 //----------------------插入操作结束------------------------------------------ 62 }
最后,我想说,前期我们只是想搭建一个方便数据分析的最小平台而已。尽管目前这系统容错能力不强,但够用就好。
在没有主要功能之前,任何优化都有可能是白费力气。