BLE対応のESP32のRSSIをRaspberry Piで検出する

**今回はBLEに対応したESP32のRSSIをRaspberry Piで検出してみたいと思います**
## 開発環境
### ESP32
- micropython
- WSL(Windows Subsystem for Linux)
- ESP32開発ボード
- ESP-idf
- ampy (書き込みツール)

###Raspberry Pi Zero WH(Bluetooth 対応)
- Raspbian
- Python3.7
- pip3

# ESP32の設定
今回はWSL内でファイルを書き込みますが，好きな書き込みツールを使用して構いません


#### 対話モードでubluetoothモジュールがあるか確認する
ESP32でBLEを使用するにはubluetoothが必要です．モジュールの有無は`help('modules')`で確認ができます

```
>>> help('modules')
__main__          framebuf          uasyncio/funcs    upip
_boot             gc                uasyncio/lock     upip_utarfile
_onewire          inisetup          uasyncio/stream   urandom
_thread           machine           ubinascii         ure
_uasyncio         math              ubluetooth        uselect
_webrepl          micropython       ucollections      usocket
apa106            neopixel          ucryptolib        ussl
btree             network           uctypes           ustruct
builtins          ntptime           uerrno            utime
cmath             onewire           uhashlib          utimeq
dht               sys               uhashlib          uwebsocket
ds18x20           uarray            uheapq            uzlib
esp               uasyncio/__init__ uio               webrepl
esp32             uasyncio/core     ujson             webrepl_setup
flashbdev         uasyncio/event    uos               websocket_helper
Plus any modules on the filesystem
```
もしなければ各自の使用している書き込みツールの方法でubluetoothモジュールをインストールしてください

### bluetoothのサンプルプログラムをインストール
''
今回はここからgitにある[micropythonのソースコード](https://github.com/micropython/micropython)を拝借

```
git clone  https://github.com/micropython/micropython
```
などでインストール

Bluetoothのサンプルプログラムは`/micropython/examples/bluetooth/` にあります．

今回使用するのは`ble_advertising.py`と`ble_temperature.py`です
これらをESP32に書き込みます

次に`ble_temperature.py`を編集します

```ble_temperature.py
import bluetooth
import random
import struct
import time
from ble_advertising import advertising_payload

from micropython import const

_IRQ_CENTRAL_CONNECT = const(1)
_IRQ_CENTRAL_DISCONNECT = const(2)

# org.bluetooth.service.environmental_sensing
_ENV_SENSE_UUID = bluetooth.UUID(0x181A)
# org.bluetooth.characteristic.temperature
_TEMP_CHAR = (
    bluetooth.UUID(0x2A6E),
    bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,
)
_ENV_SENSE_SERVICE = (
    _ENV_SENSE_UUID,
    (_TEMP_CHAR,),
)

# org.bluetooth.characteristic.gap.appearance.xml
_ADV_APPEARANCE_GENERIC_THERMOMETER = const(768)


class BLETemperature:
    def __init__(self, ble, name="beacon1"):
        self._ble = ble
        self._ble.active(True)
        self._ble.irq(handler=self._irq)
        ((self._handle,),) = self._ble.gatts_register_services((_ENV_SENSE_SERVICE,))
        self._connections = set()
        self._payload = advertising_payload(
            name=name, services=[_ENV_SENSE_UUID], appearance=_ADV_APPEARANCE_GENERIC_THERMOMETER
        )
        self._advertise()

    def _irq(self, event, data):
        # Track connections so we can send notifications.
        if event == _IRQ_CENTRAL_CONNECT:
            conn_handle, _, _, = data
            self._connections.add(conn_handle)
        elif event == _IRQ_CENTRAL_DISCONNECT:
            conn_handle, _, _, = data
            self._connections.remove(conn_handle)
            # Start advertising again to allow a new connection.
            self._advertise()

    def set_temperature(self, temp_deg_c, notify=False):
        # Data is sint16 in degrees Celsius with a resolution of 0.01 degrees Celsius.
        # Write the local value, ready for a central to read.
```
BLETemperatureクラスのdef _init(self, ble, name="mpy-temp")のmpy-tempをbeacon1など分かりやすい名前に変更します
UUIDの指定もこのファイル内でできます

#### main.pyの編集
ESP32は特に指定のない限り，電源が入るとmain.pyが実行されます
ここにBluetoothの発信し続けるように指定します

```main.py
import ble_temperature
ble_temperature.demo()
```
これをESP32に書き込んだら準備完了です


#Raspberry Piの設定
bluepyなどの必要なツールを次のコマンドでインストールします

```
$ sudo apt install libbluetooth3-dev libglib2.0 libboost-python-dev libboost-thread-dev
$ sudo apt install python3-pip
$ cd /usr/lib/arm-linux-gnueabihf/
$ sudo ln libboost_python-py37.so libboost_python-py34.so
$ sudo pip3 install gattlib
$ sudo pip3 install bluepy
$ sudo systemctl daemon-reload
$ sudo service bluetooth restart
```
3行目の`libboost_python-py37.so`は自身のデバイス内のPython3のバージョンにより異なります

### gatlibのインストールが出来ない場合
Rasberry Pi Zeroの低スペックのRasberry Piではgattlibのインストールがスワップファイルが原因で出来ない場合がある(自分がそうでした)ので対処

free -mでスワップファイルの容量を確認すると100MBしかないのでスワップファイルを編集します

```
$ free -m 
              total        used        free      shared  buff/cache   available
Mem:            875         115         523           8         236         695
Swap:            99           3          96
$ sudo nano /etc/dphys-swapfile
```
`dphys-swapfile`の`CONF_SWAPSIZE`を100から800に変更します
次のコマンドでスワップファイルを停止して開始するとスワップファイルが800MBに変更されると思います

```
$ sudo /etc/init.d/dphys-swapfile stop
$ sudo /etc/init.d/dphys-swapfile start
$ sudo free -m
 total        used        free      shared  buff/cache   available
Mem:            432          37         222           4         172         323
Swap:           799          67         732
```
これでgatlibのインストールが可能になると思います．

### スキャンプログラムでESP32のRSSIの検出
Python3でble_scan.pyを管理者権限で実行

``` ble_scan.py
import bluepy

scanner = bluepy.btle.Scanner(0)
device = scanner.scan(5)  #5秒間スキャン

for device in device:
  print('======================================================')
  print('address : %s' % device.addr)
  print('addrType: %s' % device.addrType)
  print('RSSI    : %s' % device.rssi)
  print('Adv data:')
  for (adtype, desc, value) in device.getScanData():
    print(' (%3s) %s : %s ' % (adtype, desc, value))
```

#### 実行結果

``` 
======================================================
address : fc:f5:c4:29:05:4e
addrType: public
RSSI    : -60
Adv data:
 (  1) Flags : 06
 (  9) Complete Local Name : beacon1
 (  3) Complete 16b Services : 0000181a-0000-1000-8000-00805f9b34fb
 ( 25) Appearance : 0003
======================================================

↓以下に他のBluetoothデバイス情報をが表示される
```
先ほど設定したESP32の情報とRSSIデータなどが表示されていると思います．

## おわりに
次はRasberryPiとESP32と距離をメートル表記にして表示できるようにしたいですね

### 参考サイト
Raspberry Pi で bluepy を使ってmicro:bitをコントロール(https://qiita.com/FiveOne/items/ea04b74271da0f382ed6)
BLE対応のESP32用MicroPythonのビルドと書き込み - Ubuntu (Windows Subsystem for Linux)(https://qiita.com/jp-96/items/f5a18e2d10591849bd3d)