The Bluetooth tutorials i read all mentioned that i need to have the same UUID on both sides (Server and Client) to establish a connection between two devices. But what if i dont know the UUID of my Client and if i dont care?
Background information: I have over 1000 microcontrollers with bluetooth. Each microcontroller has a fix and unchangeable UUID. Smartphones should be able to send string messages to that micrcontrollers (single connection, one smartphone is controlling one microcontroller). It should not matter which Smartphone is controlling which microcontroller. So in fact i really dont care about the UUID of the Client.
So my Smartphone is the Server and is opening a listening thread for incoming Bluetooth connections but i have to put in a UUID here:
tempBluetoothServerSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
But when i have thousand different UUID's and i really dont care about the UUID what should i put in there? Also the BluetoothSocket:
tempBluetoothSocket = this.bluetoothDevice.createRfcommSocketToServiceRecord(MY_UUID);
How to know which UUID?
So the core question is: How can i connect to any microcontroller?
I've been using this:
// Unique UUID for this application
private static final UUID UUID_ANDROID_DEVICE =
UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
private static final UUID UUID_OTHER_DEVICE =
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
And it's uses:
public AcceptThread(boolean isAndroid) {
BluetoothServerSocket tmp = null;
// Create a new listening server socket
try {
if(isAndroid)
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, UUID_ANDROID_DEVICE);
else
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, UUID_OTHER_DEVICE);
} catch (IOException e) { }
mmServerSocket = tmp;
}
public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
if(BluetoothService.this.isAndroid)
tmp = device.createRfcommSocketToServiceRecord(UUID_ANDROID_DEVICE);
else
tmp = device.createRfcommSocketToServiceRecord(UUID_OTHER_DEVICE);
} catch (IOException e) { }
mmSocket = tmp;
}
Which allows my devices to connect to any bluetooth device I've tested with. For the sake of testing, it has only been varying bluetooth barcode scanners. Although I believe this is a generic RFCOMM UUID.
It hasn't failed me yet.
Related
I dowloaded the BluetoothChat sample project here :
https://android.googlesource.com/platform/development/+/master/samples/BluetoothChat?autodive=0%2F
The fact is, when I'm launching the app on two devices (which are NOT paired), it should connect the two devices WITHOUT asking for pairing the two devices, shouldn't it ?
And in fact, when I'm trying to connect the two devices (which are NOT paired), it's asking to pair the devices .
I mean, there is this function in BluetoothChatService.java which should create an insecure socket . But it seems, that it doesn't do his job ?
/**
* This thread runs while attempting to make an outgoing connection
* with a device. It runs straight through; the connection either
* succeeds or fails.
*/
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
private String mSocketType;
public ConnectThread(BluetoothDevice device, boolean secure) {
mmDevice = device;
BluetoothSocket tmp = null;
mSocketType = secure ? "Secure" : "Insecure";
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
if (secure) {
tmp = device.createRfcommSocketToServiceRecord(
MY_UUID_SECURE);
} else {
tmp = device.createInsecureRfcommSocketToServiceRecord(
MY_UUID_INSECURE);
}
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
}
mmSocket = tmp;
}
Can somebody explain me why it asks to pair the two devices ?
The method createInsecureRfcommSocketToServiceRecord shouldn't ask for pairing unpaired devices , should it ? x)
I'm really confused .
createInsecureRfcommSocketToServiceRecord() has of
"insecure" the key the devices are using to communicate, which is, below Bluetooth 2.1, not encrypted. That is what is "unsecure".
But it does not change the fact that if the MAC address is not already in the pairing database there will always be the prompt.
So yes, it will prompt.
I'm struggling with getting consistent bluetooth connections in a star topology. I have one master phone which is a Samsung Galaxy S4 running API 10. All of the phones that connect to the bluetoothserver socket on the S4 are LG Dynamic Tracfones also running API 10.
Over the past few days, I have seen a LOT of conflicting information on the web about what type of connection to use.
This is my current set up:
MASTER CODE
public void acceptConnection() {
.... (enable bt adapter) ...
// initializes a Bluetooth server socket
bluetoothServerSocket = bc.createBluetoothServerSocket();
//connection made to Master, discovery no longer needed
bluetoothAdapter.cancelDiscovery();
BluetoothSocket bluetoothSocket;
// loops until the thread is interrupted or an exception occurs
while (!isInterrupted()) {
try {
// attempts to accept the slave application's connection
bluetoothSocket = bluetoothServerSocket.accept();
} catch (IOException e) {
// prints out the exception's stack trace
e.printStackTrace();
Log.v("Default Thread", "Connection to slave failed.");
// breaks out of the while loop
return;
}
try {
... (enumerate all input and output streams, and all bt sockets) ...
} catch (IOException e) {
// prints out the exception's stack trace
e.printStackTrace();
}
}
This is the method that is called when creating a blueToothServerSocket, and this is where half of my confusion is. How should I listen on the adapter? Currently, I'm doing it insecurely.
public BluetoothServerSocket createBluetoothServerSocket() {
// gets the name of the application
String name = "PVCED";
// gets a common UUID for both the master and slave applications
UUID uuid = UUID.fromString("23ea856c-49da-11e4-9e35-164230d1df67");
// initializes an empty Bluetooth server socket
serverSocket = null;
try {
// creates a Bluetooth socket using a common UUID
serverSocket = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(name, uuid);
} catch (IOException e) {
// prints out the exception's stack trace
e.printStackTrace();
}
return serverSocket;
}
SLAVE CODE
And this is where the other half of my confusion is, how should I create a socket? Currently I'm doing it insecurely.
private BluetoothSocket createBluetoothSocket(Set<BluetoothDevice> pairedDevices) {
// gets a common UUID for both the master and slave applications
UUID uuid = UUID.fromString("23ea856c-49da-11e4-9e35-164230d1df67");
// initialises an empty Bluetooth socket
BluetoothSocket bluetoothSocket = null;
// checks to see if there are any paired devices
if (pairedDevices.size() > 0) {
// loops through each paired device
for (BluetoothDevice device : pairedDevices) {
// checks to see if the name of the paired device is MASTER
if (device.getName().equals("MASTER")) {
try {
master = device;
// creates a Bluetooth socket using a common UUID
//bluetoothSocket = master.createRfcommSocketToServiceRecord(uuid);
//Method m = master.getClass().getMethod("createRfcommSocketToServiceRecord", new Class[] {int.class});
//bluetoothSocket = (BluetoothSocket) m.invoke(master, 1);
bluetoothSocket = master.createInsecureRfcommSocketToServiceRecord(uuid);
} catch(Exception e){
Log.v("Connect Exception", e.getMessage());
}
}
}
}
//check if we paired succesfully to a master, if not, prompt user to do so.
if (master == null){
... (tell user to pair with master via toast) ...
}
return bluetoothSocket;
}
My logcat is often filled with errors such as "Bad File Descriptor", "Unable to start Service Discovery", or "Service Discovery has failed."
What is the best connection scheme to use for my scenario? If you guys need more details on how I'm enabling/disabling bt adapters, or closing bt connections, I can supply more code.
I've been planning to make an Android App, that would communicate with this bluetooth rs232 adapter
http://www.nordfield.com/wireless-serial-rs232-bluetooth-adapter
and I'm not sure what should I do with UUID in this case? Will I be able to start a connection with an application, that would look like BluetoothChat sample app from Google?
https://android.googlesource.com/platform/development/+/25b6aed7b2e01ce7bdc0dfa1a79eaf009ad178fe/samples/BluetoothChat/
Well, I've solved the problem already. Actually there is possibility to create Bluetooth connection without knowing device's UUID. It is achieved by this code:
public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
try {
Method method;
method = device.getClass().getMethod("createRfcommSocket", new Class[] { int.class } );
tmp = (BluetoothSocket) method.invoke(device, 1);
} catch (Exception e) { }
mmSocket = tmp;
}
All of the rest of connection management is done the same as in BluetoothChat sample app from Google.
Iam trying to connect to a socket by using the connect method. Iam generating a String containing the UUID like this:
MY_UUID = UUID.fromString("45341da0-c9c1-11e1-9b21-0800200c9a66");
Then constructing a BluetoothSocket like this:
BluetoothSocket tmp = null;
I also want to connect to a specific device by its mac-address:
BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice("00:1B:DC:0F:EC:7E");
and then making the bluetoothSocket
try {
tmp = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Toast.makeText(getApplicationContext(), "Exception1: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
Just for to test I added a breakpoint where the tmp object is been initialized inside the try catch. But it's only containing NULL The remote device does support OBEX OPP, but this is just a layer above the RFCOMM in the bluetooth stack, so I think my device should support RFCOMM for connections. Can anybody tell me why my tmp object is set to null?
Is there anyway I can test whenever the socket is created?
I am trying to communicate with a Bluetooth programmable Microcontroller. The Bluetooth device on the microcontroller communicates (specifically) on Bluetooth Serial COM Port number 4.
QUESTION: How can I get the Android App to read data from this COM port (number 4)?
I know the UUID is a well known unique ID,that works for this device, but I don't think that it has anything to do with specifying the COM port.
static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
btSocket = btDevice.createRfcommSocketToServiceRecord( myUUID);
btSocket.connect();
valid.append( btDevice.getName() + "\n" + btDevice.getAddress());
north.append("Socket Connected");
InputStream mmInStream = btSocket.getInputStream();
OutputStream mmOutStream = btSocket.getOutputStream();
byte[] buffer = new byte[10];
int bytes;
StringBuffer str = new StringBuffer();
while (true) {
try {
mmOutStream.write("a".getBytes());
//Reads a # of bytes until the end of stream is reached
bytes = mmInStream.read(buffer);
//Transform to string
str.append(buffer.toString()+"\t"); //Clear the buffer
Log.e("DATA", "THE DATA: "+ str.toString());
south.setText(str.toString());
str.delete(0,str.length());
} catch (IOException e) {
break;
} }}
The COM port is something that exists only on the microcontroller, not the Bluetooth device attached to it. The Bluetooth device does not even know which COM port the microcontroller used to connect to it. The Bluetooth device's connection to the micro is via the TX and RX lines. The fact that they are attached to pins on the micro assigned to a specific COM port is irrelevant and unknown to the Bluetooth device.
I had this problem with a custom bluetooth device I built. Instead of using createRfcommSocketToServiceRecord in your connect thread, try something similar to the following:
public ConnectThread(BluetoothDevice device) throws
SecurityException, NoSuchMethodException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
mmDevice = device;
BluetoothSocket tmp = null;
// Force a BluetoothSocket for a connection with the
// given BluetoothDevice
Method m = mmDevice.getClass().getMethod("createRfcommSocket",
new Class[]{int.class});
mmSocket = (BluetoothSocket)m.invoke(mmDevice, Integer.valueOf(1));
}
Where my mmDevice is your btDevice.
This forces a socket connection between the unknown device and the smartphone. From what I've heard, there's an issue in Android connecting "non-similar" devices. Worth a shot.