I'm android developer and facing some autoConnect issue.
I'm using Arduino nano IOT and developed some simple application to communicate.
but I don't know why autoConnect doesn't work in this case.
Arduino nano continuously sends gyroscope sensing data(but only when app connected to module)
below is sample code.
#include <ArduinoBLE.h>
#include <Arduino_LSM6DS3.h>
BLEService sensorService("66df5109-edde-4f8a-a5e1-02e02a69cbd5");
BLEStringCharacteristic xSensorLevel("741c12b9-e13c-4992-8a5e-fce46dec0bff", BLERead | BLENotify,15);
BLEStringCharacteristic ySensorLevel("baad41b2-f12e-4322-9ba6-22cd9ce09832", BLERead | BLENotify,15);
BLEStringCharacteristic zSensorLevel("5748a25d-1834-4c68-a49b-81bf3aeb2e50", BLERead | BLENotify,15);
// last sensor data
float oldXLevel = 0;
float oldYLevel = 0;
float oldZLevel = 0;
long previousMillis = 0;
void setup() {
Serial.begin(9600);
while (!Serial);
if (!IMU.begin()) {
Serial.println("Failed to initialize IMU!");
while (1);
}
pinMode(LED_BUILTIN, OUTPUT);
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1);
}
BLE.setLocalName("Demo Gyroscope");
BLE.setAdvertisedService(sensorService);
sensorService.addCharacteristic(xSensorLevel);
sensorService.addCharacteristic(ySensorLevel);
sensorService.addCharacteristic(zSensorLevel);
BLE.addService(sensorService);
BLE.advertise();
Serial.println("Bluetooth device active, waiting for connections...");
}
void loop() {
BLEDevice central = BLE.central();
if (central) {
Serial.print("Connected to central: ");
Serial.println(central.address());
digitalWrite(LED_BUILTIN, HIGH);
while (central.connected()) {
//long currentMillis = millis();
updateGyroscopeLevel();
delay(300);
}
digitalWrite(LED_BUILTIN, LOW);
Serial.print("Disconnected from central: ");
Serial.println(central.address());
}
}
void updateGyroscopeLevel() {
float x, y, z;
if (IMU.gyroscopeAvailable()) {
IMU.readGyroscope(x, y, z);
if (x != oldXLevel) {
xSensorLevel.writeValue(String(x));
oldXLevel = x;
}
if (y != oldYLevel) {
ySensorLevel.writeValue(String(y));
oldYLevel = y;
}
if (z != oldZLevel) {
zSensorLevel.writeValue(String(z));
oldZLevel = z;
}
Serial.print(x);
Serial.print('\t');
Serial.print(y);
Serial.print('\t');
Serial.println(z);
}
}
and in my android app, I have set autoConnect true
private fun connectDevice(device: BluetoothDevice?) {
// update the status
broadcastUpdate(Actions.STATUS_MSG, "Connecting to ${device?.address}")
bleGatt = device?.connectGatt(context, true, gattClientCallback)
}
App can connect to module and read/write some data using UUID but when I turn off the module and turn on again, App cannot automatically connect it.
As far as I know, once I set it true, android store bt info as cache and trying to reconnect repeatedly.
(fyi, I'm not using Service to maintain connection)
but in my case, when I turn the module on again, it just shows below message in serial monitor
Bluetooth device active, waiting for connections...
It seems like app doesn't retry to connect.
I have read related questions and answers over here but couldn't find clue for my case.
My question over here is am I doing wrong? or this is normal behaviour?
when it comes to bt earphone, it's automatically connected when turn on. so I'm thinking something like that.
Please share any idea for this.
Really appreciate it!
After reading more articles, I found what's the issue.
Not sure if anyone reaching out to this question but in my case, I want app to reconnect to ble automatically even after turning off and on the ble.
But I found turning off/on the phone, turning off/on ble clear the cache in android internally. so Cannot automatically reconnect in this scenario.
Please have a look. this is really helpful for me
https://medium.com/#martijn.van.welie/making-android-ble-work-part-2-47a3cdaade07
This is not an answer but I found autoConnect is working when I use nRF Connect application. that means BT module itself has no issue and my application has issue.
Related
I'm working on a cross-platform (iOS/Android) Xamarin app, in which I need to scan IBeacon devices to assert the distance between them and the phone device.
On iOS, I use the native iOS iBeacon API, which works flawlessly and as expected.
On Android, since Android does not natively support iBeacon, I use a mix of my own code and a library "UniversalBeacon". This approach works, but when it comes to scanning (or "ranging") for Beacons over a period of time, in order to constantly assess the distance of the phone device, the experince proves very unreliable.
I am experiencing that incoming BLE packets come in as expected, but only in intervals.
Roughly summarized: Packets will come in, in a steady stream, for a seemingly random amount of time, before the packets eventually stop coming in entirely. Then, after another seemingly random amount time, packets will start coming in again. This process repeats indefinitely.
So my question is: What is causing this issue? Is it an Android quirk that I somehow have to work around?
Initiating the scan:
_ScanCallback.OnAdvertisementPacketReceived += ScanCallback_OnAdvertisementPacketReceived;
var settings = new ScanSettings.Builder()
.SetScanMode(ScanMode.LowLatency)
.Build();
_Adapter.BluetoothLeScanner.StartScan(null, settings, _ScanCallback);
Callback implementation:
internal class BLEScanCallback : ScanCallback
{
public event EventHandler<BLEAdvertisementPacketArgs> OnAdvertisementPacketReceived;
public override void OnScanFailed([GeneratedEnum] ScanFailure errorCode)
{
base.OnScanFailed(errorCode);
}
public override void OnScanResult([GeneratedEnum] ScanCallbackType callbackType, ScanResult result)
{
base.OnScanResult(callbackType, result);
switch (result.Device.Type)
{
case BluetoothDeviceType.Le:
case BluetoothDeviceType.Unknown:
try
{
var p = new BLEAdvertisementPacket
{
BluetoothAddress = result.Device.Address.ToNumericAddress(),
RawSignalStrengthInDBm = (short)result.Rssi,
Timestamp = DateTimeOffset.FromUnixTimeMilliseconds(result.TimestampNanos / 1000000),
AdvertisementType = (BLEAdvertisementType)result.ScanRecord.AdvertiseFlags,
Advertisement = new BLEAdvertisement
{
LocalName = result.ScanRecord.DeviceName
}
};
if (result.ScanRecord.ServiceUuids != null)
{
foreach (var svc in result.ScanRecord.ServiceUuids)
{
var guid = new Guid(svc.Uuid.ToString());
var data = result.ScanRecord.GetServiceData(svc);
p.Advertisement.ServiceUuids.Add(guid);
}
}
var recordData = result.ScanRecord.GetBytes();
var rec = RecordParser.Parse(recordData);
foreach (var curRec in rec)
{
if (curRec is BLEManufacturerData md)
{
p.Advertisement.ManufacturerData.Add(md);
}
if (curRec is BLEAdvertisementDataSection sd)
{
p.Advertisement.DataSections.Add(sd);
}
}
OnAdvertisementPacketReceived?.Invoke(this, new BLEAdvertisementPacketArgs(p));
}
catch (Exception ex)
{
Debugger.Break();
}
break;
default:
break;
}
}
}
I've read in various articles that this could be caused by Android automatically suspending the scan in order to save power. Whether this is the case is not obvious to me, as there does not seem to be much support on the subject.
I've already tried the following:
Changing ScanMode to LowPower/Balanced - no change
Scanning with a filter set to the specific Beacon I was testing with - filter worked, but no change in regards to the issue
Implementing logic that restarts the scan in set intervals to work around potentional limits for scan duration imposed by Android - did not affect the issue
Using other, more broadly used libraries, such as Shiny.Beacons - same experience
The issue is not caused by the Beacon device itself not advertising correctly - I've made sure of this by scanning it on another device, at the same time as my app. It is the app itself that stops scanning and/or receiving its advertisement packets.
Thanks for your time :)
I encountered a strange problem when trying to unpair and pair again with my smartphone. Currently I write a C# application on UWP (Windows 10) for BLE connection with a remote device. I use my smartphone with nRF Connect App as the peripheral.
After being paired for a while (and being inactive), when unpairing and pairing again, the application gets stuck when trying to pair again.
I broke everything down to the most basal application I could create. This is a Console App that scans the existing devices and then unpairs and pairs with the selected device:
using BLE_Test;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static async Task Main(string[] args)
{
Dictionary<ulong, string> uuidDict = BleModule.Scan().Result;
Console.WriteLine("Devices found:");
int i = 0;
foreach (var uuid in uuidDict.Keys)
Console.WriteLine(string.Format("ID: {0}, UUID: {1}, Local Name: {2}", i++, uuid, uuidDict[uuid]));
Console.WriteLine("Select ID!");
int id = int.Parse(Console.ReadLine());
ulong selectedUuid = (uuidDict.ElementAt(id)).Key;
await BleModule.Unpair(selectedUuid);
await BleModule.Pair(selectedUuid);
Console.ReadLine();
}
}
}
It calls an UWP DLL called "BLE_Test" with the class "BleModule":
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.Advertisement;
using Windows.Devices.Enumeration;
namespace BLE_Test
{
public class BleModule
{
public static async Task<Dictionary<ulong, string>> Scan()
{
var uuidDict = new Dictionary<ulong, string>();
BluetoothLEAdvertisementWatcher watcher = new BluetoothLEAdvertisementWatcher();
watcher.Received += (BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
=> AddAdvertisement(eventArgs, uuidDict);
watcher.Start();
await Task.Delay(10000);
watcher.Stop();
return uuidDict;
}
private static void AddAdvertisement(BluetoothLEAdvertisementReceivedEventArgs eventArgs, Dictionary<ulong, string> uuidDict)
{
if (uuidDict.ContainsKey(eventArgs.BluetoothAddress) == false)
uuidDict.Add(eventArgs.BluetoothAddress, eventArgs.Advertisement.LocalName);
}
public static async Task Pair(ulong uuid)
{
Console.WriteLine("Pairing...");
var bluetoothLEDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(uuid);
if (bluetoothLEDevice == null)
{
Console.WriteLine("UUID not found!");
return;
}
DeviceInformationCustomPairing customPairing = bluetoothLEDevice.DeviceInformation.Pairing.Custom;
customPairing.PairingRequested += (DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args) => args.Accept(); // We auto-accept numeric comparison result for the sake of simplicity
DevicePairingResult result = await customPairing.PairAsync(DevicePairingKinds.ConfirmPinMatch);
Console.WriteLine("Pairing Result: " + result.Status.ToString());
}
public static async Task Unpair(ulong uuid)
{
Console.WriteLine("Unpairing...");
var bluetoothLEDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(uuid);
if (bluetoothLEDevice == null)
{
Console.WriteLine("UUID not found!");
return;
}
DeviceUnpairingResult result = await bluetoothLEDevice.DeviceInformation.Pairing.UnpairAsync();
Console.WriteLine("Unpairing Result: " + result.Status.ToString());
}
}
}
If I start the program for the first time, the pairing works fine (the unpairing will be ignored as the devices are not paired yet). If I start it immediately again afterwards, it also works fine. Unpairing and pairing will both take place. But if I wait a while (typically 5-10 minutes) while not doing anything, when I start the program again, it will unpair, but then it will wait indefinitely for PairAsync() to return. No coupling request will show on the nRF Connect App, and no PairingRequested event will appear.
Aborting the stuck program and restarting it won't help. In this case, even though the smartphone is found by the BluetoothLEAdvertisementWatcher, BluetoothLEDevice.FromBluetoothAddressAsync(uuid) will return null and the device can't be paired anymore. This can only be resolved by restarting the computer or switching off and on the advertisement in the nRF Connect App, as in this case a new random BLE Address is created for the device.
I have taken a snapshot of the BLE events using Btetlparse and Wireshark. It seems that there is a problem with a malformed package:
However, I don't really understand what is going wrong. Is this a problem of the nRF Connect App? Or the UWP commands? Or did I do something wrong? I tried two different smartphones (a Samsung Galaxy and an Oppo), so I doubt that it is a problem of the smartphone. I also added a DeviceWatcher, but this didn't change anything. Can anyone help me here?
I'm developing an application to pair with two kind of sensors with the app and also these sensors are pairing with each other, we developed our custom bluetooth communication protocol. The connection is working great usually, but there are still some errors that I'm having hard time to fix it.
Sensor 1 paring alone is working great, but every time I'm pairing both of them, then i close the app, pair it again with first sensor, I got disconnected with status 19 just after the connection is established, after I try again one or two times the connection will be established properly. I was thinking that was a problem with Gatt refresh, but I already tried one solution found here and I keep reproducing this error every time.
fun connectToDevice(device: BraincareDevice, pairColor: Int) {
BleLogHelper.writeLog("Connecting to ${device.name}")
isConnecting = true
val deviceType = if (device is Sensor) DeviceType.SENSOR else DeviceType.DONGLE
if (deviceType == DeviceType.SENSOR) {
sensorConnectionSubscription?.dispose()
} else {
dongleConnectionSubscription?.dispose()
}
val connectionSubscription = device.device.establishConnection(false)
.flatMapSingle { connection ->
if (device is Sensor) {
sensorConnection = connection
connectedSensor = device
} else if (device is Dongle) {
dongleConnection = connection
connectedDongle = device
}
connection.queue(CustomRefresh())
?.observeOn(Schedulers.io())
?.doOnComplete{
BleLogHelper.writeLog("GATT REFRESHED")
}
?.subscribe ({
BleLogHelper.writeLog("GATT REFRESHED")
},{
BleLogHelper.writeLog("FAIL REFRESHING GATT")
})
BleLogHelper.writeLog("Send Request Connection Command $deviceType")
val command = BraincareBluetoothCommandProtocol.createRequestConnectionCommandFrame(deviceType)
connection.writeCharacteristic(BraincareBluetoothProtocol.rxCharacteristicUUID, command)
}
.delay(300, TimeUnit.MILLISECONDS)
.subscribe({
BleLogHelper.writeLog("Connection Established ${device.type}")
val iscon= this.isConnecting
startBlinkingDeviceLed(deviceType, pairColor)
connectionFlowListeners.forEach { it.onConnectionEstablished(device) }
}, {
BleLogHelper.writeError("Connection Lost ${device.type}", it)
BleLogHelper.writeError("Retrying...", it)
val iscon= this.isConnecting
if (isMonitoring || isConnecting || deviceType == DeviceType.DONGLE){
connectionStateListeners.forEach {
if (deviceType == DeviceType.SENSOR) {
sensorNotificationSubscription?.dispose()
sensorRssiSubscription?.dispose()
blinkingDeviceLedsSubscription?.dispose()
disconnectFromDevice(DeviceType.SENSOR)
} else {
dongleRssiSubscription?.dispose()
disconnectFromDevice(DeviceType.DONGLE)
}
isConnecting = false
it.onConnectionLost(device)
}
}else{
reconnectToDevice(device, pairColor)
}
})
if (deviceType == DeviceType.SENSOR) {
sensorConnectionSubscription = connectionSubscription
} else {
dongleConnectionSubscription = connectionSubscription
}
}
The exception is firing just after connection.writeCharacteristic(BraincareBluetoothProtocol.rxCharacteristicUUID, command)
Log error:
2019-05-21 10:54:11.816 11797-11889/io.b4c.brain4care.debug E/BLEBC: 21/05/2019 10:54:11.810 - Connection Lost SENSOR
com.polidea.rxandroidble2.exceptions.BleDisconnectedException: Disconnected from D4:57:4F:53:44:E7 with status 19 (UNKNOWN)
at com.polidea.rxandroidble2.internal.connection.RxBleGattCallback$2.onConnectionStateChange(RxBleGattCallback.java:77)
at android.bluetooth.BluetoothGatt$1$4.run(BluetoothGatt.java:268)
at android.bluetooth.BluetoothGatt.runOrQueueCallback(BluetoothGatt.java:789)
at android.bluetooth.BluetoothGatt.-wrap0(Unknown Source:0)
at android.bluetooth.BluetoothGatt$1.onClientConnectionState(BluetoothGatt.java:264)
at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:70)
at android.os.Binder.execTransact(Binder.java:682)
status=19 is GATT_CONN_TERMINATE_PEER_USER. This library since version 1.8.1 lists the reason properly. It is always advised to use the newest available version of basically any library as they bring improvements over time.
There is no clear question in the post. With the provided information it is not possible to tell more than the above — the peripheral you use disconnects from the app. Why this happens is up to your peripheral and you can possibly find an answer in the documentation.
Bear in mind that newer Android versions do not allow concurrent pairing procedures to more than one BLE device at a time. Pairing of two devices should be performed sequentially i.e.
Peripheral A starts pairing
Peripheral A finishes pairing
Peripheral B starts pairing
Peripheral B finishes pairing
Peripherals may be connected at the same time but only a single pairing procedure may be held at a time.
i'm working for a project using arduino and android studio, I would like to control my arduino from my mobile application by sending 0 t of 1, then I would like to receive arduino data on my android application,it is an obstacle detector that sends warning when there is an obstacle, here is the code of the arduino, it works because I tested with an application that I downloaded from google play, now I do not know how to display the message sent by arduino on my mobile application, and also how control the arduino from my app.
int echo = 3;
int trig = 2;
int greenled=4;
int redled=5;
float timelapse;
float distance;
char state=' ';
void setup() {
pinMode(greenled, OUTPUT);
pinMode(redled, OUTPUT);
pinMode(trig,OUTPUT);
pinMode(echo,INPUT);
digitalWrite(trig,LOW);
digitalWrite(greenled,LOW);
digitalWrite(redled,LOW);
Serial.begin(9600);
}
void loop() {
if (Serial.available()>0){
digitalWrite(trig,HIGH);
delayMicroseconds(10);
digitalWrite(trig,LOW);
timelapse=pulseIn(echo,HIGH);
distance = timelapse/58 ;
// if (distance > 200 || distance< 0 ) { Serial.println ( "Out of range"); }
if ( distance < 100 ) {
digitalWrite(redled, HIGH);
digitalWrite(greenled,LOW);
Serial.println("Attention");
delay(150);
}
else {
digitalWrite(redled,LOW);
digitalWrite(greenled,HIGH);
Serial.println("Libre");
}
delay(50);
}
else {
digitalWrite(redled,LOW);
digitalWrite(greenled,LOW);
digitalWrite(trig,LOW);
}
}
You didn't specify anything about how you're connecting your Arduino with your mobile phone. There are multiple ways to connect them together.
My wild guess here is that you're using a wired connection, as I see no code related to Bluetooth or any other communication.
If you're using OTG wired connection then, this would help.
Incase you want to do it wirelessly, you can read and write using serial port to a PC/Pi and then use a python script to upload the data to a cloud like firebase, and then read and data in your Android app from firebase. This is just one suggestion, there are many.
I'm creating windows application in C++, which connect's PC with mobile via bluetooth and winsock. Allow's you to call and send messages from mobile via computer.
I'm using AT command's to tell mobile what i want to do. Pair with mobile device and force a call with At command
ATD+420******;
works perfect, but all commands for handling SMS like
AT+CMGL, AT+CMGF, AT+CMGS etc.
phone probably doesnt recognize them and returns ERROR.
Here is code which connects PC with mobile via bluetooth and socket:
SOCKADDR_BTH RemoteEndPoint;
RemoteEndPoint.port = 0;
RemoteEndPoint.addressFamily = AF_BTH;
RemoteEndPoint.btAddr = m_foundDevices[m_deviceIndex].Address.ullLong;
RemoteEndPoint.serviceClassId = HandsfreeServiceClass_UUID;
int BTHAddrLength = sizeof(RemoteEndPoint);
// Create the socket.
if ((m_localSocket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM)) == INVALID_SOCKET)
{
// handle error.
}
// Connect the socket.
if ((iResult = connect(m_localSocket, (SOCKADDR *)&RemoteEndPoint, sizeof(RemoteEndPoint))) == INVALID_SOCKET)
{
// handle error.
}
Notice line
RemoteEndPoint.serviceClassId = HandsfreeServiceClass_UUID
I think the problem is here, becouse u cant send sms from Handsfree, but when i use another UUID, it doesnt even pair with mobile.
=== Here is just for info, how am i sending and receiving data from mobile ===
char recvbuf[DEFAULT_BUFLEN] = "";
const char *sendbuf = "AT+CMGL\r";
int len = (int)strlen(sendbuf);
if ((iResult = send(m_localSocket, sendbuf, len, MSG_OOB)) == SOCKET_ERROR)
{
// handle error. return ~0
}
if ((iResult = recv(m_localSocket, recvbuf, recvbuflen, 0)) == SOCKET_ERROR)
{
// handle error. return ~0
}
// Here recvbuf == "\r\nERROR\r\n"
-- I would like to find out the problem, why AT command's for SMS doesnt work.
Thank you for any advices!
If you have any question's about problem, i'll kindly explain.
Regards,
Filip.
EDIT
I found out answer "If you want to send SMS Messages, a Server Socket will be needed on the GSM Device", but after hours of googling i have no clue how to do that. Any suggestion's? Thank you.