BLE: when writing characteristic, getting status as 133 in onCharacteristicWrite - android

I'm trying to setup BLE client-server comm on android devices.
From the server side, I could advertise and see connection updates successfully. On the client side, I could connect to the server , discover its services and characteristics. However, when I try to write the characteristic, I'm receiving
status 133 in onCharacteristicWrite()
I'm not sure why it is happening..!! Need some help..
I've tried to do the following, but they didn't make any impact:
-> adding setWriteType
-> Changing the UUID to a private one
Do I have to get permissions before writing at client side?

I would start from checking the property of the characteristics.
Checkout this thread for more information.
If the above actions does not help then try to verify that the attributes of the BLE server side are correct. For example: if you just connecting (with no pairing or bonding) then since it's an non-encrypted link the attributes of the characteristic shouldn't include any encryption enabled.

Related

Bluetooth LE: Send "Handle Value Notification" to device

I'm trying to reproduce an ATT packet being sent to a Bluetooth LE device already connected to a phone.
Is this even possible?
I've figured out how the packet should look like, I'm just not able to wrap my head around GATT and how it translates to ATT in this specific case.
The wireshark dump looks like this:
localhost () remote () ATT 26 Sent Handle Value Notification, Handle: 0x0035 (Unknown)
Bluetooth Attribute Protocol
Opcode: Handle Value Notification (0x1b)
0... .... = Authentication Signature: False
.0.. .... = Command: False
..01 1011 = Method: Handle Value Notification (0x1b)
Handle: 0x0035 (Unknown)
Value: 0a0b313233343536373839303132
I've already figured out that the actual application payload here starts after the handle 0x0035, with 0x0a 0x0b being some custom control characters and everything afterwards a number (123456789012), exactly as I expected it to be.
How do I translate the "handle" to the GATT protocol? Is this done in Android GATT via UUIDs? If I loop over all services on that device a get a bunch of services, loads of characteristics, descriptors and I'm lost.
Oh, what I forgot to mention: None of the services and characteristics I get seem to be related to the handle 0x0035.
Is "getInstanceId" supposed to return the handle that will be used? Writing to writable characteristics on that device lead to Wireshark showing the handle value corresponding to the getInstanceId.
first thing you have to know is that in Android you can't use the Handles direktly as a developer. You have to deal with the UUIDs. in Wireshark when you have a look at the ATT Protocoll you should be able to see the UUID of the service and the characteristic when opening the Handle drop down. With this Information you should be able to detect the UUids you need.
https://developer.android.com/guide/topics/connectivity/bluetooth-le shows you how to send a value to a notification. In general you can use Constants for example to ebanle notifications. I guess if your server requires specific bytes you should be able to send them the same way.
Well, after inspecting logs and docs a little more I came to the conclusion that the remote device (which should provide serivces) here is actually using a server on the local host and this is a value notification sent from the host to the remote.

Android BLE peripheral disconnects with status code BLE_HCI_INSTANT_PASSED(0x28)

My application is able to connect to the BLE peripheral(which is an OBDII/J1939 device) device successfully.
2018-01-24 14:58:38,413 INFO LogUtil - GATT Server Status = (0) : BLE_HCI_STATUS_CODE_SUCCESS(0x00)
2018-01-24 14:58:38,414 INFO LogUtil - GATT Server New State = (2) : STATE_CONNECTED
2018-01-24 14:58:38,414 INFO LogUtil - Connected to GATT server.
Application started communication with the device but after some time it received GATT server disconnection message in onConnectionStateChange in callback implementation of BluetoothGattCallback . Below are the logs from application:
2018-01-24 15:07:46,396 INFO LogUtil - GATT Server Status = (40) : BLE_HCI_INSTANT_PASSED(0x28)
2018-01-24 15:07:46,397 INFO LogUtil - GATT Server New State = (0) : STATE_DISCONNECTED
2018-01-24 15:07:46,398 INFO LogUtil - Disconnected from GATT server.
Not able to find any reason behind BLE_HCI_INSTANT_PASSED status code.
Any help on this will be helpful.
When data is being transmitted over BLE, data transfers can only start at sync points in time known as "connection events". At the BLE link layer there are couple special requests that can be made which are relative to these sync points. They are:
LL_CHANNEL_MAP_REQ - A request to change the BLE channels being transmitted on. Bluetooth chips will change the channel map based on the noise in the environment to try to limit packet drop.
LL_CONNECTION_UPDATE_REQ - A request to change the frequency of "connection events" (known as the "connection interval"). This is done to achieve better throughput/latency or save more power.
Each of these Link Layer requests when sent over the air contains an "Instant" to change. The "Instant" is the "connection event" in the future to apply the change.
At the Link Layer, BLE is reliable. This means each Link Layer packet must be ack'd by the other side. In a noisy RF environment, it's possible a link layer packet may require a couple retries to actually send. This means the packet could arrive many "connection events" after originally intended.
If one of the packets mentioned above is received after the "Instant" the changes were supposed to be applied, by definition the BLE chip must disconnect with reason 0x28 (Instant Passed)
For additional details on the topic, the Bluetooth Core Specification available from the Bluetooth SIG website is a good reference:

Bluetooth SPP profile on SIM800H

I'm having issues when trying to use bluetooth on my project. On previous version I used the HC-05 module for bluetooth and it gives me a simple serial connection right after any device connects. Now the project evolved and we opted on using SIM800H because it gives us GSM+Bluetooth.
When I connect any android device it gives me some profiles but never SPP. I can pair normally but when using any SPP server app (https://stackoverflow.com/a/4037619/2637661) I can never send or get data from my device. If I start the connection from the Android app, it says that it's connecting while the SIM800 gives me the URC and I respond:
+BTCONNECTING: "34:c7:31:aa:37:5b","SPP"
AT+BTACPT=1
OK
+BTCONNECT: 1,"Android",34:c7:31:aa:37:5b,"SPP"
But it stays on server mode and I can't use the commands AT+BTSPPSEND or AT+BTSPPGET, as the documentation says.
On the other hand, if I start the connection from my device just like the docs say:
AT+BTCONNECT=1,4 // Device is 1 and SPP profile is 4
OK
AT+BTSPPSEND
>I type anything here + ctrl+z
SEND FAIL
and get nothing on the Android side.
Plus in both cases the connection drops after something like 30s and I can't reestablish it unless I turn the SIM800H off and on again.
Got no success using the APP mode either (sending the string "SIMCOMSPPFORAPP" right after connection succeeds for transparent communication).
The SIM800H firmware version is
AT+CGMR
Revision:1309B07SIM800H32_BT
and I tried using the following apps
Bluetooth Terminal
Bluetooth spp pro
BlueSPP
The GSM side works flawlessly and I can send/receive TCP messages everytime I try.
Does anyone have any kind of experience using this module? Thanks for reading!
UPDATE:
I'm using a simple sketch in order to talk with the module's serial, don't know if it's relevant but here it goes.
#define SIM800_POWER 23
void setup() {
Serial.begin(9600);
Serial1.begin(19200);
Serial.print("Setting all up");
pinMode(SIM800_POWER, OUTPUT);
Serial.print(".");
delay(500);
digitalWrite(SIM800_POWER, HIGH);
Serial.print(".");
Serial.println("OK");
}
void loop() {
if(Serial1.available()){
Serial.write(Serial1.read());
}
if(Serial.available()){
Serial1.write(Serial.read());
}
}
And what I get after trying Andrii's answer:
Setting all up..OK
AT
OK
AT
OK
AT
OK
AT+BTPOWER=0
OK
AT+BTPOWER=1
OK
AT+BTCONNECT=1,4
OK
+BTCONNECT: 1,"Will",d4:87:d8:77:37:0b,"SPP"
AT+BTSTATUS?
+BTSTATUS: 5
P: 1,"Will",d4:87:d8:77:37:0b
C: 1,"Will",d4:87:d8:77:37:0b,"SPP"
OK
AT+BTSPPSEND
> SIMCOMSPPFORAPP
SEND FAIL
Seems AT+BTSPPSEND without any parameters is only for AT-command send from client (your SIM800H) to server (other SIM800, not your Android device unless your Android device implements AT-command support). For data sending you should use AT+BTSPPSEND and after receiving > symbol send SIMCOMSPPFORAPP keyword and then, after receiving SEND OK response send command AT+BTSPPSEND=<LENGTH_OF_YOUR_DATA> and then, after receiving > symbol, send your data until Ctrl+Z code e.g.:
AT+BTSPPSEND
> SIMCOMSPPFORAPP
SEND OK
AT+BTSPPSEND=5
> HELLO
SEND OK
^Z
where HELLO - is your data, and 5 in AT+BTSPPSEND=5 is length of HELLO string. Details in SIM800H_BT_Application_Note.
UPDATE
Selected by bold small, but important part of answer (thanks to hlovdal)

BLE Device dissonect after receive Notifications (BLEGattException Status = 0x8)

My BLE server permanently measures a sensor value and sends a notification with 20 byte user data after each measurement. The goal is to generate as much throughput as possible.
On the client side, the value sent by the server is received and processed.
rxBleConnection.setupNotification(setDescriptorEnableNotification(characteristic))
.flatMap(notificationObservable -> notificationObservable)
.observeOn(Schedulers.newThread())
.buffer(1)
.subscribe(bytes -> {
onNotificationReceived(bytes, buffer);
} , throwable -> {
// Handle an error here.
onNotificationSetupFailure(throwable);
}
);
If I set the Connection intervall to 11.25ms, I receive all values. However, if I set the connection interval to 30ms, I receive a few values ​​and then the connection is closed.
In the Android Log i see the followed message:
BleGattException status=8 (0x8),
bleGattOperationType=BleGattOperation{description='CONNECTION_STATE'
Why is the connection interrupted and what is the trigger?
With the help of a BLE Sniffer this is not recognizable. The set connection parameters are accepted and the transfer begins. Suddenly the transmission ends and the error message appears.
Update:
BLE Sniffer screenshot has been added:
30ms, this is connection interval you set in server or android?
Btw, on android you can set speed mode
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
mBluetoothGatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);
}
Error 8 means the connection timed out. There is nothing wrong on the Android side. The problem is with the communication between the two Bluetooth controllers. If you have a sniffer then you should be able to see who is the one that fails to send packets.
Here is an Image from BLE Sniffer.
BLE Sniffer
I have the similar problem. On Android 7.0 there were two ways to keep connection:
1) If devices are bonded and there is a charachteristic reading callback with constant thread of packets. If there are no packets by some time, then connection fails.
2) If devides are not bonded, but I do TXCharacheristic.read every few seconds. If don't do that some time, then connection fails.
But now in Android 7.1.2 this way doesn't work.
May be the first way will work for you.
On your Android device you should make bonding, on your kit you should handle this bonding.
On Nexus 6P and Samsung S7 it doesn't work anymore, but I didn't try it on the other devices.
I suppose, you have min connection interval 7.5 on your BLE kit, but now it is deprecated on Android.
Try to set min connection interval to 11.25 on your BLE kit and set connection priority
gatt.requestConnectionPriority(CONNECTION_PRIORITY_HIGH);
where CONNECTION_PRIORITY_HIGH = 1
in onConnectionStateChange.
It had worked for me when I had changed min connection interval in my nordic from 7.5 to 11.25.

Android as BLE peripheral

I'm trying to create an Android 5 (lollipop) app that acts as a Bluetooth Low Energy (BLE) peripheral. The app runs on a Nexus 9 which supports BLE peripheral mode. So far I've managed to advertise a service and allow another BLE device connect to it successfully. However, it is fails when trying to read the characteristic value.
I've checked that the characteristic has the read property and that the read permission is set.
When using the LightBlue iOS app (https://itunes.apple.com/gb/app/lightblue-bluetooth-low-energy/id557428110?mt=8) I manage to discover and connect to my Nexus and see the characteristic uuid but the value doesn't show.
Any help would be highly appreciated.
First check the characteristic data you are advertising in the peripheral mode usually there are three modes
BluetoothGattCharacteristic.PROPERTY_WRITE, BluetoothGattCharacteristic.PROPERTY_READ,
BluetoothGattCharacteristic.PROPERTY_NOTIFY;
and you can build characteristic with all modes using
BluetoothGattCharacteristic.PROPERTY_WRITE |BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_NOTIFY;
Once done look for onCharacteristicWriteRequest() in BluetoothGattServerCallback() that you gave while building characteristic. When central want to send data it can write data to the characteristic with WRITE mode and you will have onCharacteristicWriteRequest() callback method triggered at peripheral side and you will have data in byte[] and make sure send response using btGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, null);
by checking the responseNeeded bool value in callback method. In this way the data is transferred from central to peripheral.
And to send data from peripheral to central use notification charatertertistc
BluetoothGattCharacteristic bgc = bluetoothGattService
.getCharacteristic(chartersticUUID);
bgc.setValue(bnd.data);
btGattServer.notifyCharacteristicChanged(centralbluetoothdevice, bgc, false);
.

Categories

Resources