파이선에서 SensorTag를 사용하기 위해 Ian Harvey의
bluepy(https://github.com/IanHarvey/bluepy) 모듈을 사용한다.
링크에서 다운받으면 다음과 같은 파일이 들어있다. bluepy 디렉토리로 가서 make 명령을 실행한다. 이 모듈은 실행하기 위해서 bluepy-helper라는 프로그램이 필요해 make를 실행하면 이 프로그램을 컴파일 해 준다.
# ls -scF
4 bluepy/ 4 README.md 4 bluez-5.4/
4 docs/ 0 __init__.py
# cd bluepy
# make
gcc -L. -O0 -g -DHAVE_CONFIG_H -I../bluez-5.4/attrib -I../bluez-5.4 -I../bluez-5.4/lib -I../bluez-5.4/src -I../bluez-5.4/gdbus -I../bluez-5.4/btio `pkg-config glib-2.0 dbus-1 --cflags` -o bluepy-helper bluepy-helper.c ../bluez-5.4/lib/bluetooth.c ../bluez-5.4/lib/hci.c ../bluez-5.4/lib/sdp.c ../bluez-5.4/lib/uuid.c ../bluez-5.4/attrib/att.c ../bluez-5.4/attrib/gatt.c ../bluez-5.4/attrib/gattrib.c ../bluez-5.4/attrib/utils.c ../bluez-5.4/btio/btio.c ../bluez-5.4/src/log.c `pkg-config glib-2.0 --libs`
# ls -scF
Makefile bluepy-helper btle.py sensortag.py
__init__.py bluepy-helper.c btle.pyc
#
두개의 파이선 파일이 들어있는데 btle.py는 BLE 관련 클래스가 정의되어 있고 sensortag.py는 btle 모듈을 사용해 SensorTag에 연결해 센서값을 읽어오는 기능을 하는 코드가 들어있다. 먼저 btle.py를 사용하면 BLE 디바이스의 service, characteristic 관련 정보를 확인할 수 있다.
# python btle.py BC:6A:29:C3:54:33
Connecting to: BC:6A:29:C3:54:33, address type: public
Service <uuid=Generic Access handleStart=1 handleEnd=11> :
Characteristic <Device Name>, supports READ
-> 'TI BLE Sensor Tag'
Characteristic <Appearance>, supports READ
-> '\x00\x00'
Characteristic <Peripheral Privacy Flag>, supports READ WRITE
-> '\x00'
Characteristic <Reconnection Address>, supports READ WRITE
-> '\x00\x00\x00\x00\x00\x00'
Characteristic <Peripheral Preferred Connection Parameters>, supports READ
-> 'P\x00\xa0\x00\x00\x00\xe8\x03'
Service <uuid=f000aa10-0451-4000-b000-000000000000 handleStart=43 handleEnd=53> :
Characteristic <f000aa11-0451-4000-b000-000000000000>, supports NOTIFY READ
-> '\x00\x00\x00'
Characteristic <f000aa12-0451-4000-b000-000000000000>, supports READ WRITE
-> '\x00'
Characteristic <f000aa13-0451-4000-b000-000000000000>, supports READ WRITE
-> 'd'
Service <uuid=Generic Attribute handleStart=12 handleEnd=15> :
Characteristic <Service Changed>, supports INDICATE
Service <uuid=ffe0 handleStart=93 handleEnd=97> :
Characteristic <ffe1>, supports NOTIFY
Service <uuid=f000aa30-0451-4000-b000-000000000000 handleStart=62 handleEnd=72> :
Characteristic <f000aa31-0451-4000-b000-000000000000>, supports NOTIFY READ
-> '\x00\x00\x00\x00\x00\x00'
Characteristic <f000aa32-0451-4000-b000-000000000000>, supports READ WRITE
-> '\x00'
Characteristic <f000aa33-0451-4000-b000-000000000000>, supports READ WRITE
-> '\xc8'
Service <uuid=f000aa00-0451-4000-b000-000000000000 handleStart=35 handleEnd=42> :
Characteristic <f000aa01-0451-4000-b000-000000000000>, supports NOTIFY READ
-> '\x00\x00\x00\x00'
Characteristic <f000aa02-0451-4000-b000-000000000000>, supports READ WRITE
-> '\x00'
Service <uuid=f000aa60-0451-4000-b000-000000000000 handleStart=98 handleEnd=104> :
Characteristic <f000aa61-0451-4000-b000-000000000000>, supports READ
-> '3\x00'
Characteristic <f000aa62-0451-4000-b000-000000000000>, supports READ WRITE
-> '\x00'
Service <uuid=f000aa50-0451-4000-b000-000000000000 handleStart=85 handleEnd=92> :
Characteristic <f000aa51-0451-4000-b000-000000000000>, supports NOTIFY READ
-> '\x00\x00\x00\x00\x00\x00'
Characteristic <f000aa52-0451-4000-b000-000000000000>, supports READ WRITE
-> '\x00'
Service <uuid=f000aa20-0451-4000-b000-000000000000 handleStart=54 handleEnd=61> :
Characteristic <f000aa21-0451-4000-b000-000000000000>, supports NOTIFY READ
-> '\x00\x00\x00\x00'
Characteristic <f000aa22-0451-4000-b000-000000000000>, supports READ WRITE
-> '\x00'
Service <uuid=Device Information handleStart=16 handleEnd=34> :
Characteristic <System ID>, supports READ
-> '3T\xc3\x00\x00)j\xbc'
Characteristic <Model Number String>, supports READ
-> 'N.A.\x00'
Characteristic <Serial Number String>, supports READ
-> 'N.A.\x00'
Characteristic <Firmware Revision String>, supports READ
-> '1.0 (Dec 10 2012)\x00'
Characteristic <Hardware Revision String>, supports READ
-> 'N.A.\x00'
Characteristic <Software Revision String>, supports READ
-> 'N.A.\x00'
Characteristic <Manufacturer Name String>, supports READ
-> 'Texas Instruments\x00'
Characteristic <IEEE 11073-20601 Regulatory Cert. Data List>, supports READ
-> '\xfe\x00experimental'
Characteristic <PnP ID>, supports READ
-> '\x01\r\x00\x00\x00\x10\x01'
Service <uuid=f000ffc0-0451-4000-b000-000000000000 handleStart=105 handleEnd=65535> :
Characteristic <f000ffc1-0451-4000-b000-000000000000>, supports READ WRITE NO RESPONSE WRITE
-> Error from Bluetooth stack (comerr)
Characteristic <f000ffc2-0451-4000-b000-000000000000>, supports READ WRITE NO RESPONSE WRITE
-> Error from Bluetooth stack (comerr)
Service <uuid=f000aa40-0451-4000-b000-000000000000 handleStart=73 handleEnd=84> :
Characteristic <f000aa41-0451-4000-b000-000000000000>, supports NOTIFY READ
-> '\x00\x00\x00\x00'
Characteristic <f000aa42-0451-4000-b000-000000000000>, supports READ WRITE
-> '\x00'
Characteristic <f000aa43-0451-4000-b000-000000000000>, supports READ
-> '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
#
SensorTag가 제공하는 각 서비스마다 characteristic에 관한 정보를 출력해준다.
sensortag.py는 실행하면 SensorTag에 연결해 원하는 센서값을 지속적으로 읽어온다.
# python sensortag.py --all BC:6A:29:C3:54:33
Connecting to BC:6A:29:C3:54:33
('Temp: ', (26.03125, 26.074251481475812))
('Humidity: ', (26.394373168945314, 41.00469970703125))
('Barometer: ', (26.645779013633728, 1016.758906206612))
('Accelerometer: ', (0.15625, 0.59375, 0.828125))
('Magnetometer: ', (-20.20263671875, 22.4609375, 95.458984375))
('Gyroscope: ', (7.95745849609375, 10.711669921875, -69.57244873046875))
** Right button DOWN
('Temp: ', (26.0625, 25.675194203681826))
('Humidity: ', (26.394373168945314, 41.00469970703125))
('Barometer: ', (26.760699868202209, 1016.8384757575767))
** Right button UP
('Accelerometer: ', (0.171875, 0.75, 0.515625))
('Magnetometer: ', (-22.857666015625, 25.787353515625, 92.315673828125))
** Right button DOWN
('Gyroscope: ', (4.44793701171875, -15.93017578125, -25.39825439453125))
** Right button UP
('Temp: ', (26.09375, 28.389209302147549))
('Humidity: ', (26.394373168945314, 41.00469970703125))
('Barometer: ', (26.8482586145401, 1017.0108461132135))
('Accelerometer: ', (0.15625, 0.765625, 0.625))
('Magnetometer: ', (-22.857666015625, 25.787353515625, 92.315673828125))
('Gyroscope: ', (6.591796875, 3.23486328125, 3.387451171875))
** Left button DOWN
('Temp: ', (26.15625, 29.185403134000069))
** Right button DOWN
('Humidity: ', (26.394373168945314, 41.00469970703125))
** Both buttons UP
('Barometer: ', (26.922136306762695, 1017.0096061331639))
('Accelerometer: ', (0.21875, 0.703125, 0.671875))
('Magnetometer: ', (-22.15576171875, 24.627685546875, 93.20068359375))
^C#
파이선 소스코드를 분석하면 SensorTag에 어떻게 연결하고 필요한 센서를 활성화 한 후 값을 읽어오는 방법을 확인할 수 있다.
여기서는 예제로 에디슨 보드에서 파이선 쉘을 실행해 직접 온습도 센서값을 읽어와 보도록 하겠다.
# rfkill unblock bluetooth
# hciconfig hci0 up
# hcitool lescan
LE Scan ...
D0:39:72:D3:4A:AF (unknown)
D0:39:72:D3:4A:AF Bean
EC:C3:09:E2:18:A4 (unknown)
BC:6A:29:C3:54:33 (unknown)
BC:6A:29:C3:54:33 SensorTag
# python
>>> import struct
>>> from btle import UUID, Peripheral, DefaultDelegate
>>> sensorOn = struct.pack("B",0x01)
>>> sensorTag = Peripheral("BC:6A:29:C3:54:33")
>>> svcUUID = "f000aa20-0451-4000-b000-000000000000"
>>> dataUUID = "f000aa21-0451-4000-b000-000000000000"
>>> ctrlUUID = "f000aa22-0451-4000-b000-000000000000"
>>> svc = sensorTag.getServiceByUUID(svcUUID)
>>> data = svc.getCharacteristics(dataUUID)[0]
>>> ctrl = svc.getCharacteristics(ctrlUUID)[0]
>>> ctrl.write(sensorOn, withResponse=True)
>>> data.read()
'\xb8l\xdfD'
>>> data.read()
'\xb8l\xb2D'
>>> (rT,rH) = struct.unpack('<HH',data.read())
>>> temp = -46.85+175.72*(rT/65536.0)
>>> RH = -6.0+125.0*((rH&0xfffc)/65536.0)
>>> temp
27.8610302734375
>>> RH
27.57696533203125
>>> def tempHum(d):
... (rT, rH) = struct.unpack('<HH', d.read())
... temp = -46.85+175.72*(rT/65536.0)
... RH = -6.0+125.0*((rH&0xfffc)/65536.0)
... return (temp, RH)
...
>>> tempHum(data)
(27.689428710937499, 25.34918212890625)
>>> tempHum(data)
(27.689428710937499, 25.31103515625)
>>> tempHum(data)
(27.692109985351557, 25.34918212890625)
>>> sensorTag.disconnect()
>>>
예제에서 svcUUID, dataUUID, ctrlUUID는 위에서 btle.py를 실행한 결과로 출력된 UUID 값이다.
...
Service <uuid=f000aa20-0451-4000-b000-000000000000 handleStart=54 handleEnd=61> :
Characteristic <f000aa21-0451-4000-b000-000000000000>, supports NOTIFY READ
-> '\x00\x00\x00\x00'
Characteristic <f000aa22-0451-4000-b000-000000000000>, supports READ WRITE
-> '\x00'
...
다른 센서들도 이와 유사한 방법으로 사용하면 된다.