Zengge BLE bulb protocol - bluetooth

I've just got a smart led bulb from Zengge and want to control it from my Linux machine with Bluetooth 4.0. I've installed latest bluez 5.x package, so I have a gatttool available. I am able to connect to my bulb and list it's services. But I have no ideas how to control it. Maybe someone have already done that (I was unable to Google for ready solution)? Or have some developments in this area? Or maybe someone have the specs?

For those who are interested, here are my findings about the bulb protocol.

1) Check if your bluetooth device is up: hcitool dev
2) If device is down: hciconfig hci0 up
3) Scan for bluetooth le devices: hcitool lescan
4) Turn on device: gatttool -b YOUR:LE:DEVICE:MAC:ADDRESS --char-write-req -a 0x001a -n 04
5) Turn off device: gatttool -b YOUR:LE:DEVICE:MAC:ADDRESS --char-write-req -a 0x001a -n 63
6) Dim warm light: gatttool -b YOUR:LE:DEVICE:MAC:ADDRESS --char-write-req -a 0x0013 -n 56000000ff0faa where ff is the hex code for the intensity.
7) Colored light: gatttool -b YOUR:LE:DEVICE:MAC:ADDRESS --char-write-req -a 0x0013 -n 56e92fff99f9aa where e9 is hex red intensity, 2f is hex green intensity, 2f is hex blue intensity
(I'v got the codes by turning on the Bluetooth HCI-snoop-log in Android wile using the Magic Light app and analysing it with Wireshark)

Related

Raspberry Pi turn on AV Receiver CEC

I have an AV Receiver that I want to turn on from standby using cec-client on raspberry pi. The physicall setup is as follows:
RPI --HDMI--> AV Receiver
TV <--ARC_HDMI--> AV Receiver
Scanning my HDMI devices with echo "scan" | cec-client -s -d 1 I get following output:
opening a connection to the CEC adapter...
requesting CEC bus information ...
CEC bus information
===================
device #0: TV
address: 0.0.0.0
active source: no
vendor: Samsung
osd string: TV
CEC version: unknown
power status: standby
language: ger
device #1: Recorder 1
address: 1.0.0.0
active source: no
vendor: Pulse Eight
osd string: CECTester
CEC version: 1.4
power status: on
language: eng
device #5: Audio
address: 3.0.0.0
active source: no
vendor: Harman/Kardon
osd string: H/K AVR
CEC version: 1.4
power status: standby
language: ???
As you can see, my AV Receiver has the device number #5 and physical address 3.0.0.0
I tried following already, using cec-o-matic as reference:
echo "on 3.0.0.0" | cec-client -s -d 0
echo "on 5" | cec-client -s -d 0
echo "tx 15:04" | cec-client -s -d 0
But neither command turns on the AV Receiver. The same commands addressing the TV work without an issue.
After a lot of trial and error, I found out that rebooting my Raspberry Pi actually turns on the receiver! Nice, at least something. Investigating further I found out that in /boot/config.txt one can add/set the hdmi_ignore_cec_init=1 parameter to indicate whether the Raspberry Pi should send an active source message while rebooting. Depending on whether this is set to 0 or 1 my AV receiver turns on when I boot/reboot my RPI.
Now, I obviously don't want to reboot my RPI whenever I want to turn on my AV Receiver. So my question is what is the specific CEC-message the Raspberry sends on boot, so I can replicate it with the cec-client with something along the lines of echo "tx <specific-cec-message>" | cec-client -s -d 1
I already tried monitoring cec traffic on boot with cec-client -f cec.log, but monitoring starts too late and misses the send signal from RPI on boot.
The easiest way to find this out would probably to have a second Raspberry Pi monitoring the bus while the other one boots, but I only have 1 RPI, so I can not test it myself.
Does anyone have an idea, or at least a source for me? Big Thanks for taking the time!
In case it matters here also the specific device models.
TV: Samsung ue55f8090
AVR: Harman Kardon AVR 156
RPI: Raspberry Pi 4 Model B Rev 1.4
RPI_OS: Raspbian GNU/Linux 10 (buster) armv
RPI_KERNEL: Kernel: 5.10.103-v7l+
After more digging, I finally found a solution to my specific problem.
For my setup, as described in my question, one can turn on the Harman Kardon AVR 156 by broadcasting an active source message with the physical address of the TV.
echo "tx 1f:82:00:00" | cec-client -s -d 1
A breakdown of the CEC Frame:
1 = Recording 1 (Raspberry Pi)
F = Broadcast
82 = Active Source
00 00 = ID (TV)
I hope this helps anyone stumbling on this in the future!

How do we get RSSI values from Bluetooth beacons (estimote to be specific) in Linux?

I need to get distances from multiple bluetooth beacons for triangulation so that I can do indoor positioning.
I have tried to give as many relevant details as possible. This project is for an RPi, but I am currently trying to test it through my laptop first. I have tried most of what I can find on the internet about this:
The best way I could find to get the rssi values was hcitool rssi <address of beacon>
From here Bluetooth LE Signal Strength Linux
To test this, I tried to get it for my mobile first. It showed "Not Connected". I thought I need to connect first, so I tried many ways to connect my mobile:
a) hcittol cc <address of mobile>
b) gatttool -b <address of mobile> -t random --interactive
c) rfcomm connect 0 <address of mobile> 10
In each case, when I clicked pair in my mobile, connection terminated.
Then, I paired my mobile the usual way from bluetooth menu, and then tried hcitool rssi <Address of mobile> which then finally returned a value -8.
Now that I had it for my mobile, I now moved to beacons.
Then, I tried the same for my beacons. This time I had to
first do hcitool lescan to get addresses of available beacons
then connect to one of the beacons using the command hcitool lecc <address of beacon> which returned the error Could not create connection: Connection timed out
So next, I again tried connecting with the other two ways:
rfcomm connect 0 <address of beacon> 10 which returned the error Can't connect RFCOMM socket: Host is down when I can be sure hci0 was up.
Then I tried with sudo gatttool -b F1:15:A7:E3:17:63 --interactive after which interactive mode opened up and I gave the command connect. This gave different errors after Attempting to connect to <address of beacon>,
mainly connect error : Connection timed out
and Error: connect error: Connection refused (111)
Then I read I need to use -t random from Bluetooth LE on Raspbian , https://ubuntuforums.org/showthread.php?t=2204808 and one another source which I can't find right now.
So I entered sudo gatttool -b F1:15:A7:E3:17:63 -t random --interactive in which when I gave the connect command, I got error Error: connect error: Device or resource busy (16) and also sometimes Error: connect error: Input/Output Error
then I read that I perhaps need to restart my hci0 by hciconfig hci0 down and then hciconfig hci0 up which did the trick, the beacon now got connected.
But then, it quickly got disconnected after saying `GLib-WARNING **: Invalid file descriptor.
`
I read here https://raspberrypi.stackexchange.com/questions/53982/how-to-fix-gatttools-glib-warning-invalid-file-descriptor that this is because of poor connections. I tried keeping the beacons closer, but it did the same.
So I tried to anyway at least get one rssi value during the short duration it is connected. But, even when it was thus connected, I did hcitool rssi <address of beacon> the error came like this:
hcitool rssi F1:15:A7:E3:17:63
Get connection info failed: No such file or directory
To which I haven't yet found a proper solution.
I tried another way of reading the rssi value, which gave the following :
hcidump -R
HCI sniffer - Bluetooth packet analyzer ver 5.37
device: hci0 snap_len: 1500 filter: 0xffffffffffffffff
> 04 0E 04 01 0B 20 00
> 04 0E 04 01 0C 20 00
> 04 0E 04 01 0C 20 00
> 04 0F 04 00 01 0D 20
> 04 0F 04 00 01 16 20
> 04 0F 04 00 01 13 20
This was before it got disconnected.
I read here Obtain RSSI with hcidump which said to read the 14th byte. since all these seemed to be hex numbers, this would mean that each number is 1 byte. But this way, I only have 7 numbers per line, how can I read the 14th byte?
Getting distance from beacons has been troubling me a lot, and has used up a a lot of my time. Please help me out on this issue. If you can help me find a resource to help me do so, I'd appreciate the help.
You don't need to connect to a device to get the signal strength RSSI values, just use the following code and pipe that to a script that extracts values from the devices you are after:
btmon &
hcitool lescan --duplicates

Gatttool non-interactive mode --char-write

Still asking about BLE devices and gatttool.
I'm able to send a char-write-cmd in interactive mode, but I'm not able to do the same in non-interactive.
This is what I send in interactive mode :
gatttool -I
[]> connect BTADDR
[BTADDR]> char-write-cmd 0x0040 01
[BTADDR]> exit
In this way I start the Alert service, which in my case makes the buzzer sounds.
In theory, the non-interactive mode should be:
gatttool -b BTADDR --char-write -a 0x0040 -n 01
But this do not send the request command event to the board, I'm checking it using a dev board.
The manual (non-interactive) way to read or write to your BLE peripheral:
To write and receive reply once: (depending on how you configure your BLE device)
sudo gatttool -i hci0 -b xx:xx:xx:xx:xx:xx --char-write-req -a 0x0025 -n ff
To write and receive reply indefinitely: (Until you disconnect from BLE device or stop your Bluetooth client)
sudo gatttool -i hci0 -b xx:xx:xx:xx:xx:xx --char-write-req -a 0x0025 -n ff --listen
Notice I only added the --listen option at the end. This mechanism only works if you configure your BLE node (sensor or actuator) to read and reply.
sources::
How to use gatttool non-interactive mode
Bluetooth Low Energy: listening for notifications/indications in linux
All that said, I still do not think it is best to control or get values from a BLE device. My direction is to move forward and use an API (maybe in python) to do the job for you.
https://github.com/peplin/pygatt
This API has been proven to work with Raspberry Pi Jessie destro.

Bluetooth LE Signal Strength Linux

Hello is there any way to get the signal strength of near by bluetooth le devises in linux? Or any good libraries for nodejs, php or mono (I do know some c++ or python but would prefer to say away from them) if a tool does not exisst but would be fairly easy to write.
On Linux, the way to do this is with the hcitool command. However, you have to be connected to get the rssi of a device. If you want to achieve this from the command line, try:
#hcitool rssi AA:BB:CC:DD:EE:FF
If you want to see the actual C code to achieve this, take a look at the bluez tools/hcitool.c file, under the cmd_rssi function.
static void cmd_rssi(int dev_id, int argc, char **argv)
{
...
}
For Bluetooth Low Energy, I only know one way to do this, and that is using the #btmon command. Run btmon in the background then scan for Bluetooth Low Energy devices:
#./btmon &
# hcitool lescan
The results displayed on the monitor should be similar to this:
> HCI Event: LE Meta Event (0x3e) plen 12
LE Advertising Report (0x02)
Num reports: 1
Event type: Scan response - SCAN_RSP (0x04)
Address type: Public (0x00)
Address: AA:BB:CC:DD:EE:FF (<Vendor Name>)
Data length: 0
***RSSI: -34 dBm (0xde)***
AA:BB:CC:DD:EE:FF <Device Name>
Note that when using btmon you do not have to connect to get the rssi of a BLE device.
No need to connect when using btmgmt
$ sudo btmgmt find
Discovery started
hci0 type 7 discovering on
hci0 dev_found: 50:8C:FD:99:0A:EC type LE Random rssi -80 flags 0x0000
AD flags 0x06
eir_len 23
…
The relative signal strength indicator is rssi -80, but the list is much longer containing more information about this and other devices.
To spy on your Bluetooth neighbourhood showing only unique MAC addresses with their strongest RSSI, run the following command:
$ sudo btmgmt find |grep rssi |sort -n |uniq -w 33
hci0 dev_found: 40:43:42:B3:71:11 type LE Random rssi -53 flags 0x0000
hci0 dev_found: 44:DA:5F:EA:C6:CF type LE Random rssi -78 flags 0x0000
hci0 dev_found: 7F:7D:08:6B:E0:37 type LE Random rssi -74 flags 0x0000
hci0 dev_found: A4:58:0F:21:A1:8C type BR/EDR rssi -79 flags 0x0000
You can use a combination of:
sudo hcitool lescan --duplicates & ;
sudo hcidump --raw
that will provide you the raw dump of all the bluetooth packets which contain all relevant information you must be interested in such as : UUID, Major, Minor, RSSI, TxPower. You will have to run some kind of script to parse and filter LE packets and make them into readable form.
One of the scripts written with Bash and S editor was provided by jjnebaker here with the problem and solution discussed here
The Other option is to use PyBluez using the example code here
But you might find the solution provided by Switchdoc labs useful according to your needs as well. here
This works for c language, but has an error when casting the bytes that have the information about de rssi signal.
https://github.com/glock45/intel-edison-playground/blob/master/scan.c
this line 121:
printf("%s - RSSI %d\n", addr, (**char**)info->data[info->length]);
should be:
printf("%s - RSSI %d\n", addr, (**int8_t**)info->data[info->length]);
I found these by looking inside bluez-version/monitor/*.c, where btmon program is. You can see the data types and structs, hcidump.c is very useful and packets.c, and main.c too, but there are many to learn about the hci sockets.
I also found a program I was able to edit to do what I wanted as well
I through it up on my github account
https://github.com/tholum/bluez/blob/master/blue.py
i found several solutions, but most were too slow for my needs to use as a tracking function.
check out https://github.com/abandonware/noble containing some examples.
my standalone scanner is also based on abandonware's module and can be found here:
https://github.com/efeuentertainment/BLE-continuous-RSSI-scan
node index.js BLEMAC
continuously lists the RSSI with an update frequency of about 2 per second / depending on BLE device.
also fast updates based on bash is:
sudo hcitool lescan --duplicates &
combined with one of the following lines:
continuous updates
sudo hcidump | grep "E6:4E:57:09:74:E4" -A 4
sudo btmon | grep "E6:4E:57:09:74:E4" -A 7
only the next received update
sudo hcidump | grep -m 1 "E6:4E:57:09:74:E4" -A 4 | grep "RSSI"
sudo btmon | grep -m 1 "E6:4E:57:09:74:E4" -A 7 | grep "RSSI"
hope that helps. it's an old thread but my search engine lead me here anyway.
try :
$ bluez-test-discovery
output :
[ 18:7A:93:05:E4:B1 ]
Name = AMIYJ_E4B1
Paired = 0
LegacyPairing = 0
Alias = AMIYJ_E4B1
Broadcaster = 0
UUIDs = dbus.Array([dbus.String(u'0000fff0-0000-1000-8000-00805f9b34fb')], signature=dbus.Signature('s'), variant_level=1)
Address = 18:7A:93:05:E4:B1
RSSI = -65
Class = 0x000000
gives you : RSSI = -65
For connected devices you can use btmgmt conn-info
e.g.
$ sudo btmgmt conn-info -t 2 E4:0C:E6:59:B6:FC
Connection Information for E4:0C:E6:59:B6:FC (LE Random)
RSSI -78 TX power 0 maximum TX power 0
(You have the code for that command at https://github.com/bluez/bluez/blob/150bbff449c787f26b7de3e6006bdb2ea6365b08/tools/btmgmt.c#L3984-L4030 ).
I think you may also be able to use BlueZ's DBus RSSI property of the org.bluez.Device1 interface :
int16 RSSI [readonly, optional]
Received Signal Strength Indicator of the remote
device (inquiry or advertising).
but that didn't work for me:
$ dbus-send --print-reply=literal --system --dest=org.bluez /org/bluez/hci0/dev_E4_0C_E6_59_B6_FC org.freedesktop.DBus.Properties.Get string:"org.bluez.Device1" string:"RSSI"
Error org.freedesktop.DBus.Error.InvalidArgs: No such property 'RSSI'
Maybe because the property is optional. Some other properties did work for me:
$ dbus-send --print-reply=literal --system --dest=org.bluez /org/bluez/hci0/dev_E4_0C_E6_59_B6_FC org.freedesktop.DBus.Properties.Get string:"org.bluez.Device1" string:"Name"
variant eono BTC 01

Bluetooth Low Energy: listening for notifications/indications in linux

I'm trying to communicate with a BLE module through a Linux machine (the module is running a heart rate profile). So far, I've been able to do everything I need except listening for Notifications and indications (e.g. listening for the Heart Rate Measurement Notification). I'm using kernel version 3.5 and bluez-5.3.
Succcessful commands used so far:
hcitool lescan
hcitool lecc
gatttool -b <Mac Address> --primary
gatttool -b <MAC Address> --characteristics
gatttool -b <MAC Address> --char-read
gatttool -b <MAC Address> --char-desc
gatttool -b <MAC Address> --interactive
Failed commands:
gatttool -b <MAC Address> --listen
Any help is greatly appreciated.
Try this...
Run gatttool -b <MAC Address> --interactive like you did before. You'll get a prompt and then you type connect. You should see a CON in the prompt indicating that you've connected to the device. Then type char-read-uuid 2902. You should get a list of all CCC (Client Characteristic Configuration) attributes on the device. You can try setting them all to 0100 to get notifications, 0200 for indications, 0300 for both, or 0000 for everything off. Type help to see all the commands and their arguments.
EDIT:
The use of the --listen argument requires you to couple it with other commands to turn on the notifications and/or indications. So here's an example that works in Bluez 4.101:
gatttool -b <MAC Address> --char-write-req --handle=0x0031 --value=0100 --listen
Obviously you need to change the handle to the handle of the CCC that you want to turn on notifications for. However, I still find it way easier to just use the interactive mode.
Looks like the older version of Bluez (hcitool & gatttool) don't allow you to write to Bluetooth Low Energy devices. I ended up installing a newer version (5.17 as of this writing) in order to enabled notifications, etc.
To get a list of all your handles you can run the following:
char-desc
You can then read from a handle:
char-read-hnd 0x000e
(the above handle is for my nrf51822 battery level)
Where the handle is one from the list you got from char-desc.
Just like Tim said above, you can write to the notification related handle to get indications or notifications. (in my case my device only had notifications)
char-write-req 0x000f 0100
(the above handle is for my nrf51822 battery level notification)
In my case the battery notification shouldn't send anything until the battery level has changed.
I wrote a pretty lengthy blog post on getting setup with Bluez. You can find it here: Get Started with Bluetooth Low Energy Feel free to check it out!
Final answer for reading heart rate on Mio Alpha :
gatttool -b xx:xx:xx:xx:xx:xx -t random --char-write-req -a 0x0025 -n 0100 --listen
Characteristic value was written successfully
Notification handle = 0x0024 value: 10 4b 33 03
Notification handle = 0x0024 value: 10 4b 33 03
Notification handle = 0x0024 value: 10 4b 33 03
Notification handle = 0x0024 value: 10 4a 3e 03
Notification handle = 0x0024 value: 10 4c 28 03 28 03
Notification handle = 0x0024 value: 10 4c 28 03
Notification handle = 0x0024 value: 10 4b 33 03
Notification handle = 0x0024 value: 10 4a 3e 03 3e 03
to retain the CCC value you need to pair the two device. once they are paired you do not need to set the CCC again. on next reconnection it will find the setting , which will be saved in thec FLASH of Key fob. try to configure after pairing via SMP.

Resources