根据ARXML中报文信息生成SWC(二)
集成的时候只有dbcasw使用的时候需要手动一个个创建port interface、runnable、runnable的event、每个runnable对应的rport、pport、port initvalue太麻烦了于是自动化脚本实现提高开发效率。1、gen_swc_from_can.py#!/usr/bin/env python3 Script: gen_swc_from_can.py Parse J1939 CAN database ARXML and generate DaVinci Developer SWC files. For each ECU node, generates: - One SENDER-RECEIVER-INTERFACE per signal (in shared PortInterfaces file) - One APPLICATION-SW-COMPONENT-TYPE with: - PPort for TX signals, RPort for RX signals - One Runnable per PDU/direction based on cycle time import xml.etree.ElementTree as ET import uuid as uuid_lib import os import sys from collections import defaultdict # ─── Configuration ─────────────────────────────────────────────────────────── INPUT_ARXML rd:\workspace\Demo\davinci\ImportFiles\Databases\CHA_CAN.arxml OUTPUT_DIR rd:\workspace\Demo\davinci\ImportFiles\Swcs PORT_IF_DIR os.path.join(OUTPUT_DIR, PortInterfaces_J1939.arxml) # ARXML settings AR_SCHEMA http://autosar.org/schema/r4.0 AR_XSI http://autosar.org/schema/r4.0 AUTOSAR_00050.xsd # ─── Helpers ────────────────────────────────────────────────────────────────── _new_uuids {} # cache deterministic UUIDs by key def make_uuid(key): Generate a deterministic UUID based on a string key. if key not in _new_uuids: _new_uuids[key] str(uuid_lib.uuid5(uuid_lib.NAMESPACE_DNS, key j1939swc)).upper() return _new_uuids[key] def indent(elem, level0, spaces_per2): Pretty-print indentation for ElementTree (in-place). s \n * (level * spaces_per) if len(elem): if not elem.text or not elem.text.strip(): elem.text s * spaces_per if not elem.tail or not elem.tail.strip(): elem.tail s for child in elem: indent(child, level 1, spaces_per) if not child.tail or not child.tail.strip(): child.tail s else: if level and (not elem.tail or not elem.tail.strip()): elem.tail s def SubElement(parent, tag, textNone, **attribs): Create a sub-element and return it, with optional text and attribs. elem ET.SubElement(parent, tag, **attribs) if text is not None: elem.text text return elem def arxml_preamble(): Return a minimal root ET.Element for a new ARXML file. root ET.Element( AUTOSAR, attrib{ {http://www.w3.org/2001/XMLSchema-instance}schemaLocation: AR_XSI, }, ) root.set(xmlns, AR_SCHEMA) # xmlns:xsi is already defined by the xsi:schemaLocation attribute above return root def arxml_element(root, short_name, uuid_key): Build the standard AR-PACKAGES AR-PACKAGE ... structure. Returns (ar_package_root, elements_parent) tuple. ar_packages SubElement(root, AR-PACKAGES) ar_package SubElement(ar_packages, AR-PACKAGE) SubElement(ar_package, SHORT-NAME, textshort_name) elements SubElement(ar_package, ELEMENTS) return ar_package, elements def _write_arxml(root_elem, filepath): Write an ARXML file from an ElementTree root element. Handles namespace formatting to match DaVinci Developer convention. ET.register_namespace(, AR_SCHEMA) raw ET.tostring(root_elem, encodingutf-8) # ElementTree with register_namespace(, ...) uses ns0: prefix # Replace to get clean default namespace output raw raw.replace(bns0:, b).replace(b xmlns:ns0, b xmlns) # Write the file with open(filepath, wb) as f: f.write(b?xml version1.0 encodingutf-8?\n) f.write(raw) def data_type_for_length(length_bits): Map signal length (bits) to AUTOSAR ImplementationDataType reference. if length_bits 8: return /AUTOSAR_Platform/ImplementationDataTypes/uint8 elif length_bits 16: return /AUTOSAR_Platform/ImplementationDataTypes/uint16 else: return /AUTOSAR_Platform/ImplementationDataTypes/uint32 def make_sender_receiver_interface(signal_name, data_type_ref): Create a SENDER-RECEIVER-INTERFACE element for one signal. sri ET.Element(SENDER-RECEIVER-INTERFACE, UUIDmake_uuid(fsri_{signal_name})) SubElement(sri, SHORT-NAME, textfPi{signal_name}) SubElement(sri, IS-SERVICE, textfalse) data_elems SubElement(sri, DATA-ELEMENTS) vdp SubElement(data_elems, VARIABLE-DATA-PROTOTYPE, UUIDmake_uuid(fvdp_{signal_name})) SubElement(vdp, SHORT-NAME, textfDe{signal_name}) sdv SubElement(vdp, SW-DATA-DEF-PROPS) sdvv SubElement(sdv, SW-DATA-DEF-PROPS-VARIANTS) sdvc SubElement(sdvv, SW-DATA-DEF-PROPS-CONDITIONAL) SubElement(sdvc, SW-CALIBRATION-ACCESS, textNOT-ACCESSIBLE) SubElement(vdp, TYPE-TREF, DESTIMPLEMENTATION-DATA-TYPE, textdata_type_ref) return sri def make_swc(ecu_name, tx_signal_names, rx_signal_names, signal_pdu_cycle_map): Create APPLICATION-SW-COMPONENT-TYPE for one ECU. signal_pdu_cycle_map: dict { signal_name - (pdu_name, cycle_sec, direction:Tx|Rx) } swc ET.Element(APPLICATION-SW-COMPONENT-TYPE, UUIDmake_uuid(fswc_{ecu_name})) SubElement(swc, SHORT-NAME, textfCtAp{ecu_name}) # ── Ports ────────────────────────────────────────────────────────────── ports SubElement(swc, PORTS) # All unique signal names (both TX and RX) for this ECU all_signals list(dict.fromkeys(tx_signal_names rx_signal_names)) # preserve order, deduplicate all_signals_set set(all_signals) for sig in all_signals: if sig in tx_signal_names: # P-PORT-PROTOTYPE (Provider) pp SubElement(ports, P-PORT-PROTOTYPE, UUIDmake_uuid(fpp_{ecu_name}_{sig})) SubElement(pp, SHORT-NAME, textfPp{sig}) # COM-SPECS with init value pcs SubElement(pp, PROVIDED-COM-SPECS) nscs SubElement(pcs, NONQUEUED-SENDER-COM-SPEC) SubElement(nscs, DATA-ELEMENT-REF, DESTVARIABLE-DATA-PROTOTYPE, textf/UserApplication/SwcJ1939/PortInterfaces/Pi{sig}/De{sig}) iv SubElement(nscs, INIT-VALUE) nvs SubElement(iv, NUMERICAL-VALUE-SPECIFICATION) SubElement(nvs, VALUE, text0) SubElement(pp, PROVIDED-INTERFACE-TREF, DESTSENDER-RECEIVER-INTERFACE, textf/UserApplication/SwcJ1939/PortInterfaces/Pi{sig}) if sig in rx_signal_names: # R-PORT-PROTOTYPE (Require) rp SubElement(ports, R-PORT-PROTOTYPE, UUIDmake_uuid(frp_{ecu_name}_{sig})) SubElement(rp, SHORT-NAME, textfRp{sig}) # COM-SPECS with init value rcs SubElement(rp, REQUIRED-COM-SPECS) nrcs SubElement(rcs, NONQUEUED-RECEIVER-COM-SPEC) SubElement(nrcs, DATA-ELEMENT-REF, DESTVARIABLE-DATA-PROTOTYPE, textf/UserApplication/SwcJ1939/PortInterfaces/Pi{sig}/De{sig}) SubElement(nrcs, ALIVE-TIMEOUT, text0) SubElement(nrcs, ENABLE-UPDATE, texttrue) flt SubElement(nrcs, FILTER) SubElement(flt, DATA-FILTER-TYPE, textALWAYS) SubElement(nrcs, HANDLE-NEVER-RECEIVED, textfalse) iv SubElement(nrcs, INIT-VALUE) nvs SubElement(iv, NUMERICAL-VALUE-SPECIFICATION) SubElement(nvs, VALUE, text0) SubElement(rp, REQUIRED-INTERFACE-TREF, DESTSENDER-RECEIVER-INTERFACE, textf/UserApplication/SwcJ1939/PortInterfaces/Pi{sig}) # ── Internal Behavior ────────────────────────────────────────────────── ib SubElement(swc, INTERNAL-BEHAVIORS) swc_ib SubElement(ib, SWC-INTERNAL-BEHAVIOR, UUIDmake_uuid(fib_{ecu_name})) SubElement(swc_ib, SHORT-NAME, textfCtAp{ecu_name}_InternalBehavior) # ── Exclusive Areas (under SWC-INTERNAL-BEHAVIOR) ── eas SubElement(swc_ib, EXCLUSIVE-AREAS) ea SubElement(eas, EXCLUSIVE-AREA, UUIDmake_uuid(fea_beh_{ecu_name})) SubElement(ea, SHORT-NAME, textEaJ1939) # ── Events (before RUNNABLES per AUTOSAR schema) ───────────────────── events SubElement(swc_ib, EVENTS) # ── Runnables ────────────────────────────────────────────────────────── runnables SubElement(swc_ib, RUNNABLES) # Build runnables grouped by (PDU, direction) to avoid duplicates # Each runnable handles all signals of one PDU in one direction pdu_dir_signals defaultdict(set) # (pdu_name, direction) - set of signal_name pdu_dir_cycle {} # (pdu_name, direction) - cycle_sec for sig, entries in signal_pdu_cycle_map.items(): for (pdu, cycle_sec, direction) in entries: key (pdu, direction) pdu_dir_signals[key].add(sig) # Use the shortest cycle for this PDUdirection if key not in pdu_dir_cycle or cycle_sec pdu_dir_cycle[key]: pdu_dir_cycle[key] cycle_sec for (pdu_name, direction), signals_in_pdu in pdu_dir_signals.items(): cycle_sec pdu_dir_cycle[(pdu_name, direction)] cycle_ms int(float(cycle_sec) * 1000) run_name fRE_{pdu_name}_{direction}_{cycle_ms:04d}ms # Timing Event for this cyclic runnable tm_event SubElement(events, TIMING-EVENT, UUIDmake_uuid(ftm_evt_{ecu_name}_{pdu_name}_{direction})) SubElement(tm_event, SHORT-NAME, textfTMT_{run_name}) SubElement(tm_event, START-ON-EVENT-REF, DESTRUNNABLE-ENTITY, textf/UserApplication/SwcJ1939/ComponentTypes/CtAp{ecu_name}/CtAp{ecu_name}_InternalBehavior/{run_name}) SubElement(tm_event, PERIOD, textstr(float(cycle_sec))) re SubElement(runnables, RUNNABLE-ENTITY, UUIDmake_uuid(fre_{ecu_name}_{pdu_name}_{direction})) SubElement(re, SHORT-NAME, textrun_name) SubElement(re, MINIMUM-START-INTERVAL, textstr(float(cycle_sec))) SubElement(re, CAN-BE-INVOKED-CONCURRENTLY, textfalse) if direction Rx: drpba SubElement(re, DATA-RECEIVE-POINT-BY-ARGUMENTS) for sig in signals_in_pdu: va SubElement(drpba, VARIABLE-ACCESS, UUIDmake_uuid(fva_rx_{ecu_name}_{pdu_name}_{sig})) SubElement(va, SHORT-NAME, textfREC_Pi{sig}_De{sig}) av SubElement(va, ACCESSED-VARIABLE) avi SubElement(av, AUTOSAR-VARIABLE-IREF) SubElement(avi, PORT-PROTOTYPE-REF, DESTR-PORT-PROTOTYPE, textf/UserApplication/SwcJ1939/ComponentTypes/CtAp{ecu_name}/Rp{sig}) SubElement(avi, TARGET-DATA-PROTOTYPE-REF, DESTVARIABLE-DATA-PROTOTYPE, textf/UserApplication/SwcJ1939/PortInterfaces/Pi{sig}/De{sig}) else: # Tx dsp SubElement(re, DATA-SEND-POINTS) for sig in signals_in_pdu: va SubElement(dsp, VARIABLE-ACCESS, UUIDmake_uuid(fva_tx_{ecu_name}_{pdu_name}_{sig})) SubElement(va, SHORT-NAME, textfSEND_Pi{sig}_De{sig}) av SubElement(va, ACCESSED-VARIABLE) avi SubElement(av, AUTOSAR-VARIABLE-IREF) SubElement(avi, PORT-PROTOTYPE-REF, DESTP-PORT-PROTOTYPE, textf/UserApplication/SwcJ1939/ComponentTypes/CtAp{ecu_name}/Pp{sig}) SubElement(avi, TARGET-DATA-PROTOTYPE-REF, DESTVARIABLE-DATA-PROTOTYPE, textf/UserApplication/SwcJ1939/PortInterfaces/Pi{sig}/De{sig}) # SYMBOL must be last child per AUTOSAR schema order SubElement(re, SYMBOL, textrun_name) # If no runnables were created (edge case), ensure RUNNABLES exists if len(pdu_dir_signals) 0: # Remove the empty RUNNABLES swc_ib.remove(runnables) # SUPPORTS-MULTIPLE-INSTANTIATION must come after RUNNABLES per AUTOSAR schema order SubElement(swc_ib, SUPPORTS-MULTIPLE-INSTANTIATION, textfalse) return swc def make_swc_implementation(ecu_name): Create SWC-IMPLEMENTATION element for one ECU. impl ET.Element(SWC-IMPLEMENTATION, UUIDmake_uuid(fimpl_{ecu_name})) SubElement(impl, SHORT-NAME, textfCtAp{ecu_name}_Implementation) SubElement(impl, BEHAVIOR-REF, DESTSWC-INTERNAL-BEHAVIOR, textf/UserApplication/SwcJ1939/ComponentTypes/CtAp{ecu_name}/CtAp{ecu_name}_InternalBehavior) return impl # ─── Main parsing logic ─────────────────────────────────────────────────────── def parse_arxml(filepath): Parse the CAN ARXML and extract ECU/Signal/PDU relationships. tree ET.parse(filepath) root tree.getroot() ns {ar: AR_SCHEMA} # ── 1. Collect ECUs ──────────────────────────────────────────────────── ecus set() # Get ECUs from NM nodes for nm_node in root.iter({http://autosar.org/schema/r4.0}J-1939-NM-NODE): sn nm_node.find(ar:SHORT-NAME, ns) if sn is not None and sn.text: ecus.add(sn.text) print(fFound {len(ecus)} ECUs: {, .join(sorted(ecus))}) # ── 2. I-SIGNAL definitions: ISignalName - (length_bits, base_type_ref) ── isignal_info {} # ISignalShortName - length (bits) for isig in root.iter({http://autosar.org/schema/r4.0}I-SIGNAL): sn isig.find(ar:SHORT-NAME, ns) length_el isig.find(ar:LENGTH, ns) if sn is not None and length_el is not None: isignal_info[sn.text] int(length_el.text) print(fFound {len(isignal_info)} I-SIGNALs) # ── 3. I-SIGNAL-TRIGGERING: signal - {Tx: ecu, Rx: [ecus]} ── sig_triggering {} # ST_name - (isignal_ref, [(ecu, direction)]) sig_to_ecu defaultdict(lambda: {Tx: [], Rx: []}) # ISignalShortName - {Tx:[ecu], Rx:[ecus]} for ist in root.iter({http://autosar.org/schema/r4.0}I-SIGNAL-TRIGGERING): st_name ist.find(ar:SHORT-NAME, ns) isig_ref ist.find(ar:I-SIGNAL-REF, ns) if st_name is None or isig_ref is None: continue isig_name isig_ref.text.split(/)[-1] # Get the ISignal short name port_refs ist.find(ar:I-SIGNAL-PORT-REFS, ns) if port_refs is None: continue ecu_dirs [] for port_ref in port_refs.findall(ar:I-SIGNAL-PORT-REF, ns): port_path port_ref.text # /ECU/{ECU}/CN_CHA_CAN/SP_{signal}_{Tx|Rx} if port_path: parts port_path.split(/) ecu_name parts[2] # /ECU/{ECU}/... port_name parts[4] # SP_{signal}_{Tx|Rx} direction Tx if port_name.endswith(_Tx) else Rx ecu_dirs.append((ecu_name, direction)) sig_to_ecu[isig_name][direction].append(ecu_name) sig_triggering[st_name.text] { isignal_ref: isig_name, ecu_dirs: ecu_dirs, } print(fFound {len(sig_triggering)} I-SIGNAL-TRIGGERINGs) # ── 4. PDU-TRIGGERING: PDU - {Tx: ecu, Rx: [ecus], signals: [ST_refs], PDU_ref} ── pdu_triggering {} for pt in root.iter({http://autosar.org/schema/r4.0}PDU-TRIGGERING): pt_name pt.find(ar:SHORT-NAME, ns) pdu_ref pt.find(ar:I-PDU-REF, ns) if pt_name is None or pdu_ref is None: continue pdu_short pdu_ref.text.split(/)[-1] # e.g. ABS_DM1_oCHA_CAN # PDU port refs port_refs pt.find(ar:I-PDU-PORT-REFS, ns) ecu_dirs [] if port_refs is not None: for port_ref in port_refs.findall(ar:I-PDU-PORT-REF, ns): port_path port_ref.text if port_path: parts port_path.split(/) ecu_name parts[2] port_name parts[4] direction Tx if port_name.endswith(_Tx) else Rx ecu_dirs.append((ecu_name, direction)) # Signal triggering refs sig_refs [] sig_trig_container pt.find(ar:I-SIGNAL-TRIGGERINGS, ns) if sig_trig_container is not None: for strc in sig_trig_container.findall(ar:I-SIGNAL-TRIGGERING-REF-CONDITIONAL, ns): str_ref strc.find(ar:I-SIGNAL-TRIGGERING-REF, ns) if str_ref is not None and str_ref.text: sig_refs.append(str_ref.text) pdu_triggering[pt_name.text] { pdu_ref: pdu_short, ecu_dirs: ecu_dirs, sig_triggering_refs: sig_refs, } print(fFound {len(pdu_triggering)} PDU-TRIGGERINGs) # ── 5. I-SIGNAL-I-PDU: PDU timing ────────────────────────────────────── pdu_cycle_time {} # pdu_short_name - cycle_time_seconds for pdu in root.iter({http://autosar.org/schema/r4.0}I-SIGNAL-I-PDU): pdu_sn pdu.find(ar:SHORT-NAME, ns) if pdu_sn is None: continue # Get the first TIME-PERIOD.VALUE for tp in pdu.iter({http://autosar.org/schema/r4.0}TIME-PERIOD): val tp.find(ar:VALUE, ns) if val is not None and val.text: pdu_cycle_time[pdu_sn.text] float(val.text) break # use the first cycle time (usually both are the same) print(fFound {len(pdu_cycle_time)} PDUs with cycle time) return { ecus: ecus, isignal_info: isignal_info, sig_to_ecu: sig_to_ecu, sig_triggering: sig_triggering, pdu_triggering: pdu_triggering, pdu_cycle_time: pdu_cycle_time, } def build_ecu_data(parsed): Build per-ECU data from parsed structures. ecus parsed[ecus] isignal_info parsed[isignal_info] sig_to_ecu parsed[sig_to_ecu] pdu_triggering parsed[pdu_triggering] pdu_cycle_time parsed[pdu_cycle_time] # ── Build ISignal name - system signal name mapping ────────────────── # ISignal names look like: ABS_Active_oABS_EBC1_oCHA_CAN # System signal names: ABS_Active # We need a shorter name for the port interface. # Extract signal name from ISignal triggering name. # The ISignal SHORT-NAME format is: {SYS_SIGNAL}_{originPDU}_{bus} # Simpler: from sig_triggering - isignal_ref (ISignal short name) # Well map ISignal - port interface signal name (the system signal part) # Build: isignal_name - port_signal_name isig_to_portsig {} for isig_name in isignal_info: # Pattern: SIGNALNAME_oPDU_oBUS - SIGNALNAME # Most J1939 signals follow this pattern parts isig_name.split(_o) if len(parts) 2: portsig parts[0] else: portsig isig_name isig_to_portsig[isig_name] portsig # ── Build PDU - signals (ISignal names) mapping ────────────────────── # From ST refs - ST name - ISignal name st_to_isig {} # ST (Signal Triggering) name - ISignal name for st_name, st_data in parsed[sig_triggering].items(): st_to_isig[st_name] st_data[isignal_ref] # ── For each ECU, collect TX/RX signals with PDUcycle ──────────────── ecu_signals defaultdict(lambda: {tx: set(), rx: set()}) # signal_name - set of (pdu_name, cycle_sec, direction) (no duplicates) signal_pdu_cycle defaultdict(set) for pt_name, pt_data in pdu_triggering.items(): pdu_ref pt_data[pdu_ref] cycle_sec pdu_cycle_time.get(pdu_ref, 1.0) # default 1s if not found # Which ECUs are TX/RX for this PDU pdu_tx_ecu None pdu_rx_ecus [] for ecu, direction in pt_data[ecu_dirs]: if direction Tx: pdu_tx_ecu ecu else: pdu_rx_ecus.append(ecu) # Get unique ISignal names for this PDU (deduplicate) isig_names set() for st_ref in pt_data[sig_triggering_refs]: # ST ref looks like: /Cluster/CHA_CAN/CHNL/ST_ABS_Active_oABS_EBC1 st_name st_ref.split(/)[-1] isig_name st_to_isig.get(st_name) if isig_name: isig_names.add(isig_name) # Map ISignal names - port signal names for isig_name in isig_names: portsig isig_to_portsig.get(isig_name, isig_name) if pdu_tx_ecu: ecu_signals[pdu_tx_ecu][tx].add(portsig) signal_pdu_cycle[portsig].add((pdu_ref, cycle_sec, Tx)) for rx_ecu in pdu_rx_ecus: ecu_signals[rx_ecu][rx].add(portsig) signal_pdu_cycle[portsig].add((pdu_ref, cycle_sec, Rx)) return { ecu_signals: ecu_signals, signal_pdu_cycle: signal_pdu_cycle, isignal_info: isignal_info, isig_to_portsig: isig_to_portsig, } def generate_output(parsed, ecu_data): Generate ARXML output files. os.makedirs(OUTPUT_DIR, exist_okTrue) ecus sorted(parsed[ecus]) isignal_info parsed[isignal_info] isig_to_portsig ecu_data[isig_to_portsig] ecu_signals ecu_data[ecu_signals] signal_pdu_cycle ecu_data[signal_pdu_cycle] # ── Collect all unique signal names across all ECUs ──────────────────── all_signals set() for ecu in ecus: all_signals.update(ecu_signals[ecu][tx]) all_signals.update(ecu_signals[ecu][rx]) all_signals sorted(all_signals) # Build ISignal name - port signal - ISignal length mapping portsig_to_isig {} for isig_name, portsig in isig_to_portsig.items(): portsig_to_isig[portsig] isig_name # ── 1. Generate PortInterfaces file ──────────────────────────────────── pi_root arxml_preamble() mxl_pkg, mxl_elements arxml_element(pi_root, UserApplication, mxl) mxl_sub_pkgs SubElement(mxl_pkg, AR-PACKAGES) swc_pkg SubElement(mxl_sub_pkgs, AR-PACKAGE) SubElement(swc_pkg, SHORT-NAME, textSwcJ1939) pi_sub_pkgs SubElement(swc_pkg, AR-PACKAGES) pi_pkg SubElement(pi_sub_pkgs, AR-PACKAGE) SubElement(pi_pkg, SHORT-NAME, textPortInterfaces) pi_elements SubElement(pi_pkg, ELEMENTS) # Remove empty ELEMENTS from UserApplication package mxl_pkg.remove(mxl_elements) for sig in all_signals: isig_name portsig_to_isig.get(sig, sig) length isignal_info.get(isig_name, 8) dt_ref data_type_for_length(length) sri make_sender_receiver_interface(sig, dt_ref) pi_elements.append(sri) indent(pi_root) # Write PortInterfaces file _write_arxml(pi_root, PORT_IF_DIR) print(f[OK] Written: {PORT_IF_DIR}) print(f - {len(all_signals)} SENDER-RECEIVER-INTERFACEs) # ── 2. Generate ComponentType file for each ECU ──────────────────────── for ecu in ecus: tx_sigs sorted(ecu_signals[ecu][tx]) rx_sigs sorted(ecu_signals[ecu][rx]) # Filter signal_pdu_cycle_map for this ECUs signals only ecu_sig_pdu {} for sig in tx_sigs rx_sigs: entries signal_pdu_cycle.get(sig, set()) # Only include entries where direction matches this ECUs role filtered [] for (pdu, cycle, direction) in entries: # For TX: only TX entries where this ECU was TX # For RX: only RX entries keep False if sig in tx_sigs and direction Tx: keep True if sig in rx_sigs and direction Rx: keep True if keep: filtered.append((pdu, cycle, direction)) if filtered: ecu_sig_pdu[sig] filtered swc_root arxml_preamble() # Package: UserApplication - SwcJ1939 - ComponentTypes mxl_pkg2, mxl_elem2 arxml_element(swc_root, UserApplication, mxl_ct_ ecu) mxl_sub_pkgs2 SubElement(mxl_pkg2, AR-PACKAGES) swc_pkg2 SubElement(mxl_sub_pkgs2, AR-PACKAGE) SubElement(swc_pkg2, SHORT-NAME, textSwcJ1939) swc_sub_pkgs SubElement(swc_pkg2, AR-PACKAGES) ct_pkg SubElement(swc_sub_pkgs, AR-PACKAGE) SubElement(ct_pkg, SHORT-NAME, textComponentTypes) ct_elements SubElement(ct_pkg, ELEMENTS) swc make_swc(ecu, tx_sigs, rx_sigs, ecu_sig_pdu) ct_elements.append(swc) impl make_swc_implementation(ecu) ct_elements.append(impl) # Remove empty ELEMENTS from UserApplication package mxl_pkg2.remove(mxl_elem2) indent(swc_root) comp_file os.path.join(OUTPUT_DIR, fCtAp{ecu}.arxml) _write_arxml(swc_root, comp_file) print(f[OK] Written: {comp_file}) print(f - TX signals: {len(tx_sigs)}, RX signals: {len(rx_sigs)}) # Count runnables run_count 0 if len(ecu_sig_pdu) 0: # collect unique (pdu, direction) pairs seen set() for entries in ecu_sig_pdu.values(): for (pdu, cycle, direction) in entries: seen.add((pdu, direction)) run_count len(seen) print(f - Runnables: {run_count}) # ─── Entry point ────────────────────────────────────────────────────────────── def main(): print( * 60) print(J1939 SWC Generator) print( * 60) print(fInput: {INPUT_ARXML}) print(fOutput: {OUTPUT_DIR}) print() parsed parse_arxml(INPUT_ARXML) ecu_data build_ecu_data(parsed) generate_output(parsed, ecu_data) print() print(Done! Files generated:) print(f 1. {PORT_IF_DIR}) for ecu in sorted(parsed[ecus]): print(f {os.path.join(OUTPUT_DIR, fCtAp{ecu}.arxml)}) print() if __name__ __main__: main()提示只需指定以下三个参数内容即可INPUT_ARXML 输入arxml文件路径OUTPUT_DIR 输出文件夹路径PORT_IF_DIR 输出port文件路径最终生成如下文件实际根据用户arxml中ECU节点生成对应的swc其中

相关新闻

Erupt 接入 S3 兼容对象存储:用 @EruptS3 将对象桶变成可管理的只读数据源

Erupt 接入 S3 兼容对象存储:用 @EruptS3 将对象桶变成可管理的只读数据源

后端低代码AI 应用人工智能AI Agent认证鉴权RAG 【免费下载链接】erupt 🚀 通用数据管理框架,VORM 对象视图模型,注解驱动低代码开发 项目地址: https://gitcode.com/erupts/erupt 点击查看 免费下载 本指南基于 Erupt 仓库中的 …

2026/10/15 3:48:43 阅读更多 →
如何找到真正合适的伴侣?【心动看互补,长久看本能】

如何找到真正合适的伴侣?【心动看互补,长久看本能】

核心主旨:所有婚恋困惑、错爱、感情内耗,本质都是分不清「生物情绪冲动」和「人格底层适配」。本文依托发展心理学、人格心理学、婚恋行为学权威研究,系统性拆解心动的本质、不合适的根源、长久关系的核心法则。前言:绝大多数人的…

2026/10/15 3:48:43 阅读更多 →
Shiny TypeScript 类型定义包 @posit/shiny:安装、使用与源码构建指南

Shiny TypeScript 类型定义包 @posit/shiny:安装、使用与源码构建指南

后端Web框架前端 【免费下载链接】shiny Easy interactive web applications with R 项目地址: https://gitcode.com/gh_mirrors/sh/shiny 点击查看 免费下载 导读 posit/shiny 是 Shiny 项目发布的 npm 包,专门为 Shiny 客户端 JavaScript 库&#xf…

2026/10/15 3:48:43 阅读更多 →

最新新闻

MIPS核心指令硬件原理与工程避坑指南

MIPS核心指令硬件原理与工程避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 4:46:53 阅读更多 →
iOS应用代码保护与Ipa Guard命令行自动化集成指南

iOS应用代码保护与Ipa Guard命令行自动化集成指南

1. 项目背景与核心价值在iOS应用开发领域,代码保护一直是开发者关注的重点。随着移动应用市场的竞争加剧,防止逆向工程和代码窃取变得尤为重要。传统的代码混淆工具往往需要手动操作,这在持续集成和自动化部署流程中显得效率低下。Ipa Guard命…

2026/10/15 4:46:53 阅读更多 →
Samba容器化实战:多租户隔离、协议兼容与权限映射

Samba容器化实战:多租户隔离、协议兼容与权限映射

1. 为什么在容器里跑Samba,而不是直接装在宿主机上?“Docker里跑Samba?这不反直觉吗?”——这是我第一次被团队同事问到这个问题时的真实反应。当时我们正在重构一个老旧的文件协作系统,原方案是在物理服务器上直接部署…

2026/10/15 4:46:53 阅读更多 →
STM32+华为云IoT+Qt:从传感器到云端的物联网数据链路实战

STM32+华为云IoT+Qt:从传感器到云端的物联网数据链路实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 4:46:53 阅读更多 →
沙箱代理工作流实战:隔离、权限与提示注入防御

沙箱代理工作流实战:隔离、权限与提示注入防御

1. 沙箱代理工作流到底在解决什么问题第一次接触“沙箱代理工作流”这个概念,是在一个自动化任务编排的项目里。当时团队想让一个智能代理去帮我们处理一批外部数据:抓取、清洗、分类、再写回内部系统。听起来很顺,但真正跑起来才发现&#x…

2026/10/15 4:46:53 阅读更多 →
模板代码生成工具:从元数据到可用接口的完整实现

模板代码生成工具:从元数据到可用接口的完整实现

1. 为什么需要模板代码生成工具:一大半重复代码其实不该手写做后端开发的朋友应该都有过这种体验:新项目启动,建表、写实体、写Mapper、写Service接口和实现、写Controller,然后前端再把列表页、表单页、弹窗、状态标签挨个撸一遍…

2026/10/15 4:45:53 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →