Repository navigation
Build the TFT pictures and theme TFTs without the Editor, and check them in CI - #407
jamesmulcahy wants to merge 8 commits into
Conversation
|
Hey, this is fricking awesome! Do you happen to know if GIMP runs on docker for all our supported architectures? If so it should be possible to allow a user to upload any background image of the choice and rebuild the TFT, right? |
Oh, that's an interesting idea. I'm not 100% sure whether it's supported across all the NSPM architectures, but in principal, it could be used to do that for any where there is support. I think the gap here would be the existing, non-"all_numbered" pages which have been manually created, and I think include elements of the underlying background in them. They'd need something similar to what I did for the new |
|
@cablesandcoffee do you have anything to add regarding @jamesmulcahy answer above. As I'm not all the familiar with the Nextion editor it doesn't really tell me much. Is this something that is possible and should be further explored? Ie. take a look if we can get gimp included in all builds of NSPanelManager in order to recompile the .tfts with the background of users wish? |
|
Don't fully understand how this changes the workflow yet when adding new stuff to the tft but I guess it gets clearer when I have to use Nextion Editor again. It was a while since we did something there. But to the answer your question @tpanajott I need to ask @jamesmulcahy: What do you mean with "non-"all_numbered" pages which have been manually created" It's a while since I thought about the HMI files and the gimp scripts and everything so sorry for not really following. :) |
make_pictures.sh runs create_pictures_{eu,us}.sh in an Ubuntu 24.04
container. It has GIMP 2.10, which the Script-Fu needs, and ImageMagick
6.9.12, which made the committed pictures: 6.9.11 (Debian bookworm)
writes different colour-space endpoints into every BMP header. A gimp
shim runs gimp-console, so no X server is needed; --xvfb runs it under
Xvfb instead. Each run starts GIMP with a fresh profile, so the
container creates the folders and empty tag cache GIMP otherwise
complains about.
The container checks that every picture the Script-Fu saves was written,
since the scripts ignore GIMP's exit status.
Both regions reproduce every committed picture byte for byte.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds the nextion package, which the TFT build scripts share, starting with nextion.hmi: it reads an HMI project's pages and component attributes, skipping event code, and edits numeric attributes in place. An edit keeps endx/endy in step with x/y/w/h and re-stamps the page, so the Editor opens the result. The page stamp is CRC-32/MPEG-2 over the page with each byte widened to a 32-bit word, XORed with a constant that depends only on the page length; nextion.crc holds that CRC, which TFT checksums use too. hmi_tool.py lists pages and components and sets attributes from the command line. The Editor has opened its edits, including to files that still hold stale blocks from earlier saves, but once rejected one for a reason not yet found; a Save As in the Editor, then editing that copy, got past it, so set says so when a file holds stale blocks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The four themes differ only in pictures, so make_tfts.sh builds every theme's TFT from the one the Editor compiled into output_tft1/: each theme's pictures from all_numbered/ are converted to RGB565 and swapped into the template's picture slots, and the checksums recomputed. Slots keep their size, since header 2 is encrypted and cannot be rewritten. It refuses pictures that do not fit their slot, and theme pictures the Editor stored compressed, whose codec is not known. The checksum algorithm comes from https://github.com/UNUF/TFTTool, reimplemented in nextion.crc. Pictures are read with Pillow and numpy, listed in requirements.txt. The display orientation is a byte in header 1, so make_tfts.sh checks that a template has its region's (EU 270, US 180), and makes us_horizontal_mirrored from the EU TFTs by changing only that byte. Upstream compiled those in the Editor from the EU HMI at orientation 90, and they differ from the EU TFTs in exactly that byte and its checksums, so the AutoHotkey script and the orientation reminder for them go. Six of the eight committed TFTs come out byte-identical to the Editor's. In EU theme 2 and US theme 3, the Editor had stored one picture compressed; those two, and the mirrored theme 2 made from EU's, are rebuilt here with that picture stored raw, so the committed TFTs are what make_tfts.sh builds. A rebuilt TFT ran correctly on a panel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An image progress bar needs empty and full pictures exactly the bar's size, matching the page background in every theme. Rather than drawing and redrawing them by hand, a region's progress_bars.txt lists its bars, each with its colour, and make_pictures.sh makes their pictures after GIMP's: the empty bar is the page background cropped to the bar, from each theme's dithered pictures, and the full bar a fill in the bar's colour. Every bar must name its colour; there is no default. The fill is the same in every theme, since the Editor compresses flat pictures and the themes may differ only in pictures it stores raw. Pages not yet in gui.HMI are skipped with a note, and pictures that would overwrite GIMP's are refused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
check_build.py fails if a theme's all_numbered/ has gaps, if a progress bar's pictures are not what its bar in the HMI makes, if no theme's TFT holds exactly the HMI's pictures (the HMI stores each picture record as the TFT does), if a TFT has the wrong display orientation, or if a TFT is not what make_tfts.sh builds, us_horizontal_mirrored included. --rendered also compares freshly rendered pictures with the committed ones, by pixels; make_pictures.sh runs the picture checks after rendering. The TFT build workflow runs the unit tests and check_build.py on changes under docker/HMI_files/, then renders everything in Docker and runs check_build.py --rendered. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
README.md covers what to do after changing an HMI, make_pictures.sh, progress_bars.txt, make_tfts.sh, hmi_tool.py, the tests and checks, the nextion package, and how us_horizontal_mirrored is made. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The generic half of the nextion/ package (hmi, fonts, images, tft, crc) now lives in nextion-tools (https://github.com/jamesmulcahy/nextion-tools, on PyPI), with its own tests, format notes and CI, alongside a Nextion display emulator for testing firmware. requirements.txt pins nextion-tools 0.1.0, and make_pictures.sh passes the same requirement to the picture-rendering image. What is particular to this build (region, themes, bars) stays here, as tft_build/. So do the tests that check this project's own files: the page and component ids, fonts and event code the firmware relies on, and that the committed TFTs are what the build makes. The decoder, CRC and image tests moved with the code. The library also reads what the old package skipped: each component's event code, its explicit id and the page id, and the .zi fonts. hmi_tool.py gains `events`, `fonts` and `dump` subcommands to show them. Every TFT still rebuilds byte-identical, and check_build.py passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5bdb0dc to
6372e31
Compare
0.1.1 names the Editor's scrolling text component (type 55), which the media player page uses for the song and artist. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summary
Building the panel GUIs today means driving the Nextion Editor on Windows with AutoHotkey, once per theme: delete every picture, import the theme's pictures, compile. Picture rendering needs a desktop GIMP, and image progress bars need their pictures drawn by hand for every theme.
This makes everything except one Editor compile per region scriptable and headless, and checks it in CI:
make_pictures.shrenders every theme's pictures with GIMP in Docker, with no display.make_tfts.shbuilds all four themes' TFTs from the one TFT the Editor compiled, by swapping pictures and recomputing the checksums. It also buildsus_horizontal_mirroredfrom the EU TFTs.progress_bars.txtlists image progress bars with their colours, and their pictures are generated from the HMI. Nothing to draw, and nothing to redraw when a bar moves.hmi_tool.pyreads an HMI's pages, components, event code and fonts, and edits numeric attributes (position, size, picture IDs) without the Editor.check_build.pyand a CI workflow fail if the committed HMIs, pictures and TFTs don't agree.docker/HMI_files/tft_automation/README.mddocuments the workflow: what to do after changing an HMI, each script, and the checks.Byte-for-byte with what's committed
make_pictures.shreproduces every committed picture byte for byte. The container is Ubuntu 24.04 for GIMP 2.10, which the Script-Fu needs, and ImageMagick 6.9.12. Debian bookworm's 6.9.11 writes different colour-space endpoints into the BMP headers (metadata only, the pixels are the same).make_tfts.shbuilds. A rebuilt TFT has run on a panel.Commits
nextionpackage the scripts share.The Nextion file formats live in nextion-tools
Commit 7 moves the generic code (reading and editing HMIs, fonts, pictures, TFT checksums) out of this repo into nextion-tools, a small library on PyPI.
requirements.txtpinsnextion-tools[images]==0.1.1, and the Docker image installs that same version. What is particular to this build (regions, themes, progress bars) stays here, intft_build/, with the tests that check this project's own files.Why a separate library:
hmi_tool.pygainsevents,fontsanddumpto show them.The cost is a dependency on a package published from my GitHub account. It's pinned to an exact version, so nothing changes here until someone bumps it. If you'd rather keep the code in this repo, commit 7 can be dropped, and the first six commits stand on their own.
Limits
make_tfts.shrefuses a template in which a picture that differs between themes is stored compressed. It asks for a new template.hmi_tool.py setchanges numeric attributes only.Testing
check_build.pypass locally at every commit (46 tests after commit 7, installing nextion-tools from PyPI).make_pictures.shfollowed bycheck_build.py --renderedpasses for both regions.make_tfts.shhas run on panels.🤖 Generated with Claude Code