Created
May 25, 2023 13:38
-
-
Save adeguet1/76b9b3b75d07b67c5f1a2ebb46a56035 to your computer and use it in GitHub Desktop.
Python script to detect any new SD card and copy some files on it. Used to flash firmware for dVRK controllers.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Script used to monitor new block device (SD card) and copy new dVRK | |
# firmware files automatically | |
# | |
# Anton Deguet | |
# | |
import pyudev | |
import subprocess | |
import time | |
import datetime | |
import os | |
import shutil | |
context = pyudev.Context() | |
monitor = pyudev.Monitor.from_netlink(context) | |
monitor.filter_by(subsystem='block') | |
now = datetime.datetime.now() | |
date_time = now.strftime("%Y-%m-%d-%H.%M.%S") | |
for device in iter(monitor.poll, None): | |
if device.action == 'add': | |
# find the device and path | |
dir(device) | |
print('udev device: {}'.format(device)) | |
slash_dev = device.device_node | |
print('/dev device: {}'.format(slash_dev)) | |
time.sleep(1.0) # 1 second to let the OS mount the device | |
mount_path = subprocess.run(['findmnt', '-n', '-o', 'TARGET', slash_dev], | |
stdout=subprocess.PIPE).stdout.decode('utf-8').strip() | |
print('mount point: {}'.format(mount_path)) | |
# create backup dirctory if needed | |
existing_files = os.listdir(mount_path) | |
if existing_files: | |
# create back dir | |
backup_path = mount_path + '/backups' | |
if not os.path.exists(backup_path): | |
os.mkdir(backup_path) | |
backup_path = backup_path + '/' + date_time | |
if not os.path.exists(backup_path): | |
os.mkdir(backup_path) | |
# move files | |
for f in existing_files: | |
if f != 'backups': | |
full_file = mount_path + '/' + f | |
print('move {} to backup directory {}'.format(full_file, backup_path)) | |
shutil.move(full_file, backup_path) | |
# copy files | |
files = ['BOOT.bin', 'firmware.xsvf'] | |
for f in files: | |
print('copy {} to {}'.format(f, mount_path)) | |
shutil.copy(f, mount_path) | |
# leave a timestamp on card | |
subprocess.run(['touch', mount_path + '/created-' + date_time], | |
stdout=subprocess.PIPE) | |
# and finally, umount | |
umount_result = subprocess.run(['umount', mount_path], | |
stdout=subprocess.PIPE).stdout.decode('utf-8').strip() | |
print('umount {}'.format(umount_result)) |
If files are found, maybe there can be a prompt whether to delete them or archive them in a backup dir? I'll also request for Keshuai to come up with a more descriptive name than firmware.xsvf. Maybe espm-firmware.xsvf or just espm.xsvf.
#
# Script used to monitor new block device (SD card) and copy new dVRK
# firmware files automatically
#
# Anton Deguet
#
import urllib.request
import os.path
import zipfile
import shutil
import pyudev
import subprocess
import time
import datetime
zip_url = 'https://github.com/jhu-cisst/mechatronics-embedded/releases/latest/download/fpgav3-micro-sd.zip'
zip_filename = 'fpgav3-micro-sd.zip'
if os.path.exists(zip_filename):
print('Removing', zip_filename)
os.remove(zip_filename)
if os.path.exists('sd_unzipped'):
print('Removing unzipped files')
shutil.rmtree('sd_unzipped')
print('Downloading', zip_url)
urllib.request.urlretrieve(zip_url, zip_filename)
print('Unzipping', zip_filename)
with zipfile.ZipFile(zip_filename, 'r') as zip_ref:
zip_ref.extractall('sd_unzipped')
print('Ready to write to SD card. Please insert card now.')
context = pyudev.Context()
monitor = pyudev.Monitor.from_netlink(context)
monitor.filter_by(subsystem='block')
now = datetime.datetime.now()
date_time = now.strftime("%Y-%m-%d-%H.%M.%S")
count = 0
for device in iter(monitor.poll, None):
if device.action == 'add':
# find the device and path
dir(device)
print('udev device: {}'.format(device))
slash_dev = device.device_node
print('/dev device: {}'.format(slash_dev))
time.sleep(1.0) # 1 second to let the OS mount the device
mount_path = subprocess.run(['findmnt', '-n', '-o', 'TARGET', slash_dev],
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
print('mount point: {}'.format(mount_path))
if not mount_path:
print('Could not find mount point. Ignored.')
continue
existing_files = os.listdir(mount_path)
if not (os.path.exists(mount_path + '/BOOT.bin') or len(existing_files) == 0):
print('The drive is not empty and does not appear to be a dVRK card. Aborting. If you want to write to this drive, please empty it first.')
else:
# create backup dirctory if needed
if existing_files:
# create back dir
backup_path = mount_path + '/backups'
if not os.path.exists(backup_path):
os.mkdir(backup_path)
backup_path = backup_path + '/' + date_time
if not os.path.exists(backup_path):
os.mkdir(backup_path)
# move files
for f in existing_files:
if f != 'backups':
full_file = mount_path + '/' + f
print('move {} to backup directory {}'.format(full_file, backup_path))
shutil.move(full_file, backup_path)
# copy files
files = os.listdir('sd_unzipped')
for f in files:
print('copy {} to {}'.format(f, mount_path))
# does not work with directories
shutil.copy('sd_unzipped/' + f, mount_path)
# leave a timestamp on card
subprocess.run(['touch', mount_path + '/created-' + date_time],
stdout=subprocess.PIPE)
# and finally, umount
umount_result = subprocess.run(['umount', mount_path],
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
print('umount {}'.format(umount_result))
count += 1
print(f'Done. Please insert the next card. Count: {count}.')
Looks o.k., but why not unzip the file directly to the SD card (with -o option to overwrite)? That would preserve the original file dates, which may be useful as another check that it is the released version.
I was trying to save CPU time by only unzipping once, but preserving the original file dates is more important.
For the dVRK, the script has been moved to the main repository: jhu-dvrk/sawIntuitiveResearchKit@1313fba
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Instead of a sleep to wait for the drive to be mounted, we could use a loop to call
findmnt
with a shorter sleep in the loop. This might be faster and safer (in case 1 second is not enough).