局域网控制系统-上位机-Android手机
Posted weifeng727
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了局域网控制系统-上位机-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); 42以上是关于局域网控制系统-上位机-Android手机的主要内容,如果未能解决你的问题,请参考以下文章
5-网络芯片CH395Q学习开发-模块使用Socket0作为TCP客户端和电脑上位机TCP服务器局域网通信
新版H7-TOOL开始支持外网控制,用户可以在任何地方使用TOOL上位机访问处于外网其它地方的TOOL,展示外网远程控制H7-TOOL脱机下载效果展示