PicoRuby.wasm can use the browser’s Web Bluetooth API through JS::BLE::GATT and JS::BLE::UART.
Use JS::BLE::GATT when you want to work directly with BLE services and characteristics. Use JS::BLE::UART when your device exposes a UART-like service such as Nordic UART Service (NUS), or when you want a small IO-compatible wrapper around a pair of TX/RX characteristics.
Web Bluetooth is a browser API, so the usual browser restrictions apply:
- It works only in browsers that support Web Bluetooth.
- The page must be served from a secure context such as HTTPS or
localhost. - Device selection must start from a user gesture such as a button click.
- The browser shows its own device picker. Ruby code cannot silently choose a nearby device.
GATT
JS::BLE::GATT.request_device opens the browser picker and returns a Device wrapper. From there, connect to the GATT server, get a service, then get a characteristic.
require 'js'
button = JS.document.getElementById('connect')
log = JS.document.getElementById('log')
button.addEventListener('click') do |_event|
svc_uuid = '0xffe0'
char_uuid = '0xffe1'
$device = JS::BLE::GATT.request_device(optional_services: [svc_uuid])
server = $device.connect
service = server.service(svc_uuid)
$char = service.characteristic(char_uuid)
$char.on_change do |data|
log[:textContent] = log[:textContent].to_s + "notify: #{data.inspect}\n"
end
$char.start_notify
$char.write("hello")
$device.on_disconnected do
log[:textContent] = log[:textContent].to_s + "disconnected\n"
end
end
Characteristic values are Ruby String objects. They may contain binary bytes, so prefer bytes, bytesize, byteslice, or protocol-specific parsing instead of assuming UTF-8 text.
Useful methods:
JS::BLE::GATT.request_device(name:, name_prefix:, services:, optional_services:)device.connect,device.disconnect,device.connected?,device.on_disconnectedserver.service(uuid)service.characteristic(uuid)characteristic.read,characteristic.write(data, without_response:)characteristic.on_change,characteristic.start_notify,characteristic.stop_notify
UUID strings starting with 0x are converted to 16-bit UUID integers for Web Bluetooth. Full UUID strings and assigned-name strings are passed through as strings.
UART
JS::BLE::UART is a higher-level wrapper that connects, starts notifications, and stores incoming bytes in an internal receive buffer. By default it uses Nordic UART Service UUIDs.
require 'js'
button = JS.document.getElementById('connect-uart')
log = JS.document.getElementById('log')
button.addEventListener('click') do |_event|
$uart = JS::BLE::UART.new
log[:textContent] = "connected to #{$uart.device.name || '(unnamed)'}\n"
$uart.puts("hello")
Task.new do
while $uart.connected?
if $uart.available?
data = $uart.read_nonblock(64)
log[:textContent] = log[:textContent].to_s + "rx: #{data.inspect}\n" if data
end
sleep 0.05
end
end
end
For a device that uses one characteristic for both TX and RX, pass the same UUID to tx_uuid: and rx_uuid:.
$uart = JS::BLE::UART.new(
service_uuid: '0xffe0',
tx_uuid: '0xffe1',
rx_uuid: '0xffe1'
)
Useful methods:
JS::BLE::UART.new(service_uuid:, tx_uuid:, rx_uuid:, name:, name_prefix:)uart.write(data),uart.puts(data)uart.read(nbytes, timeout:),uart.gets(timeout:),uart.read_nonblock(nbytes)uart.available,uart.available?,uart.connected?,uart.close
Examples
The PicoRuby.wasm demo directory has working examples:
ble_demo.htmlshows direct GATT read, write, and notify.ble_uart_demo.htmlshows theJS::BLE::UARTwrapper.ble_irb_demo.htmlandble_ota_demo.htmlshow larger BLE UART workflows.