Buffering Issues Pi Pico with HC-05 Bluethooth Module - android

This is probably my misunderstanding of the Bluetooth SPP profile or even Bluetooth itself, but I am trying to get data transferred from an Android app to a Raspberry Pi Pico, and I can get it to work in some respect, however it seems to buffer the data randomly. The Android app sends a string every second and it seems to run OK some times, and then sometimes it pauses for some amount of seconds and then it catches up with all of the data. I have a subsequent issue that the readline doesn't read a line, it reads each character and the \n as well, but that's a side issue:
I have looked to see if there are any settings on the HC-05 to see if there's a buffer on that, and the only thing I can think of is upping the baud rate, but I don't see 9600 being an issue with so few characters.
It's almost acting like the pico isn't powerful enough.
The connection is made like this:
UUID BLUETOOTH_SPP = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(deviceAddress);
socket = device.createRfcommSocketToServiceRecord(BLUETOOTH_SPP);
socket.connect();
dataOut = new DataOutputStream(socket.getOutputStream());
Data is sent with this
dataOut.writeBytes("1"+speed.intValue()+"\n");
dataOut.flush();
With the receiver python code looking like this:
from machine import Pin, UART
bt_module = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))
while True:
if (bt_module.any()):
command = bt_module.readline()
print(command);

Related

Manually set bluetooth server port in Android

I have a working Bluetooth server running (Android app). I would like to set a specific Bluetooth port for it to listen to. The reason for that is that for the client to connect, it takes about 10-15 seconds because it needs to first discover the server (i do a scan ).
the code to create the server is the following:
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
UUID my_uuid = UUID.fromString("12345678-f6ff-4f6f-1f1f-f8f8f8fffff8");
try {
BluetoothServerSocket serverSocket = adapter.listenUsingRfcommWithServiceRecord("myBluetoothServer", my_uuid);
sock1 = serverSocket.accept();
i_s = sock1.getInputStream();
o_s = new OutputStreamWriter(socket.getOutputStream());
new Thread(writter).start();
...
Question: how to specify a fixed port number for the server?
I have been looking here, of course, but it is not easy to find,:
https://developer.android.com/reference/android/bluetooth/BluetoothSocket?hl=ur
I am looking for something like serverSocket.setPort(myPortNumber) (pseudo - code)
The concept of port does not exist for Bluetooth Sockets since they are not regular TCP/IP sockets. They are just abstracted to behave like one.
As you figured out from your code, what you specify is a UUID which is a service identifier. The process to connect to a Bluetooth server goes like this:
Bluetooth Device scan: You can't skip this part, since you need a valid BluetoothDevice object
Service Discovery for a discovered Device: This is the part where you "check" if that Bluetooth Device is running the service that you are looking for (Your service UUID) So you shouldn't skip this part either, unless you want to connect to all surrounding Bluetooth devices.

Android Bluetooth RFCOMM directly to Raspberry Pi without pairing

I need to make an application that communicates through an RFCOMM socket to a Raspberry Pi, without pairing.
On the Android side, I have the MAC address of the RPi and I'm trying to connect to the server using this code:
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
BluetoothSocket mmSocket = null;
try {
mmSocket = device.createRfcommSocketToServiceRecord(UUID);
mmSocket.connect();
Log.d(TAG, "mmSocket returned");
}
...
UUID is the same as on the server-side, and i've also tried using the createInsecureRfcommSocket method.
On the Raspberry Pi side, I used the pybluez example of an rfcomm server(here is the example)
It once worked but I don't understand why it did or why it doesn't anymore, in the sense that when I tried to initiate the connection from the phone I got a pairing request on the Raspberry Pi without a pairing request on the phone, and the socket object on android had successfully connected.
Does anyone know what I am doing wrong, or any ideas that might help me, and is such a thing even feasible.
Thanks in advance.
I've found this unanswered question and I think I have a working solution at least for my case.
All I needed to do was to call these three commands:
sudo hciconfig hci0 piscan
sudo hciconfig hci0 sspmode 1
sudo hciconfig hci0 class 0x400100
The first two lines make the RPi discoverable, from this answer, which also claims the RPi should pair automatically. That does NOT work for me. It still requires PIN confirmation on both devices, that's unfortunate for a headless RPi.
The third line found in this answer is crucial and it is what allows to connect RFCOMM sockets to unpaired RPi.
It is possible that changing class will make other BT services stop working, not sure, I just need RFCOMM.
After this, the following example works for me with RPI 4B and my Win10 laptop:
import socket
from contextlib import closing
# MAC address of RPi, can be obtained with `bluetoothctl list` on RPi.
rpi_addr = 'e4:5f:01:7d:8A:A3'
# 1-32, some might be used already, e.g. 3 for me, in that case bind fails.
channel = 15
def server():
print("Creating socket")
with closing(socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM,
socket.BTPROTO_RFCOMM)) as s:
print("Binding socket")
s.bind((rpi_addr ,channel))
print("Listening socket")
s.listen()
s_sock, addr = s.accept()
with closing(s_sock):
print ("Accepted connection from "+str(addr))
data = s_sock.send(b"Hello from RPi")
def client():
print("Creating socket")
s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM,
socket.BTPROTO_RFCOMM)
print("Connecting socket")
s.connect((rpi_addr,channel))
print("Connected")
data = s.recv(1024)
print(f"Received {data}")

How do Bluetooth SDP and UUIDs work? (specifically for Android)

My understanding is that the SDP is a list of UUIDs that other devices can fetch.
According to this PDF from MIT, "A more general way to think of
SDP is as an information database." Does this mean I can add multiple values to SDP? Since Android has BluetoothDevice.fetchUuidsWithSdp(), how do I set the UUIDs of a device?
Also, what does each section of an UUID mean? UUIDs look like 00000000-0000-1000-8000-00805F9B34FB, but what information does this convey?
An UUID identifies a service that is available on a particular device. So if you call BluetoothDevice.fetchUUidsWithSdp() your BroadcastReceiver will receive the relevant Intent ACTION_UUID containing the device and the service UUID.
The bluetooth specification defines some common UUIDs.
If you don't want to connect to one of these well known services but intent to implement your own bluetooth application, then you have to just generate your own UUID (use uuidgen from a unix console or an online generator) that identifies your application/service.
You can create an UUID instance in java like this UUID uuid = UUID.fromString("785da8ea-1220-11e5-9493-1697f925ec7b");.
So if you create the server side for your bluetooth application on Android you typically do this
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
BluetoothServerSocket serverSocket = adapter.listenUsingRfcommWithServiceRecord("YourHumanReadableServiceName", uuid);
And this is where you "set" your UUID. The Android bluetooth API creates the SDP-entry consisting of YOUR application's UUID and name for you. Other devices can now retrieve this entry. Androids bluetooth stack will now associate a bluetooth channel to your BluetoothServerSocket. If you want to connect to this ServerSocket, the connecting side usually connects doing this:
// you will most likely already have this instance from a discovery or paired device list
BluetoothDevice serverDevice = adapter.getRemoteDevice(bluetoothMacAddress);
// connect to your ServerSocket using the uuid
BluetoothSocket socket = serverDevice.createRfcommSocketToServiceRecord(uuid);
socket.connect();
Android will again do the heavy lifting for you: It checks the SDP-Records on the remote device, looks up the bluetooth channel that corresponds to your service's UUID and connects using this information.
There is a common code snippet spooking around here on SO that advices you to use "reflection" to get to a hidden API looking similar to this code:
try {
// this is the way to go
socket = device.createRfcommSocketToServiceRecord(uuid);
socket.connect( );
} catch ( IOException exception ) {
// don't do that! You will bypass SDP and things will go sideways.
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
socket = (BluetoothSocket) m.invoke(device, 1);
socket.connect();
}
Most people try this and it "just works" in their dev environment but you should know what you do using this. You actively bypass the SDP lookup that retrieves the right bluetooth channel to be used with your service and you will end up connecting to channel 1. If you have more than one Service running on the device, things WILL go sideways in this cases and you will end up in debugging hell ;-)
I developed a small middleware called Blaubot to create small networks using bluetooth/wifi/nfc and experienced all sorts of problems on the devices I used to test with (12 models). It was often the case that the bluetooth stack was not fully functional anymore in cases where it got some load or after many connects/disconnects (which you usually will have, if you are developing your app). In these cases the device.createRfcommSocketToServiceRecord(uuid) would occasionally fail and only turning the bluetooth adapter off and on again helped to bring the bluetooth adapters back to life (in some cases only after a full power cycle). If this happens and you use the reflection method, you will probably not have much fun with bluetooth.
But if you know this and keep concurrent calls to the BluetoothAdapter within bounds, bluetooth connections and the adapters will be pretty stable.

How do i send information via a setup bluetooth connection

So im working around with bluetooth and trying to figure out how to send two strings via a bluetooth connection. From one android device to another.
I found this guide http://developer.android.com/guide/topics/connectivity/bluetooth.html
but it talks alot about setting up the connection. So i went straight down to the chapter about Managing a Connection. The reason i do this is that in the apps i create i plan to setup the bluetooth connection before opening the apps (via the phones usual bluetooth setup) and then open the apps and send when it is necessary.
So my question is how do i find the bluetooth socket that should be setup? Since that should be what im searching for to create the sending and recieving threads?
Hope this is enough information, else tell what more you need and ill try and answer to the best of my ability.
Best Regards Drakthal
The usual bluetooth setup only pairs between devices, it doesn't create a data connection between them (And even if it would, you wouldn't be able to access this Socket object because it's not created in your process).
After Bluetooth is turned on, you can call BluetoothAdapter.getBondedDevices() to get a set of the paired devices. You can then iterate over them, and initiate a connection to the one you want. You can't avoid the connection creation :( If you want a simplified example, you can look here (An answer I posted a while ago, regarding the whole pairing/connecting/sending/receiving subject with bluetooth).
Once you acquired an open connection, sending the 2 string is easy.
String s1 = "A", s2 = "B";
byte[] buf1 = s1.getBytes(), buf2 = s2.getBytes();
OutputStream os = connection.getOutputStream();
os.write(buf1);
os.write(buf2);
os.flush();
connection.close();

Android 2.1 Bluetooth SPP to LM058 (Serial Cable Replacement) problem

Hey I'm relatively new to Android programming (but not programming in general).
The Setup:
HTC Wildfire (running Android 2.1)
LM058 (RS232 Serial Cable Replacement)
LM058 will later on be attached to a MCU but for now it's connected to my laptop (terminal)
The Goal:
To connect Wildfire to LM058 to each other with a 'bidirectional-stream' (like: "Hello from Android", response: "Hey from LM058").
So far:
I've managed to connect the two devices (paired), I can tell by the LEDs on the LM058.
Problem:
I can't seem to send anything from my Wildfire to LM058, and can't write anything back. They are paired and Connected.
Code example:
String message = "Hello message from client to server.";
byte[] msgBuffer = message.getBytes();
try {
outStream.write(msgBuffer);
Log.e(TAG, "App was here!");
} catch (IOException e) {
Log.e(TAG, "ON RESUME: Exception during write.", e);
}
I have previously made a similar connection using a Windows Mobile succesfully, but Android seems to give me some trouble at this point.
If you can help me get passed this small hurdle I would be very gratefull!
Could it have anything to do with BaudRate, because when a link is established (paired and Connected) it should replace the two devices (as a simple RS232 cable), so my Terminal on the PC should be set to a certain BaudRate (since I can't seem to find Baud Rate in Android). But still I can't see anything, if Baudrate was wrong then I would be able to see something (even though it might be rubbish) or?
There isn't Baudrate for Bluetooth connection, only you have to configure the baudrate between your BT-RS232 device and your computer...
For the BluetoothConnection you could see the next example:
http://developer.android.com/resources/samples/BluetoothChat/index.html
or this:
http://developer.android.com/guide/topics/wireless/bluetooth.html

Categories

Resources