Skip to content

Commit 12be0d8

Browse files
committedOct 7, 2022
Modified the behaviour of pycboard for transferring device driver files to pyboard. New behaviour is:
- When a task file or hardware definition file is transferred to the pyboard, the required device driver files are tranferred unless they are already on the board and have the same file hash. - When the framework is reloaded the devices folder on the pyboard is reset, by deleting all device driver files and rebuilding the device_file2class dictionary.
1 parent f8cd36c commit 12be0d8

File tree

1 file changed

+42
-35
lines changed

1 file changed

+42
-35
lines changed
 

‎com/pycboard.py

+42-35
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def __init__(self, serial_port, baudrate=115200, verbose=True, print_func=print
6464
self.print = print_func # Function used for print statements.
6565
self.data_logger = data_logger # Instance of Data_logger class for saving and printing data.
6666
self.status = {'serial': None, 'framework':None, 'usb_mode':None}
67-
self.device_files_on_pyboard = [] # List of files in devices folder on pyboard.
67+
self.device_files_on_pyboard = {} # Dict {file_name:file_hash} of files in devices folder on pyboard.
6868
if not Pycboard.device_class2file: # Scan devices folder to find files where device classes are defined.
6969
self.make_device_class2file_map()
7070
try:
@@ -109,7 +109,7 @@ def reset(self):
109109
try:
110110
self.exec('from pyControl import *; import devices')
111111
self.status['framework'] = True # Framework imported OK.
112-
self.device_files_on_pyboard = self.get_folder_contents('devices')
112+
self.device_files_on_pyboard = self.get_folder_contents('devices', get_hash=True)
113113
except PyboardError as e:
114114
error_message = e.args[2].decode()
115115
if (("ImportError: no module named 'pyControl'" in error_message) or
@@ -260,19 +260,27 @@ def remove_file(self, file_path):
260260
except PyboardError:
261261
pass # File does not exist.
262262

263-
def get_folder_contents(self, folder_path):
264-
'''Get a list of the files in a folder on the pyboard.'''
265-
return eval(self.eval('os.listdir({})'.format(repr(folder_path))).decode())
263+
def get_folder_contents(self, folder_path, get_hash=False):
264+
'''Get a list of the files in a folder on the pyboard, if
265+
get_hash=True a dict {file_name:file_hash} is returned instead'''
266+
file_list = eval(self.eval('os.listdir({})'.format(repr(folder_path))).decode())
267+
if get_hash:
268+
return {file_name: self.get_file_hash(folder_path+'/'+file_name)
269+
for file_name in file_list}
270+
else:
271+
return file_list
266272

267273
# ------------------------------------------------------------------------------------
268274
# pyControl operations.
269275
# ------------------------------------------------------------------------------------
270276

271277
def load_framework(self):
272-
'''Copy the pyControl framework folder to the board.'''
278+
'''Copy the pyControl framework folder to the board, reset the devices folder
279+
on pyboard by removing all devices files, and rebuild the device_class2file dict.'''
273280
self.print('\nTransferring pyControl framework to pyboard.', end='')
274281
self.transfer_folder(dirs['framework'], file_type='py', show_progress=True)
275-
self.transfer_folder(dirs['devices'], files=['__init__.py'], remove_files=False, show_progress=True)
282+
self.transfer_folder(dirs['devices'], files=['__init__.py'], remove_files=True, show_progress=True)
283+
self.make_device_class2file_map()
276284
error_message = self.reset()
277285
if not self.status['framework']:
278286
self.print('\nError importing framework:')
@@ -282,12 +290,9 @@ def load_framework(self):
282290
return
283291

284292
def load_hardware_definition(self, hwd_path=os.path.join(dirs['config'], 'hardware_definition.py')):
285-
'''Transfer a hardware definition file to pyboard. Device driver files needed for
286-
the hardware definition are transferred to the pyboard and any other device driver
287-
files on the pyboard are deleted.'''
293+
'''Transfer a hardware definition file to pyboard.'''
288294
if os.path.exists(hwd_path):
289-
self.make_device_class2file_map()
290-
self.transfer_device_files(hwd_path, reset_folder=True)
295+
self.transfer_device_files(hwd_path)
291296
self.print('\nTransferring hardware definition to pyboard.', end='')
292297
self.transfer_file(hwd_path, target_path='hardware_definition.py')
293298
self.reset()
@@ -301,35 +306,37 @@ def load_hardware_definition(self, hwd_path=os.path.join(dirs['config'], 'hardwa
301306
else:
302307
self.print('Hardware definition file not found.')
303308

304-
def transfer_device_files(self, ref_file_path, reset_folder=False, return_filenames=False):
305-
'''Transfer device driver files defining classes used in ref_file to the pyboard devices folder.
306-
If reset_folder=True then any files not used by ref_file are deleted from the pyboard filesystem,
307-
and any files that have changed on the computer are retransferred. If reset_folder=False then
308-
only files that are not already on the pyboard filesystem are transferred. If return_filenames=True
309-
then no files are transferred but a list of the filenames used in ref_file is returned.'''
309+
def transfer_device_files(self, ref_file_path):
310+
'''Transfer device driver files defining classes used in ref_file to the pyboard devices folder.
311+
Driver file that are already on the pyboard are only be transferred if they have changed
312+
on the computer.'''
313+
used_device_files = self._get_used_device_files(ref_file_path)
314+
files_to_transfer = []
315+
for device_file in used_device_files: # File not on pyboard.
316+
if device_file not in self.device_files_on_pyboard.keys():
317+
files_to_transfer.append(device_file)
318+
else:
319+
file_hash = _djb2_file(os.path.join(dirs['devices'],device_file))
320+
if file_hash != self.device_files_on_pyboard[device_file]: # File has changed.
321+
files_to_transfer.append(device_file)
322+
if files_to_transfer:
323+
self.print(f'\nTransfering device driver files {files_to_transfer} to pyboard', end='')
324+
self.transfer_folder(dirs['devices'], files=files_to_transfer, remove_files=False, show_progress=True)
325+
self.reset()
326+
self.print(' OK')
327+
328+
def _get_used_device_files(self, ref_file_path):
329+
'''Return a list of device driver file names containing device classes used in ref_file'''
310330
ref_file_name = os.path.split(ref_file_path)[-1]
311331
with open(ref_file_path, 'r') as f:
312332
file_content = f.read()
313-
device_files = [Pycboard.device_class2file[device_class] for device_class in
314-
Pycboard.device_class2file.keys() if device_class in file_content
315-
and not ref_file_name == Pycboard.device_class2file[device_class]]
333+
device_files = [device_file for device_class, device_file in Pycboard.device_class2file.items()
334+
if device_class in file_content and not ref_file_name == device_file]
316335
# Add any device driver files containing classes used in device_files.
317336
for device_file in device_files.copy():
318-
device_files += self.transfer_device_files(os.path.join(dirs['devices'], device_file), return_filenames=True)
337+
device_files += self._get_used_device_files(os.path.join(dirs['devices'], device_file))
319338
device_files = list(set(device_files)) # Remove duplicates.
320-
if return_filenames:
321-
return device_files
322-
else:
323-
if reset_folder:
324-
device_files += ['__init__.py']
325-
else:
326-
device_files = list(set(device_files)-set(self.device_files_on_pyboard))
327-
if device_files:
328-
self.print(f'\nTransfering device driver files {device_files} to pyboard', end='')
329-
self.transfer_folder(dirs['devices'], files=device_files, remove_files=reset_folder, show_progress=True)
330-
self.reset()
331-
self.print(' OK')
332-
339+
return device_files
333340

334341
def make_device_class2file_map(self):
335342
'''Make dict mapping device class names to file in devices folder containing

0 commit comments

Comments
 (0)
Please sign in to comment.