I'm experimenting with Bluetooth LE with GATT and I have encountered a problem I need your help with.
I'm sending Data back and forth between a Client (One Android Application and one iOS Application) and a Server (Currently running Bleno).
I have chosen an architecture with one Characteristic only (which I think of as a Socket) and I write Requests on it from the Clients. The Server responds to the request with a Notification. Notifications can only be 20 Bytes long, so I sometimes have to split the response into several Chunks and send it as separate notifications.
My problem is that when I split the response into 10 Chunks or more, they are never received on the Clients. (For 1..9 Chunks everything works as expected).
I have used HCIDump (hcidump -i hci0 -X) to inspect the commands sent over BLE both when it fails and when it succeeds.
The following output is taken from HCIDump when sending the notifications succeeds:
< ACL data: handle 69 flags 0x00 dlen 27
ATT: Handle notify (0x1b)
handle 0x000c
value 0x06 0x09 0x46 0x46 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47
followed by:
> HCI Event: Number of Completed Packets (0x13) plen 5
handle 69 packets 1
(for each of the Notification Chunks)
The next output is taken from HCIDump when failing to send notifications:
< ACL data: handle 68 flags 0x00 dlen 27
ATT: Handle notify (0x1b)
handle 0x000c
value 0x08 0x0a 0x46 0x46 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47 0x47
But I get no "Completed packets" events, but instead a simple device: disconnected.
I have yet to figure out on which side of the communication the error occurs. As far as I know, it could be either the Clients not being able to receive and Ack the Notifications "fast" enough, our because I'm queueing too many requests on the Server side.
I have tested to add Sleep() commands between sending each notification on the Server. It does work, but feels too unstable. For 10 notifications, I needed 6 ms delay for the notifications to come through, for 30 notifications, I needed 10 ms delay.
Does anyone know where to start looking for the problem? I'm happy to provide more information if needed.
Notes:
I have tested and found exactly the same limits with my Android and iOS device.
There's a limit to how many "chunks" you can send before the queue gets filled. You have to wait for the central to confirm that it's ready to receive more data before you send the next chunk.
In bleno's case you'd wait to get back an indication in your characteristic's onIndicate callback before sending the next chunk:
var Characteristic = bleno.Characteristic;
var characteristic = new Characteristic({
uuid: 'fffffffffffffffffffffffffffffff1',
properties: [ ... ],
secure: [ ... ],
value: null,
onIndicate: null // <-- Right here
});
At least for iOS, you don't have to change your implementation to get an indication back. As long as you've called setNotifyValue:forCharacteristic: you also enable indications, as per Apple's documentation:
Sets notifications or indications for the value of a specified characteristic.
I'm not sure if more work is required for Android.
Related
I wrote a program using python3.8.2 and pymodbus on a beaglebone to do modbus RTU communication via RS485. I am using a MAX13487E on a cape connected to UART1 to drive the RS485 (p9_24, p9_26). The beaglebone is the master.
For my purposes I only require to use FC3 (read holding) and FC6 (write holding). I have been able to write with no issue. However, I am unable to read. Pymodbus returns an exception ModbusIOException('No Response received from the remote unit/Unable to decode response', 4).
Using pymodbus REPL to debug, I found that the replies received were the same as the requests sent, only shorter as the master is expecting a shorter response. i.e.
SEND: 0x32 0x3 0x1 0x30 0x0 0x1 0x80 0x3a
RECV: 0x32 0x3 0x1 0x30 0x0 0x1 0x80
I have been able to poll this same slave in the past using other masters (e.g. diagslave-modpoll for windows) with no problems.
What would be the reason this would be happening? If anyone has any experience working with the MAX13487E transceiver, would you be able to aid in its use?
I found an attribute of ModbusRTUClient() included in the kwargs** called "handle_local_reflection". Setting that to true seemed to solve the problem. I didn't bother looking into how it works, I'm just happy that it does.
However, if I was doing multiple requests in succession in only worked for the first one. Adding a small delay time.sleep(0.05) between requests made it all more stable.
In prior kernels and releases of Ubuntu, it was possible to use the hci socket interface to send an arbitrary set of 31 bytes as an advertising beacon, but in ubuntu 20.04 the hci bluetooth tools were deprecated, as were some elements of the socket API they were using.
The goal is to have some N number of devices broadcast 31 bytes of sensor data to each other at a rate of 5 Hz, and have all N read the packets from the other devices.
With the hci socket API being deprecated, the replacements are the DBus BlueZ API and the Management BlueZ API. The DBus API is limited and seems to only allow a max of 25 bytes. The Management API seems more capable, and it seems to work on Ubuntu 18.04/4.15 kernel (though even there the scan seemed to only pick up the advertisements sporadically when switching between scan and advertise every 100ms while with the hci api it was rock solid), but on Ubuntu 20.04/5.4 kernel, various issues crop up.
Using the hci socket API seems like it could still be possible, but even running something like hcitool lescan results in btmon saying Command Disallowed. I believe this might be due to LE Extended Advertising being enabled, but I have not figured out how to disable it yet.
Using the DBus API (or bluetoothctl) is still limited and doesn't allow the full use of the 31 bytes (or even 30 bytes + length)
Using the Management API leads to a Advertising Timeout shortly after setting the advertising data, which I think might be from LE Extended Advertising being enabled. This problem persists even if I explicitly set the timeout in the packet.
For example, running
btmgmt add-adv -c -d 1E000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D 1
to send an advertising packet at a fixed MAC with the advertising data being length:31 payload: 0-30 results in a btmon output of:
< HCI Command:... (0x08|0x0036) plen 25 #631 [hci0] 5676.358401
Handle: 0x01
Properties: 0x0013
Connectable
Scannable
Use legacy advertising PDUs: ADV_IND
Min advertising interval: 1280.000 msec (0x0800)
Max advertising interval: 1280.000 msec (0x0800)
Channel map: 37, 38, 39 (0x07)
Own address type: Public (0x00)
Peer address type: Public (0x00)
Peer address: 00:00:00:00:00:00 (OUI 00-00-00)
Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00)
TX power: 127 dbm (0x7f)
Primary PHY: LE 1M (0x01)
Secondary max skip: 0x00
Secondary PHY: LE 1M (0x01)
SID: 0x00
Scan request notifications: Disabled (0x00)
> HCI Event: Command Co.. (0x0e) plen 5 #632 [hci0] 5676.359321
LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1
Status: Success (0x00)
TX power (selected): 7 dbm (0x07)
< HCI Command: L.. (0x08|0x0039) plen 6 #633 [hci0] 5676.359410
Extended advertising: Enabled (0x01)
Number of sets: 1 (0x01)
Entry 0
Handle: 0x01
Duration: 2000 ms (0xc8)
Max ext adv events: 0
> HCI Event: Command Co.. (0x0e) plen 4 #634 [hci0] 5676.361330
LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2
Status: Success (0x00)
# MGMT Event: Com.. (0x0001) plen 4 {0x0003} [hci0] 5676.361372
Add Advertising (0x003e) plen 1
Status: Success (0x00)
Instance: 1
> HCI Event: LE Meta Ev.. (0x3e) plen 6 #635 [hci0] 5676.362333
LE Advertising Set Terminated (0x12)
Status: Advertising Timeout (0x3c)
Handle: 1
Connection handle: 65535
Number of completed extended advertising events: 0
Is there a good way to recreate the functionality that was available using the hci socket, or a way to disable extended advertising so that the hci socket works again?
This image from Jos Ryke might help explain what is going on. Of those 31 bytes, 3 were always used for setting the advertising flags.
Looking at the source code for btmgmt those flags are now set with the -g, and -l command line switches. Use general discoverable mode to advertise indefinitely.
static void add_adv_usage(void)
{
bt_shell_usage();
print("Options:\n"
"\t -u, --uuid <uuid> Service UUID\n"
"\t -d, --adv-data <data> Advertising Data bytes\n"
"\t -s, --scan-rsp <data> Scan Response Data bytes\n"
"\t -t, --timeout <timeout> Timeout in seconds\n"
"\t -D, --duration <duration> Duration in seconds\n"
"\t -P, --phy <phy> Phy type, Specify 1M/2M/CODED\n"
"\t -c, --connectable \"connectable\" flag\n"
"\t -g, --general-discov \"general-discoverable\" flag\n"
"\t -l, --limited-discov \"limited-discoverable\" flag\n"
"\t -n, --scan-rsp-local-name \"local-name\" flag\n"
"\t -a, --scan-rsp-appearance \"appearance\" flag\n"
"\t -m, --managed-flags \"managed-flags\" flag\n"
"\t -p, --tx-power \"tx-power\" flag\n"
"e.g.:\n"
"\tadd-adv -u 180d -u 180f -d 080954657374204C45 1");
}
The other 28 bytes must start with a byte declaring the length and a byte declaring what data type the rest of the bytes in the declared length are describing.
It is those 28 bytes that is being set with the -d option of btmgmt.
If 28 bytes are not enough, then common workarounds people use is to split the data over multiple adverts or use scan response packet.
There is more detail on the Advertising Data Format in the Core Specification where it defines an Advertising Packet as:
A packet containing an advertising PDU. See [Vol 6]
Part B, Section 2.3.1
More data is section:
BLUETOOTH CORE SPECIFICATION Version 5.2 | Vol 3, Part C | 11 ADVERTISING AND SCAN RESPONSE DATA FORMAT
It has an example for ADV_NONCONN_IND packet type:
PDU Type: 2
ChSel: RFU
TxAdd: 1 (random)
RxAdd: RFU
AdvA: 0xC1A2A3A4A5A6 (a static device address)
AdvData: (3 octets) 0x01 0x02 0x03
Which starts with the flags data type.
I am trying to connect a Wahoo Scale 1.3 to read the live weight of a person via bluetooth notifications.
The live weight can be read via the following characteristic:
handle: 0x0025, char properties: 0x10, char value handle: 0x0026, uuid: 00002b01-0000-1000-8000-00805f9b34fb.
This is working with LightBlue app on my iPhone.
When I try to receive notifications via gatttool I get the following error:
Command line gatttool: (tried also lots of different notations from different stack overflow topics)
[XX:XX:XX:XX:XX:XX][LE]> char-write-req 0x0026 0100
Error: Characteristic Write Request failed: Attribute can't be written
btmon bluetooth log
< ACL Data TX: Handle 0 flags 0x00 dlen 9 [hci0] 4.291021
ATT: Write Request (0x12) len 4
Handle: 0x0026
Data: 0100
> HCI Event: Number of Completed Packets (0x13) plen 5 [hci0] 4.327199
Num handles: 1
Handle: 0
Count: 1
> ACL Data RX: Handle 0 flags 0x02 dlen 9 [hci0] 4.383580
ATT: Error Response (0x01) len 4
Write Request (0x12)
Handle: 0x0026
Error: Write Not Permitted (0x03)
One thing I noticed is that under UUID 1901 (weight service) there are 3 properties: 1: write/indicate, 2: notify, 3: notify.
Bluetooth characteristics on LightBlue App
I am able to write with gatttool to the first property, but not to the 2 and 3 property. But how does LightBlue starts listening for notifications?
I tried this one two different systems:
Beaglebone Black with QN9021 BLE controller (Bluez 5.38, OpenWrt Linux 4.4)
Beaglebone Black WiFi/Bluetooth (Bluez 5.23, Debian Linux 4.4)
Do I get this error because of incompatiblities of the Bluez stack and the Wahoo Scale? How do I fix this?
Thank you!
0x0026 is the handle for the value, not for the descriptor. I would guess the descriptor's handle is 0x0027.
Hi I am going through hci_send_req implementation in hci.c file. in this function after sending hci command to controller . Controller send event packet. After reading event packet in buffer by read(dd, buf, sizeof(buf)) (dd is hci socket descriptor) , now we need event packet header and to get event packet header, buf is sifted by 1 byte. why??
hdr = (void *) (buf + 1); (line number 1049 of hci.c)
Please let me know about this. Thanks.
HCI Event Packets: the Host Controller notifies the HCI Driver of events:
Packet indicator (for UART interfaces) of 4.
Event code (8 bits): identifies the event.
Parameter length (8-bit): total length of all parameters in bytes.
Event parameters: the number of parameters and their length is event specific.
So first octet is for Packet indicator that is 0x04 for event packet.
for command packet - 0x01 (for UART interface)
for ACL data packet - 0x02 (for UART interface)
for SCO data packet - 0x03 (for UART interface)
I'm trying to encode AAC-LC data packed in 3gpp to RTP. I've gone through rfc 3640 but I still don't know exactly where to start from. What will I find in the AAC data exactly ? If I'm not wrong , the first 40 bytes will be the MP4 header, but what comes afterwards and where can I find It's definition ? In order to build the RTP payload, I have to include the AU headers sections, but I don't know If they are already included in the AAC data and I can't find it anywhere.
Once I have taken out the mp4 header I have the following data:
00 00 14 03 E9 1C 00 00 14 03 E9 1C
Is this the AU header ? How do I interpret this data?
An another question, what is the relation between AAC-LC and AAC-lbr...I mean, I know the first one stands for low complexity and the second one for low bit rate, but is it the same ? one includes the other ?
Thanks in advance, I'm really new to AAC and I'm quite lost !
I'm trying to do the opposite, ie decode a RTP AAC stream, so some of the references I've found so far might be useful to you:
http://www.rfc-editor.org/rfc/rfc3016.txt
this describes the rtp structure. What I've found in reading my stream, is that there there is also a framing header around the RTP packets, 2bytes for the length:
https://www.rfc-editor.org/rfc/rfc4571
On top of that I have found an extra framing of 2bytes 0x24 0x00 - still no idea what that is all about, but thought I'd let you know you may need to recreate that as well.
Sadly it seems like a lot of the interesting specs are 'pay to view'. Although I did find some useful info from this blog:
http://thompsonng.blogspot.com/2010/03/rfc-3640-for-aac.html
Regarding your other question, I have AAC-hbr which is also AAC-LC apparently, although once again I also haven't found publicly available specs for this.
Your AU header looks a bit similar to what I've got:
0x00 0x00 0x01 0xB6 0x55 0x60 0x63 0xFF 0xFF 0x7A 0x7D 0xD5 0xF7 0xB7 0xA7 0xDF
Although I was expecting the first 16bits to be a length for the headers, so like yourself, I'm not quite sure what I'm looking at...
Anyway I hope some of that was helpful.