이번 포스팅에서는 파이썬 라이브러리인 pyBluz를 Raspberry Pi 3에 설치하여 Arduino 101 BLE (Bluetooth Low Energy) 제어 및 정보 가져오는 과정을 설명합니다.
C언어하는 과정을 다음 포스팅에 소개하고 있습니다.
우선 Arduino 101에 블루투스를 이용하여 LED를 제어하는 예제 프로그램이 업로드 되어 있어야 하는데 그 과정은 다음 두 개의 포스팅에 소개하고 있습니다.
먼저 아래 포스팅은 아두이노 IDE에서 Arduino 101를 대상으로 프로그래밍 및 업로드를 하기 위한 준비과정을 설명하고 있습니다.
[Arduino & AVR/Android 101 ( Genuino 101 )] - Genuino 101 ( Arduino 101) 처음 사용해보기
그리고 다음 포스팅은 블루투스 예제를 Arduino 101에 업로드하고 안드로이드에서 Arduino 101에 연결된 LED를 블루투스 통신을 통해 제어하는 방법을 소개하고 있습니다.
[Arduino & AVR/Android 101 ( Genuino 101 )] - Genuino 101 ( Arduino 101) 블루투스 예제 실행시켜보기
파이썬 라이브러리를 사용하여 진행하기 전에 터미널에서 hcitool과 gatttool을 이용하여 통신 접속 및 데이터 전송하는 과정을 다시 한번 확인해보았습니다.
라즈베리파이3에 내장된 블루투스 디바이스를 확인합니다.
pi@pi-desktop:~$ hcitool dev
Devices:
hci0 B8:27:EB:DA:FA:66
arduino 101의 블루투스 장치의 맥주소를 검색을 통해 알아냅니다.
pi@pi-desktop:~$ sudo hcitool lescan
LE Scan ...
FC:F1:36:2B:34:32 (unknown)
98:4F:EE:0F:4E:1E LED
98:4F:EE:0F:4E:1E (unknown)
^Cpi@pi-desktop:~$
그 다음 gatttool을 사용하여 ardunio 101의 블루투스에 연결하여 아두이노 101에서 제공하는 블루투스 서비스 목록과 characteristics를 확인해봤습니다.
pi@pi-desktop:~$ sudo gatttool -i hci0 -b 98:4F:EE:0F:4E:1E -I
[98:4F:EE:0F:4E:1E][LE]> connect
Attempting to connect to 98:4F:EE:0F:4E:1E
Connection successful
[98:4F:EE:0F:4E:1E][LE]> primary
attr handle: 0x0001, end grp handle: 0x0007 uuid: 00001800-0000-1000-8000-00805f9b34fb
attr handle: 0x0008, end grp handle: 0x0008 uuid: 00001801-0000-1000-8000-00805f9b34fb
attr handle: 0x0009, end grp handle: 0xffff uuid: 19b10000-e8f2-537e-4f6c-d104768a1214
[98:4F:EE:0F:4E:1E][LE]> char-desc
handle: 0x0001, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0002, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb
handle: 0x0004, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb
handle: 0x0006, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0007, uuid: 00002a04-0000-1000-8000-00805f9b34fb
handle: 0x0008, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0009, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x000a, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x000b, uuid: 19b10001-e8f2-537e-4f6c-d104768a1214
arduino 101에 업로드 시켜둔 LED 예제코드를 열어보면 아래와 같이 선언되어 있는 것이 보입니다.
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Service
// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEUnsignedCharCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
이제 확인한 characteristics의 핸들을 가지고 arduino 101 의 LED를 제어해봅니다.
첫번째 줄을 실행시키면 LED가 켜지고, 두번째 줄을 실행시키면 LED가 꺼지게 됩니다.
[98:4F:EE:0F:4E:1E][LE]> char-write-req b 01
Characteristic value was written successfully
[98:4F:EE:0F:4E:1E][LE]> char-write-req b 00
Characteristic value was written successfully
pybluez 라이브러 태스트
이제 Raspberry Pi 3에 pybluez 라이브러리를 다음 과정을 통해 설치했습니다.
pi@pi-desktop:~$ sudo apt-get install bluetooth libbluetooth-dev
pi@pi-desktop:~$ sudo pip install pybluez
https://github.com/karulis/pybluez/tree/master/examples/ble 에 존재하는 BLE를 위한 pybluez예제를 태스트 해보았습니다.
우선 scan.py를 실행시켜 보니 다음과 같은 에러가 나서
pi@pi-desktop:~/iBeacon-Scanner-$ python scan.py
Traceback (most recent call last):
File "scan.py", line 1, in <module>
from bluetooth.ble import DiscoveryService
File "/usr/local/lib/python2.7/dist-packages/bluetooth/ble.py", line 1, in <module>
from gattlib import *
ImportError: No module named gattlib
gattlib를 설치하려고 하니 boost 관련 헤더파일이 없다는 에러가 나서 먼저 libboost-all-dev를 설치한후 gattlib를 설치했습니다.
pi@pi-desktop:~/iBeacon-Scanner-$ sudo apt-get install libboost-all-dev
pi@pi-desktop:~/iBeacon-Scanner-$ sudo pip install gattlib
이제 다시 실행을 시켜본 결과 입니다.
pi@pi-desktop:~/iBeacon-Scanner-$ sudo python scan.py
name: , address: 98:4F:EE:0F:4E:1E
hcitool 명령 결과와 비교해보니 98:4F:EE:0F:4E:1E이 arduino 101의 블루투스 맥어드레스이군요..
pi@pi-desktop:~/iBeacon-Scanner-$ sudo hcitool -i hci0 lescan
Set scan parameters failed: Input/output error
pi@pi-desktop:~/iBeacon-Scanner-$ sudo hciconfig hci0 reset
pi@pi-desktop:~/iBeacon-Scanner-$ sudo hcitool -i hci0 lescan
LE Scan ...
FC:F1:36:2B:34:32 (unknown)
98:4F:EE:0F:4E:1E LED
98:4F:EE:0F:4E:1E (unknown)
^Cpi@pi-desktop:~/iBeacon-Scanner-$
scan.py의 코드는 아래와 같습니다.
1 2 3 4 5 6 7 | from bluetooth.ble import DiscoveryService service = DiscoveryService() devices = service.discover(2) for address, name in devices.items(): print("name: {}, address: {}".format(name, address)) | cs |
패키지로 설치하는 경우 위 코드에서 첫번째 줄 에러가 나는군요.. 그럴 경우 아래 처럼 따라하시면 됩니다.
문제가 있다고 댓글에 알려주셔서 확인해보니 에러가 나는 군요..
webnautes@webnautes-W54-55SU1-SUW ~ $ python
Python 2.7.12 (default, Jul 1 2016, 15:12:24)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from bluetooth.ble import DiscoveryService
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named ble
>>>
github에는 ble.py가 존재하는데 패키지로 설치시 없는 것으로 미루어 소스로 설치하면 문제가 해결될 거 같았습니다.
우선 설치했던 패키지를 지우고
$ sudo pip uninstall pybluez
github에서 소스코드를 다운로드 받아 설치를 합니다.
$ git clone https://github.com/karulis/pybluez.git pybluez
$ cd pybluez
$ sudo python setup.py install
$ sudo pip install -e .[ble]
문제가 해결되었습니다..
webnautes@webnautes-W54-55SU1-SUW ~/pybluez $ python
Python 2.7.12 (default, Jul 1 2016, 15:12:24)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from bluetooth.ble import DiscoveryService
이제 pybluez 라이브러리를 이용하여 arduino 101에 연결된 LED를 제어해보려했지만 ble 관련 예제를 모아둔 폴더에 예제코드도 없었고 따로 검색해봤지만 마땅한 코드를 찾지 못했습니다.
pybluez에서 아직 BLE를 완벽하게 지원안하나 싶어서 대안으로 사용할 라이브러리를 수소문한 결과 bluepy를 찾을 수 있었습니다...
Bluepy 라이브러리 태스트
우선 라이브러리를 설치하고
pi@pi-desktop:~$ sudo pip install bluepy
그리고 나서 예제코드를 다운로드 받았습니다. bluepy 홈페이지에는 예제코드는 거의 없고 라이브러리 레퍼런스 메뉴얼만 있어서 따로 찾은 예제들입니다.
pi@pi-desktop:~$ git clone https://github.com/rlangoy/bluepy_examples_nRF51822_mbed.git
태스트 해보면서 일부 수정한 경우에는 코드도 같이 올려둡니다.
blesca.py
블루투스 다비이스 이름과 RSSI, Flags, 서비스 uuid,, 이름을 출력해주는 예제입니다.
주소타입이 public으로 검색된 것을 확인할 수 있는데 이후 태스트한 예제들은 모두 random으로 코드에 적혀있어서 제대로 동작을 안했습니다. public로 변경해야 제대로 동작하더군요..
1 2 3 4 5 6 7 8 9 10 | pi@pi-desktop:~/bluepy_examples_nRF51822_mbed$ sudo python blesca.py [sudo] password for pi: Device 98:4f:ee:0f:4e:1e (public), RSSI=-41 dB Flags = 06 Incomplete 128b Services = 14128a7604d16c4f7e53f2e80000b119 Complete Local Name = LED Device fc:f1:36:2b:34:32 (public), RSSI=-95 dB Short Local Name = [TV] UN65J6350 Flags = 00 Manufacturer = 7500420401010efcf1362b34323a0195d03e2a01000000000000 | cs |
getServices.py
지정한 블루투스 장치의 서비스를 출력해줍니다.
1 2 3 4 5 6 | pi@pi-desktop:~/bluepy_examples_nRF51822_mbed$ sudo python getServices.py 98:4F: EE:0F:4E:1E [sudo] password for pi: Service <uuid=Generic Attribute handleStart=8 handleEnd=8> Service <uuid=Generic Access handleStart=1 handleEnd=7> Service <uuid=19b10000-e8f2-537e-4f6c-d104768a1214 handleStart=9 handleEnd=65535> | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import sys from bluepy.btle import UUID, Peripheral if len(sys.argv) != 2: print "Fatal, must pass device address:", sys.argv[0], "<device address="">" quit() p = Peripheral(sys.argv[1],"public") services=p.getServices() #displays all services for service in services: print service | cs |
getDeviceCharacteristics.py
지정한 블루투스 장치의 Characteristics를 출력해줍니다.
1 2 3 4 5 6 7 | pi@pi-desktop:~/bluepy_examples_nRF51822_mbed$ sudo python getDeviceCharacteristics.py 98:4F:EE:0F:4E:1E Handle UUID Properties ------------------------------------------------------- 0x03 00002a00-0000-1000-8000-00805f9b34fb READ 0x05 00002a01-0000-1000-8000-00805f9b34fb READ 0x07 00002a04-0000-1000-8000-00805f9b34fb READ 0x0B 19b10001-e8f2-537e-4f6c-d104768a1214 READ WRITE | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import sys from bluepy.btle import UUID, Peripheral if len(sys.argv) != 2: print "Fatal, must pass device address:", sys.argv[0], "<device address="">" quit() p = Peripheral(sys.argv[1],"public") chList = p.getCharacteristics() print "Handle UUID Properties" print "-------------------------------------------------------" for ch in chList: print (" 0x"+ format(ch.getHandle(),'02X') +" "+str(ch.uuid) +" " + ch.propertiesToString()) | cs |
getDeviceName.py
지정한 블루투스 장치의 이름을 출력해줍니다.
1 2 | pi@pi-desktop:~/bluepy_examples_nRF51822_mbed$ sudo python getDeviceName.py 98:4F:EE:0F:4E:1E ARDUINO 101-4E1E | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import sys from bluepy.btle import UUID, Peripheral dev_name_uuid = UUID(0x2A00) if len(sys.argv) != 2: print "Fatal, must pass device address:", sys.argv[0], "<device address="">" quit() p = Peripheral(sys.argv[1],"public") try: ch = p.getCharacteristics(uuid=dev_name_uuid)[0] if (ch.supportsRead()): print ch.read() finally: p.disconnect() | cs |
writeLed2.py
기존 코드를 수정하여 아두이노 101의 LED가 깜빡이는 것을 확인했습니다..
1 2 3 4 5 6 7 8 | pi@pi-desktop:~/bluepy_examples_nRF51822_mbed$ sudo python writeLed2.py 98:4F:EE:0F:4E:1E Service <uuid=19b10000-e8f2-537e-4f6c-d104768a1214 handleStart=9 handleEnd=65535> Led on Led off Led on Led off Led on Led off | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | import sys import binascii import struct import time from bluepy.btle import UUID, Peripheral led_service_uuid ="19b10000-e8f2-537e-4f6c-d104768a1214" led_char_uuid = "19b10001-e8f2-537e-4f6c-d104768a1214" if len(sys.argv) != 2: print "Fatal, must pass device address:", sys.argv[0], "<device address="">" quit() p = Peripheral(sys.argv[1], "public") LedService=p.getServiceByUUID(led_service_uuid) print LedService try: ch = LedService.getCharacteristics(led_char_uuid)[0] while 1: ch.write(struct.pack('<B', 0x00)); print ("Led on") time.sleep(1) ch.write(struct.pack('<B', 0x01)); print ("Led off") time.sleep(1) finally: p.disconnect() | cs |
readChar.py
LED 서비스가 제공하는 Characteristics의 값을 읽어오기 위해 작성했습니다.
1 2 3 4 5 6 7 8 9 | pi@raspberrypi:~/bluepy_examples_nRF51822_mbed $ sudo python readChar.py 98:4F:EE:0F:4E:1E Service <uuid=19b10000-e8f2-537e-4f6c-d104768a1214 handleStart=9 handleEnd=65535> 0x00 0x00 0x00 0x00 0x00 0x00 0x00 | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import sys import binascii import struct import time from bluepy.btle import UUID, Peripheral led_service_uuid ="19b10000-e8f2-537e-4f6c-d104768a1214" led_char_uuid = "19b10001-e8f2-537e-4f6c-d104768a1214" if len(sys.argv) != 2: print "Fatal, must pass device address:", sys.argv[0], "<device address="">" quit() p = Peripheral(sys.argv[1], "public") LedService=p.getServiceByUUID(led_service_uuid) print LedService try: ch = LedService.getCharacteristics(led_char_uuid)[0] if (ch.supportsRead()): while 1: val = binascii.b2a_hex(ch.read()) print ("0x" + val) time.sleep(1) finally: p.disconnect() | cs |
readButton1Notify.py
아직 태스트 안함...
readButton1.py
아직 태스트 안함...
bluepy_examples_nRF51822_mbed-master.zip
'Arduino 101' 카테고리의 다른 글
Arduino 101의 Bluetooth Low Energy(BLE) 예제를 안드로이드 폰과 테스트 (6) | 2017.08.02 |
---|---|
Windows에서 Genuino 101 ( Arduino 101) 보드 처음 사용해보기 (0) | 2017.08.02 |
Android에서 Arduino 101에 연결된 LED 제어 및 상태값 읽어오기 ( Bluetooth LE 프로그래밍 ) (23) | 2017.03.20 |
Arduino 101 CurieTime 예제 ( 시간 설정 및 불러오는 예제 ) (0) | 2016.06.10 |
Android에서 Bluetooth LE( BLE) 장치 연결시 16진수로 4바이트( 16-bit UUID )인 경우 처리 (0) | 2016.06.05 |
시간날때마다 틈틈이 이것저것 해보며 블로그에 글을 남깁니다.
블로그의 문서는 종종 최신 버전으로 업데이트됩니다.
여유 시간이 날때 진행하는 거라 언제 진행될지는 알 수 없습니다.
영화,책, 생각등을 올리는 블로그도 운영하고 있습니다.
https://freewriting2024.tistory.com
제가 쓴 책도 한번 검토해보세요 ^^
그렇게 천천히 걸으면서도 그렇게 빨리 앞으로 나갈 수 있다는 건.
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!