Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ All notable changes to SIMUT firmware.
## Unreleased

**Salvar on the panel's alarm-limits editor now saves the limits that were on the screen at the tap, not what the editor holds when Core 0 gets to the event. This closes F3 of the v2.13.0 *Known* list. A display-alignment preview that was not saved no longer outlives the alignment screen, on the original panel and on the Ângulo: whichever way the screen is left except during a firmware update, Core 1 puts the saved offset back
and repaints, and the next entry starts from it. Both fixes were found by reading the code, and both were checked on the bench on 2026-10-31, on the Pico W (the original panel) and on the Pico 2 W (the Ângulo). A third change, not run on a board, closes F4: on the Ângulo, `GET /api/keypad` no longer describes the original panel's keypad. It sends the faces, the state and the policy, and names the route that lists the Ângulo's keys; the two Ângulo images get 208 and 216 B smaller and the other nine are byte for byte what they were. A last change, which moves thirteen names between two headers of the original panel's keypad, changes no image: all eleven are sha256-equal to `main`'s.**
and repaints, and the next entry starts from it. Both fixes were found by reading the code, and both were checked on the bench on 2026-10-31, on the Pico W (the original panel) and on the Pico 2 W (the Ângulo). A third change, checked on the Pico 2 W on 2026-10-31, closes F4: on the Ângulo, `GET /api/keypad` no longer describes the original panel's keypad. It sends the faces, the state and the policy, and names the route that lists the Ângulo's keys; the two Ângulo images get 208 and 216 B smaller and the other nine are byte for byte what they were. A last change, which moves thirteen names between two headers of the original panel's keypad, changes no image: all eleven are sha256-equal to `main`'s.**

### The alarm-limits save on the panel

Expand Down Expand Up @@ -78,7 +78,7 @@ The gate warns for all three, as it did, because each is under one flash sector,
- **How it is switched.** Not by an `#if`: by a UI hook, `uiKeypadTargets( )`, which answers `nullptr` on the original (`src/ui/UiDriverMembers.h`) and `"/api/ui"` on the Ângulo (defined in the class, `src/ui/angulo/Members.h`, so that it is a constant the handler sees). `handleApiKeypad( )` builds the Ângulo's answer when the hook answers and returns; otherwise its old statements run, untouched. Each side is a constant, so the branch an image does not take is not in the image: the Ângulo's images carry neither the grid's format string nor the popup's, and the six original images with the route carry no `"targets"`. The feature-sprawl count does not move, and `tools/ui_texts_allow.json` names the route's literal in `Members.h` as a route path and not text the panel draws.
- **The bench tools.** `tools/panel_users_hw_test.py` and `tools/panel_fulltable_test.py` tap the original panel by the grid. They now read the route through one reader, `tools/keypad_answer.py`, which refuses an answer with `targets` and says to tap by `/api/ui`, as `tools/tft_ui/roteiro_ui.py` does (that script reads only `faces` and `kb`, and is untouched). `Rig` also checks once at its start, right after the web login, so a run stops before it makes the test accounts or re-points the telemetry, and it deletes the web login's own account (`smap`) before it stops. An answer with no `grid` and no `targets`, which is what a device older than v25 sends, still gets the v24 layout. `WebUI.h` does not read the route.
- **The tests.** `tools/test_keypad_answer.py`, in CI's `gates` job: an original answer, an Ângulo answer (refused, with a message that names `/api/ui` and `tools/tft_ui/roteiro_ui.py`), an answer older than v25 and the groups keyboard with its popup, that each tool reads the route only through the reader, and that each of the tool's two refusals deletes the web login's account before it stops (red before those fixes, which the review asked for). It was red before the reader existed (the module was missing), and it bites: with the refusal taken out exactly one case fails, the Ângulo's, and each of the three other lines it holds fails exactly the cases it serves. Outside the repository, a script read the eleven `firmware.bin` as bytes: on `6981fd93` it fails on both Ângulo images (no `,"targets":"`, and the `"pop":[%d` and `"grid":[` format strings still there), and on this tree all 49 of its checks pass. The three images with no TFT (`pico_w_alpha`, `pico_w_air`, `pico_wire`) never compiled the route and carry neither answer. `Rig.keypad_faces( )` of `6981fd93` against the new one gave the same result and the same state on 15 answers that are not the Ângulo's.
- **Not run on a board.** The answers were proved from the images' bytes and by the host tests; no device was contacted. The Ângulo's PIN keypad was not driven through `/api/ui` for this change.
- **Checked on the Pico 2 W (2026-10-31).** The answers were first proved from the images' bytes and by the host tests. After the merge, on the bench's Pico 2 W, with the PIN keypad on the glass: on v2.13.0's release candidate the route sent the original's grid (152 × 44 at 6, 72) and `tools/keypad_answer.py` accepted it, which is the defect; on `main` at `2bead926` it sent `"targets":"/api/ui"` and neither `grid` nor `pop`, and the reader refused it. On both, a PIN typed by `/api/ui`'s targets reached Settings. The board was written back byte for byte afterwards.

### Flash (`GET /api/keypad`)

Expand Down
4 changes: 2 additions & 2 deletions CHANGELOG.pt-BR.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Todas as mudanças notáveis do firmware SIMUT.
## Não lançado

**O Salvar do editor de limites de alarme do painel passa a salvar os limites que estavam na tela no toque, e não o que o editor guarda quando o Core 0 chega ao evento. Isto fecha o F3 da lista *Conhecido* da v2.13.0. Uma prévia do alinhamento da tela que não foi salva não sobrevive mais à saída da tela, no painel original e no Ângulo: por onde quer que a tela seja deixada, menos durante uma atualização do firmware, o Core 1 devolve o deslocamento gravado
e redesenha, e a entrada seguinte parte dele. As duas correções foram encontradas lendo o código, e as duas foram conferidas na bancada em 31/10/2026, no Pico W (o painel original) e no Pico 2 W (o Ângulo). Uma terceira mudança, que não rodou numa placa, fecha o F4: no Ângulo, o `GET /api/keypad` deixa de descrever o teclado do painel original. Ele manda as faces, o estado e a política, e nomeia a rota que lista as teclas do Ângulo; as duas imagens do Ângulo ficam 208 e 216 B menores e as outras nove são, byte a byte, o que eram. Uma última mudança, a de treze nomes entre dois cabeçalhos do teclado do painel original, não muda nenhuma imagem: as onze têm o mesmo sha256 da `main`.**
e redesenha, e a entrada seguinte parte dele. As duas correções foram encontradas lendo o código, e as duas foram conferidas na bancada em 31/10/2026, no Pico W (o painel original) e no Pico 2 W (o Ângulo). Uma terceira mudança, conferida no Pico 2 W em 31/10/2026, fecha o F4: no Ângulo, o `GET /api/keypad` deixa de descrever o teclado do painel original. Ele manda as faces, o estado e a política, e nomeia a rota que lista as teclas do Ângulo; as duas imagens do Ângulo ficam 208 e 216 B menores e as outras nove são, byte a byte, o que eram. Uma última mudança, a de treze nomes entre dois cabeçalhos do teclado do painel original, não muda nenhuma imagem: as onze têm o mesmo sha256 da `main`.**

### O Salvar dos limites de alarme no painel

Expand Down Expand Up @@ -79,7 +79,7 @@ O portão avisa nas três, como já avisava, porque cada uma está a menos de um
- **Como se escolhe.** Não por um `#if`: por um gancho do driver de UI, `uiKeypadTargets( )`, que responde `nullptr` no original (`src/ui/UiDriverMembers.h`) e `"/api/ui"` no Ângulo (definido na classe, em `src/ui/angulo/Members.h`, para ser uma constante que o handler enxerga). O `handleApiKeypad( )` monta a resposta do Ângulo quando o gancho responde e volta; senão, os comandos de antes rodam, intocados. Cada lado é uma constante, então o ramo que a imagem não toma não está na imagem: as imagens do Ângulo não levam a string de formato da grade nem a do popup, e as seis imagens originais com a rota não levam `"targets"`. A contagem do `check_feature_sprawl.py` não se move, e o `tools/ui_texts_allow.json` nomeia o literal da rota em `Members.h` como caminho de rota, e não texto que o painel desenha.
- **As ferramentas de bancada.** O `tools/panel_users_hw_test.py` e o `tools/panel_fulltable_test.py` tocam o painel original pela grade. Agora leem a rota por um leitor só, o `tools/keypad_answer.py`, que recusa uma resposta com `targets` e diz para tocar pelo `/api/ui`, como faz o `tools/tft_ui/roteiro_ui.py` (esse script lê só `faces` e `kb`, e não foi tocado). O `Rig` também confere uma vez no começo, logo depois do login web, para a rodada parar antes de criar as contas de teste ou de apontar a telemetria para outro lugar, e apaga a conta do próprio login web (`smap`) antes de parar. Uma resposta sem `grid` e sem `targets`, que é o que manda um aparelho anterior à v25, continua recebendo o desenho da v24. A `WebUI.h` não lê a rota.
- **Os testes.** O `tools/test_keypad_answer.py`, no job `gates` da CI: uma resposta do original, uma do Ângulo (recusada, com uma mensagem que nomeia o `/api/ui` e o `tools/tft_ui/roteiro_ui.py`), uma anterior à v25 e o teclado de grupos com o popup, que cada ferramenta lê a rota só pelo leitor, e que cada uma das duas recusas da ferramenta apaga a conta do login web antes de parar (vermelho antes desses consertos, que a revisão pediu). Ele estava vermelho antes de o leitor existir (faltava o módulo), e morde: com a recusa tirada falha exatamente um caso, o do Ângulo, e cada uma das outras três linhas que ele segura reprova exatamente os casos a que serve. Fora do repositório, um script leu os onze `firmware.bin` como bytes: no `6981fd93` ele reprova as duas imagens do Ângulo (sem `,"targets":"`, e com as strings de formato `"pop":[%d` e `"grid":[` ainda lá), e nesta árvore passam os 49 testes dele. As três imagens sem TFT (`pico_w_alpha`, `pico_w_air`, `pico_wire`) nunca compilaram a rota e não levam nenhuma das respostas. O `Rig.keypad_faces( )` do `6981fd93` contra o novo deu o mesmo resultado e o mesmo estado em 15 respostas que não são as do Ângulo.
- **Não rodou numa placa.** As respostas foram provadas pelos bytes das imagens e pelos testes do host; nenhum aparelho foi contatado. O teclado de PIN do Ângulo não foi dirigido pelo `/api/ui` para esta mudança.
- **Conferido no Pico 2 W (31/10/2026).** As respostas foram provadas primeiro pelos bytes das imagens e pelos testes do host. Depois do merge, no Pico 2 W da bancada, com o teclado de PIN na tela: na candidata da v2.13.0 a rota mandou a grade do original (152 × 44 em 6, 72) e o `tools/keypad_answer.py` a aceitou, que é o defeito; na `main` em `2bead926` ela mandou `"targets":"/api/ui"` e nem `grid` nem `pop`, e o leitor a recusou. Nas duas, um PIN digitado pelos alvos do `/api/ui` chegou aos Ajustes. A placa foi regravada byte a byte no fim.

### Flash (`GET /api/keypad`)

Expand Down
1 change: 1 addition & 0 deletions docs/VERIFICATION.es-ES.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Lo que se ha medido en hardware real, de lo más reciente a lo más antiguo:

| Fecha | Qué | Resultado |
|---|---|---|
| 31/10/2026 | `GET /api/keypad` en el Ângulo (#311, F4), en la Pico 2 W, `main` en `2bead926` | Con el teclado de PIN en la pantalla: el candidato de la v2.13.0 (el control negativo) envió la cuadrícula del panel original (152 × 44 en 6, 72) y `tools/keypad_answer.py` la aceptó; `main` envió `"targets":"/api/ui"` y ni `grid` ni `pop`, y el lector la rechazó. En los dos, un PIN tecleado por los objetivos de `/api/ui` llegó al menú de ajustes, y la vuelta por inactividad llegó 34,6 s después del último toque. La placa se regrabó byte a byte al final |
| 31/10/2026 | El Guardar de los límites de alarma en el panel (#307) y la alineación de la pantalla (#308) en `main` (`96f503aa`), en la Pico W (panel original) y en la Pico 2 W (Ângulo) | Alineación, primero en la v2.13.0 (en la Pico 2 W, su candidata) y después en `main`: una vista previa de un paso a la Izquierda, la vuelta por inactividad de 30 s (31,7 a 35,2 s después del último toque), una entrada nueva. La v2.13.0 devolvió el dashboard desplazado (−1, 0) en los dos paneles, y su entrada nueva tomó el desplazamiento por el guardado; `main` lo devolvió en (0, 0) y empezó la entrada nueva en el desplazamiento guardado. Límites, en `main`: el MIN un paso abajo y el MAX un paso arriba, después Guardar: de la configuración que informa la API web, solo cambiaron esos dos valores (1,9 → 1,8, 24,0 → 24,1), además de valores de estado como la longitud de la cola de telemetría de alarmas, con una escritura y un registro `APP_UI_ALARM_SAVED`, y un segundo Guardar los devolvió de la misma forma; en la Pico W el receptor de telemetría recibió un registro `alarm_lim` por Guardar, con los límites nuevos y la cuenta. Una ronda en la Pico W mostró el dashboard con el pie de la pantalla de alineación debajo en la primera captura tras la entrada: una captura rasgada por la vuelta por inactividad de 30 s, no un defecto del panel. La captura lee la pantalla de abajo hacia arriba, 16 filas cada vez, y deja correr el panel entre bloques; las 32 filas de abajo muestran la pantalla de alineación y el resto el dashboard, una frontera que corta el botón SAIR, algo que ninguna pantalla dibuja. El primer intento se cortó (`WEB_SCREENSHOT_ABORTED` a las 14:27:34), y el reintento se guardó unos 40 s después del toque que abrió la pantalla (el toque no tiene hora; estimado con las dos rondas limpias). No se sabe por qué se cortaron las capturas de esa ronda, cuatro seguidas. Las dos placas se regrabaron byte a byte al final |
| 31/10/2026 | Candidato a release (v2.13.0) en la Pico W, firmado por el CI | Suite web con 67 aprobados, 0 fallos y 1 omitido en el candidato; actualización por el aire desde la v2.12.0 publicada en la release, el Air y el alpha: el `system.bin` idéntico byte a byte, todos los valores de configuración que informa la API web iguales (539 en la release, 530 en el alpha y el Air; tres sensores leyendo), el `.bkp` restaurado con 73 de 77 archivos idénticos en la release (los otros son el cursor de la telemetría, el bloque abierto del historial, el archivo del día y el log), el slot igual a la parte de la imagen (en el alpha y el Air salvo el sector de 4 KiB del banco de flash del BTstack); el candidato sobre sí mismo, comprobando su propia firma; de vuelta a la v2.12.0 por el aire y de nuevo hacia arriba, la configuración igual y el primer envío de cada versión visto en un receptor; una imagen sin firma (8), la del Air (7), la de la Pico 2 W (6) y el candidato con un byte cambiado (9) rechazadas, la configuración igual tras un reinicio; un envío cortado a 400 kB y un reinicio, con y sin el sistema de archivos lleno en medio: configuración intacta; la #283 en el Air, por primera vez en una placa: con el pack pt-BR solo en `/lang`, un despertar escribió el 567 una vez y nada del preámbulo del arranque, y el arranque siguiente registró `I18N_PACK_LOADED`; el techo de los archivos de idioma: la v2.12.0 rechaza el pack de 53.035 B y el candidato lo carga (el es-ES de 55.064 B también); 30 min sin reinicio con el cable del RESET de la PicoHand en el pin RUN (120 muestras, tres sensores con valor, heap libre de 54.932 a 55.068 B); `clk_peri` 133 MHz y `tft_hz` 66,50 MHz, la pantalla mirada por el mantenedor (sin píxeles sueltos, el toque responde), `/license` 200 con 16.400 B; la placa escrita de vuelta a su dump de llegada, byte a byte |
| 30/10/2026 | Candidato a release (v2.13.0) en la Pico 2 W, firmado por el CI | Suite web con 67 aprobados, 0 fallos y 1 omitido en el candidato; desde la v2.12.0 por su `.uf2` de fábrica, por el aire: en el otro slot, a prueba, confirmada 45,7 s después de volver, los 527 valores de configuración que informa la API web iguales (tres sensores), y `/api/ui` 401 donde la v2.12.0 daba 302 (el Ángulo dibujado); el candidato con un byte cambiado (9) y una imagen firmada con la clave de banco (12) rechazados; el candidato sobre sí mismo, dos veces; el `.uf2` de fábrica del candidato copiado a la unidad del BOOTSEL desde el slot B, tras un control (BOOTSEL sin grabar nada: la placa siguió en el B): arriba en la 2.13.0 desde el slot A, la configuración igual; 30 min sin reinicio (118 lecturas), tres sensores leyendo, heap libre de 296.732 a 296.852 B; la retención entre el panel original de la v2.12.0 y el Ángulo (C5, 15 pasos, en los dos sentidos): los 527 valores iguales en cada paso, el número de tema guardado leído como dice la regla de `UI_DRIVERS.md` (el 7 como `simut_def` en el original), el pack de 53.035 B rechazado por la v2.12.0 y cargado por las dos imágenes 2.13.0, ningún cuadro de fábrica en la consola donde se capturó, 16 capturas de la pantalla juzgadas por la sesión (17 tomadas); `clk_peri` 150 MHz y `tft_hz` 37,50 MHz; la caminata táctil con 15 aprobados y 0 fallos; la caminata de idiomas con 66 aprobados y 0 fallos; la caminata completa del Ángulo con 10 aprobados en la tercera pasada (las dos primeras se detuvieron en una captura de pantalla cortada); la placa quedó en el candidato |
Expand Down
Loading
Loading