| package ble |
| |
| import ( |
| "bytes" |
| "context" |
| "io" |
| ) |
| |
| // A ReadHandler handles GATT requests. |
| type ReadHandler interface { |
| ServeRead(req Request, rsp ResponseWriter) |
| } |
| |
| // ReadHandlerFunc is an adapter to allow the use of ordinary functions as Handlers. |
| type ReadHandlerFunc func(req Request, rsp ResponseWriter) |
| |
| // ServeRead returns f(r, maxlen, offset). |
| func (f ReadHandlerFunc) ServeRead(req Request, rsp ResponseWriter) { |
| f(req, rsp) |
| } |
| |
| // A WriteHandler handles GATT requests. |
| type WriteHandler interface { |
| ServeWrite(req Request, rsp ResponseWriter) |
| } |
| |
| // WriteHandlerFunc is an adapter to allow the use of ordinary functions as Handlers. |
| type WriteHandlerFunc func(req Request, rsp ResponseWriter) |
| |
| // ServeWrite returns f(r, maxlen, offset). |
| func (f WriteHandlerFunc) ServeWrite(req Request, rsp ResponseWriter) { |
| f(req, rsp) |
| } |
| |
| // A NotifyHandler handles GATT requests. |
| type NotifyHandler interface { |
| ServeNotify(req Request, n Notifier) |
| } |
| |
| // NotifyHandlerFunc is an adapter to allow the use of ordinary functions as Handlers. |
| type NotifyHandlerFunc func(req Request, n Notifier) |
| |
| // ServeNotify returns f(r, maxlen, offset). |
| func (f NotifyHandlerFunc) ServeNotify(req Request, n Notifier) { |
| f(req, n) |
| } |
| |
| // Request ... |
| type Request interface { |
| Conn() Conn |
| Data() []byte |
| Offset() int |
| } |
| |
| // NewRequest returns a default implementation of Request. |
| func NewRequest(conn Conn, data []byte, offset int) Request { |
| return &request{conn: conn, data: data, offset: offset} |
| } |
| |
| // Default implementation of request. |
| type request struct { |
| conn Conn |
| data []byte |
| offset int |
| } |
| |
| func (r *request) Conn() Conn { return r.conn } |
| func (r *request) Data() []byte { return r.data } |
| func (r *request) Offset() int { return r.offset } |
| |
| // ResponseWriter ... |
| type ResponseWriter interface { |
| // Write writes data to return as the characteristic value. |
| Write(b []byte) (int, error) |
| |
| // Status reports the result of the request. |
| Status() ATTError |
| |
| // SetStatus reports the result of the request. |
| SetStatus(status ATTError) |
| |
| // Len ... |
| Len() int |
| |
| // Cap ... |
| Cap() int |
| } |
| |
| // NewResponseWriter ... |
| func NewResponseWriter(buf *bytes.Buffer) ResponseWriter { |
| return &responseWriter{buf: buf} |
| } |
| |
| // responseWriter implements Response |
| type responseWriter struct { |
| buf *bytes.Buffer |
| status ATTError |
| } |
| |
| // Status reports the result of the request. |
| func (r *responseWriter) Status() ATTError { |
| return r.status |
| } |
| |
| // SetStatus reports the result of the request. |
| func (r *responseWriter) SetStatus(status ATTError) { |
| r.status = status |
| } |
| |
| // Len returns length of the buffer. |
| // Len returns 0 if it is a dummy write response for WriteCommand. |
| func (r *responseWriter) Len() int { |
| if r.buf == nil { |
| return 0 |
| } |
| return r.buf.Len() |
| } |
| |
| // Cap returns capacity of the buffer. |
| // Cap returns 0 if it is a dummy write response for WriteCommand. |
| func (r *responseWriter) Cap() int { |
| if r.buf == nil { |
| return 0 |
| } |
| return r.buf.Cap() |
| } |
| |
| // Write writes data to return as the characteristic value. |
| // Cap returns 0 with error set to ErrReqNotSupp if it is a dummy write response for WriteCommand. |
| func (r *responseWriter) Write(b []byte) (int, error) { |
| if r.buf == nil { |
| return 0, ErrReqNotSupp |
| } |
| if len(b) > r.buf.Cap()-r.buf.Len() { |
| return 0, io.ErrShortWrite |
| } |
| |
| return r.buf.Write(b) |
| } |
| |
| // Notifier ... |
| type Notifier interface { |
| // Context sends data to the central. |
| Context() context.Context |
| |
| // Write sends data to the central. |
| Write(b []byte) (int, error) |
| |
| // Close ... |
| Close() error |
| |
| // Cap returns the maximum number of bytes that may be sent in a single notification. |
| Cap() int |
| } |
| |
| type notifier struct { |
| ctx context.Context |
| maxlen int |
| cancel func() |
| send func([]byte) (int, error) |
| } |
| |
| // NewNotifier ... |
| func NewNotifier(send func([]byte) (int, error)) Notifier { |
| n := ¬ifier{} |
| n.ctx, n.cancel = context.WithCancel(context.Background()) |
| n.send = send |
| // n.maxlen = cap |
| return n |
| } |
| |
| func (n *notifier) Context() context.Context { |
| return n.ctx |
| } |
| |
| func (n *notifier) Write(b []byte) (int, error) { |
| return n.send(b) |
| } |
| |
| func (n *notifier) Close() error { |
| n.cancel() |
| return nil |
| } |
| |
| func (n *notifier) Cap() int { |
| return n.maxlen |
| } |