Files
traceability/src/pages/Index.tsx
2026-01-25 14:22:22 +01:00

1072 lines
47 KiB
TypeScript

import { useState } from "react";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion";
import { AlertTriangle, CheckCircle, XCircle, AlertCircle, Cpu, Wifi, HardDrive, Zap, Clock, Shield, Settings, Database, Radio, Activity, FileWarning, CircleHelp } from "lucide-react";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Separator } from "@/components/ui/separator";
// ESP32-S3 Specifications
const esp32Specs = {
cpu: { cores: 2, frequency: "240 MHz", architecture: "Xtensa LX7" },
memory: { sram: "512 KB", rtcSram: "16 KB", rom: "384 KB" },
flash: "External (8MB configured)",
gpio: 45,
interfaces: { spi: 4, i2c: 2, uart: 3, i2s: 2, adc: "20 channels (12-bit)" },
wireless: { wifi: "802.11 b/g/n (2.4GHz)", bluetooth: "BLE 5.0" },
security: ["AES-128/256", "SHA", "RSA", "HMAC", "Secure Boot", "Flash Encryption"],
power: ["Active", "Modem-sleep", "Light-sleep", "Deep-sleep", "Hibernation"]
};
// Budget Comparison
const budgetAnalysis = {
ram: { allocated: 225, available: 512, budget: "60%", actual: "43.9%", status: "ok" },
flash: { allocated: 5.052, available: 8, budget: "70%", actual: "63.2%", status: "ok" },
cpu: { allocated: 42, budget: "80% peak", status: "ok" }
};
// Gap Analysis Data
const gapAnalysis = [
{
category: "Communication (FG-COM)",
severity: "critical",
gaps: [
{
id: "GAP-COM-001",
title: "WiFi Protocol Details Missing",
description: "Documents mention 'WiFi / Zigbee / LoRa' but lack specific protocol selection and rationale.",
questions: [
"Which WiFi standard specifically? (802.11b/g/n all supported by ESP32-S3)",
"What is the target data rate requirement?",
"Is 2.4GHz band acceptable (5GHz not supported)?",
"What is the expected range/coverage?"
],
recommendation: "Define primary protocol as WiFi 802.11n for best throughput. Add Zigbee/LoRa as optional fallback.",
esp32Impact: "ESP32-S3 supports 802.11 b/g/n at 2.4GHz up to 150 Mbps. No 5GHz support."
},
{
id: "GAP-COM-002",
title: "TLS/DTLS Version Unspecified",
description: "Security requires TLS/DTLS but version and cipher suites are not defined.",
questions: [
"TLS 1.2 or TLS 1.3?",
"Which cipher suites are acceptable?",
"Certificate management approach?",
"Key rotation policy?"
],
recommendation: "Use TLS 1.2 with AES-128-GCM for ESP32-S3 hardware acceleration compatibility.",
esp32Impact: "ESP32-S3 has hardware crypto accelerators for AES-128/256, SHA, RSA."
},
{
id: "GAP-COM-003",
title: "Peer-to-Peer Protocol Undefined",
description: "F-COM-03 mentions peer Sensor Hub communication but no protocol specified.",
questions: [
"What transport for peer-to-peer? (WiFi Direct, BLE, ESP-NOW?)",
"What is the maximum peer count?",
"Discovery mechanism?"
],
recommendation: "Consider ESP-NOW for low-latency peer communication (250 byte payload, no WiFi connection needed).",
esp32Impact: "ESP-NOW supported natively. BLE Mesh also available."
},
{
id: "GAP-COM-004",
title: "Heartbeat/Keep-Alive Details Missing",
description: "30-second timeout mentioned but no heartbeat interval or mechanism defined.",
questions: [
"What is the heartbeat interval?",
"Payload content of heartbeat?",
"Exponential backoff parameters for reconnection?"
],
recommendation: "Define 10-second heartbeat interval with 3 missed = disconnected.",
esp32Impact: "No specific hardware limitation."
}
]
},
{
category: "Data Acquisition (FG-DAQ)",
severity: "high",
gaps: [
{
id: "GAP-DAQ-001",
title: "Specific Sensor Models Not Defined",
description: "Sensor types listed (Temp, Humidity, CO2, etc.) but no specific models or part numbers.",
questions: [
"What are the specific sensor models/part numbers?",
"What are the I2C addresses for each sensor type?",
"Are there alternative/fallback sensor models?"
],
recommendation: "Create a Sensor Catalog with approved models, I2C addresses, and driver requirements.",
esp32Impact: "ESP32-S3 has 2x I2C buses - ensure no address conflicts if using multiple sensors."
},
{
id: "GAP-DAQ-002",
title: "ADC Channel Allocation Undefined",
description: "Analog sensors mentioned but no ADC channel assignment or calibration approach.",
questions: [
"How many analog sensors are expected?",
"Which ADC channels will be used?",
"What reference voltage?",
"ADC calibration approach?"
],
recommendation: "Define ADC channel map. Use eFuse-stored calibration for ESP32-S3 ADC linearity correction.",
esp32Impact: "ESP32-S3 has 20 ADC channels, 12-bit resolution. Some GPIOs are ADC1 (usable with WiFi), some ADC2 (conflicts with WiFi)."
},
{
id: "GAP-DAQ-003",
title: "Sensor Warm-Up Times Not Specified",
description: "Many gas sensors (CO2, NH3) require warm-up periods not addressed.",
questions: [
"What are warm-up time requirements per sensor type?",
"How should readings during warm-up be handled?",
"Power-on sequencing requirements?"
],
recommendation: "Add sensor warm-up state handling. Typical: CO2 sensors 30-60 seconds, MOS sensors 24-48 hours for first use.",
esp32Impact: "No specific hardware impact, software timing only."
},
{
id: "GAP-DAQ-004",
title: "Filtering Algorithm Not Specified",
description: "High-frequency sampling mentions filtering but algorithm type not defined.",
questions: [
"Moving average, median filter, Kalman, or other?",
"Filter window size configurable?",
"Outlier rejection criteria?"
],
recommendation: "Recommend median filter (robust to outliers) with configurable window size in Machine Constants.",
esp32Impact: "CPU budget allows for moderate filtering complexity."
}
]
},
{
category: "Security (FG-SEC)",
severity: "critical",
gaps: [
{
id: "GAP-SEC-001",
title: "Key Management Lifecycle Undefined",
description: "Secure boot and encryption mentioned but key provisioning and rotation not specified.",
questions: [
"How are keys provisioned during manufacturing?",
"Key rotation policy for TLS certificates?",
"Key storage location (eFuse vs NVS encrypted)?",
"Revocation mechanism?"
],
recommendation: "Define key provisioning during manufacturing, use eFuse for secure boot keys, NVS encrypted partition for runtime keys.",
esp32Impact: "ESP32-S3 has eFuse for permanent key storage and hardware secure boot support."
},
{
id: "GAP-SEC-002",
title: "Authentication Method Not Specified",
description: "Authentication required but mechanism not defined (certificates, PSK, tokens?).",
questions: [
"Mutual TLS with certificates?",
"Pre-shared keys?",
"Device identity provisioning?"
],
recommendation: "Use X.509 certificates with device-unique identity for mutual TLS.",
esp32Impact: "ESP32-S3 supports X.509, may need external crypto chip for many certificates."
},
{
id: "GAP-SEC-003",
title: "Anti-Rollback Policy Vague",
description: "Rollback prevention mentioned as 'optional future' but critical for security.",
questions: [
"Is anti-rollback mandatory?",
"What version tracking mechanism?",
"Emergency recovery procedure?"
],
recommendation: "Implement anti-rollback using ESP32-S3 eFuse version counter.",
esp32Impact: "ESP32-S3 supports secure version tracking in eFuse (limited burn count)."
}
]
},
{
category: "OTA Updates (FG-OTA)",
severity: "high",
gaps: [
{
id: "GAP-OTA-001",
title: "Partition Scheme Not Defined",
description: "Dual-partition OTA implied but specific partition layout not documented.",
questions: [
"What is the partition table layout?",
"Factory partition included?",
"Partition sizes for app0/app1?",
"NVS partition size?"
],
recommendation: "Define: factory (4MB) + ota_0 (4MB) or app0 + app1 if 8MB flash. Reserve 64KB for NVS.",
esp32Impact: "8MB flash allows dual 3.5MB app partitions with ample NVS/data space."
},
{
id: "GAP-OTA-002",
title: "OTA Chunk Size Not Specified",
description: "Firmware transferred 'in chunks' but chunk size and protocol not defined.",
questions: [
"What chunk size? (4KB, 16KB, other?)",
"Acknowledgment per chunk or batch?",
"Resume capability after interruption?"
],
recommendation: "Use 4KB chunks with per-chunk CRC and resume from last successful chunk.",
esp32Impact: "4KB aligns with flash page size for efficient writes."
},
{
id: "GAP-OTA-003",
title: "Rollback Trigger Conditions Undefined",
description: "Rollback mentioned but trigger conditions not specified.",
questions: [
"What triggers automatic rollback?",
"Timeout for marking update successful?",
"Health check criteria?"
],
recommendation: "Implement watchdog-triggered rollback if app doesn't confirm within 60 seconds of boot.",
esp32Impact: "ESP32-S3 has app rollback support in bootloader."
}
]
},
{
category: "Persistence (FG-DATA)",
severity: "high",
gaps: [
{
id: "GAP-DATA-001",
title: "SD Card File System Not Specified",
description: "SD card storage mentioned but filesystem type not defined.",
questions: [
"FAT32, exFAT, or custom filesystem?",
"Maximum file size?",
"Directory structure?",
"Wear leveling approach?"
],
recommendation: "Use FAT32 for compatibility. Implement circular buffer with fixed-size files for wear distribution.",
esp32Impact: "ESP-IDF supports FAT32 on SD. SPI mode vs SDMMC mode?"
},
{
id: "GAP-DATA-002",
title: "Data Retention Policy Incomplete",
description: "Configurable retention mentioned but no default values or limits.",
questions: [
"Default retention period?",
"Maximum storage allocation per data type?",
"Overwrite priority (FIFO, priority-based)?"
],
recommendation: "Default 7-day retention, FIFO overwrite, 80% SD capacity for sensor data.",
esp32Impact: "No specific hardware constraint."
},
{
id: "GAP-DATA-003",
title: "NVS Partition Size and Usage Undefined",
description: "NVS mentioned for machine constants but sizing not specified.",
questions: [
"Expected size of machine constants?",
"How many NVS entries expected?",
"NVS encryption enabled?"
],
recommendation: "Allocate 64KB NVS minimum. Enable NVS encryption for sensitive data.",
esp32Impact: "ESP32-S3 supports NVS encryption with flash encryption enabled."
}
]
},
{
category: "Diagnostics (FG-DIAG)",
severity: "medium",
gaps: [
{
id: "GAP-DIAG-001",
title: "Diagnostic Code Registry Not Provided",
description: "Structured diagnostic codes required but no code table provided.",
questions: [
"What is the diagnostic code format?",
"What are all defined diagnostic codes?",
"Code ranges per subsystem?"
],
recommendation: "Create diagnostic code registry: 0x1xxx=DAQ, 0x2xxx=COM, 0x3xxx=SEC, etc.",
esp32Impact: "No specific hardware constraint."
},
{
id: "GAP-DIAG-002",
title: "Log Storage Capacity Undefined",
description: "Persistent diagnostics mentioned but storage limits not specified.",
questions: [
"Maximum log entries?",
"Log rotation policy?",
"Crash dump storage?"
],
recommendation: "1000 diagnostic entries max, FIFO rotation, separate crash dump partition.",
esp32Impact: "Consider coredump partition in flash (~64KB)."
}
]
},
{
category: "System Management (FG-SYS)",
severity: "medium",
gaps: [
{
id: "GAP-SYS-001",
title: "Watchdog Timer Configuration Not Specified",
description: "System reliability requires WDT but parameters not defined.",
questions: [
"Task WDT timeout value?",
"Which tasks are monitored?",
"Interrupt WDT configuration?"
],
recommendation: "10-second task WDT, monitor all FreeRTOS tasks, enable interrupt WDT.",
esp32Impact: "ESP32-S3 has multiple WDT: Task WDT, Interrupt WDT, RTC WDT."
},
{
id: "GAP-SYS-002",
title: "Power Management Strategy Undefined",
description: "Continuous AC power assumed but brownout/UPS handling not addressed.",
questions: [
"Brownout detection threshold?",
"UPS/battery backup expected?",
"Graceful shutdown on power loss?"
],
recommendation: "Enable brownout detector at 3.0V, implement emergency data flush on brownout interrupt.",
esp32Impact: "ESP32-S3 has programmable brownout detector."
},
{
id: "GAP-SYS-003",
title: "Time Synchronization Details Missing",
description: "Synchronized time mentioned but sync mechanism not specified.",
questions: [
"NTP, GPS, or Main Hub time sync?",
"Sync interval?",
"Drift tolerance?",
"RTC backup?"
],
recommendation: "Sync from Main Hub on connect, resync every 1 hour, ±1 second tolerance.",
esp32Impact: "ESP32-S3 has RTC. External RTC battery may be needed for power loss."
}
]
},
{
category: "Hardware Interface (HW)",
severity: "high",
gaps: [
{
id: "GAP-HW-001",
title: "GPIO Pin Assignment Not Documented",
description: "Multiple interfaces but no pin mapping provided.",
questions: [
"Complete GPIO pin assignment table?",
"Reserved/strapping pins identified?",
"I2C pull-up resistor values?"
],
recommendation: "Create comprehensive GPIO map. Avoid strapping pins (GPIO0, GPIO45, GPIO46).",
esp32Impact: "ESP32-S3 has 45 GPIOs but some have restrictions (strapping, flash, PSRAM)."
},
{
id: "GAP-HW-002",
title: "OLED Display Specifications Missing",
description: "OLED via I2C mentioned but no specifications.",
questions: [
"Display resolution?",
"Controller chip (SSD1306, SH1106)?",
"I2C address?",
"Refresh rate requirements?"
],
recommendation: "Recommend SSD1306 128x64 OLED at 0x3C, widely supported.",
esp32Impact: "I2C bus speed consideration - 400kHz recommended for smooth updates."
},
{
id: "GAP-HW-003",
title: "SD Card Interface Mode Unspecified",
description: "SD card mentioned but interface mode not defined.",
questions: [
"SPI mode or SDMMC (1-bit/4-bit)?",
"Maximum SD card size supported?",
"Speed class requirements?"
],
recommendation: "Use SDMMC 4-bit mode for best performance if GPIOs available, else SPI.",
esp32Impact: "ESP32-S3 supports both. SDMMC uses dedicated pins, SPI is more flexible."
}
]
},
{
category: "Quality & Calibration (FG-DQC)",
severity: "medium",
gaps: [
{
id: "GAP-DQC-001",
title: "Calibration Data Format Undefined",
description: "Calibration management mentioned but data structure not specified.",
questions: [
"What calibration parameters per sensor type?",
"Polynomial coefficients, offset/gain, or lookup tables?",
"Calibration data versioning?"
],
recommendation: "Define per-sensor calibration structure with version, timestamp, and polynomial coefficients.",
esp32Impact: "No specific hardware constraint."
},
{
id: "GAP-DQC-002",
title: "Sensor Validity Thresholds Not Defined",
description: "Out-of-range detection mentioned but thresholds not specified.",
questions: [
"Valid range per sensor type?",
"Rate-of-change limits?",
"Stuck sensor detection criteria?"
],
recommendation: "Define per-sensor-type: min/max physical range, max rate of change, stuck duration.",
esp32Impact: "No specific hardware constraint."
}
]
}
];
// Requirements Coverage Summary
const coverageSummary = {
totalFeatures: 24,
totalSRs: 85,
totalSWRs: 200,
coverage: {
fullySpecified: 156,
partiallySpecified: 32,
gaps: 12
}
};
const SeverityBadge = ({ severity }: { severity: string }) => {
const config = {
critical: { color: "bg-red-500/15 text-red-700 border-red-500/30", icon: XCircle },
high: { color: "bg-orange-500/15 text-orange-700 border-orange-500/30", icon: AlertTriangle },
medium: { color: "bg-yellow-500/15 text-yellow-700 border-yellow-500/30", icon: AlertCircle },
low: { color: "bg-blue-500/15 text-blue-700 border-blue-500/30", icon: CircleHelp }
};
const cfg = config[severity as keyof typeof config] || config.medium;
const Icon = cfg.icon;
return (
<Badge variant="outline" className={`${cfg.color} gap-1`}>
<Icon className="h-3 w-3" />
{severity.toUpperCase()}
</Badge>
);
};
const Index = () => {
const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
const criticalGaps = gapAnalysis.filter(g => g.severity === "critical");
const highGaps = gapAnalysis.filter(g => g.severity === "high");
const totalGapCount = gapAnalysis.reduce((acc, g) => acc + g.gaps.length, 0);
return (
<div className="min-h-screen bg-background">
{/* Header */}
<header className="border-b bg-card/50 backdrop-blur-sm sticky top-0 z-50">
<div className="container mx-auto px-4 py-4">
<div className="flex items-center justify-between">
<div>
<h1 className="text-2xl font-bold tracking-tight">ASF Sensor Hub - Requirements Gap Analysis</h1>
<p className="text-sm text-muted-foreground">DIPFECS ESP32-S3 Sub-Hub | ISO/IEC/IEEE 29148 Compliance Review</p>
</div>
<div className="flex items-center gap-3">
<Badge variant="outline" className="bg-primary/10 text-primary border-primary/30 gap-1">
<Cpu className="h-3 w-3" />
ESP32-S3
</Badge>
<Badge variant="secondary">{totalGapCount} Gaps Identified</Badge>
</div>
</div>
</div>
</header>
<main className="container mx-auto px-4 py-6">
{/* Summary Cards */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
<Card className="border-red-500/30 bg-red-500/5">
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium flex items-center gap-2">
<XCircle className="h-4 w-4 text-red-500" />
Critical Gaps
</CardTitle>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold text-red-600">
{criticalGaps.reduce((acc, g) => acc + g.gaps.length, 0)}
</div>
<p className="text-xs text-muted-foreground">in {criticalGaps.length} categories</p>
</CardContent>
</Card>
<Card className="border-orange-500/30 bg-orange-500/5">
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium flex items-center gap-2">
<AlertTriangle className="h-4 w-4 text-orange-500" />
High Priority Gaps
</CardTitle>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold text-orange-600">
{highGaps.reduce((acc, g) => acc + g.gaps.length, 0)}
</div>
<p className="text-xs text-muted-foreground">in {highGaps.length} categories</p>
</CardContent>
</Card>
<Card className="border-green-500/30 bg-green-500/5">
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
Requirements Coverage
</CardTitle>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold text-green-600">
{Math.round((coverageSummary.coverage.fullySpecified / coverageSummary.totalSWRs) * 100)}%
</div>
<p className="text-xs text-muted-foreground">{coverageSummary.coverage.fullySpecified}/{coverageSummary.totalSWRs} SWRs complete</p>
</CardContent>
</Card>
<Card className="border-blue-500/30 bg-blue-500/5">
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium flex items-center gap-2">
<Cpu className="h-4 w-4 text-blue-500" />
ESP32-S3 Compatibility
</CardTitle>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold text-blue-600">Compatible</div>
<p className="text-xs text-muted-foreground">All budgets within limits</p>
</CardContent>
</Card>
</div>
<Tabs defaultValue="gaps" className="space-y-4">
<TabsList className="grid w-full grid-cols-4 lg:w-auto lg:inline-grid">
<TabsTrigger value="gaps" className="gap-2">
<FileWarning className="h-4 w-4" />
Gap Analysis
</TabsTrigger>
<TabsTrigger value="esp32" className="gap-2">
<Cpu className="h-4 w-4" />
ESP32-S3 Specs
</TabsTrigger>
<TabsTrigger value="budgets" className="gap-2">
<Activity className="h-4 w-4" />
Resource Budgets
</TabsTrigger>
<TabsTrigger value="recommendations" className="gap-2">
<Settings className="h-4 w-4" />
Recommendations
</TabsTrigger>
</TabsList>
{/* Gap Analysis Tab */}
<TabsContent value="gaps" className="space-y-4">
<Card>
<CardHeader>
<CardTitle>Requirements Gap Analysis by Feature Group</CardTitle>
<CardDescription>
Identified gaps requiring clarification or additional requirements
</CardDescription>
</CardHeader>
<CardContent>
<ScrollArea className="h-[600px] pr-4">
<Accordion type="single" collapsible className="w-full">
{gapAnalysis.map((category, idx) => (
<AccordionItem key={idx} value={`item-${idx}`}>
<AccordionTrigger className="hover:no-underline">
<div className="flex items-center gap-3 w-full pr-4">
<SeverityBadge severity={category.severity} />
<span className="font-semibold">{category.category}</span>
<Badge variant="secondary" className="ml-auto">
{category.gaps.length} gaps
</Badge>
</div>
</AccordionTrigger>
<AccordionContent>
<div className="space-y-4 pt-2">
{category.gaps.map((gap, gapIdx) => (
<Card key={gapIdx} className="border-l-4 border-l-primary">
<CardHeader className="pb-2">
<div className="flex items-start justify-between">
<div>
<CardTitle className="text-base">{gap.id}: {gap.title}</CardTitle>
<CardDescription className="mt-1">{gap.description}</CardDescription>
</div>
</div>
</CardHeader>
<CardContent className="space-y-3">
<div>
<h4 className="text-sm font-semibold mb-2 text-muted-foreground">Questions to Resolve:</h4>
<ul className="list-disc list-inside space-y-1 text-sm">
{gap.questions.map((q, qIdx) => (
<li key={qIdx}>{q}</li>
))}
</ul>
</div>
<Separator />
<div>
<h4 className="text-sm font-semibold mb-1 text-green-700">Recommendation:</h4>
<p className="text-sm">{gap.recommendation}</p>
</div>
<div className="bg-blue-500/10 rounded-md p-2">
<h4 className="text-sm font-semibold mb-1 text-blue-700 flex items-center gap-1">
<Cpu className="h-3 w-3" />
ESP32-S3 Impact:
</h4>
<p className="text-sm text-blue-900">{gap.esp32Impact}</p>
</div>
</CardContent>
</Card>
))}
</div>
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</ScrollArea>
</CardContent>
</Card>
</TabsContent>
{/* ESP32-S3 Specs Tab */}
<TabsContent value="esp32" className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Cpu className="h-5 w-5" />
CPU
</CardTitle>
</CardHeader>
<CardContent className="space-y-2">
<div className="flex justify-between">
<span className="text-muted-foreground">Architecture</span>
<span className="font-medium">{esp32Specs.cpu.architecture}</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">Cores</span>
<span className="font-medium">{esp32Specs.cpu.cores}</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">Frequency</span>
<span className="font-medium">{esp32Specs.cpu.frequency}</span>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<HardDrive className="h-5 w-5" />
Memory
</CardTitle>
</CardHeader>
<CardContent className="space-y-2">
<div className="flex justify-between">
<span className="text-muted-foreground">SRAM</span>
<span className="font-medium">{esp32Specs.memory.sram}</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">RTC SRAM</span>
<span className="font-medium">{esp32Specs.memory.rtcSram}</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">ROM</span>
<span className="font-medium">{esp32Specs.memory.rom}</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">External Flash</span>
<span className="font-medium">{esp32Specs.flash}</span>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Wifi className="h-5 w-5" />
Wireless
</CardTitle>
</CardHeader>
<CardContent className="space-y-2">
<div className="flex justify-between">
<span className="text-muted-foreground">WiFi</span>
<span className="font-medium text-right text-xs">{esp32Specs.wireless.wifi}</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">Bluetooth</span>
<span className="font-medium">{esp32Specs.wireless.bluetooth}</span>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Radio className="h-5 w-5" />
Interfaces
</CardTitle>
</CardHeader>
<CardContent className="space-y-2">
<div className="flex justify-between">
<span className="text-muted-foreground">GPIO</span>
<span className="font-medium">{esp32Specs.gpio} pins</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">SPI</span>
<span className="font-medium">{esp32Specs.interfaces.spi} buses</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">I2C</span>
<span className="font-medium">{esp32Specs.interfaces.i2c} buses</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">UART</span>
<span className="font-medium">{esp32Specs.interfaces.uart}</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">ADC</span>
<span className="font-medium">{esp32Specs.interfaces.adc}</span>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Shield className="h-5 w-5" />
Security Features
</CardTitle>
</CardHeader>
<CardContent>
<div className="flex flex-wrap gap-2">
{esp32Specs.security.map((feature, idx) => (
<Badge key={idx} variant="secondary">{feature}</Badge>
))}
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Zap className="h-5 w-5" />
Power Modes
</CardTitle>
</CardHeader>
<CardContent>
<div className="flex flex-wrap gap-2">
{esp32Specs.power.map((mode, idx) => (
<Badge key={idx} variant="outline">{mode}</Badge>
))}
</div>
</CardContent>
</Card>
</div>
<Card className="border-yellow-500/30 bg-yellow-500/5">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-yellow-700">
<AlertTriangle className="h-5 w-5" />
ESP32-S3 Limitations to Consider
</CardTitle>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm">
<li className="flex items-start gap-2">
<span className="text-yellow-600"></span>
<span><strong>No 5GHz WiFi:</strong> Only 2.4GHz band supported</span>
</li>
<li className="flex items-start gap-2">
<span className="text-yellow-600"></span>
<span><strong>ADC2 + WiFi conflict:</strong> ADC2 channels cannot be used while WiFi is active</span>
</li>
<li className="flex items-start gap-2">
<span className="text-yellow-600"></span>
<span><strong>Touch sensor limitation:</strong> Has not passed Conducted Susceptibility test</span>
</li>
<li className="flex items-start gap-2">
<span className="text-yellow-600"></span>
<span><strong>Strapping pins:</strong> GPIO0, GPIO45, GPIO46 have boot mode restrictions</span>
</li>
<li className="flex items-start gap-2">
<span className="text-yellow-600"></span>
<span><strong>eFuse burns:</strong> Secure boot version counter has limited increments</span>
</li>
</ul>
</CardContent>
</Card>
</TabsContent>
{/* Budgets Tab */}
<TabsContent value="budgets" className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<HardDrive className="h-5 w-5" />
RAM Budget
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="flex justify-between text-sm">
<span>Allocated</span>
<span className="font-medium">{budgetAnalysis.ram.allocated} KB</span>
</div>
<div className="flex justify-between text-sm">
<span>Available (ESP32-S3)</span>
<span className="font-medium">{budgetAnalysis.ram.available} KB</span>
</div>
<div className="w-full bg-muted rounded-full h-3">
<div
className="bg-green-500 h-3 rounded-full"
style={{ width: budgetAnalysis.ram.actual }}
/>
</div>
<div className="flex justify-between text-xs text-muted-foreground">
<span>Budget: {budgetAnalysis.ram.budget} (of 307KB doc)</span>
<span>Actual: {budgetAnalysis.ram.actual}</span>
</div>
<Badge variant="outline" className="bg-green-500/10 text-green-700 border-green-500/30">
<CheckCircle className="h-3 w-3 mr-1" />
Within Budget - ESP32-S3 has 512KB vs 307KB assumed
</Badge>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Database className="h-5 w-5" />
Flash Budget
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="flex justify-between text-sm">
<span>Allocated</span>
<span className="font-medium">{budgetAnalysis.flash.allocated} MB</span>
</div>
<div className="flex justify-between text-sm">
<span>Available</span>
<span className="font-medium">{budgetAnalysis.flash.available} MB</span>
</div>
<div className="w-full bg-muted rounded-full h-3">
<div
className="bg-green-500 h-3 rounded-full"
style={{ width: budgetAnalysis.flash.actual }}
/>
</div>
<div className="flex justify-between text-xs text-muted-foreground">
<span>Budget: {budgetAnalysis.flash.budget}</span>
<span>Actual: {budgetAnalysis.flash.actual}</span>
</div>
<Badge variant="outline" className="bg-green-500/10 text-green-700 border-green-500/30">
<CheckCircle className="h-3 w-3 mr-1" />
Within Budget
</Badge>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Clock className="h-5 w-5" />
CPU Budget
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="flex justify-between text-sm">
<span>Normal Operation</span>
<span className="font-medium">{budgetAnalysis.cpu.allocated}%</span>
</div>
<div className="flex justify-between text-sm">
<span>Peak Allowed</span>
<span className="font-medium">{budgetAnalysis.cpu.budget}</span>
</div>
<div className="w-full bg-muted rounded-full h-3">
<div
className="bg-green-500 h-3 rounded-full"
style={{ width: `${budgetAnalysis.cpu.allocated}%` }}
/>
</div>
<Badge variant="outline" className="bg-green-500/10 text-green-700 border-green-500/30">
<CheckCircle className="h-3 w-3 mr-1" />
Within Budget
</Badge>
</div>
</CardContent>
</Card>
</div>
<Card>
<CardHeader>
<CardTitle>Timing Constraints Summary</CardTitle>
</CardHeader>
<CardContent>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{[
{ op: "Sensor Acquisition Cycle", time: "100ms/sensor", status: "ok" },
{ op: "All Sensors (5 max)", time: "500ms", status: "ok" },
{ op: "State Transition", time: "50ms", status: "ok" },
{ op: "Main Hub Request", time: "100ms", status: "ok" },
{ op: "OTA Update Duration", time: "10 min max", status: "ok" },
{ op: "Heartbeat Timeout", time: "30s", status: "warning" }
].map((item, idx) => (
<div key={idx} className="flex items-center justify-between p-3 border rounded-lg">
<span className="text-sm">{item.op}</span>
<div className="flex items-center gap-2">
<span className="font-mono text-sm">{item.time}</span>
{item.status === "ok" ? (
<CheckCircle className="h-4 w-4 text-green-500" />
) : (
<AlertCircle className="h-4 w-4 text-yellow-500" />
)}
</div>
</div>
))}
</div>
</CardContent>
</Card>
</TabsContent>
{/* Recommendations Tab */}
<TabsContent value="recommendations" className="space-y-4">
<Card>
<CardHeader>
<CardTitle>Priority Action Items</CardTitle>
<CardDescription>Critical and high-priority items requiring immediate attention</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
{[
{
priority: "P1",
title: "Define WiFi Protocol Specifics",
category: "Communication",
action: "Document: WiFi 802.11n, 2.4GHz, TLS 1.2 with AES-128-GCM",
severity: "critical"
},
{
priority: "P1",
title: "Create Key Management Specification",
category: "Security",
action: "Define key provisioning, storage (eFuse/NVS), rotation, and revocation procedures",
severity: "critical"
},
{
priority: "P1",
title: "Define Authentication Mechanism",
category: "Security",
action: "Specify X.509 mutual TLS with device certificates",
severity: "critical"
},
{
priority: "P2",
title: "Create Sensor Catalog",
category: "Data Acquisition",
action: "Document specific sensor models, I2C addresses, drivers, warm-up times",
severity: "high"
},
{
priority: "P2",
title: "Define OTA Partition Scheme",
category: "OTA Updates",
action: "Specify partition table: factory + ota_0/ota_1 + nvs + coredump",
severity: "high"
},
{
priority: "P2",
title: "Create GPIO Pin Assignment Table",
category: "Hardware",
action: "Complete mapping avoiding strapping pins, document I2C/SPI/UART assignments",
severity: "high"
},
{
priority: "P2",
title: "Define SD Card Interface Mode",
category: "Hardware",
action: "Specify SDMMC 4-bit vs SPI mode, file system (FAT32), wear strategy",
severity: "high"
},
{
priority: "P3",
title: "Create Diagnostic Code Registry",
category: "Diagnostics",
action: "Define code format and complete registry (0x1xxx=DAQ, 0x2xxx=COM, etc.)",
severity: "medium"
},
{
priority: "P3",
title: "Define Time Sync Mechanism",
category: "System",
action: "Specify sync from Main Hub, interval (1hr), drift tolerance (±1s)",
severity: "medium"
}
].map((item, idx) => (
<div key={idx} className="flex items-start gap-4 p-4 border rounded-lg">
<Badge
className={
item.priority === "P1"
? "bg-red-500 text-white"
: item.priority === "P2"
? "bg-orange-500 text-white"
: "bg-yellow-500 text-white"
}
>
{item.priority}
</Badge>
<div className="flex-1">
<h4 className="font-semibold">{item.title}</h4>
<p className="text-sm text-muted-foreground">{item.category}</p>
<p className="text-sm mt-1">{item.action}</p>
</div>
<SeverityBadge severity={item.severity} />
</div>
))}
</div>
</CardContent>
</Card>
<Card className="border-green-500/30 bg-green-500/5">
<CardHeader>
<CardTitle className="text-green-700">ESP32-S3 Compatibility Summary</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-2 text-sm">
<p className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
<strong>Memory:</strong> ESP32-S3 has 512KB SRAM (vs 307KB assumed) - exceeds requirements
</p>
<p className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
<strong>Flash:</strong> 8MB external flash supports dual OTA partitions
</p>
<p className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
<strong>Security:</strong> Hardware crypto accelerators support all required algorithms
</p>
<p className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
<strong>Interfaces:</strong> 2x I2C, 4x SPI, 3x UART, 20x ADC channels exceed sensor requirements
</p>
<p className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
<strong>WiFi:</strong> 802.11 b/g/n at 2.4GHz meets communication requirements
</p>
<p className="flex items-center gap-2">
<AlertCircle className="h-4 w-4 text-yellow-500" />
<strong>Note:</strong> Ensure ADC channels use ADC1 (not ADC2) when WiFi is active
</p>
</div>
</CardContent>
</Card>
</TabsContent>
</Tabs>
</main>
</div>
);
};
export default Index;