设置从蓝牙发送和接收数据之间的延迟
set delay between send and receive data from bluetooth
我设置了一个程序,使用 SPP 通过蓝牙将数据从 android 应用程序发送到微控制器。提到的微控制器设备在处理时间为 150 毫秒后发回响应。我的应用程序通过蓝牙响应处理程序收到适当的响应,因为 RecieveBuffer.And 应用程序必须再次发送数据以防微控制器未发送适当的数据。我使用如下的 while 条件语句交替发送数据,直到获得响应(在应用程序通过蓝牙响应处理程序 class 获得适当响应后,发送标志为真)。
while(!SendFlag) SendData( SendBuffer+"\r" );
有一个程序,我的程序连续发送数据,蓝牙响应处理程序从未收到任何响应,因为 while
语句检查发送标志(send flag
在应用程序获得适当响应后为真)。
如何设置让我的应用程序等待响应的延迟?我的意思是我必须发送数据并等待响应,如果响应不可接受我必须再次发送数据。
没有while
语句,我可以发送数据并得到响应。但我也必须检查接收到的数据是否可以接受。
package com.np.schoolbell;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.icu.text.SimpleDateFormat;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import ir.mirrajabi.persiancalendar.PersianCalendarView;
import ir.mirrajabi.persiancalendar.core.PersianCalendarHandler;
import ir.mirrajabi.persiancalendar.core.models.PersianDate;
public class ledControl extends AppCompatActivity {
EditText et_SendData;
static TextView tv_DataReaded;
PersianCalendarView persianCalendarView;
PersianCalendarHandler calendar;
PersianDate today;
PersianDate sampleday;
List days;
String address = null;
static String TransmiterCode="999";
static String SendBuffer=null;
static String RecieveBuffer=null;
static int Counter=0;
static boolean SendFlag=false;
BluetoothAdapter bAdapter = null;
BluetoothDevice bDevice = null;
BluetoothSocket bSocket = null;
static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); //SPP UUID. Look for it
ConnectedThread cThread;
private static BluetoothResponseHandler brHandler;
private final static int DataIsReady = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_led_control);
persianCalendarView = (PersianCalendarView)findViewById(R.id.persian_calendar2);
calendar = persianCalendarView.getCalendar();
today = calendar.getToday();
//days=calendar.getDays(1);
//Toast.makeText(this, days.toString(), Toast.LENGTH_LONG).show();
//today.setDate(1398,05,01);
//Toast.makeText(this, today.toString(), Toast.LENGTH_LONG).show();
et_SendData = (EditText) findViewById(R.id.et_SendData);
tv_DataReaded = (TextView) findViewById(R.id.tv_DataReaded);
address = getIntent().getStringExtra( "device_address" );
bAdapter = BluetoothAdapter.getDefaultAdapter();
try {
Toast.makeText(getApplicationContext(), "Connecting...", Toast.LENGTH_SHORT).show();
if( bSocket == null ) {
bDevice = bAdapter.getRemoteDevice(address);
bSocket = bDevice.createInsecureRfcommSocketToServiceRecord(myUUID);
bAdapter.cancelDiscovery();
bSocket.connect();
}
Toast.makeText(getApplicationContext(), "Connected", Toast.LENGTH_SHORT).show();
}
catch (Exception e) {
Toast.makeText(getApplicationContext(), "Connection Failed. Is it a SPP Bluetooth? Try again.", Toast.LENGTH_SHORT).show();
finish();
}
cThread = new ConnectedThread(bSocket);
cThread.start();
if (brHandler == null) brHandler = new BluetoothResponseHandler(this);
else brHandler.setTarget(this);
}
public void onClick_btn_SendData( View v ) {
SendBuffer=LoadDateTimeBuffer();
while(!SendFlag) SendData( SendBuffer+"\r" );
SendBuffer=LoadAZanSetting();
while(!SendFlag) SendData( SendBuffer+"\r" );
et_SendData.setText("");
}
public String LoadDateTimeBuffer(){
SendFlag=false;
TransmiterCode="420";
SimpleDateFormat sdf = new SimpleDateFormat("HHmmss", Locale.getDefault());
String currentTime = sdf.format(new Date());
String currentDate=ParseFaDigits.convert(calendar.formatNumber(today.getYear()))+ParseFaDigits.convert(calendar.formatNumber(today.getMonth()))+ParseFaDigits.convert(calendar.formatNumber(today.getDayOfMonth()));
return TransmiterCode+currentTime+currentDate;
}
public String LoadAZanSetting(){
SendFlag=false;
TransmiterCode="421";
boolean fajrflag=true;boolean tolueflag=true;boolean zuhrflag=true;boolean maghribflag=true;boolean ishaflag=true;
String FajrFlagString = (fajrflag) ? "1" : "0";
String TolueFlagString = (tolueflag) ? "1" : "0";
String ZuhrFlagString = (zuhrflag) ? "1" : "0";
String MaghribFlagString = (maghribflag) ? "1" : "0";
String IshaFlagString = (ishaflag) ? "1" : "0";
return TransmiterCode+FajrFlagString+TolueFlagString+ZuhrFlagString+MaghribFlagString+IshaFlagString;
}
public void SendData(String Data) {
if( bSocket != null ) {
try {
bSocket.getOutputStream().write(Data.getBytes());
}
catch (Exception e) {
Toast.makeText(getApplicationContext(), "Error in Send Data", Toast.LENGTH_LONG).show();
}
}
else {
Toast.makeText(getApplicationContext(), "Bluetooth is Not Connected", Toast.LENGTH_LONG).show();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if( bSocket == null ) return;
if( bSocket.isConnected() ) {
Disconnect();
}
}
public void onClick_Bluetooth_btn_Disconnect( View v ) {
Disconnect();
}
public void Disconnect() {
if ( bSocket != null && bSocket.isConnected() ) {
try {
bSocket.close();
Toast.makeText(getApplicationContext(), "Disconnected", Toast.LENGTH_SHORT).show();
}
catch( IOException e ) {
Toast.makeText(getApplicationContext(), "Error in Disconnecting ", Toast.LENGTH_SHORT).show();
}
}
finish();
}
public static class ConnectedThread extends Thread {
private BluetoothSocket mmSocket;
private InputStream mmInStream;
private OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
//Tell other phone that we have connected
write("connected".getBytes());
}
public void run() {
byte[] buffer = new byte[512];
int bytes;
StringBuilder readMessage = new StringBuilder();
while( !this.isInterrupted() ) {
try {
bytes = mmInStream.read(buffer);
String readed = new String(buffer, 0, bytes);
readMessage.append(readed);
if (readed.contains("\r")) {
brHandler.obtainMessage(ledControl.DataIsReady, bytes, -1, readMessage.toString()).sendToTarget();
readMessage.setLength(0);
}
} catch (Exception e) {
break;
}
}
}
// Call this from the main activity to send data to the remote device
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
// Call this from the main activity to shutdown the connection
public void cancel() {
if (mmInStream != null) {
try {mmInStream.close();} catch (Exception e) {}
mmInStream = null;
}
if (mmOutStream != null) {
try {mmOutStream.close();} catch (Exception e) {}
mmOutStream = null;
}
if (mmSocket != null) {
try {mmSocket.close();} catch (Exception e) {}
mmSocket = null;
}
this.interrupt();
}
}
private static class BluetoothResponseHandler extends Handler {
private WeakReference<ledControl> mActivity;
public BluetoothResponseHandler(ledControl activity) {
mActivity = new WeakReference<ledControl>(activity);
}
public void setTarget(ledControl target) {
mActivity.clear();
mActivity = new WeakReference<ledControl>(target);
}
@Override
public void handleMessage(Message msg) {
ledControl activity = mActivity.get();
String Data = (String)msg.obj;
if (activity != null) {
switch (msg.what) {
case DataIsReady :
if( Data == null ) return;
RecieveBuffer=Data;
if(RecieveBuffer.contains(SendBuffer))
{
tv_DataReaded.append(Data);
SendFlag=true;
TransmiterCode="";
SendBuffer="";
RecieveBuffer="";
}
else
{
SendFlag=false;
}
break;
}
}
}
}
}
非常感谢您。
我找到了解决上述问题的方法,因此我应用了一个 CountDownTimer,它每 1 秒到 3 秒发送一次数据,如果发送的数据和响应都正常,定时器将被取消以避免浪费时间。在正常情况下,此计时器会在应用程序收到适当的响应后发送一次数据。
SendBuffer=LoadDateTimeBuffer();
CountDownTimer yourCountDownTimer=new CountDownTimer(3000, 1000) {
public void onFinish() {
Toast.makeText(ledControl.this, "Error", Toast.LENGTH_SHORT).show();
}
public void onTick(long millisUntilFinished) {
// millisUntilFinished The amount of time until finished.
if(!SendFlag)SendData( SendBuffer+"\r" );
else {Toast.makeText(ledControl.this, "sent", Toast.LENGTH_SHORT).show();this.cancel();}
}
}.start();
我设置了一个程序,使用 SPP 通过蓝牙将数据从 android 应用程序发送到微控制器。提到的微控制器设备在处理时间为 150 毫秒后发回响应。我的应用程序通过蓝牙响应处理程序收到适当的响应,因为 RecieveBuffer.And 应用程序必须再次发送数据以防微控制器未发送适当的数据。我使用如下的 while 条件语句交替发送数据,直到获得响应(在应用程序通过蓝牙响应处理程序 class 获得适当响应后,发送标志为真)。
while(!SendFlag) SendData( SendBuffer+"\r" );
有一个程序,我的程序连续发送数据,蓝牙响应处理程序从未收到任何响应,因为 while
语句检查发送标志(send flag
在应用程序获得适当响应后为真)。
如何设置让我的应用程序等待响应的延迟?我的意思是我必须发送数据并等待响应,如果响应不可接受我必须再次发送数据。
没有while
语句,我可以发送数据并得到响应。但我也必须检查接收到的数据是否可以接受。
package com.np.schoolbell;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.icu.text.SimpleDateFormat;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import ir.mirrajabi.persiancalendar.PersianCalendarView;
import ir.mirrajabi.persiancalendar.core.PersianCalendarHandler;
import ir.mirrajabi.persiancalendar.core.models.PersianDate;
public class ledControl extends AppCompatActivity {
EditText et_SendData;
static TextView tv_DataReaded;
PersianCalendarView persianCalendarView;
PersianCalendarHandler calendar;
PersianDate today;
PersianDate sampleday;
List days;
String address = null;
static String TransmiterCode="999";
static String SendBuffer=null;
static String RecieveBuffer=null;
static int Counter=0;
static boolean SendFlag=false;
BluetoothAdapter bAdapter = null;
BluetoothDevice bDevice = null;
BluetoothSocket bSocket = null;
static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); //SPP UUID. Look for it
ConnectedThread cThread;
private static BluetoothResponseHandler brHandler;
private final static int DataIsReady = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_led_control);
persianCalendarView = (PersianCalendarView)findViewById(R.id.persian_calendar2);
calendar = persianCalendarView.getCalendar();
today = calendar.getToday();
//days=calendar.getDays(1);
//Toast.makeText(this, days.toString(), Toast.LENGTH_LONG).show();
//today.setDate(1398,05,01);
//Toast.makeText(this, today.toString(), Toast.LENGTH_LONG).show();
et_SendData = (EditText) findViewById(R.id.et_SendData);
tv_DataReaded = (TextView) findViewById(R.id.tv_DataReaded);
address = getIntent().getStringExtra( "device_address" );
bAdapter = BluetoothAdapter.getDefaultAdapter();
try {
Toast.makeText(getApplicationContext(), "Connecting...", Toast.LENGTH_SHORT).show();
if( bSocket == null ) {
bDevice = bAdapter.getRemoteDevice(address);
bSocket = bDevice.createInsecureRfcommSocketToServiceRecord(myUUID);
bAdapter.cancelDiscovery();
bSocket.connect();
}
Toast.makeText(getApplicationContext(), "Connected", Toast.LENGTH_SHORT).show();
}
catch (Exception e) {
Toast.makeText(getApplicationContext(), "Connection Failed. Is it a SPP Bluetooth? Try again.", Toast.LENGTH_SHORT).show();
finish();
}
cThread = new ConnectedThread(bSocket);
cThread.start();
if (brHandler == null) brHandler = new BluetoothResponseHandler(this);
else brHandler.setTarget(this);
}
public void onClick_btn_SendData( View v ) {
SendBuffer=LoadDateTimeBuffer();
while(!SendFlag) SendData( SendBuffer+"\r" );
SendBuffer=LoadAZanSetting();
while(!SendFlag) SendData( SendBuffer+"\r" );
et_SendData.setText("");
}
public String LoadDateTimeBuffer(){
SendFlag=false;
TransmiterCode="420";
SimpleDateFormat sdf = new SimpleDateFormat("HHmmss", Locale.getDefault());
String currentTime = sdf.format(new Date());
String currentDate=ParseFaDigits.convert(calendar.formatNumber(today.getYear()))+ParseFaDigits.convert(calendar.formatNumber(today.getMonth()))+ParseFaDigits.convert(calendar.formatNumber(today.getDayOfMonth()));
return TransmiterCode+currentTime+currentDate;
}
public String LoadAZanSetting(){
SendFlag=false;
TransmiterCode="421";
boolean fajrflag=true;boolean tolueflag=true;boolean zuhrflag=true;boolean maghribflag=true;boolean ishaflag=true;
String FajrFlagString = (fajrflag) ? "1" : "0";
String TolueFlagString = (tolueflag) ? "1" : "0";
String ZuhrFlagString = (zuhrflag) ? "1" : "0";
String MaghribFlagString = (maghribflag) ? "1" : "0";
String IshaFlagString = (ishaflag) ? "1" : "0";
return TransmiterCode+FajrFlagString+TolueFlagString+ZuhrFlagString+MaghribFlagString+IshaFlagString;
}
public void SendData(String Data) {
if( bSocket != null ) {
try {
bSocket.getOutputStream().write(Data.getBytes());
}
catch (Exception e) {
Toast.makeText(getApplicationContext(), "Error in Send Data", Toast.LENGTH_LONG).show();
}
}
else {
Toast.makeText(getApplicationContext(), "Bluetooth is Not Connected", Toast.LENGTH_LONG).show();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if( bSocket == null ) return;
if( bSocket.isConnected() ) {
Disconnect();
}
}
public void onClick_Bluetooth_btn_Disconnect( View v ) {
Disconnect();
}
public void Disconnect() {
if ( bSocket != null && bSocket.isConnected() ) {
try {
bSocket.close();
Toast.makeText(getApplicationContext(), "Disconnected", Toast.LENGTH_SHORT).show();
}
catch( IOException e ) {
Toast.makeText(getApplicationContext(), "Error in Disconnecting ", Toast.LENGTH_SHORT).show();
}
}
finish();
}
public static class ConnectedThread extends Thread {
private BluetoothSocket mmSocket;
private InputStream mmInStream;
private OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
//Tell other phone that we have connected
write("connected".getBytes());
}
public void run() {
byte[] buffer = new byte[512];
int bytes;
StringBuilder readMessage = new StringBuilder();
while( !this.isInterrupted() ) {
try {
bytes = mmInStream.read(buffer);
String readed = new String(buffer, 0, bytes);
readMessage.append(readed);
if (readed.contains("\r")) {
brHandler.obtainMessage(ledControl.DataIsReady, bytes, -1, readMessage.toString()).sendToTarget();
readMessage.setLength(0);
}
} catch (Exception e) {
break;
}
}
}
// Call this from the main activity to send data to the remote device
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
// Call this from the main activity to shutdown the connection
public void cancel() {
if (mmInStream != null) {
try {mmInStream.close();} catch (Exception e) {}
mmInStream = null;
}
if (mmOutStream != null) {
try {mmOutStream.close();} catch (Exception e) {}
mmOutStream = null;
}
if (mmSocket != null) {
try {mmSocket.close();} catch (Exception e) {}
mmSocket = null;
}
this.interrupt();
}
}
private static class BluetoothResponseHandler extends Handler {
private WeakReference<ledControl> mActivity;
public BluetoothResponseHandler(ledControl activity) {
mActivity = new WeakReference<ledControl>(activity);
}
public void setTarget(ledControl target) {
mActivity.clear();
mActivity = new WeakReference<ledControl>(target);
}
@Override
public void handleMessage(Message msg) {
ledControl activity = mActivity.get();
String Data = (String)msg.obj;
if (activity != null) {
switch (msg.what) {
case DataIsReady :
if( Data == null ) return;
RecieveBuffer=Data;
if(RecieveBuffer.contains(SendBuffer))
{
tv_DataReaded.append(Data);
SendFlag=true;
TransmiterCode="";
SendBuffer="";
RecieveBuffer="";
}
else
{
SendFlag=false;
}
break;
}
}
}
}
}
非常感谢您。
我找到了解决上述问题的方法,因此我应用了一个 CountDownTimer,它每 1 秒到 3 秒发送一次数据,如果发送的数据和响应都正常,定时器将被取消以避免浪费时间。在正常情况下,此计时器会在应用程序收到适当的响应后发送一次数据。
SendBuffer=LoadDateTimeBuffer();
CountDownTimer yourCountDownTimer=new CountDownTimer(3000, 1000) {
public void onFinish() {
Toast.makeText(ledControl.this, "Error", Toast.LENGTH_SHORT).show();
}
public void onTick(long millisUntilFinished) {
// millisUntilFinished The amount of time until finished.
if(!SendFlag)SendData( SendBuffer+"\r" );
else {Toast.makeText(ledControl.this, "sent", Toast.LENGTH_SHORT).show();this.cancel();}
}
}.start();