Mobiles, Shakespeare, Politics, Usability, Security.

Cheap BlueTooth Buttons and Linux

Selfie sticks - like most modern inventions - are utter tosh. But they've rapidly brought down the price of Bluetooth buttons. So who am I to complain?

Let's take the venerable AB Shutter 3 - You can find it on Amazon for around £2 including postage - or around $2 on AliExpress. Frankly, that's stupidly cheap.

OK, let's put this to work as something other than a vanity clicker! There are no instructions which come with this, it's delivered in a little plastic bag and that's it. Time to get hacking!

Aim

Once paired to a server, like the Raspberry Pi, pressing the button should run a program to turn on my Lifx bulbs.

Cracking It Open

With the battery panel slipped off and the cell removed, it's fairly easy to open the case. Fingernails are sufficient - no screws or glue!
AB Shutter 3 Circuit-

It's an AIROHA AB1126A.

AB1126A is an optimized single-chip solution which integrates baseband and radio for wireless human input device applications especially for remote smartphone camera control. It complies with Bluetooth system version 3.0.

But what happens when we ZOOM! ENHANCE!?

24C16N-

The 24C16N is a fairly generic EEPROM.

But what's this?!?!
AB1127A-
The chip is listed as an AB1127A. A chip which, seemingly, doesn't exit. Onwards!

Getting Started

When switched into the "on" position, the dongle is ready to pair.

From the Ubuntu command line:

$ hcitool scan
Scanning ...
80:00:00:00:EE:E0 AB Shutter 3

Aha! We've found it. What sort of device is it?


$ hcitool inq
Inquiring ...
80:00:00:00:EE:E0 clock offset: 0x0acd class: 0x002540

It shows up a a keyboard. Let's connect to it and trust it.

$ bluez-simple-agent hci0 80:00:00:00:EE:E0
Release
New device (/org/bluez/794/hci0/dev_80_00_00_00_EE_E0)
$ bluez-test-device trusted 80:00:00:00:EE:E0
$ bluez-test-input connect 80:00:00:00:EE:E0

To check that it is seen and connected properly:

$ xinput
↳ AB Shutter 3 id=13 [slave keyboard (3)]

Nice! Running xinput query-state "AB Shutter 3" allows us to see which keyboard keys are activated when the buttons are pressed.

It turns out that the iOS buttons sends Volume Up (key 123) whereas the Android button sends Enter (key 36).

It works! Sorta...

Pressing the selfie-button instantly sends the command to my computer! Well... until the button goes to sleep. The device is powered by a CR2032 battery which, despite the power efficiencies of Bluetooth, isn't magical.

After a few minutes of idleness, the device goes to sleep. Pressing any button wakes it up and repairs the connection - but then another button press is required to send a key press. The pairing process only takes a couple of seconds, so it's not quite instant.

Make it do something useful

Having an external button which can increase the volume or send an enter command isn't very useful. I want to press the button and have a program run which will (for example) turn on my lights.

Run a program when the Bluetooth connection is made

Because the device goes to sleep after a few minutes of inactivity, we need a way to listen for a connection. So, when a button is pressed for the first time, the device connects and a program is run.

I've half-inched the instructions from this InOut Board tutorial.

First of all, make sure Python has the ability to work with Bluetooth:
sudo apt-get install python-bluez

With that running constantly in the background, you can perform an action whenever the device connects.

Run a program when a button is pressed

Right, this is where it gets tricky! Ubuntu doesn't seem to differentiate between different keyboards attached to a device. This means you can't use loadkeys to swap keys, nor xkb.

You can, however, use xkbcomp to remap the buttons on a specific device (thanks to Stephen Wing for that tip).

This will convert the Volume Up to XF86Launch1 and Enter to XF86Launch2 - those are multimedia keycodes which shouldn't be assigned to anything by default.

The script needs to be re-run every time the Bluetooth connection is re-established. Probably best to run it on reconnect as part of the Python code above.

So, that remaps the inputs for that Bluetooth button. Ok, but how do we get XF86Launch1 to launch a program?

It's pretty easy to set keyboard shortcuts in the GUI- but how do we do it on the command line? Well, you can't. There's no way to tell a shell to run a program when a specific key has been pressed.

So, it's back to Python and listening for the key to be pressed. Which I have no idea how to do!

If you know how to detect multimedia keys, please leave a comment or answer this StackOverflow question.

Or - let me know a better, more obvious way that I'm missing!


BlueTooth buttons are available on AliExpress and Amazon for UK customers.

22 Comments

A picture of Jon Burgess Jon Burgess

The python evdev module can find the device and print the button events:

https://gist.github.com/jburgess777/a6dd67e7fbaaee82c856

$ sudo ./getButton.py
device /dev/input/event17, name "AB Shutter 3", phys "00:1b:10:00:2a:ec"
key event at 1456268812.859839, 115 (KEY_VOLUMEUP), down
key event at 1456268812.860800, 115 (KEY_VOLUMEUP), up
key event at 1456268813.736843, 28 (KEY_ENTER), down
key event at 1456268813.909845, 28 (KEY_ENTER), up

The grab() call should prevent the key presses from being seen by anything else

Reply
A picture of James James

Why not use xbindkeys? In my laptop I glue some scripts to various buttons with this .xbindkeysrc file in my home directory:

"$HOME/bin/do_suspend.sh"
m:0x0 + c:150
XF86Sleep

"$HOME/bin/do_toggle_touchpad.sh"
m:0x0 + c:199
XF86TouchpadToggle

"$HOME/bin/do_autoselect_monitor.sh"
m:0x0 + c:235
XF86Display

"wicd-cli --wireless --disconnect && sudo rfkill block 1"
m:0x0 + c:246
XF86WLAN

Reply
A picture of Alex Gibson Alex Gibson

Following this with interest. Do you have several of these buttons, from the same source, just the one, or several from different makes?
I've been thinking on similar lines, per twitter, and wonder about changing the device firmware to choose a different key. Reason for this is I want several buttons to each have different functions. Another advantage is it could work on PC and Mac easily.
Your way is very neat for Pi control and way easier to repeat under Linux, so I will reproduce it for my boiler automation as a boost button.

Will order 3 from the same vendor and see if I can also get at the firmware via those UART tags. Having control over either side of the mapping would be superb.

Reply
A picture of Terence Eden Terence Eden

I've only bought the one. My concern is that if they all identify as the same model, it might be hard to tell them apart in software. Interested to see how you get around it.

Reply
A picture of Pat Hamel Pat Hamel

Please, PLease DO NOT REMOVE THE HARDWIRED SAFETIES ON THAT BOILER PLEASE.
We had a wonderful brilliant software-oriented college-graduate do the control system update design for boiler controls (Where - don't ask).
He "ripped out all that electrical stuff".
A "failure" stopped his computer and six each six-inch valves on a full-pressure gas line opened up into one hot boiler and five cold ones with a common chimney.
The technician in the building knew he could not run away fast enough to escape the blast, so he stayed and manually killed the gas.
Do not remove or bypass the hardwired safeties on any fueled device - you could do jail time.

Please withhold my email address for obvious reasons.

Reply
A picture of Alex Gibson Alex Gibson

I 100% agree with you, and a great safety warning. Glad that situation did not end as badly as it could have.

To be specific about the scope of my own tinkering, my combi boiler has a dedicated timer control interface, which is accessible to end users. It is of the 'zero volts' type, meaning that you are operating a simple switch, closing a circuit that starts and ends at the main control board, which I DO NOT MESS WITH.

I already had an aftermarket timer switch, more sophisticated than the onboard timer, but still very closed.

I have this on now, but have tested previously replacing it with a standalone Pi, implementing a simple timing schedule.

I am preparing a nicer, web controllable version to run on the pi permanently. I am interested in using the bluetooth buttons to give it a 'just boost now' option which my wife, who is competent but disinterested in IT, a tangible improvement over our current system, and to remove the need for her to access the web page.

I plan 4 vital safety features, even given that I am using a purpose built timer control interface:

1) The interface will be one designed for switching mains from a Pi/Arduino, with proper separation of the high and low voltage sections, even though it doesn't need to be, for a few pounds extra it gave me a much more robust switch. The relay fails open, so the boiler turns off if it dies.

2) The Pi does not get to control the boiler direct. The switch signal has to be passed via an Arduino, whose only role in life is to sit in between and enforce a policy that the boiler cannot be switched on or off more than once per minute, or 10 times in 1 hour. If the Pi asks for more frequent changes, it reschedules if within 10 seconds, or sends back an error. This is because boilers are not designed to be turned on and off like a PWM duty cycle, and could be damaged if they spent all day turning on and off. The Arduino also sends a signal every hour to the Pi to say it is alive and still running its program, because I am anal about debugging in any live system.

3) The Pi only accepts connections from within my home network AND there will be a PIN page before I put it 'live'.

4) The Pi, Arduino and relay are in a sensible electronics enclosure, with good cabling, glands and cable strain relief, for the control wire, 5VDC in and wired ethernet. There is no onboard wifi, and the mains power point is some distance from the Pi.

This is the result of my own risk assessment and mitigation thoughts, and doesn't constitute a recipe for anyone seeking to do the same thing - may be worth considering the above, but research the risks yourself.

Is there anything more I could/should think about, in terms of potential risks and mitigations?

Reply
A picture of Jan Jan

How did you do with 3 of them? I ordered 6 and would like to use all 6 for competitions time measurement.

Reply
A picture of Daniel Daniel

Someone has a complete example how to remap ABShuter ? I want to move UP and DOWN a pdf file. Thanks.

Reply
A picture of Matt Brunton Matt Brunton

Hi Terence, thanks for this page - I found a selfie button in my local PoundWorld store, looks exactly like the one you have pictured (externally, at least), but I can't get the Pi to recognise it. Both the Pi and selfie button are working with other devices. The Pi dongle reports as " Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)" in lsusb and this seems to be the "chipset of choice" on various forums. I'm persevering & will update you as I get results (or not).

Reply
A picture of Adriann Adriann

is there a way to adapt this for bluetooth 4.0 buttons? I picked up some cheap ones and I can connect to them, I just can't figure out how to capture the button press when I'm connected to the button

Reply
A picture of Alex Gibson Alex Gibson

The updates have reminded me I never received those buttons I bought... gaah. Time to chase the Amazon seller...

Reply
A picture of Frederic LE GARREC Frederic LE GARREC

Hello, do you know a way to avoid the button going to sleep? I would like to put them in my children bags so that the RPi detects them when they enter the house. But as the button is sleeping, cannot work...
Thanks.

Reply

What do you reckon?

%d bloggers like this: