35
35
**Hardware:**
36
36
37
37
Adafruit Feather nRF52840 Express <https://www.adafruit.com/product/4062>
38
+ Adafruit Circuit Playground Bluefruit <https://www.adafruit.com/product/4333>
38
39
39
40
**Software and Dependencies:**
40
41
53
54
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BLE.git"
54
55
55
56
class BLEConnection :
56
- """This represents a connection to a peer BLE device.
57
-
58
- It acts as a map from a Service type to a Service instance for the connection.
59
57
"""
60
- def __init__ ( self , connection ):
61
- self . _connection = connection
62
- self . _discovered_services = {}
63
- """These are the bare remote services from _bleio."""
58
+ Represents a connection to a peer BLE device.
59
+ It acts as a map from a `Service` type to a `Service` instance for the connection.
60
+
61
+ :param bleio_connection _bleio.Connection: the native `_bleio.Connection` object to wrap
64
62
63
+ """
64
+ def __init__ (self , bleio_connection ):
65
+ self ._bleio_connection = bleio_connection
66
+ # _bleio.Service objects representing services found during discovery.
67
+ self ._discovered_bleio_services = {}
68
+ # Service objects that wrap remote services.
65
69
self ._constructed_services = {}
66
- """These are the Service instances from the library that wrap the remote services."""
67
70
68
71
def _discover_remote (self , uuid ):
69
72
remote_service = None
70
- if uuid in self ._discovered_services :
71
- remote_service = self ._discovered_services [uuid ]
73
+ if uuid in self ._discovered_bleio_services :
74
+ remote_service = self ._discovered_bleio_services [uuid ]
72
75
else :
73
- results = self ._connection .discover_remote_services ((uuid .bleio_uuid ,))
76
+ results = self ._bleio_connection .discover_remote_services ((uuid .bleio_uuid ,))
74
77
if results :
75
78
remote_service = results [0 ]
76
- self ._discovered_services [uuid ] = remote_service
79
+ self ._discovered_bleio_services [uuid ] = remote_service
77
80
return remote_service
78
81
79
82
def __contains__ (self , key ):
83
+ """
84
+ Allows easy testing for a particular Service class or a particular UUID
85
+ associated with this connection.
86
+
87
+ Example::
88
+
89
+ if UARTService in connection:
90
+ # do something
91
+
92
+ if StandardUUID(0x1234) in connection:
93
+ # do something
94
+ """
80
95
uuid = key
81
96
if hasattr (key , "uuid" ):
82
97
uuid = key .uuid
83
98
return self ._discover_remote (uuid ) is not None
84
99
85
100
def __getitem__ (self , key ):
101
+ """Return the Service for the given Service class or uuid, if any."""
86
102
uuid = key
87
103
maybe_service = False
88
104
if hasattr (key , "uuid" ):
89
105
uuid = key .uuid
90
106
maybe_service = True
91
107
92
- remote_service = self ._discover_remote (uuid )
93
-
94
108
if uuid in self ._constructed_services :
95
109
return self ._constructed_services [uuid ]
110
+
111
+ remote_service = self ._discover_remote (uuid )
96
112
if remote_service :
97
113
constructed_service = None
98
114
if maybe_service :
@@ -105,16 +121,19 @@ def __getitem__(self, key):
105
121
@property
106
122
def connected (self ):
107
123
"""True if the connection to the peer is still active."""
108
- return self ._connection .connected
124
+ return self ._bleio_connection .connected
109
125
110
126
def disconnect (self ):
111
127
"""Disconnect from peer."""
112
- self ._connection .disconnect ()
128
+ self ._bleio_connection .disconnect ()
113
129
114
130
class BLERadio :
115
- """The BLERadio class enhances the normal `_bleio.Adapter`.
131
+ """
132
+ BLERadio provides the interfaces for BLE advertising,
133
+ scanning for advertisements, and connecting to peers. There may be
134
+ multiple connections active at once.
116
135
117
- It uses the library's `Advertisement` classes and the `BLEConnection` class."""
136
+ It uses this library's `Advertisement` classes and the `BLEConnection` class."""
118
137
119
138
def __init__ (self , adapter = None ):
120
139
if not adapter :
@@ -123,34 +142,63 @@ def __init__(self, adapter=None):
123
142
self ._current_advertisement = None
124
143
self ._connection_cache = {}
125
144
126
- def start_advertising (self , advertisement , scan_response = None , ** kwargs ):
127
- """Starts advertising the given advertisement.
145
+ def start_advertising (self , advertisement , scan_response = None , interval = 0.1 ):
146
+ """
147
+ Starts advertising the given advertisement.
128
148
129
- It takes most kwargs of `_bleio.Adapter.start_advertising`."""
149
+ :param buf scan_response: scan response data packet bytes.
150
+ ``None`` if no scan response is needed.
151
+ :param float interval: advertising interval, in seconds
152
+ """
130
153
scan_response_data = None
131
154
if scan_response :
132
155
scan_response_data = bytes (scan_response )
133
156
self ._adapter .start_advertising (bytes (advertisement ),
134
157
scan_response = scan_response_data ,
135
158
connectable = advertisement .connectable ,
136
- ** kwargs )
159
+ interval = interval )
137
160
138
161
def stop_advertising (self ):
139
162
"""Stops advertising."""
140
163
self ._adapter .stop_advertising ()
141
164
142
- def start_scan (self , * advertisement_types , ** kwargs ):
143
- """Starts scanning. Returns an iterator of advertisement objects of the types given in
144
- advertisement_types. The iterator will block until an advertisement is heard or the scan
145
- times out.
146
-
147
- If any ``advertisement_types`` are given, only Advertisements of those types are produced
148
- by the returned iterator. If none are given then `Advertisement` objects will be
149
- returned."""
165
+ def start_scan (self , * advertisement_types , buffer_size = 512 , extended = False , timeout = None ,
166
+ interval = 0.1 , window = 0.1 , minimum_rssi = - 80 , active = True ):
167
+ """
168
+ Starts scanning. Returns an iterator of advertisement objects of the types given in
169
+ advertisement_types. The iterator will block until an advertisement is heard or the scan
170
+ times out.
171
+
172
+ If any ``advertisement_types`` are given, only Advertisements of those types are produced
173
+ by the returned iterator. If none are given then `Advertisement` objects will be
174
+ returned.
175
+
176
+ Advertisements and scan responses are filtered and returned separately.
177
+
178
+ :param int buffer_size: the maximum number of advertising bytes to buffer.
179
+ :param bool extended: When True, support extended advertising packets.
180
+ Increasing buffer_size is recommended when this is set.
181
+ :param float timeout: the scan timeout in seconds.
182
+ If None, will scan until `stop_scan` is called.
183
+ :param float interval: the interval (in seconds) between the start
184
+ of two consecutive scan windows
185
+ Must be in the range 0.0025 - 40.959375 seconds.
186
+ :param float window: the duration (in seconds) to scan a single BLE channel.
187
+ window must be <= interval.
188
+ :param int minimum_rssi: the minimum rssi of entries to return.
189
+ :param bool active: request and retrieve scan responses for scannable advertisements.
190
+ :return: If any ``advertisement_types`` are given,
191
+ only Advertisements of those types are produced by the returned iterator.
192
+ If none are given then `Advertisement` objects will be returned.
193
+ :rtype: iterable
194
+ """
150
195
prefixes = b""
151
196
if advertisement_types :
152
197
prefixes = b"" .join (adv .prefix for adv in advertisement_types )
153
- for entry in self ._adapter .start_scan (prefixes = prefixes , ** kwargs ):
198
+ for entry in self ._adapter .start_scan (prefixes = prefixes , buffer_size = buffer_size ,
199
+ extended = extended , timeout = timeout ,
200
+ interval = interval , window = window ,
201
+ minimum_rssi = minimum_rssi , active = active ):
154
202
adv_type = Advertisement
155
203
for possible_type in advertisement_types :
156
204
if possible_type .matches (entry ) and issubclass (possible_type , adv_type ):
@@ -167,7 +215,14 @@ def stop_scan(self):
167
215
self ._adapter .stop_scan ()
168
216
169
217
def connect (self , advertisement , * , timeout = 4 ):
170
- """Initiates a `BLEConnection` to the peer that advertised the given advertisement."""
218
+ """
219
+ Initiates a `BLEConnection` to the peer that advertised the given advertisement.
220
+
221
+ :param advertisement Advertisement: An `Advertisement` or a subclass of `Advertisement`
222
+ :param timeout float: how long to wait for a connection
223
+ :return: the connection to the peer
224
+ :rtype: BLEConnection
225
+ """
171
226
connection = self ._adapter .connect (advertisement .address , timeout = timeout )
172
227
self ._connection_cache [connection ] = BLEConnection (connection )
173
228
return self ._connection_cache [connection ]
0 commit comments