Documentation
¶
Overview ¶
Package gatt provides a Bluetooth Low Energy gatt implementation.
Gatt (Generic Attribute Profile) is the protocol used to write BLE peripherals (servers) and centrals (clients).
STATUS ¶
This package is a work in progress. The API will change.
Support for writing a peripheral is mostly done: You can create services and characteristics, advertise, accept connections, and handle requests. Central support is missing: Scan, connect, discover services and characteristics, make requests.
SETUP ¶
gatt only supports Linux, with BlueZ installed. This may change.
Installed the required packages, e.g.:
sudo apt-get install bluez libbluetooth-dev libcap2-bin
If you have BlueZ 5.14+ (or aren't sure), stop the built-in bluetooth server, which interferes with gatt, e.g.:
sudo service bluetooth stop
gatt uses two helper executables. The source for them is in the c directory. There's an included makefile. It currently assumes that your native compiler is gcc and that you want the executables in /usr/local/bin. If /usr/local/bin is not already in your PATH, add it. If you don't like those assumptions, edit the makefile. (TODO: Get someone with strong makefile-fu to help me clean this up.)
export PATH="$PATH:/usr/local/bin" cd $GOPATH/src/github.com/paypal/gatt/c make sudo make install
Root is required in the install phase to give hci-ble permissions to administer the network.
Make sure that your BLE device is up:
sudo hciconfig sudo hciconfig hci0 up # or whatever hci device you want to use
USAGE ¶
Gatt servers are constructed by creating a new server, adding services and characteristics, and then starting the server.
srv := &gatt.Server{Name: "gophergatt"}
svc := srv.AddService(gatt.MustParseUUID("09fc95c0-c111-11e3-9904-0002a5d5c51b"))
// Add a read characteristic that prints how many times it has been read
n := 0
rchar := svc.AddCharacteristic(gatt.MustParseUUID("11fac9e0-c111-11e3-9246-0002a5d5c51b"))
rchar.HandleRead(
gatt.ReadHandlerFunc(
func(resp gatt.ReadResponseWriter, req *gatt.ReadRequest) {
fmt.Fprintf(resp, "count: %d", n)
n++
}),
)
// Add a write characteristic that logs when written to
wchar := svc.AddCharacteristic(gatt.MustParseUUID("16fe0d80-c111-11e3-b8c8-0002a5d5c51b"))
wchar.HandleWriteFunc(
func(r gatt.Request, data []byte) (status byte) {
log.Println("Wrote:", string(data))
return gatt.StatusSuccess
})
// Add a notify characteristic that updates once a second
nchar := svc.AddCharacteristic(gatt.MustParseUUID("1c927b50-c116-11e3-8a33-0800200c9a66"))
nchar.HandleNotifyFunc(
func(r gatt.Request, n gatt.Notifier) {
go func() {
count := 0
for !n.Done() {
fmt.Fprintf(n, "Count: %d", count)
count++
time.Sleep(time.Second)
}
}()
})
// Start the server
log.Fatal(srv.AdvertiseAndServe())
See the rest of the docs for other options and finer-grained control.
Note that some BLE central devices, particularly iOS, may aggressively cache results from previous connections. If you change your services or characteristics, you may need to reboot the other device to pick up the changes. This is a common source of confusion and apparent bugs. For an OS X central, see http://stackoverflow.com/questions/20553957.
REFERENCES ¶
gatt started life as a port of bleno, to which it is indebted: https://github.com/sandeepmistry/bleno. If you are having problems with gatt, particularly around installation, issues filed with bleno might also be helpful references.
To try out your GATT server, it is useful to experiment with a generic BLE client. LightBlue is a good choice. It is available free for both iOS and OS X.
Index ¶
- Constants
- Variables
- type BDAddr
- type Characteristic
- func (c *Characteristic) HandleNotify(h NotifyHandler)
- func (c *Characteristic) HandleNotifyFunc(f func(r Request, n Notifier))
- func (c *Characteristic) HandleRead(h ReadHandler)
- func (c *Characteristic) HandleReadFunc(f func(resp ReadResponseWriter, req *ReadRequest))
- func (c *Characteristic) HandleWrite(h WriteHandler)
- func (c *Characteristic) HandleWriteFunc(f func(r Request, data []byte) (status byte))
- func (c *Characteristic) UUID() UUID
- type Conn
- type Notifier
- type NotifyHandler
- type NotifyHandlerFunc
- type ReadHandler
- type ReadHandlerFunc
- type ReadRequest
- type ReadResponseWriter
- type Request
- type Server
- type Service
- type UUID
- type WriteHandler
- type WriteHandlerFunc
Constants ¶
const ( StatusSuccess = attEcodeSuccess StatusInvalidOffset = attEcodeInvalidOffset StatusUnexpectedError = attEcodeUnlikely )
Supported statuses for GATT characteristic read/write operations.
const MaxEIRPacketLength = 31
MaxEIRPacketLength is the maximum allowed AdvertisingPacket and ScanResponsePacket length.
Variables ¶
var ErrEIRPacketTooLong = errors.New("max packet length is 31")
ErrEIRPacketTooLong is the error returned when an AdvertisingPacket or ScanResponsePacket is too long.
Functions ¶
This section is empty.
Types ¶
type BDAddr ¶
type BDAddr struct {
net.HardwareAddr
}
A BDAddr (Bluetooth Device Address) is a hardware-addressed-based net.Addr.
type Characteristic ¶
type Characteristic struct {
// contains filtered or unexported fields
}
A Characteristic is a BLE characteristic.
func (*Characteristic) HandleNotify ¶
func (c *Characteristic) HandleNotify(h NotifyHandler)
HandleNotify makes the characteristic support notify requests, and routes notification requests to h. HandleNotify must be called before any server using c has been started.
func (*Characteristic) HandleNotifyFunc ¶
func (c *Characteristic) HandleNotifyFunc(f func(r Request, n Notifier))
HandleNotifyFunc calls HandleNotify(NotifyHandlerFunc(f)).
func (*Characteristic) HandleRead ¶
func (c *Characteristic) HandleRead(h ReadHandler)
HandleRead makes the characteristic support read requests, and routes read requests to h. HandleRead must be called before any server using c has been started.
func (*Characteristic) HandleReadFunc ¶
func (c *Characteristic) HandleReadFunc(f func(resp ReadResponseWriter, req *ReadRequest))
HandleReadFunc calls HandleRead(ReadHandlerFunc(f)).
func (*Characteristic) HandleWrite ¶
func (c *Characteristic) HandleWrite(h WriteHandler)
HandleWrite makes the characteristic support write and write-no-response requests, and routes write requests to h. The WriteHandler does not differentiate between write and write-no-response requests; it is handled automatically. HandleWrite must be called before any server using c has been started.
func (*Characteristic) HandleWriteFunc ¶
func (c *Characteristic) HandleWriteFunc(f func(r Request, data []byte) (status byte))
HandleWriteFunc calls HandleWrite(WriteHandlerFunc(f)).
func (*Characteristic) UUID ¶
func (c *Characteristic) UUID() UUID
UUID returns the characteristic's UUID
type Conn ¶
type Conn interface {
// LocalAddr returns the address of the connected device (central).
LocalAddr() BDAddr
// LocalAddr returns the address of the local device (peripheral).
RemoteAddr() BDAddr
// Close disconnects the connection.
Close() error
// RSSI returns the last RSSI measurement, or -1 if there have not been any.
RSSI() int
// UpdateRSSI requests an RSSI update and blocks until one has been received.
// TODO: Implement.
UpdateRSSI() (rssi int, err error)
// MTU returns the current connection mtu.
MTU() int
}
Conn is a BLE connection. Due to the limitations of Bluetooth 4.0, there is only one active connection at a time; this will change in Bluetooth 4.1.
type Notifier ¶
type Notifier interface {
// Write sends data to the central.
Write(data []byte) (int, error)
// Done reports whether the central has requested not to
// receive any more notifications with this notifier.
Done() bool
// Cap returns the maximum number of bytes that may be sent
// in a single notification.
Cap() int
}
A Notifier provides a means for a GATT server to send notifications about value changes to a connected device. Notifiers are provided by NotifyHandlers.
type NotifyHandler ¶
A NotifyHandler handles GATT notification requests. Notifications can be sent using the provided notifier.
type NotifyHandlerFunc ¶
NotifyHandlerFunc is an adapter to allow the use of ordinary functions as NotifyHandlers. If f is a function with the appropriate signature, NotifyHandlerFunc(f) is a NotifyHandler that calls f.
func (NotifyHandlerFunc) ServeNotify ¶
func (f NotifyHandlerFunc) ServeNotify(r Request, n Notifier)
ServeNotify calls f(r, n).
type ReadHandler ¶
type ReadHandler interface {
ServeRead(resp ReadResponseWriter, req *ReadRequest)
}
A ReadHandler handles GATT read requests.
type ReadHandlerFunc ¶
type ReadHandlerFunc func(resp ReadResponseWriter, req *ReadRequest)
ReadHandlerFunc is an adapter to allow the use of ordinary functions as ReadHandlers. If f is a function with the appropriate signature, ReadHandlerFunc(f) is a ReadHandler that calls f.
func (ReadHandlerFunc) ServeRead ¶
func (f ReadHandlerFunc) ServeRead(resp ReadResponseWriter, req *ReadRequest)
ServeRead returns f(r, maxlen, offset).
type ReadRequest ¶
type ReadRequest struct {
Request
Cap int // maximum allowed reply length
Offset int // request value offset
}
A ReadRequest is a characteristic read request from a connected device.
type ReadResponseWriter ¶
type Request ¶
type Request struct {
Server *Server
Conn Conn
Service *Service
Characteristic *Characteristic
}
A Request is the context for a request from a connected device.
type Server ¶
type Server struct {
// Name is the device name, exposed via the Generic Access Service (0x1800).
// Name may not be changed while serving.
Name string
// HCI is the hci device to use, e.g. "hci1".
// If HCI is "", an hci device will be selected
// automatically.
HCI string
// AdvertisingPacket is an optional custom advertising packet.
// If nil, the advertising packet will constructed to advertise
// as many services as possible. AdvertisingPacket must be set,
// if at all, before starting the server. The AdvertisingPacket
// must be no longer than MaxAdvertisingPacketLength.
AdvertisingPacket []byte
// ScanResponsePacket is an optional custom scan response packet.
// If nil, the scan response packet will set to return the server
// name, truncated if necessary. ScanResponsePacket must be set,
// if at all, before starting the server. The ScanResponsePacket
// must be no longer than MaxAdvertisingPacketLength.
ScanResponsePacket []byte
// Connect is an optional callback function that will be called
// when a device has connected to the server.
Connect func(c Conn)
// Disconnect is an optional callback function that will be called
// when a device has disconnected from the server.
Disconnect func(c Conn)
// ReceiveRSSI is an optional callback function that will be called
// when an RSSI measurement has been received for a connection.
ReceiveRSSI func(c Conn, rssi int)
// Closed is an optional callback function that will be called
// when the server is closed. err will be any associated error.
// If the server was closed by calling Close, err may be nil.
Closed func(error)
// StateChange is an optional callback function that will be called
// when the server changes states.
// TODO: Break these states out into separate, meaningful methods?
// At least document them.
StateChange func(newState string)
// contains filtered or unexported fields
}
A Server is a GATT server. Servers are single-shot types; once a Server has been closed, it cannot be restarted. Instead, create a new Server. Only one server may be running at a time.
func (*Server) AddService ¶
AddService registers a new Service with the server. All services must be added before starting the server.
func (*Server) AdvertiseAndServe ¶
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
A Service is a BLE service. Calls to AddCharacteristic must occur before the service is used by a server.
func (*Service) AddCharacteristic ¶
func (s *Service) AddCharacteristic(u UUID) *Characteristic
AddCharacteristic adds a characteristic to a service. AddCharacteristic panics if the service already contains another characteristic with the same UUID.
type UUID ¶
type UUID struct {
// contains filtered or unexported fields
}
A UUID is a BLE UUID.
func MustParseUUID ¶
MustParseUUID parses a standard-format UUID string, like ParseUUID, but panics in case of error.
func ParseUUID ¶
ParseUUID parses a standard-format UUID string, such as "1800" or "34DA3AD1-7110-41A1-B1EF-4430F509CDE7".
type WriteHandler ¶
A WriteHandler handles GATT write requests. Write and WriteNR requests are presented identically; the server will ensure that a response is sent if appropriate.
type WriteHandlerFunc ¶
WriteHandlerFunc is an adapter to allow the use of ordinary functions as WriteHandlers. If f is a function with the appropriate signature, WriteHandlerFunc(f) is a WriteHandler that calls f.
func (WriteHandlerFunc) ServeWrite ¶
func (f WriteHandlerFunc) ServeWrite(r Request, data []byte) byte
ServeWrite returns f(r, data).