gatt package - github.com/paypal/gatt - Go Packages (original) (raw)
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.
As a peripheral, you can create services, characteristics, and descriptors, advertise, accept connections, and handle requests. As a central, you can scan, connect, discover services, and make requests.
SETUP ¶
gatt supports both Linux and OS X.
On Linux: To gain complete and exclusive control of the HCI device, gatt uses HCI_CHANNEL_USER (introduced in Linux v3.14) instead of HCI_CHANNEL_RAW. Those who must use an older kernel may patch in these relevant commits from Marcel Holtmann:
Bluetooth: Introduce new HCI socket channel for user operation Bluetooth: Introduce user channel flag for HCI devices Bluetooth: Refactor raw socket filter into more readable code
Note that because gatt uses HCI_CHANNEL_USER, once gatt has opened the device no other program may access it.
Before starting a gatt program, make sure that your BLE device is down:
sudo hciconfig sudo hciconfig hci0 down # or whatever hci device you want to use
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
Because gatt programs administer network devices, they must either be run as root, or be granted appropriate capabilities:
sudo
OR
sudo setcap 'cap_net_raw,cap_net_admin=eip'
USAGE
Start a simple server.
sudo go run example/server.go
Discover surrounding peripherals.
sudo go run example/discoverer.go
Connect to and explorer a peripheral device.
sudo go run example/explorer.go
See the server.go, discoverer.go, and explorer.go in the examples/ directory for writing server or client programs that run on Linux and OS X.
Users, especially on Linux platforms, seeking finer-grained control over the devices can see the examples/server_lnx.go for the usage of Option, which are platform specific.
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.
- func (a *AdvPacket) AppendField(typ byte, b []byte) *AdvPacket
- func (a *AdvPacket) AppendFlags(f byte) *AdvPacket
- func (a *AdvPacket) AppendManufacturerData(id uint16, b []byte) *AdvPacket
- func (a *AdvPacket) AppendName(n string) *AdvPacket
- func (a *AdvPacket) AppendUUIDFit(uu []UUID) bool
- func (a *AdvPacket) Bytes() [31]byte
- func (a *AdvPacket) Len() int
- func (c *Characteristic) AddDescriptor(u UUID) *Descriptor
- func (c *Characteristic) Descriptor() *Descriptor
- func (c *Characteristic) Descriptors() []*Descriptor
- func (c *Characteristic) EndHandle() uint16
- func (c *Characteristic) Handle() uint16
- 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(rsp ResponseWriter, req *ReadRequest))
- func (c *Characteristic) HandleWrite(h WriteHandler)
- func (c *Characteristic) HandleWriteFunc(f func(r Request, data []byte) (status byte))
- func (c *Characteristic) Name() string
- func (c *Characteristic) Properties() Property
- func (c *Characteristic) Service() *Service
- func (c *Characteristic) SetDescriptor(cccd *Descriptor)
- func (c *Characteristic) SetDescriptors(descs []*Descriptor)
- func (c *Characteristic) SetEndHandle(endh uint16)
- func (c *Characteristic) SetHandle(h uint16)
- func (c *Characteristic) SetVHandle(vh uint16)
- func (c *Characteristic) SetValue(b []byte)
- func (c *Characteristic) UUID() UUID
- func (c *Characteristic) VHandle() uint16
- func (d *Descriptor) Characteristic() *Characteristic
- func (d *Descriptor) Handle() uint16
- func (d *Descriptor) HandleRead(h ReadHandler)
- func (d *Descriptor) HandleReadFunc(f func(rsp ResponseWriter, req *ReadRequest))
- func (d *Descriptor) HandleWrite(h WriteHandler)
- func (d *Descriptor) HandleWriteFunc(f func(r Request, data []byte) (status byte))
- func (d *Descriptor) Name() string
- func (d *Descriptor) SetHandle(h uint16)
- func (d *Descriptor) SetValue(b []byte)
- func (d *Descriptor) UUID() UUID
- func LnxDeviceID(n int, chk bool) Option
- func LnxMaxConnections(n int) Option
- func LnxSendHCIRawCommand(c cmd.CmdParam, rsp io.Writer) Option
- func LnxSetAdvertisingData(c *cmd.LESetAdvertisingData) Option
- func LnxSetAdvertisingEnable(en bool) Option
- func LnxSetAdvertisingParameters(c *cmd.LESetAdvertisingParameters) Option
- func LnxSetScanResponseData(c *cmd.LESetScanResponseData) Option
- func (s *Service) AddCharacteristic(u UUID) *Characteristic
- func (s *Service) Characteristics() []*Characteristic
- func (s *Service) EndHandle() uint16
- func (s *Service) Handle() uint16
- func (s *Service) Name() string
- func (s *Service) SetCharacteristics(chars []*Characteristic)
- func (s *Service) SetEndHandle(endh uint16)
- func (s *Service) SetHandle(h uint16)
- func (s *Service) UUID() UUID
const ( StatusSuccess = 0 StatusInvalidOffset = 1 StatusUnexpectedError = 2 )
Supported statuses for GATT characteristic read/write operations. These correspond to att constants in the BLE spec
MaxEIRPacketLength is the maximum allowed AdvertisingPacket and ScanResponsePacket length.
ErrEIRPacketTooLong is the error returned when an AdvertisingPacket or ScanResponsePacket is too long.
This section is empty.
type AdvPacket struct {
}
AdvPacket is an utility to help crafting advertisment or scan response data.
AppendField appends a BLE advertising packet field. TODO: refuse to append field if it'd make the packet too long.
func (a *AdvPacket) AppendFlags(f byte) *AdvPacket
AppendFlags appends a flag field to the packet.
AppendManufacturerData appends a manufacturer data field to the packet.
AppendFlags appends a name field to the packet. If the name fits in the space, it will be append as a complete name field, otherwise a short name field.
func (a *AdvPacket) AppendUUIDFit(uu []UUID) bool
AppendUUIDFit appends a BLE advertised service UUID packet field if it fits in the packet, and reports whether the UUID fit.
func (a *AdvPacket) Bytes() [31]byte
Bytes returns an 31-byte array, which contains up to 31 bytes of the packet.
Len returns the length of the packets with a maximum of 31.
type Advertisement struct { LocalName string ManufacturerData []byte ServiceData []ServiceData Services []UUID OverflowService []UUID TxPowerLevel int Connectable bool SolicitedService []UUID }
This is borrowed from core bluetooth. Embedded/Linux folks might be interested in more details.
Central is the interface that represent a remote central device.
type Characteristic struct {
}
A Characteristic is a BLE characteristic.
NewCharacteristic creates and returns a Characteristic.
func (c *Characteristic) AddDescriptor(u UUID) *Descriptor
AddDescriptor adds a descriptor to a characteristic. AddDescriptor panics if the characteristic already contains another descriptor with the same UUID.
func (c *Characteristic) Descriptor() *Descriptor
Descriptor returns the Descriptor of the characteristic.
func (c Characteristic) Descriptors() []Descriptor
Descriptors returns the contained descriptors of this characteristic.
func (*Characteristic) EndHandle ¶
EndHandle returns the End Handle of the characteristic.
func (*Characteristic) Handle ¶
Handle returns the Handle of the 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 the containing service is added to a server.
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 the containing service is added to a server. HandleRead panics if the characteristic has been configured with a static value.
func (*Characteristic) HandleReadFunc ¶
func (c *Characteristic) HandleReadFunc(f func(rsp ResponseWriter, 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 the containing service is added to a server.
func (*Characteristic) HandleWriteFunc ¶
func (c *Characteristic) HandleWriteFunc(f func(r Request, data []byte) (status byte))
HandleWriteFunc calls HandleWrite(WriteHandlerFunc(f)).
Name returns the specificatin name of the characteristic. If the UUID is not assigned, Name returns empty string.
func (c *Characteristic) Properties() Property
Properties returns the properties of this characteristic.
func (c *Characteristic) Service() *Service
Service returns the containing service of this characteristic.
func (c *Characteristic) SetDescriptor(cccd *Descriptor)
SetDescriptor sets the Descriptor of the characteristic.
func (c Characteristic) SetDescriptors(descs []Descriptor)
SetDescriptors sets the list of Descriptor of the characteristic.
func (*Characteristic) SetEndHandle ¶
SetEndHandle sets the End Handle of the characteristic.
func (*Characteristic) SetHandle ¶
SetHandle sets the Handle of the characteristic.
func (*Characteristic) SetVHandle ¶
SetVHandle sets the Value Handle of the characteristic.
func (c *Characteristic) SetValue(b []byte)
SetValue makes the characteristic support read requests, and returns a static value. SetValue must be called before the containing service is added to a server. SetValue panics if the characteristic has been configured with a ReadHandler.
func (c *Characteristic) UUID() UUID
UUID returns the UUID of the characteristic.
func (*Characteristic) VHandle ¶
VHandle returns the Value Handle of the characteristic.
type Descriptor struct {
}
Descriptor is a BLE descriptor
NewDescriptor creates and returns a Descriptor.
func (d *Descriptor) Characteristic() *Characteristic
Characteristic returns the containing characteristic of the descriptor.
func (*Descriptor) Handle ¶
Handle returns the Handle of the descriptor.
func (*Descriptor) HandleRead ¶
func (d *Descriptor) HandleRead(h ReadHandler)
HandleRead makes the descriptor support read requests, and routes read requests to h. HandleRead must be called before the containing service is added to a server. HandleRead panics if the descriptor has been configured with a static value.
func (*Descriptor) HandleReadFunc ¶
func (d *Descriptor) HandleReadFunc(f func(rsp ResponseWriter, req *ReadRequest))
HandleReadFunc calls HandleRead(ReadHandlerFunc(f)).
func (*Descriptor) HandleWrite ¶
func (d *Descriptor) HandleWrite(h WriteHandler)
HandleWrite makes the descriptor 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 the containing service is added to a server.
func (*Descriptor) HandleWriteFunc ¶
func (d *Descriptor) HandleWriteFunc(f func(r Request, data []byte) (status byte))
HandleWriteFunc calls HandleWrite(WriteHandlerFunc(f)).
Name returns the specificatin name of the descriptor. If the UUID is not assigned, returns an empty string.
func (*Descriptor) SetHandle ¶
SetHandle sets the Handle of the descriptor.
func (d *Descriptor) SetValue(b []byte)
SetValue makes the descriptor support read requests, and returns a static value. SetValue must be called before the containing service is added to a server. SetValue panics if the descriptor has already configured with a ReadHandler.
func (d *Descriptor) UUID() UUID
UUID returns the UUID of the descriptor.
type Device interface { Init(stateChanged func(Device, State)) error
Advertise(a *[AdvPacket](#AdvPacket)) [error](/builtin#error)
AdvertiseNameAndServices(name [string](/builtin#string), ss [][UUID](#UUID)) [error](/builtin#error)
AdvertiseIBeaconData(b [][byte](/builtin#byte)) [error](/builtin#error)
AdvertiseIBeacon(u [UUID](#UUID), major, minor [uint16](/builtin#uint16), pwr [int8](/builtin#int8)) [error](/builtin#error)
StopAdvertising() [error](/builtin#error)
RemoveAllServices() [error](/builtin#error)
AddService(s *[Service](#Service)) [error](/builtin#error)
SetServices(ss []*[Service](#Service)) [error](/builtin#error)
Scan(ss [][UUID](#UUID), dup [bool](/builtin#bool))
StopScanning()
Connect(p [Peripheral](#Peripheral))
CancelConnection(p [Peripheral](#Peripheral))
Handle(h ...[Handler](#Handler))
Option(o ...[Option](#Option)) [error](/builtin#error)}
Device defines the interface for a BLE device. Since an interface can't define fields(properties). To implement the callback support for cerntain events, deviceHandler is defined and implementation of Device on different platforms should embed it in order to keep have keep compatible in API level. Package users can use the Handler to set these handlers.
func NewDevice(opts ...Option) (Device, error)
type Handler ¶
type Handler func(Device)
A Handler is a self-referential function, which registers the options specified. See http://commandcenter.blogspot.com.au/2014/01/self-referential-functions-and-design.html for more discussion.
func CentralConnected(f func(Central)) Handler
CentralConnected returns a Handler, which sets the specified function to be called when a device connects to the server.
func CentralDisconnected(f func(Central)) Handler
CentralDisconnected returns a Handler, which sets the specified function to be called when a device disconnects from the server.
func PeripheralConnected(f func(Peripheral, error)) Handler
PeripheralConnected returns a Handler, which sets the specified function to be called when a remote peripheral device connects.
func PeripheralDisconnected(f func(Peripheral, error)) Handler
PeripheralDisconnected returns a Handler, which sets the specified function to be called when a remote peripheral device disconnects.
func PeripheralDiscovered(f func(Peripheral, *Advertisement, int)) Handler
PeripheralDiscovered returns a Handler, which sets the specified function to be called when a remote peripheral device is found during scan procedure.
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).
An Option is a self-referential function, which sets the option specified. Most Options are platform-specific, which gives more fine-grained control over the device at a cost of losing portibility. See http://commandcenter.blogspot.com.au/2014/01/self-referential-functions-and-design.html for more discussion.
LnxDeviceID specifies which HCI device to use. If n is set to -1, all the available HCI devices will be probed. If chk is set to true, LnxDeviceID checks the LE support in the feature list of the HCI device. This is to filter devices that does not support LE. In case some LE driver that doesn't correctly set the LE support in its feature list, user can turn off the check. This option can only be used with NewDevice on Linux implementation.
NewDevice(LnxDeviceID(-1, true)) // Can only be used with NewDevice.
func LnxMaxConnections(n int) Option
LnxMaxConnections is an optional parameter. If set, it overrides the default max connections supported. This option can only be used with NewDevice on Linux implementation.
NewDevice(LnxMaxConnections(1)) // Can only be used with NewDevice.
func LnxSendHCIRawCommand ¶
LnxSendHCIRawCommand sends a raw command to the HCI device This option can be used with NewDevice or Option on Linux implementation.
// customCmd implements cmd.CmdParam as a fake vendor command. // // type customCmd struct{ ConnectionHandle uint16 } // // func (c customCmd) Opcode() int { return 0xFC01 } // func (c customCmd) Len() int { return 3 } // func (c customCmd) Marshal(b []byte) { // []byte{ // byte(c.ConnectionHandle), // byte(c.ConnectionHandle >> 8), // 0xff, // } // } // Send a custom vendor command without checking response. c := &customCmd{ConnectionHandle: 0x40} d, _ := NewDevice() d.Option(LnxSendHCIRawCommand(c, nil)) // Can only be used with Option
// Send a predefined command of cmd package. c := &cmd.LESetScanResponseData{ ScanResponseDataLength: 8, ScanResponseData: [31]byte{0x07, 0x09, 'G', 'o', 'p', 'h', 'e', 'r'}, } rsp := bytes.NewBuffer(nil) d, _ := NewDevice() d.Option(LnxSendHCIRawCommand(c, rsp)) // Can only be used with Option // Check the return status if rsp.Bytes()[0] != 0x00 { // Handle errors }
LnxSetAdvertisingData sets the advertising data to the HCI device. This option can be used with NewDevice or Option on Linux implementation.
func LnxSetAdvertisingEnable(en bool) Option
LnxSetAdvertisingEnable sets the advertising data to the HCI device. This option can be used with Option on Linux implementation.
d, _ := NewDevice() d.Option(LnxSetAdvertisingEnable(true)) // Can only be used with Option.
LnxSetAdvertisingParameters sets the advertising parameters to the HCI device. This option can be used with NewDevice or Option on Linux implementation.
o := LnxSetAdvertisingParameters(&cmd.LESetAdvertisingParameters{ AdvertisingIntervalMin: 0x800, // [0x0800]: 0.625 ms * 0x0800 = 1280.0 ms AdvertisingIntervalMax: 0x800, // [0x0800]: 0.625 ms * 0x0800 = 1280.0 ms AdvertisingType: 0x00, // [0x00]: ADV_IND, 0x01: DIRECT(HIGH), 0x02: SCAN, 0x03: NONCONN, 0x04: DIRECT(LOW) OwnAddressType: 0x00, // [0x00]: public, 0x01: random DirectAddressType: 0x00, // [0x00]: public, 0x01: random DirectAddress: [6]byte{}, // Public or Random Address of the device to be connected AdvertisingChannelMap: 0x7, // [0x07] 0x01: ch37, 0x02: ch38, 0x04: ch39 AdvertisingFilterPolicy: 0x00, }) d, _ := NewDevice(o) // Can be used with NewDevice. d.Option(o) // Or dynamically with Option.
LnxSetScanResponseData sets the scan response data to the HXI device. This option can be used with NewDevice or Option on Linux implementation.
// Manually crafting a scan response data packet with a name field. o := LnxSetScanResponseData(&cmd.LESetScanResponseData{ ScanResponseDataLength: 8, ScanResponseData: [31]byte{0x07, 0x09, 'G', 'o', 'p', 'h', 'e', 'r'}, }) d, _ := NewDevice(o) d.Option(o)
type Peripheral interface {
Device() [Device](#Device)
ID() [string](/builtin#string)
Name() [string](/builtin#string)
Services() []*[Service](#Service)
DiscoverServices(s [][UUID](#UUID)) ([]*[Service](#Service), [error](/builtin#error))
DiscoverIncludedServices(ss [][UUID](#UUID), s *[Service](#Service)) ([]*[Service](#Service), [error](/builtin#error))
DiscoverCharacteristics(c [][UUID](#UUID), s *[Service](#Service)) ([]*[Characteristic](#Characteristic), [error](/builtin#error))
DiscoverDescriptors(d [][UUID](#UUID), c *[Characteristic](#Characteristic)) ([]*[Descriptor](#Descriptor), [error](/builtin#error))
ReadCharacteristic(c *[Characteristic](#Characteristic)) ([][byte](/builtin#byte), [error](/builtin#error))
ReadLongCharacteristic(c *[Characteristic](#Characteristic)) ([][byte](/builtin#byte), [error](/builtin#error))
ReadDescriptor(d *[Descriptor](#Descriptor)) ([][byte](/builtin#byte), [error](/builtin#error))
WriteCharacteristic(c *[Characteristic](#Characteristic), b [][byte](/builtin#byte), noRsp [bool](/builtin#bool)) [error](/builtin#error)
WriteDescriptor(d *[Descriptor](#Descriptor), b [][byte](/builtin#byte)) [error](/builtin#error)
SetNotifyValue(c *[Characteristic](#Characteristic), f func(*[Characteristic](#Characteristic), [][byte](/builtin#byte), [error](/builtin#error))) [error](/builtin#error)
SetIndicateValue(c *[Characteristic](#Characteristic), f func(*[Characteristic](#Characteristic), [][byte](/builtin#byte), [error](/builtin#error))) [error](/builtin#error)
ReadRSSI() [int](/builtin#int)
SetMTU(mtu [uint16](/builtin#uint16)) [error](/builtin#error)}
Peripheral is the interface that represent a remote peripheral device.
const ( CharBroadcast Property = 0x01 CharRead Property = 0x02 CharWriteNR Property = 0x04 CharWrite Property = 0x08 CharNotify Property = 0x10 CharIndicate Property = 0x20 CharSignedWrite Property = 0x40 CharExtended Property = 0x80 )
Characteristic property flags (spec 3.3.3.1)
func (p Property) String() (result string)
type ReadHandler ¶
type ReadHandler interface { ServeRead(resp ResponseWriter, req *ReadRequest) }
A ReadHandler handles GATT read requests.
type ReadHandlerFunc ¶
type ReadHandlerFunc func(resp ResponseWriter, 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 ResponseWriter, req *ReadRequest)
ServeRead returns f(r, maxlen, offset).
type ReadRequest struct { Request Cap int Offset int }
A ReadRequest is a characteristic read request from a connected device.
A Service is a BLE service.
func NewService(u UUID) *Service
NewService creates and initialize a new Service using u as it's UUID.
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 (s Service) Characteristics() []Characteristic
Characteristic returns the contained characteristic of this service.
func (*Service) EndHandle ¶
EndHandle returns the End Handle of the service.
func (*Service) Handle ¶
Handle returns the Handle of the service.
Name returns the specificatin name of the service according to its UUID. If the UUID is not assigne, Name returns an empty string.
func (s Service) SetCharacteristics(chars []Characteristic)
SetCharacteristics sets the Characteristics of the service.
func (*Service) SetEndHandle ¶
func (s *Service) SetEndHandle(endh uint16)
SetEndHandle sets the End Handle of the service.
func (*Service) SetHandle ¶
SetHandle sets the Handle of the service.
UUID returns the UUID of the service.
type ServiceData struct { UUID UUID Data []byte }
FIXME: check the unmarshalling of this data structure.
const ( StateUnknown State = 0 StateResetting State = 1 StateUnsupported State = 2 StatePoweredOff State = 4 StatePoweredOn State = 5 )
A UUID is a BLE UUID.
MustParseUUID parses a standard-format UUID string, like ParseUUID, but panics in case of error.
ParseUUID parses a standard-format UUID string, such as "1800" or "34DA3AD1-7110-41A1-B1EF-4430F509CDE7".
UUID16 converts a uint16 (such as 0x1800) to a UUID.
func (u UUID) Equal(v UUID) bool
Equal returns a boolean reporting whether v represent the same UUID as u.
Len returns the length of the UUID, in bytes. BLE UUIDs are either 2 or 16 bytes.
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 ¶
ServeWrite returns f(r, data).