PlatSim_Genova/TestEnvironment/scripts/__OLD/GRIFO_M_PBIT - gestione migliore della seriale.py
2026-01-30 16:38:33 +01:00

982 lines
62 KiB
Python

"""
GRIFO_M_PBIT.py - Automated Power-On BIT Test for GRIFO-F/TH Radar
This script performs comprehensive Built-In Test (BIT) verification with power cycling:
- Executes configurable number of test repetitions (default: 10)
- Power cycles radar between runs to simulate cold-start conditions
- Monitors B6 LRU (Line Replaceable Unit) status fields
- Performs detailed B8 diagnostic drill-down on real failures
- Generates comprehensive statistics report with timing analysis
Test Flow:
1. Power on radar and wait for initialization
2. Execute BIT and wait for completion (timeout: 180s)
3. Verify all 12 B6 LRU status fields
4. If real failures detected, drill-down into 185 B8 diagnostic fields
5. Track statistics (timing, pass/fail counts, failure details)
6. Power off and repeat
7. Generate final comprehensive report with aggregate statistics
Author: Test Automation Team
Date: 2026-01-29
"""
import __init__
import signal
import time,sys,os
import logging
from leo_grifo_common import *
from test_common_function import *
from leo_grifo_test_report import testReport
from leo_grifo_1553 import theGrifo1553
#import leo_grifo_serial_maintnance
from logger import logger_setup
import leo_grifo_terminal
import pdb
import traceback
NUMBER_OF_REPETITIONS = 10 # Total test cycles to execute
PBIT_SEC_TIME = 180 # BIT completion timeout in seconds
# ====================
# KNOWN FAILURES CONFIGURATION
# ====================
# List of field names that are expected to fail due to HW test setup limitations.
# These failures are tracked but do not trigger B8 drill-down or test failure.
#
# Use case: When test HW setup lacks physical components (e.g., pedestal unit),
# certain status checks will always fail. Adding them here prevents false negatives.
#
# Format: Full field name from bit_fields tuple
# Note: Known failures are reported separately in statistics but don't affect test verdict
KNOWN_FAILURES = [
"radar_health_status_and_bit_report_valid_RdrHealthStatusAndBitReport_pedestal_status",
# Add more known HW setup limitations here as needed
]
interruptRequest = False # Global flag for graceful Ctrl-C handling
# ====================
# TEST STATISTICS TRACKING
# ====================
# Global dictionary to track statistics across all test repetitions.
# Populated during test execution and used to generate final comprehensive report.
#
# Structure:
# repetitions: List of dicts, one per run, containing:
# - repetition: Run number (1-based)
# - pbit_time: BIT completion time in seconds
# - bit_available: Boolean, True if BIT completed
# - success: Boolean, overall run result (pass/fail)
# - b6_total/pass/fail/known_fail: B6 LRU status check counts
# - b8_checked/pass/fail: B8 diagnostic check counts
# - failures: List of (field_name, value) tuples for real failures
# - known_failures: List of (field_name, value) tuples for expected failures
# total_runs: Counter for completed test runs
# successful_runs: Counter for runs with no real failures
# failed_runs: Counter for runs with real failures detected
test_statistics = {
'repetitions': [], # List of per-run statistics dictionaries
'total_runs': 0, # Total number of completed runs
'successful_runs': 0, # Number of runs that passed (only known failures allowed)
'failed_runs': 0, # Number of runs with real failures detected
}
def signal_handler(sig, frame):
"""Handle Ctrl-C signal for graceful test termination."""
global interruptRequest
logging.info("Ctrl-C detected, exiting gracefully...")
interruptRequest = True
def generate_final_statistics_report(report, stats):
"""
Generate comprehensive final statistics report with 8-section analysis.
Produces professional test summary suitable for formal documentation and presentations.
Includes aggregate statistics, timing analysis, failure categorization, and test verdict.
Args:
report: testReport object for PDF generation (supports add_comment method)
stats: test_statistics dictionary containing all run data
Report Sections:
1. Overall Test Summary: Total runs, success/fail rates with percentages
2. Detailed Per-Run Results: Compact table showing status, timing, B6/B8 metrics per run
3. Aggregate Statistics: Combined B6/B8 checks from all runs with pass rates
4. PBIT Timing Analysis: Average, min, max, std dev, utilization vs target timeout
5. Known Failures Tracking: HW setup limitations with consistency flags
6. Real Failures Analysis: Top 15 failures by frequency with priority levels
7. Failure Distribution: Subsystem breakdown with visual bar charts
8. Test Conclusion: Automated verdict (EXCELLENT/GOOD/ACCEPTABLE/CRITICAL)
Returns:
None (outputs to report object)
"""
report.add_comment("\n" + "="*90)
report.add_comment(" FINAL TEST STATISTICS REPORT")
report.add_comment("="*90)
# ========== SECTION 1: OVERALL SUMMARY ==========
# High-level pass/fail metrics across all test runs
total = stats['total_runs']
success = stats['successful_runs']
failed = stats['failed_runs']
success_rate = (success / total * 100) if total > 0 else 0
report.add_comment("\n┌─── OVERALL TEST SUMMARY ───────────────────────────────────────────────────────┐")
report.add_comment(f"│ Total Runs: {total:3d}")
report.add_comment(f"│ Successful Runs: {success:3d} ({success_rate:5.1f}%) │")
report.add_comment(f"│ Failed Runs: {failed:3d} ({100-success_rate:5.1f}%) │")
report.add_comment("└────────────────────────────────────────────────────────────────────────────────┘")
# ========== SECTION 2: DETAILED PER-RUN TABLE ==========
# Compact tabular view of each test run with key metrics + serial statistics
report.add_comment("\n┌─── DETAILED PER-RUN RESULTS ───────────────────────────────────────────────────────────────────────┐")
# Table columns: Run# | Status | PBIT time | B6 counts | B8 counts | Serial stats | Result
table_header = (
"│ │\n"
"│ Run │ Status │ PBIT │ B6 Status (P/F/K) │ B8 Checked │ Serial (E/F/R) │ B8 Fail │ Result │\n"
"│─────┼────────┼────────┼───────────────────┼────────────┼────────────────┼─────────┼─────────│\n"
)
report.add_comment(table_header)
for run in stats['repetitions']:
# Format run result with pass/fail indicators
status_symbol = "" if run['success'] else ""
status_text = "PASS" if run['success'] else "FAIL"
pbit_time = run['pbit_time'] if run['bit_available'] else 0
# B6 status: compact Pass/Fail/Known format for quick scanning
b6_status = f"{run['b6_pass']:2d}/{run['b6_fail']}/{run['b6_known_fail']}"
# Serial statistics: compact Error/Fatal/Recycle format
serial_stats_display = f"{run.get('serial_errors', 0)}/{run.get('serial_fatal', 0)}/{run.get('serial_recycles', 0)}"
# B8 failures: show count or '-' if not checked (no real B6 failures)
b8_fail_count = run['b8_fail']
b8_fail_display = f"{b8_fail_count:3d}" if b8_fail_count > 0 else " -"
# Result with symbol
result = f"{status_symbol} {status_text}"
row = (
f"{run['repetition']:3d}{status_text:6s}{pbit_time:5.1f}s │ "
f"{b6_status:^17s}{run['b8_checked']:10d}{serial_stats_display:^14s}{b8_fail_display:^7s}{result:7s}\n"
)
report.add_comment(row)
report.add_comment("└────────────────────────────────────────────────────────────────────────────────────────────────┘")
report.add_comment(" Legend: B6 Status = Pass/Fail/Known | Serial = Errors/Fatal/Recycles | '-' = Not checked")
# ========== SECTION 3: AGGREGATE STATISTICS ==========
# Sum all B6/B8 checks across runs for overall health assessment
report.add_comment("\n┌─── AGGREGATE STATISTICS (All Runs Combined) ──────────────────────────────────┐")
# Calculate total checks and outcomes across all repetitions
total_b6_checks = sum(r['b6_total'] for r in stats['repetitions'])
total_b6_pass = sum(r['b6_pass'] for r in stats['repetitions'])
total_b6_fail = sum(r['b6_fail'] for r in stats['repetitions'])
total_b6_known = sum(r['b6_known_fail'] for r in stats['repetitions'])
total_b8_checks = sum(r['b8_checked'] for r in stats['repetitions'])
total_b8_pass = sum(r['b8_pass'] for r in stats['repetitions'])
total_b8_fail = sum(r['b8_fail'] for r in stats['repetitions'])
b6_pass_rate = (total_b6_pass / total_b6_checks * 100) if total_b6_checks > 0 else 0
b8_pass_rate = (total_b8_pass / total_b8_checks * 100) if total_b8_checks > 0 else 0
report.add_comment(f"│ │")
report.add_comment(f"│ B6 LRU Status Checks: │")
report.add_comment(f"│ Total Checks: {total_b6_checks:5d}")
report.add_comment(f"│ Pass: {total_b6_pass:5d} ({b6_pass_rate:5.1f}%) │")
report.add_comment(f"│ Fail (Real): {total_b6_fail:5d} ({total_b6_fail/total_b6_checks*100 if total_b6_checks>0 else 0:5.1f}%) │")
report.add_comment(f"│ Known Failures: {total_b6_known:5d} ({total_b6_known/total_b6_checks*100 if total_b6_checks>0 else 0:5.1f}%) [HW setup - ignored] │")
report.add_comment(f"│ │")
if total_b8_checks > 0:
report.add_comment(f"│ B8 Diagnostic Checks: │")
report.add_comment(f"│ Total Checks: {total_b8_checks:5d}")
report.add_comment(f"│ Pass: {total_b8_pass:5d} ({b8_pass_rate:5.1f}%) │")
report.add_comment(f"│ Fail: {total_b8_fail:5d} ({total_b8_fail/total_b8_checks*100:5.1f}%) │")
report.add_comment(f"│ │")
# Serial communication aggregate statistics
total_serial_msgs = sum(r.get('serial_total', 0) for r in stats['repetitions'])
total_serial_errors = sum(r.get('serial_errors', 0) for r in stats['repetitions'])
total_serial_fatal = sum(r.get('serial_fatal', 0) for r in stats['repetitions'])
total_serial_recycles = sum(r.get('serial_recycles', 0) for r in stats['repetitions'])
report.add_comment(f"│ Serial Communication: │")
report.add_comment(f"│ Total Messages: {total_serial_msgs:5d}")
report.add_comment(f"│ Error (%%E): {total_serial_errors:5d}")
report.add_comment(f"│ Fatal (%%F): {total_serial_fatal:5d}")
report.add_comment(f"│ System Recycles: {total_serial_recycles:5d} [Power cycles + unexpected resets] │")
report.add_comment(f"│ │")
report.add_comment("└────────────────────────────────────────────────────────────────────────────────┘")
# ========== SECTION 4: TIMING ANALYSIS ==========
# Statistical analysis of BIT completion times to assess performance consistency
pbit_times = [r['pbit_time'] for r in stats['repetitions'] if r['bit_available']]
if pbit_times:
avg_pbit = sum(pbit_times) / len(pbit_times)
min_pbit = min(pbit_times)
max_pbit = max(pbit_times)
# Calculate standard deviation for timing consistency assessment
variance = sum((t - avg_pbit) ** 2 for t in pbit_times) / len(pbit_times)
std_dev = variance ** 0.5
report.add_comment("\n┌─── PBIT TIMING ANALYSIS ───────────────────────────────────────────────────────┐")
report.add_comment(f"│ │")
report.add_comment(f"│ Samples: {len(pbit_times):3d} runs │")
report.add_comment(f"│ Average: {avg_pbit:6.2f}s │")
report.add_comment(f"│ Minimum: {min_pbit:6.2f}s │")
report.add_comment(f"│ Maximum: {max_pbit:6.2f}s │")
report.add_comment(f"│ Std Deviation: {std_dev:6.2f}s │")
report.add_comment(f"│ Target Timeout: {PBIT_SEC_TIME:6.2f}s │")
# Performance indicator based on timeout utilization percentage
# <30% = EXCELLENT, <50% = GOOD, else ACCEPTABLE
avg_utilization = (avg_pbit / PBIT_SEC_TIME * 100) if PBIT_SEC_TIME > 0 else 0
perf_indicator = "EXCELLENT" if avg_utilization < 30 else "GOOD" if avg_utilization < 50 else "ACCEPTABLE"
report.add_comment(f"│ Avg Utilization: {avg_utilization:5.1f}% ({perf_indicator}) │")
report.add_comment(f"│ │")
report.add_comment("└────────────────────────────────────────────────────────────────────────────────┘")
# ========== SECTION 5: KNOWN FAILURES TRACKING ==========
# Track expected failures due to HW test setup limitations (from KNOWN_FAILURES list)
all_known = [f for r in stats['repetitions'] for f in r['known_failures']]
if all_known:
# Count occurrence frequency to identify consistent vs intermittent known issues
known_counts = {}
for field, _ in all_known:
field_name = field.split('_')[-1] # Short name
known_counts[field_name] = known_counts.get(field_name, 0) + 1
report.add_comment("\n┌─── KNOWN FAILURES (HW Setup - Ignored for Analysis) ──────────────────────────┐")
report.add_comment(f"│ │")
for field, count in sorted(known_counts.items(), key=lambda x: x[1], reverse=True):
occurrence_rate = count / total * 100
# Flag as CONSISTENT if appears in all runs, else INTERMITTENT
consistency = "CONSISTENT" if count == total else "INTERMITTENT"
report.add_comment(f"│ • {field:25s} {count:2d}/{total} runs ({occurrence_rate:5.1f}%) {consistency:12s}")
report.add_comment(f"│ │")
report.add_comment("└────────────────────────────────────────────────────────────────────────────────┘")
# ========== SECTION 5.1: SERIAL RECYCLE ANALYSIS ==========
# Track system recycles detected via serial communication (RECYCLE keyword)
all_recycles = []
for run in stats['repetitions']:
run_recycles = run.get('serial_recycles', 0)
if run_recycles > 0:
all_recycles.append((run['repetition'], run_recycles, run.get('serial_details', [])))
if total_serial_recycles > 0:
report.add_comment("\n┌─── SYSTEM RECYCLE ANALYSIS (Serial Communication) ────────────────────────────┐")
report.add_comment(f"│ │")
report.add_comment(f"│ Total Recycles Detected: {total_serial_recycles:2d}")
report.add_comment(f"│ Runs with Recycles: {len(all_recycles):2d}/{total}")
report.add_comment(f"│ │")
# Determine recycle frequency pattern
expected_recycles_per_run = 1 # Power cycle at start
unexpected_recycles = total_serial_recycles - (total * expected_recycles_per_run)
if unexpected_recycles > 0:
report.add_comment(f"│ ⚠ WARNING: {unexpected_recycles} unexpected recycles detected! │")
report.add_comment(f"│ Expected: {expected_recycles_per_run} per run (planned power cycle) │")
report.add_comment(f"│ Additional recycles may indicate system instability │")
else:
report.add_comment(f"│ ✓ All recycles expected (planned power cycles only) │")
report.add_comment(f"│ │")
report.add_comment("│ Per-Run Recycle Details: │")
for run_num, recycle_count, details in all_recycles:
recycle_details_for_run = [d for d in details if d['type'] == 'RECYCLE']
report.add_comment(f"│ Run {run_num:2d}: {recycle_count} recycle(s) │")
for detail in recycle_details_for_run[:3]: # Show first 3
timestamp = detail.get('timestamp', 'N/A')
report.add_comment(f"│ [{timestamp}] Recycle detected │")
report.add_comment(f"│ │")
report.add_comment("└────────────────────────────────────────────────────────────────────────────────┘")
# ========== SECTION 6: REAL FAILURES ANALYSIS ==========
# Analyze actual failures requiring investigation (not in KNOWN_FAILURES)
all_failures = [f for r in stats['repetitions'] for f in r['failures']]
if all_failures:
# Count failure frequency by field and assign priority levels
fail_counts = {}
for field, value in all_failures:
# Abbreviate field names for readability while preserving key information
parts = field.split('_')
if 'test_' in field:
# Test fields: extract test type and SRU location
field_short = '_'.join([p for p in parts if p.startswith('test_') or p.startswith('sru')])
else:
# Status fields: use last 2-3 parts (e.g., processor_status, transmitter_test)
field_short = '_'.join(parts[-3:]) if len(parts) > 3 else field
fail_counts[field_short] = fail_counts.get(field_short, 0) + 1
report.add_comment("\n┌─── REAL FAILURES DETECTED (Require Investigation) ────────────────────────────┐")
report.add_comment(f"│ │")
report.add_comment(f"│ Total Unique Failures: {len(fail_counts)}")
report.add_comment(f"│ Total Occurrences: {len(all_failures)}")
report.add_comment(f"│ │")
report.add_comment("│ Most Frequent Failures: │")
# Show top 15 most frequent failures with priority assignment
# Priority: HIGH (≥50% of runs), MEDIUM (≥25%), LOW (<25%)
for idx, (field, count) in enumerate(sorted(fail_counts.items(), key=lambda x: x[1], reverse=True)[:15], 1):
occurrence_rate = count / total * 100
priority = "HIGH" if count >= total/2 else "MEDIUM" if count >= total/4 else "LOW"
report.add_comment(f"{idx:2d}. {field:35s} {count:2d} occ ({occurrence_rate:5.1f}%) [{priority:6s}] │")
if len(fail_counts) > 15:
report.add_comment(f"│ ... and {len(fail_counts)-15} more unique failures │")
report.add_comment(f"│ │")
report.add_comment("└────────────────────────────────────────────────────────────────────────────────┘")
# Subsystem-level failure distribution for root cause analysis
report.add_comment("\n┌─── FAILURE DISTRIBUTION BY SUBSYSTEM ──────────────────────────────────────────┐")
category_failures = {}
for field, _ in all_failures:
# Categorize failures by subsystem using field name pattern matching
if 'failure_location_processor' in field:
cat = 'Processor SRU'
elif 'failure_location_transmitter' in field:
cat = 'Transmitter SRU'
elif 'failure_location_receiver' in field:
cat = 'Receiver SRU'
elif 'failure_location_servoloop' in field:
cat = 'Servoloop SRU'
elif 'failure_location_pedestal' in field:
cat = 'Pedestal SRU'
elif 'failure_location_rx_frontend' in field:
cat = 'RX Frontend SRU'
elif 'processor_test_results' in field or 'signal_processor' in field or 'data_processor' in field:
cat = 'Processor Tests'
elif 'transmitter_test_results' in field:
cat = 'Transmitter Tests'
elif 'receiver_and_rx' in field or 'rx_module' in field:
cat = 'Receiver Tests'
elif 'servoloop_test' in field:
cat = 'Servoloop Tests'
elif 'degradation_conditions' in field:
cat = 'Degradation'
elif 'radar_health_status' in field:
cat = 'B6 LRU Status'
else:
cat = 'Other'
category_failures[cat] = category_failures.get(cat, 0) + 1
report.add_comment(f"│ │")
for cat, count in sorted(category_failures.items(), key=lambda x: x[1], reverse=True):
cat_rate = count / len(all_failures) * 100
bar_length = int(cat_rate / 5) # Visual bar: 1 block per 5%, max 20 chars
bar = "" * bar_length
report.add_comment(f"{cat:25s} {count:3d} ({cat_rate:5.1f}%) {bar:20s}")
report.add_comment(f"│ │")
report.add_comment("└────────────────────────────────────────────────────────────────────────────────┘")
else:
report.add_comment("\n┌─── REAL FAILURES DETECTED ─────────────────────────────────────────────────────┐")
report.add_comment(f"│ │")
report.add_comment(f"│ ✓ NO REAL FAILURES DETECTED │")
report.add_comment(f"│ │")
report.add_comment(f"│ All runs completed successfully with only known HW setup limitations. │")
report.add_comment(f"│ │")
report.add_comment("└────────────────────────────────────────────────────────────────────────────────┘")
# ========== SECTION 8: TEST CONCLUSION ==========
# Automated verdict based on success rate with actionable recommendations
report.add_comment("\n┌─── TEST CONCLUSION ────────────────────────────────────────────────────────────┐")
report.add_comment(f"│ │")
# Assign verdict: EXCELLENT (100%), GOOD (≥80%), ACCEPTABLE (≥50%), CRITICAL (<50%)
if success == total:
report.add_comment(f"│ ✓✓✓ ALL RUNS PASSED ({total}/{total}) │")
report.add_comment(f"│ │")
report.add_comment(f"│ Radar BIT system is operating within expected parameters. │")
verdict = "EXCELLENT"
elif success >= total * 0.8:
report.add_comment(f"│ ✓ MOSTLY SUCCESSFUL ({success}/{total} runs passed, {success_rate:.1f}%) │")
report.add_comment(f"│ │")
report.add_comment(f"│ Radar BIT system shows good performance with minor issues. │")
verdict = "GOOD"
elif success >= total * 0.5:
report.add_comment(f"│ ⚠ PARTIAL SUCCESS ({success}/{total} runs passed, {success_rate:.1f}%) │")
report.add_comment(f"│ │")
report.add_comment(f"│ Radar BIT system requires attention. Investigation recommended. │")
verdict = "ACCEPTABLE"
else:
report.add_comment(f"│ ✗ CRITICAL ISSUES ({success}/{total} runs passed, {success_rate:.1f}%) │")
report.add_comment(f"│ │")
report.add_comment(f"│ Radar BIT system has significant problems. Immediate action required. │")
verdict = "CRITICAL"
report.add_comment(f"│ │")
report.add_comment(f"│ Overall Assessment: {verdict:20s}")
report.add_comment(f"│ │")
report.add_comment("└────────────────────────────────────────────────────────────────────────────────┘")
report.add_comment("\n" + "="*90)
report.add_comment(" END OF REPORT")
report.add_comment("="*90 + "\n")
def tgt_gen(interface):
logging.info('tgt_gen()')
#time.sleep(5)
period=10 #ms
expeced_range=1000
pcnt=0
for i in range(500):
time.sleep(0.010)
cnt = interface.getSingleMessageReceivedSz("B9")
t_num=interface.getMessageFieldValue("B9", "b9_t_num")
t_rng=interface.getMessageFieldValue("B9", "b9_t1_rng")
if (i % 10)==0:
dcnt=cnt-pcnt
pcnt=cnt
logging.info(f'TgtMsg: {cnt} {dcnt}')
if t_num>0:
logging.info(f'Tgt: {t_num} @ {t_rng}')
ret_proc_sts, err= check(theGrifo1553,(1,2), "B9", "b9_t_num")
check(theGrifo1553,(1179, 1186), "B9", "b9_t1_rng")
break
if interruptRequest is True:
break
def tgt_gen_alone(interface):
interface.logStart(3,os.path.dirname(sys.argv[0]))
for n in range(10*1000):
logging.info(f'tgt_gen_alone(): {n}')
tgt_gen(interface)
if interruptRequest is True:
break
interface.logStop()
return True
def test_proc():
global report, test_statistics
# Complete bit_fields: All B6 LRU status + All B8 degradation/SRU/test fields
# Total: 185 fields (12 B6 status + 12 B8 degradation + 43 B8 SRU + 118 B8 tests)
bit_fields = (
# ===== B6: LRU Status Fields =====
"radar_health_status_and_bit_report_valid_RdrHealthStatusAndBitReport_array_status",
"radar_health_status_and_bit_report_valid_RdrHealthStatusAndBitReport_pedestal_status",
"radar_health_status_and_bit_report_valid_RdrHealthStatusAndBitReport_pressurization_status",
"radar_health_status_and_bit_report_valid_RdrHealthStatusAndBitReport_processor_over_temperature_alarm",
"radar_health_status_and_bit_report_valid_RdrHealthStatusAndBitReport_processor_status",
"radar_health_status_and_bit_report_valid_RdrHealthStatusAndBitReport_radar_fail_status",
"radar_health_status_and_bit_report_valid_RdrHealthStatusAndBitReport_receiver_status",
"radar_health_status_and_bit_report_valid_RdrHealthStatusAndBitReport_rx_front_end_status",
"radar_health_status_and_bit_report_valid_RdrHealthStatusAndBitReport_servoloop_over_temperature_alarm",
"radar_health_status_and_bit_report_valid_RdrHealthStatusAndBitReport_servoloop_status",
"radar_health_status_and_bit_report_valid_RdrHealthStatusAndBitReport_trasmitter_over_temperature_alarm",
"radar_health_status_and_bit_report_valid_RdrHealthStatusAndBitReport_trasmitter_status",
# ===== B8: Degradation Conditions =====
"degradation_conditions_w1_DegradationConditionsW1_bcn_fail",
"degradation_conditions_w1_DegradationConditionsW1_gm_rbm_sea1_ta_wa_fail",
"degradation_conditions_w1_DegradationConditionsW1_group1_fail",
"degradation_conditions_w1_DegradationConditionsW1_group2_fail",
"degradation_conditions_w1_DegradationConditionsW1_group3_fail",
"degradation_conditions_w1_DegradationConditionsW1_group4_fail",
"degradation_conditions_w1_DegradationConditionsW1_group5_fail",
"degradation_conditions_w1_DegradationConditionsW1_hr_modes_and_gm_dbs_fail",
"degradation_conditions_w1_DegradationConditionsW1_no_rdr_symbology",
"degradation_conditions_w1_DegradationConditionsW1_not_identified_rdr_fail",
"degradation_conditions_w1_DegradationConditionsW1_selected_channel_fail",
"degradation_conditions_w1_DegradationConditionsW1_total_rdr_fail",
# ===== B8: SRU Failure Locations =====
"failure_location_pedestal_FailureLocationPedestal_sru1_gimbal",
"failure_location_pedestal_FailureLocationPedestal_sru2_waveguide",
"failure_location_pedestal_FailureLocationPedestal_sru3_waveguide",
"failure_location_pedestal_FailureLocationPedestal_sru4_delta_guard_lna_switch",
"failure_location_pedestal_FailureLocationPedestal_sru5_waveguide_switch",
"failure_location_processor_FailureLocationProcessor_sru10_main_computer",
"failure_location_processor_FailureLocationProcessor_sru11_graphic_computer",
"failure_location_processor_FailureLocationProcessor_sru12_power_supply",
"failure_location_processor_FailureLocationProcessor_sru13_det_exp",
"failure_location_processor_FailureLocationProcessor_sru14_rx_module",
"failure_location_processor_FailureLocationProcessor_sru1_motherboard_chassis",
"failure_location_processor_FailureLocationProcessor_sru2_mti_fft",
"failure_location_processor_FailureLocationProcessor_sru3_dsp0",
"failure_location_processor_FailureLocationProcessor_sru4_dsp1",
"failure_location_processor_FailureLocationProcessor_sru5_cfar_px_ctrl",
"failure_location_processor_FailureLocationProcessor_sru6_timer",
"failure_location_processor_FailureLocationProcessor_sru7_post_processor",
"failure_location_processor_FailureLocationProcessor_sru8_agc",
"failure_location_processor_FailureLocationProcessor_sru9_esa_if",
"failure_location_receiver_FailureLocationReceiver_sru1_chassis",
"failure_location_receiver_FailureLocationReceiver_sru2_uhf_assy",
"failure_location_receiver_FailureLocationReceiver_sru3_synthesizer",
"failure_location_receiver_FailureLocationReceiver_sru4_delta_guard_down_converter",
"failure_location_receiver_FailureLocationReceiver_sru5_sum_down_converter",
"failure_location_receiver_FailureLocationReceiver_sru6_lo_distributor",
"failure_location_receiver_FailureLocationReceiver_sru7_up_converter",
"failure_location_rx_frontend_FailureLocationRxFrontEnd_sru1_chassis",
"failure_location_rx_frontend_FailureLocationRxFrontEnd_sru2_delta_guard_lna",
"failure_location_rx_frontend_FailureLocationRxFrontEnd_sru3_sum_act_prot_lna",
"failure_location_rx_frontend_FailureLocationRxFrontEnd_sru4_4port_circulator",
"failure_location_rx_frontend_FailureLocationRxFrontEnd_sru5_stc_delta_guard",
"failure_location_rx_frontend_FailureLocationRxFrontEnd_sru5_stc_sum",
"failure_location_servoloop_FailureLocationServoloop_sru1_chassis",
"failure_location_servoloop_FailureLocationServoloop_sru2_power_supply",
"failure_location_servoloop_FailureLocationServoloop_sru3_digital_controller",
"failure_location_transmitter_FailureLocationTransmitter_sru1_chassis",
"failure_location_transmitter_FailureLocationTransmitter_sru2_rex_f_tx",
"failure_location_transmitter_FailureLocationTransmitter_sru3_power_supply",
"failure_location_transmitter_FailureLocationTransmitter_sru4_valve_el_twt_tx",
"failure_location_transmitter_FailureLocationTransmitter_sru5_rf_driver",
"failure_location_transmitter_FailureLocationTransmitter_sru6_controller_tx",
"failure_location_transmitter_FailureLocationTransmitter_sru7_hv_power_supply",
"failure_location_transmitter_FailureLocationTransmitter_sru8_eht_power_supply",
# ===== B8: All Test Results =====
"agc_test_results_AGCTestResults_test_agc10_pulse_compressor_interface",
"agc_test_results_AGCTestResults_test_agc11_dp_interface",
"agc_test_results_AGCTestResults_test_agc13_taxi_running",
"agc_test_results_AGCTestResults_test_agc14_external_xyp_ram",
"agc_test_results_AGCTestResults_test_agc15_servoloop_interface",
"agc_test_results_AGCTestResults_test_agc1_internal_xyp_ram",
"agc_test_results_AGCTestResults_test_agc2_external_xyp_ram",
"agc_test_results_AGCTestResults_test_agc5_dual_port_ram",
"agc_test_results_AGCTestResults_test_agc6_agc_machine",
"agc_test_results_AGCTestResults_test_agc7_sat_machine",
"agc_test_results_AGCTestResults_test_agc9_c_ram_xy_checksum",
"data_processor_test_results_DataProcessorTestResults_test_dp10_video_memory",
"data_processor_test_results_DataProcessorTestResults_test_dp11_video_unit",
"data_processor_test_results_DataProcessorTestResults_test_dp12_transputer_unit",
"data_processor_test_results_DataProcessorTestResults_test_dp13_scan_converter_polar_memory",
"data_processor_test_results_DataProcessorTestResults_test_dp14_scan_converter_format_converter",
"data_processor_test_results_DataProcessorTestResults_test_dp1_486_cpu_tests",
"data_processor_test_results_DataProcessorTestResults_test_dp2_486_interfaces_with_r3000_gc",
"data_processor_test_results_DataProcessorTestResults_test_dp3_486_interface_with_slc",
"data_processor_test_results_DataProcessorTestResults_test_dp4_slc_communications",
"data_processor_test_results_DataProcessorTestResults_test_dp5_r3000_cpu_tests",
"data_processor_test_results_DataProcessorTestResults_test_dp6_r3000_interfaces",
"data_processor_test_results_DataProcessorTestResults_test_dp7_1553_and_discretes",
"data_processor_test_results_DataProcessorTestResults_test_dp8_graphic_cpu",
"data_processor_test_results_DataProcessorTestResults_test_dp9_graphic_processors",
"integrated_system_test_results_IntegratedSystemTestResults_array_status",
"integrated_system_test_results_IntegratedSystemTestResults_cal_delta_channel_fail",
"integrated_system_test_results_IntegratedSystemTestResults_cal_injection_fail",
"integrated_system_test_results_IntegratedSystemTestResults_cal_noise_fail",
"integrated_system_test_results_IntegratedSystemTestResults_pedestal_status",
"integrated_system_test_results_IntegratedSystemTestResults_processor_status",
"integrated_system_test_results_IntegratedSystemTestResults_receiver_status",
"integrated_system_test_results_IntegratedSystemTestResults_rx_frontend_status",
"integrated_system_test_results_IntegratedSystemTestResults_servoloop_status",
"integrated_system_test_results_IntegratedSystemTestResults_test_is1_upconverter_chain_levels",
"integrated_system_test_results_IntegratedSystemTestResults_test_is2_downconverter_chain_levels",
"integrated_system_test_results_IntegratedSystemTestResults_test_is3_antenna_status_inconsistent",
"integrated_system_test_results_IntegratedSystemTestResults_test_is4_tx_status_inconsistent",
"integrated_system_test_results_IntegratedSystemTestResults_test_is5_tx_power_level",
"integrated_system_test_results_IntegratedSystemTestResults_transmitter_status",
"post_processor_test_results_PostProcessorTestResults_test_pp1_master_dsp",
"post_processor_test_results_PostProcessorTestResults_test_pp2_interface_card",
"post_processor_test_results_PostProcessorTestResults_test_pp3_cpu_cards",
"post_processor_test_results_PostProcessorTestResults_test_pp4_dma_bus",
"post_processor_test_results_PostProcessorTestResults_test_pp5_sp_interface",
"post_processor_test_results_PostProcessorTestResults_test_pp6_dp_interface",
"post_processor_test_results_PostProcessorTestResults_test_pp7_scan_converter_interface",
"post_processor_test_results_PostProcessorTestResults_test_pp8_agc_interface",
"power_supply_test_results_PowerSupplyTestResults_test_ps1_power_supply",
"power_supply_test_results_PowerSupplyTestResults_test_ps2_over_temperature",
"receiver_and_rx_frontend_test_results_ReceiverAndRxTestResults_test_fe1_lna",
"receiver_and_rx_frontend_test_results_ReceiverAndRxTestResults_test_fe2_agc_attenuators",
"receiver_and_rx_frontend_test_results_ReceiverAndRxTestResults_test_rx1_synthesizer_commands",
"receiver_and_rx_frontend_test_results_ReceiverAndRxTestResults_test_rx2_synthesizer_internal_tests",
"receiver_and_rx_frontend_test_results_ReceiverAndRxTestResults_test_rx3_uhf_oscillator_level",
"receiver_and_rx_frontend_test_results_ReceiverAndRxTestResults_test_rx4_downconverter_lo_level",
"receiver_and_rx_frontend_test_results_ReceiverAndRxTestResults_test_rx5_upconverter_lo_level",
"rx_module_test_results_RxModuleTestResults_test_rm16_calibration_sum_channel_fail",
"rx_module_test_results_RxModuleTestResults_test_rm1_master_clock_level",
"rx_module_test_results_RxModuleTestResults_test_rm2_expander_level",
"rx_module_test_results_RxModuleTestResults_test_rm3_sum_channel_down_converter",
"rx_module_test_results_RxModuleTestResults_test_rm4_dg_channel_down_converter",
"rx_module_test_results_RxModuleTestResults_test_rm5_noise_attenuators",
"servoloop_test_results_ServoloopTestResults_test_sl10_agc_control",
"servoloop_test_results_ServoloopTestResults_test_sl11_ad",
"servoloop_test_results_ServoloopTestResults_test_sl12_das",
"servoloop_test_results_ServoloopTestResults_test_sl13_serial_communications",
"servoloop_test_results_ServoloopTestResults_test_sl14_taxi_interface",
"servoloop_test_results_ServoloopTestResults_test_sl15_pedestal_centre_scan_location",
"servoloop_test_results_ServoloopTestResults_test_sl1_low_voltage_power_supply",
"servoloop_test_results_ServoloopTestResults_test_sl2_high_voltage_power_supply",
"servoloop_test_results_ServoloopTestResults_test_sl3_motor_drivers",
"servoloop_test_results_ServoloopTestResults_test_sl4_resolvers_power_supply",
"servoloop_test_results_ServoloopTestResults_test_sl5_waveguide_switch",
"servoloop_test_results_ServoloopTestResults_test_sl6_over_temperature",
"servoloop_test_results_ServoloopTestResults_test_sl7_resolver_to_digital_conv",
"servoloop_test_results_ServoloopTestResults_test_sl8_position_loop_error",
"servoloop_test_results_ServoloopTestResults_test_sl9_microprocessor",
"signal_processor_test_results_SignalProcessorTestResults_test_sp10_board_overall",
"signal_processor_test_results_SignalProcessorTestResults_test_sp11_attenuatori_antenna",
"signal_processor_test_results_SignalProcessorTestResults_test_sp14_external_sp_if",
"signal_processor_test_results_SignalProcessorTestResults_test_sp16_bcn",
"signal_processor_test_results_SignalProcessorTestResults_test_sp1_timer1_up",
"signal_processor_test_results_SignalProcessorTestResults_test_sp2_timer_dma_pxc_if",
"signal_processor_test_results_SignalProcessorTestResults_test_sp3_timer_internal",
"signal_processor_test_results_SignalProcessorTestResults_test_sp4_px_ctrl_comm",
"signal_processor_test_results_SignalProcessorTestResults_test_sp5_video1_without_ad",
"signal_processor_test_results_SignalProcessorTestResults_test_sp6_video1_with_ad",
"signal_processor_test_results_SignalProcessorTestResults_test_sp7_video2_ad_sync",
"signal_processor_test_results_SignalProcessorTestResults_test_sp8_video2_timer_sync",
"signal_processor_test_results_SignalProcessorTestResults_test_sp9_ad_da",
"signal_processor_test_results_SignalProcessorTestResults_test_sp9b_wideband_expander",
"transmitter_test_results_w1_TransmitterTestResultsW1_test_tx10_hv_ps_over_temperature_warning",
"transmitter_test_results_w1_TransmitterTestResultsW1_test_tx11_twt_helix_over_current",
"transmitter_test_results_w1_TransmitterTestResultsW1_test_tx12_cathode_to_helix_arc",
"transmitter_test_results_w1_TransmitterTestResultsW1_test_tx13_twt_over_temperature_hazard",
"transmitter_test_results_w1_TransmitterTestResultsW1_test_tx14_twt_over_temperature_warning",
"transmitter_test_results_w1_TransmitterTestResultsW1_test_tx15_cathode_under_voltage",
"transmitter_test_results_w1_TransmitterTestResultsW1_test_tx16_cathode_over_voltage",
"transmitter_test_results_w1_TransmitterTestResultsW1_test_tx1_microprocessors",
"transmitter_test_results_w1_TransmitterTestResultsW1_test_tx2_tx_rf_input",
"transmitter_test_results_w1_TransmitterTestResultsW1_test_tx3_twt_rf_input",
"transmitter_test_results_w1_TransmitterTestResultsW1_test_tx4_twt_rf_output",
"transmitter_test_results_w1_TransmitterTestResultsW1_test_tx5_tx_rf_output_level",
"transmitter_test_results_w1_TransmitterTestResultsW1_test_tx6_vswr",
"transmitter_test_results_w1_TransmitterTestResultsW1_test_tx7_three_phase_input_power",
"transmitter_test_results_w1_TransmitterTestResultsW1_test_tx8_low_voltage_power_supplies",
"transmitter_test_results_w1_TransmitterTestResultsW1_test_tx9_hv_ps_over_temperature_hazard",
"transmitter_test_results_w2_TransmitterTestResultsW2_test_tx17_collector_under_voltage",
"transmitter_test_results_w2_TransmitterTestResultsW2_test_tx18_collector_over_voltage",
"transmitter_test_results_w2_TransmitterTestResultsW2_test_tx19_rectified_voltage",
"transmitter_test_results_w2_TransmitterTestResultsW2_test_tx20_cathode_inv_current_fail",
"transmitter_test_results_w2_TransmitterTestResultsW2_test_tx21_collector_inv_current_fail",
"transmitter_test_results_w2_TransmitterTestResultsW2_test_tx22_waveguide_pressurization",
"transmitter_test_results_w2_TransmitterTestResultsW2_test_tx23_grid_window_over_duty_alt",
"transmitter_test_results_w2_TransmitterTestResultsW2_test_tx24_floating_deck_fail",
"transmitter_test_results_w2_TransmitterTestResultsW2_test_tx25_floating_deck_ps_fail",
"transmitter_test_results_w2_TransmitterTestResultsW2_test_tx26_grid_window_over_duty",
)
# ====================
# BIT FIELDS CATEGORIZATION
# ====================
# Dictionary mapping category names to field indices in bit_fields tuple.
# Used for organized drill-down reporting when B6 failures trigger B8 verification.
#
# Categories:
# B6_LRU_Status: 12 Line Replaceable Unit status fields (always checked)
# B8_Degradation: 12 system degradation condition flags
# B8_SRU_*: 43 Shop Replaceable Unit failure location flags (6 subsystems)
# B8_Test_*: 118 detailed test result fields (10 test types)
#
# Total: 185 diagnostic fields providing complete radar health visibility
bit_fields_categories = {
'B6_LRU_Status': bit_fields[0:12],
'B8_Degradation': bit_fields[12:24],
'B8_SRU_Pedestal': bit_fields[24:29],
'B8_SRU_Processor': bit_fields[29:43],
'B8_SRU_Receiver': bit_fields[43:50],
'B8_SRU_RxFrontend': bit_fields[50:56],
'B8_SRU_Servoloop': bit_fields[56:59],
'B8_SRU_Transmitter': bit_fields[59:67],
'B8_Test_AGC': bit_fields[67:78],
'B8_Test_DataProcessor': bit_fields[78:92],
'B8_Test_IntegratedSystem': bit_fields[92:107],
'B8_Test_PostProcessor': bit_fields[107:115],
'B8_Test_PowerSupply': bit_fields[115:117],
'B8_Test_Receiver': bit_fields[117:124],
'B8_Test_RxModule': bit_fields[124:130],
'B8_Test_Servoloop': bit_fields[130:145],
'B8_Test_SignalProcessor': bit_fields[145:159],
'B8_Test_Transmitter': bit_fields[159:185],
}
logger_setup('GRIFO_M_PBIT.log')
report = testReport(sys.argv[0])
interface = theGrifo1553.getInterface()
terminal = leo_grifo_terminal.GrifoSerialTerminal()
terminal.connect()
test_return = True
try:
#report.open_session('Pre Conditions')
#power_grifo_off()
#report.close_session()
############ Test Execution ############
#report.open_session('Test Execution')
report.add_comment("The Test Operator check if the failure BIT in B6_MsgRdrSettingsAndParametersTellback changes ...")
if tgt_gen_alone(interface) is False: return
for repetition in range(NUMBER_OF_REPETITIONS):
info = f'Repetition {1 + repetition} of {NUMBER_OF_REPETITIONS}'
logging.info(info)
report.open_session(info)
# Statistics for this run
run_stats = {
'repetition': repetition + 1,
'pbit_time': 0,
'bit_available': False,
'b6_total': 0,
'b6_pass': 0,
'b6_fail': 0,
'b6_known_fail': 0,
'b8_checked': 0,
'b8_pass': 0,
'b8_fail': 0,
'failures': [],
'known_failures': [],
'success': True,
# Serial statistics
'serial_total': 0,
'serial_errors': 0,
'serial_fatal': 0,
'serial_recycles': 0,
'serial_details': [], # List of notable serial events
}
test_statistics['total_runs'] += 1
# Reset serial statistics for this run
terminal.reset_serial_statistics()
report.add_comment("The test operator is required to switch off the target and wait 3 seconds.")
power_grifo_off(3)
report.add_comment("The test operator is required to switch on the target.")
power_grifo_on()
remaining_time = PBIT_SEC_TIME
pbit_start_time = time.perf_counter()
max_counter_1553_msg = 20
while remaining_time > 0:
start = time.perf_counter()
ret_rep_is_avail = False
msg_cnt = 0
mil1553_error_flag = max_counter_1553_msg
for i in range(100):
cnt = interface.getSingleMessageReceivedSz("B6_MsgRdrSettingsAndParametersTellback")
value = interface.getMessageFieldValue("B6_MsgRdrSettingsAndParametersTellback",
"radar_health_status_and_bit_report_valid_RdrHealthStatusAndBitReport_bit_report_available")
ret_rep_is_avail = value == "true"
if ret_rep_is_avail is True:
break
time.sleep(0.05)
#logging.critical(f"1553 messag count {cnt} {mil1553_error_flag}")
if cnt > msg_cnt:
mil1553_error_flag = max_counter_1553_msg
else :
mil1553_error_flag -=1
msg_cnt = cnt
if mil1553_error_flag == 0:
logging.critical("1553 communication lost")
return False
if ret_rep_is_avail is True:
time.sleep(0.02)
run_stats['bit_available'] = True
run_stats['pbit_time'] = time.perf_counter() - pbit_start_time
report.add_comment(f"BIT report available after {run_stats['pbit_time']:.1f}s")
# ===== PHASE 1: Verify ALL B6 LRU Status Fields =====
b6_lru_fields = bit_fields_categories['B6_LRU_Status']
b6_failures = []
b6_known_failures = []
for f in b6_lru_fields:
run_stats['b6_total'] += 1
ret, err = check(theGrifo1553, "false", "B6_MsgRdrSettingsAndParametersTellback", f)
if ret:
run_stats['b6_pass'] += 1
else:
if f in KNOWN_FAILURES:
# Known failure: annotate but don't trigger drill-down
run_stats['b6_known_fail'] += 1
b6_known_failures.append((f, err))
logging.warning(f"Known failure (ignored): {f}")
else:
# Real failure: needs investigation
run_stats['b6_fail'] += 1
b6_failures.append((f, err))
test_return = False
run_stats['success'] = False
# Log B6 summary
b6_summary = (
f"\n{'='*70}\n"
f"B6 LRU Status Summary:\n"
f" Total: {run_stats['b6_total']}\n"
f" Pass: {run_stats['b6_pass']}\n"
f" Fail: {run_stats['b6_fail']}\n"
f" Known Fail: {run_stats['b6_known_fail']} (ignored for drill-down)\n"
f"{'='*70}"
)
logging.info(b6_summary)
report.add_comment(b6_summary)
if b6_known_failures:
known_fail_list = "\n".join([f" - {f.split('_')[-1]}: {v}" for f, v in b6_known_failures])
report.add_comment(f"Known Failures (HW setup):\n{known_fail_list}")
run_stats['known_failures'].extend(b6_known_failures)
if b6_failures:
fail_list = "\n".join([f" - {f.split('_')[-1]}: {v}" for f, v in b6_failures])
report.add_comment(f"Real Failures detected:\n{fail_list}")
run_stats['failures'].extend(b6_failures)
# ===== PHASE 2: Drill-down B8 only if REAL failures in B6 =====
if b6_failures:
report.add_comment(f"\nDrill-down: Verifying all {len(bit_fields) - 12} B8 diagnostic fields...")
b8_fields = bit_fields[12:] # All B8 fields
b8_failures = []
for category, fields in list(bit_fields_categories.items())[1:]: # Skip B6
category_fail = 0
category_pass = 0
for f in fields:
run_stats['b8_checked'] += 1
ret, err = check(theGrifo1553, "false", "B8_MsgBitReport", f)
if ret:
category_pass += 1
run_stats['b8_pass'] += 1
else:
category_fail += 1
run_stats['b8_fail'] += 1
b8_failures.append((category, f, err))
test_return = False
if category_fail > 0:
logging.warning(f"{category}: {category_fail}/{len(fields)} failures")
# B8 summary
b8_summary = (
f"\n{'='*70}\n"
f"B8 Diagnostic Fields Summary:\n"
f" Checked: {run_stats['b8_checked']}\n"
f" Pass: {run_stats['b8_pass']}\n"
f" Fail: {run_stats['b8_fail']}\n"
f"{'='*70}"
)
logging.info(b8_summary)
report.add_comment(b8_summary)
if b8_failures:
# Group by category for clarity
fail_by_cat = {}
for cat, field, err in b8_failures:
if cat not in fail_by_cat:
fail_by_cat[cat] = []
fail_by_cat[cat].append((field.split('_')[-1], err))
fail_detail = "\nB8 Failures by Category:\n"
for cat, fails in fail_by_cat.items():
fail_detail += f"\n {cat} ({len(fails)} failures):\n"
for fname, val in fails[:5]: # Max 5 per category
fail_detail += f" - {fname}: {val}\n"
if len(fails) > 5:
fail_detail += f" ... and {len(fails)-5} more\n"
report.add_comment(fail_detail)
run_stats['failures'].extend([(f, v) for _, f, v in b8_failures])
else:
report.add_comment("\n✓ All B6 LRU Status PASS (no B8 drill-down needed)")
# Run statistics
test_statistics['repetitions'].append(run_stats)
if run_stats['success']:
test_statistics['successful_runs'] += 1
else:
test_statistics['failed_runs'] += 1
time_passed = time.perf_counter() - start
remaining_time -= time_passed
if ret_rep_is_avail is True:
remaining_time = 0
logging.info(f'{remaining_time:.1f}s remaining ...')
# Collect serial statistics for this run before closing session
serial_stats = terminal.get_serial_statistics()
run_stats['serial_total'] = serial_stats['total_messages']
run_stats['serial_errors'] = serial_stats['error_messages']
run_stats['serial_fatal'] = serial_stats['fatal_messages']
run_stats['serial_recycles'] = serial_stats['recycle_count']
# Add serial details to run report
report.add_comment("\n--- Serial Communication Summary ---")
report.add_comment(f"Total serial messages: {serial_stats['total_messages']}")
report.add_comment(f"Error messages (%%E): {serial_stats['error_messages']}")
report.add_comment(f"Fatal messages (%%F): {serial_stats['fatal_messages']}")
report.add_comment(f"System recycles: {serial_stats['recycle_count']}")
# Show recycle details if any
if serial_stats['recycle_count'] > 0:
report.add_comment("\nRecycle Events Detected:")
for timestamp, message in serial_stats['recycle_details']:
report.add_comment(f" [{timestamp}] {message}")
run_stats['serial_details'].append({'type': 'RECYCLE', 'timestamp': timestamp, 'message': message})
# Show error details if any (limit to first 5 to avoid clutter)
if serial_stats['error_messages'] > 0:
report.add_comment(f"\nError Messages (%%E) - showing first 5 of {serial_stats['error_messages']}:")
for timestamp, message in serial_stats['error_details'][:5]:
report.add_comment(f" [{timestamp}] {message}")
run_stats['serial_details'].append({'type': 'ERROR', 'timestamp': timestamp, 'message': message})
# Show fatal details if any (limit to first 5)
if serial_stats['fatal_messages'] > 0:
report.add_comment(f"\nFatal Messages (%%F) - showing first 5 of {serial_stats['fatal_messages']}:")
for timestamp, message in serial_stats['fatal_details'][:5]:
report.add_comment(f" [{timestamp}] {message}")
run_stats['serial_details'].append({'type': 'FATAL', 'timestamp': timestamp, 'message': message})
report.close_session()
if interruptRequest is True:
report.add_comment("Test interrupted by user (Ctrl-C)")
break
tgt_gen(interface)
report.add_comment("Repetitions terminated.")
# ===== FINAL STATISTICS REPORT =====
generate_final_statistics_report(report, test_statistics)
############ END STEPS ############
#report.open_session('Post Conditions')
power_grifo_off()
#report.close_session()
if terminal is not None:
terminal.disconnect()
return test_return
except Exception as e:
report.add_comment(f"Test terminated unexpectedly :{e}")
return False
finally:
report.generate_pdf()
#-- ---------------------------------------------------------------
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal_handler)
test_proc()