1
1
"""Build HAT handling functionality"""
2
2
3
+ import logging
3
4
import queue
5
+ import tempfile
4
6
import threading
5
7
import time
6
8
from enum import Enum
@@ -69,13 +71,14 @@ class BuildHAT:
69
71
RESET_GPIO_NUMBER = 4
70
72
BOOT0_GPIO_NUMBER = 22
71
73
72
- def __init__ (self , firmware , signature , version , device = "/dev/serial0" ):
74
+ def __init__ (self , firmware , signature , version , device = "/dev/serial0" , debug = False ):
73
75
"""Interact with Build HAT
74
76
75
77
:param firmware: Firmware file
76
78
:param signature: Signature file
77
79
:param version: Firmware version
78
80
:param device: Serial device to use
81
+ :param debug: Optional boolean to log debug information
79
82
:raises BuildHATError: Occurs if can't find HAT
80
83
"""
81
84
self .cond = Condition ()
@@ -88,6 +91,10 @@ def __init__(self, firmware, signature, version, device="/dev/serial0"):
88
91
self .running = True
89
92
self .vincond = Condition ()
90
93
self .vin = None
94
+ if debug :
95
+ tmp = tempfile .NamedTemporaryFile (suffix = ".log" , prefix = "buildhat-" , delete = False )
96
+ logging .basicConfig (filename = tmp .name , format = '%(asctime)s %(message)s' ,
97
+ level = logging .INFO )
91
98
92
99
for _ in range (4 ):
93
100
self .connections .append (Connection ())
@@ -99,16 +106,18 @@ def __init__(self, firmware, signature, version, device="/dev/serial0"):
99
106
# Check if we're in the bootloader or the firmware
100
107
self .write (b"version\r " )
101
108
109
+ emptydata = 0
102
110
incdata = 0
103
111
while True :
104
- try :
105
- line = self .ser .readline ().decode ('utf-8' , 'ignore' )
106
- except serial .SerialException :
107
- pass
112
+ line = self .read ()
108
113
if len (line ) == 0 :
109
- # Didn't recieve any data
110
- break
111
- if line [:len (BuildHAT .FIRMWARE )] == BuildHAT .FIRMWARE :
114
+ # Didn't receive any data
115
+ emptydata += 1
116
+ if emptydata > 3 :
117
+ break
118
+ else :
119
+ continue
120
+ if cmp (line , BuildHAT .FIRMWARE ):
112
121
self .state = HatState .FIRMWARE
113
122
ver = line [len (BuildHAT .FIRMWARE ):].split (' ' )
114
123
if int (ver [0 ]) == version :
@@ -117,7 +126,7 @@ def __init__(self, firmware, signature, version, device="/dev/serial0"):
117
126
else :
118
127
self .state = HatState .NEEDNEWFIRMWARE
119
128
break
120
- elif line [: len ( BuildHAT . BOOTLOADER )] == BuildHAT .BOOTLOADER :
129
+ elif cmp ( line , BuildHAT .BOOTLOADER ) :
121
130
self .state = HatState .BOOTLOADER
122
131
break
123
132
else :
@@ -184,15 +193,15 @@ def loadfirmware(self, firmware, signature):
184
193
self .getprompt ()
185
194
self .write ("load {} {}\r " .format (len (firm ), self .checksum (firm )).encode ())
186
195
time .sleep (0.1 )
187
- self .write (b"\x02 " )
188
- self .write (firm )
189
- self .write (b"\x03 \r " )
196
+ self .write (b"\x02 " , replace = "0x02" )
197
+ self .write (firm , replace = "--firmware file--" )
198
+ self .write (b"\x03 \r " , replace = "0x03" )
190
199
self .getprompt ()
191
200
self .write ("signature {}\r " .format (len (sig )).encode ())
192
201
time .sleep (0.1 )
193
- self .write (b"\x02 " )
194
- self .write (sig )
195
- self .write (b"\x03 \r " )
202
+ self .write (b"\x02 " , replace = "0x02" )
203
+ self .write (sig , replace = "--signature file--" )
204
+ self .write (b"\x03 \r " , replace = "0x03" )
196
205
self .getprompt ()
197
206
198
207
def getprompt (self ):
@@ -201,12 +210,8 @@ def getprompt(self):
201
210
Need to decide what we will do, when no prompt
202
211
"""
203
212
while True :
204
- line = b""
205
- try :
206
- line = self .ser .readline ().decode ('utf-8' , 'ignore' )
207
- except serial .SerialException :
208
- pass
209
- if line [:len (BuildHAT .PROMPT )] == BuildHAT .PROMPT :
213
+ line = self .read ()
214
+ if cmp (line , BuildHAT .PROMPT ):
210
215
break
211
216
212
217
def checksum (self , data ):
@@ -224,12 +229,33 @@ def checksum(self, data):
224
229
u = (u ^ data [i ]) & 0xFFFFFFFF
225
230
return u
226
231
227
- def write (self , data ):
232
+ def write (self , data , log = True , replace = "" ):
228
233
"""Write data to the serial port of Build HAT
229
234
230
235
:param data: Data to write to Build HAT
236
+ :param log: Whether to log line or not
237
+ :param replace: Whether to log an alternative string
231
238
"""
232
239
self .ser .write (data )
240
+ if not self .fin and log :
241
+ if replace != "" :
242
+ logging .info ("> {}" .format (replace ))
243
+ else :
244
+ logging .info ("> {}" .format (data .decode ('utf-8' , 'ignore' ).strip ()))
245
+
246
+ def read (self ):
247
+ """Read data from the serial port of Build HAT
248
+
249
+ :return: Line that has been read
250
+ """
251
+ line = ""
252
+ try :
253
+ line = self .ser .readline ().decode ('utf-8' , 'ignore' ).strip ()
254
+ except serial .SerialException :
255
+ pass
256
+ if line != "" :
257
+ logging .info ("< {}" .format (line ))
258
+ return line
233
259
234
260
def shutdown (self ):
235
261
"""Turn off the Build HAT devices"""
@@ -275,11 +301,7 @@ def loop(self, cond, uselist, q):
275
301
"""
276
302
count = 0
277
303
while self .running :
278
- line = b""
279
- try :
280
- line = self .ser .readline ().decode ('utf-8' , 'ignore' )
281
- except serial .SerialException :
282
- pass
304
+ line = self .read ()
283
305
if len (line ) == 0 :
284
306
continue
285
307
if line [0 ] == "P" and line [2 ] == ":" :
@@ -326,7 +348,7 @@ def runit():
326
348
327
349
if line [0 ] == "P" and (line [2 ] == "C" or line [2 ] == "M" ):
328
350
portid = int (line [1 ])
329
- data = line [5 :].strip (). split (" " )
351
+ data = line [5 :].split (" " )
330
352
newdata = []
331
353
for d in data :
332
354
if "." in d :
@@ -341,8 +363,8 @@ def runit():
341
363
with self .portcond [portid ]:
342
364
self .portcond [portid ].notify ()
343
365
344
- if len (line ) >= 5 and line [1 ] == "." and line .strip (). endswith (" V" ):
345
- vin = float (line .strip (). split (" " )[0 ])
366
+ if len (line ) >= 5 and line [1 ] == "." and line .endswith (" V" ):
367
+ vin = float (line .split (" " )[0 ])
346
368
self .vin = vin
347
369
with self .vincond :
348
370
self .vincond .notify ()
0 commit comments