我有一个通过蓝牙连接到RaspberryPi的应用程序,并在收到一些数据时将相同的数据循环到它。
我遇到了一些连接问题,所以需要这个解决方法才能将我的Android手机连接到RaspberryPi:IOException: read failed, socket might closed - Bluetooth on Android 4.3
由于某种原因,Android手机正在接收自己的输出。 String " Hello Raspberry。它是我,AndroidPhone" 以永无止境的循环发送到输出。传入的数据(来自RaspberryPi)也在一个永无止境的循环中读取。
但不知何故,我不会只接收来自RaspberryPi的数据,而是通过智能手机发送字符串。这是我的代码:
public class MainActivity extends AppCompatActivity {
private BluetoothAdapter bluetoothAdapter;
UUID SERIAL_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
@Override
protected void onCreate(Bundle savedInstanceState) {
// (...)
// Only GUI-stuff until this point
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice raspberryPi = bluetoothAdapter.getRemoteDevice("B8:27:EB:56:DC:B2");
BluetoothSocket btSocket;
try {
btSocket = raspberryPi.createRfcommSocketToServiceRecord(SERIAL_UUID);
btSocket.connect();
} catch (IOException e) {
Log.e("BTError", e.getMessage());
// Workaround, found on: https://stackoverflow.com/questions/18657427/ioexception-read-failed-socket-might-closed-bluetooth-on-android-4-3
try {
Log.e("BTError", "Trying fallback...");
btSocket = (BluetoothSocket) raspberryPi.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(raspberryPi, 1);
btSocket.connect();
(new Thread(new SendingThread(btSocket))).start();
(new Thread(new ReceivingThread(btSocket))).start();
} catch (Exception e2) {
Log.e("BTError", e2.getMessage());
Log.e("BTError", "Couldn't establish Bluetooth connection!");
}
}
}
private class SendingThread extends Thread {
private OutputStream out;
public SendingThread(BluetoothSocket btSocket) {
try {
out = btSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
int delay = 100000000;
while (true) {
if (delay == 0) {
Log.i("WRT", "Written to RaspberryPi");
out.write("Hello Raspberry. It's me, AndroidPhone".getBytes());
delay = 100000000;
}
delay--;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private class ReceivingThread extends Thread {
private InputStream in;
public ReceivingThread(BluetoothSocket btSocket) {
try {
in = btSocket.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
int data = 0;
while (true) {
try {
data = in.read();
} catch (IOException e) {
e.printStackTrace();
}
Log.i("RCV", String.valueOf((char) data));
}
}
}
在RaspberryPi端,一切看起来都很正常。一个简单的java程序启动linux命令rfcomm listen /dev/rfcomm0
,并使用/dev/rfcomm0
和FileReader
读取/写入文件FileWriter
。这方面唯一相关的路线是:
run {
// Inside writer-thread
bluetoothWriter = new BufferedWriter(new FileWriter("/dev/rfcomm0"));
while(true) {
bluetoothWriter.write("This is RaspPi");
bluetoothWriter.flush();
}
}
和
run {
// Inside reader-thread
bluetoothReader = new BufferedReader(new FileReader("/dev/rfcomm0"));
while(true) {
int incData = bluetoothReader.read();
System.out.print((char) incData);
}
}
感谢您的帮助!
编辑:仍无法解决此问题。我怀疑RaspberryPi以某种方式发回了它收到的内容。但当我禁用它发出任何东西时,智能手机仍然直接接收它发出的内容。
答案 0 :(得分:0)
我搜寻了蓝牙类资源。乍一看,该解决方法似乎是合法的。首先尝试:
if (delay == 0) {
Log.i("WRT", "Written to RaspberryPi");
out.write("Hello Raspberry. It's me, AndroidPhone".getBytes());
out.flush(); // <-- You are not flushing
delay = 100000000;
}
该消息会插入您的套接字中,以便您反复阅读。
如果那不能解决问题,我可以想到的另一种选择是将套接字初始化为您的android设备的套接字。如果在创建套接字时bluedevice设备为null,则createRfcommSocket方法似乎为您自己的设备创建了一个套接字。我不确定这将如何发生,但是如果异常后raspberryPi的状态有所改变,我想可能是值得研究的。
在raspi方面:如果您只是同时启动这两个线程,那并不意味着您一直在向“ / dev / rfcomm0”发送消息并进行刷新。我建议您对其进行更改,以使raspi通过发送回所需的消息而不是一直发送垃圾邮件来响应收到的消息。我不确定这是否是您的问题的一部分,但这至少会使调试和开发更加容易。
答案 1 :(得分:-1)
我不确定这是否是您需要的解决方案,因为我不知道您使用的是蓝牙经典还是蓝牙4.0> +,但是我为基于文本的BLE和WiFi P2P 2编写了library android的双向通信(并且我知道Raspberry Pi能够进行BLE通信),尽管我没有为BLE通信创建套接字连接,但为WiFi P2P做。看一看,希望对您有所帮助。它尚未发布,因此您必须克隆/分叉存储库。
答案 2 :(得分:-1)
我认为您在写作方面遇到困难
据我所知,对于缓冲区,应使用\ n和...
import React, {useState} from 'react';
import { BrowserRouter as Router, Switch, Route, Link, Redirect } from "react-router-dom";
import Computers from "../components/Computers";
import Mobiles from "../components/Mobiles";
import Tablets from "../components/Tablets";
const PostAd = (props) => {
const [selectedOption, setSelectedOption]=useState("");
const onChangeSelectedOption = (e) => {
const selectedOption = e.value;
setSelectedOption(e);
};
return(
<div className="container">
<h4 className="" style={{alignText:"center"}}>Post Your Advertisement</h4>
<div>
<Row>
<Col xs={3}></Col>
<Col xs={5}>
<AsyncSelect
placeholder="Search for Categories.."
loadOptions={loadOptions}
onChange={onChangeSelectedOption}
/>
</Col>
</Row><hr/>
</div>
<Router>
<div>
<Row>
<Col xs={4}>
<ul>
<li>Electronics
<ul>
<li><Link to="/computer">computer</Link></li>
<li><Link to="/mobiles">Mobiles</Link></li>
<li><Link to="/tablets">Tablets</Link></li>
</ul>
</li>
</ul>
</Col>
</Row>
<div>
<Switch>
<Route exact path="/computers" component={Computers} />
<Route exact path="/mobiles" component={Mobiles} />
<Route exact path="/tablets" component={Tablets} />
</Switch>
</div>
</div>
</Router>
</div>
)
};
export default PostAd;
但是我更喜欢结合使用bluetoothWriter.write("This is RaspPi\n");
和DataOutputStream
阅读:
BufferedReader
写:
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
try {
String line = bufferedReader.readLine();
System.out.println(line);
} catch (IOException e) {
e.printStackTrace();
}
最好纠正亲爱的朋友对flush()的观点...
我不确定,请自我测试...