// NewCountChar ... func NewCountChar() *ble.Characteristic { n := 0 c := ble.NewCharacteristic(CountCharUUID) c.HandleRead(ble.ReadHandlerFunc(func(req ble.Request, rsp ble.ResponseWriter) { fmt.Fprintf(rsp, "count: Read %d", n) log.Printf("count: Read %d", n) n++ })) c.HandleWrite(ble.WriteHandlerFunc(func(req ble.Request, rsp ble.ResponseWriter) { log.Printf("count: Wrote %s", string(req.Data())) })) c.HandleNotify(ble.NotifyHandlerFunc(func(req ble.Request, n ble.Notifier) { cnt := 0 log.Printf("count: Notification subscribed") for { select { case <-n.Context().Done(): log.Printf("count: Notification unsubscribed") return case <-time.After(time.Second): log.Printf("count: Notify: %d", cnt) if _, err := fmt.Fprintf(n, "Count: %d", cnt); err != nil { // Client disconnected prematurely before unsubscription. log.Printf("count: Failed to notify : %s", err) return } cnt++ } } })) c.HandleIndicate(ble.NotifyHandlerFunc(func(req ble.Request, n ble.Notifier) { cnt := 0 log.Printf("count: Indication subscribed") for { select { case <-n.Context().Done(): log.Printf("count: Indication unsubscribed") return case <-time.After(time.Second): log.Printf("count: Indicate: %d", cnt) if _, err := fmt.Fprintf(n, "Count: %d", cnt); err != nil { // Client disconnected prematurely before unsubscription. log.Printf("count: Failed to indicate : %s", err) return } cnt++ } } })) return c }
func newCCCD(c *ble.Characteristic) *ble.Descriptor { d := ble.NewDescriptor(ble.ClientCharacteristicConfigUUID) d.HandleRead(ble.ReadHandlerFunc(func(req ble.Request, rsp ble.ResponseWriter) { cccs := req.Conn().(*conn).cccs ccc := cccs[c.Handle] binary.Write(rsp, binary.LittleEndian, ccc) })) d.HandleWrite(ble.WriteHandlerFunc(func(req ble.Request, rsp ble.ResponseWriter) { cn := req.Conn().(*conn) old := cn.cccs[c.Handle] ccc := binary.LittleEndian.Uint16(req.Data()) oldNotify := old&cccNotify != 0 oldIndicate := old&cccIndicate != 0 newNotify := ccc&cccNotify != 0 newIndicate := ccc&cccIndicate != 0 if newNotify && !oldNotify { if c.Property&ble.CharNotify == 0 { rsp.SetStatus(ble.ErrUnlikely) return } send := func(b []byte) (int, error) { return cn.svr.notify(c.ValueHandle, b) } cn.nn[c.Handle] = ble.NewNotifier(send) go c.NotifyHandler.ServeNotify(req, cn.nn[c.Handle]) } if !newNotify && oldNotify { cn.nn[c.Handle].Close() } if newIndicate && !oldIndicate { if c.Property&ble.CharIndicate == 0 { rsp.SetStatus(ble.ErrUnlikely) return } send := func(b []byte) (int, error) { return cn.svr.indicate(c.ValueHandle, b) } cn.in[c.Handle] = ble.NewNotifier(send) go c.IndicateHandler.ServeNotify(req, cn.in[c.Handle]) } if !newIndicate && oldIndicate { cn.in[c.Handle].Close() } cn.cccs[c.Handle] = ccc })) return d }
// NewBatteryService ... func NewBatteryService() *ble.Service { lv := byte(100) s := ble.NewService(ble.UUID16(0x180F)) c := s.NewCharacteristic(ble.UUID16(0x2A19)) c.HandleRead( ble.ReadHandlerFunc(func(req ble.Request, rsp ble.ResponseWriter) { rsp.Write([]byte{lv}) lv-- })) // Characteristic User Description c.NewDescriptor(ble.UUID16(0x2901)).SetValue([]byte("Battery level between 0 and 100 percent")) // Characteristic Presentation Format c.NewDescriptor(ble.UUID16(0x2904)).SetValue([]byte{4, 1, 39, 173, 1, 0, 0}) return s }