Example #1
0
// NewEchoChar ...
func NewEchoChar() *ble.Characteristic {
	e := &echoChar{m: make(map[string]chan []byte)}
	c := ble.NewCharacteristic(EchoCharUUID)
	c.HandleWrite(ble.WriteHandlerFunc(e.written))
	c.HandleNotify(ble.NotifyHandlerFunc(e.echo))
	c.HandleIndicate(ble.NotifyHandlerFunc(e.echo))
	return c
}
Example #2
0
// 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
}
Example #3
0
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
}