gatt

package module
v0.0.0-...-e5f7072 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 28, 2014 License: BSD-3-Clause Imports: 15 Imported by: 2

README

Package gatt provides a Bluetooth Low Energy gatt implementation in Go.

Gatt (Generic Attribute Profile) is the protocol used to write BLE peripherals (servers) and centrals (clients).

Gatt is not ready for production use. The API is subject to change.

gatt is similar to bleno and noble, which offer BLE GATT implementations for node.js.

Please see godoc.org for documentation.

Gatt is released under a BSD-style license.

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

View Source
const (
	StatusSuccess         = attEcodeSuccess
	StatusInvalidOffset   = attEcodeInvalidOffset
	StatusUnexpectedError = attEcodeUnlikely
)

Supported statuses for GATT characteristic read/write operations.

View Source
const MaxEIRPacketLength = 31

MaxEIRPacketLength is the maximum allowed AdvertisingPacket and ScanResponsePacket length.

Variables

View Source
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.

func (BDAddr) Network

func (a BDAddr) Network() string

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

type NotifyHandler interface {
	ServeNotify(r Request, n Notifier)
}

A NotifyHandler handles GATT notification requests. Notifications can be sent using the provided notifier.

type NotifyHandlerFunc

type NotifyHandlerFunc func(r Request, n Notifier)

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 ReadResponseWriter interface {
	// Write writes data to return as the characteristic value.
	Write([]byte) (int, error)
	// SetStatus reports the result of the read operation. See the Status* constants.
	SetStatus(byte)
}

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

func (s *Server) AddService(u UUID) *Service

AddService registers a new Service with the server. All services must be added before starting the server.

func (*Server) AdvertiseAndServe

func (s *Server) AdvertiseAndServe() error

func (*Server) Close

func (s *Server) Close() error

Close stops a Server.

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.

func (*Service) UUID

func (s *Service) UUID() UUID

UUID returns the service's UUID.

type UUID

type UUID struct {
	// contains filtered or unexported fields
}

A UUID is a BLE UUID.

func MustParseUUID

func MustParseUUID(s string) UUID

MustParseUUID parses a standard-format UUID string, like ParseUUID, but panics in case of error.

func ParseUUID

func ParseUUID(s string) (UUID, error)

ParseUUID parses a standard-format UUID string, such as "1800" or "34DA3AD1-7110-41A1-B1EF-4430F509CDE7".

func UUID16

func UUID16(i uint16) UUID

UUID16 converts a uint16 (such as 0x1800) to a UUID.

func (UUID) Len

func (u UUID) Len() int

Len returns the length of the UUID, in bytes. BLE UUIDs are either 2 or 16 bytes.

func (UUID) String

func (u UUID) String() string

String hex-encodes a UUID.

type WriteHandler

type WriteHandler interface {
	ServeWrite(r Request, data []byte) (status byte)
}

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

type WriteHandlerFunc func(r Request, data []byte) byte

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).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL