CIocan Cosmin
Lurker
I am trying to connect my raspberry pi, which runs some form of debian jessie, to my android phone. I implemented the server side on the raspberry and the client side on the android phone. I already tested my android code with another app that had implemented the server side and I was able to send a couple of bytes from phone to phone. The problem is that after trying to implement the server side on the raspberry pi, it just isn't able to connect.
Server code on the raspberry pi:
#include <fstream>
#include "/usr/include/stdint.h"
#include "/usr/include/bluez-5.31/lib/bluetooth.h"
#include "/usr/include/bluez-5.31/lib/hci.h"
#include "/usr/include/bluez-5.31/lib/hci_lib.h"
#include "/usr/include/bluez-5.31/lib/rfcomm.h"
std:
fstream fout("output.txt");
int main(int argc, char **argv)
{
fout << "marker 0" << std::endl;
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char source[18] = "50:F0
3:40:42:55";
bdaddr_t tmp1 = {};
str2ba( source, &tmp1 );
rem_addr.rc_family = AF_BLUETOOTH;
rem_addr.rc_bdaddr = tmp1;
rem_addr.rc_channel = 1;
char buf[1024] = { 0 };
int s, client, bytes_read;
unsigned int opt = sizeof(rem_addr);
//allocate socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
if( s == -1 ) fout << "socket error" << std::endl;
//bind socket to port 1 of the first available adapter
bdaddr_t tmp2 = {0,0,0,0,0,0};
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = tmp2;
loc_addr.rc_channel = 1;
int error_check = bind(s, (struct sockaddr* )&loc_addr, sizeof(loc_addr));
if( error_check == -1 ) fout << "binding error" << std::endl;
//put socket into listening mode
error_check = 0;
error_check = listen(s, 1);
if( error_check == -1 ) fout << "listening error" << std::endl;
//accept one connection
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf( stderr, "accepter connection from %s\n", buf);
memset( buf, 0, sizeof(buf));
//read data from the client
bytes_read = recv(client, buf, sizeof(buf), 0);
if( bytes_read > 0 )
{
fout << buf[0];
}
//close connection
//close(client);
//close(s);
return 0;
}
I tried to figure out what was going on when i ran the program and i saw that socket(), bind() and listen() were not returning with an error. I also saw that the program was paused when accept() was called. From what i can tell this means that the program is waiting for an incoming connection request which is the normal behaviour. But still, the program doesn't go any farther than the line with accept() when I try to connect my phone.
Client code on the android phone:
public class MainActivity extends AppCompatActivity {
@override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (!mBluetoothAdapter.isEnabled()) {
System.exit(1);
}
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
Object[] pairedDev = pairedDevices.toArray();
ArrayAdapter<String> mArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, 0);
/*if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
ListView listView = (ListView) findViewById(R.id.PairedDevicesListView);
listView.setAdapter(mArrayAdapter);*/
ConnectThread connectThread = new ConnectThread((BluetoothDevice) pairedDev[0]);
connectThread.run();
connectThread.cancel();
}
public void buttonOnClick(View v)
{
Button button = (Button) v;
}
@override
protected void onResume() {
super.onResume();
}
@override
protected void onStart() {
super.onStart();
}
@override
protected void onPause() {
super.onPause();
}
@override
protected void onStop() {
super.onStop();
}
@override
protected void onDestroy() {
super.onDestroy();
}
@override
protected void onRestart() {
super.onRestart();
}
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
BluetoothSocket tmp = null;
mmDevice = device;
try {
tmp = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.cancelDiscovery();
try {
mmSocket.connect();
} catch (IOException connectException) {
try {
mmSocket.close();
System.exit(1);
} catch (IOException closeException) { //System.exit(1);
}
return;
}
// Do work to manage the connection (in a separate thread)
// manageConnectedSocket(mmSocket);
byte[] bytes = new byte[1];
bytes[0] = 6;
ConnectedThread connectedThread = new ConnectedThread(mmSocket);
connectedThread.write(bytes);
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final 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) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI activity
// mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();
} catch (IOException 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) { }
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
}
When I connected the two phones I was using a random UUID but since there was no option to enter a UUID in the c code of the raspberry I presumed it was the standard UUID that most devices have: "00001101-0000-1000-8000-00805F9B34FB"; or at least that's what I understood. You can assume that pairedDev[0] is the right one(the raspberry) since I already tested this out.
Server code on the raspberry pi:
#include <fstream>
#include "/usr/include/stdint.h"
#include "/usr/include/bluez-5.31/lib/bluetooth.h"
#include "/usr/include/bluez-5.31/lib/hci.h"
#include "/usr/include/bluez-5.31/lib/hci_lib.h"
#include "/usr/include/bluez-5.31/lib/rfcomm.h"
std:
fstream fout("output.txt");int main(int argc, char **argv)
{
fout << "marker 0" << std::endl;
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char source[18] = "50:F0
3:40:42:55";bdaddr_t tmp1 = {};
str2ba( source, &tmp1 );
rem_addr.rc_family = AF_BLUETOOTH;
rem_addr.rc_bdaddr = tmp1;
rem_addr.rc_channel = 1;
char buf[1024] = { 0 };
int s, client, bytes_read;
unsigned int opt = sizeof(rem_addr);
//allocate socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
if( s == -1 ) fout << "socket error" << std::endl;
//bind socket to port 1 of the first available adapter
bdaddr_t tmp2 = {0,0,0,0,0,0};
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = tmp2;
loc_addr.rc_channel = 1;
int error_check = bind(s, (struct sockaddr* )&loc_addr, sizeof(loc_addr));
if( error_check == -1 ) fout << "binding error" << std::endl;
//put socket into listening mode
error_check = 0;
error_check = listen(s, 1);
if( error_check == -1 ) fout << "listening error" << std::endl;
//accept one connection
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf( stderr, "accepter connection from %s\n", buf);
memset( buf, 0, sizeof(buf));
//read data from the client
bytes_read = recv(client, buf, sizeof(buf), 0);
if( bytes_read > 0 )
{
fout << buf[0];
}
//close connection
//close(client);
//close(s);
return 0;
}
I tried to figure out what was going on when i ran the program and i saw that socket(), bind() and listen() were not returning with an error. I also saw that the program was paused when accept() was called. From what i can tell this means that the program is waiting for an incoming connection request which is the normal behaviour. But still, the program doesn't go any farther than the line with accept() when I try to connect my phone.
Client code on the android phone:
public class MainActivity extends AppCompatActivity {
@override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (!mBluetoothAdapter.isEnabled()) {
System.exit(1);
}
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
Object[] pairedDev = pairedDevices.toArray();
ArrayAdapter<String> mArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, 0);
/*if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
ListView listView = (ListView) findViewById(R.id.PairedDevicesListView);
listView.setAdapter(mArrayAdapter);*/
ConnectThread connectThread = new ConnectThread((BluetoothDevice) pairedDev[0]);
connectThread.run();
connectThread.cancel();
}
public void buttonOnClick(View v)
{
Button button = (Button) v;
}
@override
protected void onResume() {
super.onResume();
}
@override
protected void onStart() {
super.onStart();
}
@override
protected void onPause() {
super.onPause();
}
@override
protected void onStop() {
super.onStop();
}
@override
protected void onDestroy() {
super.onDestroy();
}
@override
protected void onRestart() {
super.onRestart();
}
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
BluetoothSocket tmp = null;
mmDevice = device;
try {
tmp = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.cancelDiscovery();
try {
mmSocket.connect();
} catch (IOException connectException) {
try {
mmSocket.close();
System.exit(1);
} catch (IOException closeException) { //System.exit(1);
}
return;
}
// Do work to manage the connection (in a separate thread)
// manageConnectedSocket(mmSocket);
byte[] bytes = new byte[1];
bytes[0] = 6;
ConnectedThread connectedThread = new ConnectedThread(mmSocket);
connectedThread.write(bytes);
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final 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) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI activity
// mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();
} catch (IOException 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) { }
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
}
When I connected the two phones I was using a random UUID but since there was no option to enter a UUID in the c code of the raspberry I presumed it was the standard UUID that most devices have: "00001101-0000-1000-8000-00805F9B34FB"; or at least that's what I understood. You can assume that pairedDev[0] is the right one(the raspberry) since I already tested this out.