forked from tinygo-org/bluetooth
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gatts_linux.go
107 lines (92 loc) · 2.78 KB
/
gatts_linux.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//go:build !baremetal
package bluetooth
import (
"github.com/muka/go-bluetooth/api/service"
"github.com/muka/go-bluetooth/bluez/profile/gatt"
)
// Characteristic is a single characteristic in a service. It has an UUID and a
// value.
type Characteristic struct {
handle *service.Char
permissions CharacteristicPermissions
}
// AddService creates a new service with the characteristics listed in the
// Service struct.
func (a *Adapter) AddService(s *Service) error {
app, err := service.NewApp(service.AppOptions{
AdapterID: a.id,
})
if err != nil {
return err
}
// disable magic uuid generation because we send through a fully formed UUID.
// muka/go-bluetooth does some magic so you can use short UUIDs and it'll auto
// expand them to the full 128 bit uuid.
// setting these flags disables that behavior.
app.Options.UUIDSuffix = ""
app.Options.UUID = ""
bluezService, err := app.NewService(s.UUID.String())
if err != nil {
return err
}
err = app.AddService(bluezService)
if err != nil {
return err
}
for _, char := range s.Characteristics {
// Create characteristic handle.
bluezChar, err := bluezService.NewChar(char.UUID.String())
if err != nil {
return err
}
// Set properties.
bluezCharFlags := []string{
gatt.FlagCharacteristicBroadcast, // bit 0
gatt.FlagCharacteristicRead, // bit 1
gatt.FlagCharacteristicWriteWithoutResponse, // bit 2
gatt.FlagCharacteristicWrite, // bit 3
gatt.FlagCharacteristicNotify, // bit 4
gatt.FlagCharacteristicIndicate, // bit 5
}
for i := uint(0); i < 5; i++ {
if (char.Flags>>i)&1 != 0 {
bluezChar.Properties.Flags = append(bluezChar.Properties.Flags, bluezCharFlags[i])
}
}
bluezChar.Properties.Value = char.Value
if char.Handle != nil {
char.Handle.handle = bluezChar
char.Handle.permissions = char.Flags
}
// Do a callback when the value changes.
if char.WriteEvent != nil {
callback := char.WriteEvent
bluezChar.OnWrite(func(c *service.Char, value []byte) ([]byte, error) {
// BlueZ doesn't seem to tell who did the write, so pass 0
// always.
// It also doesn't provide which part of the value was written,
// so pretend the entire characteristic was updated (which might
// not be the case).
callback(0, 0, value)
return nil, nil
})
}
// Add characteristic to the service, to activate it.
err = bluezService.AddChar(bluezChar)
if err != nil {
return err
}
}
return app.Run()
}
// Write replaces the characteristic value with a new value.
func (c *Characteristic) Write(p []byte) (n int, err error) {
if len(p) == 0 {
return 0, nil // nothing to do
}
gattError := c.handle.WriteValue(p, nil)
if gattError != nil {
return 0, gattError
}
return len(p), nil
}