I wrote a simple program in c++ (using the Arduino ide) that opens a Serial Bluetooth connection.
#include "BluetoothSerial.h"
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
BluetoothSerial SerialBT;
void setup() {
Serial.begin(115200);
SerialBT.begin("ESP32test"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
}
void loop() {
if (Serial.available()) {
SerialBT.write(Serial.read());
}
if (SerialBT.available()) {
Serial.write(SerialBT.read());
}
}
the program runs, but when I am trying to connect to ESP32 with my phone it connects successfully but disconnects after a few seconds.
And when I am trying to connect to it via Bluetooth Terminal Application (https://play.google.com/store/apps/details?id=de.kai_morich.serial_bluetooth_terminal&hl=en) the connection won't even start.
I tested the program with multiple ESP32 devices from different types (NODEMCU, WROOM) but all of them had the same problem.
Related
Android 10 released support for BLE CoC connection so I wanted to try this out by making two simple android 10 apps, which would connect to each other with l2Cap and exchange "Hello World".
I wrote two apps, Server app and Client app, both having all permissions they need in their manifest files, and I run that apps on two Android 10 phones, and the connection was not established.
Here is the relevant part of my server app code:
try {
mServerSocket = bluetoothAdapter.listenUsingInsecureL2capChannel();
int psm = mServerSocket.getPsm();
} catch (IOException e) {
e.printStackTrace();
}
BluetoothSocket socket = mmServerSocket.accept();
Variable int psm is the PSM value I am using in client app.
Here is the relevant part of my client app code:
for (BluetoothDevice bluetoothDevice : deviceSet) {
if (!bluetoothDevice.getName().equals(PAIRED_DEVICE_NAME)) continue;
BluetoothDevice bd = adapter.getRemoteDevice(bluetoothDevice.getAddress());
bluetoothSocket = bd.createInsecureL2capChannel(psm_value);
break;
}
bluetoothSocket.connect();
where the string PAIRED_DEVICE_NAME is name of expected device, which is successfully found because devices are Bluetooth paired.
Int psm_value is the PSM value from server app. I suspect this might be a problem because I hard-coded this value from Server every time I tried to test this (every time was different value because this value is dynamically assigned and it lasts until you close server socket).
So my question is how to get remote PSM value? And how to connect these devices, because if I am using RFCOMM connection, this code works perfectly.
With this code I am getting error in bluetoothSocket.connect() line from client app saying:
java.io.IOException: read failed, socket might closed or timeout, read ret: -1
Thanks!
I am using Bluez 5.50; 5.48 was the version acquire-write became officially (non-experimentally) supported. Am I using the acquire-write / write feature properly?
On my Raspberry Pi Zero W:
pi#raspberrypi:~ $ bluetoothctl
[bluetooth]# power on
Changing power on succeeded
[bluetooth]# scan on
Discovery started
[bluetooth]# connect B8:27:E8:72:33:7A
Attempting to connect to B8:27:E8:72:33:7A
Connection successful
[DSD TECH]# menu gatt
[DSD TECH]# select-attribute 0000ffe1-0000-1000-8000-00805f9b34fb
[DSD TECH:/service0010/char0011]# acquire-write
[CHG] Attribute /org/bluez/hci0/dev_B8_27_E8_72_33_7A/service0010/char0011 WriteAcquired: yes
AcquireWrite success: fd 7 MTU 23
[DSD TECH:/service0010/char0011]# write("h")
[DSD TECH:/service0010/char0011]# write('h')
[DSD TECH:/service0010/char0011]# write(h)
[DSD TECH:/service0010/char0011]# write(0x68)
On my Arduino Nano connected to HM-10:
void setup()
{
Serial.begin(9600);
}
void loop() {
delay(10);
if (Serial.available())
{
char c = Serial.read();
Serial.println("Read value");
}
}
I use the iOS app named "Serial" which connects to my HM-10. I send the letter h over and read "Read value" on the arduino serial monitor. I do this directly before and after using the raspberry pi, on the same arduino serial monitor. The raspberry pi notifications never come thru. Yes, I am certain it is the same HM-10. It is the only HM-10 I have powered on in BLE range, and I cannot connect to the UUID while my phone is connected. (Actually, I submit connect B8:27:E8:72:33:7A to the raspberry pi, and keeps trying, and then disconnect from phone, and rpi automatically connects).
Thanks in advance!
When using gatt services with bluetoothctl, leave off the parentheses and just use:
write 0x68
acquire-write returns a file descriptor that can be used for writing to the GATT characteristic, usage of write will be locked. so either use acquire-write (which requires a write-without-response flag) or use write.
void WriteValue(array{byte} value, dict options)
Issues a request to write the value of the
characteristic.
Possible options: "offset": Start offset
"device": Device path (Server only)
"link": Link type (Server only)
"prepare-authorize": boolean Is prepare
authorization
request
Possible Errors: org.bluez.Error.Failed
org.bluez.Error.InProgress
org.bluez.Error.NotPermitted
org.bluez.Error.InvalidValueLength
org.bluez.Error.NotAuthorized
org.bluez.Error.NotSupported
fd, uint16 AcquireWrite(dict options) [optional]
Acquire file descriptor and MTU for writing. Usage of
WriteValue will be locked causing it to return
NotPermitted error.
For server the MTU returned shall be equal or smaller
than the negotiated MTU.
For client it only works with characteristic that has
WriteAcquired property which relies on
write-without-response Flag.
To release the lock the client shall close the file
descriptor, a HUP is generated in case the device
is disconnected.
Note: the MTU can only be negotiated once and is
symmetric therefore this method may be delayed in
order to have the exchange MTU completed, because of
that the file descriptor is closed during
reconnections as the MTU has to be renegotiated.
Possible options: "device": Object Device (Server only)
"MTU": Exchanged MTU (Server only)
"link": Link type (Server only)
Possible Errors: org.bluez.Error.Failed
org.bluez.Error.NotSupported
I've connected my sim808 module to a HC05 bluetooth module with SPP profile.
Hc05 UART config is 9600 , no parity,1 stop.
i'm connecting with these at commands:
AT+BTPOWER=1
AT+BTCONNECT=1,4 // I have already paired two devices
when i send message printf("0adch=0&temp=27&hu=14") via HC05 to SIM808 , it breaks message to multiple parts like below (I've connected SIM808 to PC via a usb-ttl convertor,so i can see messages on sim RX port) :
+BTSPPDATA: 1,1,0
+BTSPPDATA: 1,10,adch=0&tem
+BTSPPDATA: 1,10,p=27&hu=14
I have previously paired with a Bluetooth device that supports RFCOMM.
When my app is opened I continuously try to connect to the device by opening the RFCOMM. This way my app automatically connects when the device comes in range.
deviceInfoCollection = await DeviceInformation.FindAllAsync(RfcommDeviceService.GetDeviceSelector(RfcommServiceId.SerialPort));
LogData(String.Format("Number of mldp devices is {0}", deviceInfoCollection.Count));
foreach (DeviceInformation deviceInfo in deviceInfoCollection)
{
LogData(String.Format("ID:{0}, NAME:{1}", deviceInfo.Id, deviceInfo.Name));
}
Then run this on a timer:
try
{
// The first time this method is invoked by a store app, it should be called
// from a UI thread in order to display the consent prompt
// https://msdn.microsoft.com/en-us/windows.devices.bluetooth.rfcomm.rfcommdeviceservice.fromidasync
RfcommDeviceService rfcommService = await RfcommDeviceService.FromIdAsync(deviceInfo.Id);
LogData(String.Format("ID:{0}, NAME:{1}", deviceInfo.Id, deviceInfo.Name));
}
catch (Exception)
{
LogData(String.Format("Can not request rfcomm service from device ID:{0}, NAME:{1}", deviceInfo.Id, deviceInfo.Name));
}
Is there any way to query when the device is in range , rather than trying to connect? I would prefer to only attempt connection when the device is in range.
For RFCOMM (BT2.0, BT2.1) you can run a device enumeration periodically, see also Get bluetooth devices in range
However your actual implementation with a connection attempt may work a little better.
For Bluetooth 4.0, you can listen to the advertisements of the BT module, see also https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/BluetoothAdvertisement
If you're talking to an embedded device (e.g. some robot, or homebrew appliances using RFCOMM) I am afraid there is no better solution than what you're doing.
If you're taking to a phone (which supports both BT4.0 and BT2.1) you can use the BT4 advertisements to signal the proximity of the device, then connect via RFCOMM.
If I have a Android phone which is already connected with a bluetooth headset (paired and connected) to it.
How I can get information about that specific headset.
Using getBondedDevices() method I get list of all paired devices..I need information about CONNECTED device only.
I can not wait for broadcast receiver to check status, because I need this information at the start of my application. So please suggest is there any way to get this information without waiting for broadcast.
You can do this through the IBluetoothA2dp interface in API 11 and up. Some more info on there is here: Android connect to a paired bluetooth headset
Here is a great resource to see the difference in what is available to this interface between API 10 and 11 where it changed quite a bit.
http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/bluetooth/BluetoothA2dp.java/?v=diff&id2=2.2_r1.1
Hope that helps.
You can use the getConnectedDevices for the HEADSET Profile to get the device to which it is connected.
Check this out to see if headset is connected (ICS only):
public boolean isVoiceConnected()
{
boolean retval = true;
try {
retval = BluetoothAdapter.getDefaultAdapter().getProfileConnectionState(android.bluetooth.BluetoothProfile.HEADSET) != android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
} catch (Exception exc) {
// nothing to do
}
return retval;
}