prototooth/examples/nusserver/main.go
Ayke van Laethem 6c7d25c022
examples/nusserver: refactor terminal handling
The over-the-air newline format has been changed to LF always, for
simplicity. We might have used CR instead but LF works, and is the
newline format normally used on Unix (in files and stdio, except for raw
terminals).
2020-06-11 15:46:08 +02:00

96 lines
2.8 KiB
Go

package main
// This example implements a NUS (Nordic UART Service) peripheral.
// I can't find much official documentation on the protocol, but this can be
// helpful:
// https://learn.adafruit.com/introducing-adafruit-ble-bluetooth-low-energy-friend/uart-service
//
// Code to interact with a raw terminal is in separate files with build tags.
import (
"github.com/tinygo-org/bluetooth"
"github.com/tinygo-org/bluetooth/rawterm"
)
var (
serviceUUID = bluetooth.NewUUID([16]byte{0x6E, 0x40, 0x00, 0x01, 0xB5, 0xA3, 0xF3, 0x93, 0xE0, 0xA9, 0xE5, 0x0E, 0x24, 0xDC, 0xCA, 0x9E})
rxUUID = bluetooth.NewUUID([16]byte{0x6E, 0x40, 0x00, 0x02, 0xB5, 0xA3, 0xF3, 0x93, 0xE0, 0xA9, 0xE5, 0x0E, 0x24, 0xDC, 0xCA, 0x9E})
txUUID = bluetooth.NewUUID([16]byte{0x6E, 0x40, 0x00, 0x03, 0xB5, 0xA3, 0xF3, 0x93, 0xE0, 0xA9, 0xE5, 0x0E, 0x24, 0xDC, 0xCA, 0x9E})
)
func main() {
println("starting")
adapter := bluetooth.DefaultAdapter
must("enable BLE stack", adapter.Enable())
adv := adapter.DefaultAdvertisement()
must("config adv", adv.Configure(bluetooth.AdvertisementOptions{
LocalName: "NUS", // Nordic UART Service
ServiceUUIDs: []bluetooth.UUID{serviceUUID},
}))
must("start adv", adv.Start())
var rxChar bluetooth.Characteristic
var txChar bluetooth.Characteristic
must("add service", adapter.AddService(&bluetooth.Service{
UUID: serviceUUID,
Characteristics: []bluetooth.CharacteristicConfig{
{
Handle: &rxChar,
UUID: rxUUID,
Flags: bluetooth.CharacteristicWritePermission | bluetooth.CharacteristicWriteWithoutResponsePermission,
WriteEvent: func(client bluetooth.Connection, offset int, value []byte) {
txChar.Write(value)
for _, c := range value {
rawterm.Putchar(c)
}
},
},
{
Handle: &txChar,
UUID: txUUID,
Flags: bluetooth.CharacteristicNotifyPermission | bluetooth.CharacteristicReadPermission,
},
},
}))
rawterm.Configure()
defer rawterm.Restore()
print("NUS console enabled, use Ctrl-X to exit\r\n")
var line []byte
for {
ch := rawterm.Getchar()
rawterm.Putchar(ch)
line = append(line, ch)
// Send the current line to the central.
if ch == '\x18' {
// The user pressed Ctrl-X, exit the terminal.
break
} else if ch == '\n' {
sendbuf := line // copy buffer
// Reset the slice while keeping the buffer in place.
line = line[:0]
// Send the sendbuf after breaking it up in pieces.
for len(sendbuf) != 0 {
// Chop off up to 20 bytes from the sendbuf.
partlen := 20
if len(sendbuf) < 20 {
partlen = len(sendbuf)
}
part := sendbuf[:partlen]
sendbuf = sendbuf[partlen:]
// This also sends a notification.
_, err := txChar.Write(part)
must("send notification", err)
}
}
}
}
func must(action string, err error) {
if err != nil {
panic("failed to " + action + ": " + err.Error())
}
}