Wrong payload when using BlueZ stack as peripheral
Two issues:
First, in order to get BlueZ to advertise, the byte sequence you supply must include a valid BLE advertisement header, which is a minimum of 8 bytes. So to advertise "helloworld" you actually need to send:
sudo hcitool -i hci0 cmd 0x08 0x0008 10 02 01 1a 0c ff 18 01 48 45 4c 4c 4f 57 4f 52 4c 44
The first 8 bytes are the header and the next 10 bytes are the string "helloworld" encoded as 8-bit ASCII.
The first 8 bytes can be broken down like this:
10 # Total length of the advertising packet
02 # Number of bytes that follow in first AD structure
01 # Flags AD type
1A # Flags value 0x1A = 000011010
bit 0 (OFF) LE Limited Discoverable Mode
bit 1 (ON) LE General Discoverable Mode
bit 2 (OFF) BR/EDR Not Supported
bit 3 (ON) Simultaneous LE and BR/EDR to Same Device Capable (controller)
bit 4 (ON) Simultaneous LE and BR/EDR to Same Device Capable (Host)
0C # Number of bytes that follow in second (and last) AD structure
FF # Manufacturer specific data AD type
18 01 # Company identifier code (0x0118 == Radius Networks)
Note that this header contains two different length fields that you must adjust if you change the length of the "helloworld" payload. Also, for experimentation purposes, you are welcome to use any two bytes for the company identifier that you want.
Second, you can't see the raw bytes of a detected advertisement with the hcitool lescan
command. To see the raw bytes, you have to use this command in combination with the hcidump
command. See here for details: https://stackoverflow.com/a/21790504/1461050
Use BlueZ Stack As A Peripheral (Advertiser)
With your Bluetooth dongle plugged in, running the following command will tell you the device name and give its state:
$ hciconfig
The output should look something like this:
hci0: Type: BR/EDR Bus: USB
BD Address: 00:01:02:aa:bb:cc ACL MTU: 1021:8 SCO MTU: 64:1
DOWN
RX bytes:1000 acl:0 sco:0 events:47 errors:0
TX bytes:1072 acl:0 sco:0 commands:47 errors:0
This indicates the device is called hci0 is in a down state. Issue the following command to bring it up:
$ sudo hciconfig hci0 up
Now it should look like:
$ hciconfig
hci0: Type: BR/EDR Bus: USB
BD Address: 00:01:02:aa:bb:cc ACL MTU: 1021:8 SCO MTU: 64:1
UP RUNNING
RX bytes:1000 acl:0 sco:0 events:47 errors:0
TX bytes:1072 acl:0 sco:0 commands:47 errors:0
Next, execute the following example command to configure the advertising data to be sent.
$ sudo hcitool -i hci0 cmd 0x08 0x0008 1e 02 01 1a 1a ff 4c 00 02 15 e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 00 00 00 00 c5 00 00 00 00 00 00 00 00 00 00 00 00 00
You can change the hex bytes (starting with 1e) to send different byte sequences for your advertisement. One that literally sends the ASCII codes for "HELLO WORLD" would use: 48 45 4c 4c 4f 57 4f 52 4c 44
(EDIT: But you will also have to prefix this message with a valid header, see here.)
Now, use the following command to activate advertising on the dongle, this will start sending "Helo World" packets.
$ sudo hciconfig hci0 leadv 0
EDIT: the above command makes the advertised service connectable. If you don't want to allow connections, change it to $ sudo hciconfig hci0 leadv 3
You can also disable advertising using the following command:
$ sudo hciconfig hci0 noleadv
iBeacon emulation ubuntu error
Oh Gosh! I have found someone with exactly the same problem as me.
Look Here.
Response that helped from @Richard Wifall
I saw the same issue as memoryhole where I had to remove the extra zeros. I also had to enable advertising before I configured the advertising data for it to work properly with my dongle.
Here is the exact sequence/commands that worked for me:
sudo hciconfig hci0 up
sudo hciconfig hci0 leadv 3
sudo hcitool -i hci0 cmd 0x08 0x0008 1e 02 01 1a 1a ff 4c 00 02 15 e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 00 00 00 00 c5 00
This is what my version of the Radius script ended up looking like:
#!/bin/sh
../ibeacon.conf
echo "Launching virtual iBeacon..."
sudo hciconfig $BLUETOOTH_DEVICE up
sudo hciconfig $BLUETOOTH_DEVICE leadv 3
sudo hcitool -i $BLUETOOTH_DEVICE cmd 0x08 0x0008 1e 02 01 1a 1a ff 4c 00 02 15 $UUID $MAJOR $MINOR $POWER 00
echo "Complete"
This was on a Rasberry Pi with a ORICO BTA-402-BK branded BLE dongle (CSR8510 A10)
(I would have left this as a comment, but didn't have enough rep)
Android BLE GATT write data is not being received by BLE Peripheral despite GATT_SUCCESS
Well the success status is only reported after the peripheral has actually sent back a Write Response.
So either you write to the wrong characteristic, the wrong device, or you are not correctly detecting at the peripheral when an incoming write has been received.
One way to debug this is to use the hci snoop log in Android, or using a BLE sniffer.
Bluetooth LE - Single Characteristic with Large Payload or Multiple Characteristics with Small Payload?
Since you have four separate strings I would recommend that you make four characteristics as well. The data packets in BLE is usually about 20 bytes (23 bytes minus some ATT overhead) so your data fits in a single packet. And when you do a read long (on a single long attribute) your going to get a single read response packet back before you ask for the next chunk of data. You would probably end up with the same amount of packets going back and forth to read the data. Obviously, discovering four vs only one characteristic takes a few extra packets, but nothing to worry about.
Simply put - is it better in this instance to small chunks of data
multiple times or send a larger chunk of data once?
Only if your data strings are considerably smaller than 20 bytes.
You talk about having the peripheral write it's data to the central (presumably right after connection). Normally this is done the other way, where the central first discovers the peripheral database (after connection of course) and then read the data it's interested in.
You can also consider using indications, rather than reads. This is typical for a peripheral sensor which is logging data. The central connects, discovers the database and then enable notification for a given attribute. The peripheral will then send each data sample (maybe packed in some way) with indications until all the locally logged data has been transferred. With indication, every transfer is acknowledged so the peripheral can wait for the confirmation before removing the data locally making sure you don't loose logging samples.
Which approach would be better for allowing as many Peripherals to
connect to a Central as possible? Does it matter?
The way to organize and transfer data does not matter in how many peripherals your central can connect to. But if your peripherals write into the central database you need to make sure they don't write to the same handle(s). Better to do a read or indication/confirmation initiated by the central.
Unable to write data into hardware peripheral
This is not a Core Bluetooth based problem you have here.
For debugging, you could use
NSLog(@"%@", payload);
For your string to NSData conversion, your approach seems very complicated. I would suggest something simple like
NSData* payload = [iData[uuid] dataUsingEncoding:NSUTF8StringEncoding];
if (payload.length > 20)
{
// handle error. most LE peripherals don't support longer values.
}
Another error could be that you mix ASCII 0 '0'
with a binary zero '\0'
when writing your value.
What replaced libbluetooth1-dev for C programming using BlueZ?
Managed to sort it out in my case after finding another stackoverflow question - I needed to run apt-get install libbluetooth-dev
(not libbluetooth1-dev
as the tutorial said) and then compile as instructed. The apt-get installed libbluetooth-dev
and libbluetooth3
which is the current version of libbluetooth.
Related Topics
Writing a Bash For-Loop with a Variable Top-End
How to Print Message to Stderr in Go
Any Way to Specify the Location of Profile Data
Running Scheme from the Command Line
Configuring Selinux Permissions on (Svs-V) Ipc Semaphores
Shell Script Printing Contents of Variable Containing Output of a Command Removes Newline Characters
Linux, Print All Lines in a File, Not Starting With
How to Change Version String of the Kernel
"Tput: No Value for $Term and No -T Specified " Error Logged by Cron Process
Why Should I Recompile an Entire Program Just for a Library Update
Use Wc on All Subdirectories to Count the Sum of Lines
Shell Script to Copy and Prepend Folder Name to Files from Multiple Subdirectories