package main // BLE scanner example. // Scans for nearby BLE devices and shows their names, addresses and signal // strength (RSSI) on the display. Press button A to clear the list. import ( "image/color" "machine" "strconv" "time" "github.com/tinygo-org/bluetooth" "tinygo.org/x/drivers/st7789" "tinygo.org/x/tinyfont" "tinygo.org/x/tinyfont/freesans" ) const maxDevices = 5 type bleDevice struct { name string addr string rssi int16 } var ( adapter = bluetooth.DefaultAdapter display st7789.Device devices [maxDevices]bleDevice count int ) var ( black = color.RGBA{0, 0, 0, 255} cyan = color.RGBA{0, 200, 255, 255} white = color.RGBA{255, 255, 255, 255} yellow = color.RGBA{255, 220, 0, 255} green = color.RGBA{0, 220, 100, 255} gray = color.RGBA{150, 150, 150, 255} ) func main() { initDisplay() btnA := machine.P1_06 btnA.Configure(machine.PinConfig{Mode: machine.PinInputPullup}) must("enable BLE", adapter.Enable()) drawHeader() // scan runs in a goroutine; found devices are stored and displayed in the main loop go func() { adapter.Scan(func(a *bluetooth.Adapter, result bluetooth.ScanResult) { name := result.LocalName() if name == "" { name = result.Address.String() } // update existing entry if already seen, otherwise add new found := false for i := 0; i < count; i++ { if devices[i].addr == result.Address.String() { devices[i].rssi = result.RSSI found = true break } } if !found && count < maxDevices { devices[count] = bleDevice{ name: name, addr: result.Address.String(), rssi: result.RSSI, } count++ } }) }() for { // button A clears the list if !btnA.Get() { count = 0 display.FillRectangle(0, 32, 240, 103, black) time.Sleep(200 * time.Millisecond) } drawDevices() time.Sleep(500 * time.Millisecond) } } func initDisplay() { machine.SPI0.Configure(machine.SPIConfig{ SCK: machine.P1_01, SDO: machine.P1_02, Frequency: 8000000, Mode: 0, }) display = st7789.New(machine.SPI0, machine.P1_15, machine.P1_13, machine.P0_10, machine.P0_09) display.Configure(st7789.Config{ Rotation: st7789.ROTATION_90, Width: 135, Height: 240, RowOffset: 40, ColumnOffset: 53, }) display.FillScreen(black) } func drawHeader() { tinyfont.WriteLine(&display, &freesans.Bold12pt7b, 10, 24, "BLE Scanner", cyan) } func drawDevices() { // clear device list area display.FillRectangle(0, 32, 240, 103, black) if count == 0 { tinyfont.WriteLine(&display, &freesans.Regular9pt7b, 10, 55, "No devices found...", gray) return } for i := 0; i < count; i++ { y := int16(52 + i*20) name := devices[i].name if len(name) > 16 { name = name[:16] } rssi := " " + strconv.Itoa(int(devices[i].rssi)) + "dB" // color by signal strength c := white if devices[i].rssi > -60 { c = green } else if devices[i].rssi > -80 { c = yellow } tinyfont.WriteLine(&display, &freesans.Regular9pt7b, 5, y, name+rssi, c) } } func must(action string, err error) { if err != nil { panic("failed to " + action + ": " + err.Error()) } }