原创:局域网控制系统-上位机-Android手机
.java文件源码(供参考,请使用前自行作修改):
1 package com.example.hello; 2 3 import java.io.DataInputStream; 4 import java.io.DataOutputStream; 5 import java.io.IOException; 6 import java.net.Socket; 7 import java.util.Timer; 8 import java.util.TimerTask; 9 10 import android.os.Bundle; 11 import android.os.Handler; 12 import android.os.Message; 13 import android.app.Activity; 14 import android.view.KeyEvent; 15 import android.view.Menu; 16 import android.view.View; 17 import android.view.View.OnClickListener; 18 import android.widget.Button; 19 import android.widget.CompoundButton; 20 import android.widget.EditText; 21 import android.widget.ImageView; 22 import android.widget.Switch; 23 import android.widget.TextView; 24 25 public class MainActivity extends Activity { 26 27 private Switch light00,light01,light02; 28 private TextView current_ip,socketstate,notice1; 29 private int[] temperature=new int[1]; 30 private TextView[] tv_temperature=new TextView[temperature.length]; 31 32 private EditText et_ip1,et_ip2,et_ip3,et_ip4,et_port; 33 //private EditText et_deviceID; 34 private Button btn_set_ip,delete_socket,fengmingqi1,jdq_off,jdq_on; 35 private ImageView light_00,light_01,light_02; 36 private ImageView jidianqi1; 37 38 private int port = 8080; 39 private String IP=""; 40 private Socket socket=null; 41 Thread thread1=null,thread2=null; 42 private byte[] tcp_receive_buf=new byte[DataPackage_Length]; 43 private static final int DataPackage_Length=15; //只接收15个字符(数据包长度为15) 44 private DataInputStream dataInputStream=null; 45 private DataOutputStream dataOutputStream=null; 46 47 private static final String deviceID = "03"; //用于串口通信时,定义本地设备ID 48 private static final String datapackage_headflag = "A"; //用于串口通信时,定义数据包头部的验证标记 49 50 //----------通信监测----------// 51 private boolean NeedToCheckTCP = false; 52 private boolean heartbeat = false; //心跳包(用来协助监测通信是否断开) 53 private Timer timer_TCPMonitor=null; 54 55 //----------产生发送数据的间隔----------// 56 private boolean SendCMD_WaitFlag = false; 57 private Timer timer_SetSendCMD_Interval=null; 58 void SetSendCMD_Interval(int Interval) 59 { 60 timer_SetSendCMD_Interval=new Timer(); 61 timer_SetSendCMD_Interval.schedule(new TimerTask() { 62 @Override 63 public void run() { 64 SendCMD_WaitFlag = false; 65 } 66 },Interval,600000); //定时器开始工作 67 } 68 69 //----------定时器控制指令的发送----------// 70 private Timer timer_SendCMD=null; 71 72 //----------------------------通信协议----------------------------// 73 /* 74 客户端数据包格式解释(长度恒为15): 75 例如:A01_fmq_01Off___# 76 A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种) 77 01-----设备代号 78 fmq_01Off___--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部 79 #---------数据包的结束标记 80 81 服务器端数据包格式解释(长度恒为15): 82 例如:A02_SenT010250# 83 A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种) 84 02-----设备代号 85 SenT010250--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部 86 #---------数据包的结束标记 87 */ 88 89 //---------------------------------固定发送数据包集------------------------------// 90 private static final String tcp_data_try=datapackage_headflag+deviceID+"_Try!______#"; 91 private static final String tcp_data_SenT00=datapackage_headflag+deviceID+"_SenT00____#"; 92 private static final String tcp_data_fmq00off=datapackage_headflag+deviceID+"_fmq_00Off_#"; 93 private static final String tcp_data_fmq00on=datapackage_headflag+deviceID+"_fmq_00On__#"; 94 private static final String tcp_data_jdq00off=datapackage_headflag+deviceID+"_jdq_00Off_#"; 95 private static final String tcp_data_jdq00on=datapackage_headflag+deviceID+"_jdq_00On__#"; 96 private static final String tcp_data_light00on=datapackage_headflag+deviceID+"_Ligt00On__#"; 97 private static final String tcp_data_light00off=datapackage_headflag+deviceID+"_Ligt00Off_#"; 98 private static final String tcp_data_light01on=datapackage_headflag+deviceID+"_Ligt01On__#"; 99 private static final String tcp_data_light01off=datapackage_headflag+deviceID+"_Ligt01Off_#"; 100 private static final String tcp_data_light02on=datapackage_headflag+deviceID+"_Ligt02On__#"; 101 private static final String tcp_data_light02off=datapackage_headflag+deviceID+"_Ligt02Off_#"; 102 private static final String tcp_data_socketoff=datapackage_headflag+deviceID+"_SockOff__#"; 103 104 private boolean connectflag=false; 105 private boolean openfmq00=false; 106 107 @Override 108 protected void onCreate(Bundle savedInstanceState) { 109 super.onCreate(savedInstanceState); 110 setContentView(R.layout.activity_main); 111 112 current_ip=(TextView)findViewById(R.id.tv_current_ip); 113 socketstate=(TextView)findViewById(R.id.tv_socketstate); 114 notice1=(TextView)findViewById(R.id.tv_notice1); 115 tv_temperature[0]=(TextView)findViewById(R.id.tv_temperature00); 116 et_ip1=(EditText)findViewById(R.id.et_ip1); 117 et_ip2=(EditText)findViewById(R.id.et_ip2); 118 et_ip3=(EditText)findViewById(R.id.et_ip3); 119 et_ip4=(EditText)findViewById(R.id.et_ip4); 120 et_port=(EditText)findViewById(R.id.et_port); 121 //et_deviceID=(EditText)findViewById(R.id.et_deviceID); 122 btn_set_ip=(Button)findViewById(R.id.btn_setip); 123 delete_socket=(Button)findViewById(R.id.btn_deletesocket); 124 fengmingqi1=(Button)findViewById(R.id.btn_fmq1); 125 jdq_off=(Button)findViewById(R.id.btn_jidianqi_off); 126 jdq_on=(Button)findViewById(R.id.btn_jidianqi_on); 127 light00=(Switch)findViewById(R.id.sw_light00); 128 light01=(Switch)findViewById(R.id.sw_light01); 129 light02=(Switch)findViewById(R.id.sw_light02); 130 light_00=(ImageView)findViewById(R.id.image_light00); 131 light_01=(ImageView)findViewById(R.id.image_light01); 132 light_02=(ImageView)findViewById(R.id.image_light02); 133 jidianqi1=(ImageView)findViewById(R.id.image_jidianqi1); 134 135 current_ip.setText("暂无"); 136 137 light00.setTextOff("关闭"); 138 light00.setTextOn("打开"); 139 light01.setTextOff("关闭"); 140 light01.setTextOn("打开"); 141 light02.setTextOff("关闭"); 142 light02.setTextOn("打开"); 143 144 light00.setEnabled(false); 145 light01.setEnabled(false); 146 light02.setEnabled(false); 147 148 //控制light 149 light00.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 150 @Override 151 public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) { 152 light00.setEnabled(false); 153 if(light00.isChecked()){ 154 if(tcp_send_data(tcp_data_light00on,4)){ 155 light_00.setImageDrawable(getResources().getDrawable(R.drawable.open_light)); 156 light00.setEnabled(true); //涉及到UI操作,但此行代码是主线程执行的,所以不会导致程序崩毁 157 } 158 } 159 else{ 160 if(tcp_send_data(tcp_data_light00off,4)){ 161 light_00.setImageDrawable(getResources().getDrawable(R.drawable.close_light)); 162 light00.setEnabled(true); 163 } 164 } 165 } 166 }); 167 //控制light 168 light01.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 169 @Override 170 public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) { 171 light01.setEnabled(false); 172 if(light01.isChecked()){ 173 if(tcp_send_data(tcp_data_light01on,4)){ 174 light_01.setImageDrawable(getResources().getDrawable(R.drawable.open_light)); 175 light01.setEnabled(true); 176 } 177 } 178 else{ 179 if(tcp_send_data(tcp_data_light01off,4)){ 180 light_01.setImageDrawable(getResources().getDrawable(R.drawable.close_light)); 181 light01.setEnabled(true); 182 } 183 } 184 } 185 }); 186 //控制light 187 light02.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 188 @Override 189 public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) { 190 light02.setEnabled(false); 191 if(light02.isChecked()){ 192 if(tcp_send_data(tcp_data_light02on,4)){ 193 light_02.setImageDrawable(getResources().getDrawable(R.drawable.open_light)); 194 light02.setEnabled(true); 195 } 196 } 197 else{ 198 if(tcp_send_data(tcp_data_light02off,4)){ 199 light_02.setImageDrawable(getResources().getDrawable(R.drawable.close_light)); 200 light02.setEnabled(true); 201 } 202 } 203 } 204 }); 205 //测试蜂鸣器 206 fengmingqi1.setOnClickListener(new OnClickListener() { 207 @Override 208 public void onClick(View arg0) { 209 if(connectflag==true){ 210 if(openfmq00==true){ 211 if(tcp_send_data(tcp_data_fmq00off,3000)){ 212 openfmq00=false; 213 fengmingqi1.setText("启动蜂鸣器"); 214 } 215 } 216 else{ 217 if(tcp_send_data(tcp_data_fmq00on,4)){ 218 openfmq00=true; 219 fengmingqi1.setText("关闭蜂鸣器"); 220 } 221 } 222 } 223 } 224 }); 225 //控制继电器 226 jdq_off.setOnClickListener(new OnClickListener() { 227 @Override 228 public void onClick(View arg0) { 229 if(connectflag==true){ 230 if(tcp_send_data(tcp_data_jdq00off,4)){ 231 jidianqi1.setImageDrawable(getResources().getDrawable(R.drawable.jidianqi_off)); 232 } 233 } 234 } 235 }); 236 //控制继电器 237 jdq_on.setOnClickListener(new OnClickListener() { 238 @Override 239 public void onClick(View arg0) { 240 if(connectflag==true){ 241 if(tcp_send_data(tcp_data_jdq00on,4)){ 242 jidianqi1.setImageDrawable(getResources().getDrawable(R.drawable.jidianqi_on)); 243 } 244 } 245 } 246 }); 247 //建立socket连接 248 btn_set_ip.setOnClickListener(new OnClickListener() { 249 @Override 250 public void onClick(View arg0) { 251 setsocket(); 252 } 253 }); 254 //删除socket 255 delete_socket.setOnClickListener(new OnClickListener() { 256 @Override 257 public void onClick(View arg0) { 258 if(connectflag==true){ 259 tcp_send_data(tcp_data_socketoff,4); 260 DeleteSocket(); 261 Message message=new Message(); 262 message.what=5; 263 handler.sendMessage(message); //发送Messgae给与主线程绑定的handler,让主线程来作出响应,主要是让主线程做一些UI的操作 264 } 265 } 266 }); 267 } 268 269 /*----------------设置按返回键会将程序后台运行而不是关闭-------------------*/ 270 public boolean onKeyDown(int keyCode, KeyEvent event) { 271 if (keyCode == KeyEvent.KEYCODE_BACK) { 272 moveTaskToBack(false); //false保留后台运行 true不保留后台运行 273 return true; 274 } 275 return super.onKeyDown(keyCode, event); 276 } 277 /*---------------------------------------------------------------------------*/ 278 279 /*------------------------------自定义函数---------------------------------*/ 280 //TCP发送数据,返回一个布尔值,用来确定是否发送数据成功 281 boolean tcp_send_data(String str,int MinInterval){ 282 while(SendCMD_WaitFlag); //等待结束上一次发送数据所要求的间隔,以保证每次发送出去的数据包都能被正确接收处理 try{ 283 if(timer_SetSendCMD_Interval != null){ 284 timer_SetSendCMD_Interval.cancel(); //注意:timer对象在没有工作的时候,不能对其进行cancel,否则会导致程序崩毁 285 timer_SetSendCMD_Interval=null; 286 } 287 //SendCMD_WaitFlag = true; 288 try{ 289 dataOutputStream.write(str.getBytes()); 290 dataOutputStream.flush(); 291 SetSendCMD_Interval(MinInterval); 292 return true; 293 } 294 catch(IOException e){ 295 Message message=new Message(); 296 message.what=3; 297 message.obj="socket连接失败!"; 298 handler.sendMessage(message); 299 DeleteSocket(); 300 SendCMD_WaitFlag = false; 301 return false; 302 } 303 } 304 305 void DeleteSocket(){ 306 connectflag=false; 307 SendCMD_WaitFlag = false; 308 if(timer_TCPMonitor!=null){timer_TCPMonitor.cancel();timer_TCPMonitor=null;} 309 if(timer_SendCMD!=null){timer_SendCMD.cancel();timer_SendCMD=null;} 310 if(socket!=null) { try{socket.close();}catch(IOException a){}} 311 if(thread2!=null) { thread2.interrupt(); thread2=null;} //destroy和stop方法对于thread类对象来说都是不可取的 312 if(thread1!=null) { thread1.interrupt(); thread1=null;} //先暂停线程的运行,然后再解除线程映射 313 } 314 private void startConnected() 315 { 316 //建立连接前进行初始化 317 DeleteSocket(); 318 319 thread2=new Thread(new Runnable() { //创建一个没有标识符映射的子线程,因为创建socket是不能交给主线程来实现的 320 public void run() { 321 try{ 322 socket=new Socket(IP,port); //建立SOCKET连接 323 socket.setSoTimeout(1000); //在对socket输入流进行读操作的时候,会尝试进行1000ms的读取操作 324 325 dataInputStream=new DataInputStream(socket.getInputStream()); //创建输入数据流 326 dataOutputStream=new DataOutputStream(socket.getOutputStream()); //创建输出数据流 327 } 328 //catch(SocketTimeoutException e){} 329 catch (IOException e) { 330 Message message=new Message(); 331 message.what=3; 332 message.obj="socket连接失败!"; 333 handler.sendMessage(message); 334 return; 335 } 336 337 //刚开始创建连接,进行一次连接测试,检查是否连接成功 338 if(tcp_send_data(tcp_data_try,30)){ 339 Message message=new Message(); 340 connectflag=true; 341 message.what=4; 342 handler.sendMessage(message); 343 } 344 else{ 345 return; 346 } 347 348 //--------------------------建立连接后进行初始化--------------------------// 349 //不断尝试读取接收缓冲区的数据 350 TryRead_ReceivedBuffer(); 351 //每隔1000ms获取一次温度值数据 352 timer_SendCMD=new Timer(); 353 timer_SendCMD.schedule(new TimerTask() { //定时器要执行的任务尽可能在以这种方式设定,以免出现麻烦 354 @Override 355 public void run() { 356 tcp_send_data(tcp_data_SenT00,60); //建议获取一次温度值后产生60ms发送间隔 357 } 358 },100,1000); 359 //循环发送特定数据包出去,根据反馈以确定是否断开连接,如果反馈到心跳包,则表明连接没有断开 360 NeedToCheckTCP = false; 361 timer_TCPMonitor=new Timer(); 362 timer_TCPMonitor.schedule(new TimerTask() { //定时器要执行的任务尽可能在以这种方式设定,以免出现麻烦 363 @Override 364 public void run() { 365 Message message=new Message(); 366 if (NeedToCheckTCP) //检查是否接收到心跳包 367 { 368 NeedToCheckTCP = false; 369 if (heartbeat) 370 { 371 heartbeat = false; 372 } 373 else 374 { 375 DeleteSocket(); 376 message.what=3; 377 message.obj="已断开连接,因为没有接收到心跳包!"; 378 handler.sendMessage(message); 379 } 380 } 381 else //请求接收者反馈心跳包,以确认连接是否出现异常 382 { 383 NeedToCheckTCP = true; 384 tcp_send_data(tcp_data_try,25); 385 } 386 } 387 },2000,2000); 388 } 389 }); 390 thread2.start(); 391 } 392 //更新UI这种操作必须由主线程来实现,否则会导致程序崩毁 393 private Handler handler = new Handler(){ 394 @Override 395 public void handleMessage(Message msg){ 396 switch(msg.what){ 397 case 1: 398 if(temperature[msg.arg1]<0){ 399 tv_temperature[msg.arg1].setText(Integer.toString(temperature[msg.arg1] / 10) + "." + Integer.toString((temperature[msg.arg1] % 10)*(-1)) + "℃"); 400 } 401 else{ 402 tv_temperature[msg.arg1].setText("+"+Integer.toString(temperature[msg.arg1] / 10) + "." + Integer.toString((temperature[msg.arg1] % 10)) + "℃"); 403 } 404 notice1.setText(msg.obj.toString()); 405 break; 406 case 2: 407 408 break; 409 case 3: 410 light00.setEnabled(false); 411 light01.setEnabled(false); 412 light02.setEnabled(false); 413 notice1.setText(msg.obj.toString()); 414 socketstate.setText(" 未连接!"); 415 break; 416 case 4: 417 notice1.setText("socket连接成功!"); 418 socketstate.setText(" 已连接!"); 419 light00.setEnabled(true); 420 light01.setEnabled(true); 421 light02.setEnabled(true); 422 break; 423 case 5: 424 light00.setEnabled(false); 425 light01.setEnabled(false); 426 light02.setEnabled(false); 427 notice1.setText("手动断开连接!"); 428 socketstate.setText(" 未连接!"); 429 break; 430 case 6: 431 //temperature[0].setText(Integer.toString(num++)); //测试专用 432 notice1.setText(msg.obj.toString()); //之所以要加toString()是因为msg.obj是指一个通用对象,必须要对这个通用对象转换成某类对象才能被使用 433 break; 434 default: 435 436 break; 437 } 438 } 439 }; 440 //处理串口接收数据包函数(成功处理数据包则返回true,否则返回false) 441 public boolean Deal_UART_RecData(String ReceStr){ 442 Message message=new Message(); 443 if(ReceStr.length()==DataPackage_Length){ 444 if(ReceStr.substring(0, 1).equals(datapackage_headflag)&&(ReceStr.substring(14, 15).equals("#"))){ //数据包头尾标记验证 445 try{ 446 switch(Integer.parseInt(ReceStr.substring(1, 2))){ //识别设备D的第1位数字 447 case 0: 448 switch(Integer.parseInt(ReceStr.substring(2, 3))){ //识别设备ID的第2位数字 449 case 2: 450 if(ReceStr.substring(4, 8).equals("SenT")){ //判断指令头部是否为"SenT" A02_SenT00-245# 451 try{ //注意:"-12"转int类型正确 ,“+12”转int类型异常 ,"12"转int类型正确 452 message.arg1=Integer.parseInt(ReceStr.substring(8, 10)); 453 if(message.arg1<tv_temperature.length){ 454 temperature[message.arg1]=Integer.parseInt(ReceStr.substring(10, 14)); 455 message.obj="更新温度传感器值成功"; 456 message.what=1; 457 handler.sendMessage(message); //请求主线程进行UI操作,以处理接收到的数据 458 return true; 459 } 460 } 461 catch(NumberFormatException b) //:string转int异常 462 { 463 message.what=6; 464 message.obj="接收的指令:指令尾部异常"; 465 handler.sendMessage(message); //请求主线程进行UI操作,以处理接收到的数据 466 return false; 467 } 468 } 469 if(ReceStr.substring(4, 8).equals("Beat")){ //判断指令头部是否为"Beat" 470 heartbeat = true; 471 return true; 472 } 473 message.what=6; 474 message.obj="接收的指令:指令头部异常"; 475 handler.sendMessage(message); //请求主线程进行UI操作,以处理接收到的数据 476 return false; 477 default: 478 message.what=6; 479 message.obj="接收的数据包:设备ID异常"; 480 handler.sendMessage(message); //请求主线程进行UI操作,以处理接收到的数据 481 return false; 482 } 483 default: 484 message.what=6; 485 message.obj="接收的数据包:设备ID异常"; 486 handler.sendMessage(message); //请求主线程进行UI操作,以处理接收到的数据 487 return false; 488 } 489 } 490 catch(NumberFormatException b){ //:string转int异常 491 message.what=6; 492 message.obj="接收的数据包:设备ID异常"; 493 handler.sendMessage(message); //请求主线程进行UI操作,以处理接收到的数据 494 return false; 495 } 496 497 } 498 message.what=6; 499 message.obj="接收的数据包:头尾标记验证异常"; 500 handler.sendMessage(message); //请求主线程进行UI操作,以处理接收到的数据 501 return false; 502 } 503 message.what=6; 504 message.obj="接收的数据包:长度异常"; 505 handler.sendMessage(message); //请求主线程进行UI操作,以处理接收到的数据 506 return false; 507 } 508 private void TryRead_ReceivedBuffer(){ 509 thread1=new Thread(new Runnable() { 510 @Override 511 public void run() { 512 while (socket!=null&&!socket.isClosed()) { //循环检测是否接收到新的数据 513 if(dataInputStream!=null) 514 { 515 try { 516 //为保证正确处理接收到的数据,2次接收的间隔必须要足够大(如要涉及费时操作建议2秒),即要保证接收缓冲区不能出现一条或以上的指令,不然就是多指令混在缓冲区,那么读出来的时候,相当于是把多条指令同时进行处理,这会出错 517 dataInputStream.read(tcp_receive_buf); //循环尝试读取接收缓冲区的数据,每次尝试持续时间为1s,假如有数据来到,则将数据读到数组里去,缓冲区自动清除读过的字节,时间到了却没有数据来到,则抛出异常 518 519 String receive_str=new String(tcp_receive_buf); //将tcp_receive_buf数组的值进行映射,转换出string,注意:空字符也会进行映射 520 for(byte i=0;i<15;i++){ //清空tcp_receive_buf数组 521 tcp_receive_buf[i]=0; 522 } 523 //下面尝试对接收到的数据包(receive_str)进行处理 524 if(Deal_UART_RecData(receive_str)){ 525 526 } 527 else{ 528 529 } 530 } 531 catch (IOException e) { 532 //如果没有接收到数据则执行下面的代码 533 534 } 535 } 536 } 537 } 538 }); 539 thread1.start(); 540 } 541 private void setsocket() { 542 String ip1 = et_ip1.getText().toString(); 543 String ip2 = et_ip2.getText().toString(); 544 String ip3 = et_ip3.getText().toString(); 545 String ip4 = et_ip4.getText().toString(); 546 String port = et_port.getText().toString(); 547 548 if (isIP(ip1) && isIP(ip2) && isIP(ip3) && isIP(ip4) && isPort(port)) 549 { 550 IP = ip1 + "." + ip2 + "." + ip3 + "." + ip4; 551 current_ip.setText(IP + ":" + port); 552 startConnected(); 553 554 } 555 else { 556 //Toast.makeText(this, "IP或Port输入有误", Toast.LENGTH_SHORT).show(); 557 socketstate.setText("IP或Port格式输入有误!"); 558 } 559 } 560 //port格式检查 561 private boolean isPort(String s) { 562 int i = -1; 563 try { 564 i = Integer.parseInt(s); 565 } catch (NumberFormatException e) { 566 e.printStackTrace(); 567 return false; 568 } 569 if ((i > 0) && (i<65536)) { 570 port = i; // 设置端口 571 return true; 572 } 573 else { 574 return false; 575 } 576 } 577 //IP格式检查 578 private boolean isIP(String s) { 579 int i = -1; 580 try { 581 i = Integer.parseInt(s); 582 } 583 catch (NumberFormatException e) { 584 e.printStackTrace(); 585 return false; 586 } 587 if ((i >= 0) && (i < 256)) { 588 return true; 589 } 590 else { 591 return false; 592 } 593 } 594 /*--------------------------------------------------------------------------------*/ 595 596 @Override 597 public boolean onCreateOptionsMenu(Menu menu) { 598 // Inflate the menu; this adds items to the action bar if it is present. 599 getMenuInflater().inflate(R.menu.main, menu); 600 return true; 601 } 602 603 }
.XML文件源码(供参考,请使用前自行作修改):
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:id="@+id/LinearLayout1" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:orientation="vertical" 7 android:paddingBottom="@dimen/activity_vertical_margin" 8 android:paddingLeft="@dimen/activity_horizontal_margin" 9 android:paddingRight="@dimen/activity_horizontal_margin" 10 android:paddingTop="@dimen/activity_vertical_margin" 11 tools:context=".MainActivity" > 12 13 <LinearLayout 14 android:layout_width="match_parent" 15 android:layout_height="wrap_content" > 16 17 <TextView 18 android:id="@+id/textView1" 19 android:layout_width="wrap_content" 20 android:layout_height="wrap_content" 21 android:text="当前连接:" /> 22 23 <TextView 24 android:id="@+id/tv_current_ip" 25 android:layout_width="wrap_content" 26 android:layout_height="wrap_content" 27 android:layout_weight="0.28" 28 android:text="暂无" 29 android:textSize="15sp" /> 30 31 </LinearLayout> 32 33 <LinearLayout 34 android:layout_width="match_parent" 35 android:layout_height="wrap_content" > 36 37 <TextView 38 android:id="@+id/textView3" 39 android:layout_width="wrap_content" 40 android:layout_height="wrap_content" 41 android:text="IP:" /> 42 43 <EditText 44 android:id="@+id/et_ip1" 45 android:layout_width="wrap_content" 46 android:layout_height="wrap_content" 47 android:layout_weight="1" 48 android:text="192" 49 android:ems="10" > 50 51 <requestFocus /> 52 </EditText> 53 54 <TextView 55 android:id="@+id/textView4" 56 android:layout_width="wrap_content" 57 android:layout_height="wrap_content" 58 android:text="." /> 59 60 <EditText 61 android:id="@+id/et_ip2" 62 android:layout_width="wrap_content" 63 android:layout_height="wrap_content" 64 android:layout_weight="1" 65 android:text="168" 66 android:ems="10" /> 67 68 <TextView 69 android:id="@+id/textView5" 70 android:layout_width="wrap_content" 71 android:layout_height="wrap_content" 72 android:text="." /> 73 74 <EditText 75 android:id="@+id/et_ip3" 76 android:layout_width="wrap_content" 77 android:layout_height="wrap_content" 78 android:layout_weight="1" 79 android:ems="10" /> 80 81 <TextView 82 android:id="@+id/textView6" 83 android:layout_width="wrap_content" 84 android:layout_height="wrap_content" 85 android:text="." /> 86 87 <EditText 88 android:id="@+id/et_ip4" 89 android:layout_width="wrap_content" 90 android:layout_height="wrap_content" 91 android:layout_weight="1" 92 android:ems="10" /> 93 </LinearLayout> 94 95 <LinearLayout 96 android:layout_width="match_parent" 97 android:layout_height="wrap_content" > 98 99 <TextView 100 android:id="@+id/textView7" 101 android:layout_width="wrap_content" 102 android:layout_height="wrap_content" 103 android:text="PORT" /> 104 105 <EditText 106 android:id="@+id/et_port" 107 android:layout_width="76dp" 108 android:layout_height="wrap_content" 109 android:ems="10" /> 110 111 <Button 112 android:id="@+id/btn_setip" 113 android:layout_width="92dp" 114 android:layout_height="wrap_content" 115 android:text="连接" /> 116 117 <Button 118 android:id="@+id/btn_deletesocket" 119 android:layout_width="match_parent" 120 android:layout_height="wrap_content" 121 android:text="断开" /> 122 </LinearLayout> 123 124 <TextView 125 android:id="@+id/textView2" 126 android:layout_width="wrap_content" 127 android:layout_height="wrap_content" 128 android:text="下面是控制面板:" /> 129 130 <LinearLayout 131 android:layout_width="match_parent" 132 android:layout_height="wrap_content" > 133 134 <TextView 135 android:id="@+id/textView8" 136 android:layout_width="wrap_content" 137 android:layout_height="wrap_content" 138 android:layout_gravity="right" 139 android:layout_marginLeft="70dp" 140 android:text="温度传感器值:" /> 141 142 <TextView 143 android:id="@+id/tv_temperature00" 144 android:layout_width="wrap_content" 145 android:layout_height="wrap_content" 146 android:layout_weight="2" 147 android:text="暂无" /> 148 149 </LinearLayout> 150 151 <LinearLayout 152 android:layout_width="match_parent" 153 android:layout_height="wrap_content" > 154 155 <ImageView 156 android:id="@+id/image_light00" 157 android:layout_width="74dp" 158 android:layout_height="66dp" 159 android:layout_weight="1" 160 android:src="@drawable/close_light" /> 161 162 <ImageView 163 android:id="@+id/image_light01" 164 android:layout_width="74dp" 165 android:layout_height="66dp" 166 android:layout_weight="1" 167 android:src="@drawable/close_light" /> 168 169 <ImageView 170 android:id="@+id/image_light02" 171 android:layout_width="74dp" 172 android:layout_height="66dp" 173 android:layout_weight="1" 174 android:src="@drawable/close_light" /> 175 </LinearLayout> 176 177 <LinearLayout 178 android:layout_width="match_parent" 179 android:layout_height="wrap_content" > 180 181 <Switch 182 android:id="@+id/sw_light00" 183 android:layout_width="wrap_content" 184 android:layout_height="wrap_content" 185 android:layout_weight="1" /> 186 187 <Switch 188 android:id="@+id/sw_light01" 189 android:layout_width="wrap_content" 190 android:layout_height="wrap_content" 191 android:layout_weight="1" /> 192 193 <Switch 194 android:id="@+id/sw_light02" 195 android:layout_width="wrap_content" 196 android:layout_height="wrap_content" 197 android:layout_weight="1" /> 198 </LinearLayout> 199 200 <LinearLayout 201 android:layout_width="match_parent" 202 android:layout_height="wrap_content" > 203 204 <Button 205 android:id="@+id/btn_jidianqi_on" 206 android:layout_width="wrap_content" 207 android:layout_height="wrap_content" 208 android:layout_gravity="bottom" 209 android:layout_weight="1" 210 android:text="吸合" /> 211 212 <ImageView 213 android:id="@+id/image_jidianqi1" 214 android:layout_width="wrap_content" 215 android:layout_height="86dp" 216 android:layout_weight="3.08" 217 android:src="@drawable/jidianqi_off" /> 218 219 <Button 220 android:id="@+id/btn_jidianqi_off" 221 android:layout_width="wrap_content" 222 android:layout_height="wrap_content" 223 android:layout_gravity="bottom" 224 android:layout_weight="1" 225 android:text="断开" /> 226 </LinearLayout> 227 228 <Button 229 android:id="@+id/btn_fmq1" 230 android:layout_width="wrap_content" 231 android:layout_height="wrap_content" 232 android:layout_gravity="center_horizontal" 233 android:text="启动蜂鸣器" /> 234 235 <LinearLayout 236 android:layout_width="match_parent" 237 android:layout_height="wrap_content" > 238 239 <TextView 240 android:id="@+id/textView9" 241 android:layout_width="wrap_content" 242 android:layout_height="wrap_content" 243 android:text="当前连接状态:" /> 244 245 <TextView 246 android:id="@+id/tv_socketstate" 247 android:layout_width="wrap_content" 248 android:layout_height="wrap_content" 249 android:text="未连接" /> 250 251 </LinearLayout> 252 253 <LinearLayout 254 android:layout_width="match_parent" 255 android:layout_height="wrap_content" > 256 257 <TextView 258 android:id="@+id/textView10" 259 android:layout_width="wrap_content" 260 android:layout_height="wrap_content" 261 android:text="消息通知栏:" /> 262 263 <TextView 264 android:id="@+id/tv_notice1" 265 android:layout_width="wrap_content" 266 android:layout_height="wrap_content" 267 android:text="" /> 268 269 </LinearLayout> 270 271 </LinearLayout>
程序界面如下:
与ESP8266透传模块(作socket服务器端)连接后,对单片机进行远程控制。
想要完整工程文件或疑问可以私聊我~
请另外观看项目的2个部分:
1)局域网控制系统-下位机-单片机
2)局域网控制系统-上位机-PC机
尊重作者的劳动,转载请记得注明来源:http://www.cnblogs.com/weifeng727/p/5618100.html