diff --git a/DESPLIEGUE.md b/DESPLIEGUE.md index d839fce..6ba6fe5 100644 --- a/DESPLIEGUE.md +++ b/DESPLIEGUE.md @@ -98,6 +98,42 @@ sudo cut -d: -f1 /etc/nginx/hbox-docs.htpasswd # lista de usuarios Administradores (quién puede borrar o reabrir actas) = variable `ACTAS_ADMINS` del servicio, hoy `leo`. Alan y Daniel quedan como técnicos: llenan y envían, no borran. +### 7 · Permisos para que los técnicos cambien su contraseña (una sola vez) + +La página **Mi cuenta** (`/cuenta.html`) deja que cada quien cambie su propia contraseña, y que el +administrador restablezca la de otro. Para eso el servicio tiene que poder **escribir** el archivo de +usuarios que nginx solo **lee**: + +```bash +# quién es el usuario de nginx (normalmente www-data) +grep -E "^\s*user" /etc/nginx/nginx.conf + +sudo chown leo:www-data /etc/nginx/hbox-docs.htpasswd +sudo chmod 640 /etc/nginx/hbox-docs.htpasswd +sudo systemctl restart actas-hbox +``` + +Así: **leo** (el servicio) escribe, **www-data** (nginx) lee, y nadie más puede ni leerlo. + +Comprueba que las contraseñas estén en el formato que el servicio sabe verificar: + +```bash +sudo cut -d: -f2 /etc/nginx/hbox-docs.htpasswd | cut -c1-6 +``` + +Todas deben decir `$apr1$`. Si alguna sale distinta (`$2y$` es bcrypt), esa persona no va a poder +cambiar la suya sola: restablécesela desde la propia página, que la vuelve a guardar en `$apr1$`. + +!!! note "Por qué no se usa el comando `htpasswd` desde el servicio" + Pasar una contraseña como argumento (`htpasswd -b … clave`) la deja visible en `ps` para + cualquiera con sesión en el servidor. El hash `$apr1$` se calcula dentro del proceso; está + verificado carácter por carácter contra la salida de `htpasswd`, incluyendo acentos y espacios. + +!!! tip "Al cambiar la contraseña, la sesión no se cae" + HTTP Basic se guarda en el navegador: quien cambie la suya sigue navegando con la anterior hasta + que cierre sesión o cierre el navegador. La página lo explica y ofrece la liga de **Salir** para + probarla de inmediato. No es un error. + --- ## B · Verificación después de desplegar @@ -158,3 +194,5 @@ rsync -az leo@git.helgen.online:/srv/projects/drogheda/adjuntos/ ~/respaldo-foto | Las fotos se ven rotas en el tablero | falta la carpeta `adjuntos` o su permiso | paso 3 | | `mkdocs build --strict` falla | un enlace del `nav` apunta a un archivo que no existe | revisa `mkdocs.yml` | | El técnico no puede entrar | usuario no creado, o se usó `htpasswd -c` y borró a los demás | paso 5 | +| «El servicio no tiene permiso de escribir el archivo de usuarios» | falta el `chown`/`chmod` del htpasswd | paso 7 | +| «Tu contraseña está guardada en un formato que no puedo verificar» | esa entrada es bcrypt, no `$apr1$` | restablecerla desde `/cuenta.html` como administrador | diff --git a/backend/actas-hbox.service b/backend/actas-hbox.service index d826880..c55df89 100644 --- a/backend/actas-hbox.service +++ b/backend/actas-hbox.service @@ -12,6 +12,8 @@ Environment=ADJUNTO_MAX_MB=8 Environment=ARCHIVO_MAX_MB=20 Environment=ACTAS_REPETIBLES=diagnostico-campo,instalacion-campo Environment=ACTAS_ADMINS=leo +Environment=HTPASSWD_FILE=/etc/nginx/hbox-docs.htpasswd +Environment=PASS_MIN=8 Environment=PORT=8081 ExecStart=/srv/projects/drogheda/hbox-docs/backend/venv/bin/gunicorn -w 2 -b 127.0.0.1:8081 app:app Restart=on-failure diff --git a/backend/app.py b/backend/app.py index 91733f8..44a1f53 100644 --- a/backend/app.py +++ b/backend/app.py @@ -26,7 +26,7 @@ Rutas: Actas compuestas (integracion, ensamble): traen d["componentes"] = {clave: serie_modulo}. En los tipos de TIPOS_UNICOS un módulo no puede aparecer en dos actas reales (409). """ -import os, re, json, csv, datetime, uuid +import os, re, json, csv, datetime, uuid, hashlib from flask import Flask, request, jsonify, abort, send_file app = Flask(__name__) @@ -435,5 +435,131 @@ def _muy_grande(e): f"logs: máximo {LOG_MAX_MB} MB)."), 413 +# ------------------------------------------------- contraseñas (HTTP Basic de nginx) +# El archivo de usuarios de nginx se escribe aquí mismo, sin invocar `htpasswd`: +# pasar una contraseña como argumento de un proceso la deja visible en `ps`. +HTPASSWD = os.environ.get("HTPASSWD_FILE", "/etc/nginx/hbox-docs.htpasswd") +PASS_MIN = int(os.environ.get("PASS_MIN", "8")) +ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + + +def _to64(v, n): + return "".join(ITOA64[(v >> (6 * i)) & 0x3F] for i in range(n)) + + +def apr1(password, salt): + """Hash Apache MD5 ($apr1$): lo que escribe htpasswd por defecto y lo que lee nginx.""" + pw = password.encode("utf-8") + sl = salt.encode("ascii") + ctx = hashlib.md5(pw + b"$apr1$" + sl) + final = hashlib.md5(pw + sl + pw).digest() + i = len(pw) + while i > 0: + ctx.update(final[:16] if i > 16 else final[:i]); i -= 16 + i = len(pw) + while i: + ctx.update(b"\0" if (i & 1) else pw[:1]); i >>= 1 + final = ctx.digest() + for i in range(1000): + c = hashlib.md5() + c.update(pw if (i & 1) else final) + if i % 3: c.update(sl) + if i % 7: c.update(pw) + c.update(final if (i & 1) else pw) + final = c.digest() + out = "".join(_to64((final[a] << 16) | (final[b] << 8) | final[c], 4) + for a, b, c in ((0, 6, 12), (1, 7, 13), (2, 8, 14), (3, 9, 15), (4, 10, 5))) + return "$apr1$" + salt + "$" + out + _to64(final[11], 2) + + +def _leer_htpasswd(): + if not os.path.isfile(HTPASSWD): + return None + with open(HTPASSWD, encoding="utf-8") as f: + return f.read().splitlines() + + +def _escribir_htpasswd(lineas): + """Reescribe el archivo de forma atómica, conservando permisos y dueño.""" + carpeta = os.path.dirname(HTPASSWD) or "." + st = os.stat(HTPASSWD) + tmp = os.path.join(carpeta, ".htpasswd.tmp-" + uuid.uuid4().hex[:8]) + with open(tmp, "w", encoding="utf-8") as f: + f.write("\n".join(lineas) + "\n") + os.chmod(tmp, st.st_mode & 0o7777) + try: + os.chown(tmp, st.st_uid, st.st_gid) + except PermissionError: + pass + os.replace(tmp, HTPASSWD) + + +@app.get("/api/usuarios") +def usuarios(): + """Lista de usuarios (solo administrador), para el restablecimiento.""" + if not is_admin(): + return jsonify(ok=False, error="Solo un administrador puede ver la lista."), 403 + lineas = _leer_htpasswd() + if lineas is None: + return jsonify(ok=False, error="No encuentro el archivo de usuarios."), 500 + return jsonify(ok=True, usuarios=sorted(l.split(":", 1)[0] for l in lineas if ":" in l)) + + +@app.post("/api/password") +def cambiar_password(): + yo = current_user() + if not yo: + return jsonify(ok=False, error="No puedo identificarte. Vuelve a iniciar sesión."), 403 + try: + d = request.get_json(force=True) or {} + except Exception: + return jsonify(ok=False, error="JSON inválido"), 400 + + destino = str(d.get("usuario") or yo).strip() + actual = str(d.get("actual") or "") + nueva = str(d.get("nueva") or "") + confirma = str(d.get("confirma") or "") + es_reset = (destino.lower() != yo.lower()) + + if es_reset and not is_admin(): + return jsonify(ok=False, error="Solo puedes cambiar tu propia contraseña."), 403 + if len(nueva) < PASS_MIN: + return jsonify(ok=False, error=f"La nueva contraseña debe tener al menos {PASS_MIN} caracteres."), 400 + if nueva != confirma: + return jsonify(ok=False, error="Las dos contraseñas nuevas no coinciden."), 400 + if not es_reset and nueva == actual: + return jsonify(ok=False, error="La nueva contraseña es igual a la actual."), 400 + + lineas = _leer_htpasswd() + if lineas is None: + return jsonify(ok=False, error="No encuentro el archivo de usuarios en el servidor."), 500 + + idx = next((i for i, l in enumerate(lineas) + if ":" in l and l.split(":", 1)[0] == destino), None) + if idx is None: + return jsonify(ok=False, error=f"El usuario {destino} no existe."), 404 + + guardado = lineas[idx].split(":", 1)[1] + if not es_reset: + partes = guardado.split("$") + if not guardado.startswith("$apr1$") or len(partes) < 4: + return jsonify(ok=False, error="Tu contraseña está guardada en un formato que este " + "servicio no puede verificar. Pide a Leo que la restablezca."), 400 + if apr1(actual, partes[2]) != guardado: + return jsonify(ok=False, error="La contraseña actual no es correcta."), 403 + + salt = "".join(ITOA64[b % 64] for b in os.urandom(8)) + lineas[idx] = destino + ":" + apr1(nueva, salt) + try: + _escribir_htpasswd(lineas) + except PermissionError: + return jsonify(ok=False, error="El servicio no tiene permiso de escribir el archivo de " + "usuarios. Avisa a Leo (permisos de hbox-docs.htpasswd)."), 500 + except OSError as e: + return jsonify(ok=False, error="No se pudo guardar: " + str(e)), 500 + + return jsonify(ok=True, usuario=destino, reset=es_reset) + + if __name__ == "__main__": app.run(host="127.0.0.1", port=int(os.environ.get("PORT", "8081"))) diff --git a/docs/cuenta.html b/docs/cuenta.html new file mode 100644 index 0000000..7f78b1c --- /dev/null +++ b/docs/cuenta.html @@ -0,0 +1,183 @@ + + + + + +Mi cuenta — HBOX + + + + +
+
+

Mi cuenta

+

Aquí cambias tu contraseña de acceso al sitio.

+
+
+ ← Documentación + Cerrar sesión +
+ +
Consultando quién eres…
+ +
+

Cambiar mi contraseña

+

Elige algo que recuerdes sin apuntarlo. Mínimo 8 caracteres.

+
+ + +
+
+ + +
+
Mientras más larga, mejor. Una frase con espacios funciona y se recuerda.
+
+
+ + + 👁 Ver lo que escribí +
+ +
+
+ + + +
+

Si olvidaste tu contraseña

+

+ No hay recuperación por correo: pídele a Leo que te la restablezca desde esta misma página. + Es cosa de un minuto. +

+
+
+ + + + diff --git a/docs/descargas/SHA256SUMS.txt b/docs/descargas/SHA256SUMS.txt index eef56a1..8c0bf9b 100644 --- a/docs/descargas/SHA256SUMS.txt +++ b/docs/descargas/SHA256SUMS.txt @@ -1 +1 @@ -a8de74b3d7768e9d5656ae0bff05475445c0cd2599ecfdc4ab081e517ed3d6ef hbox-v5-bringup_0.4.0.bin +98656ddcc4e209e291d554341318c74d3f05713ce7198c7f6dc2d816eb3c6c3f hbox-v5-bringup_0.5.0.bin diff --git a/docs/descargas/hbox-v5-bringup-README.md b/docs/descargas/hbox-v5-bringup-README.md index 9eb1cbe..6954428 100644 --- a/docs/descargas/hbox-v5-bringup-README.md +++ b/docs/descargas/hbox-v5-bringup-README.md @@ -1,7 +1,7 @@ # hbox_v5_bringup — EinarBoard v5 first-flash bring-up firmware Bench-proves a newly assembled v5 board over USB-C **J11** only. Never powers the RTK stack. -0.4.0 field-minimum: AUTO by default (stack self-powers with 5 V on P2, kept on through 5 V loss), watchdog, fan, link recovery, LEDs; charge OFF. Bench mode: `P`+`Y` stack ON/OFF, `n` NMEA monitor (fix 4 = RTK FIX). Console (0.2.1): CR+LF lines, `EVT` on every state change, named `STAT` every 5 s, `$PHLG` every 10 s in the fleet v3.x layout (server-parseable). +0.5.0: Modo B in-band $PHLG (server Salud column) on top of the 0.4.0 field-minimum: AUTO by default (stack self-powers with 5 V on P2, kept on through 5 V loss), watchdog, fan, link recovery, LEDs; charge OFF. Bench mode: `P`+`Y` stack ON/OFF, `n` NMEA monitor (fix 4 = RTK FIX). Console (0.2.1): CR+LF lines, `EVT` on every state change, named `STAT` every 5 s, `$PHLG` every 10 s in the fleet v3.x layout (server-parseable). Checks: HSE 25 MHz + USB CDC · LSE Y4 · I2C: PCF8574 0x20 / SHT40 0x44 / TMP102 0x48 / SC16IS752 0x4D · gauge + RGB LED walk · ADC · digital inputs. Prints PASS/FAIL, then a `STAT` line every 2 s. Console commands: `r` rerun · `g` gauge walk · `i` I2C scan · `h` help. @@ -23,14 +23,15 @@ generic variant defaults to HSI, which is not accurate enough for USB. ## Flash (DFU, J11) Hold **SW2** (BOOT0) → tap **SW1** (RESET) → release SW2 → device `0483:DF11` appears. ```bash -dfu-util -a 0 -s 0x08000000:leave -D release/hbox-v5-bringup_0.4.0.bin +dfu-util -a 0 -s 0x08000000:leave -D release/hbox-v5-bringup_0.5.0.bin ``` -or STM32CubeProgrammer → USB → Connect → Download `release/hbox-v5-bringup_0.4.0.bin` @ `0x08000000`. +or STM32CubeProgrammer → USB → Connect → Download `release/hbox-v5-bringup_0.5.0.bin` @ `0x08000000`. ## Release | File | Version | SHA-256 (first 16) | Size | |---|---|---|---| -| **`release/hbox-v5-bringup_0.4.0.bin`** | **0.4.0 (2026-09-17) — USE THIS (field-minimum, AUTO by default)** | `a8de74b3d7768e9d` | 75 524 B | +| **`release/hbox-v5-bringup_0.5.0.bin`** | **0.5.0 (2026-09-18) — USE THIS (field-minimum + Modo B telemetry)** | `98656ddcc4e209e2` | 77 312 B | +| `release/superseded/hbox-v5-bringup_0.4.0.bin` | 0.4.0 — superseded (no in-band telemetry) | `a8de74b3d7768e9d` | 75 524 B | | `release/superseded/hbox-v5-bringup_0.3.0.bin` | 0.3.0 — superseded (AUTO opt-in, no watchdog/fan/recovery) | `d4608c739cef2661` | 72 860 B | | `release/superseded/hbox-v5-bringup_0.2.1.bin` | 0.2.1 — superseded (no AUTO mode; stack OFF on 5 V loss) | `78b34f4603550c05` | 70 084 B | | `release/superseded/hbox-v5-bringup_0.2.0.bin` | 0.2.0 — superseded (LF-only console, no EVT/$PHLG) | `8491625d494f9ee1` | 64 780 B | @@ -38,6 +39,14 @@ or STM32CubeProgrammer → USB → Connect → Download `release/hbox-v5-bringup | `release/hbox-v5-bringup_0.1.0.bin` | 0.1.0 — SUPERSEDED (no float printf, ETH_CS driven) | `1a9a77ae479c8f86` | 41 040 B | ## Changelog +- **0.5.0** (2026-09-18) — **Modo B: `$PHLG` in band.** Once the stack is on and the F9P has been talking for 10 s, USART1 + (PA10 tap / PA9) is started **before** K1 (PB5) is energised; the F9P TX2 stream then flows F9P → PA10 → MCU → PA9 → K1 NO → modem DIN + byte for byte, and a `$PHLG` (same 24 fields) is injected every 30 s only after > 8 ms of line idle (a GGA is never split). + Corrections modem → F9P stay on their direct wire. Fail-safe is hardware: PB5 low (reset, IWDG, any stack-off) = K1 NC = direct path. + Prerequisites shipped with it: **256-byte UART rings** (`build_opt.h`, `static_assert`ed at compile), **non-blocking SHT40** + (two-phase kick/poll), console STAT/`$PHLG` deferred to line-idle gaps, K1 released before `EEPROM.write` (flash erase stalls the core) + and before the `r` self-tests. `B` toggles Modo B (default allowed). `STAT` adds `modoB= relay= phlg_aire=`. + Server: no change needed — `retranslator._parse_phlg` already accepts the sentence; units get the **Salud** column. - **0.4.0** (2026-09-17) — **field-minimum ("-fm")**: what a unit needs to be left on a machine for days **without the production charge governor**. **AUTO is now the default** (only the flash byte `0x5A` means MANUAL; a virgin board powers the stack by itself). IWDG 16 s watchdog · fan policy = v3.0.3 (vehicle 5 V+ign → 100 %; battery → thermostat 48/45 C on the hottest sensor) · diff --git a/docs/descargas/hbox-v5-bringup_0.4.0.bin b/docs/descargas/hbox-v5-bringup_0.5.0.bin similarity index 57% rename from docs/descargas/hbox-v5-bringup_0.4.0.bin rename to docs/descargas/hbox-v5-bringup_0.5.0.bin index 7939648..3288d08 100644 Binary files a/docs/descargas/hbox-v5-bringup_0.4.0.bin and b/docs/descargas/hbox-v5-bringup_0.5.0.bin differ diff --git a/docs/descargas/index.md b/docs/descargas/index.md index 22df8b6..cd875e3 100644 --- a/docs/descargas/index.md +++ b/docs/descargas/index.md @@ -7,30 +7,34 @@ Archivos que el técnico necesita en el banco. Verificar el SHA-256 antes de fla | Archivo | Versión | SHA-256 | Uso | |---|---|---|---| -| [**hbox-v5-bringup_0.4.0.bin**](hbox-v5-bringup_0.4.0.bin) | **0.4.0** (2026-09-17) | `a8de74b3d7768e9d…` ([SHA256SUMS](SHA256SUMS.txt)) | Sección 5 del [procedimiento de prueba y flasheo v5](../procedimientos/v5-prueba-y-flasheo.md) y sección 5 del [ensamble](../procedimientos/v5-ensamble.md) (modo de banco `P` / `n`) | +| [**hbox-v5-bringup_0.5.0.bin**](hbox-v5-bringup_0.5.0.bin) | **0.5.0** (2026-09-18) | `98656ddcc4e209e2…` ([SHA256SUMS](SHA256SUMS.txt)) | Sección 5 del [procedimiento de prueba y flasheo v5](../procedimientos/v5-prueba-y-flasheo.md) y sección 5 del [ensamble](../procedimientos/v5-ensamble.md) (modo de banco `P` / `n`) | Flasheo por DFU en **J11** (mantener **SW2**, pulsar y soltar **SW1**, soltar SW2): ```bash -dfu-util -a 0 -s 0x08000000:leave -D hbox-v5-bringup_0.4.0.bin +dfu-util -a 0 -s 0x08000000:leave -D hbox-v5-bringup_0.5.0.bin ``` o con **STM32CubeProgrammer** → USB → Connect → Download del `.bin` en `0x08000000`. -!!! note "Tarjetas ya flasheadas con 0.1.1 / 0.2.0 / 0.2.1 / 0.3.0" - Re-flashear con 0.4.0 por el mismo procedimiento DFU. **La primera línea de la consola tras reset dice la versión** - (`hbox-v5-bringup 0.4.0 built …`): si la línea `STAT` no termina en `stack=…`, la tarjeta sigue con 0.1.1. +!!! note "Tarjetas ya flasheadas con cualquier versión anterior" + Re-flashear con 0.5.0 por el mismo procedimiento DFU. **La primera línea de la consola tras reset dice la versión** + (`hbox-v5-bringup 0.5.0 built …`): si la línea `STAT` no termina en `stack=…`, la tarjeta sigue con 0.1.1. -!!! tip "Consola 0.4.0" +!!! tip "Consola 0.5.0" Líneas `EVT` en cada cambio (stack, ignición, 5 V, cargador, NMEA, fix), `STAT` con nombres cada 5 s y `$PHLG` cada 10 s (misma trama de salud que lee el servidor). Teclear `l` para la leyenda y `v` para los puntos de medición de la etapa RTK. Para encender la etapa RTK: `P` y luego `Y` (requiere 5 V en P2). -!!! warning "0.4.0 = firmware de campo mínimo — AUTO de fábrica" +!!! warning "0.5.0 = firmware de campo mínimo + telemetría en banda — AUTO de fábrica" Desde 0.4.0 el modo AUTO es el **de fábrica**: la etapa RTK se enciende sola 3 s después de ver 5 V en P2 — no hace falta consola ni teclear `A`. Incluye watchdog 16 s, ventilador (política v3.0.3), recuperación de enlace (ciclo de etapa si el F9P deja de hablar 60 s; LIMP tras 3 ciclos), LEDs de carga y color de estado, corte térmico 60 °C y corte de batería 3.40 V. - **El cargador sigue APAGADO: el paquete es de un solo uso hasta el firmware de producción.** Anotarlo en el acta de la unidad. Si se pierde el 5 V, la etapa **sigue encendida desde la batería** + **El cargador sigue APAGADO: el paquete es de un solo uso hasta el firmware de producción.** Anotarlo en el acta de la unidad. + + **0.5.0 — Modo B:** 10 s después de que el F9P empieza a hablar, el MCU conmuta K1 y la trama `$PHLG` viaja al servidor + cada 30 s junto con el NMEA (columna **Salud** del monitor). En consola: `STAT … modoB=ON relay=… phlg_aire=…` (debe subir de + 1 en 1 cada 30 s). Si el MCU falla, K1 regresa solo al paso directo F9P→módem. `B` lo bloquea/permite para pruebas. Si se pierde el 5 V, la etapa **sigue encendida desde la batería** y la consola registra `EVT BACKUP inicio` / `BACKUP fin` con duración y tramas NMEA: esa es la prueba de respaldo. Se apaga sola si vbat < 3.40 V o temperatura > 50 °C. `A` de nuevo regresa a MANUAL. El cargador sigue apagado en todos los modos. diff --git a/docs/index.md b/docs/index.md index 81875e7..1f0691b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -109,6 +109,14 @@ Sitio interno de Helgen Technologies. **Busca abajo lo que vas a hacer hoy.** [Índice de actas](actas/index.md) · [Tablero de producción](tablero.html) +- ### 👤 Mi cuenta + + --- + + Cambiar tu contraseña del sitio. Si la olvidaste, Leo te la restablece desde ahí mismo. + + [Cambiar mi contraseña](cuenta.html) + - ### 🌿 Git y archivos de diseño --- diff --git a/docs/procedimientos/v5-ensamble.md b/docs/procedimientos/v5-ensamble.md index c4bc6f0..6002551 100644 --- a/docs/procedimientos/v5-ensamble.md +++ b/docs/procedimientos/v5-ensamble.md @@ -53,7 +53,7 @@ si el módulo ya está asignado. | Ítem | Notas | |---|---| | Gabinete HBOX con panel perforado (GX16-5, 3 × SMA, RJ45, prensaestopas) | según el diseño mecánico vigente | -| EinarBoard **V5-NN** aprobada, con firmware de bring-up **0.4.0 o superior** | ver acta de tarjeta | +| EinarBoard **V5-NN** aprobada, con firmware de bring-up **0.5.0 o superior** | ver acta de tarjeta | | simpleRTK2B Pro **ARD-NNN** y módem 4G NTRIP Master **RTK-NNNN** aprobados e integrados | con sus bolsas | | Fuente **Mean Well SD-15B-05** (24 V → 5 V) | va dentro del HBOX | | Pack de batería **1S4P** con NTC (3 hilos → P4) | conectar al final | diff --git a/docs/procedimientos/v5-prueba-final-unidad.md b/docs/procedimientos/v5-prueba-final-unidad.md index f06fd9b..ed10ded 100644 --- a/docs/procedimientos/v5-prueba-final-unidad.md +++ b/docs/procedimientos/v5-prueba-final-unidad.md @@ -1,13 +1,13 @@ -# HBOX v5 — Prueba final de unidad ensamblada con firmware 0.4.0 (field-minimum) +# HBOX v5 — Prueba final de unidad ensamblada con firmware 0.5.0 (field-minimum + telemetría) **Alcance:** unidad completa (EinarBoard V5 + ArduSimple + módem 4G + batería + antenas) dentro del HBOX, antes de embarcar. -**Firmware:** `hbox-v5-bringup_0.4.0.bin` (SHA-256 `a8de74b3…`) — descarga en . +**Firmware:** `hbox-v5-bringup_0.5.0.bin` (SHA-256 `98656ddc…`) — descarga en . **Duración:** ~45 min por unidad (P1–P6). Registrar todo en el acta de ensamble (`HBOX5-Exx-Axxx-Rxxxx`). -!!! warning "Lo que 0.4.0 NO hace" +!!! warning "Lo que 0.5.0 NO hace" **No carga la batería** (cargador apagado). El paquete es de un solo uso: sostiene la unidad cuando se va el 5 V del vehículo hasta 3.40 V y después la unidad solo funciona con alimentación del vehículo. Las unidades regresan a laptop (DFU en J11, 2 min) - cuando salga el firmware de producción. Anotar en el acta: *«fw 0.4.0-fm, cargador OFF»*. + cuando salga el firmware de producción. Anotar en el acta: *«fw 0.5.0-fm, cargador OFF»*. ## 0. Preparación - Consola: cable USB-C en **J11**, PuTTY/CoolTerm **115200**. Cada línea es `STAT`, `EVT` o `$PHLG`; teclear `l` para la leyenda. @@ -20,7 +20,7 @@ Energizar 24 V (con ignición) y **no tocar la consola**. | Esperado | Si falla | |---|---| -| Banner `hbox-v5-bringup 0.4.0` · `modo=AUTO` · `inputs at boot: v5=5.2–5.4V(ok) ign=ON` | otra versión → re-flashear; `ign=OFF` → arnés pin 3 / divisor 22k-10k | +| Banner `hbox-v5-bringup 0.5.0` · `modo=AUTO` · `inputs at boot: v5=5.2–5.4V(ok) ign=ON` | otra versión → re-flashear; `ign=OFF` → arnés pin 3 / divisor 22k-10k | | `---- RESULT: 12 PASS / 0 FAIL ----` · `>>> BOARD OK` | cualquier `[FAIL]` → tarjeta a revisión, no embarcar | | `EVT … STACK ON reason=auto` **sin teclear nada** (≈10 s tras el banner) | no enciende → `STAT` muestra `v5=` bajo 4.5 o `modo=MAN` (teclear `A`) | | `EVT … NMEA primera trama` < 3 s después · `EVT FAN ON (vehiculo: 5V+ign)` | sin NMEA → ArduSimple no arranca: medir SW_5V (MOD1 pin 5) ≈ 5 V | @@ -33,7 +33,9 @@ Dejar la unidad 10 min encendida con el módem registrándose (LEDs del módem / |---|---| | `STAT … v5=5.2x–5.3x(ok)` **todo el tiempo**; nunca `(BAJO)` ni `EVT V5 BAJO` | `BAJO` → el riel cae con la ráfaga LTE: SD-15B ajustado a ~5.3 V en P2 (memo 24-Jul, PFI LTC4040) | | `tbat`/`tair`/`tmcu` estables (< 45 °C en banco) · `i2cerr=0` | `i2cerr` subiendo → bus I²C / soldadura U3/U4/U13 | -| `$PHLG,0.4.0-fm,RUN,…` cada 10 s, `rec=0`, sin `LIMP` | `rec` > 0 sin causa → NMEA intermitente: revisar MOD1 / UART1 F9P | +| `$PHLG,0.5.0-fm,RUN,…` cada 10 s, `rec=0`, sin `LIMP` | `rec` > 0 sin causa → NMEA intermitente: revisar MOD1 / UART1 F9P | +| **Modo B:** ≈10 s tras la primera NMEA, `EVT MODOB ON`; luego `STAT … modoB=ON relay=` (sube cientos/s) `phlg_aire=` (+1 cada 30 s) | `modoB=off` permanente → sin NMEA en PA3 o `B` bloqueado; `relay=0` con `modoB=ON` → K1 / PA10 | +| **Servidor:** en ≤ 2 min la unidad `H00xx` muestra la columna **Salud** (fw `0.5.0-fm`, vbat, temperaturas) y sigue reportando posición 1 Hz | posición sí pero sin Salud → el módem no reenvía la `$PHLG`: revisar `$$$AS+` (modo transparente) | ## P3 — Respaldo de batería (6 min) — **la prueba que nunca se había hecho en v5** Con la etapa ON: **desconectar el 24 V** (se va el 5 V del SD-15B). Esperar 5 min. Reconectar. @@ -63,7 +65,7 @@ Con la etapa ON y > 90 s de encendida: **retirar el ArduSimple del socket** (o s ## P6 — Apagado y acta (2 min) - Quitar ignición: `EVT IGN OFF`, `EVT FAN OFF (bateria: termostato)`; la etapa sigue ON mientras haya 5 V (el SD-15B sigue con 24 V). - Quitar 24 V: si la batería está, entra `BACKUP` (P3); dejarla hasta `SLEEP` **no** es necesario — reconectar y apagar con `P`. -- Guardar el log. En el acta: versión (`0.4.0-fm`), `uid=` del banner, resultado P1–P5, `vbat` final, y la nota *cargador OFF*. +- Guardar el log. En el acta: versión (`0.5.0-fm`), `uid=` del banner, resultado P1–P5, `vbat` final, y la nota *cargador OFF*. ## Lectura rápida del LED RGB (para el técnico de campo) | Color | Significado | diff --git a/docs/procedimientos/v5-prueba-y-flasheo.md b/docs/procedimientos/v5-prueba-y-flasheo.md index e3f1c64..4c4b8e1 100644 --- a/docs/procedimientos/v5-prueba-y-flasheo.md +++ b/docs/procedimientos/v5-prueba-y-flasheo.md @@ -37,7 +37,7 @@ y dejarla flasheada con el firmware de arranque entregado por ingeniería. | 1 | Fuente de banco 0–30 V con límite de corriente ajustable | | 1 | Cable USB-C ↔ USB-C (o USB-A ↔ USB-C) **con datos** (no solo carga) | | 1 | Laptop con **STM32CubeProgrammer** instalado (o `dfu-util` en terminal) | -| 1 | Archivo de firmware: **`hbox-v5-bringup_0.4.0.bin`** — descarga: **https://drogheda.helgen.online/descargas/** (repo: `04-Source-Code/firmware/hbox_v5_bringup/release/`, SHA-256 inicia `a8de74b3`) | +| 1 | Archivo de firmware: **`hbox-v5-bringup_0.5.0.bin`** — descarga: **https://drogheda.helgen.online/descargas/** (repo: `04-Source-Code/firmware/hbox_v5_bringup/release/`, SHA-256 inicia `98656ddc`) | | 1 | Jumper 2.54 mm para P11 (interruptor de corte) | | 1 | Lupa o lámpara con aumento | | — | Hoja de registro (sección 7) | @@ -183,7 +183,7 @@ Solo para tarjetas que pasaron las secciones 1 a 4. 2. Arriba a la derecha, en el selector de conexión elegir **USB**. Pulsar el botón de refrescar; debe aparecer `USB1`. Pulsar **Connect**. 3. Ir a la pestaña **Erasing & Programming** (icono de flecha hacia abajo, lado izquierdo). -4. **File path** → seleccionar `hbox-v5-bringup_0.4.0.bin`. +4. **File path** → seleccionar `hbox-v5-bringup_0.5.0.bin`. 5. **Start address** = `0x08000000`. Marcar **Verify programming** y **Run after programming**. 6. Pulsar **Start Programming**. Esperar "File download complete" y "Verify… successful". 7. Pulsar **Disconnect**. @@ -192,7 +192,7 @@ Solo para tarjetas que pasaron las secciones 1 a 4. ```bash dfu-util -l # debe listar [0483:df11] -dfu-util -a 0 -s 0x08000000:leave -D hbox-v5-bringup_0.4.0.bin +dfu-util -a 0 -s 0x08000000:leave -D hbox-v5-bringup_0.5.0.bin ``` ### 5d. Verificación después del flasheo @@ -206,7 +206,7 @@ dfu-util -a 0 -s 0x08000000:leave -D hbox-v5-bringup_0.4.0.bin | **D17** (LED azul) + LED de panel en P8 (si hay) | **Parpadean** a 1 Hz (MCU ejecutando el firmware) | | **DB1 → DB4** (LEDs del indicador de batería) | Se encienden **en secuencia** una vez, luego se apagan; después R, G, B en P14 si hay LED RGB conectado | | Laptop | Aparece un **puerto serie** nuevo ("STMicroelectronics Virtual COM Port" / `usbmodem…`) | -| Terminal serie a **115200 baud** | Encabezado `hbox-v5-bringup 0.4.0` (cualquier otra version: re-flashear), luego líneas `[PASS]` / `[FAIL]`, y al final **`>>> BOARD OK`** | +| Terminal serie a **115200 baud** | Encabezado `hbox-v5-bringup 0.5.0` (cualquier otra version: re-flashear), luego líneas `[PASS]` / `[FAIL]`, y al final **`>>> BOARD OK`** | 3. Si el terminal se abrió tarde y no se vio el reporte: teclear **`r`** en el terminal → repite todas las pruebas (y vuelve a encender los LEDs en secuencia). diff --git a/mkdocs.yml b/mkdocs.yml index 0b05248..bd0407b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -88,5 +88,6 @@ nav: - "Histórico — Proto bench v3": procedimientos/historico-proto-bench-v3.md - "Histórico — Protoboard": procedimientos/historico-protoboard.md + - "👤 Mi cuenta (cambiar contraseña)": cuenta.html - "⚙ Administración (Leo)": admin.html - "🚪 Salir": salir.html diff --git a/scripts/sync-docs.sh b/scripts/sync-docs.sh index b468443..e075e80 100644 --- a/scripts/sync-docs.sh +++ b/scripts/sync-docs.sh @@ -22,7 +22,7 @@ declare -a MAP=( "03-Architecture-Hardware/kicad/docs/GIT-GUIDE_Colaboradores-Externos_ES.md|docs/git/guia-git-es.md" "03-Architecture-Hardware/kicad/docs/GIT-GUIDE_External-Collaborators_EN.md|docs/git/git-guide-en.md" # Descargas para técnicos (firmware de bring-up v5) - "04-Source-Code/firmware/hbox_v5_bringup/release/hbox-v5-bringup_0.4.0.bin|docs/descargas/hbox-v5-bringup_0.4.0.bin" + "04-Source-Code/firmware/hbox_v5_bringup/release/hbox-v5-bringup_0.5.0.bin|docs/descargas/hbox-v5-bringup_0.5.0.bin" "04-Source-Code/firmware/hbox_v5_bringup/release/SHA256SUMS|docs/descargas/SHA256SUMS.txt" "04-Source-Code/firmware/hbox_v5_bringup/README.md|docs/descargas/hbox-v5-bringup-README.md" )