1271 lines
65 KiB
HTML
1271 lines
65 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="es">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Arquitectura Gráfica y Modo Kiosco - NASA Video en Debian 13</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600&family=Inter:wght@300;400;500;600;700&family=Outfit:wght@500;600;700;800&display=swap" rel="stylesheet">
|
|
<style>
|
|
:root {
|
|
--bg-main: #070b14;
|
|
--bg-secondary: #0f172a;
|
|
--bg-card: rgba(19, 28, 49, 0.85);
|
|
--bg-card-hover: rgba(28, 40, 68, 0.95);
|
|
--bg-code: #060911;
|
|
--border-color: rgba(148, 163, 184, 0.14);
|
|
--border-highlight: rgba(56, 189, 248, 0.4);
|
|
--text-primary: #f8fafc;
|
|
--text-secondary: #cbd5e1;
|
|
--text-muted: #94a3b8;
|
|
--accent-cyan: #38bdf8;
|
|
--accent-blue: #3b82f6;
|
|
--accent-indigo: #818cf8;
|
|
--accent-emerald: #10b981;
|
|
--accent-amber: #f59e0b;
|
|
--accent-rose: #f43f5e;
|
|
--accent-purple: #a855f7;
|
|
--radius-lg: 16px;
|
|
--radius-md: 12px;
|
|
--radius-sm: 8px;
|
|
--shadow-card: 0 10px 30px -5px rgba(0, 0, 0, 0.5);
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
body {
|
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
background-color: var(--bg-main);
|
|
color: var(--text-primary);
|
|
line-height: 1.6;
|
|
background-image:
|
|
radial-gradient(circle at 10% 10%, rgba(56, 189, 248, 0.08) 0%, transparent 35%),
|
|
radial-gradient(circle at 90% 20%, rgba(16, 185, 129, 0.07) 0%, transparent 35%),
|
|
radial-gradient(circle at 50% 90%, rgba(129, 140, 248, 0.07) 0%, transparent 40%);
|
|
background-attachment: fixed;
|
|
padding: 2rem 1.25rem 4rem;
|
|
}
|
|
|
|
.container {
|
|
max-width: 1340px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
/* Header */
|
|
header {
|
|
background: linear-gradient(135deg, rgba(15, 23, 42, 0.95), rgba(30, 41, 59, 0.85));
|
|
border: 1px solid var(--border-highlight);
|
|
border-radius: var(--radius-lg);
|
|
padding: 2.25rem;
|
|
margin-bottom: 2rem;
|
|
box-shadow: var(--shadow-card);
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
header::before {
|
|
content: "";
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 4px;
|
|
background: linear-gradient(90deg, var(--accent-cyan), var(--accent-emerald), var(--accent-indigo));
|
|
}
|
|
|
|
.header-top {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
flex-wrap: wrap;
|
|
gap: 1.5rem;
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.brand-group {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1.25rem;
|
|
}
|
|
|
|
.brand-logo {
|
|
width: 64px;
|
|
height: 64px;
|
|
border-radius: 14px;
|
|
background: linear-gradient(135deg, #0b3d91, #1e40af);
|
|
border: 2px solid var(--accent-cyan);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-family: 'Outfit', sans-serif;
|
|
font-weight: 800;
|
|
font-size: 1.35rem;
|
|
letter-spacing: 0.04em;
|
|
color: #fff;
|
|
box-shadow: 0 0 25px rgba(56, 189, 248, 0.3);
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.title-block h1 {
|
|
font-family: 'Outfit', sans-serif;
|
|
font-size: 2.15rem;
|
|
font-weight: 800;
|
|
letter-spacing: -0.02em;
|
|
color: #ffffff;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
.title-block p {
|
|
color: var(--accent-cyan);
|
|
font-size: 1.05rem;
|
|
font-weight: 500;
|
|
margin-top: 0.35rem;
|
|
}
|
|
|
|
.badge-row {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 0.6rem;
|
|
}
|
|
|
|
.badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.4rem;
|
|
padding: 0.35rem 0.85rem;
|
|
border-radius: 999px;
|
|
font-size: 0.8rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.02em;
|
|
}
|
|
|
|
.badge-cyan { background: rgba(56, 189, 248, 0.15); color: #7dd3fc; border: 1px solid rgba(56, 189, 248, 0.35); }
|
|
.badge-emerald { background: rgba(16, 185, 129, 0.15); color: #6ee7b7; border: 1px solid rgba(16, 185, 129, 0.35); }
|
|
.badge-amber { background: rgba(245, 158, 11, 0.15); color: #fcd34d; border: 1px solid rgba(245, 158, 11, 0.35); }
|
|
.badge-purple { background: rgba(168, 85, 247, 0.15); color: #d8b4fe; border: 1px solid rgba(168, 85, 247, 0.35); }
|
|
.badge-rose { background: rgba(244, 63, 94, 0.15); color: #fda4af; border: 1px solid rgba(244, 63, 94, 0.35); }
|
|
|
|
/* Navigation Pills */
|
|
.quick-nav {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 0.6rem;
|
|
margin-top: 1.25rem;
|
|
padding-top: 1.25rem;
|
|
border-top: 1px solid var(--border-color);
|
|
}
|
|
|
|
.quick-nav a {
|
|
text-decoration: none;
|
|
color: var(--text-secondary);
|
|
background: rgba(255, 255, 255, 0.04);
|
|
border: 1px solid var(--border-color);
|
|
padding: 0.45rem 0.95rem;
|
|
border-radius: var(--radius-sm);
|
|
font-size: 0.85rem;
|
|
font-weight: 500;
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.quick-nav a:hover {
|
|
color: #fff;
|
|
border-color: var(--accent-cyan);
|
|
background: rgba(56, 189, 248, 0.12);
|
|
transform: translateY(-1px);
|
|
}
|
|
|
|
/* KPI / Summary Grid */
|
|
.kpi-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
|
gap: 1rem;
|
|
margin-bottom: 2.25rem;
|
|
}
|
|
|
|
.kpi-card {
|
|
background: var(--bg-card);
|
|
border: 1px solid var(--border-color);
|
|
border-radius: var(--radius-md);
|
|
padding: 1.25rem;
|
|
box-shadow: var(--shadow-card);
|
|
transition: transform 0.2s ease, border-color 0.2s ease;
|
|
}
|
|
|
|
.kpi-card:hover {
|
|
transform: translateY(-2px);
|
|
border-color: var(--border-highlight);
|
|
}
|
|
|
|
.kpi-label {
|
|
font-size: 0.75rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.06em;
|
|
color: var(--text-muted);
|
|
font-weight: 700;
|
|
margin-bottom: 0.35rem;
|
|
}
|
|
|
|
.kpi-value {
|
|
font-family: 'Outfit', sans-serif;
|
|
font-size: 1.25rem;
|
|
font-weight: 700;
|
|
color: var(--text-primary);
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
|
|
.kpi-sub {
|
|
font-size: 0.82rem;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
/* Sections & Cards */
|
|
section {
|
|
margin-bottom: 2.5rem;
|
|
scroll-margin-top: 1.5rem;
|
|
}
|
|
|
|
.section-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.75rem;
|
|
margin-bottom: 1.25rem;
|
|
}
|
|
|
|
.section-num {
|
|
width: 36px;
|
|
height: 36px;
|
|
border-radius: 10px;
|
|
background: linear-gradient(135deg, var(--accent-cyan), var(--accent-blue));
|
|
color: #06101f;
|
|
font-family: 'Outfit', sans-serif;
|
|
font-weight: 800;
|
|
font-size: 1.1rem;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.section-title {
|
|
font-family: 'Outfit', sans-serif;
|
|
font-size: 1.6rem;
|
|
font-weight: 700;
|
|
color: #ffffff;
|
|
}
|
|
|
|
.card {
|
|
background: var(--bg-card);
|
|
border: 1px solid var(--border-color);
|
|
border-radius: var(--radius-lg);
|
|
padding: 1.75rem;
|
|
margin-bottom: 1.5rem;
|
|
box-shadow: var(--shadow-card);
|
|
}
|
|
|
|
.card h3 {
|
|
font-family: 'Outfit', sans-serif;
|
|
font-size: 1.25rem;
|
|
color: var(--accent-cyan);
|
|
margin-bottom: 0.85rem;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.card p {
|
|
color: var(--text-secondary);
|
|
margin-bottom: 0.85rem;
|
|
font-size: 0.95rem;
|
|
}
|
|
|
|
/* Dual Columns for Admin vs Nasa */
|
|
.dual-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(420px, 1fr));
|
|
gap: 1.5rem;
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
@media (max-width: 900px) {
|
|
.dual-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
|
|
.session-card {
|
|
background: var(--bg-card);
|
|
border-radius: var(--radius-lg);
|
|
padding: 1.75rem;
|
|
box-shadow: var(--shadow-card);
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.session-admin {
|
|
border: 1px solid rgba(56, 189, 248, 0.45);
|
|
}
|
|
|
|
.session-admin::before {
|
|
content: "";
|
|
position: absolute;
|
|
top: 0; left: 0; right: 0; height: 4px;
|
|
background: linear-gradient(90deg, #38bdf8, #3b82f6);
|
|
}
|
|
|
|
.session-nasa {
|
|
border: 1px solid rgba(16, 185, 129, 0.45);
|
|
}
|
|
|
|
.session-nasa::before {
|
|
content: "";
|
|
position: absolute;
|
|
top: 0; left: 0; right: 0; height: 4px;
|
|
background: linear-gradient(90deg, #10b981, #059669);
|
|
}
|
|
|
|
.session-head {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 1.1rem;
|
|
padding-bottom: 0.9rem;
|
|
border-bottom: 1px solid var(--border-color);
|
|
}
|
|
|
|
.session-name {
|
|
font-family: 'Outfit', sans-serif;
|
|
font-size: 1.45rem;
|
|
font-weight: 800;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.6rem;
|
|
}
|
|
|
|
.feature-list {
|
|
list-style: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
.feature-list li {
|
|
position: relative;
|
|
padding-left: 1.5rem;
|
|
margin-bottom: 0.65rem;
|
|
color: var(--text-secondary);
|
|
font-size: 0.92rem;
|
|
}
|
|
|
|
.feature-list li::before {
|
|
content: "->";
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
font-family: 'Fira Code', monospace;
|
|
font-weight: 700;
|
|
color: var(--accent-cyan);
|
|
}
|
|
|
|
.session-nasa .feature-list li::before {
|
|
color: var(--accent-emerald);
|
|
}
|
|
|
|
/* SVG Blueprint Containers */
|
|
.diagram-box {
|
|
background: #080d1a;
|
|
border: 1px solid rgba(56, 189, 248, 0.28);
|
|
border-radius: var(--radius-lg);
|
|
padding: 1.5rem;
|
|
margin: 1.25rem 0 1.75rem;
|
|
overflow-x: auto;
|
|
box-shadow: inset 0 0 40px rgba(0, 0, 0, 0.6);
|
|
}
|
|
|
|
.diagram-caption {
|
|
text-align: center;
|
|
font-size: 0.85rem;
|
|
color: var(--text-muted);
|
|
margin-top: 0.85rem;
|
|
font-style: italic;
|
|
}
|
|
|
|
svg.blueprint {
|
|
width: 100%;
|
|
height: auto;
|
|
min-width: 860px;
|
|
display: block;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
/* Tables */
|
|
.table-wrap {
|
|
overflow-x: auto;
|
|
border-radius: var(--radius-md);
|
|
border: 1px solid var(--border-color);
|
|
margin: 1rem 0;
|
|
}
|
|
|
|
table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
background: rgba(10, 15, 28, 0.7);
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
th, td {
|
|
padding: 0.85rem 1.1rem;
|
|
text-align: left;
|
|
border-bottom: 1px solid var(--border-color);
|
|
vertical-align: top;
|
|
}
|
|
|
|
th {
|
|
background: rgba(30, 41, 59, 0.85);
|
|
color: var(--accent-cyan);
|
|
font-family: 'Outfit', sans-serif;
|
|
font-weight: 700;
|
|
font-size: 0.85rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.04em;
|
|
}
|
|
|
|
tr:last-child td {
|
|
border-bottom: none;
|
|
}
|
|
|
|
tr:hover td {
|
|
background: rgba(255, 255, 255, 0.02);
|
|
}
|
|
|
|
/* Code & Pre */
|
|
code {
|
|
font-family: 'Fira Code', monospace;
|
|
background: rgba(2, 6, 23, 0.85);
|
|
color: #7dd3fc;
|
|
padding: 0.18rem 0.42rem;
|
|
border-radius: 5px;
|
|
font-size: 0.85em;
|
|
border: 1px solid rgba(56, 189, 248, 0.18);
|
|
}
|
|
|
|
.code-block {
|
|
position: relative;
|
|
background: var(--bg-code);
|
|
border: 1px solid var(--border-color);
|
|
border-radius: var(--radius-md);
|
|
margin: 0.85rem 0 1.2rem;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.code-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 0.5rem 1rem;
|
|
background: rgba(30, 41, 59, 0.65);
|
|
border-bottom: 1px solid var(--border-color);
|
|
font-family: 'Fira Code', monospace;
|
|
font-size: 0.78rem;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.copy-btn {
|
|
background: rgba(56, 189, 248, 0.14);
|
|
color: var(--accent-cyan);
|
|
border: 1px solid rgba(56, 189, 248, 0.35);
|
|
border-radius: 6px;
|
|
padding: 0.25rem 0.65rem;
|
|
font-size: 0.75rem;
|
|
font-family: 'Inter', sans-serif;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.copy-btn:hover {
|
|
background: var(--accent-cyan);
|
|
color: #06101f;
|
|
}
|
|
|
|
pre {
|
|
padding: 1rem 1.15rem;
|
|
overflow-x: auto;
|
|
font-family: 'Fira Code', monospace;
|
|
font-size: 0.84rem;
|
|
line-height: 1.55;
|
|
color: #e2e8f0;
|
|
}
|
|
|
|
pre code {
|
|
background: transparent;
|
|
border: none;
|
|
padding: 0;
|
|
color: inherit;
|
|
font-size: inherit;
|
|
}
|
|
|
|
/* Tech Stack Grid */
|
|
.tech-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
|
|
gap: 1.15rem;
|
|
}
|
|
|
|
.tech-item {
|
|
background: rgba(15, 23, 42, 0.75);
|
|
border: 1px solid var(--border-color);
|
|
border-radius: var(--radius-md);
|
|
padding: 1.25rem;
|
|
transition: border-color 0.2s ease;
|
|
}
|
|
|
|
.tech-item:hover {
|
|
border-color: var(--accent-cyan);
|
|
}
|
|
|
|
.tech-tag {
|
|
display: inline-block;
|
|
font-size: 0.72rem;
|
|
font-weight: 700;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
padding: 0.2rem 0.55rem;
|
|
border-radius: 4px;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.tech-item h4 {
|
|
font-family: 'Outfit', sans-serif;
|
|
font-size: 1.1rem;
|
|
color: #fff;
|
|
margin-bottom: 0.4rem;
|
|
}
|
|
|
|
.tech-item p {
|
|
font-size: 0.87rem;
|
|
color: var(--text-secondary);
|
|
margin: 0;
|
|
}
|
|
|
|
/* Callout Alerts */
|
|
.callout {
|
|
border-left: 4px solid var(--accent-cyan);
|
|
background: rgba(56, 189, 248, 0.08);
|
|
border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
|
|
padding: 1rem 1.25rem;
|
|
margin: 1rem 0;
|
|
font-size: 0.92rem;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.callout strong {
|
|
color: #fff;
|
|
}
|
|
|
|
.callout-emerald {
|
|
border-left-color: var(--accent-emerald);
|
|
background: rgba(16, 185, 129, 0.08);
|
|
}
|
|
|
|
.callout-amber {
|
|
border-left-color: var(--accent-amber);
|
|
background: rgba(245, 158, 11, 0.08);
|
|
}
|
|
|
|
footer {
|
|
text-align: center;
|
|
margin-top: 3.5rem;
|
|
padding-top: 1.5rem;
|
|
border-top: 1px solid var(--border-color);
|
|
color: var(--text-muted);
|
|
font-size: 0.85rem;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
|
|
<!-- ENCABEZADO PRINCIPAL -->
|
|
<header>
|
|
<div class="header-top">
|
|
<div class="brand-group">
|
|
<div class="brand-logo">NASA</div>
|
|
<div class="title-block">
|
|
<h1>Arquitectura Gráfica, Sesiones y Modo Kiosco</h1>
|
|
<p>Sistema de Captura, Control PTZ y Medición en Pantalla (NA-SA Video Capture) sobre Debian 13</p>
|
|
</div>
|
|
</div>
|
|
<div class="badge-row">
|
|
<span class="badge badge-cyan">Debian 13 (Trixie)</span>
|
|
<span class="badge badge-purple">X11 / Xorg Single-Session</span>
|
|
<span class="badge badge-amber">LightDM + Slick Greeter</span>
|
|
<span class="badge badge-cyan">Admin: XFCE 4</span>
|
|
<span class="badge badge-emerald">Operario: Openbox Kiosk</span>
|
|
</div>
|
|
</div>
|
|
|
|
<p style="color: var(--text-secondary); font-size: 0.96rem; max-width: 1100px;">
|
|
Este documento describe en detalle cómo está estructurado el sistema operativo <strong>Debian 13</strong> para separar completamente el entorno de administración (usuario <code>admin</code> con escritorio completo <strong>XFCE 4</strong>) del entorno de operación en planta (usuario <code>nasa</code> en <strong>Modo Kiosco bloqueado sobre Openbox</strong>), cómo se construyó mediante scripts automatizados, cómo se protegen las grabaciones en <code>/datos</code> para que el operario no pueda borrar archivos y qué tecnologías intervienen en cada capa.
|
|
</p>
|
|
|
|
<nav class="quick-nav">
|
|
<a href="#arquitectura-general">1. Gráfico de Arquitectura General</a>
|
|
<a href="#sesiones">2. Sesiones: admin vs nasa</a>
|
|
<a href="#modo-kiosco">3. Cómo se Generó el Modo Kiosco</a>
|
|
<a href="#flujo-watchdog">4. Gráfico: Watchdog y Menú F1</a>
|
|
<a href="#proteccion-datos">5. Gráfico: Partición /datos y Guardián Inotify</a>
|
|
<a href="#tecnologias">6. Tecnologías Utilizadas</a>
|
|
<a href="#comandos">7. Scripts y Comandos Clave</a>
|
|
<a href="componentes_sistema_grafico.html" style="border-color: var(--accent-cyan); color: #7dd3fc; background: rgba(56, 189, 248, 0.14); font-weight: 700;">Ver Guía Concisa de Componentes (LightDM, Openbox, Xorg...) -></a>
|
|
</nav>
|
|
</header>
|
|
|
|
<!-- RESUMEN RAPIDO (KPIs) -->
|
|
<div class="kpi-grid">
|
|
<div class="kpi-card">
|
|
<div class="kpi-label">Sistema Base y Display</div>
|
|
<div class="kpi-value">Debian 13 + Xorg</div>
|
|
<div class="kpi-sub">LightDM + Slick Greeter en español con filtro <code>LD_PRELOAD</code> en C y usuario <code>nasa</code> preseleccionado.</div>
|
|
</div>
|
|
<div class="kpi-card">
|
|
<div class="kpi-label">Sesión Administrador</div>
|
|
<div class="kpi-value" style="color: var(--accent-cyan);">admin -> XFCE 4</div>
|
|
<div class="kpi-sub">Escritorio completo, terminal, compilación CMake/C++, Thunar y control total (lectura/borrado) en <code>/datos</code>.</div>
|
|
</div>
|
|
<div class="kpi-card">
|
|
<div class="kpi-label">Sesión Operario (Kiosco)</div>
|
|
<div class="kpi-value" style="color: var(--accent-emerald);">nasa -> Openbox Kiosk</div>
|
|
<div class="kpi-sub">App <code>nasa_video</code> a pantalla completa sin bordes, auto-relanzamiento en 1 s y salida exclusiva vía <code>F1</code> o <code>Ctrl+Alt+Supr</code>.</div>
|
|
</div>
|
|
<div class="kpi-card">
|
|
<div class="kpi-label">Resguardo de Grabaciones</div>
|
|
<div class="kpi-value" style="color: var(--accent-amber);">/datos + Inotify Guard</div>
|
|
<div class="kpi-sub">Demonio <code>nasa-datos-guard.service</code> que pasa cada archivo cerrado a <code>admin:nasa (0644)</code> impidiendo borrados por <code>nasa</code>.</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- SECCIÓN 1: GRÁFICO DE ARQUITECTURA GENERAL -->
|
|
<section id="arquitectura-general">
|
|
<div class="section-header">
|
|
<div class="section-num">1</div>
|
|
<h2 class="section-title">Arquitectura General del Sistema y Relación de Componentes</h2>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<p>
|
|
El sistema corre sobre una única sesión gráfica Xorg activa a la vez (<code>allow-user-switching=false</code>) para garantizar acceso exclusivo y directo al hardware de captura (<strong>Magewell PCIe</strong>), decodificación por hardware (<strong>NVIDIA NVDEC + CUDA Zero-Copy OpenGL</strong>) y bus serie (<strong>RS-485 Pelco-D</strong>). Al encender el equipo, <strong>LightDM</strong> presenta <strong>Slick Greeter</strong> y enruta a cada usuario hacia un entorno gráfico totalmente distinto según su rol:
|
|
</p>
|
|
|
|
<div class="diagram-box">
|
|
<svg class="blueprint" viewBox="0 0 1120 690" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<defs>
|
|
<pattern id="bg-grid" width="32" height="32" patternUnits="userSpaceOnUse">
|
|
<path d="M 32 0 L 0 0 0 32" fill="none" stroke="#1e293b" stroke-width="0.7" stroke-opacity="0.55"/>
|
|
</pattern>
|
|
<marker id="arrow-cyan" viewBox="0 0 10 10" refX="7" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
|
<path d="M 0 1 L 10 5 L 0 9 z" fill="#38bdf8"/>
|
|
</marker>
|
|
<marker id="arrow-emerald" viewBox="0 0 10 10" refX="7" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
|
<path d="M 0 1 L 10 5 L 0 9 z" fill="#10b981"/>
|
|
</marker>
|
|
<marker id="arrow-amber" viewBox="0 0 10 10" refX="7" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
|
<path d="M 0 1 L 10 5 L 0 9 z" fill="#f59e0b"/>
|
|
</marker>
|
|
</defs>
|
|
|
|
<!-- Fondo cuadriculado -->
|
|
<rect width="1120" height="690" rx="12" fill="url(#bg-grid)"/>
|
|
|
|
<!-- CAPA 1: HARDWARE Y KERNEL DEBIAN 13 -->
|
|
<rect x="40" y="20" width="1040" height="82" rx="10" fill="#0f172a" stroke="#475569" stroke-width="1.5"/>
|
|
<text x="60" y="46" fill="#94a3b8" font-family="Outfit, sans-serif" font-size="13" font-weight="700">CAPA 1: SISTEMA OPERATIVO BASE Y HARDWARE INDUSTRIAL</text>
|
|
<text x="60" y="70" fill="#f8fafc" font-family="Inter, sans-serif" font-size="14" font-weight="600">Debian 13 (Trixie) Kernel Linux x86_64 + systemd + Xorg Server (Sin DPMS / Sin Suspensión)</text>
|
|
|
|
<!-- Chips de Hardware -->
|
|
<rect x="650" y="34" width="125" height="50" rx="6" fill="#1e293b" stroke="#38bdf8" stroke-width="1"/>
|
|
<text x="712" y="55" text-anchor="middle" fill="#7dd3fc" font-family="Fira Code, monospace" font-size="11" font-weight="600">GPU NVIDIA</text>
|
|
<text x="712" y="72" text-anchor="middle" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="10">CUDA + NVDEC</text>
|
|
|
|
<rect x="788" y="34" width="135" height="50" rx="6" fill="#1e293b" stroke="#38bdf8" stroke-width="1"/>
|
|
<text x="855" y="55" text-anchor="middle" fill="#7dd3fc" font-family="Fira Code, monospace" font-size="11" font-weight="600">Magewell SDK</text>
|
|
<text x="855" y="72" text-anchor="middle" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="10">libMWCapture.so</text>
|
|
|
|
<rect x="935" y="34" width="125" height="50" rx="6" fill="#1e293b" stroke="#38bdf8" stroke-width="1"/>
|
|
<text x="997" y="55" text-anchor="middle" fill="#7dd3fc" font-family="Fira Code, monospace" font-size="11" font-weight="600">RS-485 Serial</text>
|
|
<text x="997" y="72" text-anchor="middle" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="10">dialout / PTZ</text>
|
|
|
|
<!-- Flecha hacia LightDM -->
|
|
<line x1="560" y1="102" x2="560" y2="132" stroke="#38bdf8" stroke-width="2" marker-end="url(#arrow-cyan)"/>
|
|
|
|
<!-- CAPA 2: DISPLAY MANAGER (LIGHTDM + SLICK GREETER) -->
|
|
<rect x="200" y="135" width="720" height="96" rx="10" fill="#131c31" stroke="#f59e0b" stroke-width="1.8"/>
|
|
<text x="560" y="160" text-anchor="middle" fill="#fcd34d" font-family="Outfit, sans-serif" font-size="15" font-weight="700">GESTOR DE SESIÓN: LightDM + Slick Greeter Personalizado</text>
|
|
<text x="560" y="182" text-anchor="middle" fill="#e2e8f0" font-family="Inter, sans-serif" font-size="12">
|
|
• Preselección automática: nasa-greeter-setup fija last-user=nasa • Sesión única: allow-user-switching=false
|
|
</text>
|
|
<text x="560" y="201" text-anchor="middle" fill="#94a3b8" font-family="Fira Code, monospace" font-size="11">
|
|
• Wrapper LD_PRELOAD: /usr/local/lib/slick-greeter-filter-a11y.so (Español + Oculta High Contrast/Screen Reader)
|
|
</text>
|
|
<text x="560" y="219" text-anchor="middle" fill="#7dd3fc" font-family="Fira Code, monospace" font-size="11">
|
|
• Asignación fija de sesión vía ~/.dmrc + /var/lib/AccountsService/users/{admin,nasa}
|
|
</text>
|
|
|
|
<!-- Bifurcación de flechas hacia Admin y Nasa -->
|
|
<path d="M 380 231 L 380 258 L 270 258 L 270 282" stroke="#38bdf8" stroke-width="2.2" fill="none" marker-end="url(#arrow-cyan)"/>
|
|
<path d="M 740 231 L 740 258 L 850 258 L 850 282" stroke="#10b981" stroke-width="2.2" fill="none" marker-end="url(#arrow-emerald)"/>
|
|
|
|
<rect x="215" y="244" width="140" height="22" rx="4" fill="#0f172a" stroke="#38bdf8" stroke-width="1"/>
|
|
<text x="285" y="259" text-anchor="middle" fill="#7dd3fc" font-family="Fira Code, monospace" font-size="11" font-weight="600">Login: admin</text>
|
|
|
|
<rect x="765" y="244" width="140" height="22" rx="4" fill="#0f172a" stroke="#10b981" stroke-width="1"/>
|
|
<text x="835" y="259" text-anchor="middle" fill="#6ee7b7" font-family="Fira Code, monospace" font-size="11" font-weight="600">Login: nasa</text>
|
|
|
|
<!-- RAMA IZQUIERDA: SESIÓN ADMIN (XFCE 4) -->
|
|
<rect x="40" y="286" width="465" height="245" rx="12" fill="#0f1b2d" stroke="#38bdf8" stroke-width="2"/>
|
|
<rect x="40" y="286" width="465" height="36" rx="10" fill="#1e3a5f"/>
|
|
<text x="272" y="309" text-anchor="middle" fill="#ffffff" font-family="Outfit, sans-serif" font-size="15" font-weight="700">SESIÓN ADMINISTRADOR: Usuario "admin" (XFCE 4)</text>
|
|
|
|
<rect x="62" y="336" width="420" height="52" rx="7" fill="#16243b" stroke="#334155"/>
|
|
<text x="76" y="356" fill="#7dd3fc" font-family="Fira Code, monospace" font-size="12" font-weight="600">Entorno: XFCE 4 Desktop (Session=xfce)</text>
|
|
<text x="76" y="375" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="11.5">Gestor xfwm4 (vblank_mode=xpresent) + Panel XFCE + Terminal</text>
|
|
|
|
<rect x="62" y="398" width="420" height="56" rx="7" fill="#16243b" stroke="#334155"/>
|
|
<text x="76" y="418" fill="#7dd3fc" font-family="Fira Code, monospace" font-size="12" font-weight="600">Desarrollo y Despliegue (/home/admin/repos/nasa_video)</text>
|
|
<text x="76" y="437" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="11.5">Compilación CMake + deploy_kiosk.sh + prepare_kiosk_test.sh</text>
|
|
|
|
<rect x="62" y="464" width="420" height="52" rx="7" fill="#16243b" stroke="#334155"/>
|
|
<text x="76" y="484" fill="#7dd3fc" font-family="Fira Code, monospace" font-size="12" font-weight="600">Gestión de Archivos (Thunar + Permisos Root/Admin)</text>
|
|
<text x="76" y="503" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="11.5">Dueño de /datos (Lectura, Escritura, Renombrado y Borrado total)</text>
|
|
|
|
<!-- RAMA DERECHA: SESIÓN NASA (MODO KIOSCO OPENBOX) -->
|
|
<rect x="595" y="286" width="485" height="245" rx="12" fill="#0b211d" stroke="#10b981" stroke-width="2"/>
|
|
<rect x="595" y="286" width="485" height="36" rx="10" fill="#065f46"/>
|
|
<text x="837" y="309" text-anchor="middle" fill="#ffffff" font-family="Outfit, sans-serif" font-size="15" font-weight="700">SESIÓN OPERARIO: Usuario "nasa" (Modo Kiosco)</text>
|
|
|
|
<rect x="615" y="336" width="445" height="52" rx="7" fill="#112e28" stroke="#1f4d42"/>
|
|
<text x="630" y="356" fill="#6ee7b7" font-family="Fira Code, monospace" font-size="12" font-weight="600">Gestor: Openbox Bloqueado (/etc/xdg/nasa-video-kiosk/rc.xml)</text>
|
|
<text x="630" y="375" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="11.5">1 escritorio, sin bordes, sin menú contextual, sin terminal ni explorador</text>
|
|
|
|
<rect x="615" y="398" width="445" height="56" rx="7" fill="#112e28" stroke="#1f4d42"/>
|
|
<text x="630" y="418" fill="#6ee7b7" font-family="Fira Code, monospace" font-size="12" font-weight="600">Lanzador Watchdog: /usr/local/bin/nasa-video-kiosk-session</text>
|
|
<text x="630" y="437" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="11.5">Ejecuta nasa_video con NASA_KIOSK_MODE=1 y auto-relanza en 1 s si cae</text>
|
|
|
|
<rect x="615" y="464" width="445" height="52" rx="7" fill="#112e28" stroke="#1f4d42"/>
|
|
<text x="630" y="484" fill="#6ee7b7" font-family="Fira Code, monospace" font-size="12" font-weight="600">Control de Salida: Tecla F1 (Menú Qt) / Ctrl+Alt+Supr (Panel GTK3)</text>
|
|
<text x="630" y="503" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="11.5">Únicas acciones fuera de la app: Cerrar sesión, Reiniciar y Apagar (Polkit)</text>
|
|
|
|
<!-- Flechas hacia CAPA 3: PARTICIÓN COMPARTIDA /datos -->
|
|
<path d="M 272 531 L 272 572" stroke="#38bdf8" stroke-width="2.2" marker-end="url(#arrow-cyan)"/>
|
|
<path d="M 837 531 L 837 572" stroke="#10b981" stroke-width="2.2" marker-end="url(#arrow-emerald)"/>
|
|
|
|
<!-- CAPA 3: ALMACENAMIENTO COMPARTIDO /datos -->
|
|
<rect x="40" y="576" width="1040" height="94" rx="12" fill="#171625" stroke="#f59e0b" stroke-width="2"/>
|
|
<text x="560" y="602" text-anchor="middle" fill="#fcd34d" font-family="Outfit, sans-serif" font-size="15" font-weight="700">
|
|
PUNTO DE ENCUENTRO: PARTICIÓN /datos/NA-SA_Video + SERVICIO GUARDIÁN (nasa-datos-guard.service)
|
|
</text>
|
|
<text x="272" y="628" text-anchor="middle" fill="#7dd3fc" font-family="Inter, sans-serif" font-size="12" font-weight="600">
|
|
admin (Dueño admin:nasa): Lectura, Escritura y Borrado Total
|
|
</text>
|
|
<text x="837" y="628" text-anchor="middle" fill="#6ee7b7" font-family="Inter, sans-serif" font-size="12" font-weight="600">
|
|
nasa (Grupo nasa): Graba Videos y Mediciones, Reproduce, NO PUEDE BORRAR
|
|
</text>
|
|
<text x="560" y="652" text-anchor="middle" fill="#cbd5e1" font-family="Fira Code, monospace" font-size="11.5">
|
|
Directorios 3775 (setgid + sticky bit) | Archivos cerrados pasan por inotify (IN_CLOSE_WRITE) a admin:nasa (0644)
|
|
</text>
|
|
</svg>
|
|
<div class="diagram-caption">
|
|
Figura 1: Arquitectura general del sistema Debian 13 mostrando la bifurcación en LightDM hacia XFCE (admin) y Openbox Kiosk (nasa), y su convergencia controlada en la partición /datos.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- SECCIÓN 2: LAS DOS SESIONES (ADMIN VS NASA) -->
|
|
<section id="sesiones">
|
|
<div class="section-header">
|
|
<div class="section-num">2</div>
|
|
<h2 class="section-title">Las Dos Sesiones: <code>admin</code> (Administrador) vs <code>nasa</code> (Operario)</h2>
|
|
</div>
|
|
|
|
<div class="dual-grid">
|
|
<!-- Tarjeta ADMIN -->
|
|
<div class="session-card session-admin">
|
|
<div class="session-head">
|
|
<div class="session-name" style="color: var(--accent-cyan);">
|
|
<span>Usuario: <code>admin</code></span>
|
|
</div>
|
|
<span class="badge badge-cyan">Escritorio XFCE 4 Completo</span>
|
|
</div>
|
|
<ul class="feature-list">
|
|
<li><strong>Propósito:</strong> Administración del sistema, compilación y actualización del software, diagnóstico de hardware y gestión/depuración de grabaciones.</li>
|
|
<li><strong>Sesión Fijada:</strong> <code>Session=xfce</code> en <code>~admin/.dmrc</code> y en <code>/var/lib/AccountsService/users/admin</code>.</li>
|
|
<li><strong>Entorno de Escritorio:</strong> XFCE 4 completo con gestor de ventanas <code>xfwm4</code> (ajustado con <code>vblank_mode=xpresent</code> para evitar pantalla negra en NVIDIA).</li>
|
|
<li><strong>Herramientas Disponibles:</strong> Terminal completa, compilador GCC/CMake, navegador de archivos <strong>Thunar</strong> con marcadores directos a <code>/datos</code> y <code>/datos/NA-SA_Video</code>.</li>
|
|
<li><strong>Privilegios sobre <code>/datos</code>:</strong> Es el propietario (<code>admin:nasa</code>) de todas las carpetas y archivos. Puede leer, copiar, mover, renombrar y <strong>eliminar</strong> cualquier grabación o captura.</li>
|
|
<li><strong>Flujo de Despliegue:</strong> Desde <code>/home/admin/repos/nasa_video</code> compila los cambios y los publica hacia el kiosco ejecutando <code>deploy_kiosk.sh</code>.</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Tarjeta NASA -->
|
|
<div class="session-card session-nasa">
|
|
<div class="session-head">
|
|
<div class="session-name" style="color: var(--accent-emerald);">
|
|
<span>Usuario: <code>nasa</code></span>
|
|
</div>
|
|
<span class="badge badge-emerald">Modo Kiosco (Openbox)</span>
|
|
</div>
|
|
<ul class="feature-list">
|
|
<li><strong>Propósito:</strong> Operación diaria en planta por parte de los operarios de Soldadura, Reparación y END sin acceso al sistema operativo subyacente.</li>
|
|
<li><strong>Sesión Fijada:</strong> <code>Session=nasa-video-kiosk</code> en <code>~nasa/.dmrc</code> y en <code>/var/lib/AccountsService/users/nasa</code> (con ícono <code>.face</code> de VENG).</li>
|
|
<li><strong>Entorno Gráfico:</strong> <strong>Openbox</strong> dedicado sin paneles de escritorio, sin menú de aplicaciones de Debian, sin explorador de archivos y con un único escritorio virtual.</li>
|
|
<li><strong>Comportamiento de <code>nasa_video</code>:</strong> Se inicia en <strong>pantalla completa sin bordes</strong> (<code>NASA_KIOSK_MODE=1</code>), oculta <code>Archivo -> Salir</code> y desactiva <code>F11</code>, <code>Esc</code> y <code>Alt+F4</code>.</li>
|
|
<li><strong>Privilegios sobre <code>/datos</code>:</strong> Puede grabar nuevos videos, guardar capturas de medición en pantalla, crear subcarpetas y reproducir videos, pero <strong>no puede borrar ni sobreescribir</strong> archivos existentes.</li>
|
|
<li><strong>Salida Controlada:</strong> Al presionar <strong><code>F1</code></strong> (o <code>Ctrl+Alt+Supr</code>) accede únicamente a <em>Cerrar sesión</em>, <em>Reiniciar</em> o <em>Apagar</em> con confirmación.</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tabla Comparativa -->
|
|
<div class="card">
|
|
<h3>Tabla Comparativa Técnica entre Sesiones</h3>
|
|
<div class="table-wrap">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Característica / Parámetro</th>
|
|
<th>Sesión <code>admin</code> (Administrador)</th>
|
|
<th>Sesión <code>nasa</code> (Operario Kiosco)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><strong>Archivo de Sesión X11</strong></td>
|
|
<td><code>/usr/share/xsessions/xfce.desktop</code></td>
|
|
<td><code>/usr/share/xsessions/nasa-video-kiosk.desktop</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Gestor de Ventanas (WM)</strong></td>
|
|
<td><code>xfwm4</code> (XFCE Window Manager)</td>
|
|
<td><code>openbox</code> con <code>/etc/xdg/nasa-video-kiosk/rc.xml</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Modo de Ventana de <code>nasa_video</code></strong></td>
|
|
<td>Ventana normal redimensionable (1280x720) + <code>F11</code> libre</td>
|
|
<td>Pantalla completa forzada (<code>showFullScreen()</code> y <code><fullscreen>yes</fullscreen></code>)</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Ejecutable Utilizado</strong></td>
|
|
<td><code>/home/admin/repos/nasa_video/build/nasa_video</code></td>
|
|
<td><code>~nasa/Applications/nasa_video/nasa_video</code> (o <code>.AppImage</code>)</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Supervisión de Proceso (Watchdog)</strong></td>
|
|
<td>No (ejecución manual bajo demanda)</td>
|
|
<td>Sí: <code>/usr/local/bin/nasa-video-kiosk-session</code> (relanza en 1 s)</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Permisos en <code>/datos/NA-SA_Video</code></strong></td>
|
|
<td>Dueño <code>admin</code>: Lectura, Escritura, Modificación y <strong>Borrado</strong></td>
|
|
<td>Grupo <code>nasa</code>: Creación de nuevos archivos y lectura. <strong>Borrado bloqueado</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Acceso a Terminal / Sistema</strong></td>
|
|
<td>Total (<code>bash</code>, <code>sudo</code>, <code>apt</code>, <code>systemctl</code>)</td>
|
|
<td>Bloqueado (sin atajos a terminal, ni navegador, ni gestor de archivos)</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Control de Energía (Apagar / Reiniciar)</strong></td>
|
|
<td>Menú de salida de XFCE / <code>sudo systemctl</code></td>
|
|
<td>Menú <code>F1</code> (Qt) o <code>Ctrl+Alt+Supr</code> (GTK3) autorizado vía Polkit</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- SECCIÓN 3: CÓMO SE GENERÓ EL MODO KIOSCO -->
|
|
<section id="modo-kiosco">
|
|
<div class="section-header">
|
|
<div class="section-num">3</div>
|
|
<h2 class="section-title">Cómo se Generó el Modo Kiosco (Componentes y Construcción)</h2>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<p>
|
|
El modo kiosco no depende de extensiones frágiles de navegador ni de bloquear un escritorio pesado, sino que se construyó combinando <strong>cinco piezas de ingeniería a nivel de sistema e interfaz</strong> orquestadas íntegramente por el script <code>prepare_kiosk_test.sh</code> y el código C++ de <code>MainWindow.cpp</code>:
|
|
</p>
|
|
|
|
<div class="table-wrap">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Componente Generado</th>
|
|
<th>Ruta en el Sistema</th>
|
|
<th>Qué hace exactamente y cómo funciona</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><strong>1. Definición de Sesión XSession</strong></td>
|
|
<td><code>/usr/share/xsessions/nasa-video-kiosk.desktop</code></td>
|
|
<td>Registra la sesión <em>NASA Video Kiosk</em> en LightDM. Ejecuta <code>openbox --sm-disable --config-file /etc/xdg/nasa-video-kiosk/rc.xml --startup /usr/local/bin/nasa-video-kiosk-session</code>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>2. Reglas de Ventanas y Teclado Openbox</strong></td>
|
|
<td><code>/etc/xdg/nasa-video-kiosk/rc.xml</code><br><code>/etc/xdg/nasa-video-kiosk/menu.xml</code></td>
|
|
<td>Fija 1 solo escritorio, márgenes 0, elimina el menú raíz de clic derecho, habilita únicamente <code>Alt+Tab</code> (para alternar con el Panel Virtual de controlador o el Reproductor) y <code>Ctrl+Alt+Supr</code>. Fuerza <code><decor>no</decor></code> y <code><fullscreen>yes</fullscreen></code> en <code>NA-SA Video Capture*</code>, y coloca en capa superior (<code><layer>above</layer></code>) los diálogos secundarios.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>3. Script Lanzador y Watchdog</strong></td>
|
|
<td><code>/usr/local/bin/nasa-video-kiosk-session</code></td>
|
|
<td>Exporta <code>NASA_KIOSK_MODE=1</code>, desactiva DPMS/salvapantallas con <code>xset</code>, pinta el fondo X11 en azul oscuro (<code>#051a30</code>) y ejecuta un bucle infinito que inicia el binario o AppImage en <code>~nasa/Applications/</code>. Si el proceso termina y no existe el archivo bandera <code>nasa-kiosk-stopping-<uid></code>, lo vuelve a lanzar en <strong>1 segundo</strong>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>4. Adaptación Nativa en la App Qt6</strong></td>
|
|
<td><code>src/ui/MainWindow.cpp</code><br><code>src/main.cpp</code></td>
|
|
<td>Detecta <code>NASA_KIOSK_MODE=1</code> o <code>USER=nasa</code>. Abre la ventana en <code>showFullScreen()</code>, ignora <code>closeEvent</code> (bloquea <code>Alt+F4</code>), desactiva <code>F11</code> y <code>Esc</code>, oculta <code>Archivo -> Salir</code> y lo reemplaza por <strong>Cerrar sesión...</strong>, <strong>Reiniciar...</strong> y <strong>Apagar...</strong>. Además, captura la tecla <strong><code>F1</code></strong> (y <code>XF86HomePage</code>) para desplegar instantáneamente el menú <code>Sistema</code>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>5. Panel de Sesión GTK3 / XFCE UI</strong></td>
|
|
<td><code>/usr/local/bin/nasa-video-kiosk-panel</code></td>
|
|
<td>Script en Python 3 con <code>PyGObject (GTK 3 + GdkX11)</code> y <code>libxfce4ui-2</code>. Despliega un menú en la esquina superior derecha y cuadros de diálogo nativos de XFCE con cuenta regresiva de 30 segundos para Reiniciar, Apagar o Cerrar sesión cuando se invoca con <code>Ctrl+Alt+Supr</code>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>6. Regla Polkit de Energía</strong></td>
|
|
<td><code>/etc/polkit-1/rules.d/60-nasa-kiosk-power.rules</code></td>
|
|
<td>Autoriza explícitamente al usuario sin privilegios <code>nasa</code> a ejecutar las acciones D-Bus <code>org.freedesktop.login1.power-off</code> y <code>org.freedesktop.login1.reboot</code> sin pedir contraseña de administrador.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>7. Filtro C para Slick Greeter</strong></td>
|
|
<td><code>/usr/local/lib/slick-greeter-filter-a11y.so</code><br><code>/usr/sbin/slick-greeter</code></td>
|
|
<td>Generado por <code>deploy_filter_a11y.sh</code>. Usa <code>dpkg-divert</code> y <code>LD_PRELOAD</code> para interceptar funciones GTK en la pantalla de login, forzando el idioma español (traduce <em>Quit...</em> a <em>Salir...</em>) y ocultando del menú de accesibilidad el <em>Lector de pantalla</em> y <em>Contraste alto</em>, dejando solo el <em>Teclado en pantalla</em>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>8. Bloqueo de Suspensión y Blanking</strong></td>
|
|
<td><code>/etc/X11/xorg.conf.d/10-nasa-no-blanking.conf</code><br><code>/etc/systemd/sleep.conf.d/nasa-no-sleep.conf</code><br><code>/etc/systemd/logind.conf.d/nasa-no-idle.conf</code></td>
|
|
<td>Desactiva por completo el apagado de monitor (DPMS), el protector de pantalla, <code>light-locker</code> y los estados de suspensión/hibernación tanto en Xorg como en <code>systemd</code> y <code>xfce4-power-manager</code>.</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- SECCIÓN 4: GRÁFICO DEL CICLO DE VIDA DEL KIOSCO Y WATCHDOG -->
|
|
<section id="flujo-watchdog">
|
|
<div class="section-header">
|
|
<div class="section-num">4</div>
|
|
<h2 class="section-title">Gráfico: Ciclo de Vida del Kiosco, Watchdog y Salida con <code>F1</code> / <code>Ctrl+Alt+Supr</code></h2>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<p>
|
|
Uno de los puntos clave del diseño es cómo distinguir entre un <strong>cierre inesperado</strong> (que debe recuperarse automáticamente en 1 segundo sin intervención del operario) y una <strong>salida autorizada</strong> (Cerrar sesión, Reiniciar o Apagar). Esto se resuelve mediante un archivo bandera en memoria (<code>/run/user/<uid>/nasa-kiosk-stopping-<uid></code>) que tanto la ventana principal Qt6 como el panel GTK3 escriben justo antes de ordenar el cierre:
|
|
</p>
|
|
|
|
<div class="diagram-box">
|
|
<svg class="blueprint" viewBox="0 0 1120 470" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<rect width="1120" height="470" rx="12" fill="url(#bg-grid)"/>
|
|
|
|
<!-- Paso 1: Inicio de sesion nasa -->
|
|
<rect x="35" y="45" width="215" height="90" rx="10" fill="#131c31" stroke="#38bdf8" stroke-width="1.8"/>
|
|
<text x="142" y="72" text-anchor="middle" fill="#7dd3fc" font-family="Outfit, sans-serif" font-size="14" font-weight="700">1. Login "nasa"</text>
|
|
<text x="142" y="93" text-anchor="middle" fill="#e2e8f0" font-family="Fira Code, monospace" font-size="11">openbox --sm-disable</text>
|
|
<text x="142" y="112" text-anchor="middle" fill="#94a3b8" font-family="Inter, sans-serif" font-size="11">Carga rc.xml y lanza</text>
|
|
<text x="142" y="126" text-anchor="middle" fill="#94a3b8" font-family="Fira Code, monospace" font-size="10.5">nasa-video-kiosk-session</text>
|
|
|
|
<line x1="250" y1="90" x2="295" y2="90" stroke="#38bdf8" stroke-width="2" marker-end="url(#arrow-cyan)"/>
|
|
|
|
<!-- Paso 2: Watchdog Script -->
|
|
<rect x="298" y="35" width="250" height="110" rx="10" fill="#0b211d" stroke="#10b981" stroke-width="1.8"/>
|
|
<text x="423" y="62" text-anchor="middle" fill="#6ee7b7" font-family="Outfit, sans-serif" font-size="14" font-weight="700">2. Bucle Watchdog</text>
|
|
<text x="423" y="82" text-anchor="middle" fill="#e2e8f0" font-family="Fira Code, monospace" font-size="11">export NASA_KIOSK_MODE=1</text>
|
|
<text x="423" y="100" text-anchor="middle" fill="#cbd5e1" font-family="Fira Code, monospace" font-size="10.5">xset s off s noblank -dpms</text>
|
|
<text x="423" y="118" text-anchor="middle" fill="#fcd34d" font-family="Fira Code, monospace" font-size="11">while [ ! -e "$STOP_FLAG" ]</text>
|
|
<text x="423" y="135" text-anchor="middle" fill="#94a3b8" font-family="Inter, sans-serif" font-size="10.5">Lanza Binario o AppImage</text>
|
|
|
|
<line x1="548" y1="90" x2="595" y2="90" stroke="#10b981" stroke-width="2" marker-end="url(#arrow-emerald)"/>
|
|
|
|
<!-- Paso 3: App NASA Video corriendo -->
|
|
<rect x="598" y="35" width="265" height="110" rx="10" fill="#16243b" stroke="#38bdf8" stroke-width="2"/>
|
|
<text x="730" y="62" text-anchor="middle" fill="#ffffff" font-family="Outfit, sans-serif" font-size="14" font-weight="700">3. App nasa_video Activa</text>
|
|
<text x="730" y="82" text-anchor="middle" fill="#7dd3fc" font-family="Inter, sans-serif" font-size="11.5">• Pantalla Completa sin bordes</text>
|
|
<text x="730" y="100" text-anchor="middle" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="11.5">• Captura, PTZ, Grabación y Medición</text>
|
|
<text x="730" y="118" text-anchor="middle" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="11.5">• Diálogos hijos en layer "above"</text>
|
|
<text x="730" y="135" text-anchor="middle" fill="#fda4af" font-family="Fira Code, monospace" font-size="10.5">Alt+F4 / F11 / Esc bloqueados</text>
|
|
|
|
<!-- Caso A: Cierre inesperado (Loop de retorno arriba) -->
|
|
<path d="M 730 145 L 730 215 L 423 215 L 423 148" stroke="#f59e0b" stroke-width="2" stroke-dasharray="6 4" fill="none" marker-end="url(#arrow-amber)"/>
|
|
<rect x="465" y="192" width="230" height="44" rx="6" fill="#1f1a14" stroke="#f59e0b" stroke-width="1.2"/>
|
|
<text x="580" y="211" text-anchor="middle" fill="#fcd34d" font-family="Outfit, sans-serif" font-size="12" font-weight="700">¿Cierre inesperado? (Sin STOP_FLAG)</text>
|
|
<text x="580" y="227" text-anchor="middle" fill="#fde68a" font-family="Fira Code, monospace" font-size="10.5">sleep 1 -> Auto-relanza en 1 seg</text>
|
|
|
|
<!-- Caso B: Usuario presiona F1 o Ctrl+Alt+Supr -->
|
|
<line x1="863" y1="90" x2="905" y2="90" stroke="#38bdf8" stroke-width="2" marker-end="url(#arrow-cyan)"/>
|
|
|
|
<rect x="908" y="35" width="180" height="110" rx="10" fill="#1e1b38" stroke="#a855f7" stroke-width="1.8"/>
|
|
<text x="998" y="60" text-anchor="middle" fill="#d8b4fe" font-family="Outfit, sans-serif" font-size="13.5" font-weight="700">4. Acción de Salida</text>
|
|
<text x="998" y="80" text-anchor="middle" fill="#e2e8f0" font-family="Fira Code, monospace" font-size="11">Tecla F1 (Menú Qt)</text>
|
|
<text x="998" y="96" text-anchor="middle" fill="#94a3b8" font-family="Inter, sans-serif" font-size="10.5">o bien</text>
|
|
<text x="998" y="112" text-anchor="middle" fill="#e2e8f0" font-family="Fira Code, monospace" font-size="11">Ctrl+Alt+Supr (GTK3)</text>
|
|
<text x="998" y="132" text-anchor="middle" fill="#6ee7b7" font-family="Inter, sans-serif" font-size="10.5">Diálogo de Confirmación</text>
|
|
|
|
<!-- Flecha hacia abajo desde Paso 4 -->
|
|
<line x1="998" y1="145" x2="998" y2="285" stroke="#10b981" stroke-width="2" marker-end="url(#arrow-emerald)"/>
|
|
|
|
<!-- Paso 5: Escritura de STOP_FLAG -->
|
|
<rect x="740" y="288" width="348" height="135" rx="10" fill="#112e28" stroke="#10b981" stroke-width="1.8"/>
|
|
<text x="914" y="314" text-anchor="middle" fill="#6ee7b7" font-family="Outfit, sans-serif" font-size="14" font-weight="700">5. Señalización Limpia (STOP_FLAG)</text>
|
|
<text x="914" y="336" text-anchor="middle" fill="#e2e8f0" font-family="Fira Code, monospace" font-size="11">Crea /run/user/UID/nasa-kiosk-stopping-UID</text>
|
|
<text x="914" y="358" text-anchor="middle" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="11.5">• Cerrar sesión: openbox --exit + loginctl</text>
|
|
<text x="914" y="378" text-anchor="middle" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="11.5">• Reiniciar: systemctl reboot -i (vía Polkit)</text>
|
|
<text x="914" y="398" text-anchor="middle" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="11.5">• Apagar: systemctl poweroff -i (vía Polkit)</text>
|
|
|
|
<!-- Flecha final hacia LightDM / Apagado -->
|
|
<line x1="740" y1="355" x2="550" y2="355" stroke="#38bdf8" stroke-width="2" marker-end="url(#arrow-cyan)"/>
|
|
|
|
<rect x="240" y="305" width="308" height="100" rx="10" fill="#131c31" stroke="#38bdf8" stroke-width="1.8"/>
|
|
<text x="394" y="334" text-anchor="middle" fill="#7dd3fc" font-family="Outfit, sans-serif" font-size="14" font-weight="700">6. Retorno Inmediato a LightDM</text>
|
|
<text x="394" y="356" text-anchor="middle" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="11.5">El bucle Watchdog detecta STOP_FLAG,</text>
|
|
<text x="394" y="374" text-anchor="middle" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="11.5">finaliza Openbox sin timeouts y vuelve a</text>
|
|
<text x="394" y="392" text-anchor="middle" fill="#fcd34d" font-family="Fira Code, monospace" font-size="11">Slick Greeter (o apaga/reinicia el equipo)</text>
|
|
</svg>
|
|
<div class="diagram-caption">
|
|
Figura 2: Flujo del supervisor (Watchdog) diferenciando un cierre accidental (auto-relanzamiento en 1 s) de una acción de salida confirmada por el operario.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- SECCIÓN 5: GRÁFICO DE LA PARTICIÓN /DATOS Y GUARDIÁN INOTIFY -->
|
|
<section id="proteccion-datos">
|
|
<div class="section-header">
|
|
<div class="section-num">5</div>
|
|
<h2 class="section-title">Gráfico: Relación entre <code>nasa</code> y <code>admin</code> en <code>/datos</code> (Protección Anti-Borrado)</h2>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<p>
|
|
Un requerimiento crítico del sistema es que el usuario <code>nasa</code> pueda <strong>grabar nuevos videos (<code>.mp4</code>), guardar imágenes de mediciones (<code>.png</code>) y crear carpetas</strong> dentro de <code>/datos/NA-SA_Video/<Perfil></code>, pero que <strong>bajo ninguna circunstancia pueda borrar ni sobreescribir</strong> archivos ya generados (ni siquiera desde el cuadro de diálogo de selección de archivos de Qt). Al mismo tiempo, el usuario <code>admin</code> debe tener permisos totales desde XFCE.
|
|
</p>
|
|
|
|
<div class="callout callout-emerald">
|
|
<strong>¿Cómo se resolvió técnicamente?</strong> Combinando permisos UNIX avanzados en los directorios (modo <code>3775</code> = <code>setgid 2000</code> + <code>sticky bit 1000</code> con dueño <code>admin:nasa</code>) junto con el demonio en tiempo real <code>/usr/local/bin/nasa-datos-guard</code> (ejecutado por <code>systemd</code> como root), el cual escucha eventos <code>inotify</code> del kernel Linux.
|
|
</div>
|
|
|
|
<div class="diagram-box">
|
|
<svg class="blueprint" viewBox="0 0 1120 390" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<rect width="1120" height="390" rx="12" fill="url(#bg-grid)"/>
|
|
|
|
<!-- Paso 1: Escritura en curso por nasa -->
|
|
<rect x="35" y="45" width="245" height="135" rx="10" fill="#0b211d" stroke="#10b981" stroke-width="1.8"/>
|
|
<text x="157" y="72" text-anchor="middle" fill="#6ee7b7" font-family="Outfit, sans-serif" font-size="14" font-weight="700">1. Grabación en Curso (nasa)</text>
|
|
<text x="157" y="95" text-anchor="middle" fill="#e2e8f0" font-family="Inter, sans-serif" font-size="11.5">Directorio padre tiene modo 3775</text>
|
|
<text x="157" y="113" text-anchor="middle" fill="#7dd3fc" font-family="Fira Code, monospace" font-size="11">drwxrwsr-t (admin:nasa)</text>
|
|
<text x="157" y="135" text-anchor="middle" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="11">nasa tiene permiso de escritura grupal,</text>
|
|
<text x="157" y="152" text-anchor="middle" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="11">crea el archivo .mp4 / .png y escribe</text>
|
|
|
|
<line x1="280" y1="112" x2="325" y2="112" stroke="#10b981" stroke-width="2" marker-end="url(#arrow-emerald)"/>
|
|
|
|
<!-- Paso 2: Cierre del archivo y Evento Inotify -->
|
|
<rect x="328" y="45" width="245" height="135" rx="10" fill="#1f1a14" stroke="#f59e0b" stroke-width="1.8"/>
|
|
<text x="450" y="72" text-anchor="middle" fill="#fcd34d" font-family="Outfit, sans-serif" font-size="14" font-weight="700">2. Cierre del Archivo (Kernel)</text>
|
|
<text x="450" y="95" text-anchor="middle" fill="#e2e8f0" font-family="Inter, sans-serif" font-size="11.5">Al detener la grabación o guardar</text>
|
|
<text x="450" y="113" text-anchor="middle" fill="#e2e8f0" font-family="Inter, sans-serif" font-size="11.5">la captura, el descriptor se cierra y</text>
|
|
<text x="450" y="134" text-anchor="middle" fill="#fcd34d" font-family="Fira Code, monospace" font-size="11" font-weight="600">Linux emite IN_CLOSE_WRITE</text>
|
|
<text x="450" y="154" text-anchor="middle" fill="#94a3b8" font-family="Fira Code, monospace" font-size="10.5">(o IN_MOVED_TO / IN_CREATE)</text>
|
|
|
|
<line x1="573" y1="112" x2="618" y2="112" stroke="#f59e0b" stroke-width="2" marker-end="url(#arrow-amber)"/>
|
|
|
|
<!-- Paso 3: Demonio nasa-datos-guard -->
|
|
<rect x="621" y="45" width="245" height="135" rx="10" fill="#131c31" stroke="#38bdf8" stroke-width="1.8"/>
|
|
<text x="743" y="72" text-anchor="middle" fill="#7dd3fc" font-family="Outfit, sans-serif" font-size="14" font-weight="700">3. nasa-datos-guard.service</text>
|
|
<text x="743" y="95" text-anchor="middle" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="11.5">Demonio Python3 + ctypes inotify</text>
|
|
<text x="743" y="115" text-anchor="middle" fill="#e2e8f0" font-family="Inter, sans-serif" font-size="11.5">aplica instantáneamente:</text>
|
|
<text x="743" y="136" text-anchor="middle" fill="#6ee7b7" font-family="Fira Code, monospace" font-size="11">chown admin:nasa archivo</text>
|
|
<text x="743" y="155" text-anchor="middle" fill="#6ee7b7" font-family="Fira Code, monospace" font-size="11">chmod 0644 (-rw-r--r--)</text>
|
|
|
|
<line x1="866" y1="112" x2="905" y2="112" stroke="#38bdf8" stroke-width="2" marker-end="url(#arrow-cyan)"/>
|
|
|
|
<!-- Paso 4: Estado Final del Archivo -->
|
|
<rect x="908" y="45" width="180" height="135" rx="10" fill="#1e1b38" stroke="#a855f7" stroke-width="1.8"/>
|
|
<text x="998" y="72" text-anchor="middle" fill="#d8b4fe" font-family="Outfit, sans-serif" font-size="14" font-weight="700">4. Archivo Blindado</text>
|
|
<text x="998" y="96" text-anchor="middle" fill="#ffffff" font-family="Fira Code, monospace" font-size="11">Dueño: admin:nasa</text>
|
|
<text x="998" y="114" text-anchor="middle" fill="#ffffff" font-family="Fira Code, monospace" font-size="11">Modo: 0644</text>
|
|
<text x="998" y="136" text-anchor="middle" fill="#fda4af" font-family="Inter, sans-serif" font-size="11" font-weight="600">Sticky Bit (+t) en carpeta</text>
|
|
<text x="998" y="153" text-anchor="middle" fill="#cbd5e1" font-family="Inter, sans-serif" font-size="10.5">impide borrar a no-dueños</text>
|
|
|
|
<!-- Resultado para cada usuario abajo -->
|
|
<rect x="65" y="225" width="465" height="125" rx="10" fill="#112e28" stroke="#10b981" stroke-width="1.5"/>
|
|
<text x="297" y="252" text-anchor="middle" fill="#6ee7b7" font-family="Outfit, sans-serif" font-size="14" font-weight="700">Efecto en Sesión "nasa" (Operario)</text>
|
|
<text x="297" y="276" text-anchor="middle" fill="#e2e8f0" font-family="Inter, sans-serif" font-size="12">• Puede reproducir todos los videos desde el Reproductor integrado.</text>
|
|
<text x="297" y="297" text-anchor="middle" fill="#e2e8f0" font-family="Inter, sans-serif" font-size="12">• Puede seguir creando carpetas y nuevas grabaciones sin límite.</text>
|
|
<text x="297" y="320" text-anchor="middle" fill="#fda4af" font-family="Inter, sans-serif" font-size="12" font-weight="600">• PROHIBIDO borrar, renombrar o pisar archivos cerrados (EACCES/EPERM).</text>
|
|
|
|
<rect x="585" y="225" width="465" height="125" rx="10" fill="#0f1b2d" stroke="#38bdf8" stroke-width="1.5"/>
|
|
<text x="817" y="252" text-anchor="middle" fill="#7dd3fc" font-family="Outfit, sans-serif" font-size="14" font-weight="700">Efecto en Sesión "admin" (XFCE / Thunar)</text>
|
|
<text x="817" y="276" text-anchor="middle" fill="#e2e8f0" font-family="Inter, sans-serif" font-size="12">• Es el propietario directo (admin) de las carpetas (3775) y archivos (0644).</text>
|
|
<text x="817" y="297" text-anchor="middle" fill="#e2e8f0" font-family="Inter, sans-serif" font-size="12">• Ve la partición "Datos" y "Grabaciones NASA" en el panel lateral de Thunar.</text>
|
|
<text x="817" y="320" text-anchor="middle" fill="#6ee7b7" font-family="Inter, sans-serif" font-size="12" font-weight="600">• Permiso total para organizar, exportar a USB o eliminar grabaciones antiguas.</text>
|
|
</svg>
|
|
<div class="diagram-caption">
|
|
Figura 3: Mecanismo de protección automática "Write-Only / No-Delete" sobre /datos mediante el servicio systemd nasa-datos-guard.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- SECCIÓN 6: TECNOLOGÍAS UTILIZADAS -->
|
|
<section id="tecnologias">
|
|
<div class="section-header">
|
|
<div class="section-num">6</div>
|
|
<h2 class="section-title">Stack de Tecnologías Utilizadas en el Proyecto</h2>
|
|
</div>
|
|
|
|
<div class="tech-grid">
|
|
<div class="tech-item">
|
|
<span class="tech-tag badge-cyan">Sistema Operativo & Display</span>
|
|
<h4>Debian 13 (Trixie) + X11 / Xorg</h4>
|
|
<p>Base Linux estable de 64 bits ejecutando servidor gráfico Xorg en modo de sesión única (<code>allow-user-switching=false</code>) con flags <code>BlankTime 0</code> y <code>DPMS false</code>.</p>
|
|
</div>
|
|
|
|
<div class="tech-item">
|
|
<span class="tech-tag badge-amber">Gestor de Inicio de Sesión</span>
|
|
<h4>LightDM + Slick Greeter + C Hook</h4>
|
|
<p>Pantalla de login personalizada con imagen de fondo institucional, script de preselección de usuario (<code>nasa</code>) y biblioteca en C (<code>slick-greeter-filter-a11y.so</code>) inyectada vía <code>LD_PRELOAD</code>.</p>
|
|
</div>
|
|
|
|
<div class="tech-item">
|
|
<span class="tech-tag badge-cyan">Escritorio Administrador</span>
|
|
<h4>XFCE 4 + Thunar + xfconf</h4>
|
|
<p>Entorno de escritorio ligero y completo para la cuenta <code>admin</code>, configurado con <code>vblank_mode=xpresent</code> en <code>xfwm4</code> y montaje visible de <code>/datos</code> vía <code>x-gvfs-show</code>.</p>
|
|
</div>
|
|
|
|
<div class="tech-item">
|
|
<span class="tech-tag badge-emerald">Gestor de Ventanas Kiosco</span>
|
|
<h4>Openbox 3.4 (Modo Aislado)</h4>
|
|
<p>Gestor de ventanas minimalista para la cuenta <code>nasa</code>, configurado mediante <code>/etc/xdg/nasa-video-kiosk/rc.xml</code> sin bordes de ventana ni menús de sistema.</p>
|
|
</div>
|
|
|
|
<div class="tech-item">
|
|
<span class="tech-tag badge-purple">Aplicación Principal</span>
|
|
<h4>C++17 + Qt 6 + CMake</h4>
|
|
<p>Interfaz gráfica nativa (<code>Qt6::Widgets</code>, <code>Qt6::OpenGLWidgets</code>, <code>Qt6::Multimedia</code>, <code>Qt6::SerialPort</code>) con traducción oficial al español (<code>qtbase_es.qm</code>) y estilos <code>styles.qss</code>.</p>
|
|
</div>
|
|
|
|
<div class="tech-item">
|
|
<span class="tech-tag badge-rose">Video & Aceleración GPU</span>
|
|
<h4>Magewell SDK + FFmpeg NVDEC + CUDA</h4>
|
|
<p>Captura industrial de baja latencia con <code>libMWCapture.so</code>, decodificación de video por hardware NVIDIA (NVDEC) e interoperabilidad <strong>Zero-Copy CUDA-OpenGL</strong>.</p>
|
|
</div>
|
|
|
|
<div class="tech-item">
|
|
<span class="tech-tag badge-cyan">Visión Artificial & Control</span>
|
|
<h4>OpenCV + RS-485 (Pelco-D / PTZ)</h4>
|
|
<p>Módulo de calibración con patrón damero y medición geométrica en pantalla sobre fotogramas en vivo, más panel virtual de controlador serie RS-485.</p>
|
|
</div>
|
|
|
|
<div class="tech-item">
|
|
<span class="tech-tag badge-emerald">Servicios de Kiosco & Seguridad</span>
|
|
<h4>Python 3 + PyGObject (GTK3) + Inotify + Polkit</h4>
|
|
<p>Panel de salida con diálogos nativos <code>libxfce4ui-2</code>, demonio guardián de archivos con <code>inotify</code> sobre <code>libc.so.6</code> y reglas <code>polkit-1</code> para apagado/reinicio sin root.</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- SECCIÓN 7: SCRIPTS Y COMANDOS CLAVE -->
|
|
<section id="comandos">
|
|
<div class="section-header">
|
|
<div class="section-num">7</div>
|
|
<h2 class="section-title">Scripts de Generación, Despliegue y Diagnóstico</h2>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3>1. Compilar y Desplegar Cambios al Modo Kiosco (<code>deploy_kiosk.sh</code>)</h3>
|
|
<p>
|
|
Desde la sesión <code>admin</code>, este comando compila el proyecto en C++ y actualiza automáticamente el binario, las librerías, las reglas de Openbox, los permisos de <code>/datos</code> y la sesión del usuario <code>nasa</code>:
|
|
</p>
|
|
<div class="code-block">
|
|
<div class="code-header">
|
|
<span>bash - Compilación y despliegue directo al kiosco</span>
|
|
<button class="copy-btn" onclick="copyCode(this)">Copiar comando</button>
|
|
</div>
|
|
<pre><code>/home/admin/repos/nasa_video/deploy_kiosk.sh</code></pre>
|
|
</div>
|
|
|
|
<h3>2. Verificar el Estado Integral del Kiosco (<code>prepare_kiosk_test.sh --check</code>)</h3>
|
|
<p>
|
|
Permite comprobar en cualquier momento la cuenta <code>nasa</code>, qué binario o AppImage está activo, el estado de Openbox, Slick Greeter, el servicio guardián <code>nasa-datos-guard.service</code> y las últimas líneas del log <code>~nasa/.local/state/nasa-video/kiosk.log</code>:
|
|
</p>
|
|
<div class="code-block">
|
|
<div class="code-header">
|
|
<span>bash - Diagnóstico de configuración</span>
|
|
<button class="copy-btn" onclick="copyCode(this)">Copiar comando</button>
|
|
</div>
|
|
<pre><code>sudo /home/admin/repos/nasa_video/prepare_kiosk_test.sh --check</code></pre>
|
|
</div>
|
|
|
|
<h3>3. Configurar o Reinstalar la Sesión Kiosco Manualmente</h3>
|
|
<p>
|
|
El script maestro admite instalar tanto el binario compilado actual como un paquete autónomo <code>.AppImage</code> (generado con <code>build_appimage.sh</code>), además de configurar Slick Greeter y su filtro de accesibilidad en español:
|
|
</p>
|
|
<div class="code-block">
|
|
<div class="code-header">
|
|
<span>bash - Aprovisionamiento completo del kiosco y greeter</span>
|
|
<button class="copy-btn" onclick="copyCode(this)">Copiar comandos</button>
|
|
</div>
|
|
<pre><code># Instalar el binario compilado y configurar toda la sesión kiosco para nasa
|
|
sudo /home/admin/repos/nasa_video/prepare_kiosk_test.sh --setup /home/admin/repos/nasa_video/build/nasa_video
|
|
|
|
# Instalar y configurar Slick Greeter en LightDM con fondo corporativo
|
|
sudo /home/admin/repos/nasa_video/prepare_kiosk_test.sh --install-greeter
|
|
|
|
# Compilar e inyectar el filtro de idioma español y accesibilidad para Slick Greeter
|
|
/home/admin/repos/nasa_video/deploy_filter_a11y.sh</code></pre>
|
|
</div>
|
|
|
|
<h3>4. Script de Emergencia / Restauración de Sesiones (<code>restore_greeter.sh</code>)</h3>
|
|
<p>
|
|
Si por alguna prueba manual se alteraran las sesiones por defecto de LightDM o <code>AccountsService</code>, este script restaura <code>nasa</code> al modo kiosco (<code>nasa-video-kiosk</code>) y <code>admin</code> a su escritorio <code>xfce</code>:
|
|
</p>
|
|
<div class="code-block">
|
|
<div class="code-header">
|
|
<span>bash - Restauración de sesiones</span>
|
|
<button class="copy-btn" onclick="copyCode(this)">Copiar comando</button>
|
|
</div>
|
|
<pre><code>sudo /home/admin/repos/nasa_video/restore_greeter.sh</code></pre>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<footer>
|
|
<p>Documentación Técnica de Arquitectura Gráfica y Modo Kiosco — Proyecto <strong>NA-SA Video Capture</strong> sobre Debian 13 (Trixie)</p>
|
|
<p style="margin-top: 0.35rem;">Ubicación del documento: <code>/home/sebastian/repos/Interfaz_grafica_SO_video_nasa/index.html</code></p>
|
|
</footer>
|
|
|
|
</div>
|
|
|
|
<script>
|
|
function copyCode(btn) {
|
|
const pre = btn.closest('.code-block').querySelector('pre');
|
|
const text = pre ? pre.innerText : '';
|
|
navigator.clipboard.writeText(text).then(() => {
|
|
const original = btn.innerText;
|
|
btn.innerText = '¡Copiado!';
|
|
btn.style.background = '#10b981';
|
|
btn.style.color = '#06101f';
|
|
setTimeout(() => {
|
|
btn.innerText = original;
|
|
btn.style.background = '';
|
|
btn.style.color = '';
|
|
}, 1800);
|
|
});
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|