6 import os, sys, subprocess
10 print """------------------------------------------------------------- 11 Welcome to the Ubiquity Robotics Firmware Updater! 13 Please make sure that you are not running any ROS nodes. 14 - sudo systemctl stop magni-base 16 Note: Updating the firmware requires access to the internet. 17 ------------------------------------------------------------- 20 TMP_FILE_PATH =
'/tmp/firmware' 23 parser = argparse.ArgumentParser(description=
'Ubiquity Robotics Firmware Updater')
24 parser.add_argument(
'--device', help=
'Serial port to use (eg /dev/ttyAMA0)', default=
'/dev/ttyAMA0')
25 parser.add_argument(
'--file', help=
'Path to a firmware file', default=
'')
26 args = parser.parse_args()
28 serial_port = args.device
30 if (subprocess.call([
'fuser',
'-v', serial_port], stdout=
None) == 0):
32 print "Another process is using the serial port, cannot upgrade firmware" 33 print "Make sure you stopped any running ROS nodes. To stop default nodes:" 34 print "sudo systemctl stop magni-base" 38 path_to_file = args.file
41 path_to_file = TMP_FILE_PATH
43 email = raw_input(
"Please enter your email address: ").strip()
46 r = requests.post(
'https://api.ubiquityrobotics.com/token/', json = {
'email': email})
48 if r.status_code != 200:
49 print "Error with requesting a token %d" % r.status_code
52 print "An access token was sent to your email address" 54 token = raw_input(
"Please enter your access token: ").strip()
56 version = raw_input(
"What version would you like (press enter for latest): ").strip()
61 auth_headers = {
"Authorization":
"Bearer %s" % token}
62 r = requests.get(
'https://api.ubiquityrobotics.com/firmware/%s' % version, headers=auth_headers)
64 if r.status_code != 200:
65 print "Error downloading firmware %d" % r.status_code
68 with open(path_to_file,
'w+b')
as fd:
69 for chunk
in r.iter_content(chunk_size=128):
72 print "\nUpdating firmware now. Do not power off the robot. This is expected to take less than a minute." 89 if type(bc) != int
or bc < 1:
90 raise Exception(
"Invalid read: " + str(bc))
103 f = open(filename,
"r") 108 not_encrypted =
False 115 if c ==
":" and encrypted:
116 raise Exception(
"Partial encryption")
117 if c ==
"+" and not_encrypted:
118 raise Exception(
"Partial encryption")
119 if c
not in [
'\n',
'\r',
'\t',
' ',
':',
"+"]:
120 fcontent = fcontent + c
121 while len(fcontent) >= 2:
122 fout += chr(int(fcontent[0:2], 16))
123 fcontent = fcontent[2:]
124 assert not_encrypted
or encrypted
131 out = out + ord(b) * scale
135 arrc = [x
for x
in arr]
140 asilicon_id = [x
for x
in f.read(4)]
141 asilicon_id.reverse()
143 for a
in asilicon_id:
146 silicon_rev = f.read(1)
147 checksum_type = f.read(1)
148 return silicon_id, silicon_rev, checksum_type
153 data = f.read(data_length)
155 return flash_id, row_number, data_length, data, checksum
161 data = f.read(data_length + 12)
162 return flash_id, row_number, data_length, data
166 return str(x) +
" <- " + str([hex(ord(l))
for l
in x])
168 return str(type(x)) +
" -> " + str(x)
184 if type(mylen) != int
or mylen < 0:
185 raise Exception(
"Invalid length goal for packet: " +
cstr(mylen))
186 if len(self.
inp) != mylen:
187 raise Exception(
"Invalid length for packet: " + len(self.
inp) +
" should be " + str(inp))
193 for step
in xrange(0, mylen):
194 numa.append(chr(num % 256))
196 self.
out.extend(numa)
199 raise Exception(
"Write to packet after send")
203 self.
out.extend([i
for i
in x])
205 self.
out.append(chr(x))
209 raise Exception(
"Read from packet before send")
210 if type(bytes) != int
or bytes < 1:
211 raise Exception(
"Invalid byte read: " +
cstr(bytes))
221 init_bytes = [chr(0x1), self.
cmd,
222 chr((len(self.
out) / 001) % 256),
223 chr((len(self.
out) / 256) % 256)]
224 init_bytes.extend(self.
out)
226 if DEBUG:
print "-"*120
227 if DEBUG:
print "Send packet: " +
cstr(self.
out)
230 for c
in init_bytes: ib_buf += c
231 if DEBUG:
print "Packet without end and checksum is",
cstr(ib_buf)
234 if DEBUG:
print "Checksum is", checksum,
"LSB", (checksum / 001) % 256,
"MSB", (checksum / 256) % 256
236 ib_buf += chr((checksum / 001) % 256)
237 ib_buf += chr((checksum / 256) % 256)
248 start_byte = header[0:1]
249 if start_byte != str(chr(0x01)):
250 raise Exception(
"Packet did not start with valid start byte, instead: " +
cstr(start_byte) +
" -- header: " +
cstr(header))
251 status_code = header[1:2]
252 if status_code != str(chr(0x00)):
253 raise Exception(
"Packet did not start with valid status, instead: " +
cstr(status_code) +
" -- header: " +
cstr(header))
254 data_length_raw = header[2:4]
255 data_length = (ord(data_length_raw[0])) + (ord(data_length_raw[1])) * 256
256 if DEBUG:
print "Read in", data_length,
"from",
cstr(data_length_raw)
258 if len(self.
inp) != data_length:
259 raise Exception(
"We tried to read: " + str(data_length) +
" but instead read: " + str(len(self.
inp)) +
" -- header: " +
cstr(header))
262 checksum_bytes = start_byte + status_code + data_length_raw + self.
inp 265 checksum_raw = self.
ser.
read(2)
266 checksum = (ord(checksum_raw[0])) + (ord(checksum_raw[1]) * 256)
267 if checksum != checksum_comp:
268 raise Exception(
"Invalid checksum for packet: " +
cstr(checksum) +
" != " +
cstr(checksum_comp) +
" -- header: " +
cstr(header))
271 if end_byte != str(chr(0x17)):
272 raise Exception(
"Invalid terminator for packet: " +
cstr(end_byte) +
" -- header: " +
cstr(header))
293 x = (crc >> 8) ^ (int(ord(byte)) & 0xFF)
295 crc = ushort(ushort(crc << 8) ^ ushort(x << 12) ^ ushort(x << 5) ^ ushort(x))
301 p.write(row_number, 2)
310 silicon_id = p.read(4)
311 silicon_rev = p.read(1)
312 bootloader_version = p.read(3)
313 return silicon_id, silicon_rev, bootloader_version
320 flash_first_row = p.read_num(2)
321 flash_last_row = p.read_num(2)
322 return flash_first_row, flash_last_row
327 p.write(row_number, 2)
336 p.write(row_number, 2)
345 p.write(row_number, 2)
348 checksum = p.read_num(1)
367 p.write(app_number, 1)
370 valid_app_number = p.read_num(1)
371 active_app_number = p.read_num(1)
372 return valid_app_number, active_app_number
376 p.write(app_number, 1)
389 p.do_ignore_response()
395 return ((a & 0xFF) + (b & 0xFF)) & 0xFF
398 r =
add8(checksum, flash_id)
399 r =
add8(r, row_number)
400 r =
add8(r, row_number >> 8)
401 r =
add8(r, row_size)
402 r =
add8(r, row_size >> 8)
403 if DEBUG:
print "Checksum convert:", checksum, flash_id, row_number, row_size,
"out:", r
410 print "Unable to open file: ", path_to_file
411 except InvalidFileException:
412 print "File is not of the correct format" 413 print(
"Encryption:", hex_stream.is_encrypted())
415 ser = serial.Serial(serial_port, 38400, timeout=1, bytesize=8,
416 parity=serial.PARITY_NONE, stopbits=1, xonxoff=0, rtscts=0)
419 request_bootloader = [0x7E, 0x3E, 0x01, 0x01, 0x01, 0x01, 0x01]
420 request_bootloader.append(0xFF - sum(request_bootloader[1:]))
421 ser.write(
"".join([chr(x)
for x
in request_bootloader]))
426 file_silicon_id, file_silicon_rev, file_checksum_type =
read__header(hex_stream)
427 if file_silicon_id != silicon_id:
428 raise Exception(
"The silicon ids did not match " +
cstr(file_silicon_id) +
" != " +
cstr(silicon_id))
429 if file_silicon_rev != silicon_rev:
430 raise Exception(
"The silicon revs did not match")
432 if file_checksum_type != str(chr(0)):
433 raise Exception(
"Invalid checksum type: " +
cstr(file_checksum_type))
439 while hex_stream.is_open():
440 if not hex_stream.is_encrypted():
442 print "Writing row", row_number,
"for", flash_id,
"process at", (
"%.2f" % last_percent),
"percent completion" 443 last_percent = (100.0 * hex_stream.get_position()) / hex_stream.get_size()
446 if DEBUG:
print "Write", flash_id, row_number, data_length, len(data), checksum,
"->", real_checksum
449 if DEBUG:
print "Flash: ", flash_first_row, flash_last_row
450 if row_number < flash_first_row
or row_number > flash_last_row:
451 raise Exception(
"Invalid row: must be between " + str(flash_first_row)
452 +
" and " + str(flash_last_row) +
" but is " + str(row_number))
458 while data_strip != []
and data_strip !=
"":
459 bytes_at_a_time = 256
460 data_next = data_strip[0:bytes_at_a_time]
461 data_strip = data_strip[bytes_at_a_time:]
462 data_sent += bytes_at_a_time
463 if DEBUG:
print "Sending", len(data_next),
"Sent: ", data_sent,
"Left: ", len(data_strip)
464 if data_strip == []
or data_strip ==
"":
466 if DEBUG:
print "Last packet" 469 if real_checksum != comp_checksum:
470 raise Exception(
"Checksum error at " + flash_id +
" " + row_number
471 +
". We wanted " +
cstr(real_checksum) +
" but we got " +
cstr(comp_checksum))
473 if DEBUG:
print "Checksum valid", flash_id, row_number,
"->", real_checksum,
"==", comp_checksum
478 print "Writing row", row_number,
"for", flash_id,
"process at", (
"%.2f" % last_percent),
"percent completion" 479 last_percent = (100.0 * hex_stream.get_position()) / hex_stream.get_size()
480 assert len(data) < 256
484 raise Exception(
"Application checksum invalid")
495 print "Finished upgrading firmware!" def send__get_flash_size(ser, flash_id)
def write(self, x, mylen=None)
def twos_complement(bytes)
def send__encrypted_program_row(ser, flash_id, row_number, data_next)
def compute_checksum(bytes)
def do_ignore_response(self)
def send__verify_row(ser, flash_id, row_number)
def send__enter_bootloader(ser)
def send__program_row(ser, flash_id, row_number, data_next)
def __init__(self, ser, cmd)
def send__data(ser, data_next)
def send__sync_bootloader(ser)
def read_num(self, bytes)
def require_len(self, mylen)
def send__get_application_status(ser, app_number)
def __init__(self, content, encrypted)
def send__set_active_application(ser, app_number)
def convert_checksum(checksum, flash_id, row_number, row_size)
def send__exit_bootloader(ser)
def send__erase_row(ser, flash_id, row_number)
def send__verify_checksum(ser)
def file_convert_num(arr)
def read__encrypted_flash_line(f)