So, there’s a lot of information out there about how to get Bluetooth working on your Intel Edison. For example, Intel has published this incredibly 73 page document on using the Edison bluetooth. 73 pages?!
There’s also some info on the forums, but I couldn’t get any of the examples to work without significant modification. So, I’ve written my own examples here. This page contains information about Edison to Edison (or Edison to other Linux box) communication. There will be an accompanying Edison to smart phone tutorial on the way as well.
The First Connection Handshake
Before we can connect from the the Edisons directly from the command line, we need to pair these devices so that they make the handshake for the first time. Designate one Edison the “master” and the other one the “slave”. The master initiates the connection; the slave will get connected to.
So, go ahead and boot-up and log into both Edisons. The first thing is to unblock the bluetooth on both devices.
root@edison:~# rfkill unblock bluetooth
Check to make sure that this worked by listing the devices
root@edison:~# rfkill list 0: phy0: wlan Soft blocked: no Hard blocked: no 1: brcmfmac-wifi: wlan Soft blocked: no Hard blocked: no 2: bcm43xx Bluetooth: bluetooth Soft blocked: no Hard blocked: no 3: hci0: bluetooth Soft blocked: no Hard blocked: no
Next, we’ll use the command line utility bluetoothctl in order to make the preliminary pairing. You’re going to issue all the following commands on both devices until I tell you otherwise.
root@edison:~# bluetoothctl [NEW] Controller XX:XX:XX:XX:XX:XX edison [default]
When bluetoothctl starts up, your Edison Bluetooth Mac address and name will pop up (I’ve listed the XX stuff in place of mine). The bluetoothctl command help will list all the possible program commands for you.
[bluetooth]# help Available commands: list List available controllers show [ctrl] Controller information select Select default controller devices List available devices paired-devices List paired devices power <on/off> Set controller power pairable <on/off> Set controller pairable mode discoverable <on/off> Set controller discoverable mode agent <on/off/capability> Enable/disable agent with given capability default-agent Set agent as the default one scan <on/off> Scan for devices info Device information pair Pair with device trust Trust device untrust Untrust device block Block device unblock Unblock device remove Remove device connect Connect device disconnect Disconnect device version Display version quit Quit program
When the two Edisons pair for the first time, they need user interaction to validate. This means we need to create an active keyboard agent to perform the confirmation.
[bluetooth]# agent KeyboardDisplay Agent registered [bluetooth]# default-agent Default agent request successful
Now, on the slave device, change the settings so that the device is on, pairable, and discoverable. This will allow the master to “see” it and connect to it.
[bluetooth]# power on Changing power on succeeded [bluetooth]# pairable on Changing pairable on succeeded [bluetooth]# discoverable on Changing discoverable on succeeded [CHG] Controller 98:4F:EE:03:41:90 Discoverable: yes
Now, on the master side, start a scan and after a little bit of time you should see your Edison.
[bluetooth]# scan on Discovery started [CHG] Controller XX:XX:XX:XX:XX:XX Discovering: yes [NEW] Device YY:YY:YY:YY:YY:YY 5C-F9-38-D7-8F-37 [NEW] Device AA:AA:AA:AA:AA:AA Kelsey’s MacBook Air [NEW] Device BB:BB:BB:BB:BB:BB BlueZ 5.24
Once you’ve confirmed that you can see your other Edison and that it matches the Mac address you know to be true, turn the scan back off.
[bluetooth]# scan off
Go ahead and initiate the pairing from the master side:
[bluetooth]# pair AA:AA:AA:AA:AA:AA Attempting to pair with AA:AA:AA:AA:AA:AA [CHG] Device AA:AA:AA:AA:AA:AA Connected: yes Request confirmation [agent] Confirm passkey 719442 (yes/no): yes [CHG] Device AA:AA:AA:AA:AA:AA Paired: yes Pairing successful [CHG] Device AA:AA:AA:AA:AA:AA Connected: no
Both Edisons will prompt you to confirm the passkey in the step above. This is why we needed the KeyboardInput as our default-agent. When you confirm on both ends, the pairing will take place. Note that we’re paired now, but we’re not yet connected.
To connect, first change the settings on the slave side to “trust” the master
[bluetooth]# trust XX:XX:XX:XX:XX:XX [CHG] Device XX:XX:XX:XX:XX:XX Trusted: yes Changing XX:XX:XX:XX:XX:XX trust succeeded
Then go ahead and pair from the master side
[bluetooth]# connect 98:4F:EE:03:41:90 Attempting to connect to 98:4F:EE:03:41:90 [CHG] Device 98:4F:EE:03:41:90 Connected: yes Connection successful
Stable connection from the command line
This is all fine and good, but I don’t want to have to do this every single time. This interactivity is kind of annoying.
So, to establish connections from the command line we can use the rfcomm tool. On both sides, we need to issue the following statements:
root@edison:~# rfkill unblock bluetooth root@edison:~# hciconfig hci0 piscan root@edison:~# hciconfig hci0 sspmode 1
The piscan command makes the Edisons discoverable, and the sspmode puts Edison into simple secure pairing mode. Now, on the slave side, we need to open a port and listen on this port for an incoming connection
root@edison:~# sdptool add --channel=22 SP root@edison:~# rfcomm listen /dev/rfcomm0 22 &
The & sign at the end of the first command runs the command in the background. This isn’t strictly necessary, though running it in the foreground will entirely take over your terminal so long as you’re connected and you won’t be able to do anything else. Running it in the background will still give the feedback in the console (hit enter to remove it from your current command prompt or get your prompt back). It’ll look something like this:
Waiting for connection on channel 22
Score! So now all we need to do is connect from the other side. On the master, issue the following:
root@edison:~# rfcomm connect /dev/rfcomm0 AA:AA:AA:AA:AA:AA 22 &
Again, I’m just using the & symbol to keep from tying up my entire console. You should now receive confirmation on both sides that you are connected!
Reading Bluetooth Data
My favorite tool for reading bluetooth data is the Python PySerial Library. It’s not in any of the opkg repos, so you’ve got to use pip to install it. Pip is in the opkg repos, but it’s not been installing correctly for me from there, so I use the command line:
root@edison:~# wget https://bootstrap.pypa.io/get-pip.py --no-check-certificate root@edison:~# python get-pip.py root@edison:~# pip install pyserial
Then, fire up python on both Edisons to send some bluetooth messages back and forth.
Import the pyserial library and open the rfcomm0 port, which is the bluetooth port we chose on both Edisons. I usually set a timeout or else the thing will hang forever if the connection goes awry.
>>> import serial >>> ser = serial.Serial("/dev/rfcomm0", timeout=0.5) >>> ser.write("hello") >>> ser.write([1,2,3,4,5]) >>> ser.read() >>> ser.read(5)
Anything you write on one edison will be readable on the other. The write function takes strings or arrays and the read function reads one byte at a time unless an integer is specified as an argument.
And that’s it. Congratulations! Bluetooth is working
WARNING: Edison uses the BlueZ stack to control the bluetooth. Sometimes Bluez can be a bit wild when you disconnect, basically freezing your Edison to everything but a power cycle. Don’t worry, your Edison is fine. Just power it on back up.
NOTE: You can actually control the bluetoothctl program from the command line by using echo statements, but I’ve had very little reliable success with this method:
root@edison:~# echo -e ‘power on\nconnect 98:4F:EE:03:41:90\nquit’ | bluetoothctl