# Copyright 2024 Volvo Car Corporation # Licensed under Apache 2.0. # -*- coding: utf-8 -*- """Module for creating a project a2l-file from a template.""" from string import Template class A2lProjectTemplate: """Class for A2l Project Template.""" def __init__(self, spm_a2l, asap2_version, project_name, events, ip_address, ip_port): self.spm_a2l = spm_a2l self.asap2_version = asap2_version self.project_name = project_name self.events = events self.ip_address = ip_address self.ip_port = ip_port self.event_template = Template( ' /begin EVENT\n' ' "$name" /* EVENT CHANNEL NAME */\n' ' "$short_name" /* EVENT CHANNEL SHORT NAME */\n' ' $channel_id /* EVENT CHANNEL NUMBER */\n' ' DAQ_STIM\n' ' 0xFF\n' ' $time_cycle /* EVENT TIME CYCLE */\n' ' $time_unit /* EVENT TIME UNIT */\n' ' 0x00\n' ' /end EVENT\n' ) self.template = Template( 'ASAP2_VERSION $asap2_version\n' '/begin PROJECT $project_name ""\n' ' /begin MODULE XCP ""\n' ' /begin A2ML\n' ' struct Protocol_Layer {\n' ' uint; /* XCP protocol layer version, current 0x100 */\n' ' uint; /* T1 [ms] */\n' ' uint; /* T2 [ms] */\n' ' uint; /* T3 [ms] */\n' ' uint; /* T4 [ms] */\n' ' uint; /* T5 [ms] */\n' ' uint; /* T6 [ms] */\n' ' uint; /* T7 [ms] */\n' ' uchar; /* MAX_CTO */\n' ' uint; /* MAX_DTO */\n' ' enum {\n' ' "BYTE_ORDER_MSB_LAST" = 0,\n' ' "BYTE_ORDER_MSB_FIRST" = 1\n' ' };\n' ' enum {\n' ' "ADDRESS_GRANULARITY_BYTE" = 1,\n' ' "ADDRESS_GRANULARITY_WORD" = 2,\n' ' "ADDRESS_GRANULARITY_DWORD" = 4\n' ' };\n' ' taggedstruct {\n' ' ("OPTIONAL_CMD" enum {\n' ' "GET_COMM_MODE_INFO" = 251,\n' ' "GET_ID" = 250,\n' ' "SET_REQUEST" = 249,\n' ' "GET_SEED" = 248,\n' ' "UNLOCK" = 247,\n' ' "SET_MTA" = 246,\n' ' "UPLOAD" = 245,\n' ' "SHORT_UPLOAD" = 244,\n' ' "BUILD_CHECKSUM" = 243,\n' ' "TRANSPORT_LAYER_CMD" = 242,\n' ' "USER_CMD" = 241,\n' ' "DOWNLOAD" = 240,\n' ' "DOWNLOAD_NEXT" = 239,\n' ' "DOWNLOAD_MAX" = 238,\n' ' "SHORT_DOWNLOAD" = 237,\n' ' "MODIFY_BITS" = 236,\n' ' "SET_CAL_PAGE" = 235,\n' ' "GET_CAL_PAGE" = 234,\n' ' "GET_PAG_PROCESSOR_INFO" = 233,\n' ' "GET_SEGMENT_INFO" = 232,\n' ' "GET_PAGE_INFO" = 231,\n' ' "SET_SEGMENT_MODE" = 230,\n' ' "GET_SEGMENT_MODE" = 229,\n' ' "COPY_CAL_PAGE" = 228,\n' ' "CLEAR_DAQ_LIST" = 227,\n' ' "SET_DAQ_PTR" = 226,\n' ' "WRITE_DAQ" = 225,\n' ' "SET_DAQ_LIST_MODE" = 224,\n' ' "GET_DAQ_LIST_MODE" = 223,\n' ' "START_STOP_DAQ_LIST" = 222,\n' ' "START_STOP_SYNCH" = 221,\n' ' "GET_DAQ_CLOCK" = 220,\n' ' "READ_DAQ" = 219,\n' ' "GET_DAQ_PROCESSOR_INFO" = 218,\n' ' "GET_DAQ_RESOLUTION_INFO" = 217,\n' ' "GET_DAQ_LIST_INFO" = 216,\n' ' "GET_DAQ_EVENT_INFO" = 215,\n' ' "FREE_DAQ" = 214,\n' ' "ALLOC_DAQ" = 213,\n' ' "ALLOC_ODT" = 212,\n' ' "ALLOC_ODT_ENTRY" = 211,\n' ' "PROGRAM_START" = 210,\n' ' "PROGRAM_CLEAR" = 209,\n' ' "PROGRAM" = 208,\n' ' "PROGRAM_RESET" = 207,\n' ' "GET_PGM_PROCESSOR_INFO" = 206,\n' ' "GET_SECTOR_INFO" = 205,\n' ' "PROGRAM_PREPARE" = 204,\n' ' "PROGRAM_FORMAT" = 203,\n' ' "PROGRAM_NEXT" = 202,\n' ' "PROGRAM_MAX" = 201,\n' ' "PROGRAM_VERIFY" = 200\n' ' })*;\n' ' "COMMUNICATION_MODE_SUPPORTED" taggedunion {\n' ' "BLOCK" taggedstruct {\n' ' "SLAVE" ;\n' ' "MASTER" struct {\n' ' uchar; /* MAX_BS */\n' ' uchar; /* MIN_ST */\n' ' };\n' ' };\n' ' "INTERLEAVED" uchar; /* QUEUE_SIZE */\n' ' };\n' ' "SEED_AND_KEY_EXTERNAL_FUNCTION" char[256];/* Name of the Seed&Key function */\n' ' };\n' ' };\n' '\n' ' struct Daq {\n' ' enum {\n' ' "STATIC" = 0,\n' ' "DYNAMIC" = 1\n' ' };\n' ' uint; /* MAX_DAQ */\n' ' uint; /* MAX_EVENT_CHANNEL */\n' ' uchar; /* MIN_DAQ */\n' ' enum {\n' ' "OPTIMISATION_TYPE_DEFAULT" = 0,\n' ' "OPTIMISATION_TYPE_ODT_TYPE_16" = 1,\n' ' "OPTIMISATION_TYPE_ODT_TYPE_32" = 2,\n' ' "OPTIMISATION_TYPE_ODT_TYPE_64" = 3,\n' ' "OPTIMISATION_TYPE_ODT_TYPE_ALIGNMENT" = 4,\n' ' "OPTIMISATION_TYPE_MAX_ENTRY_SIZE" = 5\n' ' };\n' ' enum {\n' ' "ADDRESS_EXTENSION_FREE" = 0,\n' ' "ADDRESS_EXTENSION_ODT" = 1,\n' ' "ADDRESS_EXTENSION_DAQ" = 3\n' ' };\n' ' enum {\n' ' "IDENTIFICATION_FIELD_TYPE_ABSOLUTE" = 0,\n' ' "IDENTIFICATION_FIELD_TYPE_RELATIVE_BYTE" = 1,\n' ' "IDENTIFICATION_FIELD_TYPE_RELATIVE_WORD" = 2,\n' ' "IDENTIFICATION_FIELD_TYPE_RELATIVE_WORD_ALIGNED" = 3\n' ' };\n' ' enum {\n' ' "GRANULARITY_ODT_ENTRY_SIZE_DAQ_BYTE" = 1,\n' ' "GRANULARITY_ODT_ENTRY_SIZE_DAQ_WORD" = 2,\n' ' "GRANULARITY_ODT_ENTRY_SIZE_DAQ_DWORD" = 4,\n' ' "GRANULARITY_ODT_ENTRY_SIZE_DAQ_DLONG" = 8\n' ' };\n' ' uchar; /* MAX_ODT_ENTRY_SIZE_DAQ */\n' ' enum {\n' ' "NO_OVERLOAD_INDICATION" = 0,\n' ' "OVERLOAD_INDICATION_PID" = 1,\n' ' "OVERLOAD_INDICATION_EVENT" = 2\n' ' };\n' ' taggedstruct {\n' ' "PRESCALER_SUPPORTED" ;\n' ' "RESUME_SUPPORTED" ;\n' ' block "STIM" struct {\n' ' enum {\n' ' "GRANULARITY_ODT_ENTRY_SIZE_STIM_BYTE" = 1,\n' ' "GRANULARITY_ODT_ENTRY_SIZE_STIM_WORD" = 2,\n' ' "GRANULARITY_ODT_ENTRY_SIZE_STIM_DWORD" = 4,\n' ' "GRANULARITY_ODT_ENTRY_SIZE_STIM_DLONG" = 8\n' ' };\n' ' uchar; /* MAX_ODT_ENTRY_SIZE_STIM */\n' ' taggedstruct {\n' ' "BIT_STIM_SUPPORTED" ;\n' ' };\n' ' };\n' ' block "TIMESTAMP_SUPPORTED" struct {\n' ' uint; /* TIMESTAMP_TICKS */\n' ' enum {\n' ' "NO_TIME_STAMP" = 0,\n' ' "SIZE_BYTE" = 1,\n' ' "SIZE_WORD" = 2,\n' ' "SIZE_DWORD" = 4\n' ' };\n' ' enum {\n' ' "UNIT_1NS" = 0,\n' ' "UNIT_10NS" = 1,\n' ' "UNIT_100NS" = 2,\n' ' "UNIT_1US" = 3,\n' ' "UNIT_10US" = 4,\n' ' "UNIT_100US" = 5,\n' ' "UNIT_1MS" = 6,\n' ' "UNIT_10MS" = 7,\n' ' "UNIT_100MS" = 8,\n' ' "UNIT_1S" = 9\n' ' };\n' ' taggedstruct {\n' ' "TIMESTAMP_FIXED" ;\n' ' };\n' ' };\n' ' "PID_OFF_SUPPORTED" ;\n' ' (block "DAQ_LIST" struct {\n' ' uint; /* DAQ_LIST_NUMBER */\n' ' taggedstruct {\n' ' "DAQ_LIST_TYPE" enum {\n' ' "DAQ" = 1,\n' ' "STIM" = 2,\n' ' "DAQ_STIM" = 3\n' ' };\n' ' "MAX_ODT" uchar;\n' ' "MAX_ODT_ENTRIES" uchar;\n' ' "FIRST_PID" uchar;\n' ' "EVENT_FIXED" uint;\n' ' block "PREDEFINED" taggedstruct {\n' ' (block "ODT" struct {\n' ' uchar; /* ODT number */\n' ' taggedstruct {\n' ' ("ODT_ENTRY" struct {\n' ' uchar; /* ODT_ENTRY number */\n' ' ulong; /* address of element */\n' ' uchar; /* address extension of element */\n' ' uchar; /* size of element [AG] */\n' ' uchar; /* BIT_OFFSET */\n' ' })*;\n' ' };\n' ' })*;\n' ' };\n' ' };\n' ' })*;\n' ' (block "EVENT" struct {\n' ' char[101]; /* EVENT_CHANNEL_NAME */\n' ' char[9]; /* EVENT_CHANNEL_SHORT_NAME */\n' ' uint; /* EVENT_CHANNEL_NUMBER */\n' ' enum {\n' ' "DAQ" = 1,\n' ' "STIM" = 2,\n' ' "DAQ_STIM" = 3\n' ' };\n' ' uchar; /* MAX_DAQ_LIST */\n' ' uchar; /* TIME_CYCLE */\n' ' uchar; /* TIME_UNIT */\n' ' uchar; /* PRIORITY */\n' ' })*;\n' ' };\n' ' };\n' '\n' ' taggedunion Daq_Event {\n' ' "FIXED_EVENT_LIST" taggedstruct {\n' ' ("EVENT" uint)*;\n' ' };\n' ' "VARIABLE" taggedstruct {\n' ' block "AVAILABLE_EVENT_LIST" taggedstruct {\n' ' ("EVENT" uint)*;\n' ' };\n' ' block "DEFAULT_EVENT_LIST" taggedstruct {\n' ' ("EVENT" uint)*;\n' ' };\n' ' };\n' ' };\n' '\n' ' struct Pag {\n' ' uchar; /* MAX_SEGMENTS */\n' ' taggedstruct {\n' ' "FREEZE_SUPPORTED" ;\n' ' };\n' ' };\n' '\n' ' struct Pgm {\n' ' enum {\n' ' "PGM_MODE_ABSOLUTE" = 1,\n' ' "PGM_MODE_FUNCTIONAL" = 2,\n' ' "PGM_MODE_ABSOLUTE_AND_FUNCTIONAL" = 3\n' ' };\n' ' uchar; /* MAX_SECTORS */\n' ' uchar; /* MAX_CTO_PGM */\n' ' taggedstruct {\n' ' (block "SECTOR" struct {\n' ' char[101]; /* SECTOR_NAME */\n' ' uchar; /* SECTOR_NUMBER */\n' ' ulong; /* Address */\n' ' ulong; /* Length */\n' ' uchar; /* CLEAR_SEQUENCE_NUMBER */\n' ' uchar; /* PROGRAM_SEQUENCE_NUMBER */\n' ' uchar; /* PROGRAM_METHOD */\n' ' })*;\n' ' "COMMUNICATION_MODE_SUPPORTED" taggedunion {\n' ' "BLOCK" taggedstruct {\n' ' "SLAVE" ;\n' ' "MASTER" struct {\n' ' uchar; /* MAX_BS_PGM */\n' ' uchar; /* MIN_ST_PGM */\n' ' };\n' ' };\n' ' "INTERLEAVED" uchar; /* QUEUE_SIZE_PGM */\n' ' };\n' ' };\n' ' };\n' '\n' ' struct Segment {\n' ' uchar; /* SEGMENT_NUMBER */\n' ' uchar; /* number of pages */\n' ' uchar; /* ADDRESS_EXTENSION */\n' ' uchar; /* COMPRESSION_METHOD */\n' ' uchar; /* ENCRYPTION_METHOD */\n' ' taggedstruct {\n' ' block "CHECKSUM" struct {\n' ' enum {\n' ' "XCP_ADD_11" = 1,\n' ' "XCP_ADD_12" = 2,\n' ' "XCP_ADD_14" = 3,\n' ' "XCP_ADD_22" = 4,\n' ' "XCP_ADD_24" = 5,\n' ' "XCP_ADD_44" = 6,\n' ' "XCP_CRC_16" = 7,\n' ' "XCP_CRC_16_CITT" = 8,\n' ' "XCP_CRC_32" = 9,\n' ' "XCP_USER_DEFINED" = 255\n' ' };\n' ' taggedstruct {\n' ' "MAX_BLOCK_SIZE" ulong;\n' ' "EXTERNAL_FUNCTION" char[256]; /* Name of the Checksum.DLL */\n' ' };\n' ' };\n' ' (block "PAGE" struct {\n' ' uchar; /* PAGE_NUMBER */\n' ' enum {\n' ' "ECU_ACCESS_NOT_ALLOWED" = 0,\n' ' "ECU_ACCESS_WITHOUT_XCP_ONLY" = 1,\n' ' "ECU_ACCESS_WITH_XCP_ONLY" = 2,\n' ' "ECU_ACCESS_DONT_CARE" = 3\n' ' };\n' ' enum {\n' ' "XCP_READ_ACCESS_NOT_ALLOWED" = 0,\n' ' "XCP_READ_ACCESS_WITHOUT_ECU_ONLY" = 1,\n' ' "XCP_READ_ACCESS_WITH_ECU_ONLY" = 2,\n' ' "XCP_READ_ACCESS_DONT_CARE" = 3\n' ' };\n' ' enum {\n' ' "XCP_WRITE_ACCESS_NOT_ALLOWED" = 0,\n' ' "XCP_WRITE_ACCESS_WITHOUT_ECU_ONLY" = 1,\n' ' "XCP_WRITE_ACCESS_WITH_ECU_ONLY" = 2,\n' ' "XCP_WRITE_ACCESS_DONT_CARE" = 3\n' ' };\n' ' taggedstruct {\n' ' "INIT_SEGMENT" uchar; /* references segment that initialises this page */\n' ' };\n' ' })*;\n' ' (block "ADDRESS_MAPPING" struct {\n' ' ulong; /* source address */\n' ' ulong; /* destination address */\n' ' ulong; /* length */\n' ' })*;\n' ' "PGM_VERIFY" ulong; /* verification value for PGM */\n' ' };\n' ' };\n' '\n' ' taggedstruct Common_Parameters {\n' ' block "PROTOCOL_LAYER" struct Protocol_Layer;\n' ' block "SEGMENT" struct Segment;\n' ' block "DAQ" struct Daq;\n' ' block "PAG" struct Pag;\n' ' block "PGM" struct Pgm;\n' ' block "DAQ_EVENT" taggedunion Daq_Event;\n' ' };\n' '\n' ' struct UDP_IP_Parameters {\n' ' uint; /* XCP on UDP_IP version, currently 0x0100 */\n' ' uint; /* PORT */\n' ' taggedunion {\n' ' "HOST_NAME" char[256];\n' ' "ADDRESS" char[15];\n' ' };\n' ' };\n' '\n' ' block "IF_DATA" taggedunion if_data {\n' ' "XCP" struct {\n' ' taggedstruct Common_Parameters; /* default parameters */\n' ' taggedstruct {\n' ' block "XCP_ON_UDP_IP" struct {\n' ' struct UDP_IP_Parameters; /* specific for UDP_IP */\n' ' taggedstruct Common_Parameters; /* overruling of default */\n' ' };\n' ' };\n' ' };\n' ' };\n' ' /end A2ML\n' '\n' ' /begin MOD_COMMON ""\n' ' BYTE_ORDER MSB_LAST\n' ' ALIGNMENT_BYTE 1\n' ' ALIGNMENT_WORD 1\n' ' ALIGNMENT_LONG 1\n' ' ALIGNMENT_FLOAT32_IEEE 1\n' ' ALIGNMENT_FLOAT64_IEEE 1\n' ' /end MOD_COMMON\n' '\n' ' /begin IF_DATA XCP\n' ' /begin PROTOCOL_LAYER\n' ' 0x0100\n' ' 0x03E8\n' ' 0xC8\n' ' 0x00\n' ' 0x00\n' ' 0x00\n' ' 0x00\n' ' 0x00\n' ' 0x60\n' ' 0x12C\n' ' BYTE_ORDER_MSB_LAST\n' ' ADDRESS_GRANULARITY_BYTE\n' ' OPTIONAL_CMD ALLOC_ODT_ENTRY\n' ' OPTIONAL_CMD ALLOC_ODT\n' ' OPTIONAL_CMD ALLOC_DAQ\n' ' OPTIONAL_CMD FREE_DAQ\n' ' OPTIONAL_CMD GET_DAQ_RESOLUTION_INFO\n' ' OPTIONAL_CMD GET_DAQ_PROCESSOR_INFO\n' ' OPTIONAL_CMD START_STOP_SYNCH\n' ' OPTIONAL_CMD GET_DAQ_CLOCK\n' ' OPTIONAL_CMD START_STOP_DAQ_LIST\n' ' OPTIONAL_CMD GET_DAQ_LIST_MODE\n' ' OPTIONAL_CMD SET_DAQ_LIST_MODE\n' ' OPTIONAL_CMD WRITE_DAQ\n' ' OPTIONAL_CMD SET_DAQ_PTR\n' ' OPTIONAL_CMD CLEAR_DAQ_LIST\n' ' OPTIONAL_CMD SHORT_UPLOAD\n' ' OPTIONAL_CMD UPLOAD\n' ' OPTIONAL_CMD SET_MTA\n' ' OPTIONAL_CMD GET_ID\n' ' OPTIONAL_CMD GET_COMM_MODE_INFO\n' ' OPTIONAL_CMD BUILD_CHECKSUM\n' ' OPTIONAL_CMD SET_SEGMENT_MODE\n' ' OPTIONAL_CMD GET_SEGMENT_MODE\n' ' OPTIONAL_CMD SET_REQUEST\n' ' OPTIONAL_CMD GET_SEED\n' ' OPTIONAL_CMD UNLOCK\n' ' OPTIONAL_CMD COPY_CAL_PAGE\n' ' SEED_AND_KEY_EXTERNAL_FUNCTION Seed_Key.dll' '/* Add name of seed & key dll file here.*/\n' ' /end PROTOCOL_LAYER\n' '\n' ' /begin DAQ\n' ' DYNAMIC\n' ' 0x00\n' ' 0x06\n' ' 0x00\n' ' OPTIMISATION_TYPE_DEFAULT\n' ' ADDRESS_EXTENSION_FREE\n' ' IDENTIFICATION_FIELD_TYPE_ABSOLUTE\n' ' GRANULARITY_ODT_ENTRY_SIZE_DAQ_BYTE\n' ' 0x60\n' ' NO_OVERLOAD_INDICATION\n' ' /begin TIMESTAMP_SUPPORTED\n' ' 0x01\n' ' SIZE_DWORD\n' ' UNIT_100US\n' ' TIMESTAMP_FIXED\n' ' /end TIMESTAMP_SUPPORTED\n' '\n' '$events\n' ' /end DAQ\n' '\n' ' /begin PAG\n' ' 0x01\n' ' FREEZE_SUPPORTED\n' ' /end PAG\n' ' /begin PGM\n' ' PGM_MODE_ABSOLUTE\n' ' 0x01\n' ' 0x00\n' ' /begin SECTOR\n' ' "Sector"\n' ' 0x00\n' ' 0x22014\n' ' 0x38\n' ' 0x00\n' ' 0x00\n' ' 0x00\n' ' /end SECTOR\n' ' /end PGM\n' '\n' ' /begin XCP_ON_UDP_IP\n' ' 0x0100\n' ' $ip_port\n' ' ADDRESS "$ip_address"\n' ' /end XCP_ON_UDP_IP\n' ' /end IF_DATA\n' '\n' ' /begin MOD_PAR ""\n' ' /begin MEMORY_SEGMENT\n' ' caldata "caldata"\n' ' DATA FLASH INTERN 0x00000 0x0000 -1 -1 -1 -1 -1\n' ' /begin IF_DATA XCP\n' ' /begin SEGMENT\n' ' 0x00\n' ' 0x02\n' ' 0x00\n' ' 0x00\n' ' 0x00\n' ' /begin CHECKSUM\n' ' XCP_CRC_16_CITT\n' ' /end CHECKSUM\n' ' /begin PAGE\n' ' 0x00\n' ' ECU_ACCESS_WITH_XCP_ONLY\n' ' XCP_READ_ACCESS_WITH_ECU_ONLY\n' ' XCP_WRITE_ACCESS_NOT_ALLOWED\n' ' INIT_SEGMENT 0x00\n' ' /end PAGE\n' ' /begin PAGE\n' ' 0x01\n' ' ECU_ACCESS_WITH_XCP_ONLY\n' ' XCP_READ_ACCESS_WITH_ECU_ONLY\n' ' XCP_WRITE_ACCESS_WITH_ECU_ONLY\n' ' INIT_SEGMENT 0x00\n' ' /end PAGE\n' ' /end SEGMENT\n' ' /end IF_DATA\n' ' /end MEMORY_SEGMENT\n' ' /begin MEMORY_SEGMENT\n' ' text ".text"\n' ' CODE ROM INTERN 0x26030 0x72c10 -1 -1 -1 -1 -1\n' ' /begin IF_DATA XCP\n' ' /begin SEGMENT\n' ' 0x01\n' ' 0x01\n' ' 0x00\n' ' 0x00\n' ' 0x00\n' ' /begin CHECKSUM\n' ' XCP_CRC_16_CITT\n' ' /end CHECKSUM\n' ' /begin PAGE\n' ' 0x01\n' ' ECU_ACCESS_WITH_XCP_ONLY\n' ' XCP_READ_ACCESS_WITH_ECU_ONLY\n' ' XCP_WRITE_ACCESS_WITH_ECU_ONLY\n' ' INIT_SEGMENT 0x00\n' ' /end PAGE\n' ' /end SEGMENT\n' ' /end IF_DATA\n' ' /end MEMORY_SEGMENT\n' ' /end MOD_PAR\n' '\n' ' /begin COMPU_METHOD BitSlice.CONVERSION ""\n' ' RAT_FUNC "%6.2f" ""\n' ' COEFFS 0 1 0 0 0 1\n' ' /end COMPU_METHOD\n' '\n' ' /* SPM declarations start. */\n' '\n' '$spm_a2l\n' '\n' ' /* SPM declarations end. */\n' '\n' ' /begin RECORD_LAYOUT __UBYTE_Z\n' ' FNC_VALUES 1 UBYTE ROW_DIR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT __UWORD_Z\n' ' FNC_VALUES 1 UWORD ROW_DIR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT __ULONG_Z\n' ' FNC_VALUES 1 ULONG ROW_DIR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT __SBYTE_Z\n' ' FNC_VALUES 1 SBYTE ROW_DIR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT __SWORD_Z\n' ' FNC_VALUES 1 SWORD ROW_DIR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT __SLONG_Z\n' ' FNC_VALUES 1 SLONG ROW_DIR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT __FLOAT32_IEEE_Z\n' ' FNC_VALUES 1 FLOAT32_IEEE ROW_DIR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT __FLOAT64_IEEE_Z\n' ' FNC_VALUES 1 FLOAT64_IEEE ROW_DIR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT __UBYTE_S\n' ' FNC_VALUES 1 UBYTE COLUMN_DIR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT __UWORD_S\n' ' FNC_VALUES 1 UWORD COLUMN_DIR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT __ULONG_S\n' ' FNC_VALUES 1 ULONG COLUMN_DIR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT __SBYTE_S\n' ' FNC_VALUES 1 SBYTE COLUMN_DIR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT __SWORD_S\n' ' FNC_VALUES 1 SWORD COLUMN_DIR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT __SLONG_S\n' ' FNC_VALUES 1 SLONG COLUMN_DIR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT __FLOAT32_IEEE_S\n' ' FNC_VALUES 1 FLOAT32_IEEE COLUMN_DIR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT __FLOAT64_IEEE_S\n' ' FNC_VALUES 1 FLOAT64_IEEE COLUMN_DIR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT SSV__UBYTE_S\n' ' AXIS_PTS_X 1 UBYTE INDEX_INCR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT SSV__UWORD_S\n' ' AXIS_PTS_X 1 UWORD INDEX_INCR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT SSV__ULONG_S\n' ' AXIS_PTS_X 1 ULONG INDEX_INCR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT SSV__SBYTE_S\n' ' AXIS_PTS_X 1 SBYTE INDEX_INCR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT SSV__SWORD_S\n' ' AXIS_PTS_X 1 SWORD INDEX_INCR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT SSV__SLONG_S\n' ' AXIS_PTS_X 1 SLONG INDEX_INCR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT SSV__FLOAT32_IEEE_S\n' ' AXIS_PTS_X 1 FLOAT32_IEEE INDEX_INCR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /begin RECORD_LAYOUT SSV__FLOAT64_IEEE_S\n' ' AXIS_PTS_X 1 FLOAT64_IEEE INDEX_INCR DIRECT\n' ' /end RECORD_LAYOUT\n' '\n' ' /end MODULE\n' '/end PROJECT\n' ) def render(self): """Render the complete A2L. Returns: a2l (str): The A2L for the project. """ event_a2l = '' for event in self.events: event_a2l += self.event_template.substitute( name=event['name'], short_name=event['name'], channel_id=event['channel_id'], time_cycle=event['time_cycle'], time_unit=event['time_unit'] ) return self.template.substitute( events=event_a2l, asap2_version=self.asap2_version, project_name=self.project_name.replace('-', '_'), ip_address=self.ip_address, ip_port=self.ip_port, spm_a2l=self.spm_a2l ) class A2lSilverTemplate: """Class for A2l Silver Template.""" def __init__(self, base_a2l): """Init.""" self.patched_a2l = self.basic_patching(base_a2l) self.template = Template( '/* QTronic Header */\n' 'ASAP2_VERSION 1 6\n' '/begin PROJECT SPM ""\n' '/begin MODULE SPM ""\n' '\n' '$base_a2l' '\n' '/end MODULE\n' '/end PROJECT' ) @staticmethod def basic_patching(base_a2l): """Perform required basic patching. Args: base_a2l (str): Inital A2l content. Returns: (str): Patched A2L content. """ return "".join([char if ord(char) < 128 else "?" for char in base_a2l]) def render(self): """Render the complete A2L. Returns: (str): The patched A2L for Silver. """ if "ASAP2_VERSION" in self.patched_a2l[:999]: return self.patched_a2l return self.template.substitute(base_a2l=self.patched_a2l)