// MIT License // // Copyright (c) 2020 Alex Howarth // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. package tilt import ( "context" "log" "time" "github.com/JuulLabs-OSS/ble" "github.com/JuulLabs-OSS/ble/examples/lib/dev" "github.com/pkg/errors" ) // Scanner for Tilt devices type Scanner struct { devices Devices } // Devices stores discovered devices type Devices map[Color]Tilt // NewScanner returns a Scanner func NewScanner() *Scanner { return &Scanner{} } // Scan finds Tilt devices and times out after a duration func (s *Scanner) Scan(ctx context.Context, timeout time.Duration) error { s.devices = make(map[Color]Tilt) d, err := dev.NewDevice("go-tilt") if err != nil { return err } ble.SetDefaultDevice(d) ctx2 := ble.WithSigHandler(context.WithTimeout(ctx, timeout)) err = ble.Scan(ctx2, false, s.advHandler, advFilter) if err != nil { switch errors.Cause(err) { case nil: case context.DeadlineExceeded: // Finished scanning break case context.Canceled: break default: return err } } return err } func advFilter(a ble.Advertisement) bool { return IsTilt(a.ManufacturerData()) } func (s *Scanner) advHandler(a ble.Advertisement) { // create iBeacon b, err := NewIBeacon(a.ManufacturerData()) if err != nil { log.Println(err) return } // create Tilt from iBeacon t, err := NewTilt(b) if err != nil { log.Println(err) return } s.HandleTilt(t) } // HandleTilt adds a discovered Tilt to a map func (s *Scanner) HandleTilt(t Tilt) { s.devices[t.col] = t } // Tilts contains the found devices func (s *Scanner) Tilts() Devices { return s.devices }