def __init__(self, fw, channel = 16, serial_port = None, snr = None): ''' Ininitialises the OTA Flasher class which handles flashing the devboard with the needed OTA Server firmware and the update file for the OTA Client. The said devboard shall become the OTA Server which shall propagate the image on the Zigbee network. Keyword arguments: fw -- path to the update file for the OTA Client channel -- a 802.15.4 channel number, on which the OTA Server shall operate (default 16) serial_port -- a serial port of the connected devboard which shall be flashed with OTA Server snr -- a JLink serial number of the connected devboard which shall be flashed with OTA Server Note: only one parameter out of (serial_port, snr) must be provided, since the superclass constructor shall handle resolving the rest. ''' # Call the superclass constructor Flasher.__init__(self, serial_port, snr) # Create a Intel Hex out of the Zigbee Update file ih = IntelHex() update = open(fw, 'rb').read() ih.puts(OTAFlasher.OTA_UPDATE_OFFSET, update) self.update_firmware_hex = fw + '.hex' ih.write_hex_file(self.update_firmware_hex) # Open the serial channel to the devboard and save the 802.15.4 channel self.ser = Serial(self.serial_port, 115200) self.channel = channel
def test_valid_baud_rate(self): self.assertEqual( Flasher.is_valid_baud_rate([ '17', 'A5', 'D8', '46', # magic number '02', # struct version 'FF', 'FF', 'FF', # (reserved for future use) '00', '00', '00', '00', # revision hash '01', '02', '00', # major, minor, patch 'FF', # (reserved for future use) '03', # softdevice ble api number '01', # transport type 'FF', 'FF', # (reserved for future use) '00', 'C2', '01', '00' # baud rate ]), True)
def test_valid_version(self): self.assertEqual(Flasher.is_valid_version( ['17', 'A5', 'D8', '46', # magic number '02', # struct version 'FF', 'FF', 'FF', # (reserved for future use) '00', '00', '00', '00', # revision hash '01', '02', '03' # major, minor, patch ]), True)
def test_valid_parse(self): self.assertEqual( Flasher.parse_fw_struct(self.raw_data), { 'len': 24, 'magic_number': ['17', 'A5', 'D8', '46'], 'version': '4.1.1', 'baud_rate': 1000000, 'api_version': 5 })
def test_programming(self): settings = Settings.current() serial_ports = [port for port in BLEDriver.enum_serial_ports()] # Check that from enumeration matches # kits provided from settings found_ports = map(lambda port: port.port, serial_ports) for serial_port in settings.serial_ports: self.assertIn(serial_port, found_ports) for serial_port in serial_ports: if serial_port.port in settings.serial_ports: serial_number = serial_port.serial_number logger.info("%s/%s deleting existing firmware", serial_port.port, serial_number) flasher = Flasher(serial_port=serial_port.port) flasher.erase() self.assertFalse( flasher.fw_check(), "#{} must be programmed because it is erased".format( serial_number), ) flasher.fw_flash() logger.info("%s/%s programmed", serial_port.port, serial_number) self.assertTrue( flasher.fw_check(), "#{} is programmed, shall not be programmed again".format( serial_number), ) flasher.reset() logger.info("%s/%s programmed successfully", serial_port.port, serial_number)
def flash_connectivity(comport, jlink_snr): flasher = Flasher(serial_port=comport, snr=jlink_snr) if flasher.fw_check(): print("Board already flashed with connectivity firmware.") else: print("Flashing connectivity firmware...") flasher.fw_flash() print("Connectivity firmware flashed.") flasher.reset() time.sleep(1)
def main(port): descs = BLEDriver.enum_serial_ports() print("enum_serial_ports: {} serial ports found".format(len(descs))) for i, d in enumerate(descs): print("\nSerial port #{}:".format(i)) print("|") print("|- Port: \"{}\"".format(d.port)) print("|- Manufacturer: \"{}\"".format(d.manufacturer)) print("|- Serial Number: \"{}\"".format(d.serial_number)) print("|- PnP ID: \"{}\"".format(d.pnp_id)) print("|- Location ID: \"{}\"".format(d.location_id)) print("|- Vendor ID: \"{}\"".format(d.vendor_id)) print("|_ Product ID: \"{}\"".format(d.product_id)) if port != None: flasher = Flasher(serial_port=port) if flasher.fw_check(): print("Port \"{}\" already flashed with connectivity firmware".format(port)) else: print("Flashing Port \"{}\"".format(port)) flasher.fw_flash() print("Firmware flashed")
def ble(package, conn_ic_id, port, connect_delay, name, address, jlink_snr, flash_connectivity): """ Perform a Device Firmware Update on a device with a bootloader that supports BLE DFU. This requires a second nRF device, connected to this computer, with connectivity firmware loaded. The connectivity device will perform the DFU procedure onto the target device. """ ble_driver_init(conn_ic_id) if name is None and address is None: name = 'DfuTarg' click.echo( "No target selected. Default device name: {} is used.".format( name)) if port is None and jlink_snr is not None: port = get_port_by_snr(jlink_snr) elif port is None: port = enumerate_ports() if port is None: click.echo( "\nNo Segger USB CDC ports found, please connect your board.") return if flash_connectivity: flasher = Flasher(serial_port=port, snr=jlink_snr) if flasher.fw_check(): click.echo("Board already flashed with connectivity firmware.") else: click.echo("Flashing connectivity firmware...") flasher.fw_flash() click.echo("Connectivity firmware flashed.") flasher.reset() time.sleep(1) logger.info("Using connectivity board at serial port: {}".format(port)) ble_backend = DfuTransportBle(serial_port=str(port), target_device_name=str(name), target_device_addr=str(address)) ble_backend.register_events_callback(DfuEvent.PROGRESS_EVENT, update_progress) dfu = Dfu(zip_file_path=package, dfu_transport=ble_backend, connect_delay=connect_delay) if logger.getEffectiveLevel() > logging.INFO: with click.progressbar(length=dfu.dfu_get_total_size()) as bar: global global_bar global_bar = bar dfu.dfu_send_images() else: dfu.dfu_send_images() click.echo("Device programmed.")
def test_valid_baud_rate(self): self.assertEqual(Flasher.is_valid_baud_rate( ['17', 'A5', 'D8', '46', # magic number '02', # struct version 'FF', 'FF', 'FF', # (reserved for future use) '00', '00', '00', '00', # revision hash '01', '02', '00', # major, minor, patch 'FF', # (reserved for future use) '03', # softdevice ble api number '01', # transport type 'FF', 'FF', # (reserved for future use) '00', 'C2', '01', '00' # baud rate ]), True)
def main(port): descs = BLEDriver.enum_serial_ports() print("enum_serial_ports: {} serial ports found".format(len(descs))) for i, d in enumerate(descs): print("\nSerial port #{}:".format(i)) print("|") print("|- Port: \"{}\"".format(d.port)) print("|- Manufacturer: \"{}\"".format(d.manufacturer)) print("|- Serial Number: \"{}\"".format(d.serial_number)) print("|- PnP ID: \"{}\"".format(d.pnp_id)) print("|- Location ID: \"{}\"".format(d.location_id)) print("|- Vendor ID: \"{}\"".format(d.vendor_id)) print("|_ Product ID: \"{}\"".format(d.product_id)) if port != None: flasher = Flasher(serial_port=port) if flasher.fw_check(): print("Port \"{}\" already flashed with connectivity firmware". format(port)) else: print("Flashing Port \"{}\"".format(port)) flasher.fw_flash() print("Firmware flashed")
def ble(package, conn_ic_id, port, name, address, jlink_snr, flash_connectivity): ble_driver_init(conn_ic_id) """Perform a Device Firmware Update on a device with a bootloader that supports BLE DFU.""" if name is None and address is None: name = 'DfuTarg' click.echo("No target selected. Default device name: {} is used.".format(name)) if port is None and jlink_snr is not None: click.echo("Please specify also serial port.") return elif port is None: port = enumerate_ports() if port is None: click.echo("\nNo Segger USB CDC ports found, please connect your board.") return if flash_connectivity: flasher = Flasher(serial_port=port, snr = jlink_snr) if flasher.fw_check(): click.echo("Board already flashed with connectivity firmware.") else: click.echo("Flashing connectivity firmware...") flasher.fw_flash() click.echo("Connectivity firmware flashed.") flasher.reset() time.sleep(1) logger.info("Using connectivity board at serial port: {}".format(port)) ble_backend = DfuTransportBle(serial_port=str(port), target_device_name=str(name), target_device_addr=str(address)) ble_backend.register_events_callback(DfuEvent.PROGRESS_EVENT, update_progress) dfu = Dfu(zip_file_path = package, dfu_transport = ble_backend) if logger.getEffectiveLevel() > logging.INFO: with click.progressbar(length=dfu.dfu_get_total_size()) as bar: global global_bar global_bar = bar dfu.dfu_send_images() else: dfu.dfu_send_images() click.echo("Device programmed.")
def ble(package, port, name, address, jlink_snr, flash_connectivity): """Perform a Device Firmware Update on a device with a bootloader that supports BLE DFU.""" if name is None and address is None: name = 'DfuTarg' click.echo("No target selected. Default device name: {} is used.".format(name)) if port is None and jlink_snr is not None: click.echo("Please specify also serial port.") return elif port is None: port = enumerate_ports() if flash_connectivity: flasher = Flasher(serial_port=port, snr = jlink_snr) if flasher.fw_check(): click.echo("Connectivity already flashed with firmware.") else: click.echo("Flashing connectivity ") flasher.fw_flash() click.echo("Connectivity flashed") flasher.reset() time.sleep(1) ble_backend = DfuTransportBle(serial_port=str(port), target_device_name=str(name), target_device_addr=str(address)) ble_backend.register_events_callback(DfuEvent.PROGRESS_EVENT, update_progress) dfu = Dfu(zip_file_path = package, dfu_transport = ble_backend) with click.progressbar(length=dfu.dfu_get_total_size()) as bar: global global_bar global_bar = bar dfu.dfu_send_images() click.echo("Device programmed.")
def thread(package, port, address, server_port, panid, channel, jlink_snr, flash_connectivity, sim, rate, reset_suppress): """ Perform a Device Firmware Update on a device that supports Thread DFU. This requires a second nRF device, connected to this computer, with Thread Network CoProcessor (NCP) firmware loaded. The NCP device will perform the DFU procedure onto the target device. """ ble_driver_init('NRF52') from nordicsemi.thread import tncp from nordicsemi.thread.dfu_thread import create_dfu_server from nordicsemi.thread.tncp import NCPTransport from nordicsemi.thread.ncp_flasher import NCPFlasher mcast_dfu = False if address is None: address = ipaddress.ip_address(u"ff03::1") click.echo("Address not specified. Using ff03::1 (all Thread nodes)") else: try: address = ipaddress.ip_address(address) mcast_dfu = address.is_multicast except: click.echo("Invalid IPv6 address") return 1 if (not sim): if port is None and jlink_snr is None: click.echo("Please specify serial port or Jlink serial number.") return 2 elif port is None: port = get_port_by_snr(jlink_snr) if port is None: click.echo("\nNo Segger USB CDC ports found, please connect your board.") return 3 stream_descriptor = 'u:' + port click.echo("Using connectivity board at serial port: {}".format(port)) else: stream_descriptor = 'p:' + Flasher.which('ot-ncp') + ' 30' click.echo("Using ot-ncp binary: {}".format(stream_descriptor)) if flash_connectivity: flasher = NCPFlasher(serial_port=port, snr = jlink_snr) if flasher.fw_check(): click.echo("Board already flashed with connectivity firmware.") else: click.echo("Flashing connectivity firmware...") flasher.fw_flash() click.echo("Connectivity firmware flashed.") flasher.reset() # Delay is required because NCP needs time to initialize. time.sleep(1.0) config = tncp.NCPTransport.get_default_config() if (panid): config[tncp.NCPTransport.CFG_KEY_PANID] = panid if (channel): config[tncp.NCPTransport.CFG_KEY_CHANNEL] = channel if (flash_connectivity): config[tncp.NCPTransport.CFG_KEY_RESET] = False opts = type('DFUServerOptions', (object,), {})() opts.rate = rate opts.reset_suppress = reset_suppress opts.mcast_dfu = mcast_dfu transport = NCPTransport(server_port, stream_descriptor, config) dfu = create_dfu_server(transport, package, opts) try: sighandler = lambda signum, frame : transport.close() signal.signal(signal.SIGINT, sighandler) signal.signal(signal.SIGTERM, sighandler) transport.open() # Delay DFU trigger until NCP promotes to a router (6 seconds by default) click.echo("Waiting for NCP to promote to a router...") time.sleep(6.0) dfu.trigger(address, 3) click.echo("Thread DFU server is running... Press <Ctrl + D> to stop.") pause() click.echo("Terminating") except Exception as e: logger.exception(e) finally: transport.close()
def test_valid_version(self): self.assertTrue(Flasher.is_valid_version('4.1.1'))
def test_invalid_parse(self): with self.assertRaises(IndexError): Flasher.parse_fw_struct(self.raw_data_wrong_format)
def test_valid_baud_rate(self): self.assertTrue(Flasher.is_valid_baud_rate(1000000))
def test_invalid_version(self): self.assertFalse(Flasher.is_valid_version('4.0.0'))
def __init__(self, serial_port = None, snr = None): Flasher.__init__(self, serial_port, snr)
def test_valid_number(self): self.assertEqual( Flasher.is_valid_magic_number(['17', 'A5', 'D8', '46']), True)
def test_invalid_number(self): self.assertEqual( Flasher.is_valid_magic_number(['17', 'A5', 'D8', '45']), False)
data = conn.recv(1024) outbuf = [ord(x) for x in data] b.write_data(outbuf) #came out of loop conn.close() args.name = ' '.join(args.name) comport = args.com[0] jlink_snr = args.snr[0] flash_connectivity = True logging.basicConfig(format='%(message)s', level=logging.INFO) if flash_connectivity: flasher = Flasher(serial_port=comport, snr = jlink_snr) if flasher.fw_check(): logger.info("Board already flashed with connectivity firmware.") else: logger.info("Flashing connectivity firmware...") flasher.fw_flash() logger.info("Connectivity firmware flashed.") flasher.reset() time.sleep(1) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print 'Socket created'
def test_invalid_baud_rate(self): self.assertFalse(Flasher.is_valid_baud_rate(115200))
def test_invalid_number(self): self.assertEqual(Flasher.is_valid_magic_number( ['17', 'A5', 'D8', '45'] ), False)
def test_valid_number(self): self.assertEqual(Flasher.is_valid_magic_number( ['17', 'A5', 'D8', '46'] ), True)
def thread(package, port, address, server_port, prefix, panid, channel, jlink_snr, flash_connectivity, sim): ble_driver_init('NRF52') from nordicsemi.thread import tncp from nordicsemi.thread.dfu_thread import create_dfu_server from nordicsemi.thread.tncp import NCPTransport from nordicsemi.thread.ncp_flasher import NCPFlasher """Perform a Device Firmware Update on a device with a bootloader that supports Thread DFU.""" if address is None: address = ipaddress.ip_address(u"ff03::1") click.echo("Address not specified. Using ff03::1 (all Thread nodes)") else: try: address = ipaddress.ip_address(address) except: click.echo("Invalid IPv6 address") return if (not sim): if port is None and jlink_snr is None: click.echo("Please specify serial port or Jlink serial number.") return elif port is None: port = get_port_by_snr(jlink_snr) if port is None: click.echo("\nNo Segger USB CDC ports found, please connect your board.") return stream_descriptor = 'u:' + port logger.info("Using connectivity board at serial port: {}".format(port)) else: stream_descriptor = 'p:' + Flasher.which('ot-ncp') + ' 30' logger.info("Using ot-ncp binary: {}".format(stream_descriptor)) if flash_connectivity: flasher = NCPFlasher(serial_port=port, snr = jlink_snr) if flasher.fw_check(): click.echo("Board already flashed with connectivity firmware.") else: click.echo("Flashing connectivity firmware...") flasher.fw_flash() click.echo("Connectivity firmware flashed.") flasher.reset() # Delay is required because NCP needs time to initialize. time.sleep(1.0) config = tncp.NCPTransport.get_default_config() if (panid): config[tncp.NCPTransport.CFG_KEY_PANID] = panid if (channel): config[tncp.NCPTransport.CFG_KEY_CHANNEL] = channel if (flash_connectivity): config[tncp.NCPTransport.CFG_KEY_RESET] = False transport = NCPTransport(server_port, stream_descriptor, config) dfu = create_dfu_server(transport, package, prefix) try: sighandler = lambda signum, frame : dfu.stop signal.signal(signal.SIGINT, sighandler) signal.signal(signal.SIGTERM, sighandler) dfu.start() dfu.trigger(address, 3) click.echo("Press <ENTER> terminate") pause() click.echo("Terminating") except Exception as e: logger.exception(e) finally: dfu.stop()