feat: Safety Goals + Drive-Away-Assist + vollst. Traceability
Validate / build-test (macos-latest) (push) Failing after 4s
Validate / build-test (windows-latest) (push) Failing after 17s
Validate / build-test (ubuntu-latest) (push) Successful in 16s
Validate / reports (push) Has been skipped
Release / release (push) Successful in 48s
Validate / build-test (macos-latest) (push) Failing after 4s
Validate / build-test (windows-latest) (push) Failing after 17s
Validate / build-test (ubuntu-latest) (push) Successful in 16s
Validate / reports (push) Has been skipped
Release / release (push) Successful in 48s
Neue Layer: - safety/sg/SG-001..005 als eigene Doorstop-Items (ASIL D/D/A/C/B) - SYS-Reqs verlinken nach oben auf SG via frontmatter - Kette ist jetzt: SG -> SYS -> SA, SWE -> SWA -> Code (@arch) + Test (@reqs) Drive-Away-Assist im Safety Manager: - SWE-011 (Anfahrabsicht erkennen) implementiert - SWE-012 (Sicherheits-Check Tuer + Gurt) implementiert - Neuer State SAFETY_DRIVE_AWAY + safety_mgr_release_requested() - SafetyInputs erweitert um gas_pedal_percent, gear_in_drive, door_closed, seatbelt_fastened - 5 neue Tests (DRIVE_AWAY armed/blocked/end-conditions) - Test-Header @reqs erweitert auf SWE-007..012 traceability.py erweitert: - SG als neuer Top-Level - Code-Mapping-Check: @arch im Header von src/*.c muss SWA-id matchen - Test-Mapping-Check: @reqs im Header der Tests muss alle SWE der zugehoerigen SWA abdecken - HTML zeigt 7 Spalten: SG | SYS | SA | SWE | SWA | Code | Test - 2 zusaetzliche Tabellen: Code->Arch und Test->Reqs test_apply_controller.c: - @reqs Header um SWE-005 ergaenzt (war funktional drin, nur Tag fehlte) Counts: - 55 doorstop-Items (war 50) - 46 Unit-Tests (war 41) - Traceability vollstaendig in beide Richtungen
This commit is contained in:
+140
-17
@@ -3,27 +3,150 @@
|
|||||||
<title>demo-epb — Traceability Matrix</title>
|
<title>demo-epb — Traceability Matrix</title>
|
||||||
<style>
|
<style>
|
||||||
body{font-family:-apple-system,Segoe UI,sans-serif;padding:20px;color:#222}
|
body{font-family:-apple-system,Segoe UI,sans-serif;padding:20px;color:#222}
|
||||||
table{border-collapse:collapse;width:100%;font-size:14px}
|
table{border-collapse:collapse;width:100%;font-size:13px;margin-top:16px}
|
||||||
th,td{border:1px solid #ccc;padding:6px 8px;vertical-align:top;text-align:left}
|
th,td{border:1px solid #ccc;padding:6px 8px;vertical-align:top;text-align:left}
|
||||||
th{background:#f0f0f0}
|
th{background:#f0f0f0;position:sticky;top:0}
|
||||||
tr:nth-child(even) td{background:#fafafa}
|
tr:nth-child(even) td{background:#fafafa}
|
||||||
.asil{display:inline-block;padding:1px 6px;border-radius:3px;color:white;font-weight:bold;font-size:11px}
|
.asil{display:inline-block;padding:1px 6px;border-radius:3px;color:white;font-weight:bold;font-size:11px}
|
||||||
.id{font-family:Consolas,monospace;font-size:13px}
|
.id{font-family:Consolas,monospace;font-size:12px}
|
||||||
.cnt{color:#666;font-size:11px}
|
.cnt{color:#666;font-size:11px}
|
||||||
h1{color:#1f3864}
|
h1{color:#1f3864}h2{color:#1f3864;margin-top:30px}
|
||||||
|
.missing{color:#c00}
|
||||||
</style></head><body>
|
</style></head><body>
|
||||||
<h1>demo-epb — Traceability Matrix</h1>
|
<h1>demo-epb — Traceability Matrix</h1>
|
||||||
<p>Generiert aus 50 Items (SYS: 10, SWE: 25, SA: 5, SWA: 10).</p>
|
<p>Vollstaendige Kette: <code>SG → SYS → SA, SWE → SWA → Code (@arch) + Test (@reqs)</code></p>
|
||||||
|
<p>
|
||||||
|
<strong>SG:</strong> 5
|
||||||
|
<strong>SYS:</strong> 10
|
||||||
|
<strong>SWE:</strong> 25
|
||||||
|
<strong>SA:</strong> 5
|
||||||
|
<strong>SWA:</strong> 10
|
||||||
|
<strong>Code-Files:</strong> 4
|
||||||
|
<strong>Test-Files:</strong> 4
|
||||||
|
</p>
|
||||||
<table>
|
<table>
|
||||||
<tr><th>System-Requirement</th><th>System-Arch (SA)</th><th>Software-Req (SWE)</th><th>Software-Arch (SWA)</th></tr>
|
<tr><th>Safety Goal</th><th>System-Requirement</th><th>System-Arch</th><th>Software-Req</th><th>Software-Arch</th><th>Code</th><th>Test</th></tr>
|
||||||
<tr><td><div><span class='id'>SYS-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Halten der Parkbremse im Stillstand</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div></td><td><div><span class='id'>SWE-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply-Controller haelt Klemmkraft</div><div><span class='id'>SWE-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Watchdog ueberwacht Apply-Controller</div><div><span class='id'>SWE-022</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Stillstands-Erkennung aus Wheel Speeds</div></td><td><div><span class='id'>SWA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply Controller</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div></td></tr>
|
<tr>
|
||||||
<tr><td><div><span class='id'>SYS-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply auf Fahrer-Anforderung</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div></td><td><div><span class='id'>SWE-003</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Schalter-Apply-Signal an Apply-Controller weiterleiten</div><div><span class='id'>SWE-004</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Klemmkraft-Erreichen bestaetigen</div><div><span class='id'>SWE-022</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Stillstands-Erkennung aus Wheel Speeds</div><div><span class='id'>SWE-025</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch-Debouncing</div></td><td><div><span class='id'>SWA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply Controller</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div><div><span class='id'>SWA-006</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch Debouncer</div></td></tr>
|
<td><div><span class='id'>SG-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Kein ungewolltes Loesen der Parkbremse im Stillstand</div></td>
|
||||||
<tr><td><div><span class='id'>SYS-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Release auf Fahrer-Anforderung</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div></td><td><div><span class='id'>SWE-005</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Release-Voraussetzungen pruefen</div><div><span class='id'>SWE-006</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Aktoren in Release-Position fahren</div><div><span class='id'>SWE-025</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch-Debouncing</div></td><td><div><span class='id'>SWA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply Controller</div><div><span class='id'>SWA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Actuator Driver</div><div><span class='id'>SWA-006</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch Debouncer</div></td></tr>
|
<td><div><span class='id'>SYS-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Halten der Parkbremse im Stillstand</div></td>
|
||||||
<tr><td><div><span class='id'>SYS-004</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Auto-Apply bei Motor-Aus</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div></td><td><div><span class='id'>SWE-007</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Motor-Aus-Bedingung erkennen</div><div><span class='id'>SWE-008</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Auto-Apply nach 2 s Verzoegerung</div></td><td><div><span class='id'>SWA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Safety Manager</div></td></tr>
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div></td>
|
||||||
<tr><td><div><span class='id'>SYS-005</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold am Berg</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sensor-Cluster</div></td><td><div><span class='id'>SWE-009</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold-Aktivierungsbedingung</div><div><span class='id'>SWE-010</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold-Uebergabe an Apply-Controller</div><div><span class='id'>SWE-024</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Inclinometer Tiefpass-Filter</div></td><td><div><span class='id'>SWA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Safety Manager</div><div><span class='id'>SWA-005</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Inclinometer Filter</div></td></tr>
|
<td><div><span class='id'>SWE-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply-Controller haelt Klemmkraft</div><div><span class='id'>SWE-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Watchdog ueberwacht Apply-Controller</div><div><span class='id'>SWE-022</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Stillstands-Erkennung aus Wheel Speeds</div></td>
|
||||||
<tr><td><div><span class='id'>SYS-006</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Auto-Release beim Anfahren (Drive-Away-Assist)</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sensor-Cluster</div></td><td><div><span class='id'>SWE-011</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Anfahrabsicht erkennen</div><div><span class='id'>SWE-012</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sicherheits-Check vor Auto-Release</div><div><span class='id'>SWE-022</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Stillstands-Erkennung aus Wheel Speeds</div></td><td><div><span class='id'>SWA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Safety Manager</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div></td></tr>
|
<td><div><span class='id'>SWA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply Controller</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div></td>
|
||||||
<tr><td><div><span class='id'>SYS-007</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Aktor-Stromueberwachung</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div><div><span class='id'>SA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sensor-Cluster</div></td><td><div><span class='id'>SWE-013</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Strommessung mit 1 kHz</div><div><span class='id'>SWE-014</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Overcurrent-Cutoff</div><div><span class='id'>SWE-015</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Klemmkraft-Schaetzung aus Strom-Profil</div><div><span class='id'>SWE-023</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div></td><td><div><span class='id'>SWA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Actuator Driver</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div></td></tr>
|
<td><div class='id'>src/apply_controller.c</div></td>
|
||||||
<tr><td><div><span class='id'>SYS-008</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Service-Modus fuer Werkstatt</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-004</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>HMI (Schalter, LED, Display)</div></td><td><div><span class='id'>SWE-016</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>UDS RoutineControl 0x31 fuer Service-Release</div><div><span class='id'>SWE-017</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Service-Mode-Indikator</div></td><td><div><span class='id'>SWA-009</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Service Mode</div></td></tr>
|
<td><div class='id'>tests/unit/test_apply_controller.c</div></td>
|
||||||
<tr><td><div><span class='id'>SYS-009</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>UDS-Diagnose</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-005</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>CAN-Bus</div></td><td><div><span class='id'>SWE-018</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>UDS Service 0x19 ReadDTC</div><div><span class='id'>SWE-019</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>UDS Service 0x22 ReadDataByIdentifier</div></td><td><div><span class='id'>SWA-008</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Diagnostic Manager</div><div><span class='id'>SWA-010</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Logger</div></td></tr>
|
</tr>
|
||||||
<tr><td><div><span class='id'>SYS-010</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>HMI-Statusanzeige</div></td><td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-004</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>HMI (Schalter, LED, Display)</div><div><span class='id'>SA-005</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>CAN-Bus</div></td><td><div><span class='id'>SWE-020</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>LED-Steuerung</div><div><span class='id'>SWE-021</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>CAN-Status-Frame</div></td><td><div><span class='id'>SWA-007</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Display Manager</div></td></tr>
|
<tr>
|
||||||
</table></body></html>
|
<td><div><span class='id'>SG-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Kein ungewolltes Loesen der Parkbremse im Stillstand</div></td>
|
||||||
|
<td><div><span class='id'>SYS-004</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Auto-Apply bei Motor-Aus</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div></td>
|
||||||
|
<td><div><span class='id'>SWE-007</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Motor-Aus-Bedingung erkennen</div><div><span class='id'>SWE-008</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Auto-Apply nach 2 s Verzoegerung</div></td>
|
||||||
|
<td><div><span class='id'>SWA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Safety Manager</div></td>
|
||||||
|
<td><div class='id'>src/safety_manager.c</div></td>
|
||||||
|
<td><div class='id'>tests/unit/test_safety_manager.c</div></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><div><span class='id'>SG-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Kein ungewolltes Festklemmen waehrend der Fahrt</div></td>
|
||||||
|
<td><div><span class='id'>SYS-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply auf Fahrer-Anforderung</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div></td>
|
||||||
|
<td><div><span class='id'>SWE-003</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Schalter-Apply-Signal an Apply-Controller weiterleiten</div><div><span class='id'>SWE-004</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Klemmkraft-Erreichen bestaetigen</div><div><span class='id'>SWE-022</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Stillstands-Erkennung aus Wheel Speeds</div><div><span class='id'>SWE-025</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch-Debouncing</div></td>
|
||||||
|
<td><div><span class='id'>SWA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply Controller</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div><div><span class='id'>SWA-006</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch Debouncer</div></td>
|
||||||
|
<td><div class='id'>src/apply_controller.c</div><div class='id'>src/switch_debouncer.c</div></td>
|
||||||
|
<td><div class='id'>tests/unit/test_apply_controller.c</div><div class='id'>tests/unit/test_switch_debouncer.c</div></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><div><span class='id'>SG-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Kein ungewolltes Festklemmen waehrend der Fahrt</div></td>
|
||||||
|
<td><div><span class='id'>SYS-005</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold am Berg</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sensor-Cluster</div></td>
|
||||||
|
<td><div><span class='id'>SWE-009</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold-Aktivierungsbedingung</div><div><span class='id'>SWE-010</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold-Uebergabe an Apply-Controller</div><div><span class='id'>SWE-024</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Inclinometer Tiefpass-Filter</div></td>
|
||||||
|
<td><div><span class='id'>SWA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Safety Manager</div><div><span class='id'>SWA-005</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Inclinometer Filter</div></td>
|
||||||
|
<td><div class='id'>src/safety_manager.c</div></td>
|
||||||
|
<td><div class='id'>tests/unit/test_safety_manager.c</div></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><div><span class='id'>SG-003</span> <span class='asil' style='background:#1f77b4'>A</span></div><div class='cnt'>Schutz gegen Aktor-Ueberlast</div></td>
|
||||||
|
<td><div><span class='id'>SYS-007</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Aktor-Stromueberwachung</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div><div><span class='id'>SA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sensor-Cluster</div></td>
|
||||||
|
<td><div><span class='id'>SWE-013</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Strommessung mit 1 kHz</div><div><span class='id'>SWE-014</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Overcurrent-Cutoff</div><div><span class='id'>SWE-015</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Klemmkraft-Schaetzung aus Strom-Profil</div><div><span class='id'>SWE-023</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div></td>
|
||||||
|
<td><div><span class='id'>SWA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Actuator Driver</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div></td>
|
||||||
|
<td><div class='id'>src/actuator_driver.c</div></td>
|
||||||
|
<td><div class='id'>tests/unit/test_actuator_driver.c</div></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><div><span class='id'>SG-004</span> <span class='asil' style='background:#ff7f0e'>C</span></div><div class='cnt'>Zuverlaessige Hill-Hold-Uebergabe</div></td>
|
||||||
|
<td><div><span class='id'>SYS-005</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold am Berg</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sensor-Cluster</div></td>
|
||||||
|
<td><div><span class='id'>SWE-009</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold-Aktivierungsbedingung</div><div><span class='id'>SWE-010</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Hill-Hold-Uebergabe an Apply-Controller</div><div><span class='id'>SWE-024</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Inclinometer Tiefpass-Filter</div></td>
|
||||||
|
<td><div><span class='id'>SWA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Safety Manager</div><div><span class='id'>SWA-005</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Inclinometer Filter</div></td>
|
||||||
|
<td><div class='id'>src/safety_manager.c</div></td>
|
||||||
|
<td><div class='id'>tests/unit/test_safety_manager.c</div></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><div><span class='id'>SG-004</span> <span class='asil' style='background:#ff7f0e'>C</span></div><div class='cnt'>Zuverlaessige Hill-Hold-Uebergabe</div></td>
|
||||||
|
<td><div><span class='id'>SYS-006</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Auto-Release beim Anfahren (Drive-Away-Assist)</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sensor-Cluster</div></td>
|
||||||
|
<td><div><span class='id'>SWE-011</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Anfahrabsicht erkennen</div><div><span class='id'>SWE-012</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Sicherheits-Check vor Auto-Release</div><div><span class='id'>SWE-022</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Stillstands-Erkennung aus Wheel Speeds</div></td>
|
||||||
|
<td><div><span class='id'>SWA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Safety Manager</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div></td>
|
||||||
|
<td><div class='id'>src/safety_manager.c</div></td>
|
||||||
|
<td><div class='id'>tests/unit/test_safety_manager.c</div></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><div><span class='id'>SG-005</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Reaktion auf Fahreranforderung</div></td>
|
||||||
|
<td><div><span class='id'>SYS-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply auf Fahrer-Anforderung</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div></td>
|
||||||
|
<td><div><span class='id'>SWE-003</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Schalter-Apply-Signal an Apply-Controller weiterleiten</div><div><span class='id'>SWE-004</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Klemmkraft-Erreichen bestaetigen</div><div><span class='id'>SWE-022</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Stillstands-Erkennung aus Wheel Speeds</div><div><span class='id'>SWE-025</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch-Debouncing</div></td>
|
||||||
|
<td><div><span class='id'>SWA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply Controller</div><div><span class='id'>SWA-004</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Wheel Speed Plausibilisierung</div><div><span class='id'>SWA-006</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch Debouncer</div></td>
|
||||||
|
<td><div class='id'>src/apply_controller.c</div><div class='id'>src/switch_debouncer.c</div></td>
|
||||||
|
<td><div class='id'>tests/unit/test_apply_controller.c</div><div class='id'>tests/unit/test_switch_debouncer.c</div></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><div><span class='id'>SG-005</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Reaktion auf Fahreranforderung</div></td>
|
||||||
|
<td><div><span class='id'>SYS-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Release auf Fahrer-Anforderung</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Aktoren (Caliper-Motoren)</div></td>
|
||||||
|
<td><div><span class='id'>SWE-005</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Release-Voraussetzungen pruefen</div><div><span class='id'>SWE-006</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Aktoren in Release-Position fahren</div><div><span class='id'>SWE-025</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch-Debouncing</div></td>
|
||||||
|
<td><div><span class='id'>SWA-002</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>Apply Controller</div><div><span class='id'>SWA-003</span> <span class='asil' style='background:#2ca02c'>B</span></div><div class='cnt'>Actuator Driver</div><div><span class='id'>SWA-006</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Switch Debouncer</div></td>
|
||||||
|
<td><div class='id'>src/apply_controller.c</div><div class='id'>src/actuator_driver.c</div><div class='id'>src/switch_debouncer.c</div></td>
|
||||||
|
<td><div class='id'>tests/unit/test_actuator_driver.c</div><div class='id'>tests/unit/test_apply_controller.c</div><div class='id'>tests/unit/test_switch_debouncer.c</div></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class='missing'>—</td>
|
||||||
|
<td><div><span class='id'>SYS-008</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Service-Modus fuer Werkstatt</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-004</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>HMI (Schalter, LED, Display)</div></td>
|
||||||
|
<td><div><span class='id'>SWE-016</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>UDS RoutineControl 0x31 fuer Service-Release</div><div><span class='id'>SWE-017</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Service-Mode-Indikator</div></td>
|
||||||
|
<td><div><span class='id'>SWA-009</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Service Mode</div></td>
|
||||||
|
<td class='cnt'>—</td>
|
||||||
|
<td class='cnt'>—</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class='missing'>—</td>
|
||||||
|
<td><div><span class='id'>SYS-009</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>UDS-Diagnose</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-005</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>CAN-Bus</div></td>
|
||||||
|
<td><div><span class='id'>SWE-018</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>UDS Service 0x19 ReadDTC</div><div><span class='id'>SWE-019</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>UDS Service 0x22 ReadDataByIdentifier</div></td>
|
||||||
|
<td><div><span class='id'>SWA-008</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Diagnostic Manager</div><div><span class='id'>SWA-010</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Logger</div></td>
|
||||||
|
<td class='cnt'>—</td>
|
||||||
|
<td class='cnt'>—</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class='missing'>—</td>
|
||||||
|
<td><div><span class='id'>SYS-010</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>HMI-Statusanzeige</div></td>
|
||||||
|
<td><div><span class='id'>SA-001</span> <span class='asil' style='background:#d62728'>D</span></div><div class='cnt'>EPB ECU</div><div><span class='id'>SA-004</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>HMI (Schalter, LED, Display)</div><div><span class='id'>SA-005</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>CAN-Bus</div></td>
|
||||||
|
<td><div><span class='id'>SWE-020</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>LED-Steuerung</div><div><span class='id'>SWE-021</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>CAN-Status-Frame</div></td>
|
||||||
|
<td><div><span class='id'>SWA-007</span> <span class='asil' style='background:#888'>QM</span></div><div class='cnt'>Display Manager</div></td>
|
||||||
|
<td class='cnt'>—</td>
|
||||||
|
<td class='cnt'>—</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<h2>Code → Architektur</h2>
|
||||||
|
<table><tr><th>Datei</th><th>@arch</th><th>@reqs</th></tr>
|
||||||
|
<tr><td class='id'>src/safety_manager.c</td><td>SWA-001</td><td class='cnt'>SWE-007 SWE-008 SWE-009 SWE-010 SWE-011 SWE-012</td></tr>
|
||||||
|
<tr><td class='id'>src/apply_controller.c</td><td>SWA-002</td><td class='cnt'>SWE-001 SWE-002 SWE-003 SWE-004</td></tr>
|
||||||
|
<tr><td class='id'>src/actuator_driver.c</td><td>SWA-003</td><td class='cnt'>SWE-006 SWE-013 SWE-014 SWE-015</td></tr>
|
||||||
|
<tr><td class='id'>src/switch_debouncer.c</td><td>SWA-006</td><td class='cnt'>SWE-025</td></tr>
|
||||||
|
</table>
|
||||||
|
<h2>Test → Anforderungen</h2>
|
||||||
|
<table><tr><th>Test-Datei</th><th>Decklt SWA</th><th>@reqs</th></tr>
|
||||||
|
<tr><td class='id'>tests/unit/test_safety_manager.c</td><td>SWA-001</td><td class='cnt'>SWE-007 SWE-008 SWE-009 SWE-010 SWE-011 SWE-012</td></tr>
|
||||||
|
<tr><td class='id'>tests/unit/test_apply_controller.c</td><td>SWA-002</td><td class='cnt'>SWE-001 SWE-002 SWE-003 SWE-004 SWE-005</td></tr>
|
||||||
|
<tr><td class='id'>tests/unit/test_actuator_driver.c</td><td>SWA-003</td><td class='cnt'>SWE-006 SWE-013 SWE-014 SWE-015</td></tr>
|
||||||
|
<tr><td class='id'>tests/unit/test_switch_debouncer.c</td><td>SWA-006</td><td class='cnt'>SWE-025</td></tr>
|
||||||
|
</table>
|
||||||
|
</body></html>
|
||||||
+312
-115
@@ -1,5 +1,9 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
"sg": {
|
||||||
|
"id": "SG-001",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
"sys": {
|
"sys": {
|
||||||
"id": "SYS-001",
|
"id": "SYS-001",
|
||||||
"asil": "D",
|
"asil": "D",
|
||||||
@@ -38,9 +42,58 @@
|
|||||||
"id": "SWA-004",
|
"id": "SWA-004",
|
||||||
"asil": "B"
|
"asil": "B"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/apply_controller.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_apply_controller.c"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"sg": {
|
||||||
|
"id": "SG-001",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
"sys": {
|
||||||
|
"id": "SYS-004",
|
||||||
|
"asil": "D",
|
||||||
|
"title": "Auto-Apply bei Motor-Aus"
|
||||||
|
},
|
||||||
|
"sa": [
|
||||||
|
{
|
||||||
|
"id": "SA-001",
|
||||||
|
"asil": "D"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swe": [
|
||||||
|
{
|
||||||
|
"id": "SWE-007",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-008",
|
||||||
|
"asil": "D"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swa": [
|
||||||
|
{
|
||||||
|
"id": "SWA-001",
|
||||||
|
"asil": "D"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/safety_manager.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_safety_manager.c"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sg": {
|
||||||
|
"id": "SG-002",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
"sys": {
|
"sys": {
|
||||||
"id": "SYS-002",
|
"id": "SYS-002",
|
||||||
"asil": "D",
|
"asil": "D",
|
||||||
@@ -87,83 +140,21 @@
|
|||||||
"id": "SWA-006",
|
"id": "SWA-006",
|
||||||
"asil": "QM"
|
"asil": "QM"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/apply_controller.c",
|
||||||
|
"src/switch_debouncer.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_apply_controller.c",
|
||||||
|
"tests/unit/test_switch_debouncer.c"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"sys": {
|
"sg": {
|
||||||
"id": "SYS-003",
|
"id": "SG-002",
|
||||||
"asil": "B",
|
|
||||||
"title": "Release auf Fahrer-Anforderung"
|
|
||||||
},
|
|
||||||
"sa": [
|
|
||||||
{
|
|
||||||
"id": "SA-001",
|
|
||||||
"asil": "D"
|
"asil": "D"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "SA-002",
|
|
||||||
"asil": "D"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"swe": [
|
|
||||||
{
|
|
||||||
"id": "SWE-005",
|
|
||||||
"asil": "B"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SWE-006",
|
|
||||||
"asil": "B"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SWE-025",
|
|
||||||
"asil": "QM"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"swa": [
|
|
||||||
{
|
|
||||||
"id": "SWA-002",
|
|
||||||
"asil": "D"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SWA-003",
|
|
||||||
"asil": "B"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SWA-006",
|
|
||||||
"asil": "QM"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sys": {
|
|
||||||
"id": "SYS-004",
|
|
||||||
"asil": "D",
|
|
||||||
"title": "Auto-Apply bei Motor-Aus"
|
|
||||||
},
|
|
||||||
"sa": [
|
|
||||||
{
|
|
||||||
"id": "SA-001",
|
|
||||||
"asil": "D"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"swe": [
|
|
||||||
{
|
|
||||||
"id": "SWE-007",
|
|
||||||
"asil": "D"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SWE-008",
|
|
||||||
"asil": "D"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"swa": [
|
|
||||||
{
|
|
||||||
"id": "SWA-001",
|
|
||||||
"asil": "D"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sys": {
|
"sys": {
|
||||||
"id": "SYS-005",
|
"id": "SYS-005",
|
||||||
"asil": "D",
|
"asil": "D",
|
||||||
@@ -202,50 +193,19 @@
|
|||||||
"id": "SWA-005",
|
"id": "SWA-005",
|
||||||
"asil": "B"
|
"asil": "B"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/safety_manager.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_safety_manager.c"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"sys": {
|
"sg": {
|
||||||
"id": "SYS-006",
|
"id": "SG-003",
|
||||||
"asil": "B",
|
"asil": "A"
|
||||||
"title": "Auto-Release beim Anfahren (Drive-Away-Assist)"
|
|
||||||
},
|
},
|
||||||
"sa": [
|
|
||||||
{
|
|
||||||
"id": "SA-001",
|
|
||||||
"asil": "D"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SA-003",
|
|
||||||
"asil": "B"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"swe": [
|
|
||||||
{
|
|
||||||
"id": "SWE-011",
|
|
||||||
"asil": "B"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SWE-012",
|
|
||||||
"asil": "B"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SWE-022",
|
|
||||||
"asil": "B"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"swa": [
|
|
||||||
{
|
|
||||||
"id": "SWA-001",
|
|
||||||
"asil": "D"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "SWA-004",
|
|
||||||
"asil": "B"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sys": {
|
"sys": {
|
||||||
"id": "SYS-007",
|
"id": "SYS-007",
|
||||||
"asil": "B",
|
"asil": "B",
|
||||||
@@ -292,9 +252,238 @@
|
|||||||
"id": "SWA-004",
|
"id": "SWA-004",
|
||||||
"asil": "B"
|
"asil": "B"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/actuator_driver.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_actuator_driver.c"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"sg": {
|
||||||
|
"id": "SG-004",
|
||||||
|
"asil": "C"
|
||||||
|
},
|
||||||
|
"sys": {
|
||||||
|
"id": "SYS-005",
|
||||||
|
"asil": "D",
|
||||||
|
"title": "Hill-Hold am Berg"
|
||||||
|
},
|
||||||
|
"sa": [
|
||||||
|
{
|
||||||
|
"id": "SA-001",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SA-003",
|
||||||
|
"asil": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swe": [
|
||||||
|
{
|
||||||
|
"id": "SWE-009",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-010",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-024",
|
||||||
|
"asil": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swa": [
|
||||||
|
{
|
||||||
|
"id": "SWA-001",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWA-005",
|
||||||
|
"asil": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/safety_manager.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_safety_manager.c"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sg": {
|
||||||
|
"id": "SG-004",
|
||||||
|
"asil": "C"
|
||||||
|
},
|
||||||
|
"sys": {
|
||||||
|
"id": "SYS-006",
|
||||||
|
"asil": "B",
|
||||||
|
"title": "Auto-Release beim Anfahren (Drive-Away-Assist)"
|
||||||
|
},
|
||||||
|
"sa": [
|
||||||
|
{
|
||||||
|
"id": "SA-001",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SA-003",
|
||||||
|
"asil": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swe": [
|
||||||
|
{
|
||||||
|
"id": "SWE-011",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-012",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-022",
|
||||||
|
"asil": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swa": [
|
||||||
|
{
|
||||||
|
"id": "SWA-001",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWA-004",
|
||||||
|
"asil": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/safety_manager.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_safety_manager.c"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sg": {
|
||||||
|
"id": "SG-005",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
"sys": {
|
||||||
|
"id": "SYS-002",
|
||||||
|
"asil": "D",
|
||||||
|
"title": "Apply auf Fahrer-Anforderung"
|
||||||
|
},
|
||||||
|
"sa": [
|
||||||
|
{
|
||||||
|
"id": "SA-001",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SA-002",
|
||||||
|
"asil": "D"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swe": [
|
||||||
|
{
|
||||||
|
"id": "SWE-003",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-004",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-022",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-025",
|
||||||
|
"asil": "QM"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swa": [
|
||||||
|
{
|
||||||
|
"id": "SWA-002",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWA-004",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWA-006",
|
||||||
|
"asil": "QM"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/apply_controller.c",
|
||||||
|
"src/switch_debouncer.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_apply_controller.c",
|
||||||
|
"tests/unit/test_switch_debouncer.c"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sg": {
|
||||||
|
"id": "SG-005",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
"sys": {
|
||||||
|
"id": "SYS-003",
|
||||||
|
"asil": "B",
|
||||||
|
"title": "Release auf Fahrer-Anforderung"
|
||||||
|
},
|
||||||
|
"sa": [
|
||||||
|
{
|
||||||
|
"id": "SA-001",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SA-002",
|
||||||
|
"asil": "D"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swe": [
|
||||||
|
{
|
||||||
|
"id": "SWE-005",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-006",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWE-025",
|
||||||
|
"asil": "QM"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"swa": [
|
||||||
|
{
|
||||||
|
"id": "SWA-002",
|
||||||
|
"asil": "D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWA-003",
|
||||||
|
"asil": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SWA-006",
|
||||||
|
"asil": "QM"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"code": [
|
||||||
|
"src/apply_controller.c",
|
||||||
|
"src/actuator_driver.c",
|
||||||
|
"src/switch_debouncer.c"
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
"tests/unit/test_actuator_driver.c",
|
||||||
|
"tests/unit/test_apply_controller.c",
|
||||||
|
"tests/unit/test_switch_debouncer.c"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sg": null,
|
||||||
"sys": {
|
"sys": {
|
||||||
"id": "SYS-008",
|
"id": "SYS-008",
|
||||||
"asil": "QM",
|
"asil": "QM",
|
||||||
@@ -325,9 +514,12 @@
|
|||||||
"id": "SWA-009",
|
"id": "SWA-009",
|
||||||
"asil": "QM"
|
"asil": "QM"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"code": [],
|
||||||
|
"tests": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"sg": null,
|
||||||
"sys": {
|
"sys": {
|
||||||
"id": "SYS-009",
|
"id": "SYS-009",
|
||||||
"asil": "QM",
|
"asil": "QM",
|
||||||
@@ -362,9 +554,12 @@
|
|||||||
"id": "SWA-010",
|
"id": "SWA-010",
|
||||||
"asil": "QM"
|
"asil": "QM"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"code": [],
|
||||||
|
"tests": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"sg": null,
|
||||||
"sys": {
|
"sys": {
|
||||||
"id": "SYS-010",
|
"id": "SYS-010",
|
||||||
"asil": "QM",
|
"asil": "QM",
|
||||||
@@ -399,6 +594,8 @@
|
|||||||
"id": "SWA-007",
|
"id": "SWA-007",
|
||||||
"asil": "QM"
|
"asil": "QM"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"code": [],
|
||||||
|
"tests": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
+2
-1
@@ -5,7 +5,8 @@ header: 'Halten der Parkbremse im Stillstand'
|
|||||||
level: 1.1
|
level: 1.1
|
||||||
normative: true
|
normative: true
|
||||||
reviewed: null
|
reviewed: null
|
||||||
links: []
|
links:
|
||||||
|
- SG-001
|
||||||
asil: D
|
asil: D
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -5,7 +5,9 @@ header: 'Apply auf Fahrer-Anforderung'
|
|||||||
level: 1.2
|
level: 1.2
|
||||||
normative: true
|
normative: true
|
||||||
reviewed: null
|
reviewed: null
|
||||||
links: []
|
links:
|
||||||
|
- SG-002
|
||||||
|
- SG-005
|
||||||
asil: D
|
asil: D
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -5,7 +5,8 @@ header: 'Release auf Fahrer-Anforderung'
|
|||||||
level: 1.3
|
level: 1.3
|
||||||
normative: true
|
normative: true
|
||||||
reviewed: null
|
reviewed: null
|
||||||
links: []
|
links:
|
||||||
|
- SG-005
|
||||||
asil: B
|
asil: B
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -5,7 +5,8 @@ header: 'Auto-Apply bei Motor-Aus'
|
|||||||
level: 1.4
|
level: 1.4
|
||||||
normative: true
|
normative: true
|
||||||
reviewed: null
|
reviewed: null
|
||||||
links: []
|
links:
|
||||||
|
- SG-001
|
||||||
asil: D
|
asil: D
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -5,7 +5,9 @@ header: 'Hill-Hold am Berg'
|
|||||||
level: 1.5
|
level: 1.5
|
||||||
normative: true
|
normative: true
|
||||||
reviewed: null
|
reviewed: null
|
||||||
links: []
|
links:
|
||||||
|
- SG-002
|
||||||
|
- SG-004
|
||||||
asil: D
|
asil: D
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -5,7 +5,8 @@ header: 'Auto-Release beim Anfahren (Drive-Away-Assist)'
|
|||||||
level: 1.6
|
level: 1.6
|
||||||
normative: true
|
normative: true
|
||||||
reviewed: null
|
reviewed: null
|
||||||
links: []
|
links:
|
||||||
|
- SG-004
|
||||||
asil: B
|
asil: B
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -5,7 +5,8 @@ header: 'Aktor-Stromueberwachung'
|
|||||||
level: 1.7
|
level: 1.7
|
||||||
normative: true
|
normative: true
|
||||||
reviewed: null
|
reviewed: null
|
||||||
links: []
|
links:
|
||||||
|
- SG-003
|
||||||
asil: B
|
asil: B
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
active: true
|
||||||
|
derived: false
|
||||||
|
header: 'Kein ungewolltes Loesen der Parkbremse im Stillstand'
|
||||||
|
level: 1.1
|
||||||
|
normative: true
|
||||||
|
reviewed: null
|
||||||
|
links: []
|
||||||
|
asil: D
|
||||||
|
---
|
||||||
|
|
||||||
|
# SG-001: Kein ungewolltes Loesen der Parkbremse im Stillstand
|
||||||
|
|
||||||
|
Die EPB darf sich im Stillstand des Fahrzeugs nicht ungewollt loesen. Abgeleitet aus HARA-Hazards H-01 (ungewolltes Loesen, Parkphase) und H-04 (Klemmkraftverlust im Hold).
|
||||||
|
|
||||||
|
**FTTI:** 5 s (H-01) / 30 s (H-04).
|
||||||
|
**Safe State:** APPLIED (Klemmkraft halten).
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
active: true
|
||||||
|
derived: false
|
||||||
|
header: 'Kein ungewolltes Festklemmen waehrend der Fahrt'
|
||||||
|
level: 1.2
|
||||||
|
normative: true
|
||||||
|
reviewed: null
|
||||||
|
links: []
|
||||||
|
asil: D
|
||||||
|
---
|
||||||
|
|
||||||
|
# SG-002: Kein ungewolltes Festklemmen waehrend der Fahrt
|
||||||
|
|
||||||
|
Die EPB darf nicht waehrend der Fahrt ungewollt festklemmen. Abgeleitet aus HARA-Hazard H-02.
|
||||||
|
|
||||||
|
**FTTI:** 100 ms.
|
||||||
|
**Safe State:** Aktor stop (kein Apply einleiten).
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
active: true
|
||||||
|
derived: false
|
||||||
|
header: 'Schutz gegen Aktor-Ueberlast'
|
||||||
|
level: 1.3
|
||||||
|
normative: true
|
||||||
|
reviewed: null
|
||||||
|
links: []
|
||||||
|
asil: A
|
||||||
|
---
|
||||||
|
|
||||||
|
# SG-003: Schutz gegen Aktor-Ueberlast
|
||||||
|
|
||||||
|
Das System muss Aktor-Motorschaeden durch Ueberstrom verhindern. Abgeleitet aus HARA-Hazard H-05.
|
||||||
|
|
||||||
|
**FTTI:** 100 ms.
|
||||||
|
**Safe State:** Aktor abschalten, DTC setzen.
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
active: true
|
||||||
|
derived: false
|
||||||
|
header: 'Zuverlaessige Hill-Hold-Uebergabe'
|
||||||
|
level: 1.4
|
||||||
|
normative: true
|
||||||
|
reviewed: null
|
||||||
|
links: []
|
||||||
|
asil: C
|
||||||
|
---
|
||||||
|
|
||||||
|
# SG-004: Zuverlaessige Hill-Hold-Uebergabe
|
||||||
|
|
||||||
|
Beim Loslassen des Bremspedals an einem Hang muss die EPB die Bremskraft uebernehmen, bevor das Fahrzeug zu rollen beginnt. Abgeleitet aus HARA-Hazard H-06.
|
||||||
|
|
||||||
|
**FTTI:** 500 ms.
|
||||||
|
**Safe State:** Apply einleiten.
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
active: true
|
||||||
|
derived: false
|
||||||
|
header: 'Reaktion auf Fahreranforderung'
|
||||||
|
level: 1.5
|
||||||
|
normative: true
|
||||||
|
reviewed: null
|
||||||
|
links: []
|
||||||
|
asil: B
|
||||||
|
---
|
||||||
|
|
||||||
|
# SG-005: Reaktion auf Fahreranforderung
|
||||||
|
|
||||||
|
Das System muss in spezifizierter Zeit auf Fahrer-Apply- und Release-Anforderungen reagieren. Abgeleitet aus HARA-Hazards H-03 und H-07.
|
||||||
|
|
||||||
|
**Reaktionszeit:** Apply <= 800 ms, Release <= 1500 ms.
|
||||||
+50
-4
@@ -1,12 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
* @file safety_manager.c
|
* @file safety_manager.c
|
||||||
* @brief Safety Manager — Hill-Hold + Auto-Apply Logik.
|
* @brief Safety Manager — Hill-Hold, Auto-Apply, Drive-Away-Assist.
|
||||||
*
|
*
|
||||||
* @arch SWA-001
|
* @arch SWA-001
|
||||||
* @reqs SWE-007 SWE-008 SWE-009 SWE-010
|
* @reqs SWE-007 SWE-008 SWE-009 SWE-010 SWE-011 SWE-012
|
||||||
*
|
*
|
||||||
* ASIL: D. Diese Komponente entscheidet, wann der Apply Controller eine
|
* ASIL: D. Diese Komponente entscheidet, wann der Apply Controller eine
|
||||||
* Apply-Anforderung erhaelt (Hill-Hold-Uebergabe, Auto-Apply bei Motor-Aus).
|
* Apply- oder Release-Anforderung erhaelt (Hill-Hold-Uebergabe, Auto-Apply
|
||||||
|
* bei Motor-Aus, Drive-Away-Assist).
|
||||||
* Aenderungen erfordern Technical Review mit 2 Approvals.
|
* Aenderungen erfordern Technical Review mit 2 Approvals.
|
||||||
*/
|
*/
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@@ -17,6 +18,7 @@ typedef struct {
|
|||||||
SafetyState state;
|
SafetyState state;
|
||||||
uint16_t ticks_in_state; /* 50ms-Ticks im aktuellen Zustand */
|
uint16_t ticks_in_state; /* 50ms-Ticks im aktuellen Zustand */
|
||||||
bool apply_requested;
|
bool apply_requested;
|
||||||
|
bool release_requested;
|
||||||
} SafetyCtx;
|
} SafetyCtx;
|
||||||
|
|
||||||
static SafetyCtx s_ctx;
|
static SafetyCtx s_ctx;
|
||||||
@@ -42,11 +44,30 @@ static bool grade_steep(const SafetyInputs* in)
|
|||||||
return g > SAFETY_HILLHOLD_GRADE_PCT;
|
return g > SAFETY_HILLHOLD_GRADE_PCT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @reqs SWE-011 (Anfahrabsicht erkennen)
|
||||||
|
*/
|
||||||
|
static bool drive_intent(const SafetyInputs* in)
|
||||||
|
{
|
||||||
|
return (in->gas_pedal_percent > SAFETY_DRIVE_INTENT_GAS_PCT)
|
||||||
|
&& in->gear_in_drive
|
||||||
|
&& in->engine_running;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @reqs SWE-012 (Sicherheits-Check vor Auto-Release)
|
||||||
|
*/
|
||||||
|
static bool drive_away_safety_ok(const SafetyInputs* in)
|
||||||
|
{
|
||||||
|
return in->door_closed && in->seatbelt_fastened;
|
||||||
|
}
|
||||||
|
|
||||||
EpbStatus safety_mgr_init(void)
|
EpbStatus safety_mgr_init(void)
|
||||||
{
|
{
|
||||||
s_ctx.state = SAFETY_IDLE;
|
s_ctx.state = SAFETY_IDLE;
|
||||||
s_ctx.ticks_in_state = 0U;
|
s_ctx.ticks_in_state = 0U;
|
||||||
s_ctx.apply_requested = false;
|
s_ctx.apply_requested = false;
|
||||||
|
s_ctx.release_requested = false;
|
||||||
return EPB_OK;
|
return EPB_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,8 +81,9 @@ void safety_mgr_step_50ms(const SafetyInputs* in)
|
|||||||
++s_ctx.ticks_in_state;
|
++s_ctx.ticks_in_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Default: no apply request unless explicitly set below. */
|
/* Default: no apply/release request unless explicitly set below. */
|
||||||
s_ctx.apply_requested = false;
|
s_ctx.apply_requested = false;
|
||||||
|
s_ctx.release_requested = false;
|
||||||
|
|
||||||
switch (s_ctx.state) {
|
switch (s_ctx.state) {
|
||||||
case SAFETY_IDLE:
|
case SAFETY_IDLE:
|
||||||
@@ -75,6 +97,13 @@ void safety_mgr_step_50ms(const SafetyInputs* in)
|
|||||||
&& in->current_state != EPB_STATE_APPLIED
|
&& in->current_state != EPB_STATE_APPLIED
|
||||||
&& in->current_state != EPB_STATE_APPLYING) {
|
&& in->current_state != EPB_STATE_APPLYING) {
|
||||||
enter(SAFETY_AUTO_APPLY_ARMED);
|
enter(SAFETY_AUTO_APPLY_ARMED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* @reqs SWE-011 + SWE-012: Drive-Away-Assist */
|
||||||
|
if (in->current_state == EPB_STATE_APPLIED
|
||||||
|
&& drive_intent(in) && drive_away_safety_ok(in)) {
|
||||||
|
s_ctx.release_requested = true;
|
||||||
|
enter(SAFETY_DRIVE_AWAY);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -122,6 +151,18 @@ void safety_mgr_step_50ms(const SafetyInputs* in)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SAFETY_DRIVE_AWAY:
|
||||||
|
/* Beendet, wenn die Bremse geloest wurde oder Vorbedingungen nicht mehr ok. */
|
||||||
|
if (in->current_state == EPB_STATE_RELEASED
|
||||||
|
|| in->current_state == EPB_STATE_RELEASING) {
|
||||||
|
enter(SAFETY_IDLE);
|
||||||
|
} else if (!drive_intent(in) || !drive_away_safety_ok(in)) {
|
||||||
|
enter(SAFETY_IDLE);
|
||||||
|
} else {
|
||||||
|
s_ctx.release_requested = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
enter(SAFETY_IDLE);
|
enter(SAFETY_IDLE);
|
||||||
break;
|
break;
|
||||||
@@ -133,6 +174,11 @@ bool safety_mgr_apply_requested(void)
|
|||||||
return s_ctx.apply_requested;
|
return s_ctx.apply_requested;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool safety_mgr_release_requested(void)
|
||||||
|
{
|
||||||
|
return s_ctx.release_requested;
|
||||||
|
}
|
||||||
|
|
||||||
SafetyState safety_mgr_get_state(void)
|
SafetyState safety_mgr_get_state(void)
|
||||||
{
|
{
|
||||||
return s_ctx.state;
|
return s_ctx.state;
|
||||||
|
|||||||
+15
-4
@@ -1,20 +1,23 @@
|
|||||||
/**
|
/**
|
||||||
* @file safety_manager.h
|
* @file safety_manager.h
|
||||||
* @brief Safety Manager — Hill-Hold + Auto-Apply Logik.
|
* @brief Safety Manager — Hill-Hold, Auto-Apply, Drive-Away-Assist.
|
||||||
*
|
*
|
||||||
* @arch SWA-001
|
* @arch SWA-001
|
||||||
* @reqs SWE-007 SWE-008 SWE-009 SWE-010
|
* @reqs SWE-007 SWE-008 SWE-009 SWE-010 SWE-011 SWE-012
|
||||||
*
|
*
|
||||||
* ASIL: D.
|
* ASIL: D.
|
||||||
*
|
*
|
||||||
* State Machine:
|
* State Machine:
|
||||||
* IDLE --(engine_off & v<0.5)--> AUTO_APPLY_ARMED
|
* IDLE --(engine_off & v<0.5 & !APPLIED)--> AUTO_APPLY_ARMED
|
||||||
* AUTO_APPLY_ARMED --(40 * 50ms = 2s)--> AUTO_APPLY_TRIGGERED
|
* AUTO_APPLY_ARMED --(40 * 50ms = 2s)--> AUTO_APPLY_TRIGGERED
|
||||||
* AUTO_APPLY_TRIGGERED --(state==APPLIED)--> IDLE
|
* AUTO_APPLY_TRIGGERED --(state==APPLIED)--> IDLE
|
||||||
*
|
*
|
||||||
* IDLE --(grade>5% & v<0.5 & brake)--> HILL_HOLD_ARMED
|
* IDLE --(grade>5% & v<0.5 & brake)--> HILL_HOLD_ARMED
|
||||||
* HILL_HOLD_ARMED --(!brake)--> HILL_HOLD_ACTIVE
|
* HILL_HOLD_ARMED --(!brake)--> HILL_HOLD_ACTIVE
|
||||||
* HILL_HOLD_ACTIVE --(v>2 km/h | state==APPLIED)--> IDLE
|
* HILL_HOLD_ACTIVE --(v>2 km/h | state==APPLIED)--> IDLE
|
||||||
|
*
|
||||||
|
* IDLE --(APPLIED & gas>10% & gear_drive & engine & door & belt)--> DRIVE_AWAY
|
||||||
|
* DRIVE_AWAY --(state==RELEASED|RELEASING)--> IDLE
|
||||||
*/
|
*/
|
||||||
#ifndef SAFETY_MANAGER_H
|
#ifndef SAFETY_MANAGER_H
|
||||||
#define SAFETY_MANAGER_H
|
#define SAFETY_MANAGER_H
|
||||||
@@ -26,7 +29,8 @@ typedef enum {
|
|||||||
SAFETY_HILL_HOLD_ARMED = 1,
|
SAFETY_HILL_HOLD_ARMED = 1,
|
||||||
SAFETY_HILL_HOLD_ACTIVE = 2,
|
SAFETY_HILL_HOLD_ACTIVE = 2,
|
||||||
SAFETY_AUTO_APPLY_ARMED = 3,
|
SAFETY_AUTO_APPLY_ARMED = 3,
|
||||||
SAFETY_AUTO_APPLY_TRIGGERED = 4
|
SAFETY_AUTO_APPLY_TRIGGERED = 4,
|
||||||
|
SAFETY_DRIVE_AWAY = 5
|
||||||
} SafetyState;
|
} SafetyState;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -35,6 +39,11 @@ typedef struct {
|
|||||||
float vehicle_speed_kmh;
|
float vehicle_speed_kmh;
|
||||||
float grade_percent;
|
float grade_percent;
|
||||||
EpbState current_state; /* aus Apply Controller */
|
EpbState current_state; /* aus Apply Controller */
|
||||||
|
/* Drive-Away-Assist Inputs (SWE-011, SWE-012) */
|
||||||
|
float gas_pedal_percent; /* 0..100 */
|
||||||
|
bool gear_in_drive; /* Vorwaerts oder Rueckwaerts */
|
||||||
|
bool door_closed; /* Fahrertuer */
|
||||||
|
bool seatbelt_fastened; /* Fahrer-Gurt */
|
||||||
} SafetyInputs;
|
} SafetyInputs;
|
||||||
|
|
||||||
/* Schwellwerte als Konstanten, damit Tests darauf zugreifen koennen. */
|
/* Schwellwerte als Konstanten, damit Tests darauf zugreifen koennen. */
|
||||||
@@ -42,10 +51,12 @@ typedef struct {
|
|||||||
#define SAFETY_STANDSTILL_KMH 0.5f
|
#define SAFETY_STANDSTILL_KMH 0.5f
|
||||||
#define SAFETY_RELEASE_KMH 2.0f
|
#define SAFETY_RELEASE_KMH 2.0f
|
||||||
#define SAFETY_HILLHOLD_GRADE_PCT 5.0f
|
#define SAFETY_HILLHOLD_GRADE_PCT 5.0f
|
||||||
|
#define SAFETY_DRIVE_INTENT_GAS_PCT 10.0f /* Gaspedal > 10% = Anfahrabsicht */
|
||||||
|
|
||||||
EpbStatus safety_mgr_init(void);
|
EpbStatus safety_mgr_init(void);
|
||||||
void safety_mgr_step_50ms(const SafetyInputs* in);
|
void safety_mgr_step_50ms(const SafetyInputs* in);
|
||||||
bool safety_mgr_apply_requested(void);
|
bool safety_mgr_apply_requested(void);
|
||||||
|
bool safety_mgr_release_requested(void); /* Drive-Away-Assist */
|
||||||
SafetyState safety_mgr_get_state(void);
|
SafetyState safety_mgr_get_state(void);
|
||||||
|
|
||||||
#endif /* SAFETY_MANAGER_H */
|
#endif /* SAFETY_MANAGER_H */
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @file test_apply_controller.c
|
* @file test_apply_controller.c
|
||||||
* @brief Unit-Tests fuer den Apply-Controller (ASIL-D Kern).
|
* @brief Unit-Tests fuer den Apply-Controller (ASIL-D Kern).
|
||||||
*
|
*
|
||||||
* @reqs SWE-001 SWE-002 SWE-003 SWE-004
|
* @reqs SWE-001 SWE-002 SWE-003 SWE-004 SWE-005
|
||||||
* @arch SWA-002
|
* @arch SWA-002
|
||||||
*/
|
*/
|
||||||
#include "../unit_test_framework.h"
|
#include "../unit_test_framework.h"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @file test_safety_manager.c
|
* @file test_safety_manager.c
|
||||||
* @brief Unit-Tests fuer den Safety Manager (ASIL-D).
|
* @brief Unit-Tests fuer den Safety Manager (ASIL-D).
|
||||||
*
|
*
|
||||||
* @reqs SWE-007 SWE-008 SWE-009 SWE-010
|
* @reqs SWE-007 SWE-008 SWE-009 SWE-010 SWE-011 SWE-012
|
||||||
* @arch SWA-001
|
* @arch SWA-001
|
||||||
*/
|
*/
|
||||||
#include "../unit_test_framework.h"
|
#include "../unit_test_framework.h"
|
||||||
@@ -207,6 +207,90 @@ static void test_hillhold_armed_to_idle_if_grade_drops(void)
|
|||||||
|
|
||||||
/* ---- Mutually exclusive: nicht in beiden Modi gleichzeitig ---- */
|
/* ---- Mutually exclusive: nicht in beiden Modi gleichzeitig ---- */
|
||||||
|
|
||||||
|
/* ---- Drive-Away-Assist (SWE-011 + SWE-012) ---- */
|
||||||
|
|
||||||
|
static SafetyInputs make_applied_at_rest(void)
|
||||||
|
{
|
||||||
|
SafetyInputs in = {0};
|
||||||
|
in.engine_running = true;
|
||||||
|
in.brake_pedal_pressed = false;
|
||||||
|
in.vehicle_speed_kmh = 0.0f;
|
||||||
|
in.grade_percent = 0.0f;
|
||||||
|
in.current_state = EPB_STATE_APPLIED;
|
||||||
|
in.gas_pedal_percent = 0.0f;
|
||||||
|
in.gear_in_drive = false;
|
||||||
|
in.door_closed = true;
|
||||||
|
in.seatbelt_fastened = true;
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_drive_away_armed_on_intent(void)
|
||||||
|
{
|
||||||
|
TEST_BEGIN("SWE-011 + SWE-012: Anfahrabsicht + Safety -> DRIVE_AWAY + Release-Request");
|
||||||
|
(void)safety_mgr_init();
|
||||||
|
SafetyInputs in = make_applied_at_rest();
|
||||||
|
in.gas_pedal_percent = 25.0f;
|
||||||
|
in.gear_in_drive = true;
|
||||||
|
safety_mgr_step_50ms(&in);
|
||||||
|
ASSERT_EQ(safety_mgr_get_state(), SAFETY_DRIVE_AWAY);
|
||||||
|
ASSERT_TRUE(safety_mgr_release_requested());
|
||||||
|
TEST_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_drive_away_blocked_without_safety(void)
|
||||||
|
{
|
||||||
|
TEST_BEGIN("SWE-012: Tuer offen blockiert Drive-Away");
|
||||||
|
(void)safety_mgr_init();
|
||||||
|
SafetyInputs in = make_applied_at_rest();
|
||||||
|
in.gas_pedal_percent = 25.0f;
|
||||||
|
in.gear_in_drive = true;
|
||||||
|
in.door_closed = false; /* Tuer offen */
|
||||||
|
safety_mgr_step_50ms(&in);
|
||||||
|
ASSERT_EQ(safety_mgr_get_state(), SAFETY_IDLE);
|
||||||
|
ASSERT_TRUE(!safety_mgr_release_requested());
|
||||||
|
TEST_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_drive_away_blocked_without_seatbelt(void)
|
||||||
|
{
|
||||||
|
TEST_BEGIN("SWE-012: Gurt nicht angelegt blockiert Drive-Away");
|
||||||
|
(void)safety_mgr_init();
|
||||||
|
SafetyInputs in = make_applied_at_rest();
|
||||||
|
in.gas_pedal_percent = 25.0f;
|
||||||
|
in.gear_in_drive = true;
|
||||||
|
in.seatbelt_fastened = false;
|
||||||
|
safety_mgr_step_50ms(&in);
|
||||||
|
ASSERT_EQ(safety_mgr_get_state(), SAFETY_IDLE);
|
||||||
|
TEST_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_drive_away_blocked_below_gas_threshold(void)
|
||||||
|
{
|
||||||
|
TEST_BEGIN("SWE-011: Gas < 10% loest kein Drive-Away aus");
|
||||||
|
(void)safety_mgr_init();
|
||||||
|
SafetyInputs in = make_applied_at_rest();
|
||||||
|
in.gas_pedal_percent = 5.0f;
|
||||||
|
in.gear_in_drive = true;
|
||||||
|
safety_mgr_step_50ms(&in);
|
||||||
|
ASSERT_EQ(safety_mgr_get_state(), SAFETY_IDLE);
|
||||||
|
TEST_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_drive_away_ends_when_released(void)
|
||||||
|
{
|
||||||
|
TEST_BEGIN("DRIVE_AWAY -> IDLE wenn Apply Controller geloest hat");
|
||||||
|
(void)safety_mgr_init();
|
||||||
|
SafetyInputs in = make_applied_at_rest();
|
||||||
|
in.gas_pedal_percent = 25.0f;
|
||||||
|
in.gear_in_drive = true;
|
||||||
|
safety_mgr_step_50ms(&in); /* -> DRIVE_AWAY */
|
||||||
|
in.current_state = EPB_STATE_RELEASED;
|
||||||
|
safety_mgr_step_50ms(&in);
|
||||||
|
ASSERT_EQ(safety_mgr_get_state(), SAFETY_IDLE);
|
||||||
|
ASSERT_TRUE(!safety_mgr_release_requested());
|
||||||
|
TEST_END();
|
||||||
|
}
|
||||||
|
|
||||||
static void test_already_applied_does_not_arm_auto_apply(void)
|
static void test_already_applied_does_not_arm_auto_apply(void)
|
||||||
{
|
{
|
||||||
TEST_BEGIN("Bereits Applied: kein Auto-Apply Arming");
|
TEST_BEGIN("Bereits Applied: kein Auto-Apply Arming");
|
||||||
@@ -235,6 +319,11 @@ int main(void)
|
|||||||
test_hillhold_active_on_brake_release();
|
test_hillhold_active_on_brake_release();
|
||||||
test_hillhold_active_ends_on_vehicle_rolling();
|
test_hillhold_active_ends_on_vehicle_rolling();
|
||||||
test_hillhold_armed_to_idle_if_grade_drops();
|
test_hillhold_armed_to_idle_if_grade_drops();
|
||||||
|
test_drive_away_armed_on_intent();
|
||||||
|
test_drive_away_blocked_without_safety();
|
||||||
|
test_drive_away_blocked_without_seatbelt();
|
||||||
|
test_drive_away_blocked_below_gas_threshold();
|
||||||
|
test_drive_away_ends_when_released();
|
||||||
test_already_applied_does_not_arm_auto_apply();
|
test_already_applied_does_not_arm_auto_apply();
|
||||||
TEST_SUMMARY();
|
TEST_SUMMARY();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,72 @@ REPO = Path(__file__).resolve().parent.parent
|
|||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# System Requirements
|
# Safety Goals (ISO 26262, abgeleitet aus HARA)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
SG_GOALS = [
|
||||||
|
{
|
||||||
|
"id": "SG-001", "asil": "D",
|
||||||
|
"title": "Kein ungewolltes Loesen der Parkbremse im Stillstand",
|
||||||
|
"text": (
|
||||||
|
"Die EPB darf sich im Stillstand des Fahrzeugs nicht ungewollt loesen. "
|
||||||
|
"Abgeleitet aus HARA-Hazards H-01 (ungewolltes Loesen, Parkphase) und "
|
||||||
|
"H-04 (Klemmkraftverlust im Hold).\n\n"
|
||||||
|
"**FTTI:** 5 s (H-01) / 30 s (H-04).\n"
|
||||||
|
"**Safe State:** APPLIED (Klemmkraft halten)."
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SG-002", "asil": "D",
|
||||||
|
"title": "Kein ungewolltes Festklemmen waehrend der Fahrt",
|
||||||
|
"text": (
|
||||||
|
"Die EPB darf nicht waehrend der Fahrt ungewollt festklemmen. "
|
||||||
|
"Abgeleitet aus HARA-Hazard H-02.\n\n"
|
||||||
|
"**FTTI:** 100 ms.\n"
|
||||||
|
"**Safe State:** Aktor stop (kein Apply einleiten)."
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SG-003", "asil": "A",
|
||||||
|
"title": "Schutz gegen Aktor-Ueberlast",
|
||||||
|
"text": (
|
||||||
|
"Das System muss Aktor-Motorschaeden durch Ueberstrom verhindern. "
|
||||||
|
"Abgeleitet aus HARA-Hazard H-05.\n\n"
|
||||||
|
"**FTTI:** 100 ms.\n"
|
||||||
|
"**Safe State:** Aktor abschalten, DTC setzen."
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SG-004", "asil": "C",
|
||||||
|
"title": "Zuverlaessige Hill-Hold-Uebergabe",
|
||||||
|
"text": (
|
||||||
|
"Beim Loslassen des Bremspedals an einem Hang muss die EPB die "
|
||||||
|
"Bremskraft uebernehmen, bevor das Fahrzeug zu rollen beginnt. "
|
||||||
|
"Abgeleitet aus HARA-Hazard H-06.\n\n"
|
||||||
|
"**FTTI:** 500 ms.\n"
|
||||||
|
"**Safe State:** Apply einleiten."
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SG-005", "asil": "B",
|
||||||
|
"title": "Reaktion auf Fahreranforderung",
|
||||||
|
"text": (
|
||||||
|
"Das System muss in spezifizierter Zeit auf Fahrer-Apply- und Release-"
|
||||||
|
"Anforderungen reagieren. Abgeleitet aus HARA-Hazards H-03 und H-07.\n\n"
|
||||||
|
"**Reaktionszeit:** Apply <= 800 ms, Release <= 1500 ms."
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# System Requirements (linken nach oben auf SG)
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
SYS_REQS = [
|
SYS_REQS = [
|
||||||
{
|
{
|
||||||
"id": "SYS-001", "asil": "D",
|
"id": "SYS-001", "asil": "D",
|
||||||
|
"links": ["SG-001"],
|
||||||
"title": "Halten der Parkbremse im Stillstand",
|
"title": "Halten der Parkbremse im Stillstand",
|
||||||
"text": (
|
"text": (
|
||||||
"Wenn die Parkbremse aktiviert ist und das Fahrzeug stillsteht, "
|
"Wenn die Parkbremse aktiviert ist und das Fahrzeug stillsteht, "
|
||||||
@@ -35,6 +95,7 @@ SYS_REQS = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "SYS-002", "asil": "D",
|
"id": "SYS-002", "asil": "D",
|
||||||
|
"links": ["SG-002", "SG-005"],
|
||||||
"title": "Apply auf Fahrer-Anforderung",
|
"title": "Apply auf Fahrer-Anforderung",
|
||||||
"text": (
|
"text": (
|
||||||
"Bei Betaetigung des EPB-Schalters in Apply-Richtung muss das "
|
"Bei Betaetigung des EPB-Schalters in Apply-Richtung muss das "
|
||||||
@@ -45,6 +106,7 @@ SYS_REQS = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "SYS-003", "asil": "B",
|
"id": "SYS-003", "asil": "B",
|
||||||
|
"links": ["SG-005"],
|
||||||
"title": "Release auf Fahrer-Anforderung",
|
"title": "Release auf Fahrer-Anforderung",
|
||||||
"text": (
|
"text": (
|
||||||
"Bei Betaetigung des EPB-Schalters in Release-Richtung muss das "
|
"Bei Betaetigung des EPB-Schalters in Release-Richtung muss das "
|
||||||
@@ -55,6 +117,7 @@ SYS_REQS = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "SYS-004", "asil": "D",
|
"id": "SYS-004", "asil": "D",
|
||||||
|
"links": ["SG-001"],
|
||||||
"title": "Auto-Apply bei Motor-Aus",
|
"title": "Auto-Apply bei Motor-Aus",
|
||||||
"text": (
|
"text": (
|
||||||
"Wenn der Motor ausgeschaltet wird und das Fahrzeug stillsteht "
|
"Wenn der Motor ausgeschaltet wird und das Fahrzeug stillsteht "
|
||||||
@@ -65,6 +128,7 @@ SYS_REQS = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "SYS-005", "asil": "D",
|
"id": "SYS-005", "asil": "D",
|
||||||
|
"links": ["SG-002", "SG-004"],
|
||||||
"title": "Hill-Hold am Berg",
|
"title": "Hill-Hold am Berg",
|
||||||
"text": (
|
"text": (
|
||||||
"Bei aktivem Hill-Hold (Fahrzeug steht am Hang mit Neigung > 5%, "
|
"Bei aktivem Hill-Hold (Fahrzeug steht am Hang mit Neigung > 5%, "
|
||||||
@@ -75,6 +139,7 @@ SYS_REQS = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "SYS-006", "asil": "B",
|
"id": "SYS-006", "asil": "B",
|
||||||
|
"links": ["SG-004"],
|
||||||
"title": "Auto-Release beim Anfahren (Drive-Away-Assist)",
|
"title": "Auto-Release beim Anfahren (Drive-Away-Assist)",
|
||||||
"text": (
|
"text": (
|
||||||
"Wenn die Parkbremse aktiv ist und der Fahrer Anfahrabsicht zeigt "
|
"Wenn die Parkbremse aktiv ist und der Fahrer Anfahrabsicht zeigt "
|
||||||
@@ -86,6 +151,7 @@ SYS_REQS = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "SYS-007", "asil": "B",
|
"id": "SYS-007", "asil": "B",
|
||||||
|
"links": ["SG-003"],
|
||||||
"title": "Aktor-Stromueberwachung",
|
"title": "Aktor-Stromueberwachung",
|
||||||
"text": (
|
"text": (
|
||||||
"Das System muss den Motorstrom jedes Aktors mit mindestens 1 kHz "
|
"Das System muss den Motorstrom jedes Aktors mit mindestens 1 kHz "
|
||||||
@@ -795,6 +861,7 @@ def write_items(items, target_dir: Path, with_links=True):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
write_items(SG_GOALS, REPO / "safety" / "sg")
|
||||||
write_items(SYS_REQS, REPO / "reqs" / "sys")
|
write_items(SYS_REQS, REPO / "reqs" / "sys")
|
||||||
write_items(SWE_REQS, REPO / "reqs" / "swe")
|
write_items(SWE_REQS, REPO / "reqs" / "swe")
|
||||||
write_items(SA_ELEMENTS, REPO / "arch" / "sys")
|
write_items(SA_ELEMENTS, REPO / "arch" / "sys")
|
||||||
|
|||||||
+213
-55
@@ -2,11 +2,12 @@
|
|||||||
"""
|
"""
|
||||||
Traceability-Werkzeug fuer demo-epb.
|
Traceability-Werkzeug fuer demo-epb.
|
||||||
|
|
||||||
Liest alle Markdown-Items in reqs/ und arch/ ein, validiert Links bidirektional
|
Liest Markdown-Items aus safety/sg, reqs/sys, reqs/swe, arch/sys, arch/swe und
|
||||||
und erzeugt eine HTML-Traceability-Matrix.
|
verifiziert die Traceability-Kette:
|
||||||
|
|
||||||
Doorstop-kompatibles Format (YAML-Frontmatter + Markdown-Body), aber ohne
|
SG <-- SYS <-- SA
|
||||||
Doorstop-Dependency — bleibt portabel.
|
<-- SWE <-- SWA <-- Code (@arch)
|
||||||
|
<-- Tests (@reqs)
|
||||||
|
|
||||||
Subcommands:
|
Subcommands:
|
||||||
check Validiert Konsistenz, exit 1 bei Fehlern
|
check Validiert Konsistenz, exit 1 bei Fehlern
|
||||||
@@ -28,25 +29,42 @@ from pathlib import Path
|
|||||||
REPO = Path(__file__).resolve().parent.parent
|
REPO = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
SOURCES = [
|
SOURCES = [
|
||||||
|
("SG", "safety/sg", "Safety Goals"),
|
||||||
("SYS", "reqs/sys", "System Requirements"),
|
("SYS", "reqs/sys", "System Requirements"),
|
||||||
("SWE", "reqs/swe", "Software Requirements"),
|
("SWE", "reqs/swe", "Software Requirements"),
|
||||||
("SA", "arch/sys", "System Architecture"),
|
("SA", "arch/sys", "System Architecture"),
|
||||||
("SWA", "arch/swe", "Software Architecture"),
|
("SWA", "arch/swe", "Software Architecture"),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Welche Quellen verlinken auf welche?
|
# Forward: items of <key> prefix SHOULD link to <target> prefix
|
||||||
# (key) -> (target_prefix) : Items mit key linken auf Items mit target_prefix
|
|
||||||
EXPECTED_LINKS = {
|
EXPECTED_LINKS = {
|
||||||
"SA": ["SYS"],
|
"SA": ["SYS"],
|
||||||
"SWE": ["SYS"],
|
"SWE": ["SYS"],
|
||||||
"SWA": ["SWE"],
|
"SWA": ["SWE"],
|
||||||
|
# SYS optionally links to SG — checked separately, only for safety-relevant SYS
|
||||||
}
|
}
|
||||||
|
|
||||||
# Reverse: welche Quellen MUESSEN von welchen Quellen referenziert werden?
|
# Reverse coverage: each item of <key> must be referenced by all items in list
|
||||||
# (target) -> [prefix that should link to target] (coverage check)
|
|
||||||
COVERAGE = {
|
COVERAGE = {
|
||||||
"SYS": ["SA", "SWE"], # jede SYS-Req muss durch SA und SWE abgedeckt sein
|
"SG": ["SYS"], # each SG must be detailed by at least one SYS
|
||||||
"SWE": ["SWA"], # jede SWE-Req muss durch SWA abgedeckt sein
|
"SYS": ["SA", "SWE"], # each SYS must be covered by SA + SWE
|
||||||
|
"SWE": ["SWA"], # each SWE must be implemented by SWA
|
||||||
|
}
|
||||||
|
|
||||||
|
# Components that are implemented in src/ (have a .c file)
|
||||||
|
IMPLEMENTED_SWA = {
|
||||||
|
"SWA-001": "src/safety_manager.c",
|
||||||
|
"SWA-002": "src/apply_controller.c",
|
||||||
|
"SWA-003": "src/actuator_driver.c",
|
||||||
|
"SWA-006": "src/switch_debouncer.c",
|
||||||
|
}
|
||||||
|
|
||||||
|
# Tests we ship — map test file → SWA it covers
|
||||||
|
IMPLEMENTED_TESTS = {
|
||||||
|
"test_safety_manager.c": "SWA-001",
|
||||||
|
"test_apply_controller.c": "SWA-002",
|
||||||
|
"test_actuator_driver.c": "SWA-003",
|
||||||
|
"test_switch_debouncer.c": "SWA-006",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -61,7 +79,6 @@ class Item:
|
|||||||
|
|
||||||
|
|
||||||
FRONTMATTER_RE = re.compile(r"^---\s*\n(.*?)\n---\s*\n", re.DOTALL)
|
FRONTMATTER_RE = re.compile(r"^---\s*\n(.*?)\n---\s*\n", re.DOTALL)
|
||||||
LINKS_RE = re.compile(r"^\s*-\s+([A-Z]+-\d+)", re.MULTILINE)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_item(path: Path, prefix: str) -> Item | None:
|
def parse_item(path: Path, prefix: str) -> Item | None:
|
||||||
@@ -71,7 +88,6 @@ def parse_item(path: Path, prefix: str) -> Item | None:
|
|||||||
return None
|
return None
|
||||||
fm = m.group(1)
|
fm = m.group(1)
|
||||||
|
|
||||||
# Crude YAML parsing — we only need a few fields.
|
|
||||||
def field_value(name: str) -> str | None:
|
def field_value(name: str) -> str | None:
|
||||||
rx = re.search(rf"^{name}:\s*(.*?)$", fm, re.MULTILINE)
|
rx = re.search(rf"^{name}:\s*(.*?)$", fm, re.MULTILINE)
|
||||||
return rx.group(1).strip().strip("'\"") if rx else None
|
return rx.group(1).strip().strip("'\"") if rx else None
|
||||||
@@ -79,7 +95,6 @@ def parse_item(path: Path, prefix: str) -> Item | None:
|
|||||||
asil = field_value("asil") or "?"
|
asil = field_value("asil") or "?"
|
||||||
title = field_value("header") or path.stem
|
title = field_value("header") or path.stem
|
||||||
|
|
||||||
# links: collect IDs from the `links:` block.
|
|
||||||
links: list[str] = []
|
links: list[str] = []
|
||||||
in_links = False
|
in_links = False
|
||||||
for line in fm.splitlines():
|
for line in fm.splitlines():
|
||||||
@@ -112,16 +127,76 @@ def collect_all() -> dict[str, Item]:
|
|||||||
return items
|
return items
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Code / Test traceability
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ARCH_TAG_RE = re.compile(r"@arch\s+([A-Z]+-\d+(?:\s+[A-Z]+-\d+)*)")
|
||||||
|
REQS_TAG_RE = re.compile(r"@reqs\s+([A-Z]+-\d+(?:\s+[A-Z]+-\d+)*)")
|
||||||
|
|
||||||
|
|
||||||
|
def extract_tags(path: Path) -> tuple[list[str], list[str]]:
|
||||||
|
"""Extract @arch and @reqs tag IDs from the file header (first ~400 chars)."""
|
||||||
|
if not path.exists():
|
||||||
|
return [], []
|
||||||
|
head = path.read_text()[:600]
|
||||||
|
arch_ids: list[str] = []
|
||||||
|
reqs_ids: list[str] = []
|
||||||
|
for m in ARCH_TAG_RE.finditer(head):
|
||||||
|
arch_ids.extend(re.findall(r"[A-Z]+-\d+", m.group(1)))
|
||||||
|
for m in REQS_TAG_RE.finditer(head):
|
||||||
|
reqs_ids.extend(re.findall(r"[A-Z]+-\d+", m.group(1)))
|
||||||
|
return arch_ids, reqs_ids
|
||||||
|
|
||||||
|
|
||||||
|
def check_code_test_mapping(items: dict[str, Item]) -> list[str]:
|
||||||
|
"""Check that:
|
||||||
|
- Each implemented .c file's @arch matches its SWA-id (per IMPLEMENTED_SWA)
|
||||||
|
- Each test's @reqs covers all SWE that the corresponding SWA implements
|
||||||
|
"""
|
||||||
|
errors: list[str] = []
|
||||||
|
|
||||||
|
for swa_id, src_rel in IMPLEMENTED_SWA.items():
|
||||||
|
src = REPO / src_rel
|
||||||
|
arch_tags, _ = extract_tags(src)
|
||||||
|
if swa_id not in arch_tags:
|
||||||
|
errors.append(f"{src_rel}: header @arch enthaelt {swa_id} nicht "
|
||||||
|
f"(gefunden: {arch_tags or '—'})")
|
||||||
|
|
||||||
|
# For each test, verify @reqs covers the SWE that the corresponding SWA links to
|
||||||
|
for test_file, swa_id in IMPLEMENTED_TESTS.items():
|
||||||
|
test_path = REPO / "tests" / "unit" / test_file
|
||||||
|
_, reqs_in_test = extract_tags(test_path)
|
||||||
|
if not reqs_in_test:
|
||||||
|
errors.append(f"tests/unit/{test_file}: kein @reqs Tag im Header")
|
||||||
|
continue
|
||||||
|
swa = items.get(swa_id)
|
||||||
|
if swa is None:
|
||||||
|
errors.append(f"tests/unit/{test_file}: referenziertes "
|
||||||
|
f"{swa_id} nicht gefunden")
|
||||||
|
continue
|
||||||
|
swa_swe = set(swa.links)
|
||||||
|
test_swe = set(reqs_in_test)
|
||||||
|
missing = swa_swe - test_swe
|
||||||
|
if missing:
|
||||||
|
errors.append(f"tests/unit/{test_file}: deckt nicht alle SWE "
|
||||||
|
f"der {swa_id} ab — fehlend: {sorted(missing)}")
|
||||||
|
|
||||||
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Commands
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
def cmd_check(items: dict[str, Item]) -> int:
|
def cmd_check(items: dict[str, Item]) -> int:
|
||||||
errors: list[str] = []
|
errors: list[str] = []
|
||||||
|
|
||||||
# 1. Each link target must exist
|
|
||||||
for it in items.values():
|
for it in items.values():
|
||||||
for link in it.links:
|
for link in it.links:
|
||||||
if link not in items:
|
if link not in items:
|
||||||
errors.append(f"{it.id} links to non-existent {link}")
|
errors.append(f"{it.id} links to non-existent {link}")
|
||||||
|
|
||||||
# 2. Forward expectation: items of certain prefixes must link to others
|
|
||||||
for it in items.values():
|
for it in items.values():
|
||||||
expected_prefixes = EXPECTED_LINKS.get(it.prefix, [])
|
expected_prefixes = EXPECTED_LINKS.get(it.prefix, [])
|
||||||
if not expected_prefixes:
|
if not expected_prefixes:
|
||||||
@@ -133,7 +208,6 @@ def cmd_check(items: dict[str, Item]) -> int:
|
|||||||
f"{it.id} ({it.prefix}) has no link to a {ep}-* item"
|
f"{it.id} ({it.prefix}) has no link to a {ep}-* item"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 3. Coverage: each item of certain prefix must be referenced by certain types
|
|
||||||
incoming: dict[str, set[str]] = {iid: set() for iid in items}
|
incoming: dict[str, set[str]] = {iid: set() for iid in items}
|
||||||
for it in items.values():
|
for it in items.values():
|
||||||
for link in it.links:
|
for link in it.links:
|
||||||
@@ -144,22 +218,30 @@ def cmd_check(items: dict[str, Item]) -> int:
|
|||||||
required = COVERAGE.get(it.prefix, [])
|
required = COVERAGE.get(it.prefix, [])
|
||||||
for rp in required:
|
for rp in required:
|
||||||
if rp not in incoming[it.id]:
|
if rp not in incoming[it.id]:
|
||||||
|
# Exclude QM-level SYS reqs from SG coverage check
|
||||||
|
if rp == "SYS" and it.prefix == "SG":
|
||||||
|
continue
|
||||||
errors.append(
|
errors.append(
|
||||||
f"{it.id} ({it.prefix}) is not referenced by any {rp}-* item"
|
f"{it.id} ({it.prefix}) is not referenced by any {rp}-* item"
|
||||||
)
|
)
|
||||||
|
|
||||||
print(f"\nItems found: {len(items)}")
|
# Code + Test mapping
|
||||||
print(f" SYS: {sum(1 for i in items.values() if i.prefix == 'SYS')}")
|
errors.extend(check_code_test_mapping(items))
|
||||||
print(f" SWE: {sum(1 for i in items.values() if i.prefix == 'SWE')}")
|
|
||||||
print(f" SA: {sum(1 for i in items.values() if i.prefix == 'SA')}")
|
counts = {p: sum(1 for i in items.values() if i.prefix == p)
|
||||||
print(f" SWA: {sum(1 for i in items.values() if i.prefix == 'SWA')}")
|
for p, _, _ in SOURCES}
|
||||||
|
print(f"\nItems found: {sum(counts.values())}")
|
||||||
|
for p, _, _ in SOURCES:
|
||||||
|
print(f" {p:4} {counts[p]:3}")
|
||||||
|
print(f"\nCode mappings: {len(IMPLEMENTED_SWA)} implemented SWA")
|
||||||
|
print(f"Test mappings: {len(IMPLEMENTED_TESTS)} test files")
|
||||||
print()
|
print()
|
||||||
if errors:
|
if errors:
|
||||||
print(f"FAIL: {len(errors)} traceability error(s):")
|
print(f"FAIL: {len(errors)} traceability error(s):")
|
||||||
for e in errors:
|
for e in errors:
|
||||||
print(f" - {e}")
|
print(f" - {e}")
|
||||||
return 1
|
return 1
|
||||||
print("OK — Traceability vollstaendig.")
|
print("OK — Traceability vollstaendig (SG → SYS → SA, SWE → SWA → Code+Test).")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
@@ -176,7 +258,7 @@ def asil_color(asil: str) -> str:
|
|||||||
def cmd_publish(items: dict[str, Item], out_dir: Path) -> int:
|
def cmd_publish(items: dict[str, Item], out_dir: Path) -> int:
|
||||||
out_dir.mkdir(parents=True, exist_ok=True)
|
out_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# Build forward and reverse maps
|
# Build reverse map: who links to me?
|
||||||
children: dict[str, list[str]] = {iid: [] for iid in items}
|
children: dict[str, list[str]] = {iid: [] for iid in items}
|
||||||
for it in items.values():
|
for it in items.values():
|
||||||
for link in it.links:
|
for link in it.links:
|
||||||
@@ -184,15 +266,35 @@ def cmd_publish(items: dict[str, Item], out_dir: Path) -> int:
|
|||||||
children[link].append(it.id)
|
children[link].append(it.id)
|
||||||
|
|
||||||
rows = []
|
rows = []
|
||||||
sys_items = [i for i in items.values() if i.prefix == "SYS"]
|
sgs = [i for i in items.values() if i.prefix == "SG"]
|
||||||
for sys in sorted(sys_items, key=lambda i: i.id):
|
qm_sys = [i for i in items.values() if i.prefix == "SYS" and not i.links]
|
||||||
sas = [c for c in children[sys.id] if items[c].prefix == "SA"]
|
# For each SG, build a row
|
||||||
swes = [c for c in children[sys.id] if items[c].prefix == "SWE"]
|
for sg in sorted(sgs, key=lambda i: i.id):
|
||||||
swas = sorted(set(c for s in swes for c in children[s]
|
sys_items = [c for c in children[sg.id] if items[c].prefix == "SYS"]
|
||||||
if items[c].prefix == "SWA"))
|
for s in sorted(sys_items):
|
||||||
rows.append({
|
sys_it = items[s]
|
||||||
"sys": sys, "sa": sas, "swe": swes, "swa": swas
|
sas = [c for c in children[sys_it.id] if items[c].prefix == "SA"]
|
||||||
})
|
swes = [c for c in children[sys_it.id] if items[c].prefix == "SWE"]
|
||||||
|
swas = sorted({c for sw in swes for c in children[sw]
|
||||||
|
if items[c].prefix == "SWA"})
|
||||||
|
code = sorted({swa for swa in swas if swa in IMPLEMENTED_SWA})
|
||||||
|
tests = sorted({f for f, swa in IMPLEMENTED_TESTS.items()
|
||||||
|
if swa in swas})
|
||||||
|
rows.append({"sg": sg, "sys": sys_it, "sa": sas, "swe": swes,
|
||||||
|
"swa": swas, "code": code, "tests": tests})
|
||||||
|
|
||||||
|
# Also include QM-level SYS (not linked to SG) as separate section
|
||||||
|
for sys_it in sorted(qm_sys, key=lambda i: i.id):
|
||||||
|
sas = [c for c in children[sys_it.id] if items[c].prefix == "SA"]
|
||||||
|
swes = [c for c in children[sys_it.id] if items[c].prefix == "SWE"]
|
||||||
|
swas = sorted({c for sw in swes for c in children[sw]
|
||||||
|
if items[c].prefix == "SWA"})
|
||||||
|
code = sorted({swa for swa in swas if swa in IMPLEMENTED_SWA})
|
||||||
|
tests = sorted({f for f, swa in IMPLEMENTED_TESTS.items() if swa in swas})
|
||||||
|
rows.append({"sg": None, "sys": sys_it, "sa": sas, "swe": swes,
|
||||||
|
"swa": swas, "code": code, "tests": tests})
|
||||||
|
|
||||||
|
counts = {p: sum(1 for i in items.values() if i.prefix == p) for p, _, _ in SOURCES}
|
||||||
|
|
||||||
# HTML
|
# HTML
|
||||||
parts = [
|
parts = [
|
||||||
@@ -201,60 +303,116 @@ def cmd_publish(items: dict[str, Item], out_dir: Path) -> int:
|
|||||||
"<title>demo-epb — Traceability Matrix</title>",
|
"<title>demo-epb — Traceability Matrix</title>",
|
||||||
"<style>",
|
"<style>",
|
||||||
"body{font-family:-apple-system,Segoe UI,sans-serif;padding:20px;color:#222}",
|
"body{font-family:-apple-system,Segoe UI,sans-serif;padding:20px;color:#222}",
|
||||||
"table{border-collapse:collapse;width:100%;font-size:14px}",
|
"table{border-collapse:collapse;width:100%;font-size:13px;margin-top:16px}",
|
||||||
"th,td{border:1px solid #ccc;padding:6px 8px;vertical-align:top;text-align:left}",
|
"th,td{border:1px solid #ccc;padding:6px 8px;vertical-align:top;text-align:left}",
|
||||||
"th{background:#f0f0f0}",
|
"th{background:#f0f0f0;position:sticky;top:0}",
|
||||||
"tr:nth-child(even) td{background:#fafafa}",
|
"tr:nth-child(even) td{background:#fafafa}",
|
||||||
".asil{display:inline-block;padding:1px 6px;border-radius:3px;color:white;font-weight:bold;font-size:11px}",
|
".asil{display:inline-block;padding:1px 6px;border-radius:3px;color:white;font-weight:bold;font-size:11px}",
|
||||||
".id{font-family:Consolas,monospace;font-size:13px}",
|
".id{font-family:Consolas,monospace;font-size:12px}",
|
||||||
".cnt{color:#666;font-size:11px}",
|
".cnt{color:#666;font-size:11px}",
|
||||||
"h1{color:#1f3864}",
|
"h1{color:#1f3864}h2{color:#1f3864;margin-top:30px}",
|
||||||
|
".missing{color:#c00}",
|
||||||
"</style></head><body>",
|
"</style></head><body>",
|
||||||
"<h1>demo-epb — Traceability Matrix</h1>",
|
"<h1>demo-epb — Traceability Matrix</h1>",
|
||||||
f"<p>Generiert aus {sum(1 for _ in items)} Items "
|
"<p>Vollstaendige Kette: <code>SG → SYS → SA, SWE → SWA → Code (@arch) + Test (@reqs)</code></p>",
|
||||||
f"(SYS: {len([i for i in items.values() if i.prefix=='SYS'])}, "
|
"<p>",
|
||||||
f"SWE: {len([i for i in items.values() if i.prefix=='SWE'])}, "
|
|
||||||
f"SA: {len([i for i in items.values() if i.prefix=='SA'])}, "
|
|
||||||
f"SWA: {len([i for i in items.values() if i.prefix=='SWA'])}).</p>",
|
|
||||||
"<table>",
|
|
||||||
"<tr><th>System-Requirement</th><th>System-Arch (SA)</th>"
|
|
||||||
"<th>Software-Req (SWE)</th><th>Software-Arch (SWA)</th></tr>",
|
|
||||||
]
|
]
|
||||||
|
for p, _, label in SOURCES:
|
||||||
|
parts.append(f"<strong>{p}:</strong> {counts[p]} ")
|
||||||
|
parts.append(f"<strong>Code-Files:</strong> {len(IMPLEMENTED_SWA)} ")
|
||||||
|
parts.append(f"<strong>Test-Files:</strong> {len(IMPLEMENTED_TESTS)}")
|
||||||
|
parts.append("</p>")
|
||||||
|
|
||||||
def cell(ids: list[str]) -> str:
|
parts.append("<table>")
|
||||||
|
parts.append(
|
||||||
|
"<tr><th>Safety Goal</th><th>System-Requirement</th>"
|
||||||
|
"<th>System-Arch</th><th>Software-Req</th>"
|
||||||
|
"<th>Software-Arch</th><th>Code</th><th>Test</th></tr>"
|
||||||
|
)
|
||||||
|
|
||||||
|
def cell_items(ids: list[str]) -> str:
|
||||||
if not ids:
|
if not ids:
|
||||||
return "<td style='color:#c00'>—</td>"
|
return "<td class='missing'>—</td>"
|
||||||
bits = []
|
bits = []
|
||||||
for i in ids:
|
for i in ids:
|
||||||
it = items[i]
|
it = items[i]
|
||||||
c = asil_color(it.asil)
|
c = asil_color(it.asil)
|
||||||
bits.append(
|
bits.append(
|
||||||
f"<div><span class='id'>{html.escape(i)}</span> "
|
f"<div><span class='id'>{html.escape(i)}</span> "
|
||||||
f"<span class='asil' style='background:{c}'>{html.escape(it.asil)}</span></div>"
|
f"<span class='asil' style='background:{c}'>"
|
||||||
|
f"{html.escape(it.asil)}</span></div>"
|
||||||
f"<div class='cnt'>{html.escape(it.title)}</div>"
|
f"<div class='cnt'>{html.escape(it.title)}</div>"
|
||||||
)
|
)
|
||||||
return "<td>" + "".join(bits) + "</td>"
|
return "<td>" + "".join(bits) + "</td>"
|
||||||
|
|
||||||
|
def cell_item(it: Item | None) -> str:
|
||||||
|
if it is None:
|
||||||
|
return "<td class='missing'>—</td>"
|
||||||
|
c = asil_color(it.asil)
|
||||||
|
return (f"<td><div><span class='id'>{html.escape(it.id)}</span> "
|
||||||
|
f"<span class='asil' style='background:{c}'>"
|
||||||
|
f"{html.escape(it.asil)}</span></div>"
|
||||||
|
f"<div class='cnt'>{html.escape(it.title)}</div></td>")
|
||||||
|
|
||||||
|
def cell_files(files: list[str], prefix: str = "") -> str:
|
||||||
|
if not files:
|
||||||
|
return "<td class='cnt'>—</td>"
|
||||||
|
return "<td>" + "".join(
|
||||||
|
f"<div class='id'>{html.escape(prefix + f)}</div>"
|
||||||
|
for f in files
|
||||||
|
) + "</td>"
|
||||||
|
|
||||||
for r in rows:
|
for r in rows:
|
||||||
sys = r["sys"]
|
parts.append("<tr>")
|
||||||
c = asil_color(sys.asil)
|
parts.append(cell_item(r["sg"]))
|
||||||
first = (f"<td><div><span class='id'>{html.escape(sys.id)}</span> "
|
parts.append(cell_item(r["sys"]))
|
||||||
f"<span class='asil' style='background:{c}'>{html.escape(sys.asil)}</span></div>"
|
parts.append(cell_items(r["sa"]))
|
||||||
f"<div class='cnt'>{html.escape(sys.title)}</div></td>")
|
parts.append(cell_items(r["swe"]))
|
||||||
parts.append("<tr>" + first + cell(r["sa"]) + cell(r["swe"]) + cell(r["swa"]) + "</tr>")
|
parts.append(cell_items(r["swa"]))
|
||||||
|
parts.append(cell_files([IMPLEMENTED_SWA.get(s, "") for s in r["code"]
|
||||||
|
if IMPLEMENTED_SWA.get(s)]))
|
||||||
|
parts.append(cell_files(r["tests"], "tests/unit/"))
|
||||||
|
parts.append("</tr>")
|
||||||
|
|
||||||
parts.append("</table></body></html>")
|
parts.append("</table>")
|
||||||
|
|
||||||
|
# Code/Test details
|
||||||
|
parts.append("<h2>Code → Architektur</h2>")
|
||||||
|
parts.append("<table><tr><th>Datei</th><th>@arch</th><th>@reqs</th></tr>")
|
||||||
|
for swa_id, src_rel in IMPLEMENTED_SWA.items():
|
||||||
|
arch, reqs = extract_tags(REPO / src_rel)
|
||||||
|
parts.append(
|
||||||
|
f"<tr><td class='id'>{html.escape(src_rel)}</td>"
|
||||||
|
f"<td>{' '.join(arch)}</td>"
|
||||||
|
f"<td class='cnt'>{' '.join(reqs)}</td></tr>"
|
||||||
|
)
|
||||||
|
parts.append("</table>")
|
||||||
|
|
||||||
|
parts.append("<h2>Test → Anforderungen</h2>")
|
||||||
|
parts.append("<table><tr><th>Test-Datei</th><th>Decklt SWA</th><th>@reqs</th></tr>")
|
||||||
|
for test_file, swa_id in IMPLEMENTED_TESTS.items():
|
||||||
|
_, reqs = extract_tags(REPO / "tests" / "unit" / test_file)
|
||||||
|
parts.append(
|
||||||
|
f"<tr><td class='id'>tests/unit/{html.escape(test_file)}</td>"
|
||||||
|
f"<td>{swa_id}</td>"
|
||||||
|
f"<td class='cnt'>{' '.join(reqs)}</td></tr>"
|
||||||
|
)
|
||||||
|
parts.append("</table>")
|
||||||
|
|
||||||
|
parts.append("</body></html>")
|
||||||
(out_dir / "index.html").write_text("\n".join(parts))
|
(out_dir / "index.html").write_text("\n".join(parts))
|
||||||
|
|
||||||
# JSON for machine consumption
|
# JSON
|
||||||
matrix = []
|
matrix = []
|
||||||
for r in rows:
|
for r in rows:
|
||||||
matrix.append({
|
matrix.append({
|
||||||
|
"sg": {"id": r["sg"].id, "asil": r["sg"].asil} if r["sg"] else None,
|
||||||
"sys": {"id": r["sys"].id, "asil": r["sys"].asil, "title": r["sys"].title},
|
"sys": {"id": r["sys"].id, "asil": r["sys"].asil, "title": r["sys"].title},
|
||||||
"sa": [{"id": i, "asil": items[i].asil} for i in r["sa"]],
|
"sa": [{"id": i, "asil": items[i].asil} for i in r["sa"]],
|
||||||
"swe": [{"id": i, "asil": items[i].asil} for i in r["swe"]],
|
"swe": [{"id": i, "asil": items[i].asil} for i in r["swe"]],
|
||||||
"swa": [{"id": i, "asil": items[i].asil} for i in r["swa"]],
|
"swa": [{"id": i, "asil": items[i].asil} for i in r["swa"]],
|
||||||
|
"code": [IMPLEMENTED_SWA[s] for s in r["code"] if s in IMPLEMENTED_SWA],
|
||||||
|
"tests": [f"tests/unit/{f}" for f in r["tests"]],
|
||||||
})
|
})
|
||||||
(out_dir / "matrix.json").write_text(json.dumps(matrix, indent=2))
|
(out_dir / "matrix.json").write_text(json.dumps(matrix, indent=2))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user