11.8. aioble 모듈¶
Bluetooth Core 사양은 두 개의 MicroPython 모듈에 대응되는 용어 체계를 제공합니다.
bluetooth– BLE 컨트롤러에 대한 저수준 바인딩. 동기식이며 IRQ 스타일 콜백을 통해 이벤트 기반으로 동작하고, 바이트 버퍼, 핸들, 그리고 기본 GATT 기본 요소를 중심으로 구성됩니다. 프로토콜을 Python 애플리케이션이 소비하고 싶어 하는 방식이 아니라 있는 그대로 노출합니다.aioble–bluetooth위에 Python으로 작성된 고수준 래퍼로, 모든 원격 작업을asyncio코루틴으로, 모든 BLE 객체(서비스, 특성, 연결, 스캔 결과, L2CAP 채널)를 사용하기 편한 Python 클래스로 바꿉니다. 스캔은 비동기 이터레이터가 되고, 연결은 비동기 컨텍스트 매니저가 되며, 알림은 await 가능해집니다.
11.8.1. 저수준 모듈을 찾아야 할 때¶
bluetooth 는 여전히 두 가지 좁은 경우에 적합한 답입니다:
aioble자체가 만들어진 것과 같은 종류의 코드, 즉 프로토콜에 대한 IRQ 수준 제어가 필요한 새로운 패턴을 작성하는 경우.aioble패키지를 사용할 수 없는 하드웨어 타깃에서 실행 중이며, 컨트롤러를 감싸는 얇은 심(shim)만이 유일한 선택지인 경우.
모든 카메라 애플리케이션에서는 aioble 이 적합한 답입니다.
11.8.2. aioble 프로그램의 구성 요소¶
모든 aioble 기반 애플리케이션은 어떤 역할을 수행하든 관계없이 소수의 움직이는 부분으로 이루어져 있습니다.
장시간 실행되는
asyncio이벤트 루프.aioble의 모든 것은 코루틴이므로, 애플리케이션은 단일 이벤트 루프상의 하나 이상의 작업으로 구성됩니다. 루프, 작업, 예외에 대한 자세한 내용은 Asyncio 를 참조하세요.켜져 있는 무선 장치.
aioble은 최초 사용 시 BLE 무선 장치를 암묵적으로 활성화하지만,aioble.config()(무선 장치가 켜져 있음을 보장한 후bluetooth.BLE.config()로 전달함)를 사용해 명시적으로 제어할 수도 있고,aioble.stop()으로 종료할 수도 있습니다.한 번에 진행 중인 하나 이상의 역할. peripheral 측에서는 등록된 GATT 서비스 집합(
aioble.register_services()참조)과 실행 중인aioble.advertise()코루틴이 있습니다. central 측에서는 실행 중인aioble.scan()이터레이터 또는 대기 중인aioble.Device.connect()가 있습니다. 라디오가 작업을 멀티플렉싱하며, 애플리케이션은 각 역할을 독립적인 작업으로 봅니다.
11.8.3. 최소 peripheral¶
가장 작으면서도 유용한 aioble 프로그램, 즉 하나의 읽기 전용 특성을 광고하는 peripheral은 짧습니다:
import aioble
import asyncio
import bluetooth
SERVICE_UUID = bluetooth.UUID(0x181A) # Environmental Sensing
TEMP_UUID = bluetooth.UUID(0x2A6E) # Temperature
service = aioble.Service(SERVICE_UUID)
temp = aioble.Characteristic(service, TEMP_UUID, read=True)
aioble.register_services(service)
async def main():
while True:
conn = await aioble.advertise(
interval_us=250000,
name="openmv-temp",
services=[SERVICE_UUID],
)
async with conn:
await conn.disconnected()
asyncio.run(main())
연결하고 한 번 읽는 것 외에는 아무것도 하지 않는 central도 마찬가지로 짧습니다:
import aioble
import asyncio
import bluetooth
SERVICE_UUID = bluetooth.UUID(0x181A)
TEMP_UUID = bluetooth.UUID(0x2A6E)
async def main():
device = None
async with aioble.scan(duration_ms=5000, active=True) as scanner:
async for result in scanner:
if SERVICE_UUID in result.services():
device = result.device
break
if device is None:
return
async with await device.connect() as conn:
service = await conn.service(SERVICE_UUID)
char = await service.characteristic(TEMP_UUID)
print(await char.read())
asyncio.run(main())
두 프로그램 모두 약 15줄이며 “라디오가 꺼져 있음”부터 “유용한 작업 완료”까지 전체 흐름을 다룹니다.
11.8.4. 라디오 끄기¶
배터리 구동 카메라에서 BLE 라디오는 예산상 가장 큰 재량적 소비 요소입니다. 두 가지 조절 장치가 중요합니다.
첫 번째는 암묵적입니다. aioble 은 최초 사용 시 라디오를 활성화하고, 라디오는 예약된 이벤트(광고 버스트, 연결 이벤트, 스캔 윈도우) 사이에 자동으로 잠듭니다. aioble.advertise() / aioble.scan() 에서 더 긴 간격을 선택하고 connect() 시점에 더 긴 연결 간격에 합의하면 라디오가 그만큼 더 많은 시간 동안 꺼진 상태로 유지됩니다. 광고와 스캔 의 광고 표가 여기서 실용적인 안내가 됩니다.
두 번째는 명시적 종료입니다:
import aioble
await do_burst_of_ble_work()
aioble.stop() # radio deactivated; in-flight tasks unwound
await asyncio.sleep(60) # sleep with the radio off
# ... next aioble call brings the radio back up automatically
aioble.stop() 은 기반 BLE 라디오를 비활성화하고 진행 중인 모든 것을 해제합니다. 열린 연결이 끊기고, 스캐너와 광고자가 취소되며, L2CAP 채널이 닫힙니다. 해당 작업을 기다리던 코루틴은 평소의 예외(DeviceDisconnectedError 등)를 발생시키는데, 이는 주변의 async with 블록이 작성된 정리 메커니즘입니다. 이후에 aioble 코루틴을 호출하면 라디오가 처음부터 다시 활성화됩니다.
주기적으로 동작하는 배터리 구동 센서 카메라의 전형적인 패턴은 다음과 같습니다:
일정에 따라 깨어납니다(타이머, 모션 센서, 버튼).
BLE 작업 버스트를 실행합니다. 광고하고, 연결을 수락하고, 값을 푸시하고, 연결을 해제합니다.
aioble.stop()을 호출하고 다음 깨어남까지 절전 모드로 들어갑니다.
11.8.5. aioble이 하지 않는 것¶
aioble 은 애플리케이션이 사용하는 계층인 GATT, GAP, L2CAP을 의도적으로 다룹니다. 세 가지는 범위를 벗어납니다:
링크 계층 아래의 모든 것. 채널 선택, 주파수 호핑, 패킷 확인 응답, 링크 계층 암호화는 모두 BLE 포트와 컨트롤러 실리콘 내부에서 일어납니다.
aioble은 그 수준의 훅을 노출하지 않습니다.클래식 Bluetooth.
aioble은 BLE 전용입니다. 오디오 링크, RFCOMM, A2DP 및 기타 클래식 프로파일 기능은 API의 일부가 아닙니다.Bluetooth Mesh. Bluetooth SIG의 메시 네트워킹 계층(BLE 광고 위의 별도 스택)은 카메라에 구현되어 있지 않습니다. 카메라는 광고하고 관찰할 수 있지만, 메시 네트워크의 릴레이 / 프렌드 / 프록시 역할에는 참여할 수 없습니다.
11.8.6. 예외¶
aioble 에서는 네 가지 예외 유형이 나옵니다. 각각은 무언가 잘못되었을 때 작업을 await하고 있던 코루틴 내부에서 발생합니다. 이들이 전파되면 async with 블록이 깔끔하게 해제됩니다.
aioble.DeviceDisconnectedError– GATT 작업(read,write,notified,indicated,subscribe,exchange_mtu등)이 진행 중일 때 피어로의 BLE 링크가 끊겼습니다. 대기 중이던 코루틴 내부에서 발생합니다. 단연코 가장 흔한 예외이므로, 손실 시 재연결해야 하는 모든 코드에서 이를 잡으세요.aioble.GattError– GATT 작업이 피어에 도달했지만 0이 아닌 ATT 상태로 완료되었습니다(응답 포함 write 거부, indicate 미확인, read 권한 없음 등). 상태 코드는 예외의_status속성에 있습니다.aioble.L2CAPDisconnectedError–send(),recvinto(), 또는flush()가 진행 중일 때 L2CAP 채널이 끊겼습니다. 어느 쪽이든 채널을 닫았거나, 기반 GAP 연결이 사라졌을 수 있습니다.aioble.L2CAPConnectionError– 리스너가 거부했거나 컨트롤러가 채널 설정에 실패했을 때l2cap_connect()에서 발생합니다. Bluetooth 상태 코드가 첫 번째 위치 인자입니다.
명시적 timeout_ms 를 받는 작업(connect / discovery / read / write / pair 호출 및 래퍼로서의 timeout())은 작업이 완료되기 전에 마감 시한이 경과하면 추가로 asyncio 의 asyncio.TimeoutError 를 발생시킵니다.