188 lines
4.1 KiB
Go
188 lines
4.1 KiB
Go
|
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
|
||
|
}
|