class SystemFiles: files = { SystemFileIds.UID: UidFile(), SystemFileIds.FIRMWARE_VERSION: FirmwareVersionFile(), SystemFileIds.DLL_CONFIG: DllConfigFile(), SystemFileIds.ACCESS_PROFILE_0: AccessProfileFile(access_specifier=0), SystemFileIds.ACCESS_PROFILE_1: AccessProfileFile(access_specifier=1), SystemFileIds.ACCESS_PROFILE_2: AccessProfileFile(access_specifier=2), SystemFileIds.ACCESS_PROFILE_3: AccessProfileFile(access_specifier=3), SystemFileIds.ACCESS_PROFILE_4: AccessProfileFile(access_specifier=4), SystemFileIds.ACCESS_PROFILE_5: AccessProfileFile(access_specifier=5), SystemFileIds.ACCESS_PROFILE_6: AccessProfileFile(access_specifier=6), SystemFileIds.ACCESS_PROFILE_7: AccessProfileFile(access_specifier=7), SystemFileIds.ACCESS_PROFILE_8: AccessProfileFile(access_specifier=8), SystemFileIds.ACCESS_PROFILE_9: AccessProfileFile(access_specifier=9), SystemFileIds.ACCESS_PROFILE_10: AccessProfileFile(access_specifier=10), SystemFileIds.ACCESS_PROFILE_11: AccessProfileFile(access_specifier=11), SystemFileIds.ACCESS_PROFILE_12: AccessProfileFile(access_specifier=12), SystemFileIds.ACCESS_PROFILE_13: AccessProfileFile(access_specifier=13), SystemFileIds.ACCESS_PROFILE_14: AccessProfileFile(access_specifier=14), } def get_all_system_files(self): return sorted(self.files, key=lambda t: t.value)
def test_parsing(self): file_contents = [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 # UID ] config = UidFile.parse(ConstBitStream(bytes=file_contents)) self.assertEqual(config.uid, 9)
def read_uid(self): self.send_command( Command.create_with_read_file_action_system_file(UidFile())) while True: # TODO timeout commands, info = self.read() for command in commands: for action in command.actions: if type(action) is RegularAction \ and type(action.operation) is ReturnFileData \ and action.operand.offset.id == SystemFileIds.UID: return struct.unpack(">Q", bytearray(action.operand.data))[0]
def connect(self): if self.connected: return read_modem_info_action = Command.create_with_read_file_action_system_file( UidFile()) read_modem_info_action.add_action( RegularAction(operation=ReadFileData(operand=DataRequest( offset=Offset(id=FirmwareVersionFile().id, offset=Length( 0)), # TODO offset size length=FirmwareVersionFile().length)))) if self.skip_alp_parsing: self.log.info( "Running in skip_alp_parsing mode, not checking if we can receive the modem's UID" ) self.connected = True self.execute_command_async(read_modem_info_action) return True resp_cmd = self.execute_command(read_modem_info_action, timeout_seconds=10) if len(resp_cmd) == 0: self.log.warning("Timed out reading node information") return False for action in resp_cmd[0].actions: if type(action) is RegularAction and type( action.operation) is ReturnFileData: if action.operand.offset.id == SystemFileIds.UID.value: self.uid = '{:x}'.format( struct.unpack(">Q", str(bytearray(action.operand.data)))[0]) if action.operand.offset.id == SystemFileIds.FIRMWARE_VERSION.value: self.firmware_version = FirmwareVersionFile.parse( ConstBitStream(bytearray(action.operand.data))) if self.uid and self.firmware_version: self.connected = True if self.connected: self.log.info( "connected to {}, node UID {} running D7AP v{}, application \"{}\" with git sha1 {}" .format(self.config["device"], self.uid, self.firmware_version.d7ap_version, self.firmware_version.application_name, self.firmware_version.git_sha1)) return True else: return False
def _connect_serial_modem(self): self.dev = serial.Serial( port=self.config["device"], baudrate=self.config["baudrate"], timeout=None, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, xonxoff=False, rtscts=False, dsrdtr=False, exclusive=True, ) self.dev.flush() # ignore possible buffered data self.start_reading() read_modem_info_action = Command.create_with_read_file_action_system_file( UidFile()) read_modem_info_action.add_action( RegularAction(operation=ReadFileData(operand=DataRequest( offset=Offset(id=FirmwareVersionFile().id, offset=Length( 0)), # TODO offset size length=FirmwareVersionFile().length)))) resp_cmd = self.execute_command(read_modem_info_action, timeout_seconds=60) if len(resp_cmd) == 0: self.log.warning("Timed out reading node information") return False for action in resp_cmd[0].actions: if type(action) is RegularAction and type( action.operation) is ReturnFileData: if action.operand.offset.id == SystemFileIds.UID.value: self.uid = '{:x}'.format( struct.unpack(">Q", bytearray(action.operand.data))[0]) if action.operand.offset.id == SystemFileIds.FIRMWARE_VERSION.value: self.firmware_version = FirmwareVersionFile.parse( ConstBitStream(bytearray(action.operand.data))) if self.uid and self.firmware_version: return True return False
def _connect_serial_modem(self): self.dev = serial.Serial( port=self.config["device"], baudrate=self.config["baudrate"], timeout=0.5, ) read_modem_info_action = Command.create_with_read_file_action_system_file( UidFile()) read_modem_info_action.add_action( RegularAction(operation=ReadFileData(operand=DataRequest( offset=Offset(id=FirmwareVersionFile().id, offset=0), # TODO offset size length=FirmwareVersionFile().length)))) self.send_command(read_modem_info_action) # read thread not yet running here, read sync start_time = datetime.now() timeout = False while not timeout: commands, info = self.read() for command in commands: for action in command.actions: if type(action) is RegularAction and type( action.operation) is ReturnFileData: if action.operand.offset.id == SystemFileIds.UID.value: self.uid = '{:x}'.format( struct.unpack(">Q", bytearray( action.operand.data))[0]) if action.operand.offset.id == SystemFileIds.FIRMWARE_VERSION.value: self.firmware_version = FirmwareVersionFile.parse( ConstBitStream(bytearray(action.operand.data))) if self.uid and self.firmware_version: return True if (datetime.now() - start_time).total_seconds() > 2: timeout = True self.log("Timed out reading node information") return False
class SystemFiles: files = { SystemFileIds.UID: UidFile(), SystemFileIds.FACTORY_SETTINGS: FactorySettingsFile(), SystemFileIds.FIRMWARE_VERSION: FirmwareVersionFile(), SystemFileIds.DEVICE_CAPACITY: NotImplementedFile(SystemFileIds.DEVICE_CAPACITY.value, 19), SystemFileIds.DEVICE_STATUS: NotImplementedFile(SystemFileIds.DEVICE_STATUS, 9), SystemFileIds.ENGINEERING_MODE: EngineeringModeFile(), SystemFileIds.VID: VidFile(), SystemFileIds.RFU_07: NotImplementedFile(SystemFileIds.RFU_07, 0), SystemFileIds.PHY_CONFIG: NotImplementedFile(SystemFileIds.PHY_CONFIG, 9), SystemFileIds.PHY_STATUS: NotImplementedFile(SystemFileIds.PHY_STATUS, 24), # TODO assuming 3 channels for now SystemFileIds.DLL_CONFIG: DllConfigFile(), SystemFileIds.DLL_STATUS: NotImplementedFile(SystemFileIds.DLL_STATUS, 12), SystemFileIds.NWL_ROUTING: NotImplementedFile(SystemFileIds.NWL_ROUTING, 1), # TODO variable routing table SystemFileIds.NWL_SECURITY: NotImplementedFile(SystemFileIds.NWL_SECURITY, 5), SystemFileIds.NWL_SECURITY_KEY: SecurityKeyFile(), SystemFileIds.NWL_SSR: NotImplementedFile(SystemFileIds.NWL_SSR, 4), # TODO 0 recorded devices SystemFileIds.NWL_STATUS: NotImplementedFile(SystemFileIds.NWL_STATUS, 20), SystemFileIds.TRL_STATUS: NotImplementedFile(SystemFileIds.TRL_STATUS, 1), # TODO 0 TRL records SystemFileIds.SEL_CONFIG: NotImplementedFile(SystemFileIds.SEL_CONFIG, 6), SystemFileIds.FOF_STATUS: NotImplementedFile(SystemFileIds.FOF_STATUS, 10), SystemFileIds.RFU_14: NotImplementedFile(SystemFileIds.RFU_14, 0), SystemFileIds.RFU_15: NotImplementedFile(SystemFileIds.RFU_15, 0), SystemFileIds.RFU_16: NotImplementedFile(SystemFileIds.RFU_16, 0), SystemFileIds.LOCATION_DATA: NotImplementedFile(SystemFileIds.LOCATION_DATA, 1), # TODO 0 recorded locations SystemFileIds.D7AALP_RFU_18: NotImplementedFile(SystemFileIds.D7AALP_RFU_18, 0), SystemFileIds.D7AALP_RFU_19: NotImplementedFile(SystemFileIds.D7AALP_RFU_19, 0), SystemFileIds.D7AALP_RFU_1A: NotImplementedFile(SystemFileIds.D7AALP_RFU_1A, 0), SystemFileIds.D7AALP_RFU_1B: NotImplementedFile(SystemFileIds.D7AALP_RFU_1B, 0), SystemFileIds.D7AALP_RFU_1C: NotImplementedFile(SystemFileIds.D7AALP_RFU_1C, 0), SystemFileIds.D7AALP_RFU_1D: NotImplementedFile(SystemFileIds.D7AALP_RFU_1D, 0), SystemFileIds.D7AALP_RFU_1E: NotImplementedFile(SystemFileIds.D7AALP_RFU_1E, 0), SystemFileIds.D7AALP_RFU_1F: NotImplementedFile(SystemFileIds.D7AALP_RFU_1F, 0), SystemFileIds.ACCESS_PROFILE_0: AccessProfileFile(access_specifier=0), SystemFileIds.ACCESS_PROFILE_1: AccessProfileFile(access_specifier=1), SystemFileIds.ACCESS_PROFILE_2: AccessProfileFile(access_specifier=2), SystemFileIds.ACCESS_PROFILE_3: AccessProfileFile(access_specifier=3), SystemFileIds.ACCESS_PROFILE_4: AccessProfileFile(access_specifier=4), SystemFileIds.ACCESS_PROFILE_5: AccessProfileFile(access_specifier=5), SystemFileIds.ACCESS_PROFILE_6: AccessProfileFile(access_specifier=6), SystemFileIds.ACCESS_PROFILE_7: AccessProfileFile(access_specifier=7), SystemFileIds.ACCESS_PROFILE_8: AccessProfileFile(access_specifier=8), SystemFileIds.ACCESS_PROFILE_9: AccessProfileFile(access_specifier=9), SystemFileIds.ACCESS_PROFILE_10: AccessProfileFile(access_specifier=10), SystemFileIds.ACCESS_PROFILE_11: AccessProfileFile(access_specifier=11), SystemFileIds.ACCESS_PROFILE_12: AccessProfileFile(access_specifier=12), SystemFileIds.ACCESS_PROFILE_13: AccessProfileFile(access_specifier=13), SystemFileIds.ACCESS_PROFILE_14: AccessProfileFile(access_specifier=14) } def get_all_system_files(self): return sorted(self.files, key=lambda t: t.value)
help="serial device /dev file modem", default="/dev/ttyACM1") argparser.add_argument("-r", "--rate", help="baudrate for serial device", type=int, default=115200) argparser.add_argument("-v", "--verbose", help="verbose", default=False, action="store_true") config = argparser.parse_args() modem = Modem(config.device, config.rate, receive_callback=received_command_callback, show_logging=config.verbose) modem.d7asp_fifo_flush( alp_command=Command.create_with_read_file_action_system_file( file=UidFile(), interface_type=InterfaceType.D7ASP, interface_configuration=Configuration( qos=QoS(resp_mod=ResponseMode.RESP_MODE_ALL), addressee=Addressee(access_class=0x01, id_type=IdType.NOID)))) modem.start_reading() while True: pass
def test_default_constructor(self): f = UidFile() self.assertEqual(f.uid, 0)
def test_byte_generation(self): uid = 12345 bytes = bytearray(UidFile(uid)) self.assertEqual(len(bytes), 8) self.assertEqual(struct.unpack(">Q", bytes)[0], uid)
def bad(): UidFile(uid=-1) self.assertRaises(ValueError, bad)
def test_constructor(self): uid = 0xDEADBEEF f = UidFile(uid=uid) self.assertEqual(f.uid, uid)
def bad(): UidFile(uid=-1)