982 lines
62 KiB
Python
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() |