ubuntuでpythonのbluetooth開発環境を構築3

bluepyでプログラムを作っていましたがDelegateやNotificationの部分できちんと動作しなかったところがあるので、またライブラリを変更します

今回使ったのはこちら
github.com

環境

ubuntu16.04
python2.7

RaspberryPi3 B+ でも確認
(Linux raspberrypi.local 4.14.71-v7+ #1145 SMP Fri Sep 21 15:38:35 BST 2018 armv7l GNU/Linux)(STRETCH)

pythonは2系で動かします

Adafruit_Python_BluefruitLEインストール

sudo apt-get update
sudo apt-get -y install libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev
git clone https://github.com/adafruit/Adafruit_Python_BluefruitLE
cd Adafruit_Python_BluefruitLE/
sudo python2 setup.py install

ここまでは公式通りにインストール
しかし、ここからbluez-5.33を公式通りにインストールしたらエラーが出たため5.37を入れます

cd ~
wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.37.tar.xz
tar xvf bluez-5.37.tar.xz
cd bluez-5.37
./configure
make
sudo make install
sudo systemctl start bluetooth
sudo systemctl enable bluetooth

lowEnergy有効化

sudo nano /lib/systemd/system/bluetooth.service
9行目を
ExecStart=/usr/local/libexec/bluetooth/bluetoothd  
から
ExecStart=/usr/local/libexec/bluetooth/bluetoothd    --experimental  
に修正
sudo systemctl daemon-reload
sudo systemctl restart bluetooth

そしたらサンプルプログラムを動かします。
手持ちが前回同様blenano2なのでそれを使いました。
(プログラムはこちら
blenano2は電源入れておいて、
examples/low_level.pyを編集します

# Example of low level interaction with a BLE UART device that has an RX and TX
# characteristic for receiving and sending data.  This doesn't use any service
# implementation and instead just manipulates the services and characteristics
# on a device.  See the uart_service.py example for a simpler UART service
# example that uses a high level service implementation.
# Author: Tony DiCola
import logging
import time
import uuid
import struct
import binascii
import Adafruit_BluefruitLE


# Enable debug output.
#logging.basicConfig(level=logging.DEBUG)

# Define service and characteristic UUIDs used by the UART service.
UART_SERVICE_UUID = uuid.UUID('713d0000-503e-4c75-ba94-3148f18d941e')
#TX_CHAR_UUID      = uuid.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E')
RX_CHAR_UUID      = uuid.UUID('713d0001-503e-4c75-ba94-3148f18d941e')

# Get the BLE provider for the current platform.
ble = Adafruit_BluefruitLE.get_provider()


# Main function implements the program logic so it can run in a background
# thread.  Most platforms require the main thread to handle GUI events and other
# asyncronous events like BLE actions.  All of the threading logic is taken care
# of automatically though and you just need to provide a main function that uses
# the BLE provider.
def main():
    # Clear any cached data because both bluez and CoreBluetooth have issues with
    # caching data and it going stale.
    ble.clear_cached_data()

    # Get the first available BLE network adapter and make sure it's powered on.
    adapter = ble.get_default_adapter()
    adapter.power_on()
    print('Using adapter: {0}'.format(adapter.name))

    # Disconnect any currently connected UART devices.  Good for cleaning up and
    # starting from a fresh state.
    print('Disconnecting any connected UART devices...')
    ble.disconnect_devices([UART_SERVICE_UUID])

    # Scan for UART devices.
    print('Searching for UART device...')
    try:
        adapter.start_scan()
        # Search for the first UART device found (will time out after 60 seconds
        # but you can specify an optional timeout_sec parameter to change it).
        device = ble.find_device(service_uuids=[UART_SERVICE_UUID])
        if device is None:
            raise RuntimeError('Failed to find UART device!')
    finally:
        # Make sure scanning is stopped before exiting.
        adapter.stop_scan()

    print('Connecting to device...')
    device.connect()  # Will time out after 60 seconds, specify timeout_sec parameter
                      # to change the timeout.

    # Once connected do everything else in a try/finally to make sure the device
    # is disconnected when done.
    try:
        # Wait for service discovery to complete for at least the specified
        # service and characteristic UUID lists.  Will time out after 60 seconds
        # (specify timeout_sec parameter to override).
        print('Discovering services...')
        device.discover([UART_SERVICE_UUID], [ RX_CHAR_UUID])#TX_CHAR_UUID

        # Find the UART service and its characteristics.
        uart = device.find_service(UART_SERVICE_UUID)
        rx = uart.find_characteristic(RX_CHAR_UUID)
        #tx = uart.find_characteristic(TX_CHAR_UUID)

        # Write a string to the TX characteristic.
        #print('Sending message to device...')
        #tx.write_value('Hello world!\r\n')

        # Function to receive RX characteristic changes.  Note that this will
        # be called on a different thread so be careful to make sure state that
        # the function changes is thread safe.  Use queue or other thread-safe
        # primitives to send data to other threads.
        def received(data):
            #print('Received: {0}'.format((data)))
            print(binascii.b2a_hex(data))

        # Turn on notification of RX characteristics using the callback above.
        print('Subscribing to RX characteristic changes...')
        rx.start_notify(received)

        # Now just wait for 30 seconds to receive data.
        print('Waiting 60 seconds to receive data from the device...')
        time.sleep(60)
    finally:
        # Make sure device is disconnected on exit.
        device.disconnect()


# Initialize the BLE system.  MUST be called before other BLE calls!
ble.initialize()

# Start the mainloop to process BLE events, and run the provided function in
# a background thread.  When the provided main function stops running, returns
# an integer status code, or throws an error the program will exit.
ble.run_mainloop_with(main)

python2で実行すると

Using adapter: astina-System-Product-Name
Disconnecting any connected UART devices...
Searching for UART device...
Connecting to device...
Discovering services...
Subscribing to RX characteristic changes...
Waiting 60 seconds to receive data from the device...
0102030000
0102030000
0102030000

みたいな感じでbluetooth経由で受信したデータが表示されます。(表示した受信データはblenano2のプログラムをちょっといじったので違います)

ちなみにDiscovering services...で止まってしまう場合は内部のbluetooth設定とかで止まっている可能性があります。
その場合は手動でbluetoothをオンオフしたりPCを再起動させたほうがいいです。
またRaspberryPi3 B+でも確認できました。

以上です。