How to Read Raspberry Pico Temperature and Transmit it to a Browser using Web Bluetooth
GPT와 대화
ChatGPT - Pico Web Bluetooth Terminal
테스트 사이트
# ble_uart_peripheral.py
import bluetooth
import time
from ble_advertising import advertising_payload
from micropython import const
_UART_SERVICE_UUID = bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')
_UART_TX_CHAR_UUID = bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E') # Central에서 알림 받을 특성
_UART_RX_CHAR_UUID = bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E') # Central에서 쓰기 할 특성
_UART_TX = (
_UART_TX_CHAR_UUID,
bluetooth.FLAG_NOTIFY,
)
_UART_RX = (
_UART_RX_CHAR_UUID,
bluetooth.FLAG_WRITE,
)
_UART_SERVICE = (
_UART_SERVICE_UUID,
(_UART_TX, _UART_RX),
)
_IRQ_CENTRAL_CONNECT = const(1)
_IRQ_CENTRAL_DISCONNECT = const(2)
_IRQ_GATTS_WRITE = const(3)
class BLEUART:
def __init__(self, ble, name='Pico', rxbuf=100):
self._ble = ble
self._ble.active(True)
self._ble.irq(self._irq)
((self._tx_handle, self._rx_handle),) = self._ble.gatts_register_services((_UART_SERVICE,))
self._connections = set()
self._rx_buffer = bytearray()
self._handler = None
self._payload = advertising_payload(name=name, services=[_UART_SERVICE_UUID])
self._advertise()
def irq(self, handler):
self._handler = handler
def _irq(self, event, data):
if event == _IRQ_CENTRAL_CONNECT:
conn_handle, addr_type, addr = data
print('Connected', addr)
self._connections.add(conn_handle)
elif event == _IRQ_CENTRAL_DISCONNECT:
conn_handle, addr_type, addr = data
print('Disconnected', addr)
self._connections.remove(conn_handle)
self._advertise()
elif event == _IRQ_GATTS_WRITE:
conn_handle, value_handle = data
if value_handle == self._rx_handle:
msg = self._ble.gatts_read(self._rx_handle)
print('Received:', msg.decode().strip())
# 받은 데이터를 그대로 전송 (에코)
for conn_handle in self._connections:
self._ble.gatts_notify(conn_handle, self._tx_handle, msg)
def write(self, data):
for conn_handle in self._connections:
self._ble.gatts_notify(conn_handle, self._tx_handle, data)
def _advertise(self, interval_us=500000):
self._ble.gap_advertise(interval_us, adv_data=self._payload)
def demo():
ble = bluetooth.BLE()
uart = BLEUART(ble)
try:
while True:
time.sleep_ms(1000)
except KeyboardInterrupt:
pass
if __name__ == "__main__":
demo()
ble_advertising.py
# ble_advertising.py
import struct
from micropython import const
_ADV_TYPE_FLAGS = const(0x01)
_ADV_TYPE_NAME = const(0x09)
_ADV_TYPE_UUID16_COMPLETE = const(0x03)
_ADV_TYPE_UUID128_COMPLETE = const(0x07)
def advertising_payload(limited_disc=False, br_edr=False, name=None, services=None):
payload = bytearray()
# 플래그
flags = (0x02 if limited_disc else 0x06) + (0x00 if br_edr else 0x04)
payload += struct.pack('BB', 2, _ADV_TYPE_FLAGS)
payload += struct.pack('B', flags)
# 이름
if name:
name_bytes = name.encode('utf-8')
payload += struct.pack('BB', len(name_bytes) + 1, _ADV_TYPE_NAME)
payload += name_bytes
# 서비스 UUID
if services:
for uuid in services:
b = bytes(uuid)
if len(b) == 2:
payload += struct.pack('BB', len(b) + 1, _ADV_TYPE_UUID16_COMPLETE)
payload += b
elif len(b) == 16:
payload += struct.pack('BB', len(b) + 1, _ADV_TYPE_UUID128_COMPLETE)
payload += b
return payload