원래 목적대로 구글신에게 좀 더 많은 신탁을 구한 결과 다음의 사항을 알게 되었다.
- Hands-Free Profile(HFP)를 사용해서 명령과 데이터를 주고받는다.
- 여기서 컴퓨터 또는 아이폰은 Hands-Free Device(블투시계)에 대해 AG(Audio Gateway)로 동작한다.
- HFP는 RFCOMM 위에 올라가는 프로파일로 예전 모뎀 제어에 널리 사용되던 AT 커맨드를 사용한다.
AG | HF device | |
RING | --> | |
+CLIP 1234567890 | --> | |
전화온거 알려주고 발신자 번호 표시 후 사용자가 전화 받기 버튼을 누름 | ||
<-- | ATA | |
OK | --> | |
음성통화로 연결됨 |
위의 시나리오에서 붉은색 문자가 시리얼 프로파일(RFCOMM)을 사용해 상대방 기기에게 전달되게 된다.
뿐만 아니고 소니 에릭슨 블루투스 장비들의 AT명령어 목록을 담고 있는 PDF파일과 HFP Application Guideline이라는 문서까지 구할 수 있었다. 이에 대한 내용은 좀 더 공부해서 맥/아이폰 또는 아뒤노용의 smartWatchM류의 프로그램 개발에 사용해 볼 예정이다. 이 부분에 대한 상세한 내용은 추후 포스팅에 다시 거론하기로 하겠다.
서론이 너무 길어졌는데 이 목적의 소프트웨어 개발에 가장 기본적이고 필수적인것이 블루투스를 사용해 컴퓨터(또는 아이폰, 아뒤노 등등)이 블투시계/팔찌와 통신을 하는 방법을 찾는 것이다. 일단 사용할 언어는 파이썬으로 생각하고 있기에 파이썬용 블루투스 API를 찾아 본 결과 발견한것이 LightBlue 이다. 파이썬용 크로스 플랫폼 블루투스 API로 맥 OS X, 리눅스 용 뿐 아니고 심비안 시리즈 60 플랫폼도 지원한다. (즉 현재 국내에서 판매중인 노키아 6210s도 Symbian OS 9.3 Series 60 UI를 사용하고 있기 때문에 노키아 6210s에서도 파이썬으로 블루투스 프로그램을 작성할 수 있다는 소리다.)
* 심비안 시리즈 60 플랫폼은 꽤 오래전부터 파이썬을 지원해 왔다. Python for Symbian Series 60
현재 LightBlue에서 지원하는 기능은 다음과 같다.
- 디바이스 및 서비스 검색
- RFCOMM과 L2CAP에 대한 표준 소켓 인터페이스
- OBEX를 통한 파일 전송
- RFCOMM과 OBEX 서비스 advertising
- 로컬 디바이스 정보
사용법은 매우 간단해서 일단 lightblue를 설치한 다음 예제를 잠시만 보면 매우 쉽게 사용할 수 있다.
무엇보다 먼저 lightblue 모듈을 임포트 해 줘야 한다.
>>> import lightblue
그 다음 주변에 있는 디바이스와 각 디바이스의 서비스를 검색하는 방법은 다음과 같다.
>>> lightblue.finddevices()
[('00:0E:6D:71:A2:0B', u'My6600', 5243396), ('00:0D:93:19:C8:68',
u'pantherbox', 1057028)]
검색된 디바이스 중 두번째 디바이스가 제공하는 서비스 목록을 확인한다.
>>> lightblue.findservices('00:0D:93:19:C8:68')
[('00:0D:93:19:C8:68', 10, 'OBEX Object Push'), ('00:0D:93:19:C8:68', 15,
'OBEX File Transfer'), ('00:0D:93:19:C8:68', 1, 'Bluetooth-PDA-Sync'),
('00:0D:93:19:C8:68', 3, 'Palm Serial Port')]
GUI를 통해 사용자가 디바이스와 서비스를 선택하게 할 수도 있다.
>>> lightblue.selectdevice() # brings up a device-selection GUI
('00:0E:6D:71:A2:0B', u'My6600', 5243396)
>>> lightblue.selectservice() # brings up a service-selection GUI
('00:0E:6D:71:A2:0B', 2, u'Bluetooth Serial Port')
RFCOMM 소켓을 사용하려면 다음과 같이 하면 된다.
# client socket
>>> s = lightblue.socket()
>>> s.connect(("00:12:2c:45:8a:7b", 5))
>>> s.send("hello")
5
>>> s.close()
# server socket
>>> s = lightblue.socket()
>>> s.bind(("", 0)) # bind to 0 to bind to dynamically assigned port
>>> s.listen(1)
>>> lightblue.advertise("My RFCOMM Service", s, lightblue.RFCOMM)
>>> conn, addr = s.accept()
>>> print "Connected by", addr
Connected by ('00:0D:93:19:C8:68', 5)
>>> conn.recv(1024)
"hello"
>>> conn.close()
>>> s.close()
위에서 보다시피 표준 소켓 인터페이스를 사용하기 때문에 네트웍 프로그래밍과 별다른 차이가 없다.
OBEX를 사용해 파일을 전송하려면 다음과 같이 하면 된다.
# send a file (can pass file name or file object)
>>> lightblue.obex.sendfile("00:12:2c:45:8a:7b", 10, "MyFile.txt")
# receive a file and save it as MyFile.txt
>>> s = lightblue.socket()
>>> s.bind(("", 0))
>>> lightblue.advertise("My OBEX Service", s, lightblue.OBEX)
>>> lightblue.obex.recvfile(s, "MyFile.txt") # or pass file object instead
>>> s.close()
OBEX 클라이언트 세션을 실행하려면 다음과 같다.
# send a business card (vCard) to an Object Push service
>>> client = lightblue.obex.OBEXClient("00:12:2c:45:8a:7b", 10)
>>> client.connect()
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
>>> client.put({"name": "MyBusinessCard.vcf"}, file("MyBusinessCard.vcf", "r"))
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
>>> client.disconnect()
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
# get a directory listing from a File Transfer service
# (see examples/obex_ftp_client.py for a basic File Transfer client implementation)
>>> client = lightblue.obex.OBEXClient("00:12:2c:45:8a:7b", 15)
>>> ftp_target_uuid = '\xf9\xec{\xc4\x95<\x11\xd2\x98NRT\x00\xdc\x9e\t'
>>> client.connect({"target": ftp_target_uuid})
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={'connection-id': 327258,
'who': '\xf9\xec{\xc4\x95<\x11\xd2\x98NRT\x00\xdc\x9e\t'}>
>>> import StringIO
>>> dirlist = StringIO.StringIO()
>>> client.get({'type': 'x-obex/folder-listing'}, dirlist)
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={'length': 292}>
>>> dirlist.getvalue()
'<?xml version="1.0"?>\n<!DOCTYPE folder-listing SYSTEM
"obex-folder-listing.dtd"\n [ <!ATTLIST folder mem-type CDATA #IMPLIED>\n
<!ATTLIST folder label CDATA #IMPLIED> ]>\n<folder-listing version="1.0">\n
<folder name="C:" user-perm="RW" mem-type="DEV" label="Phone memory"/>\n</folder-listing>'
>>> client.disconnect()
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
로컬 디바이스의 정보를 얻으려면 다음과 같다.
>>> lightblue.gethostaddr()
'00:0F:3D:5F:20:F0'
>>> lightblue.finddevicename(lightblue.gethostaddr()) # get local device name
u'susebox'
>>> lightblue.gethostclass() # class of device
3670276
* LightBlue를 사용해서 맥을 Lego NXT에 연결시켜주는 프로그램도 나와 있다.
Python/Bluetooth Support for Lego Mindstorms NXT on Mac OS X
* 아뒤노에 블루투스를 연결하기 위해 현재 사용을 고려중인 모듈은 이것이다.BT2.0+EDR class 2 module로 시리얼 프로파일을 가지고 있기 때문에 전원과 Rx, Tx만 시리얼 포트에 연결해주면 되기 때문에 아주 쉽게 사용할 수 있다. 또한 저렴한 가격($19.5)이 최대 장점이다.
궁금한게 있습니다 lightblue.obex.sendfile("00:12:2c:45:8a:7b", 10, "MyFile.txt")여기서 포트번호는 10번으로 전부 같은건가요?
답글삭제