RaspberryPi同士でbluetooth通信

ラズパイ同士でBluetooth経由で通信を行う手法を後輩が纏めてくれたので、僕がQiitaにてまとめる。
# 1. 環境構築
## Bluetoothドライバのインストール

```
$ sudo apt install bluetooth
```

## 関連パッケージのインストール

```
$ sudo apt install libusb-dev
$ sudo apt install libdbus-1-dev
$ sudo apt install libglib2.0-dev
$ sudo apt install libudev-dev
$ sudo apt install libical-dev
$ sudo apt install libreadline-dev
$ sudo apt install libdbus-glib-1-dev
$ sudo apt install libbluetooth-dev
```

## BlueZのインストール

```
$ wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.45.tar.xz
$ xz -dv bluez-5.45.tar.xz
$ tar -xf bluez-5.45.tar
$ cd bluez-5.45/
$ ./configure --enable-experimental
$ make
$ sudo make install
$ sudo pip install pybluez
```

makeは割と長い。
オプションを付けて、`make -j4`でmakeしても良い。
`-j4`は４コア使用。

# 2. ペアリングを行う

まずserver側のmacアドレスを確認する。
server側のRaspberryPiにて

```
$ hciconfig
hci0:   Type: BR/EDR  Bus: USB
    BD Address: B8:27:EB:B9:40:6E  ACL MTU: 1021:8  SCO MTU: 64:1
    UP RUNNING PSCAN 
    RX bytes:1724 acl:0 sco:0 events:92 errors:0
    TX bytes:1364 acl:0 sco:0 commands:87 errors:0
```

`BD Address: B8:27:EB:B9:40:6E`がmacアドレス。

## server側でBluetoothが検索されるのを許可する

```
$ bluetoothctl
[bluetooth] # discoverable on
Changing discoverable on succeesed
[CHG] Controller B8:27:EB:B9:40:6E Discoverable : yes
[bluetooth] #
```

## client側でペアリング

```
$ bluetoothctl
[bluetooth] # pair B8:27:EB:B9:40:6E
Attempting to pair with B8:27:EB:B9:40:6E  ←成功
Device B8:27:EB:B9:40:6E not available     ←失敗  失敗しても根気強くやろう
```

# 3. Pyhtonプログラムにて通信

## client側

```py:client.py
# -*- coding: utf-8 -*-

import time
import bluetooth

PORT =1
server_socket=bluetooth.BluetoothSocket( bluetooth.RFCOMM )

print "connect..."

server_socket.bind( ("",PORT ))
server_socket.listen(1)

client_socket,address = server_socket.accept()

print "connection success!!"

while 1:
  try:
    data = client_socket.recv(1024)
    print "receive [%s]" % data
    print '\n'
  except KeyboardInterrupt:
    client_socket.close()
    server_socket.close()
    break
  except:
    print "error"
    print '\n'
    client_socket.close()
    server_socket.close()
    break
```

## server側

メインプログラム

```py:Main.py
# -*- coding: utf-8 -*-
# Main.py
from RN42 import RN42
from time import sleep
import RPi.GPIO as GPIO
import sys
import time

class Main:
    #""" Main Class """
    
    # Setting & Connect
    ras = RN42("ras", "B8:27:EB:B9:40:6E", 1)
    ras.connectBluetooth(ras.bdAddr,ras.port)
    
    print "Entering main loop now"

    while 1:
        try:
            ras.sock.send("Hello World")
            print "data send"
            time.sleep(1)
        except KeyboardInterrupt:
            ras.disconnect(ras.sock)
```

通信部をまとめたライブラリ

```py:RN42.py
# -*- coding: utf-8 -*-
# RN42.py
from time import sleep
import sys
import bluetooth

class RN42:
    def __init__(self, name, addr, num):
        """ Arduino with RN42"""
        self.__name = name     #Set Name
        self.__bdAddr = addr   #the address form the Arduino RN42
        self.__port = num      #Connect Port (RaspberryPi  to Arduino)
        self.__sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM) #config

    @property
    def name(self):
        pass
    @name.getter
    def name(self):
        return self.__name
    @name.setter
    def name(self,name):
        self.__name = name

    @property
    def bdAddr(self):
        pass
    @bdAddr.getter
    def bdAddr(self):
        return self.__bdAddr
    @bdAddr.setter
    def bdAddr(self,value):
        self.__bdAddr = value
        return

    @property
    def port(self):
        pass
    @port.getter
    def port(self):
        return self.__port
    @port.setter
    def port(self,value):
        self.__port = value
        return

    @property
    def sock(self):
        pass
    @sock.getter
    def sock(self):
        return self.__sock
    @sock.setter
    def sock(self, value):
        self.__sock = value
    def reConnect(self, addr, num):
        self.__bdAddr = addr   #the address form the Arduino RN42
        self.__port = num      #Connect Port (RaspberryPi  to Arduino)
        self.__sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM) #config

    def connectBluetooth(self, bdAddr, port):
        while(1):
            try:
                print self.__name + " : Connect......"
                self.__sock.connect((bdAddr,port))
                sleep(2)
                print self.__name + " : Successful Connected!!!"
                break
            except bluetooth.BluetoothError :
                print self.name + " : connecting failed"
                print "try connecting"
                self.reConnect(bdAddr, port)
                sleep(0.5)
            except KeyboardInterrupt:
                break
            
    def disConnect(self,sock):
        sock.close() 
```

serverとclientで実行すれば`Hello World`が送られ続ける。

# 参考Web

- [Raspberry Pi 3でBluetoothデバイス接続](http://blog.akanumahiroaki.com/entry/2017/06/02/080000)
- [Raspberry PiでBluetooth 4 (Bluetooth Low Energy) を使えるようにする](https://qiita.com/ozora-kobo/items/876706bb73d8a692d53f)
- [Raspberry PiでUSB/Bluetoothアダプタを使う](https://qiita.com/yuyakato/items/4ca410bd216a8aadd5ce)
- [17.2. socket — 低レベルネットワークインターフェース](https://docs.python.jp/2.7/library/socket.html)
- [3.2. Communicating with RFCOMM](https://people.csail.mit.edu/albert/bluez-intro/x232.html)
- [Bluetooth Programming with Python 3](http://blog.kevindoran.co/bluetooth-programming-with-python-3/)