prototooth/examples/nusserver/main.go
deadprogram 97532eaed4 domain: use custom domain for go.mod and examples
Signed-off-by: deadprogram <ron@hybridgroup.com>
2020-09-09 16:04:40 +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 (
"tinygo.org/x/bluetooth"
"tinygo.org/x/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())
}
}