auto-sync 2026-09-19 18:00
This commit is contained in:
parent
7465a9e1fb
commit
dd9c962471
@ -54,7 +54,7 @@ El backend la deduce sola de `ACTAS_DIR`; si prefieres fijarla, agrega a
|
|||||||
Environment=ADJUNTOS_DIR=/srv/projects/drogheda/adjuntos
|
Environment=ADJUNTOS_DIR=/srv/projects/drogheda/adjuntos
|
||||||
Environment=ADJUNTO_MAX_MB=8
|
Environment=ADJUNTO_MAX_MB=8
|
||||||
Environment=ARCHIVO_MAX_MB=20
|
Environment=ARCHIVO_MAX_MB=20
|
||||||
Environment=ACTAS_REPETIBLES=diagnostico-campo,instalacion-campo
|
Environment=ACTAS_REPETIBLES=diagnostico-campo,diagnostico-banco,instalacion-campo,reflasheo,dano,envio,recepcion
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4 · nginx — subida de fotos e identidad del técnico (una sola vez)
|
### 4 · nginx — subida de fotos e identidad del técnico (una sola vez)
|
||||||
|
|||||||
@ -10,7 +10,7 @@ Environment=ACTAS_DIR=/srv/projects/drogheda/actas
|
|||||||
Environment=ADJUNTOS_DIR=/srv/projects/drogheda/adjuntos
|
Environment=ADJUNTOS_DIR=/srv/projects/drogheda/adjuntos
|
||||||
Environment=ADJUNTO_MAX_MB=8
|
Environment=ADJUNTO_MAX_MB=8
|
||||||
Environment=ARCHIVO_MAX_MB=20
|
Environment=ARCHIVO_MAX_MB=20
|
||||||
Environment=ACTAS_REPETIBLES=diagnostico-campo,instalacion-campo
|
Environment=ACTAS_REPETIBLES=diagnostico-campo,diagnostico-banco,instalacion-campo,reflasheo,dano,envio,recepcion
|
||||||
Environment=ACTAS_ADMINS=leo
|
Environment=ACTAS_ADMINS=leo
|
||||||
Environment=HTPASSWD_FILE=/etc/nginx/hbox-docs.htpasswd
|
Environment=HTPASSWD_FILE=/etc/nginx/hbox-docs.htpasswd
|
||||||
Environment=PASS_MIN=8
|
Environment=PASS_MIN=8
|
||||||
|
|||||||
@ -36,7 +36,7 @@ ADMINS = {u.strip().lower() for u in os.environ.get("ACTAS_ADMINS", "leo").split
|
|||||||
TIPOS_UNICOS = {"ensamble"} # tipos en los que un componente solo puede usarse en un acta real
|
TIPOS_UNICOS = {"ensamble"} # tipos en los que un componente solo puede usarse en un acta real
|
||||||
# Tipos REPETIBLES: una misma serie puede tener varias actas (cada visita a campo es un evento nuevo).
|
# Tipos REPETIBLES: una misma serie puede tener varias actas (cada visita a campo es un evento nuevo).
|
||||||
TIPOS_REPETIBLES = {t.strip() for t in os.environ.get(
|
TIPOS_REPETIBLES = {t.strip() for t in os.environ.get(
|
||||||
"ACTAS_REPETIBLES", "diagnostico-campo,diagnostico-banco,instalacion-campo,reflasheo").split(",") if t.strip()}
|
"ACTAS_REPETIBLES", "diagnostico-campo,diagnostico-banco,instalacion-campo,reflasheo,dano,envio,recepcion").split(",") if t.strip()}
|
||||||
|
|
||||||
# Subida de fotos
|
# Subida de fotos
|
||||||
MAX_MB = int(os.environ.get("ADJUNTO_MAX_MB", "8"))
|
MAX_MB = int(os.environ.get("ADJUNTO_MAX_MB", "8"))
|
||||||
@ -193,9 +193,11 @@ def crear():
|
|||||||
os.makedirs(carpeta, exist_ok=True)
|
os.makedirs(carpeta, exist_ok=True)
|
||||||
archivo = f"{serie}_{iso.replace(':', '-')}.json"
|
archivo = f"{serie}_{iso.replace(':', '-')}.json"
|
||||||
if es_repetible(tipo):
|
if es_repetible(tipo):
|
||||||
# cada visita es un registro propio: sufijo único para que dos envíos
|
# cada visita es un registro propio. El nombre lleva microsegundos para que el
|
||||||
# en el mismo segundo (doble toque) no se pisen
|
# orden alfabético SEA el orden cronológico (dos envíos en el mismo segundo no
|
||||||
archivo = f"{serie}_{iso.replace(':', '-')}_{uuid.uuid4().hex[:6]}.json"
|
# se pisan ni se desordenan), y un sufijo aleatorio por si acaso.
|
||||||
|
micro = datetime.datetime.now().strftime("%f")
|
||||||
|
archivo = f"{serie}_{iso.replace(':', '-')}-{micro}_{uuid.uuid4().hex[:4]}.json"
|
||||||
with open(os.path.join(carpeta, archivo), "w", encoding="utf-8") as f:
|
with open(os.path.join(carpeta, archivo), "w", encoding="utf-8") as f:
|
||||||
json.dump(d, f, ensure_ascii=False, indent=2)
|
json.dump(d, f, ensure_ascii=False, indent=2)
|
||||||
|
|
||||||
@ -290,7 +292,7 @@ def listar():
|
|||||||
"resultado": d.get("resultado"), "recibido": d.get("_recibido")}
|
"resultado": d.get("resultado"), "recibido": d.get("_recibido")}
|
||||||
if isinstance(d.get("componentes"), dict):
|
if isinstance(d.get("componentes"), dict):
|
||||||
fila["componentes"] = d["componentes"]
|
fila["componentes"] = d["componentes"]
|
||||||
for k in ("clasificacion", "accion", "motivo", "maquina", "terminal", "unidad"):
|
for k in ("clasificacion", "accion", "motivo", "maquina", "terminal", "unidad", "resumen"):
|
||||||
if d.get(k):
|
if d.get(k):
|
||||||
fila[k] = d[k]
|
fila[k] = d[k]
|
||||||
if d.get("archivos"):
|
if d.get("archivos"):
|
||||||
@ -631,7 +633,9 @@ def expediente():
|
|||||||
actas.sort(key=_clave, reverse=True)
|
actas.sort(key=_clave, reverse=True)
|
||||||
relacionadas.sort(key=_clave, reverse=True)
|
relacionadas.sort(key=_clave, reverse=True)
|
||||||
fotos, logs = _listar_adjuntos(serie)
|
fotos, logs = _listar_adjuntos(serie)
|
||||||
|
marca = estado_serie(serie)
|
||||||
return jsonify(ok=True, serie=serie, actas=actas, relacionadas=relacionadas,
|
return jsonify(ok=True, serie=serie, actas=actas, relacionadas=relacionadas,
|
||||||
|
marca=marca["marca"], marca_acta=marca["acta"],
|
||||||
fotos=fotos, logs=logs,
|
fotos=fotos, logs=logs,
|
||||||
total=len(actas), total_fotos=len(fotos), total_logs=len(logs))
|
total=len(actas), total_fotos=len(fotos), total_logs=len(logs))
|
||||||
|
|
||||||
@ -654,5 +658,64 @@ def series():
|
|||||||
for k, v in sorted(vistas.items())])
|
for k, v in sorted(vistas.items())])
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------- estado de una serie (daños abiertos)
|
||||||
|
# Un acta de tipo 'dano' MARCA la serie. La marca se levanta con otra acta 'dano' cuyo
|
||||||
|
# campo 'accion' empiece por "Reparada" o "Baja": lo último que se dijo, manda.
|
||||||
|
def estado_serie(serie):
|
||||||
|
"""Devuelve {'marca': None|'DANADA'|'BAJA', 'acta': {...}|None} para una serie."""
|
||||||
|
carpeta = os.path.join(BASE, "dano")
|
||||||
|
ultimo = None
|
||||||
|
# listar_serie() ordena por nombre = cronológico (los repetibles llevan microsegundos).
|
||||||
|
# Manda la ÚLTIMA acta registrada, no la de fecha de visita más reciente: si alguien
|
||||||
|
# captura hoy un daño de la semana pasada, hoy es cuando la serie se marca.
|
||||||
|
for fn in listar_serie("dano", serie) if os.path.isdir(carpeta) else []:
|
||||||
|
try:
|
||||||
|
with open(os.path.join(carpeta, fn), encoding="utf-8") as f:
|
||||||
|
d = json.load(f)
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
if "PRUEBA" in serie.upper():
|
||||||
|
continue
|
||||||
|
ultimo = {"archivo": fn, "fecha": d.get("fecha"), "recibido": d.get("_recibido"),
|
||||||
|
"tecnico": d.get("tecnico"), "clasificacion": d.get("clasificacion"),
|
||||||
|
"accion": d.get("accion"), "resumen": d.get("resumen")}
|
||||||
|
if not ultimo:
|
||||||
|
return {"marca": None, "acta": None}
|
||||||
|
acc = str(ultimo.get("accion") or "")
|
||||||
|
if acc.startswith("Baja"):
|
||||||
|
return {"marca": "BAJA", "acta": ultimo}
|
||||||
|
if acc.startswith("Reparada"):
|
||||||
|
return {"marca": None, "acta": ultimo}
|
||||||
|
return {"marca": "DANADA", "acta": ultimo}
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/api/estado")
|
||||||
|
def estado():
|
||||||
|
"""Marca de daño/baja de una serie — lo consultan TODOS los formularios al elegirla."""
|
||||||
|
serie = slug(request.args.get("serie"), 24)
|
||||||
|
if not serie:
|
||||||
|
return jsonify(ok=False, error="falta serie"), 400
|
||||||
|
e = estado_serie(serie)
|
||||||
|
return jsonify(ok=True, serie=serie, marca=e["marca"], acta=e["acta"])
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/api/danos")
|
||||||
|
def danos():
|
||||||
|
"""Todas las series con marca vigente (dañada o baja), para el tablero."""
|
||||||
|
out = []
|
||||||
|
carpeta = os.path.join(BASE, "dano")
|
||||||
|
if os.path.isdir(carpeta):
|
||||||
|
vistas = set()
|
||||||
|
for fn in sorted(os.listdir(carpeta)):
|
||||||
|
if fn.endswith(".json"):
|
||||||
|
ser = fn.split("_2")[0] if "_2" in fn else fn[:-5]
|
||||||
|
vistas.add(ser)
|
||||||
|
for ser in sorted(vistas):
|
||||||
|
e = estado_serie(ser)
|
||||||
|
if e["marca"]:
|
||||||
|
out.append({"serie": ser, "marca": e["marca"], "acta": e["acta"]})
|
||||||
|
return jsonify(ok=True, total=len(out), series=out)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.run(host="127.0.0.1", port=int(os.environ.get("PORT", "8081")))
|
app.run(host="127.0.0.1", port=int(os.environ.get("PORT", "8081")))
|
||||||
|
|||||||
@ -49,6 +49,12 @@ visitas anteriores antes de empezar. Permite **subir fotos** desde el teléfono.
|
|||||||
Procedimiento: [Diagnóstico en campo](../diagnostico/procedimiento-diagnostico-campo.md) ·
|
Procedimiento: [Diagnóstico en campo](../diagnostico/procedimiento-diagnostico-campo.md) ·
|
||||||
Seguimiento: [Tablero de campo](../diagnostico/tablero-campo.html).
|
Seguimiento: [Tablero de campo](../diagnostico/tablero-campo.html).
|
||||||
|
|
||||||
|
**[▶ Acta de daño o incidente](../formularios/dano.html)** — cualquier serie. **Marca** la serie: todos los
|
||||||
|
formularios avisan al elegirla. Se levanta con «Reparada»; «Baja» la hace permanente.
|
||||||
|
|
||||||
|
**[▶ Acta de envío](../formularios/envio.html)** · **[▶ Acta de recepción](../formularios/recepcion.html)** — el
|
||||||
|
tramo entre el banco y el puerto. Mapa completo: [Ciclo de vida](../procedimientos/ciclo-de-vida.md).
|
||||||
|
|
||||||
## Cómo se usan
|
## Cómo se usan
|
||||||
|
|
||||||
1. Abre el formulario y **elige el número de serie** (o los módulos, en integración y ensamble).
|
1. Abre el formulario y **elige el número de serie** (o los módulos, en integración y ensamble).
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
035ebeb348461765f099341603a9e99b94512f8477509efb78aa7caf953f4c2f hbox-fw-v3_3.0.4.bin
|
035ebeb348461765f099341603a9e99b94512f8477509efb78aa7caf953f4c2f hbox-tarjetaV3_3.0.4.bin
|
||||||
a68a87ff1f6b34a8284e9e5e32c95da7bb8d8adc071c5fd64412a3e744e46b28 hbox-fw-v4_4.0.0.bin
|
a68a87ff1f6b34a8284e9e5e32c95da7bb8d8adc071c5fd64412a3e744e46b28 hbox-tarjetaV3_4.0.0.bin
|
||||||
a8de74b3d7768e9d5656ae0bff05475445c0cd2599ecfdc4ab081e517ed3d6ef hbox-v5-bringup_0.4.0.bin
|
a8de74b3d7768e9d5656ae0bff05475445c0cd2599ecfdc4ab081e517ed3d6ef hbox-v5-bringup_0.4.0.bin
|
||||||
e1f351084e803306c376989b284ca0f9f9f1a3445e59494f8a5ff7a9652ad44c hbox-v5-bringup_0.5.1.bin
|
e1f351084e803306c376989b284ca0f9f9f1a3445e59494f8a5ff7a9652ad44c hbox-v5-bringup_0.5.1.bin
|
||||||
|
|||||||
@ -21,19 +21,31 @@ Cada carga se registra en el **[acta de reflasheo](../formularios/reflasheo.html
|
|||||||
Un binario incompleto o de otra generación puede dejar la tarjeta inservible.
|
Un binario incompleto o de otra generación puede dejar la tarjeta inservible.
|
||||||
`shasum -a 256 archivo` (macOS) · `sha256sum archivo` (Linux) · `certutil -hashfile archivo SHA256` (Windows).
|
`shasum -a 256 archivo` (macOS) · `sha256sum archivo` (Linux) · `certutil -hashfile archivo SHA256` (Windows).
|
||||||
|
|
||||||
## Firmware del HBOX (por generación de tarjeta)
|
## Firmware del HBOX — qué binario va en qué tarjeta
|
||||||
|
|
||||||
| Generación | Archivo | Para qué sirve |
|
**La versión del firmware no dice nada de la tarjeta.** `0.3.0` no es "para V3" ni `0.4.0` "para V4":
|
||||||
|---|---|---|
|
son versiones viejas del firmware de **V5**. El binario lleva la tarjeta en el nombre y eso es lo que manda.
|
||||||
| **V3** — flota desplegada (RTK-003, RTK-006, RTK-014) | ⚠ [`hbox-fw-v3_3.0.4.bin`](hbox-fw-v3_3.0.4.bin) — compilado, **sin prueba de banco** | Mismo comportamiento que el 3.0.3 de campo, compilado con el core 3.x |
|
|
||||||
| **V4** | ⚠ [`hbox-fw-v4_4.0.0.bin`](hbox-fw-v4_4.0.0.bin) — compilado, **sin prueba de banco** | Telemetría en banda: el `$PHLG` y el `$PHEV` llegan al servidor por el módem |
|
| Tarjeta | MCU | Firmware (código) | Binario vigente |
|
||||||
| **V5** — EinarBoard v5 | ✅ `hbox-v5-bringup_0.5.1.bin` (abajo) | Bring-up de tarjeta en banco |
|
|---|---|---|---|
|
||||||
|
| **V3** — EinarBoard 1.0, las 3 unidades en campo | Blackpill en zócalo (F411CE) | `blackpillrtkcode_v3` · `_v4` | [`hbox-tarjetaV3_3.0.4.bin`](hbox-tarjetaV3_3.0.4.bin) ⚠ sin prueba de banco |
|
||||||
|
| **V3** con telemetría en banda | Blackpill en zócalo | `blackpillrtkcode_v4` (4.0.0) | [`hbox-tarjetaV3_4.0.0.bin`](hbox-tarjetaV3_4.0.0.bin) ⚠ sin prueba de banco |
|
||||||
|
| **V4** — `hbox-watchdog-v4` | Blackpill en zócalo + PCF8574 · W5500 · SC16IS752 | **ninguno** | — |
|
||||||
|
| **V5** — `hbox-watchdog-v5`, lote de 15 | STM32F411RET6 soldado | `hbox_v5_bringup` | [`hbox-v5-bringup_0.5.1.bin`](hbox-v5-bringup_0.5.1.bin) ✅ **en despliegue** |
|
||||||
|
|
||||||
|
!!! danger "Lo que NO se puede cruzar"
|
||||||
|
- Un binario de **V5** en una **V3 o V4**: es otro MCU (soldado vs Blackpill), otro reloj y otro mapa
|
||||||
|
de pines. Lo más probable es que ni enumere por USB.
|
||||||
|
- `blackpillrtkcode` en una **V4**: maneja los LEDs de carga en PB12–PB15, que en la V4 son el SPI
|
||||||
|
del W5500. La V4 **no tiene firmware todavía**; hasta que lo tenga, no se flashea con nada.
|
||||||
|
- `hbox-v5-bringup_0.4.0` (o 0.3.0) en cualquier tarjeta: son versiones **superadas** de V5, sin
|
||||||
|
watchdog, ventilador ni recuperación de enlace. Solo se conservan por trazabilidad.
|
||||||
|
|
||||||
### Firmware de bring-up — EinarBoard v5
|
### Firmware de bring-up — EinarBoard v5
|
||||||
|
|
||||||
| Archivo | Versión | SHA-256 | Uso |
|
| 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) — **campo, sin telemetría en banda** (probado en unidad) | `a8de74b3d7768e9d…` ([SHA256SUMS](SHA256SUMS.txt)) |
|
| [`hbox-v5-bringup_0.4.0.bin`](hbox-v5-bringup_0.4.0.bin) | 0.4.0 (2026-09-17) — **superada**, sin telemetría en banda | `a8de74b3d7768e9d…` ([SHA256SUMS](SHA256SUMS.txt)) |
|
||||||
| [**hbox-v5-bringup_0.5.1.bin**](hbox-v5-bringup_0.5.1.bin) | **0.5.1** (2026-09-18) — **campo + Modo B / telemetría — EN PRUEBA** (reportado: etapa RTK no enciende) | `e1f351084e803306…` | 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.1.bin**](hbox-v5-bringup_0.5.1.bin) | **0.5.1** (2026-09-18) — **campo + Modo B / telemetría — EN PRUEBA** (reportado: etapa RTK no enciende) | `e1f351084e803306…` | 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):
|
Flasheo por DFU en **J11** (mantener **SW2**, pulsar y soltar **SW1**, soltar SW2):
|
||||||
@ -44,14 +56,13 @@ dfu-util -a 0 -s 0x08000000:leave -D hbox-v5-bringup_0.5.1.bin
|
|||||||
|
|
||||||
o con **STM32CubeProgrammer** → USB → Connect → Download del `.bin` en `0x08000000`.
|
o con **STM32CubeProgrammer** → USB → Connect → Download del `.bin` en `0x08000000`.
|
||||||
|
|
||||||
!!! danger "18-sep, tarde: A/B entre 0.4.0 y 0.5.1"
|
!!! success "A/B 0.4.0 vs 0.5.1 — cerrado el 19-sep"
|
||||||
Se reportó que con **0.5.1** la etapa RTK no enciende y con **0.4.0** sí. Hasta cerrar el diagnóstico:
|
El 18-sep por la tarde se reportó que con 0.5.1 la etapa RTK no encendía. **Resuelto:** 0.5.1 ensambla,
|
||||||
**embarcar con 0.4.0**. Para diagnosticar 0.5.1 en UNA unidad: consola en J11, tap a SW1, guardar todo desde el banner
|
enciende y reporta telemetría completa en el monitor desplegado. **Se embarca con 0.5.1.** `0.4.0`
|
||||||
hasta 2 min después; luego teclear `s`, `v` y `B` (bloquea Modo B) y anotar si la etapa enciende con `B`.
|
sigue descargable solo como referencia de versiones anteriores.
|
||||||
Mandar el log completo — el diagnóstico sale de ahí, no del LED.
|
|
||||||
|
|
||||||
!!! note "Tarjetas ya flasheadas con cualquier versión anterior"
|
!!! note "Tarjetas ya flasheadas con cualquier versión anterior"
|
||||||
Re-flashear con 0.4.0 (o 0.5.1 solo para la prueba A/B) por el mismo procedimiento DFU. **La primera línea de la consola tras reset dice la versión**
|
Re-flashear con **0.5.1** por el mismo procedimiento DFU. **La primera línea de la consola tras reset dice la versión**
|
||||||
(`hbox-v5-bringup 0.5.1 built …`): si la línea `STAT` no termina en `stack=…`, la tarjeta sigue con 0.1.1.
|
(`hbox-v5-bringup 0.5.1 built …`): si la línea `STAT` no termina en `stack=…`, la tarjeta sigue con 0.1.1.
|
||||||
|
|
||||||
!!! tip "Consola 0.5.1"
|
!!! tip "Consola 0.5.1"
|
||||||
@ -83,21 +94,19 @@ o con **STM32CubeProgrammer** → USB → Connect → Download del `.bin` en `0x
|
|||||||
|
|
||||||
Notas de compilación y cambios: [README del firmware de bring-up](hbox-v5-bringup-README.md).
|
Notas de compilación y cambios: [README del firmware de bring-up](hbox-v5-bringup-README.md).
|
||||||
|
|
||||||
### Firmware de campo — tarjetas V3 y V4 (detalle)
|
### Firmware de campo — tarjeta V3 (detalle)
|
||||||
|
|
||||||
!!! danger "Estos binarios todavía NO se flashean en una unidad de campo"
|
!!! danger "Estos binarios todavía NO se flashean en una unidad de campo"
|
||||||
Compilaron limpio el 19-sep y pasan el simulador, pero **ninguno ha corrido sobre una
|
Compilaron limpio el 19-sep y pasan el simulador, pero **ninguno ha corrido sobre una
|
||||||
EinarBoard 1.0 real**. Hasta que ingeniería los pruebe en banco (RTK-003 o RTK-006) y quite
|
EinarBoard 1.0 real**. Hasta que ingeniería los pruebe en banco (RTK-003 o RTK-006) y quite
|
||||||
este aviso, solo se usan en la mesa de ingeniería. Esto aplica sobre todo a **V4**, que pone
|
este aviso, solo se usan en la mesa de ingeniería. Esto aplica sobre todo al **4.0.0**, que pone
|
||||||
el MCU en línea con el enlace que lleva las correcciones RTK.
|
el MCU en línea con el enlace que lleva las correcciones RTK.
|
||||||
|
|
||||||
!!! warning "V4 y el A/B pendiente de 0.5.1"
|
!!! tip "Prueba de banco del 4.0.0: en par"
|
||||||
El fallo de **0.5.1** en v5 (la etapa RTK no enciende) tiene como sospechoso principal al
|
El 4.0.0 activa el Modo B por omisión. Aunque el A/B de V5 ya cerró bien, la primera prueba en
|
||||||
**Modo B**, y **v4 activa el Modo B por omisión**. Hasta que el A/B de v5 dé una causa, la
|
una V3 real se hace **en par**: el binario publicado y uno compilado con `-DENABLE_MODOB=0`,
|
||||||
prueba de banco de v4 se hace **en par**: el binario publicado (Modo B encendido) y uno
|
sobre la misma unidad. Si el fix RTK cae al energizar K1, o `v5min` se hunde en ese instante,
|
||||||
compilado sin Modo B, sobre la misma unidad, comparando si la etapa enciende y qué dice
|
el sospechoso es la bobina de K1 llevando el riel al PFI del LTC4040.
|
||||||
`v5min` en el momento en que K1 se energiza — una caída ahí sería la bobina de K1 hundiendo
|
|
||||||
el riel hasta el PFI del LTC4040.
|
|
||||||
```bash
|
```bash
|
||||||
arduino-cli compile --fqbn "$FQBN" --build-property "compiler.cpp.extra_flags=-DENABLE_MODOB=0" \
|
arduino-cli compile --fqbn "$FQBN" --build-property "compiler.cpp.extra_flags=-DENABLE_MODOB=0" \
|
||||||
--output-dir build/v4-sinB blackpillrtkcode_v4
|
--output-dir build/v4-sinB blackpillrtkcode_v4
|
||||||
@ -108,8 +117,8 @@ bring-up del v5. Se usa en el [reflasheo en taller](../procedimientos/reflasheo-
|
|||||||
|
|
||||||
| Generación | Archivo | Estado |
|
| Generación | Archivo | Estado |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| **V3** — flota desplegada | [`hbox-fw-v3_3.0.4.bin`](hbox-fw-v3_3.0.4.bin) · 62 464 B · `035ebeb3…` | ⚠ **compilado 19-sep, falta prueba de banco** |
|
| **V3** — flota desplegada | [`hbox-tarjetaV3_3.0.4.bin`](hbox-tarjetaV3_3.0.4.bin) · 62 464 B · `035ebeb3…` | ⚠ compilado 19-sep, falta prueba de banco |
|
||||||
| **V4** | [`hbox-fw-v4_4.0.0.bin`](hbox-fw-v4_4.0.0.bin) · 64 352 B · `a68a87ff…` | ⚠ **compilado 19-sep, falta prueba de banco**. Validado en el simulador de host |
|
| **V3** con telemetría | [`hbox-tarjetaV3_4.0.0.bin`](hbox-tarjetaV3_4.0.0.bin) · 64 352 B · `a68a87ff…` | ⚠ compilado 19-sep, falta prueba de banco. El «4» es la versión del firmware, **no** la tarjeta |
|
||||||
|
|
||||||
!!! danger "Mientras diga «pendiente», no hay binario aprobado"
|
!!! danger "Mientras diga «pendiente», no hay binario aprobado"
|
||||||
No flashees una unidad V3 o V4 con un archivo que no esté publicado aquí con su SHA-256. Los
|
No flashees una unidad V3 o V4 con un archivo que no esté publicado aquí con su SHA-256. Los
|
||||||
@ -182,7 +191,7 @@ binario mal compilado deja unidades muertas en el patio.
|
|||||||
- [ ] Compilado con el `TARGET_` correcto para esa generación de tarjeta.
|
- [ ] Compilado con el `TARGET_` correcto para esa generación de tarjeta.
|
||||||
- [ ] **Probado en banco sobre hardware real**, no solo compilado sin errores.
|
- [ ] **Probado en banco sobre hardware real**, no solo compilado sin errores.
|
||||||
- [ ] Verificada la polaridad del control de carga sobre la tarjeta.
|
- [ ] Verificada la polaridad del control de carga sobre la tarjeta.
|
||||||
- [ ] Nombre con versión: `hbox-fw-v3_X.Y.Z.bin`.
|
- [ ] Nombre con **tarjeta y versión**: `hbox-tarjetaV3_X.Y.Z.bin`. La versión del firmware nunca se infiere de la tarjeta ni al revés.
|
||||||
- [ ] Su línea en `SHA256SUMS.txt`.
|
- [ ] Su línea en `SHA256SUMS.txt`.
|
||||||
- [ ] Anotado en el `CHANGELOG.md` del repositorio de firmware, con fecha y quién lo probó.
|
- [ ] Anotado en el `CHANGELOG.md` del repositorio de firmware, con fecha y quién lo probó.
|
||||||
- [ ] Actualizada la tabla de esta página.
|
- [ ] Actualizada la tabla de esta página.
|
||||||
|
|||||||
@ -138,6 +138,7 @@ function render(actas){
|
|||||||
title:'Ver el expediente completo',text:u.serie})),
|
title:'Ver el expediente completo',text:u.serie})),
|
||||||
el('div',{class:'m',text:(u.maquina||'')+(u.nota?' · '+u.nota:'')})));
|
el('div',{class:'m',text:(u.maquina||'')+(u.nota?' · '+u.nota:'')})));
|
||||||
const [cls,txt] = vs.length ? pill(vs[0]) : ['pend','Sin diagnóstico'];
|
const [cls,txt] = vs.length ? pill(vs[0]) : ['pend','Sin diagnóstico'];
|
||||||
|
if(DANOS[u.serie]) cab.append(el('span',{class:'pill falla',text:DANOS[u.serie].marca==='BAJA'?'⛔ BAJA':'⚠ DAÑADA'}));
|
||||||
cab.append(el('span',{class:'pill '+cls,text:txt}));
|
cab.append(el('span',{class:'pill '+cls,text:txt}));
|
||||||
box.append(cab);
|
box.append(cab);
|
||||||
|
|
||||||
@ -178,9 +179,11 @@ function render(actas){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let DANOS = {};
|
||||||
async function cargar(){
|
async function cargar(){
|
||||||
document.getElementById('meta').textContent = 'Cargando…';
|
document.getElementById('meta').textContent = 'Cargando…';
|
||||||
try{
|
try{
|
||||||
|
try{ const d=await (await fetch('/api/danos',{cache:'no-store'})).json(); DANOS={}; (d.series||[]).forEach(x=>DANOS[x.serie]=x); }catch(e){}
|
||||||
const r = await fetch('/api/actas',{cache:'no-store'});
|
const r = await fetch('/api/actas',{cache:'no-store'});
|
||||||
const j = await r.json();
|
const j = await r.json();
|
||||||
render(j.actas||[]);
|
render(j.actas||[]);
|
||||||
|
|||||||
@ -129,3 +129,9 @@ button.mini-btn{background:#fff;border:1px solid var(--linea);border-radius:6px;
|
|||||||
.mini.doc .est{font-size:11.5px;flex:0 0 auto}
|
.mini.doc .est{font-size:11.5px;flex:0 0 auto}
|
||||||
input[type=date]{width:100%;padding:11px 12px;border:1px solid var(--linea);border-radius:9px;
|
input[type=date]{width:100%;padding:11px 12px;border:1px solid var(--linea);border-radius:9px;
|
||||||
font-size:16px;background:#fff;color:var(--tinta)}
|
font-size:16px;background:#fff;color:var(--tinta)}
|
||||||
|
|
||||||
|
/* marca de daño / baja: se muestra en cualquier acta al elegir la serie */
|
||||||
|
.marca{display:none;margin:0 0 14px;padding:12px 14px;border-radius:10px;font-size:14.5px;line-height:1.45}
|
||||||
|
.marca.danada{display:block;background:var(--aviso-bg);border:2px solid var(--aviso);color:#7a4a00}
|
||||||
|
.marca.baja{display:block;background:var(--falla-bg);border:2px solid var(--falla);color:#8a1a1a}
|
||||||
|
.marca a{color:inherit;font-weight:700}
|
||||||
|
|||||||
@ -131,6 +131,37 @@
|
|||||||
wrap.append(banner);
|
wrap.append(banner);
|
||||||
const hist = $('div', { class: 'hist' });
|
const hist = $('div', { class: 'hist' });
|
||||||
if (cfg.repetible) wrap.append(hist);
|
if (cfg.repetible) wrap.append(hist);
|
||||||
|
// Marca de daño: la consultan TODOS los formularios (banco, campo, produccion).
|
||||||
|
// Una tarjeta con corto no debe poder entrar a un ensamble sin que alguien lo vea.
|
||||||
|
const marcaBox = $('div', { class: 'marca' });
|
||||||
|
wrap.append(marcaBox);
|
||||||
|
async function consultarMarca() {
|
||||||
|
marcaBox.innerHTML = ''; marcaBox.className = 'marca';
|
||||||
|
if (cfg.tipo === 'dano') return;
|
||||||
|
// En un acta compuesta (ensamble, integración) se revisa CADA módulo elegido, no solo
|
||||||
|
// la unidad calculada: una tarjeta con corto no debe poder entrar a un ensamble.
|
||||||
|
const series = compuesta ? Object.values(seleccion()).filter(v => v) : [serieActual()];
|
||||||
|
const aRevisar = series.filter(v => v && !esPrueba(v));
|
||||||
|
if (!aRevisar.length) return;
|
||||||
|
const avisos = [];
|
||||||
|
await Promise.all(aRevisar.map(async s => {
|
||||||
|
try {
|
||||||
|
const j = await (await fetch(`/api/estado?serie=${encodeURIComponent(s)}`, { cache: 'no-store' })).json();
|
||||||
|
if (j.marca) avisos.push({ s, j });
|
||||||
|
} catch (e) {}
|
||||||
|
}));
|
||||||
|
if (!avisos.length) return;
|
||||||
|
const baja = avisos.some(x => x.j.marca === 'BAJA');
|
||||||
|
marcaBox.className = 'marca ' + (baja ? 'baja' : 'danada');
|
||||||
|
marcaBox.innerHTML = avisos.map(({ s, j }) => {
|
||||||
|
const a = j.acta || {};
|
||||||
|
return (j.marca === 'BAJA' ? '⛔ <b>' + s + ' está dada de BAJA</b>' : '⚠ <b>' + s + ' está marcada como DAÑADA</b>')
|
||||||
|
+ (a.fecha ? ' desde el ' + a.fecha : '') + (a.clasificacion ? ' — ' + a.clasificacion : '')
|
||||||
|
+ (a.resumen ? '<br>' + a.resumen : '')
|
||||||
|
+ '<br><a href="../unidad.html?serie=' + encodeURIComponent(s) + '">Ver su expediente</a>'
|
||||||
|
+ (j.marca === 'BAJA' ? '. No debe usarse ni instalarse.' : '. Revisa el acta de daño antes de continuar.');
|
||||||
|
}).join('<hr style="border:0;border-top:1px solid currentColor;opacity:.3;margin:8px 0">');
|
||||||
|
}
|
||||||
|
|
||||||
// selección actual de componentes -> {clave: valor}
|
// selección actual de componentes -> {clave: valor}
|
||||||
function seleccion() { const s = {}; for (const k in compSel) s[k] = compSel[k].value; return s; }
|
function seleccion() { const s = {}; for (const k in compSel) s[k] = compSel[k].value; return s; }
|
||||||
@ -236,11 +267,13 @@
|
|||||||
const firma = $('section', { class: 'paso firma' });
|
const firma = $('section', { class: 'paso firma' });
|
||||||
firma.append($('h2', { text: 'Cierre y firma' }));
|
firma.append($('h2', { text: 'Cierre y firma' }));
|
||||||
firma.append($('p', { class: 'sub', text: 'Al enviar, quedas registrado como responsable de esta prueba.' }));
|
firma.append($('p', { class: 'sub', text: 'Al enviar, quedas registrado como responsable de esta prueba.' }));
|
||||||
|
// cfg.resultadoFijo = 'REGISTRADO': actas que no aprueban ni reprueban nada (daños, envíos).
|
||||||
|
// Se oculta el selector y el valor se manda fijo, para que el servidor siga teniendo 'resultado'.
|
||||||
const res = $('div', { class: 'resultado' });
|
const res = $('div', { class: 'resultado' });
|
||||||
const rOK = $('label', { class: 'ok' }); rOK.append($('input', { type: 'radio', name: 'resultado', value: 'OK' }), document.createTextNode(cfg.textoOK || 'APROBADA'));
|
const rOK = $('label', { class: 'ok' }); rOK.append($('input', { type: 'radio', name: 'resultado', value: 'OK' }), document.createTextNode(cfg.textoOK || 'APROBADA'));
|
||||||
const rNO = $('label', { class: 'falla' }); rNO.append($('input', { type: 'radio', name: 'resultado', value: 'FALLA' }), document.createTextNode('FALLA'));
|
const rNO = $('label', { class: 'falla' }); rNO.append($('input', { type: 'radio', name: 'resultado', value: 'FALLA' }), document.createTextNode('FALLA'));
|
||||||
res.append(rOK, rNO);
|
res.append(rOK, rNO);
|
||||||
firma.append($('label', { text: 'Resultado final' }), res);
|
if (!cfg.resultadoFijo) firma.append($('label', { text: 'Resultado final' }), res);
|
||||||
const conf = $('label', { class: 'chk', style: 'margin-top:14px' });
|
const conf = $('label', { class: 'chk', style: 'margin-top:14px' });
|
||||||
conf.append($('input', { type: 'checkbox', id: 'f_conforme' }));
|
conf.append($('input', { type: 'checkbox', id: 'f_conforme' }));
|
||||||
conf.append($('span', { class: 'txt', html: 'Confirmo que <b>seguí el procedimiento completo</b> y que los datos anotados son verídicos.' }));
|
conf.append($('span', { class: 'txt', html: 'Confirmo que <b>seguí el procedimiento completo</b> y que los datos anotados son verídicos.' }));
|
||||||
@ -545,7 +578,7 @@
|
|||||||
});
|
});
|
||||||
const rr = wrap.querySelector('input[name=resultado]:checked');
|
const rr = wrap.querySelector('input[name=resultado]:checked');
|
||||||
const d = { tipo: cfg.tipo, serie: serieActual(), tecnico: tecnico.value,
|
const d = { tipo: cfg.tipo, serie: serieActual(), tecnico: tecnico.value,
|
||||||
conforme: conforme().checked, resultado: rr ? rr.value : '', respuestas: r };
|
conforme: conforme().checked, resultado: cfg.resultadoFijo || (rr ? rr.value : ''), respuestas: r };
|
||||||
if (compuesta) { d.componentes = seleccion(); d.verificacion = Object.assign({}, verif); }
|
if (compuesta) { d.componentes = seleccion(); d.verificacion = Object.assign({}, verif); }
|
||||||
if (fotos.length) d.fotos = fotos;
|
if (fotos.length) d.fotos = fotos;
|
||||||
if (archivos.length) d.archivos = archivos;
|
if (archivos.length) d.archivos = archivos;
|
||||||
@ -587,6 +620,7 @@
|
|||||||
blankFields(); showEditable();
|
blankFields(); showEditable();
|
||||||
if (compuesta) { if (usados === null) await cargarUsados(); await verificar(); }
|
if (compuesta) { if (usados === null) await cargarUsados(); await verificar(); }
|
||||||
if (cfg.repetible) cargarHistorial();
|
if (cfg.repetible) cargarHistorial();
|
||||||
|
consultarMarca();
|
||||||
if (!s) {
|
if (!s) {
|
||||||
estado.textContent = compuesta ? 'Elige los tres módulos' : (flota ? 'Elige la unidad' : 'Elige el número de serie');
|
estado.textContent = compuesta ? 'Elige los tres módulos' : (flota ? 'Elige la unidad' : 'Elige el número de serie');
|
||||||
aplicarCondiciones(); return;
|
aplicarCondiciones(); return;
|
||||||
@ -637,6 +671,8 @@
|
|||||||
if (locked) return;
|
if (locked) return;
|
||||||
const d = snapshot();
|
const d = snapshot();
|
||||||
if (!d.serie) return fail(compuesta ? 'Elige los tres módulos.' : 'Elige el número de serie.');
|
if (!d.serie) return fail(compuesta ? 'Elige los tres módulos.' : 'Elige el número de serie.');
|
||||||
|
if (compuesta && cfg.exigirAprobados && !esPrueba(d.serie) && marcaBox.classList.contains('baja'))
|
||||||
|
return fail('Uno de los módulos está dado de BAJA. No se puede ensamblar con él.');
|
||||||
if (compuesta && cfg.exigirAprobados && !esPrueba(d.serie) && !todoAprobado())
|
if (compuesta && cfg.exigirAprobados && !esPrueba(d.serie) && !todoAprobado())
|
||||||
return fail('Hay módulos sin aprobar, sin acta o ya asignados a otra unidad. No se puede enviar.');
|
return fail('Hay módulos sin aprobar, sin acta o ya asignados a otra unidad. No se puede enviar.');
|
||||||
if (!d.tecnico.trim()) return fail('Escribe tu nombre.');
|
if (!d.tecnico.trim()) return fail('Escribe tu nombre.');
|
||||||
|
|||||||
102
docs/formularios/dano.html
Normal file
102
docs/formularios/dano.html
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="es">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Acta de daño o incidente — HBOX</title>
|
||||||
|
<link rel="stylesheet" href="acta.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="acta"></div>
|
||||||
|
<script src="flota.js"></script>
|
||||||
|
<script src="series.js"></script>
|
||||||
|
<script src="acta.js"></script>
|
||||||
|
<script>
|
||||||
|
const energizada = v => String(v.energizada || '').startsWith('Sí');
|
||||||
|
|
||||||
|
Acta.render({
|
||||||
|
tipo: 'dano',
|
||||||
|
repetible: true,
|
||||||
|
resultadoFijo: 'REGISTRADO',
|
||||||
|
tecnicoDesdeUsuario: true,
|
||||||
|
nombres: { alan: 'Alán Basurto', daniel: 'Daniel Martínez', leo: 'Leo Rodríguez' },
|
||||||
|
unidades: window.SERIES,
|
||||||
|
etiquetaSerie: 'Tarjeta, módulo o unidad dañada',
|
||||||
|
titulo: 'Acta de daño o incidente',
|
||||||
|
subtitulo: 'Helgen Technologies · cualquier cosa con número de serie: tarjeta, módulo o unidad completa.',
|
||||||
|
intro: '<b>Para qué sirve.</b> Hoy una tarjeta con un corto puede acabar dentro de un ensamble sin que nadie '
|
||||||
|
+ 'lo sepa, porque no queda registro. Esta acta <b>marca</b> la serie: desde que se envía, cualquier '
|
||||||
|
+ 'formulario que la elija muestra el aviso, y su expediente cuenta qué pasó. La marca se levanta con '
|
||||||
|
+ 'otra acta de daño cuya disposición sea <b>«Reparada»</b>, o se vuelve permanente con <b>«Baja»</b>. '
|
||||||
|
+ 'No es para asignar culpas: es para que el daño no se pierda de vista.',
|
||||||
|
secciones: [
|
||||||
|
|
||||||
|
{ titulo: '0 · Qué se dañó y dónde',
|
||||||
|
items: [
|
||||||
|
{ tipo:'fecha', clave:'fecha', req:true, guardaEn:'fecha', txt:'Fecha del daño (o de cuando se detectó)' },
|
||||||
|
{ tipo:'radio', clave:'que', req:true, txt:'¿Qué es?',
|
||||||
|
opciones:['Tarjeta EinarBoard','Módulo ArduSimple','Módem 4G','Unidad HBOX completa','Otro (cable, antena, gabinete…)'] },
|
||||||
|
{ tipo:'radio', clave:'donde', req:true, txt:'¿Dónde ocurrió?',
|
||||||
|
opciones:['En el banco (prueba o flasheo)','Durante el ensamble','En transporte o almacén','En campo, instalada','No se sabe — así se encontró'] },
|
||||||
|
{ tipo:'texto', clave:'quien_detecto', rows:'1', txt:'¿Quién lo detectó y cómo?', ph:'Daniel, al medir continuidad antes de energizar' },
|
||||||
|
] },
|
||||||
|
|
||||||
|
{ titulo: '1 · Qué pasó',
|
||||||
|
sub:'Cuenta lo que viste, no lo que supones. "No se sabe" es una respuesta válida.',
|
||||||
|
items: [
|
||||||
|
{ tipo:'radio', clave:'clasificacion', req:true, guardaEn:'clasificacion', txt:'Tipo de daño',
|
||||||
|
opciones:[
|
||||||
|
'Corto a tierra',
|
||||||
|
'Sobrevoltaje o polaridad invertida',
|
||||||
|
'Componente quemado o sobrecalentado',
|
||||||
|
'Daño mecánico (golpe, pin doblado, conector roto)',
|
||||||
|
'Agua o corrosión',
|
||||||
|
'Batería dañada',
|
||||||
|
'Error de ensamble o soldadura',
|
||||||
|
'Falla sin causa aparente',
|
||||||
|
'Otro'] },
|
||||||
|
{ tipo:'radio', clave:'energizada', req:true, txt:'¿Estaba energizada cuando ocurrió?',
|
||||||
|
opciones:['Sí','No','No se sabe'] },
|
||||||
|
{ tipo:'texto', clave:'fuente', si:energizada, rows:'1', txt:'¿Con qué fuente y a cuánto?', ph:'Fuente de banco 24 V, límite 500 mA' },
|
||||||
|
{ tipo:'texto', clave:'haciendo', rows:'2', txt:'¿Qué se estaba haciendo en ese momento?',
|
||||||
|
ph:'Se conectaba el arnés del GX16 con la fuente encendida.' },
|
||||||
|
{ tipo:'texto', clave:'resumen', req:true, guardaEn:'resumen', rows:'2',
|
||||||
|
txt:'Resumen en una línea (es lo que verán los demás formularios como aviso)',
|
||||||
|
ph:'Corto VEH5V a GND en la zona de Q10; no energizar.' },
|
||||||
|
{ tipo:'texto', clave:'descripcion', req:true, rows:'4', txt:'Descripción completa',
|
||||||
|
ph:'Qué se midió, qué se vio, qué se olió, en qué orden pasó.' },
|
||||||
|
] },
|
||||||
|
|
||||||
|
{ titulo: '2 · Evidencia',
|
||||||
|
items: [
|
||||||
|
{ tipo:'foto', clave:'f_dano', req:true, etiqueta:'dano', txt:'El daño, de cerca.' },
|
||||||
|
{ tipo:'foto', clave:'f_general', etiqueta:'general', txt:'La pieza completa, para ubicar el daño.' },
|
||||||
|
{ tipo:'medida', clave:'r_corto', txt:'Si fue corto: resistencia medida a tierra', u:'Ω' },
|
||||||
|
{ tipo:'texto', clave:'componentes', rows:'2', txt:'Componentes afectados (designadores si los conoces)', ph:'Q10, D5, pista bajo U6' },
|
||||||
|
{ tipo:'archivo', clave:'log', etiqueta:'dano', txt:'Captura o log relacionado, si lo hay' },
|
||||||
|
] },
|
||||||
|
|
||||||
|
{ titulo: '3 · Disposición — esto es lo que MARCA la serie',
|
||||||
|
sub:'Lo último que se registre aquí es lo que vale. Para levantar una marca, registra una nueva acta con «Reparada».',
|
||||||
|
items: [
|
||||||
|
{ tipo:'radio', clave:'accion', req:true, guardaEn:'accion', txt:'¿Cómo queda?',
|
||||||
|
opciones:[
|
||||||
|
'Marcada como dañada — en espera de diagnóstico o reparación',
|
||||||
|
'Enviada a Querétaro para evaluación',
|
||||||
|
'Canibalizada — sus módulos buenos pasan a otra unidad',
|
||||||
|
'Reparada — vuelve a servicio (levanta la marca)',
|
||||||
|
'Baja definitiva (marca permanente)'],
|
||||||
|
aviso:'<b>Reparada</b> quita el aviso de los formularios. <b>Baja</b> lo vuelve permanente y la serie no debe volver a usarse ni instalarse.' },
|
||||||
|
{ tipo:'texto', clave:'reparacion', si:v=>String(v.accion||'').startsWith('Reparada'), rows:'2', req:true,
|
||||||
|
txt:'¿Qué se reparó y quién lo verificó?' },
|
||||||
|
{ tipo:'texto', clave:'modulos_rescatados', si:v=>String(v.accion||'').startsWith('Canibalizada'), rows:'2',
|
||||||
|
txt:'¿Qué módulos se rescataron y a dónde fueron?', ph:'ARD-010 y RTK-0006 quedan libres para otro ensamble' },
|
||||||
|
{ tipo:'check', clave:'etiquetada', txt:'La pieza quedó <b>etiquetada físicamente</b> como dañada (cinta roja o marcador) y separada de las buenas.' },
|
||||||
|
{ tipo:'texto', clave:'leccion', rows:'2', txt:'¿Qué habría evitado esto?',
|
||||||
|
ph:'Medir continuidad antes de energizar; la acta de banco ya lo pide en el paso 2.' },
|
||||||
|
] },
|
||||||
|
]
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
83
docs/formularios/envio.html
Normal file
83
docs/formularios/envio.html
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="es">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Acta de envío — HBOX</title>
|
||||||
|
<link rel="stylesheet" href="acta.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="acta"></div>
|
||||||
|
<script src="flota.js"></script>
|
||||||
|
<script src="series.js"></script>
|
||||||
|
<script src="acta.js"></script>
|
||||||
|
<script>
|
||||||
|
const conBateria = v => String(v.bateria || '').startsWith('Sí');
|
||||||
|
|
||||||
|
Acta.render({
|
||||||
|
tipo: 'envio',
|
||||||
|
repetible: true,
|
||||||
|
resultadoFijo: 'ENVIADA',
|
||||||
|
tecnicoDesdeUsuario: true,
|
||||||
|
nombres: { alan: 'Alán Basurto', daniel: 'Daniel Martínez', leo: 'Leo Rodríguez' },
|
||||||
|
unidades: window.SERIES,
|
||||||
|
etiquetaSerie: 'Unidad que se envía',
|
||||||
|
titulo: 'Acta de envío',
|
||||||
|
subtitulo: 'Helgen Technologies · se llena al cerrar la caja, no después.',
|
||||||
|
intro: '<b>Para qué sirve.</b> Fija el estado exacto en que salió la unidad: qué firmware traía, qué SIM, '
|
||||||
|
+ 'qué iba en la caja y cómo se veía. Cuando llegue, el acta de <b>recepción</b> se compara contra '
|
||||||
|
+ 'esta. Si algo falta o llegó golpeado, se sabe en qué tramo pasó.',
|
||||||
|
secciones: [
|
||||||
|
|
||||||
|
{ titulo: '0 · Qué se manda y a dónde',
|
||||||
|
items: [
|
||||||
|
{ tipo:'fecha', clave:'fecha', req:true, guardaEn:'fecha', txt:'Fecha de envío' },
|
||||||
|
{ tipo:'radio', clave:'destino', req:true, guardaEn:'clasificacion', txt:'Destino',
|
||||||
|
opciones:['ICAVE (Veracruz)','TIMSA','EIT','LCT','Taller Veracruz','Querétaro (regreso)','Otro'] },
|
||||||
|
{ tipo:'texto', clave:'maquina_destino', rows:'1', guardaEn:'maquina_id', txt:'Máquina a la que va, si ya se sabe', ph:'FL-JUN-060' },
|
||||||
|
{ tipo:'radio', clave:'medio', req:true, txt:'¿Cómo viaja?',
|
||||||
|
opciones:['Paquetería (guía abajo)','La lleva alguien de Helgen','La recoge el cliente'] },
|
||||||
|
{ tipo:'texto', clave:'guia', rows:'1', txt:'Número de guía o quién la lleva' },
|
||||||
|
] },
|
||||||
|
|
||||||
|
{ titulo: '1 · Antes de cerrar la caja — requisitos',
|
||||||
|
sub:'Si alguno de estos no se cumple, la unidad NO se envía.',
|
||||||
|
items: [
|
||||||
|
{ tipo:'check', clave:'prueba_final', req:true, txt:'Tiene <b>acta de prueba final aprobada</b> en el sitio (no vale "ya la probé").' },
|
||||||
|
{ tipo:'check', clave:'sin_marca', req:true, txt:'Al elegir la serie arriba <b>no apareció aviso de daño</b>.' },
|
||||||
|
{ tipo:'texto', clave:'fw', rows:'1', req:true, txt:'Firmware que trae (línea BOOT o banner de consola)', ph:'fw=3.0.4' },
|
||||||
|
{ tipo:'texto', clave:'iccid', rows:'1', req:true, txt:'ICCID de la SIM instalada' },
|
||||||
|
{ tipo:'texto', clave:'imei', rows:'1', txt:'IMEI del módem' },
|
||||||
|
{ tipo:'texto', clave:'id_estacion', rows:'1', txt:'ID de estación del módem (AS+K)' },
|
||||||
|
{ tipo:'check', clave:'config_flash', txt:'Configuración del ZED-F9P guardada en <b>FLASH</b> (no solo RAM).' },
|
||||||
|
] },
|
||||||
|
|
||||||
|
{ titulo: '2 · Lo que va en la caja',
|
||||||
|
items: [
|
||||||
|
{ tipo:'check', clave:'c_unidad', req:true, txt:'Unidad HBOX cerrada y etiquetada con su serie.' },
|
||||||
|
{ tipo:'check', clave:'c_ant_gnss', txt:'Antena GNSS con su cable.' },
|
||||||
|
{ tipo:'check', clave:'c_ant_lte', txt:'2 antenas LTE.' },
|
||||||
|
{ tipo:'check', clave:'c_gx16', txt:'Arnés GX16 hacia el gabinete.' },
|
||||||
|
{ tipo:'check', clave:'c_fuente', txt:'Fuente Mean Well y material de gabinete (si aplica).' },
|
||||||
|
{ tipo:'check', clave:'c_docs', txt:'Hoja impresa con serie, máquina destino y contacto de Helgen.' },
|
||||||
|
{ tipo:'texto', clave:'extras', rows:'2', txt:'Otras cosas que van (tornillería, cinchos, repuestos…)' },
|
||||||
|
{ tipo:'radio', clave:'bateria', req:true, txt:'¿Viaja con batería instalada?',
|
||||||
|
opciones:['Sí','No — se retiró','No tiene batería'],
|
||||||
|
aviso:'Una batería de litio <b>no viaja en avión</b> como carga normal. Si va por paquetería, confirma con ellos que va por tierra.' },
|
||||||
|
{ tipo:'medida', clave:'v_bat', si:conBateria, txt:'Voltaje de la batería al empacar', esperado:'3.6 – 4.0 V', u:'V' },
|
||||||
|
] },
|
||||||
|
|
||||||
|
{ titulo: '3 · Evidencia',
|
||||||
|
items: [
|
||||||
|
{ tipo:'foto', clave:'f_abierta', req:true, etiqueta:'caja-abierta', txt:'La caja abierta con todo adentro, antes de cerrar.' },
|
||||||
|
{ tipo:'foto', clave:'f_unidad', req:true, etiqueta:'unidad', txt:'La unidad con su etiqueta legible.' },
|
||||||
|
{ tipo:'foto', clave:'f_cerrada', etiqueta:'caja-cerrada', txt:'La caja cerrada y rotulada.' },
|
||||||
|
{ tipo:'radio', clave:'accion', req:true, guardaEn:'accion', txt:'Estado',
|
||||||
|
opciones:['Enviada','Lista pero detenida (explica abajo)'] },
|
||||||
|
{ tipo:'texto', clave:'observaciones', rows:'3', txt:'Observaciones' },
|
||||||
|
] },
|
||||||
|
]
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
91
docs/formularios/recepcion.html
Normal file
91
docs/formularios/recepcion.html
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="es">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Acta de recepción — HBOX</title>
|
||||||
|
<link rel="stylesheet" href="acta.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="acta"></div>
|
||||||
|
<script src="flota.js"></script>
|
||||||
|
<script src="series.js"></script>
|
||||||
|
<script src="acta.js"></script>
|
||||||
|
<script>
|
||||||
|
const enciende = v => String(v.enciende || '').startsWith('Sí');
|
||||||
|
|
||||||
|
Acta.render({
|
||||||
|
tipo: 'recepcion',
|
||||||
|
repetible: true,
|
||||||
|
tecnicoDesdeUsuario: true,
|
||||||
|
nombres: { alan: 'Alán Basurto', daniel: 'Daniel Martínez', leo: 'Leo Rodríguez' },
|
||||||
|
unidades: window.SERIES,
|
||||||
|
etiquetaSerie: 'Unidad que se recibe',
|
||||||
|
titulo: 'Acta de recepción',
|
||||||
|
subtitulo: 'Helgen Technologies · se llena al abrir la caja, ANTES de entrar al puerto.',
|
||||||
|
textoOK: 'LISTA PARA ENTRAR',
|
||||||
|
intro: '<b>Para qué sirve.</b> Es la última revisión antes de que la unidad cruce la puerta del puerto, '
|
||||||
|
+ 'donde ya no se puede regresar por un cable. Se compara contra el <b>acta de envío</b>: mismo '
|
||||||
|
+ 'firmware, misma SIM, mismo contenido. Lo que no coincida, aquí se detecta. Historial de la unidad: '
|
||||||
|
+ 'elige la serie y mira sus visitas anteriores arriba.',
|
||||||
|
secciones: [
|
||||||
|
|
||||||
|
{ titulo: '0 · Qué llega y dónde',
|
||||||
|
items: [
|
||||||
|
{ tipo:'fecha', clave:'fecha', req:true, guardaEn:'fecha', txt:'Fecha de recepción' },
|
||||||
|
{ tipo:'radio', clave:'donde', req:true, guardaEn:'clasificacion', txt:'¿Dónde la recibes?',
|
||||||
|
opciones:['Taller Veracruz','Oficina ICAVE','Otra terminal','Querétaro'] },
|
||||||
|
{ tipo:'texto', clave:'guia', rows:'1', txt:'Número de guía o quién la entregó' },
|
||||||
|
{ tipo:'texto', clave:'maquina_destino', rows:'1', guardaEn:'maquina_id', txt:'Máquina a la que va', ph:'FL-JUN-060' },
|
||||||
|
] },
|
||||||
|
|
||||||
|
{ titulo: '1 · El paquete, antes de abrir',
|
||||||
|
items: [
|
||||||
|
{ tipo:'foto', clave:'f_paquete', req:true, etiqueta:'paquete', txt:'La caja cerrada tal como llegó.' },
|
||||||
|
{ tipo:'radio', clave:'paquete', req:true, txt:'Estado del paquete',
|
||||||
|
opciones:['Intacto','Golpeado o aplastado','Abierto o con cinta distinta','Mojado'] },
|
||||||
|
{ tipo:'foto', clave:'f_dano_paquete', etiqueta:'paquete-dano', si:v=>!String(v.paquete||'').startsWith('Intacto'), req:true,
|
||||||
|
txt:'Foto del daño del paquete, antes de abrirlo.' },
|
||||||
|
] },
|
||||||
|
|
||||||
|
{ titulo: '2 · Contenido contra el acta de envío',
|
||||||
|
sub:'Abre el acta de envío de esta unidad (expediente) y compara punto por punto.',
|
||||||
|
items: [
|
||||||
|
{ tipo:'check', clave:'c_unidad', req:true, txt:'Unidad HBOX presente, etiqueta legible, <b>la serie coincide</b> con la del envío.' },
|
||||||
|
{ tipo:'check', clave:'c_ant_gnss', txt:'Antena GNSS con cable.' },
|
||||||
|
{ tipo:'check', clave:'c_ant_lte', txt:'2 antenas LTE.' },
|
||||||
|
{ tipo:'check', clave:'c_gx16', txt:'Arnés GX16.' },
|
||||||
|
{ tipo:'check', clave:'c_docs', txt:'Hoja con serie, máquina y contacto.' },
|
||||||
|
{ tipo:'texto', clave:'faltante', rows:'2', txt:'¿Falta algo o llegó algo de más?' },
|
||||||
|
{ tipo:'foto', clave:'f_contenido', req:true, etiqueta:'contenido', txt:'Todo el contenido desplegado.' },
|
||||||
|
] },
|
||||||
|
|
||||||
|
{ titulo: '3 · Prueba rápida de vida (5 minutos, en el taller)',
|
||||||
|
sub:'Con fuente de 24 V y las antenas conectadas. No hace falta cielo abierto para esto.',
|
||||||
|
items: [
|
||||||
|
{ tipo:'radio', clave:'enciende', req:true, txt:'¿Enciende y el LED parpadea?',
|
||||||
|
opciones:['Sí','No — LED apagado','Enciende pero se apaga'] },
|
||||||
|
{ tipo:'texto', clave:'fw', rows:'1', si:enciende, req:true, txt:'Firmware que reporta (línea BOOT)', ph:'fw=3.0.4' },
|
||||||
|
{ tipo:'check', clave:'fw_coincide', si:enciende, txt:'El firmware <b>coincide con el del acta de envío</b>.' },
|
||||||
|
{ tipo:'radio', clave:'modem', si:enciende, txt:'LED de red del módem 4G tras 3 minutos',
|
||||||
|
opciones:['Lento o fijo (registró)','Rápido (no registra)','Apagado'] },
|
||||||
|
{ tipo:'check', clave:'sim_ok', si:enciende, txt:'La SIM es la del acta de envío (ICCID coincide).' },
|
||||||
|
{ tipo:'archivo', clave:'log', etiqueta:'recepcion', si:enciende, txt:'Captura de la consola (opcional, pero útil si algo se ve raro)' },
|
||||||
|
] },
|
||||||
|
|
||||||
|
{ titulo: '4 · Veredicto',
|
||||||
|
items: [
|
||||||
|
{ tipo:'radio', clave:'accion', req:true, guardaEn:'accion', txt:'¿Entra al puerto?',
|
||||||
|
opciones:[
|
||||||
|
'Lista para entrar al puerto',
|
||||||
|
'Entra con observaciones (anótalas)',
|
||||||
|
'No entra — se queda en el taller para revisión',
|
||||||
|
'Rechazada — regresa a Querétaro'],
|
||||||
|
aviso:'Si no enciende o el firmware no coincide, <b>no entra</b>. Instalarla y descubrirlo arriba de una máquina cuesta una visita más y un permiso más.' },
|
||||||
|
{ tipo:'texto', clave:'observaciones', rows:'3', txt:'Observaciones' },
|
||||||
|
] },
|
||||||
|
]
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -70,7 +70,7 @@ Acta.render({
|
|||||||
sub:'DFU por USB del Blackpill. El binario se descarga del sitio, nunca de un USB que ande circulando.',
|
sub:'DFU por USB del Blackpill. El binario se descarga del sitio, nunca de un USB que ande circulando.',
|
||||||
items: [
|
items: [
|
||||||
{ tipo:'texto', clave:'bin_nombre', rows:'1', req:true,
|
{ tipo:'texto', clave:'bin_nombre', rows:'1', req:true,
|
||||||
txt:'Archivo binario que usaste (nombre completo)', ph:'hbox-fw-v3_X.Y.Z.bin' },
|
txt:'Archivo binario que usaste (nombre completo)', ph:'hbox-tarjetaV3_X.Y.Z.bin' },
|
||||||
{ tipo:'radio', clave:'bin_origen', req:true, txt:'¿De dónde lo sacaste?',
|
{ tipo:'radio', clave:'bin_origen', req:true, txt:'¿De dónde lo sacaste?',
|
||||||
opciones:['De la página de Descargas del sitio','Me lo pasó ingeniería directo','De otro lado'],
|
opciones:['De la página de Descargas del sitio','Me lo pasó ingeniería directo','De otro lado'],
|
||||||
aviso:'Si no salió del sitio ni de ingeniería, <b>detente</b>: un binario de la generación equivocada puede dejar la batería cargando cuando debería estar cortada.' },
|
aviso:'Si no salió del sitio ni de ingeniería, <b>detente</b>: un binario de la generación equivocada puede dejar la batería cargando cuando debería estar cortada.' },
|
||||||
|
|||||||
15
docs/formularios/series.js
Normal file
15
docs/formularios/series.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* Catálogo de series conocidas para actas que aplican a CUALQUIER cosa con número
|
||||||
|
(daños, envío, recepción). Junta la flota en campo con los lotes de producción. */
|
||||||
|
(function () {
|
||||||
|
const F = (window.FLOTA || []).map(u => ({ serie: u.serie, etiqueta: u.etiqueta, maquina: u.maquina,
|
||||||
|
terminal: 'Unidades en campo', nota: u.nota }));
|
||||||
|
const gen = (pref, n, pad, grupo, desc) => Array.from({ length: n }, (_, i) => {
|
||||||
|
const s = pref + '-' + String(i + 1).padStart(pad, '0');
|
||||||
|
return { serie: s, etiqueta: s + ' — ' + desc, terminal: grupo };
|
||||||
|
});
|
||||||
|
window.SERIES = F.concat(
|
||||||
|
gen('V5', 30, 2, 'Tarjetas EinarBoard V5', 'tarjeta EinarBoard v5'),
|
||||||
|
gen('ARD', 30, 3, 'Módulos simpleRTK2B Pro', 'módulo ArduSimple'),
|
||||||
|
gen('RTK', 30, 4, 'Módems 4G NTRIP Master', 'módem 4G')
|
||||||
|
);
|
||||||
|
})();
|
||||||
@ -41,6 +41,23 @@ Sitio interno de Helgen Technologies. **Busca abajo lo que vas a hacer hoy.**
|
|||||||
|
|
||||||
[Procedimiento de reflasheo](procedimientos/reflasheo-unidades.md)
|
[Procedimiento de reflasheo](procedimientos/reflasheo-unidades.md)
|
||||||
|
|
||||||
|
- ### 🚨 Algo se dañó
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Tarjeta con corto, módulo golpeado, unidad mojada. Registra el daño y la serie queda
|
||||||
|
**marcada**: cualquier acta que la elija mostrará el aviso.
|
||||||
|
|
||||||
|
[**▶ Acta de daño o incidente**](formularios/dano.html){ .md-button .md-button--primary }
|
||||||
|
|
||||||
|
- ### 📦 Sale o llega una unidad
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Qué salió en la caja y en qué estado llegó, antes de entrar al puerto.
|
||||||
|
|
||||||
|
[Acta de envío](formularios/envio.html) · [Acta de recepción](formularios/recepcion.html) · [Ciclo de vida](procedimientos/ciclo-de-vida.md)
|
||||||
|
|
||||||
- ### 🗂 Todo sobre una unidad
|
- ### 🗂 Todo sobre una unidad
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
103
docs/procedimientos/ciclo-de-vida.md
Normal file
103
docs/procedimientos/ciclo-de-vida.md
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
# El ciclo de vida de una unidad HBOX — qué acta en qué momento
|
||||||
|
|
||||||
|
**Versión:** 1.0 · 19-sep-2026 · **Responsable:** Leo Rodríguez
|
||||||
|
|
||||||
|
Una unidad pasa por nueve momentos entre la tarjeta desnuda y la máquina en el patio. Cada uno
|
||||||
|
tiene su procedimiento y su acta, y **todas las actas cuelgan del número de serie**, así que el
|
||||||
|
[expediente](../unidad.html) de cualquier tarjeta, módulo o unidad cuenta la historia completa —
|
||||||
|
incluidos los daños.
|
||||||
|
|
||||||
|
## El mapa
|
||||||
|
|
||||||
|
| # | Momento | Dónde | Procedimiento | Acta | Estado |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| 1 | **Tarjeta desnuda** llega de fábrica | Banco QRO | [Prueba y flasheo](v5-prueba-y-flasheo.md) | [Tarjeta V5](../formularios/v5.html) | ✅ |
|
||||||
|
| 2 | **Módulos** RTK y 4G, uno por uno | Banco QRO | [Módulos §2–3](v5-modulos-integracion.md) | [ArduSimple](../formularios/ardusimple.html) · [Módem 4G](../formularios/modem4g.html) | ✅ |
|
||||||
|
| 3 | **Pre-ensamble**: la pareja que irá junta | Banco QRO | [Módulos §4](v5-modulos-integracion.md) | [Integración](../formularios/integracion.html) | ✅ |
|
||||||
|
| 4 | **Ensamble** de la unidad | Banco QRO | [Ensamble](v5-ensamble.md) | [Ensamble](../formularios/ensamble.html) — no acepta módulos sin acta aprobada ni ya usados | ✅ |
|
||||||
|
| 5 | **Prueba final** antes de embarcar | Banco QRO | [Prueba final](v5-prueba-final-unidad.md) | *(se registra en la de ensamble)* | ✅ |
|
||||||
|
| 6 | **Envío** | QRO → terminal | [abajo](#6-envio) | [Envío](../formularios/envio.html) | 🆕 |
|
||||||
|
| 7 | **Recepción**, antes de entrar al puerto | Taller Veracruz | [abajo](#7-recepcion) | [Recepción](../formularios/recepcion.html) | 🆕 |
|
||||||
|
| 8 | **Instalación** en la máquina | Patio | ⬜ pendiente | ⬜ `instalacion-campo` (el servidor ya lo acepta) | ⬜ |
|
||||||
|
| 9 | **Vida en campo**: falla, diagnóstico, reflasheo | Patio / taller | [Campo](../diagnostico/procedimiento-diagnostico-campo.md) · [Banco](diagnostico-banco.md) · [Reflasheo](reflasheo-unidades.md) | [Campo](../formularios/diagnostico.html) · [Banco](../formularios/banco.html) · [Reflasheo](../formularios/reflasheo.html) | ✅ |
|
||||||
|
| ⚡ | **Daño o incidente**, en cualquier momento | Donde sea | [abajo](#dano-en-cualquier-momento) | [Daño](../formularios/dano.html) — **marca la serie** | 🆕 |
|
||||||
|
|
||||||
|
Lo único que falta del ciclo es el **8 · Instalación**. Se escribe con el mismo motor cuando
|
||||||
|
lo decidas: checklist de gabinete, GX16, antenas, foto final y primera posición vista en el servidor.
|
||||||
|
|
||||||
|
## Las tres reglas que cruzan todo el ciclo
|
||||||
|
|
||||||
|
**1 · Nada avanza sin acta.** Un módulo sin acta aprobada no entra al ensamble (el formulario lo
|
||||||
|
impide). Una unidad sin prueba final aprobada no se envía (el acta de envío lo pide). Una unidad
|
||||||
|
que no coincide con su acta de envío no entra al puerto (la de recepción lo pide).
|
||||||
|
|
||||||
|
**2 · Una serie dañada se ve desde cualquier acta.** Registrar un daño **marca** la serie. Desde
|
||||||
|
ese momento, todo formulario que la elija —banco, campo, ensamble, envío— muestra el aviso en
|
||||||
|
amarillo, con la fecha y el resumen. Así una tarjeta con un corto no puede acabar dentro de un
|
||||||
|
ensamble sin que alguien lo vea. La marca se levanta con otra acta de daño cuya disposición sea
|
||||||
|
**«Reparada»**, o se vuelve permanente con **«Baja»** (aviso en rojo).
|
||||||
|
|
||||||
|
**3 · La serie es la llave.** Tarjeta (`V5-06`), módulo (`ARD-010`, `RTK-0006`), unidad de campo
|
||||||
|
(`RTK-014`) o unidad ensamblada (`HBOX5-E06-A010-R0006`): todo lo que se registre contra una serie
|
||||||
|
aparece en su expediente, y un módulo además aparece en el expediente de la unidad que lo lleva.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6 · Envío
|
||||||
|
|
||||||
|
Se llena **al cerrar la caja**, no después. Fija el estado exacto en que salió la unidad para que
|
||||||
|
la recepción tenga contra qué comparar.
|
||||||
|
|
||||||
|
Requisitos que el acta exige antes de dejar enviar:
|
||||||
|
|
||||||
|
- Acta de **prueba final aprobada** en el sitio.
|
||||||
|
- **Sin marca de daño** en la serie.
|
||||||
|
- Firmware que trae (línea `BOOT`), **ICCID** de la SIM, ID de estación del módem.
|
||||||
|
- Configuración del ZED-F9P guardada en **FLASH**.
|
||||||
|
|
||||||
|
Contenido de la caja (cada punto es una casilla): unidad etiquetada · antena GNSS · 2 antenas LTE ·
|
||||||
|
arnés GX16 · material de gabinete si aplica · hoja impresa con serie, máquina destino y contacto.
|
||||||
|
|
||||||
|
!!! warning "Batería"
|
||||||
|
Una batería de litio **no viaja en avión** como carga normal. Si va por paquetería, confirmar
|
||||||
|
que va por tierra, y anotar su voltaje al empacar.
|
||||||
|
|
||||||
|
Fotos: la caja abierta con todo adentro, la unidad con su etiqueta legible, la caja cerrada y rotulada.
|
||||||
|
|
||||||
|
## 7 · Recepción
|
||||||
|
|
||||||
|
Se llena **al abrir la caja, antes de entrar al puerto** — la última oportunidad de regresar por un
|
||||||
|
cable. Se compara contra el acta de envío de esa unidad (está en su expediente).
|
||||||
|
|
||||||
|
1. **Paquete, antes de abrir:** foto tal como llegó; si viene golpeado, mojado o abierto, foto del daño.
|
||||||
|
2. **Contenido contra el envío:** misma serie, mismas piezas. Lo que falte o sobre, se anota.
|
||||||
|
3. **Prueba rápida de vida** (5 min, en el taller, fuente de 24 V): enciende y el LED parpadea ·
|
||||||
|
`BOOT` reporta el **mismo firmware** que el envío · el módem registra en Telcel (LED lento o fijo) ·
|
||||||
|
la SIM es la misma (ICCID).
|
||||||
|
4. **Veredicto:** lista para entrar · entra con observaciones · se queda en el taller · rechazada.
|
||||||
|
|
||||||
|
!!! danger "Si no enciende o el firmware no coincide, no entra"
|
||||||
|
Instalarla y descubrirlo arriba de una máquina cuesta una visita más y un permiso más de ICAVE.
|
||||||
|
|
||||||
|
## ⚡ Daño en cualquier momento
|
||||||
|
|
||||||
|
Para cualquier cosa con número de serie: tarjeta, módulo, unidad completa, o incluso un cable o
|
||||||
|
antena. No es para asignar culpas; es para que el daño **no se pierda de vista**.
|
||||||
|
|
||||||
|
Qué registra: qué es y dónde ocurrió · tipo de daño (corto, sobrevoltaje, quemado, golpe, agua,
|
||||||
|
batería, error de ensamble, sin causa aparente) · si estaba energizada y con qué · **resumen en
|
||||||
|
una línea** (es lo que ven los demás formularios) · descripción · foto del daño · componentes
|
||||||
|
afectados · **disposición**.
|
||||||
|
|
||||||
|
La disposición es lo que marca:
|
||||||
|
|
||||||
|
| Disposición | Efecto en la serie |
|
||||||
|
|---|---|
|
||||||
|
| Marcada como dañada — en espera | ⚠ aviso amarillo en todos los formularios |
|
||||||
|
| Enviada a Querétaro para evaluación | ⚠ aviso amarillo |
|
||||||
|
| Canibalizada — sus módulos buenos pasan a otra unidad | ⚠ aviso amarillo; anotar qué módulos quedan libres |
|
||||||
|
| **Reparada** — vuelve a servicio | levanta la marca |
|
||||||
|
| **Baja** definitiva | ⛔ aviso rojo, permanente |
|
||||||
|
|
||||||
|
Y una casilla que conviene no saltarse: **la pieza quedó etiquetada físicamente** (cinta roja) y
|
||||||
|
separada de las buenas. El sitio marca la serie; la cinta marca la tarjeta que alguien tiene en la mano.
|
||||||
@ -37,9 +37,9 @@ cuando debería estar cortada.
|
|||||||
|
|
||||||
| Generación de tarjeta | Binario | Estado |
|
| Generación de tarjeta | Binario | Estado |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| **V3** (flota desplegada: RTK-003, RTK-006, RTK-014) | `hbox-fw-v3_*.bin` | ⬜ pendiente de publicar |
|
| **V3** — EinarBoard 1.0 (RTK-003, RTK-006, RTK-014), Blackpill | `hbox-tarjetaV3_3.0.4.bin` · `hbox-tarjetaV3_4.0.0.bin` (telemetría) | ⚠ publicados, sin prueba de banco |
|
||||||
| **V4** | `hbox-fw-v4_*.bin` | ⬜ pendiente de publicar |
|
| **V4** — Blackpill + PCF8574/W5500/SC16IS752 | **ninguno** | ⛔ sin firmware: `blackpillrtkcode` choca en PB12–15 con el W5500 |
|
||||||
| **V5** (EinarBoard v5, banco) | `hbox-v5-bringup_0.4.0.bin` | ✅ publicado |
|
| **V5** — MCU soldado, lote de 15 | `hbox-v5-bringup_0.5.1.bin` | ✅ en despliegue |
|
||||||
|
|
||||||
Si el renglón dice *pendiente*, **no hay binario aprobado todavía**: el flasheo de esa generación
|
Si el renglón dice *pendiente*, **no hay binario aprobado todavía**: el flasheo de esa generación
|
||||||
está detenido hasta que ingeniería lo publique (§6).
|
está detenido hasta que ingeniería lo publique (§6).
|
||||||
@ -55,9 +55,9 @@ Verifica el archivo antes de flashear:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# macOS / Linux
|
# macOS / Linux
|
||||||
shasum -a 256 hbox-fw-v3_X.Y.Z.bin
|
shasum -a 256 hbox-tarjetaV3_X.Y.Z.bin
|
||||||
# Windows (PowerShell)
|
# Windows (PowerShell)
|
||||||
Get-FileHash .\hbox-fw-v3_X.Y.Z.bin -Algorithm SHA256
|
Get-FileHash .\hbox-tarjetaV3_X.Y.Z.bin -Algorithm SHA256
|
||||||
```
|
```
|
||||||
|
|
||||||
Debe coincidir **carácter por carácter** con el que publica `SHA256SUMS.txt`. Si no coincide,
|
Debe coincidir **carácter por carácter** con el que publica `SHA256SUMS.txt`. Si no coincide,
|
||||||
@ -76,7 +76,7 @@ descárgalo otra vez; si sigue sin coincidir, no lo uses y avisa.
|
|||||||
Si no aparece: repite la secuencia; si sigue sin salir, el cable no lleva datos o el MCU no arranca.
|
Si no aparece: repite la secuencia; si sigue sin salir, el cable no lleva datos o el MCU no arranca.
|
||||||
4. **Graba el binario** en la dirección **`0x08000000`**:
|
4. **Graba el binario** en la dirección **`0x08000000`**:
|
||||||
- *STM32CubeProgrammer* → conectar en **USB/DFU** → *Open file* → *Download*.
|
- *STM32CubeProgrammer* → conectar en **USB/DFU** → *Open file* → *Download*.
|
||||||
- o bien: `dfu-util -a 0 -s 0x08000000:leave -D hbox-fw-v3_X.Y.Z.bin`
|
- o bien: `dfu-util -a 0 -s 0x08000000:leave -D hbox-tarjetaV3_X.Y.Z.bin`
|
||||||
5. Espera a **«Download complete»** y **«Verify successful»**. Si falla a la mitad, **no desconectes**:
|
5. Espera a **«Download complete»** y **«Verify successful»**. Si falla a la mitad, **no desconectes**:
|
||||||
repite el paso 3 y vuelve a grabar.
|
repite el paso 3 y vuelve a grabar.
|
||||||
6. Presiona **RESET**.
|
6. Presiona **RESET**.
|
||||||
@ -143,8 +143,8 @@ arduino-cli compile \
|
|||||||
blackpillrtkcode_v3/ # o blackpillrtkcode_v4/ para la version con telemetria
|
blackpillrtkcode_v3/ # o blackpillrtkcode_v4/ para la version con telemetria
|
||||||
|
|
||||||
# 4. nómbralo por su versión y saca su huella
|
# 4. nómbralo por su versión y saca su huella
|
||||||
mv release/blackpillrtkcode_v3.ino.bin release/hbox-fw-v3_3.0.4.bin
|
mv release/blackpillrtkcode_v3.ino.bin release/hbox-tarjetaV3_3.0.4.bin
|
||||||
shasum -a 256 release/hbox-fw-v3_3.0.4.bin | tee -a release/SHA256SUMS
|
shasum -a 256 release/hbox-tarjetaV3_3.0.4.bin | tee -a release/SHA256SUMS
|
||||||
```
|
```
|
||||||
|
|
||||||
**El destino de tarjeta ya viene bien por omisión:** el propio `.ino` trae `TARGET_EINARBOARD 1` y
|
**El destino de tarjeta ya viene bien por omisión:** el propio `.ino` trae `TARGET_EINARBOARD 1` y
|
||||||
|
|||||||
@ -38,7 +38,7 @@ section.bloque .sub{color:var(--tinta2);font-size:13.5px;margin:0 0 12px}
|
|||||||
.ev::before{content:"";position:absolute;left:-27px;top:18px;width:11px;height:11px;border-radius:50%;
|
.ev::before{content:"";position:absolute;left:-27px;top:18px;width:11px;height:11px;border-radius:50%;
|
||||||
background:var(--pend);border:2px solid var(--papel)}
|
background:var(--pend);border:2px solid var(--papel)}
|
||||||
.ev.campo::before{background:var(--naranja)} .ev.banco::before{background:var(--info)}
|
.ev.campo::before{background:var(--naranja)} .ev.banco::before{background:var(--info)}
|
||||||
.ev.flash::before{background:#7048e8} .ev.prod::before{background:var(--ok)}
|
.ev.flash::before{background:#7048e8} .ev.prod::before{background:var(--ok)} .ev.falla::before{background:var(--falla)}
|
||||||
.ev .cab{display:flex;flex-wrap:wrap;gap:8px;align-items:baseline;justify-content:space-between}
|
.ev .cab{display:flex;flex-wrap:wrap;gap:8px;align-items:baseline;justify-content:space-between}
|
||||||
.ev .t{font-weight:700;font-size:15px}
|
.ev .t{font-weight:700;font-size:15px}
|
||||||
.ev .f{color:var(--tinta2);font-size:12.5px}
|
.ev .f{color:var(--tinta2);font-size:12.5px}
|
||||||
@ -92,6 +92,7 @@ const kb=n=>n>1048576?(n/1048576).toFixed(1)+' MB':Math.max(1,Math.round(n/1024)
|
|||||||
|
|
||||||
const NOMBRE={'diagnostico-campo':['Diagnóstico en campo','campo'],'diagnostico-banco':['Diagnóstico en banco','banco'],
|
const NOMBRE={'diagnostico-campo':['Diagnóstico en campo','campo'],'diagnostico-banco':['Diagnóstico en banco','banco'],
|
||||||
'reflasheo':['Reflasheo','flash'],'instalacion-campo':['Instalación en sitio','campo'],
|
'reflasheo':['Reflasheo','flash'],'instalacion-campo':['Instalación en sitio','campo'],
|
||||||
|
'dano':['⚡ Daño o incidente','falla'],'envio':['📦 Envío','prod'],'recepcion':['📦 Recepción','prod'],
|
||||||
'prueba-v5':['Prueba de tarjeta V5','prod'],'prueba-v4':['Prueba de tarjeta V4','prod'],
|
'prueba-v5':['Prueba de tarjeta V5','prod'],'prueba-v4':['Prueba de tarjeta V4','prod'],
|
||||||
'modulo-ard':['Módulo ArduSimple','prod'],'modulo-4g':['Módem 4G','prod'],
|
'modulo-ard':['Módulo ArduSimple','prod'],'modulo-4g':['Módem 4G','prod'],
|
||||||
'integracion':['Integración RTK + 4G','prod'],'ensamble':['Ensamble de unidad','prod']};
|
'integracion':['Integración RTK + 4G','prod'],'ensamble':['Ensamble de unidad','prod']};
|
||||||
@ -150,6 +151,13 @@ function render(j){
|
|||||||
? '<b>'+(u.maquina||'')+'</b> · '+(u.terminal||'')+(u.nota?'<br>'+u.nota:'')
|
? '<b>'+(u.maquina||'')+'</b> · '+(u.terminal||'')+(u.nota?'<br>'+u.nota:'')
|
||||||
: 'Esta serie no está en el registro de flota (flota.js).';
|
: 'Esta serie no está en el registro de flota (flota.js).';
|
||||||
|
|
||||||
|
if(j.marca){
|
||||||
|
const m=j.marca_acta||{};
|
||||||
|
cont.append(el('div',{class:'err',style:j.marca==='BAJA'?'':'background:#fff9db;color:#7a4a00;border-color:#f08c00',
|
||||||
|
html:(j.marca==='BAJA'?'⛔ <b>Serie dada de BAJA</b>':'⚠ <b>Serie marcada como DAÑADA</b>')
|
||||||
|
+(m.fecha?' desde el '+m.fecha:'')+(m.clasificacion?' — '+m.clasificacion:'')+(m.resumen?'<br>'+m.resumen:'')
|
||||||
|
+(m.accion?'<br>Disposición: '+m.accion:'')}));
|
||||||
|
}
|
||||||
const kp=el('div',{class:'kpis'});
|
const kp=el('div',{class:'kpis'});
|
||||||
[[j.total,'Actas registradas'],[j.total_fotos,'Fotos'],[j.total_logs,'Archivos de log'],
|
[[j.total,'Actas registradas'],[j.total_fotos,'Fotos'],[j.total_logs,'Archivos de log'],
|
||||||
[j.relacionadas.length,'Actas que la mencionan']]
|
[j.relacionadas.length,'Actas que la mencionan']]
|
||||||
|
|||||||
@ -75,6 +75,12 @@ nav:
|
|||||||
- "Firmware, parámetros 4G y ZED-F9P": descargas/index.md
|
- "Firmware, parámetros 4G y ZED-F9P": descargas/index.md
|
||||||
- "README firmware bring-up v5": descargas/hbox-v5-bringup-README.md
|
- "README firmware bring-up v5": descargas/hbox-v5-bringup-README.md
|
||||||
|
|
||||||
|
- "📦 Ciclo de vida — envío, recepción, daños":
|
||||||
|
- "El ciclo de vida de una unidad (mapa)": procedimientos/ciclo-de-vida.md
|
||||||
|
- "▶ Acta de envío": formularios/envio.html
|
||||||
|
- "▶ Acta de recepción (antes de entrar al puerto)": formularios/recepcion.html
|
||||||
|
- "▶ Acta de daño o incidente": formularios/dano.html
|
||||||
|
|
||||||
- "🗂 Expediente de una unidad": unidad.html
|
- "🗂 Expediente de una unidad": unidad.html
|
||||||
- "📋 Actas — índice y cómo se usan": actas/index.md
|
- "📋 Actas — índice y cómo se usan": actas/index.md
|
||||||
|
|
||||||
|
|||||||
@ -24,8 +24,8 @@ declare -a MAP=(
|
|||||||
# Descargas para técnicos (firmware de bring-up v5)
|
# Descargas para técnicos (firmware de bring-up v5)
|
||||||
"04-Source-Code/firmware/hbox_v5_bringup/release/hbox-v5-bringup_0.5.1.bin|docs/descargas/hbox-v5-bringup_0.5.1.bin"
|
"04-Source-Code/firmware/hbox_v5_bringup/release/hbox-v5-bringup_0.5.1.bin|docs/descargas/hbox-v5-bringup_0.5.1.bin"
|
||||||
"04-Source-Code/firmware/hbox_v5_bringup/release/superseded/hbox-v5-bringup_0.4.0.bin|docs/descargas/hbox-v5-bringup_0.4.0.bin"
|
"04-Source-Code/firmware/hbox_v5_bringup/release/superseded/hbox-v5-bringup_0.4.0.bin|docs/descargas/hbox-v5-bringup_0.4.0.bin"
|
||||||
"04-Source-Code/firmware/release/hbox-fw-v3_3.0.4.bin|docs/descargas/hbox-fw-v3_3.0.4.bin"
|
"04-Source-Code/firmware/release/hbox-tarjetaV3_3.0.4.bin|docs/descargas/hbox-tarjetaV3_3.0.4.bin"
|
||||||
"04-Source-Code/firmware/release/hbox-fw-v4_4.0.0.bin|docs/descargas/hbox-fw-v4_4.0.0.bin"
|
"04-Source-Code/firmware/release/hbox-tarjetaV3_4.0.0.bin|docs/descargas/hbox-tarjetaV3_4.0.0.bin"
|
||||||
"04-Source-Code/firmware/hbox_v5_bringup/README.md|docs/descargas/hbox-v5-bringup-README.md"
|
"04-Source-Code/firmware/hbox_v5_bringup/README.md|docs/descargas/hbox-v5-bringup-README.md"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user