After some further research, plus plenty of trial and error, I eventually got a bluetooth network up and running, connecting together one Raspberry Pi 3 with four Raspberry Pi Zero Ws, and decided to document the steps I took for my own reference, as well as for anyone else who would like to achieve the same.
To setup the Bluetooth network we need to allocate one Raspberry Pi to act as the central hub, responsible for allocating IP addresses, IP forwarding (if needed), along with one or more client Raspberry Pis to connect to it.
Setting up the Hub
- Download the latest Raspbian image (Here I am using 2017-04-10-raspbian-jessie-lite.zip) and write to an SD Card.
- Boot the Raspberry Pi, login and run the 'raspi-config' application.
pi@raspberrypi:~$ sudo raspi-config
- Select option 2 to change the hostname, setting it to 'hub'.
- Select 'Finish', followed by 'Yes' to reboot.
- Wait for the Raspberry Pi to reboot and log in again.
- Setup a network connection. Depending on your setup this can be either by plugging in an Ethernet cable or by setting up a Wireless connection.
- Install the packages required for setting up the bluetooth network.
pi@hub:
~$ sudo apt-get install bluez-test-scripts bridge-utils dnsmasq python-dbus
- Next we need to add the network interface we'll be using for Bluetooth. Edit the /etc/network/interfaces file and add the following to it.
auto pan0
iface pan0 inet static
address 172.168.10.1
netmask 255.255.255.0
bridge-ports none
bridge-fd 0
- And then we need to configure dnsmasq to listen on the pan0 interface and assign IP addresses in the correct range. Edit the /etc/dnsmasq.conf file and add the following
domain-needed
bogus-priv
no-resolv
no-poll
server=8.8.8.8
local=/localnet/
interface=pan0
no-hosts
expand-hosts
domain=local
# Enable DHCP for the 172.168.200.X range
dhcp-range=172.168.10.10,172.168.10.50,12h
- To setup the bluetooth network we'll be using one of the BlueZ test scripts (installed as part of the bluez-test-scripts package earlier), however the test script exits after 16 minutes, so we need to copy and edit the script.
pi@hub:~$ sudo cp /usr/share/doc/bluez-test-scripts/examples/bluezutils.py /usr/local/sbin/
pi@hub:~$ sudo cp /usr/share/doc/bluez-test-scripts/examples/test-nap /usr/local/sbin/
pi@hub:~$ sudo chmod +x /usr/local/sbin/test-nap
- To keep the script running edit /usr/local/sbin/test-nap and change the lines :-
try:
time.sleep(1000)
- to
try:
while True:
time.sleep(1000)
- We want the script to run at startup and one of the easiest ways is using the crontab file. Edit your crontab by running crontab -e and add the following line to the end.
@reboot sudo nohup /usr/local/sbin/test-nap pan0 &
- Reboot once more (sudo reboot), log in and check that the pan0 interface exists, and the test-nap script is running.
pi@hub:~$ ifconfig pan0
pan0 Link encap:Ethernet HWaddr da:87:54:2c:f8:66
inet addr:172.168.10.1 Bcast:172.168.10.255 Mask:255.255.255.0
inet6 addr: fe80::d887:54ff:fe2c:f866/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:60 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:9090 (8.8 KiB)
pi@hub:~$ ps ax | grep test-nap
438 ? S 0:00 sudo nohup /usr/local/sbin/test-nap pan0
470 ? S 0:00 /usr/bin/python /usr/local/sbin/test-nap pan0
851 ttyS0 S+ 0:00 grep --color=auto test-nap
- If everything is running as expected we just need to take a note of the Bluetooth MAC so we can tell the clients who they need to contact. We can find this by running 'hciconfig dev'.
pi@hub:~$ hciconfig dev
hci0: Type: BR/EDR Bus: UART
BD Address: B8:27:EB:25:A0:AE ACL MTU: 1021:8 SCO MTU: 64:1
UP RUNNING
RX bytes:731 acl:0 sco:0 events:44 errors:0
TX bytes:1784 acl:0 sco:0 commands:44 errors:0
Setting up a client
- Download the latest Raspbian image (Here I am using 2017-04-10-raspbian-jessie-lite.zip) and write to an SD Card.
- Boot the Raspberry Pi, login and run the 'raspi-config' application.
pi@raspberrypi:~$ sudo raspi-config
- Select option 2 to change the hostname, change it to 'client0'.
- Select 'Finish', followed by 'Yes' to reboot.
- Wait for the Raspberry to reboot and log in again.
- Setup a network connection. Depending on your setup this can be either by plugging in an Ethernet cable or by setting up a Wireless connection.
- Install the packages required for setting up the bluetooth network.
pi@client0: sudo apt-get install python-dbus
- Download a helper script for establishing the bluetooth network.
pi@client0:~ $ wget https://raw.githubusercontent.com/mk-fg/fgtk/master/bt-pan
pi@client0:~ $ sudo mv bt-pan /usr/local/sbin/
pi@client0:~ $ sudo chmod +x /usr/local/sbin/bt-pan
- Again we want to run this script at startup, so run crontab -e and add the following, replacing the MAC Address with that of your bluetooth dongle.
@reboot sudo noup /usr/local/sbin/bt-pan client B8:27:EB:25:A0:AE &
Pair client to hub
Before the network can be established a bluetooth connection first needs to be setup between the client device and the hub. This is achieved by making use of the 'bluetoothctl' application.- First setup the client so it can be discovered by running the commands in bold below.
pi@client0:~ $ sudo bluetoothctl
[NEW] Controller B8:27:EB:5B:CB:74 client0 [default]
[bluetooth]# power on
Changing power on succeeded
[bluetooth]# discoverable on
Changing discoverable on succeeded
[CHG] Controller B8:27:EB:5B:CB:74 Discoverable: yes
- Then scan for, and connect to it, from the hub (again using the commands in bold). Once its found we want to pair and trust the client to allow it to auto connect in future,
pi@hub:~$ sudo bluetoothctl
[NEW] Controller B8:27:EB:25:A0:AE hub [default]
[bluetooth]# power on
Changing power on succeeded
[bluetooth]# agent on
Agent registered
[bluetooth]# scan on
Discovery started
[CHG] Controller B8:27:EB:25:A0:AE Discovering: yes
[NEW] Device B8:27:EB:5B:CB:74 client0
[bluetooth]# pair B8:27:EB:5B:CB:74
Attempting to pair with B8:27:EB:5B:CB:74
[CHG] Device B8:27:EB:5B:CB:74 Connected: yes
[CHG] Device B8:27:EB:5B:CB:74 UUIDs:
0000110c-0000-1000-8000-00805f9b34fb
0000110e-0000-1000-8000-00805f9b34fb
00001200-0000-1000-8000-00805f9b34fb
00001800-0000-1000-8000-00805f9b34fb
00001801-0000-1000-8000-00805f9b34fb
[CHG] Device B8:27:EB:5B:CB:74 Paired: yes
Pairing successful
[bluetooth]# trust B8:27:EB:5B:CB:74
[CHG] Device B8:27:EB:5B:CB:74 Trusted: yes
Changing B8:27:EB:5B:CB:74 trust succeeded
[CHG] Device B8:27:EB:5B:CB:74 Connected: no
[bluetooth]#
- With the client paired and trusted we can exit out of the bluetoothctl app on both the hub and client by using the quit command.
- To check that the Bluetooth network is working reboot the client device (sudo reboot), log in and check if the bnep0 interface now exists and has been assigned an IP address.
pi@client0:~ $ ifconfig bnep0
bnep0 Link encap:Ethernet HWaddr b8:27:eb:5b:cb:74
inet addr:172.168.10.45 Bcast:172.168.10.255 Mask:255.255.255.0
inet6 addr: fe80::ba27:ebff:fe5b:cb74/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:60 errors:0 dropped:0 overruns:0 frame:0
TX packets:53 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
- To confirm the connection has been established attempt to connect to the hub from the client.
pi@client0:~ $ ping 172.168.10.1
PING 172.168.10.1 (172.168.10.1) 56(84) bytes of data.
64 bytes from 172.168.10.1: icmp_seq=1 ttl=64 time=190 ms
64 bytes from 172.168.10.1: icmp_seq=2 ttl=64 time=33.7 ms
--- 172.168.10.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 33.782/112.324/190.867/78.543 ms
If all has gone well you now have a working Bluetooth network, which you can now extend with multiple clients.
Optional extras
Setup static IP for a client
Sometimes its useful for a client to always be assigned the same IP address when it establishes the network connection and, luckily, this is easy to achieve.- First look up the client's bluetooth address using the 'hciconfig dev' command used earlier.
- Then, on the hub, edit the /etc/dnsmasq.conf file and add the following entry, replacing the MAC with that of your client device.
dhcp-host=B8:27:EB:5B:CB:74,172.168.10.101,client0
- Once the file has been updated we need to restart the dnsmasq service so the changes take effect.
pi@hub:~$ sudo service dnsmasq restart
- Now the next time the client requests an IP address it will receive the one listed in the file, and additional entries can be added for every client in the Bluetooth network.
Enable IP port forwarding
If your 'hub' Raspberry Pi has a Wireless or Ethernet network connection you can choose to share it with the client Raspberry Pis, in theory allowing them to access the internet via bluetooth.
- To configure the 'hub' to forward its network connection first edit the /etc/sysctl.conf file and uncomment line 28 to read :-
net.ipv4.ip_forward=1
- Next edit the /etc/rc.local file and add, the following. Updating 'eth0' to match your upstream network interface (e.g. wlan0).
# Enable port forwarding. Change eth0 to match the primary network connection name
/sbin/iptables -P FORWARD ACCEPT
/sbin/iptables --table nat -A POSTROUTING -o eth0 -j MASQUERADE
- Finally reboot (sudo reboot), and you should now be able to access this shared network connection from any of the client Raspberry Pis.
Wrap up
Hopefully this set of instructions are relatively clear and cover all the steps needed to get a basic Bluetooth network up and running (Either using a Raspberry Pi with built in Bluetooth, or an older model with a USB bluetooth adaptor). More work would be needed to make this a robust solution (i.e. the client only tries to establish a connection when it first starts up) but its a solid base to build upon. In theory it should also work on none Raspberry Pi based hardware that is also running Debian Jessie or equivalent, but I've not tried myself.
Whilst a bluetooth network is not as fast as a Wifi one (in my tests 200KB/s vs 1500KB/s) it uses slightly less power to run. On a PiZero W transferring files over WiFi seemed to pull about 0.1A more than when using Bluetooth, of course WiFi was also about 8 times faster. Not a huge difference, but if you are running the Raspberry Pi off battery, e.g. running a remote sensor, and are only transferring smaller amounts of data then this could add up to make a difference to the run time of the Pi.
Leo