@@ -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 ('\n Transferring 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 ('\n Error 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 ('\n Transferring 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'\n Transfering 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'\n Transfering 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