forked from go-ble/ble
/
adv.go
143 lines (120 loc) · 3.93 KB
/
adv.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package hci
import (
"net"
"github.com/LassiHeikkila/ble"
"github.com/LassiHeikkila/ble/linux/adv"
"github.com/LassiHeikkila/ble/linux/hci/evt"
)
// RandomAddress is a Random Device Address.
type RandomAddress struct {
ble.Addr
}
// [Vol 6, Part B, 4.4.2] [Vol 3, Part C, 11]
const (
evtTypAdvInd = 0x00 // Connectable undirected advertising (ADV_IND).
evtTypAdvDirectInd = 0x01 // Connectable directed advertising (ADV_DIRECT_IND).
evtTypAdvScanInd = 0x02 // Scannable undirected advertising (ADV_SCAN_IND).
evtTypAdvNonconnInd = 0x03 // Non connectable undirected advertising (ADV_NONCONN_IND).
evtTypScanRsp = 0x04 // Scan Response (SCAN_RSP).
)
func newAdvertisement(e evt.LEAdvertisingReport, i int) *Advertisement {
return &Advertisement{e: e, i: i}
}
// Advertisement implements ble.Advertisement and other functions that are only
// available on Linux.
type Advertisement struct {
e evt.LEAdvertisingReport
i int
sr *Advertisement
// cached packets.
p *adv.Packet
}
// setScanResponse ssociate sca response to the existing advertisement.
func (a *Advertisement) setScanResponse(sr *Advertisement) {
a.sr = sr
a.p = nil // clear the cached.
}
// packets returns the combined advertising packet and scan response (if presents)
func (a *Advertisement) packets() *adv.Packet {
if a.p != nil {
return a.p
}
return adv.NewRawPacket(a.Data(), a.ScanResponse())
}
// LocalName returns the LocalName of the remote peripheral.
func (a *Advertisement) LocalName() string {
if a.packets().LocalName() != "" {
return a.packets().LocalName()
}
// sometimes name can be found in scan response packet, e.g. in Teltonika beacons:
// https://wiki.teltonika-gps.com/view/EYE_SENSOR_/_BTSMP1#Protocol_description
if a.sr != nil && a.sr.LocalName() != "" {
return a.sr.LocalName()
}
return ""
}
// ManufacturerData returns the ManufacturerData of the advertisement.
func (a *Advertisement) ManufacturerData(keys ...uint16) []byte {
return a.packets().ManufacturerData(keys...)
}
// ServiceData returns the service data of the advertisement.
func (a *Advertisement) ServiceData() []ble.ServiceData {
return a.packets().ServiceData()
}
// Services returns the service UUIDs of the advertisement.
func (a *Advertisement) Services() []ble.UUID {
return a.packets().UUIDs()
}
// OverflowService returns the UUIDs of overflowed service.
func (a *Advertisement) OverflowService() []ble.UUID {
return a.packets().UUIDs()
}
// TxPowerLevel returns the tx power level of the remote peripheral.
func (a *Advertisement) TxPowerLevel() int {
pwr, _ := a.packets().TxPower()
return pwr
}
// SolicitedService returns UUIDs of solicited services.
func (a *Advertisement) SolicitedService() []ble.UUID {
return a.packets().ServiceSol()
}
// Connectable indicates weather the remote peripheral is connectable.
func (a *Advertisement) Connectable() bool {
return a.EventType() == evtTypAdvDirectInd || a.EventType() == evtTypAdvInd
}
// RSSI returns RSSI signal strength.
func (a *Advertisement) RSSI() int {
return int(a.e.RSSI(a.i))
}
// Addr returns the address of the remote peripheral.
func (a *Advertisement) Addr() ble.Addr {
b := a.e.Address(a.i)
addr := net.HardwareAddr([]byte{b[5], b[4], b[3], b[2], b[1], b[0]})
if a.e.AddressType(a.i) == 1 {
return RandomAddress{addr}
}
return addr
}
// EventType returns the event type of Advertisement.
// This is linux sepcific.
func (a *Advertisement) EventType() uint8 {
return a.e.EventType(a.i)
}
// AddressType returns the address type of the Advertisement.
// This is linux sepcific.
func (a *Advertisement) AddressType() uint8 {
return a.e.AddressType(a.i)
}
// Data returns the advertising data of the packet.
// This is linux specific.
func (a *Advertisement) Data() []byte {
return a.e.Data(a.i)
}
// ScanResponse returns the scan response of the packet, if it presents.
// This is linux sepcific.
func (a *Advertisement) ScanResponse() []byte {
if a.sr == nil {
return nil
}
return a.sr.Data()
}