update
This commit is contained in:
25
Caddyfile
Normal file
25
Caddyfile
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
:80 {
|
||||||
|
root * /srv
|
||||||
|
|
||||||
|
# Enable gzip compression
|
||||||
|
encode gzip
|
||||||
|
|
||||||
|
# Handle client-side routing - try file, then index.html
|
||||||
|
try_files {path} /index.html
|
||||||
|
|
||||||
|
# Serve static files
|
||||||
|
file_server
|
||||||
|
|
||||||
|
# Cache static assets
|
||||||
|
@static {
|
||||||
|
path *.js *.css *.png *.jpg *.jpeg *.gif *.ico *.svg *.woff *.woff2 *.ttf *.eot
|
||||||
|
}
|
||||||
|
header @static Cache-Control "public, max-age=31536000, immutable"
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
header {
|
||||||
|
X-Frame-Options "SAMEORIGIN"
|
||||||
|
X-Content-Type-Options "nosniff"
|
||||||
|
X-XSS-Protection "1; mode=block"
|
||||||
|
}
|
||||||
|
}
|
||||||
16
Dockerfile
16
Dockerfile
@@ -16,17 +16,17 @@ COPY . .
|
|||||||
# Build the application
|
# Build the application
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
# Production stage
|
# Production stage - Using Caddy
|
||||||
FROM nginx:alpine AS production
|
FROM caddy:2-alpine AS production
|
||||||
|
|
||||||
# Copy custom nginx config
|
|
||||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
|
||||||
|
|
||||||
# Copy built assets from builder stage
|
# Copy built assets from builder stage
|
||||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
COPY --from=builder /app/dist /srv
|
||||||
|
|
||||||
|
# Copy Caddyfile
|
||||||
|
COPY Caddyfile /etc/caddy/Caddyfile
|
||||||
|
|
||||||
# Expose port 80
|
# Expose port 80
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
# Start nginx
|
# Start Caddy
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile"]
|
||||||
|
|||||||
28
deploy.sh
28
deploy.sh
@@ -76,26 +76,24 @@ else
|
|||||||
print_status "Caddy network exists"
|
print_status "Caddy network exists"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Step 4: Update Caddy configuration
|
# Step 4: Show Caddy configuration to add
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BLUE}Step 4: Updating Caddy configuration...${NC}"
|
echo -e "${BLUE}Step 4: Caddy configuration...${NC}"
|
||||||
|
|
||||||
# Check if Traceability entry already exists in Caddyfile
|
# Check if Traceability entry already exists in Caddyfile
|
||||||
if grep -q "Traceability.nabd-co.com" "$CADDY_DIR/Caddyfile" 2>/dev/null; then
|
if grep -q "Traceability.nabd-co.com" "$CADDY_DIR/Caddyfile" 2>/dev/null; then
|
||||||
print_status "Caddy configuration already exists"
|
print_status "Caddy configuration already exists in Caddyfile"
|
||||||
else
|
else
|
||||||
# Append Traceability configuration to Caddyfile
|
print_warning "Add this entry to your Caddyfile at $CADDY_DIR/Caddyfile:"
|
||||||
cat >> "$CADDY_DIR/Caddyfile" << 'EOF'
|
echo ""
|
||||||
|
echo -e "${YELLOW}# -------------------------"
|
||||||
# -------------------------
|
echo "# Traceability Matrix Proxy"
|
||||||
# Traceability Matrix Proxy
|
echo "# -------------------------"
|
||||||
# -------------------------
|
echo "Traceability.nabd-co.com {"
|
||||||
Traceability.nabd-co.com {
|
echo " reverse_proxy traceability_web:80"
|
||||||
reverse_proxy traceability_web:80
|
echo " encode gzip"
|
||||||
encode gzip
|
echo -e "}${NC}"
|
||||||
}
|
echo ""
|
||||||
EOF
|
|
||||||
print_status "Added Traceability configuration to Caddyfile"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Step 5: Build and start the application
|
# Step 5: Build and start the application
|
||||||
|
|||||||
@@ -8,11 +8,8 @@ services:
|
|||||||
container_name: traceability_web
|
container_name: traceability_web
|
||||||
restart: always
|
restart: always
|
||||||
networks:
|
networks:
|
||||||
- caddy_network
|
- caddy_default
|
||||||
labels:
|
|
||||||
- "traefik.enable=false"
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
caddy_network:
|
caddy_default:
|
||||||
external: true
|
external: true
|
||||||
name: caddy_default
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import DocumentationPage from "./pages/DocumentationPage";
|
|||||||
import AnalysisPage from "./pages/AnalysisPage";
|
import AnalysisPage from "./pages/AnalysisPage";
|
||||||
import ALMTypePage from "./pages/ALMTypePage";
|
import ALMTypePage from "./pages/ALMTypePage";
|
||||||
import TraceabilityMatrixPage from "./pages/TraceabilityMatrixPage";
|
import TraceabilityMatrixPage from "./pages/TraceabilityMatrixPage";
|
||||||
|
import ESPIDFHelperPage from "./pages/ESPIDFHelperPage";
|
||||||
import NotFound from "./pages/NotFound";
|
import NotFound from "./pages/NotFound";
|
||||||
|
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
@@ -23,6 +24,7 @@ const App = () => (
|
|||||||
<Route path="/documentation" element={<DocumentationPage />} />
|
<Route path="/documentation" element={<DocumentationPage />} />
|
||||||
<Route path="/analysis" element={<AnalysisPage />} />
|
<Route path="/analysis" element={<AnalysisPage />} />
|
||||||
<Route path="/matrix" element={<TraceabilityMatrixPage />} />
|
<Route path="/matrix" element={<TraceabilityMatrixPage />} />
|
||||||
|
<Route path="/esp-idf" element={<ESPIDFHelperPage />} />
|
||||||
<Route path="/alm/:type" element={<ALMTypePage />} />
|
<Route path="/alm/:type" element={<ALMTypePage />} />
|
||||||
{/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
|
{/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
|
||||||
<Route path="*" element={<NotFound />} />
|
<Route path="*" element={<NotFound />} />
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
LayoutDashboard,
|
LayoutDashboard,
|
||||||
ChevronDown,
|
ChevronDown,
|
||||||
ChevronRight,
|
ChevronRight,
|
||||||
|
Cpu,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { NavLink } from "@/components/NavLink";
|
import { NavLink } from "@/components/NavLink";
|
||||||
import { useLocation } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
@@ -37,6 +38,7 @@ const mainItems = [
|
|||||||
{ title: "Traceability Matrix", url: "/matrix", icon: GitBranch },
|
{ title: "Traceability Matrix", url: "/matrix", icon: GitBranch },
|
||||||
{ title: "Documentation", url: "/documentation", icon: BookOpen },
|
{ title: "Documentation", url: "/documentation", icon: BookOpen },
|
||||||
{ title: "Gap Analysis", url: "/analysis", icon: Search },
|
{ title: "Gap Analysis", url: "/analysis", icon: Search },
|
||||||
|
{ title: "ESP-IDF Helper", url: "/esp-idf", icon: Cpu },
|
||||||
];
|
];
|
||||||
|
|
||||||
const almItems = [
|
const almItems = [
|
||||||
|
|||||||
726
src/pages/ESPIDFHelperPage.tsx
Normal file
726
src/pages/ESPIDFHelperPage.tsx
Normal file
@@ -0,0 +1,726 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { AppLayout } from "@/components/layout/AppLayout";
|
||||||
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import {
|
||||||
|
Cpu,
|
||||||
|
Wifi,
|
||||||
|
Bluetooth,
|
||||||
|
Shield,
|
||||||
|
Zap,
|
||||||
|
HardDrive,
|
||||||
|
Code,
|
||||||
|
Terminal,
|
||||||
|
Search,
|
||||||
|
ExternalLink,
|
||||||
|
Layers,
|
||||||
|
Radio,
|
||||||
|
Database,
|
||||||
|
Lock,
|
||||||
|
RefreshCw,
|
||||||
|
Settings,
|
||||||
|
Clock,
|
||||||
|
Thermometer,
|
||||||
|
CircuitBoard,
|
||||||
|
Cable,
|
||||||
|
Gauge,
|
||||||
|
Monitor
|
||||||
|
} from "lucide-react";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
// ESP-IDF V5.4 Data
|
||||||
|
const supportedChips = [
|
||||||
|
{ name: "ESP32", cores: "Dual-core Xtensa LX6", flash: "Up to 16MB", ram: "520KB SRAM", wifi: true, bt: "Classic + BLE", status: "Stable" },
|
||||||
|
{ name: "ESP32-S2", cores: "Single-core Xtensa LX7", flash: "Up to 16MB", ram: "320KB SRAM", wifi: true, bt: null, status: "Stable" },
|
||||||
|
{ name: "ESP32-S3", cores: "Dual-core Xtensa LX7", flash: "Up to 16MB", ram: "512KB SRAM + 8MB PSRAM", wifi: true, bt: "BLE 5.0", status: "Stable" },
|
||||||
|
{ name: "ESP32-C2", cores: "Single-core RISC-V", flash: "Up to 4MB", ram: "272KB SRAM", wifi: true, bt: "BLE 5.0", status: "Stable" },
|
||||||
|
{ name: "ESP32-C3", cores: "Single-core RISC-V", flash: "Up to 16MB", ram: "400KB SRAM", wifi: true, bt: "BLE 5.0", status: "Stable" },
|
||||||
|
{ name: "ESP32-C6", cores: "Single-core RISC-V", flash: "Up to 16MB", ram: "512KB SRAM", wifi: "WiFi 6", bt: "BLE 5.0 + 802.15.4", status: "Stable" },
|
||||||
|
{ name: "ESP32-H2", cores: "Single-core RISC-V", flash: "Up to 4MB", ram: "320KB SRAM", wifi: false, bt: "BLE 5.0 + 802.15.4", status: "Stable" },
|
||||||
|
{ name: "ESP32-P4", cores: "Dual-core RISC-V HP + LP", flash: "External", ram: "768KB + 8KB LP", wifi: false, bt: false, status: "Preview" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const peripherals = [
|
||||||
|
{
|
||||||
|
name: "GPIO",
|
||||||
|
icon: CircuitBoard,
|
||||||
|
description: "General Purpose Input/Output pins with interrupt support",
|
||||||
|
apis: ["gpio_config()", "gpio_set_level()", "gpio_get_level()", "gpio_install_isr_service()", "gpio_isr_handler_add()"],
|
||||||
|
features: ["Pull-up/Pull-down resistors", "Interrupt on edge/level", "RTC GPIO support", "Sleep retention (v5.4)"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SPI",
|
||||||
|
icon: Cable,
|
||||||
|
description: "Serial Peripheral Interface for high-speed communication",
|
||||||
|
apis: ["spi_bus_initialize()", "spi_bus_add_device()", "spi_device_transmit()", "spi_device_queue_trans()"],
|
||||||
|
features: ["Master/Slave modes", "DMA support", "Up to 80MHz", "Multiple devices per bus", "Sleep retention (v5.4)"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "I2C",
|
||||||
|
icon: Cable,
|
||||||
|
description: "Inter-Integrated Circuit for sensor communication",
|
||||||
|
apis: ["i2c_param_config()", "i2c_driver_install()", "i2c_master_write_read_device()", "i2c_master_cmd_begin()"],
|
||||||
|
features: ["Master/Slave modes", "Standard (100kHz) and Fast (400kHz)", "Clock stretching", "LP-I2C on C6/P4"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "UART",
|
||||||
|
icon: Terminal,
|
||||||
|
description: "Universal Asynchronous Receiver/Transmitter",
|
||||||
|
apis: ["uart_driver_install()", "uart_param_config()", "uart_write_bytes()", "uart_read_bytes()"],
|
||||||
|
features: ["Hardware flow control", "Ring buffer", "Pattern detection", "RS-485 support"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ADC",
|
||||||
|
icon: Gauge,
|
||||||
|
description: "Analog to Digital Converter (12-bit resolution)",
|
||||||
|
apis: ["adc_oneshot_new_unit()", "adc_oneshot_read()", "adc_cali_create_scheme_curve_fitting()", "adc_continuous_start()"],
|
||||||
|
features: ["Oneshot & Continuous modes", "Hardware calibration", "Attenuation settings", "LP-ADC on C6/P4"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "LEDC (PWM)",
|
||||||
|
icon: Zap,
|
||||||
|
description: "LED Controller for PWM signal generation",
|
||||||
|
apis: ["ledc_timer_config()", "ledc_channel_config()", "ledc_set_duty()", "ledc_update_duty()", "ledc_fade_start()"],
|
||||||
|
features: ["High-speed & low-speed modes", "Hardware fade", "Multiple channels", "Up to 40MHz"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Timer",
|
||||||
|
icon: Clock,
|
||||||
|
description: "Hardware timers for precise timing operations",
|
||||||
|
apis: ["gptimer_new_timer()", "gptimer_set_alarm_action()", "gptimer_start()", "esp_timer_create()"],
|
||||||
|
features: ["64-bit general purpose timers", "Alarm on match", "Auto-reload", "High-resolution esp_timer"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Temperature Sensor",
|
||||||
|
icon: Thermometer,
|
||||||
|
description: "Built-in temperature sensor",
|
||||||
|
apis: ["temperature_sensor_install()", "temperature_sensor_enable()", "temperature_sensor_get_celsius()"],
|
||||||
|
features: ["On-chip temperature", "-10°C to 80°C range", "Low power consumption"]
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const networkingFeatures = [
|
||||||
|
{
|
||||||
|
name: "WiFi",
|
||||||
|
icon: Wifi,
|
||||||
|
description: "802.11 b/g/n wireless connectivity",
|
||||||
|
apis: ["esp_wifi_init()", "esp_wifi_set_mode()", "esp_wifi_set_config()", "esp_wifi_connect()", "esp_wifi_scan_start()"],
|
||||||
|
modes: ["Station (STA)", "SoftAP", "STA+AP", "Promiscuous", "WiFi 6 (C6 only)"],
|
||||||
|
features: ["WPA3 security", "FTM calibration (v5.4)", "Improved coex power (v5.4)", "ESP-NOW protocol"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bluetooth",
|
||||||
|
icon: Bluetooth,
|
||||||
|
description: "Bluetooth Classic and BLE support",
|
||||||
|
apis: ["esp_bt_controller_init()", "esp_bluedroid_init()", "esp_ble_gap_start_advertising()", "nimble_port_init()"],
|
||||||
|
modes: ["Classic BR/EDR (ESP32/S3)", "BLE 5.0", "Mesh", "HID", "A2DP/AVRCP"],
|
||||||
|
features: ["Dual-mode", "Cover Art AVRCP (v5.4)", "NimBLE 1.7.0 (v5.4)", "Device ID Profile"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Thread / Zigbee",
|
||||||
|
icon: Radio,
|
||||||
|
description: "802.15.4 mesh networking protocols",
|
||||||
|
apis: ["esp_openthread_init()", "esp_zb_init()", "esp_zb_start()"],
|
||||||
|
modes: ["Thread Border Router", "Zigbee Coordinator/Router/End Device"],
|
||||||
|
features: ["Matter support", "TREL (v5.4)", "Zigbee 1.6.x", "RCP over USB (v5.4)"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ESP-NETIF",
|
||||||
|
icon: Layers,
|
||||||
|
description: "Network interface abstraction layer",
|
||||||
|
apis: ["esp_netif_init()", "esp_netif_create_default_wifi_sta()", "esp_netif_get_ip_info()"],
|
||||||
|
modes: ["WiFi", "Ethernet", "PPP", "SLIP"],
|
||||||
|
features: ["DHCP client/server", "Static IP", "IPv4/IPv6", "DNS"]
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const protocolsLibraries = [
|
||||||
|
{
|
||||||
|
category: "HTTP/HTTPS",
|
||||||
|
items: [
|
||||||
|
{ name: "esp_http_client", description: "HTTP client for REST APIs", apis: ["esp_http_client_init()", "esp_http_client_perform()"] },
|
||||||
|
{ name: "esp_http_server", description: "HTTP server for web dashboards", apis: ["httpd_start()", "httpd_register_uri_handler()"] },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: "MQTT",
|
||||||
|
items: [
|
||||||
|
{ name: "esp_mqtt", description: "MQTT v3.1.1/v5.0 client", apis: ["esp_mqtt_client_init()", "esp_mqtt_client_subscribe()", "esp_mqtt_client_publish()"] },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: "WebSocket",
|
||||||
|
items: [
|
||||||
|
{ name: "esp_websocket_client", description: "WebSocket client", apis: ["esp_websocket_client_init()", "esp_websocket_client_send_text()"] },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: "mDNS/DNS",
|
||||||
|
items: [
|
||||||
|
{ name: "mdns", description: "Multicast DNS service discovery", apis: ["mdns_init()", "mdns_hostname_set()", "mdns_service_add()"] },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: "TLS/SSL",
|
||||||
|
items: [
|
||||||
|
{ name: "esp_tls", description: "TLS/SSL wrapper (mbedTLS 3.6.0)", apis: ["esp_tls_conn_new()", "esp_tls_conn_read()", "esp_tls_conn_write()"] },
|
||||||
|
{ name: "esp_crt_bundle", description: "Certificate bundle for HTTPS", apis: ["esp_crt_bundle_attach()"] },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const storageOptions = [
|
||||||
|
{
|
||||||
|
name: "NVS (Non-Volatile Storage)",
|
||||||
|
icon: Database,
|
||||||
|
description: "Key-value storage for configuration and small data",
|
||||||
|
apis: ["nvs_flash_init()", "nvs_open()", "nvs_set_str()", "nvs_get_i32()", "nvs_commit()"],
|
||||||
|
useCase: "WiFi credentials, device settings, calibration data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SPIFFS",
|
||||||
|
icon: HardDrive,
|
||||||
|
description: "SPI Flash File System for read-heavy workloads",
|
||||||
|
apis: ["esp_vfs_spiffs_register()", "fopen()", "fread()", "fwrite()"],
|
||||||
|
useCase: "Web assets, configuration files, logs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "FATFS",
|
||||||
|
icon: HardDrive,
|
||||||
|
description: "FAT file system with SD card support",
|
||||||
|
apis: ["esp_vfs_fat_mount()", "esp_vfs_fat_sdmmc_mount()"],
|
||||||
|
useCase: "SD card data logging, removable storage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "LittleFS",
|
||||||
|
icon: HardDrive,
|
||||||
|
description: "Power-loss resilient file system",
|
||||||
|
apis: ["esp_vfs_littlefs_register()"],
|
||||||
|
useCase: "Frequent writes, power-unstable environments"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Wear Leveling",
|
||||||
|
icon: RefreshCw,
|
||||||
|
description: "Flash wear leveling layer",
|
||||||
|
apis: ["wl_mount()", "wl_read()", "wl_write()"],
|
||||||
|
useCase: "Extend flash lifespan for heavy write workloads"
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const securityFeatures = [
|
||||||
|
{
|
||||||
|
name: "Secure Boot V2",
|
||||||
|
icon: Shield,
|
||||||
|
description: "Cryptographic verification of boot chain",
|
||||||
|
details: ["RSA-3072 or ECDSA signatures", "Anti-rollback protection", "Hardware root of trust"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Flash Encryption",
|
||||||
|
icon: Lock,
|
||||||
|
description: "AES-256 encryption of flash contents",
|
||||||
|
details: ["Hardware encryption engine", "Transparent to application", "Development & Release modes"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Hardware Crypto",
|
||||||
|
icon: Cpu,
|
||||||
|
description: "Hardware-accelerated cryptographic operations",
|
||||||
|
details: ["AES, SHA, RSA, ECDSA", "Random number generator", "Digital signature peripheral"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mbedTLS 3.6.0",
|
||||||
|
icon: Lock,
|
||||||
|
description: "TLS/SSL library (updated in v5.4)",
|
||||||
|
details: ["TLS 1.2/1.3 support", "Certificate management", "Optimized RAM usage (v5.4)"]
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const v54Highlights = [
|
||||||
|
{ title: "ESP32-P4 Support", description: "Initial support for the high-performance non-wireless SoC with dual RISC-V cores" },
|
||||||
|
{ title: "Sleep Retention", description: "GPIO, SPI, I2C peripherals maintain state during light sleep on C6/H2" },
|
||||||
|
{ title: "PSRAM Retention", description: "External PSRAM data preserved during light sleep on supported chips" },
|
||||||
|
{ title: "mbedTLS 3.6.0", description: "Updated TLS library with reduced RAM usage for Certificate Bundle" },
|
||||||
|
{ title: "LP Core Expansion", description: "LP-ADC, LP-SPI, LP-I2C support on C6/P4 for ultra-low power operation" },
|
||||||
|
{ title: "NimBLE 1.7.0", description: "Updated BLE stack with improved stability and features" },
|
||||||
|
{ title: "WiFi FTM", description: "Fine Timing Measurement calibration support for C6" },
|
||||||
|
{ title: "Thread TREL", description: "Thread Radio Encapsulation Link support for improved mesh networking" },
|
||||||
|
{ title: "Bootloader Mocks", description: "New mocking framework for improved unit testing capabilities" },
|
||||||
|
{ title: "AVRCP Cover Art", description: "Bluedroid now supports album artwork transfer over Bluetooth" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const ESPIDFHelperPage = () => {
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
|
||||||
|
const filteredPeripherals = peripherals.filter(p =>
|
||||||
|
p.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||||
|
p.description.toLowerCase().includes(searchTerm.toLowerCase())
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppLayout>
|
||||||
|
<div className="p-6 space-y-6">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
|
||||||
|
<div>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className="p-2 bg-primary/10 rounded-lg">
|
||||||
|
<Cpu className="h-8 w-8 text-primary" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h1 className="text-3xl font-bold text-foreground">ESP-IDF V5.4 Helper</h1>
|
||||||
|
<p className="text-muted-foreground">Comprehensive reference for Espressif IoT Development Framework</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Badge variant="outline" className="text-sm">
|
||||||
|
Version 5.4.3 (Latest)
|
||||||
|
</Badge>
|
||||||
|
<a
|
||||||
|
href="https://github.com/espressif/esp-idf/tree/release/v5.4"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="inline-flex items-center gap-1 text-sm text-primary hover:underline"
|
||||||
|
>
|
||||||
|
GitHub <ExternalLink className="h-3 w-3" />
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="https://docs.espressif.com/projects/esp-idf/en/v5.4/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="inline-flex items-center gap-1 text-sm text-primary hover:underline"
|
||||||
|
>
|
||||||
|
Docs <ExternalLink className="h-3 w-3" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* V5.4 Highlights */}
|
||||||
|
<Card className="border-primary/20 bg-primary/5">
|
||||||
|
<CardHeader className="pb-3">
|
||||||
|
<CardTitle className="flex items-center gap-2 text-lg">
|
||||||
|
<Zap className="h-5 w-5 text-primary" />
|
||||||
|
What's New in ESP-IDF V5.4
|
||||||
|
</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 gap-3">
|
||||||
|
{v54Highlights.map((item, idx) => (
|
||||||
|
<div key={idx} className="p-3 bg-background rounded-lg border">
|
||||||
|
<p className="font-medium text-sm text-foreground">{item.title}</p>
|
||||||
|
<p className="text-xs text-muted-foreground mt-1">{item.description}</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* Search */}
|
||||||
|
<div className="relative max-w-md">
|
||||||
|
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
|
||||||
|
<Input
|
||||||
|
placeholder="Search peripherals, APIs, features..."
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
className="pl-10"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Tabs defaultValue="chips" className="space-y-4">
|
||||||
|
<TabsList className="flex-wrap h-auto gap-1">
|
||||||
|
<TabsTrigger value="chips">Supported Chips</TabsTrigger>
|
||||||
|
<TabsTrigger value="peripherals">Peripherals</TabsTrigger>
|
||||||
|
<TabsTrigger value="networking">Networking</TabsTrigger>
|
||||||
|
<TabsTrigger value="protocols">Protocols & Libraries</TabsTrigger>
|
||||||
|
<TabsTrigger value="storage">Storage</TabsTrigger>
|
||||||
|
<TabsTrigger value="security">Security</TabsTrigger>
|
||||||
|
<TabsTrigger value="tools">Development Tools</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
|
||||||
|
{/* Supported Chips */}
|
||||||
|
<TabsContent value="chips" className="space-y-4">
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Supported Microcontrollers</CardTitle>
|
||||||
|
<CardDescription>ESP-IDF V5.4 supports the following ESP32 series chips</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<table className="w-full text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b">
|
||||||
|
<th className="text-left p-3 font-medium">Chip</th>
|
||||||
|
<th className="text-left p-3 font-medium">Processor</th>
|
||||||
|
<th className="text-left p-3 font-medium">Flash</th>
|
||||||
|
<th className="text-left p-3 font-medium">RAM</th>
|
||||||
|
<th className="text-left p-3 font-medium">WiFi</th>
|
||||||
|
<th className="text-left p-3 font-medium">Bluetooth</th>
|
||||||
|
<th className="text-left p-3 font-medium">Status</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{supportedChips.map((chip) => (
|
||||||
|
<tr key={chip.name} className="border-b hover:bg-muted/50">
|
||||||
|
<td className="p-3 font-medium">{chip.name}</td>
|
||||||
|
<td className="p-3 text-muted-foreground">{chip.cores}</td>
|
||||||
|
<td className="p-3 text-muted-foreground">{chip.flash}</td>
|
||||||
|
<td className="p-3 text-muted-foreground">{chip.ram}</td>
|
||||||
|
<td className="p-3">
|
||||||
|
{chip.wifi ? (
|
||||||
|
<Badge variant="outline" className="bg-green-500/10 text-green-600 border-green-500/20">
|
||||||
|
{typeof chip.wifi === 'string' ? chip.wifi : 'Yes'}
|
||||||
|
</Badge>
|
||||||
|
) : (
|
||||||
|
<Badge variant="outline" className="bg-muted text-muted-foreground">No</Badge>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="p-3">
|
||||||
|
{chip.bt ? (
|
||||||
|
<Badge variant="outline" className="bg-blue-500/10 text-blue-600 border-blue-500/20">
|
||||||
|
{chip.bt}
|
||||||
|
</Badge>
|
||||||
|
) : (
|
||||||
|
<Badge variant="outline" className="bg-muted text-muted-foreground">No</Badge>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="p-3">
|
||||||
|
<Badge variant={chip.status === "Stable" ? "default" : "secondary"}>
|
||||||
|
{chip.status}
|
||||||
|
</Badge>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
{/* Peripherals */}
|
||||||
|
<TabsContent value="peripherals" className="space-y-4">
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||||
|
{filteredPeripherals.map((peripheral) => (
|
||||||
|
<Card key={peripheral.name}>
|
||||||
|
<CardHeader className="pb-3">
|
||||||
|
<CardTitle className="flex items-center gap-2 text-lg">
|
||||||
|
<peripheral.icon className="h-5 w-5 text-primary" />
|
||||||
|
{peripheral.name}
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription>{peripheral.description}</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-3">
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-medium text-muted-foreground mb-2">KEY APIs</p>
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
|
{peripheral.apis.map((api) => (
|
||||||
|
<code key={api} className="px-2 py-0.5 bg-muted rounded text-xs font-mono">
|
||||||
|
{api}
|
||||||
|
</code>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-medium text-muted-foreground mb-2">FEATURES</p>
|
||||||
|
<ul className="text-sm text-muted-foreground space-y-1">
|
||||||
|
{peripheral.features.map((feature) => (
|
||||||
|
<li key={feature} className="flex items-center gap-2">
|
||||||
|
<div className="h-1.5 w-1.5 rounded-full bg-primary" />
|
||||||
|
{feature}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
{/* Networking */}
|
||||||
|
<TabsContent value="networking" className="space-y-4">
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||||
|
{networkingFeatures.map((feature) => (
|
||||||
|
<Card key={feature.name}>
|
||||||
|
<CardHeader className="pb-3">
|
||||||
|
<CardTitle className="flex items-center gap-2 text-lg">
|
||||||
|
<feature.icon className="h-5 w-5 text-primary" />
|
||||||
|
{feature.name}
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription>{feature.description}</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-3">
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-medium text-muted-foreground mb-2">MODES</p>
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
|
{feature.modes.map((mode) => (
|
||||||
|
<Badge key={mode} variant="outline" className="text-xs">
|
||||||
|
{mode}
|
||||||
|
</Badge>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-medium text-muted-foreground mb-2">KEY APIs</p>
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
|
{feature.apis.map((api) => (
|
||||||
|
<code key={api} className="px-2 py-0.5 bg-muted rounded text-xs font-mono">
|
||||||
|
{api}
|
||||||
|
</code>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-medium text-muted-foreground mb-2">FEATURES</p>
|
||||||
|
<ul className="text-sm text-muted-foreground space-y-1">
|
||||||
|
{feature.features.map((f) => (
|
||||||
|
<li key={f} className="flex items-center gap-2">
|
||||||
|
<div className="h-1.5 w-1.5 rounded-full bg-primary" />
|
||||||
|
{f}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
{/* Protocols & Libraries */}
|
||||||
|
<TabsContent value="protocols" className="space-y-4">
|
||||||
|
{protocolsLibraries.map((category) => (
|
||||||
|
<Card key={category.category}>
|
||||||
|
<CardHeader className="pb-3">
|
||||||
|
<CardTitle className="text-lg">{category.category}</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
{category.items.map((item) => (
|
||||||
|
<div key={item.name} className="p-3 bg-muted/50 rounded-lg">
|
||||||
|
<p className="font-medium text-sm">{item.name}</p>
|
||||||
|
<p className="text-xs text-muted-foreground mt-1">{item.description}</p>
|
||||||
|
<div className="flex flex-wrap gap-1 mt-2">
|
||||||
|
{item.apis.map((api) => (
|
||||||
|
<code key={api} className="px-1.5 py-0.5 bg-background rounded text-xs font-mono">
|
||||||
|
{api}
|
||||||
|
</code>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
{/* Storage */}
|
||||||
|
<TabsContent value="storage" className="space-y-4">
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4">
|
||||||
|
{storageOptions.map((storage) => (
|
||||||
|
<Card key={storage.name}>
|
||||||
|
<CardHeader className="pb-3">
|
||||||
|
<CardTitle className="flex items-center gap-2 text-lg">
|
||||||
|
<storage.icon className="h-5 w-5 text-primary" />
|
||||||
|
{storage.name}
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription>{storage.description}</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-3">
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-medium text-muted-foreground mb-2">KEY APIs</p>
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
|
{storage.apis.map((api) => (
|
||||||
|
<code key={api} className="px-2 py-0.5 bg-muted rounded text-xs font-mono">
|
||||||
|
{api}
|
||||||
|
</code>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="p-2 bg-muted/50 rounded">
|
||||||
|
<p className="text-xs font-medium text-muted-foreground">USE CASE</p>
|
||||||
|
<p className="text-sm mt-1">{storage.useCase}</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
{/* Security */}
|
||||||
|
<TabsContent value="security" className="space-y-4">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
{securityFeatures.map((feature) => (
|
||||||
|
<Card key={feature.name}>
|
||||||
|
<CardHeader className="pb-3">
|
||||||
|
<CardTitle className="flex items-center gap-2 text-lg">
|
||||||
|
<feature.icon className="h-5 w-5 text-primary" />
|
||||||
|
{feature.name}
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription>{feature.description}</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<ul className="space-y-2">
|
||||||
|
{feature.details.map((detail) => (
|
||||||
|
<li key={detail} className="flex items-center gap-2 text-sm">
|
||||||
|
<div className="h-1.5 w-1.5 rounded-full bg-green-500" />
|
||||||
|
{detail}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
{/* Development Tools */}
|
||||||
|
<TabsContent value="tools" className="space-y-4">
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="flex items-center gap-2">
|
||||||
|
<Terminal className="h-5 w-5 text-primary" />
|
||||||
|
idf.py - Build System
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription>Primary command-line tool for ESP-IDF projects</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-3">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<div className="p-2 bg-muted rounded font-mono text-sm">
|
||||||
|
<span className="text-muted-foreground">$</span> idf.py set-target esp32s3
|
||||||
|
</div>
|
||||||
|
<div className="p-2 bg-muted rounded font-mono text-sm">
|
||||||
|
<span className="text-muted-foreground">$</span> idf.py menuconfig
|
||||||
|
</div>
|
||||||
|
<div className="p-2 bg-muted rounded font-mono text-sm">
|
||||||
|
<span className="text-muted-foreground">$</span> idf.py build
|
||||||
|
</div>
|
||||||
|
<div className="p-2 bg-muted rounded font-mono text-sm">
|
||||||
|
<span className="text-muted-foreground">$</span> idf.py -p /dev/ttyUSB0 flash monitor
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="flex items-center gap-2">
|
||||||
|
<Settings className="h-5 w-5 text-primary" />
|
||||||
|
menuconfig - Configuration
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription>Interactive configuration system for project settings</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<ul className="space-y-2 text-sm">
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<div className="h-1.5 w-1.5 rounded-full bg-primary" />
|
||||||
|
Component configuration (WiFi, Bluetooth, etc.)
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<div className="h-1.5 w-1.5 rounded-full bg-primary" />
|
||||||
|
Compiler and optimization settings
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<div className="h-1.5 w-1.5 rounded-full bg-primary" />
|
||||||
|
Partition table configuration
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<div className="h-1.5 w-1.5 rounded-full bg-primary" />
|
||||||
|
Security settings (Secure Boot, Flash Encryption)
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<div className="h-1.5 w-1.5 rounded-full bg-primary" />
|
||||||
|
FreeRTOS and system configuration
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="flex items-center gap-2">
|
||||||
|
<Monitor className="h-5 w-5 text-primary" />
|
||||||
|
Debugging Tools
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription>Tools for debugging and profiling</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<ul className="space-y-2 text-sm">
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<div className="h-1.5 w-1.5 rounded-full bg-primary" />
|
||||||
|
<strong>idf.py monitor</strong> - Serial console output
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<div className="h-1.5 w-1.5 rounded-full bg-primary" />
|
||||||
|
<strong>GDB</strong> - Hardware debugging via JTAG
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<div className="h-1.5 w-1.5 rounded-full bg-primary" />
|
||||||
|
<strong>Core Dump</strong> - Post-mortem analysis
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<div className="h-1.5 w-1.5 rounded-full bg-primary" />
|
||||||
|
<strong>Application Tracing</strong> - Real-time tracing
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<div className="h-1.5 w-1.5 rounded-full bg-primary" />
|
||||||
|
<strong>Heap Analysis</strong> - Memory debugging
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="flex items-center gap-2">
|
||||||
|
<Code className="h-5 w-5 text-primary" />
|
||||||
|
FreeRTOS APIs
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription>Real-time operating system primitives</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-3">
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-medium text-muted-foreground mb-2">TASK MANAGEMENT</p>
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
|
{["xTaskCreate()", "vTaskDelete()", "vTaskDelay()", "xTaskNotify()"].map((api) => (
|
||||||
|
<code key={api} className="px-2 py-0.5 bg-muted rounded text-xs font-mono">
|
||||||
|
{api}
|
||||||
|
</code>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-medium text-muted-foreground mb-2">SYNCHRONIZATION</p>
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
|
{["xSemaphoreCreateMutex()", "xQueueCreate()", "xEventGroupCreate()"].map((api) => (
|
||||||
|
<code key={api} className="px-2 py-0.5 bg-muted rounded text-xs font-mono">
|
||||||
|
{api}
|
||||||
|
</code>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-medium text-muted-foreground mb-2">ESP EVENT LOOP</p>
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
|
{["esp_event_loop_create_default()", "esp_event_handler_register()", "esp_event_post()"].map((api) => (
|
||||||
|
<code key={api} className="px-2 py-0.5 bg-muted rounded text-xs font-mono">
|
||||||
|
{api}
|
||||||
|
</code>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
</div>
|
||||||
|
</AppLayout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ESPIDFHelperPage;
|
||||||
Reference in New Issue
Block a user