52
52
from micropython import const
53
53
54
54
# pylint: disable=bad-whitespace
55
- _MSG_COMMAND = const (0x10 ) # Command message
56
- _MSG_RESPONSE = const (0x20 ) # Response message
57
- _MSG_ALERT = const (0x40 ) # Alert message
58
- _MSG_ERROR = const (0x80 ) # Error message
59
-
60
- _SDEP_INITIALIZE = const (0xBEEF ) # Resets the Bluefruit device
61
- _SDEP_ATCOMMAND = const (0x0A00 ) # AT command wrapper
62
- _SDEP_BLEUART_TX = const (0x0A01 ) # BLE UART transmit data
63
- _SDEP_BLEUART_RX = const (0x0A02 ) # BLE UART read data
64
-
65
- _ARG_STRING = const (0x0100 ) # String data type
66
- _ARG_BYTEARRAY = const (0x0200 ) # Byte array data type
67
- _ARG_INT32 = const (0x0300 ) # Signed 32-bit integer data type
68
- _ARG_UINT32 = const (0x0400 ) # Unsigned 32-bit integer data type
69
- _ARG_INT16 = const (0x0500 ) # Signed 16-bit integer data type
70
- _ARG_UINT16 = const (0x0600 ) # Unsigned 16-bit integer data type
71
- _ARG_INT8 = const (0x0700 ) # Signed 8-bit integer data type
72
- _ARG_UINT8 = const (0x0800 ) # Unsigned 8-bit integer data type
73
-
74
- _ERROR_INVALIDMSGTYPE = const (0x8021 ) # SDEP: Unexpected SDEP MsgType
75
- _ERROR_INVALIDCMDID = const (0x8022 ) # SDEP: Unknown command ID
76
- _ERROR_INVALIDPAYLOAD = const (0x8023 ) # SDEP: Payload problem
77
- _ERROR_INVALIDLEN = const (0x8024 ) # SDEP: Indicated len too large
78
- _ERROR_INVALIDINPUT = const (0x8060 ) # AT: Invalid data
79
- _ERROR_UNKNOWNCMD = const (0x8061 ) # AT: Unknown command name
80
- _ERROR_INVALIDPARAM = const (0x8062 ) # AT: Invalid param value
81
- _ERROR_UNSUPPORTED = const (0x8063 ) # AT: Unsupported command
55
+ _MSG_COMMAND = const (0x10 ) # Command message
56
+ _MSG_RESPONSE = const (0x20 ) # Response message
57
+ _MSG_ALERT = const (0x40 ) # Alert message
58
+ _MSG_ERROR = const (0x80 ) # Error message
59
+
60
+ _SDEP_INITIALIZE = const (0xBEEF ) # Resets the Bluefruit device
61
+ _SDEP_ATCOMMAND = const (0x0A00 ) # AT command wrapper
62
+ _SDEP_BLEUART_TX = const (0x0A01 ) # BLE UART transmit data
63
+ _SDEP_BLEUART_RX = const (0x0A02 ) # BLE UART read data
64
+
65
+ _ARG_STRING = const (0x0100 ) # String data type
66
+ _ARG_BYTEARRAY = const (0x0200 ) # Byte array data type
67
+ _ARG_INT32 = const (0x0300 ) # Signed 32-bit integer data type
68
+ _ARG_UINT32 = const (0x0400 ) # Unsigned 32-bit integer data type
69
+ _ARG_INT16 = const (0x0500 ) # Signed 16-bit integer data type
70
+ _ARG_UINT16 = const (0x0600 ) # Unsigned 16-bit integer data type
71
+ _ARG_INT8 = const (0x0700 ) # Signed 8-bit integer data type
72
+ _ARG_UINT8 = const (0x0800 ) # Unsigned 8-bit integer data type
73
+
74
+ _ERROR_INVALIDMSGTYPE = const (0x8021 ) # SDEP: Unexpected SDEP MsgType
75
+ _ERROR_INVALIDCMDID = const (0x8022 ) # SDEP: Unknown command ID
76
+ _ERROR_INVALIDPAYLOAD = const (0x8023 ) # SDEP: Payload problem
77
+ _ERROR_INVALIDLEN = const (0x8024 ) # SDEP: Indicated len too large
78
+ _ERROR_INVALIDINPUT = const (0x8060 ) # AT: Invalid data
79
+ _ERROR_UNKNOWNCMD = const (0x8061 ) # AT: Unknown command name
80
+ _ERROR_INVALIDPARAM = const (0x8062 ) # AT: Invalid param value
81
+ _ERROR_UNSUPPORTED = const (0x8063 ) # AT: Unsupported command
82
82
83
83
# For the Bluefruit Connect packets
84
- _PACKET_BUTTON_LEN = const (5 )
85
- _PACKET_COLOR_LEN = const (6 )
84
+ _PACKET_BUTTON_LEN = const (5 )
85
+ _PACKET_COLOR_LEN = const (6 )
86
86
87
87
# pylint: enable=bad-whitespace
88
88
89
89
90
90
class BluefruitSPI :
91
91
"""Helper for the Bluefruit LE SPI Friend"""
92
92
93
- def __init__ (self , spi , cs , irq , reset , debug = False ): # pylint: disable=too-many-arguments
93
+ def __init__ (
94
+ self , spi , cs , irq , reset , debug = False
95
+ ): # pylint: disable=too-many-arguments
94
96
self ._irq = irq
95
97
self ._buf_tx = bytearray (20 )
96
98
self ._buf_rx = bytearray (20 )
@@ -114,8 +116,7 @@ def __init__(self, spi, cs, irq, reset, debug=False): # pylint: disable=too-many
114
116
self ._irq .direction = Direction .INPUT
115
117
self ._irq .pull = Pull .DOWN
116
118
117
- self ._spi_device = SPIDevice (spi , cs ,
118
- baudrate = 4000000 , phase = 0 , polarity = 0 )
119
+ self ._spi_device = SPIDevice (spi , cs , baudrate = 4000000 , phase = 0 , polarity = 0 )
119
120
120
121
def _cmd (self , cmd ): # pylint: disable=too-many-branches
121
122
"""
@@ -129,9 +130,9 @@ def _cmd(self, cmd): # pylint: disable=too-many-branches
129
130
if len (cmd ) > 127 :
130
131
if self ._debug :
131
132
print ("ERROR: Command too long." )
132
- raise ValueError (' Command too long.' )
133
+ raise ValueError (" Command too long." )
133
134
134
- more = 0x80 # More bit is in pos 8, 1 = more data available
135
+ more = 0x80 # More bit is in pos 8, 1 = more data available
135
136
pos = 0
136
137
while len (cmd ) - pos :
137
138
# Construct the SDEP packet
@@ -142,9 +143,15 @@ def _cmd(self, cmd): # pylint: disable=too-many-branches
142
143
if plen > 16 :
143
144
plen = 16
144
145
# Note the 'more' value in bit 8 of the packet len
145
- struct .pack_into ("<BHB16s" , self ._buf_tx , 0 ,
146
- _MSG_COMMAND , _SDEP_ATCOMMAND ,
147
- plen | more , cmd [pos :pos + plen ])
146
+ struct .pack_into (
147
+ "<BHB16s" ,
148
+ self ._buf_tx ,
149
+ 0 ,
150
+ _MSG_COMMAND ,
151
+ _SDEP_ATCOMMAND ,
152
+ plen | more ,
153
+ cmd [pos : pos + plen ],
154
+ )
148
155
if self ._debug :
149
156
print ("Writing: " , [hex (b ) for b in self ._buf_tx ])
150
157
else :
@@ -155,7 +162,7 @@ def _cmd(self, cmd): # pylint: disable=too-many-branches
155
162
156
163
# Send out the SPI bus
157
164
with self ._spi_device as spi :
158
- spi .write (self ._buf_tx , end = len (cmd ) + 4 ) # pylint: disable=no-member
165
+ spi .write (self ._buf_tx , end = len (cmd ) + 4 ) # pylint: disable=no-member
159
166
160
167
# Wait up to 200ms for a response
161
168
timeout = 0.2
@@ -165,7 +172,7 @@ def _cmd(self, cmd): # pylint: disable=too-many-branches
165
172
if timeout <= 0 :
166
173
if self ._debug :
167
174
print ("ERROR: Timed out waiting for a response." )
168
- raise RuntimeError (' Timed out waiting for a response.' )
175
+ raise RuntimeError (" Timed out waiting for a response." )
169
176
170
177
# Retrieve the response message
171
178
msgtype = 0
@@ -179,11 +186,11 @@ def _cmd(self, cmd): # pylint: disable=too-many-branches
179
186
spi .readinto (self ._buf_rx )
180
187
181
188
# Read the message envelope and contents
182
- msgtype , rspid , rsplen = struct .unpack (' >BHB' , self ._buf_rx [0 :4 ])
189
+ msgtype , rspid , rsplen = struct .unpack (" >BHB" , self ._buf_rx [0 :4 ])
183
190
if rsplen >= 16 :
184
191
rsp += self ._buf_rx [4 :20 ]
185
192
else :
186
- rsp += self ._buf_rx [4 : rsplen + 4 ]
193
+ rsp += self ._buf_rx [4 : rsplen + 4 ]
187
194
if self ._debug :
188
195
print ("Reading: " , [hex (b ) for b in self ._buf_rx ])
189
196
else :
@@ -200,35 +207,34 @@ def init(self):
200
207
This command should complete in under 1s.
201
208
"""
202
209
# Construct the SDEP packet
203
- struct .pack_into ("<BHB" , self ._buf_tx , 0 ,
204
- _MSG_COMMAND , _SDEP_INITIALIZE , 0 )
210
+ struct .pack_into ("<BHB" , self ._buf_tx , 0 , _MSG_COMMAND , _SDEP_INITIALIZE , 0 )
205
211
if self ._debug :
206
212
print ("Writing: " , [hex (b ) for b in self ._buf_tx ])
207
213
208
214
# Send out the SPI bus
209
215
with self ._spi_device as spi :
210
- spi .write (self ._buf_tx , end = 4 ) # pylint: disable=no-member
216
+ spi .write (self ._buf_tx , end = 4 ) # pylint: disable=no-member
211
217
212
218
# Wait 1 second for the command to complete.
213
219
time .sleep (1 )
214
220
215
221
@property
216
222
def connected (self ):
217
223
"""Whether the Bluefruit module is connected to the central"""
218
- return int (self .command_check_OK (b' AT+GAPGETCONN' )) == 1
224
+ return int (self .command_check_OK (b" AT+GAPGETCONN" )) == 1
219
225
220
226
def uart_tx (self , data ):
221
227
"""
222
228
Sends the specific bytestring out over BLE UART.
223
229
:param data: The bytestring to send.
224
230
"""
225
- return self ._cmd (b' AT+BLEUARTTX=' + data + b' \r \n ' )
231
+ return self ._cmd (b" AT+BLEUARTTX=" + data + b" \r \n " )
226
232
227
233
def uart_rx (self ):
228
234
"""
229
235
Reads byte data from the BLE UART FIFO.
230
236
"""
231
- data = self .command_check_OK (b' AT+BLEUARTRX' )
237
+ data = self .command_check_OK (b" AT+BLEUARTRX" )
232
238
if data :
233
239
# remove \r\n from ending
234
240
return data [:- 2 ]
@@ -237,7 +243,7 @@ def uart_rx(self):
237
243
def command (self , string ):
238
244
"""Send a command and check response code"""
239
245
try :
240
- msgtype , msgid , rsp = self ._cmd (string + "\n " )
246
+ msgtype , msgid , rsp = self ._cmd (string + "\n " )
241
247
if msgtype == _MSG_ERROR :
242
248
raise RuntimeError ("Error (id:{0})" .format (hex (msgid )))
243
249
if msgtype == _MSG_RESPONSE :
@@ -246,20 +252,20 @@ def command(self, string):
246
252
except RuntimeError as error :
247
253
raise RuntimeError ("AT command failure: " + repr (error ))
248
254
249
- def command_check_OK (self , command , delay = 0.0 ): # pylint: disable=invalid-name
255
+ def command_check_OK (self , command , delay = 0.0 ): # pylint: disable=invalid-name
250
256
"""Send a fully formed bytestring AT command, and check
251
257
whether we got an 'OK' back. Returns payload bytes if there is any"""
252
258
ret = self .command (command )
253
259
time .sleep (delay )
254
260
if not ret or not ret [- 4 :]:
255
261
raise RuntimeError ("Not OK" )
256
- if ret [- 4 :] != b' OK\r \n ' :
262
+ if ret [- 4 :] != b" OK\r \n " :
257
263
raise RuntimeError ("Not OK" )
258
264
if ret [:- 4 ]:
259
265
return ret [:- 4 ]
260
266
return None
261
267
262
- def read_packet (self ): # pylint: disable=too-many-return-statements
268
+ def read_packet (self ): # pylint: disable=too-many-return-statements
263
269
"""
264
270
Will read a Bluefruit Connect packet and return it in a parsed format.
265
271
Currently supports Button and Color packets only
@@ -270,16 +276,16 @@ def read_packet(self): # pylint: disable=too-many-return-statements
270
276
# convert to an array of character bytes
271
277
self ._buffer += [chr (b ) for b in data ]
272
278
# Find beginning of new packet, starts with a '!'
273
- while self ._buffer and self ._buffer [0 ] != '!' :
279
+ while self ._buffer and self ._buffer [0 ] != "!" :
274
280
self ._buffer .pop (0 )
275
281
# we need at least 2 bytes in the buffer
276
282
if len (self ._buffer ) < 2 :
277
283
return None
278
284
279
285
# Packet beginning found
280
- if self ._buffer [1 ] == 'B' :
286
+ if self ._buffer [1 ] == "B" :
281
287
plen = _PACKET_BUTTON_LEN
282
- elif self ._buffer [1 ] == 'C' :
288
+ elif self ._buffer [1 ] == "C" :
283
289
plen = _PACKET_COLOR_LEN
284
290
else :
285
291
# unknown packet type
@@ -289,16 +295,16 @@ def read_packet(self): # pylint: disable=too-many-return-statements
289
295
# split packet off of buffer cache
290
296
packet = self ._buffer [0 :plen ]
291
297
292
- self ._buffer = self ._buffer [plen :] # remove packet from buffer
293
- if sum ([ord (x ) for x in packet ]) % 256 != 255 : # check sum
298
+ self ._buffer = self ._buffer [plen :] # remove packet from buffer
299
+ if sum ([ord (x ) for x in packet ]) % 256 != 255 : # check sum
294
300
return None
295
301
296
302
# OK packet's good!
297
- if packet [1 ] == 'B' : # buttons have 2 int args to parse
303
+ if packet [1 ] == "B" : # buttons have 2 int args to parse
298
304
# button number & True/False press
299
- return ('B' , int (packet [2 ]), packet [3 ] == '1' )
300
- if packet [1 ] == 'C' : # colorpick has 3 int args to parse
305
+ return ("B" , int (packet [2 ]), packet [3 ] == "1" )
306
+ if packet [1 ] == "C" : # colorpick has 3 int args to parse
301
307
# red, green and blue
302
- return ('C' , ord (packet [2 ]), ord (packet [3 ]), ord (packet [4 ]))
308
+ return ("C" , ord (packet [2 ]), ord (packet [3 ]), ord (packet [4 ]))
303
309
# We don't nicely parse this yet
304
310
return packet [1 :- 1 ]
0 commit comments