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
81 changes: 81 additions & 0 deletions .github/workflows/docs-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Publishes the manual in documentation-site/ to 76cb/OpenTag-Station-Docs, whose own workflow
# builds and deploys GitHub Pages. Runs on every merge to main that changes the manual, pre-release
# versions included. One-time setup (deploy key and the DOCS_DEPLOY_KEY secret) is described in
# documentation-site/README.md under "Publish".
name: Publish manual

on:
push:
branches: [main]
paths:
- 'documentation-site/**'
- VERSION
- tools/export_docs.py
workflow_dispatch:

permissions:
contents: read

concurrency:
group: docs-publish
cancel-in-progress: false

jobs:
publish:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
# The same checks as the CI documentation job.
- run: python -m pip install -r documentation-site/requirements.txt
- run: python tools/check_public_privacy.py
- run: python tools/check_hardware_docs.py
- run: python tools/export_docs.py --check
- run: python tools/check_committed_images.py
- run: python documentation-site/scripts/check_images.py
- run: python -m mkdocs build --strict -f documentation-site/mkdocs.yml
- run: python documentation-site/scripts/validate.py documentation-site/site
- run: python tools/export_docs.py --output "$RUNNER_TEMP/export"
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
repository: 76cb/OpenTag-Station-Docs
ref: main
path: docs-repo
fetch-depth: 0
ssh-key: ${{ secrets.DOCS_DEPLOY_KEY }}
persist-credentials: true
# --delete removes manual files that no longer exist; the Docs repository keeps its own
# .git, deploy workflow and .gitignore.
- run: rsync -a --delete --exclude=.git --exclude=.github --exclude=.gitignore "$RUNNER_TEMP/export/" docs-repo/
- id: changes
working-directory: docs-repo
run: |
if [ -z "$(git status --porcelain)" ]; then
echo "Manual already up to date"
echo "changed=false" >> "$GITHUB_OUTPUT"
else
git status --short
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
# The Docs repository's own checks, so a broken export never reaches its main.
- if: steps.changes.outputs.changed == 'true'
working-directory: docs-repo
run: |
python -m pip install -r requirements.txt
python scripts/validate.py docs
python scripts/check_images.py
python -m mkdocs build --strict
python scripts/validate.py site
rm -rf site
- if: steps.changes.outputs.changed == 'true'
working-directory: docs-repo
env:
SOURCE_SHA: ${{ github.sha }}
run: |
git config user.name 'github-actions[bot]'
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
git add -A
git commit -m "Manual for $(cat ../VERSION) from 76cb/OpenTag-Station@${SOURCE_SHA::7}"
git push origin HEAD:main
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,40 @@

What changed in each version of OpenTag Station, newest first.

## 1.0.1-beta.5

Pre-release for testers. First step of the tag-support roadmap (#93): the reader now also looks
for ISO 14443A (NFC-A) tags and names them. Nothing is read from them yet. Not run on a WT32 by
the author; see "Needs a station" below.

**NFC**
- **NTAG, MIFARE and other NFC-A tags are found and named.** Each poll cycle still asks for
NFC-V (ISO 15693) tags first, exactly as before. Only when that finds nothing, and no NFC-V tag
is being tracked, does the same cycle also run an ISO 14443A detection (REQA and anticollision).
So an OpenPrintTag is found and lost on the same polls as in 1.0.1-beta.4; the only added cost
is one short NFC-A request on cycles with no NFC-V tag.
- An NFC-A tag is reported with its NFCID1, SAK and ATQA and a kind derived from the SAK (NXP
AN10833): `type2` (NTAG, MIFARE Ultralight), `mifare_classic`, `type4` or `other`. Nothing on
the tag is read, it is not looked up in Spoolman, and the automatic weigh does not start for it.
- Touchscreen: Home shows "TAG FOUND" / "Tag type not supported yet" with the kind; the Tag page
shows the kind and the ID; the NFC READER setup step says "Tag found. Its type is not supported
yet." Browser: the Dashboard shows "Tag type not supported yet" / "Not supported yet", Manage
tag names the kind, and "Multiple NFC-A tags detected" when there are several.
- API: `GET /api/v1/nfc` gains `technology` (`nfcv`, `nfca` or null) and, for an NFC-A tag, the
state `unsupported_technology`, lifecycle `UNSUPPORTED_TYPE`, the NFCID1 as `uid` and an `nfca`
object (`nfcid1`, `length`, `sak`, `atqa`, `kind`, `description`). `inventory.technology` now
names the technology of the tag on the reader.
- The serial diagnostic line adds `technology=` and, for an NFC-A tag, its NFCID1, SAK, ATQA and
kind.
- The production NFC check (`tools/check_production_nfc.py`) permits exactly three NFC-A RFAL
calls (mode switch, technology detection, collision resolution) in the I2C driver only, and
the ELF check now also fails if a Type 2 read or write, ISO-DEP or NFC-DEP routine is linked.

**Needs a station**
- Detection and removal timing of an OpenPrintTag before and after this change, and the
detection of an NTAG and a MIFARE Classic tag, have not been measured by the author. The
acceptance steps are in the pull request for this release and in issue #93.

## 1.0.1-beta.4

Pre-release for testers. The Community catalog is gone, and the leftovers from the 1.1 cleanup
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ The manual's source is in [`documentation-site/`](documentation-site/README.md).

| Tag family | Spools and tags | Plan |
|---|---|---|
| MIFARE Classic (ISO 14443A) | Bambu Lab, Creality CFS, Anycubic ACE, QIDI Box | Read first. Write where the format allows it. |
| NTAG (ISO 14443A) | OpenSpool, plain NTAG213 / 215 / 216 stickers | Read and write |
| MIFARE Classic (ISO 14443A) | Bambu Lab, Creality CFS, Anycubic ACE, QIDI Box | Detected and named since 1.0.1-beta.5. Read first. Write where the format allows it. |
| NTAG (ISO 14443A) | OpenSpool, plain NTAG213 / 215 / 216 stickers | Detected and named since 1.0.1-beta.5. Read and write |
| Other ISO 15693 chips | Tags that are not SLIX2 | Write support. They are read today. |
| ISO 14443B, FeliCa | Nothing on spools that the project knows of | Added if a spool system adopts them |

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.1-beta.4
1.0.1-beta.5
7 changes: 6 additions & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,12 @@ and its grace period have ended (`src/nfc/worker_startup.hpp`).
## Data flow

**Read a tag.** `BackendWorker::poll_nfc()` → `NfcWorker::poll()` → `ReadOnlyService`: inventory,
two full reads that must match, `Codec::decode`. The result is handed to `StationWorkflow`, which
two full reads that must match, `Codec::decode`. Each poll cycle (`src/nfc/poll_schedule.hpp`,
every 500 ms) runs the NFC-V inventory first, as it always has; only when that finds nothing and no
NFC-V tag is being tracked does the same field window also run an ISO 14443A detection
(`I2cReader::inventory_nfca()`: mode switch, REQA, anticollision). An NFC-A tag is reported as
`ReadState::unsupported_technology` with its NFCID1, SAK and ATQA (`nfc::nfca::Identity`); nothing
is read from it and it is not handed to the workflow (#93). The result is handed to `StationWorkflow`, which
uses `SpoolIdentityResolver` and `SpoolmanAdapter` to find the spool. `StationWorkflow` stages:
`awaiting_spool`, `resolving_spool`, `spool_resolution_unavailable`, `spool_not_found`,
`spool_selection_required`, `spool_ready`, `assignment_complete`. `waiting_for_stable_weight` is
Expand Down
Binary file modified docs/images/assignment.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/dashboard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 8 additions & 8 deletions docs/images/provenance.json
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
{
"privacy_checked_before_capture": true,
"browser_captures": 80,
"touch_layout_fixtures": 42,
"touch_layout_fixtures": 43,
"sources": {
"tools/product_journeys.cjs": "3675d1bda218f4932fde3e8b232b5aac75ae1bb196b85fe92705c53e3b15e9ab",
"tools/product_review.py": "376adaa8e3c6255ad7bf4e73cc35e53e7f9ccb6acdc8610ee77ccf39a3a6cffd",
"tools/test_writer_display.py": "e75bcccecc8e79862928d63c072bfa8c4f5eb6463f4a1dae8a91f9610104ace9",
"tools/capture_product_review.cjs": "23d6c11b616ac2c271e980410b162d71cf69b72575a452926794bf4838fe22d0",
"tools/render_touch_review.py": "8cb523c706690f681f2dc887a726b21e99de020a4d8ec00a9708982073daeeac",
"tools/check_public_privacy.py": "b5b3fc8482b8e9692e1524002b911cbcace8c213fd180454469f7c4963ebacd9",
"src/web/web_assets.cpp": "cf10ec9b702f74a4b06ab9e7edc2746d1bfe1d2aa378d38991b61d6711bf1342",
"src/web/web_assets.cpp": "b565808d7de2cb95615d7ae49db614e4303aec28e91f5ae3ab8c61fa3eefb84c",
"src/web/writer_assets.cpp": "18ca31fb929c43f13138fbd4839e4ed60dc10e342cc2c0dbabb6e95d4c8a48c7",
"src/web/writer_layout.inc": "c8835b92d1951269254fec884fe210fc725060528e5505e18a207fbe23d67f98",
"src/ui/product_layout.hpp": "4b3139a7f8e95142f53b72a4c9f4ac05d103426a29210885823b30b3171c8979",
"src/ui/tag_flow.hpp": "e960c1ef2412f9c6c9b64c6c41801045bc640323645df17bf2978da370942f1f",
"src/ui/tag_flow.hpp": "44647a07d972e510c8363d115382c4e8fbdf3c1ef48686cdae0f8a8aee66d3dd",
"src/ui/touch_input.hpp": "80fa15c718726adbbd3c35173479826f2c1bc0b8ff9a63133e737b17b3998eed",
"test/test_touch_flow/fixtures.hpp": "b9a846f95e3824b2dd7e416935695d672fa57a4cbf573889a6d9eb9a44832247"
"test/test_touch_flow/fixtures.hpp": "e895bf1032a0ddb04a71178fdc8ac3169fb3457274c376ff3e5bbf333f4efe1a"
},
"images": {
"docs/images/dashboard.png": "85e32b85fd99ced2cc3abbfcbf2a5628f52233c39494780ec4fa5f828d6f4455",
"docs/images/weigh.png": "fc9770fe4c4d3ed408b000855673fa64dd3f54ebbc094194869044961cbf2f6f",
"docs/images/assignment.png": "d8607ee2bbd563e83d3977f59a104f03af97e2d66db878d2665fcdf014ed4f9a",
"docs/images/tag-management.png": "d62ec05ca6a84589217054bb333af84ac59fd6987d553c7305b977fce4448356",
"docs/images/dashboard.png": "5a532d455b3d67bd8199043b2b11bb1deba036ae776484082fcac62fd14aace5",
"docs/images/weigh.png": "2a2b2b70419ec4038aa37ef2ad630ef77f13cf2230f444a684805f1750df6bc4",
"docs/images/assignment.png": "60dcdb03a77d12639f0964a8fc2d26d441a9e4c4aa7fb51ae7f7af53387a1362",
"docs/images/tag-management.png": "41772e6e29be1725052d1df0e352fa874850da612c915ed112d030536057df1c",
"docs/images/wt32-home.png": "c768e1b3be568f2563bdf0a368f2cf5b4aab2e2e6efb8a98c8a996ff4dcdc7e3"
}
}
Binary file modified docs/images/tag-management.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/weigh.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 21 additions & 2 deletions documentation-site/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,31 @@ CI runs the same checks on every pull request.

## Publish

A merge to `main` that changes `documentation-site/`, `VERSION` or `tools/export_docs.py` publishes
the manual automatically: the workflow `.github/workflows/docs-publish.yml` ("Publish manual") runs
the checks above, exports the manual, syncs the export over a checkout of
`76cb/OpenTag-Station-Docs` (removing files that no longer exist there, keeping that repository's
`.git`, `.github` and `.gitignore`), runs the Docs repository's own checks, and pushes a commit
`Manual for <version> from 76cb/OpenTag-Station@<commit>` to its `main`. That repository's workflow
then builds and deploys GitHub Pages. Pre-release versions are published too. When nothing changed,
the workflow prints `Manual already up to date` and stops.

To inspect the export locally:

```sh
python tools/export_docs.py --output <empty-directory>
```

Copy the exported files over a clone of `76cb/OpenTag-Station-Docs` (keep its `.git` directory),
commit and push. That repository's workflow runs the same checks and deploys to GitHub Pages.
The export stamps the firmware commit and version into `firmware.json`.

One-time setup, needed before the first run:

1. Generate a key pair: `ssh-keygen -t ed25519 -N "" -f docs-deploy-key`.
2. On `76cb/OpenTag-Station-Docs`, add `docs-deploy-key.pub` as a deploy key with write access
(Settings → Deploy keys → Add deploy key, tick **Allow write access**).
3. On `76cb/OpenTag-Station`, add the private key `docs-deploy-key` as the repository secret
`DOCS_DEPLOY_KEY` (Settings → Secrets and variables → Actions → New repository secret).
4. Run the workflow once by hand: Actions → **Publish manual** → **Run workflow**. This first run
brings the Docs repository up to date.

The manual is under the firmware's [PolyForm Noncommercial license](LICENSE.md).
Binary file modified documentation-site/docs/assets/images/browser/assignment.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified documentation-site/docs/assets/images/browser/dashboard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified documentation-site/docs/assets/images/browser/tag-management.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified documentation-site/docs/assets/images/browser/weigh.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 14 additions & 6 deletions documentation-site/docs/contributing/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ publishes it, then updates the USB installer from the same files.
Before a release, run the [hardware acceptance](testing.md#hardware-acceptance) checks on a real
station.

The current version is `1.0.1-beta.4`.
The current version is `1.0.1-beta.5`.

## Version names

Expand Down Expand Up @@ -55,13 +55,21 @@ workflow); when the release already exists it only redeploys the installer from

## Publish the manual

The manual is not published automatically. It is exported from the firmware repository and
committed to <https://github.com/76cb/OpenTag-Station-Docs>, which deploys it.
The manual is published automatically. A merge to `main` that changes `documentation-site/`,
`VERSION` or `tools/export_docs.py` runs the workflow **Publish manual**
(`.github/workflows/docs-publish.yml`). It checks the manual, exports it, and pushes the export to
<https://github.com/76cb/OpenTag-Station-Docs>, which deploys it. Pre-release versions are published
too. The commit there is named `Manual for <version> from 76cb/OpenTag-Station@<commit>`; when
nothing changed the workflow prints `Manual already up to date`.

The export copies `documentation-site/`, records the firmware version and commit in `firmware.json`,
and points links to repository files at that commit. To look at it without publishing:

```sh
python tools/export_docs.py --output <empty-directory>
```

The export copies `documentation-site/`, records the firmware version and commit, and points
links to repository files at that commit. Copy the result into a clone of the Docs repository
and commit it there.
The workflow needs a deploy key once; the setup is in the
[documentation-site README](https://github.com/76cb/OpenTag-Station/blob/main/documentation-site/README.md#publish).
Until the secret `DOCS_DEPLOY_KEY` exists, the workflow fails at the Docs repository checkout and
nothing is published.
9 changes: 5 additions & 4 deletions documentation-site/docs/daily-use/identify.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ Until then tags are ignored; see [Tag is not detected](../troubleshooting/tag.md
| Blank tag | "COMPATIBLE BLANK TAG", "Ready to write", "Open Manage tag to choose a spool". The first button reads **WRITE TAG**. | "Blank tag", "Ready to write". The first button reads **Write tag**. | [Write the tag](manage-tags.md). |
| Blank tag, or tag with other data, that Spoolman links to a spool | The spool's name, "Spool #N" and "NNN g remaining", with the normal **WEIGH** button | The spool's name, "Spool #N", its weight and "Linked to Spoolman", with the normal **Weigh** button | Weigh it, or [write the tag](manage-tags.md) to put the filament data on it. See [below](#tags-spoolman-links-to-a-spool). |
| Tag the station cannot use | On the **Tag** page: "This tag can't be used as it is", a reason, and "Use a blank NXP ICODE SLIX2 tag." | Dashboard: "Reading spool…" and "Tag needs attention". In **Manage tag**: "Unsupported" and "OpenPrintTag decode failed / unsupported" | Use a blank NXP ICODE SLIX2 tag. See [Which tags work](../openprinttag/supported-tags.md). |
| Two or more tags on the reader | Home keeps showing "Place a spool". The **Tag** page shows "Two tags on the reader. Remove one." | In **Manage tag**: "Multiple NFC-V tags detected" and "Remove extra tags and present exactly one tag." | Leave one tag on the reader. |
| Two or more tags on the reader | Home keeps showing "Place a spool". The **Tag** page shows "Two tags on the reader. Remove one." | In **Manage tag**: "Multiple NFC-V tags detected" (or "Multiple NFC-A tags detected") and "Remove extra tags and present exactly one tag." | Leave one tag on the reader. |
| NTAG or MIFARE tag (NFC-A) | Home: "TAG FOUND", "Tag type not supported yet" and the tag's kind, for example "NTAG or other Type 2 tag (NFC-A)". The **Tag** page shows the same with the tag's ID. | Dashboard: "Tag type not supported yet", "Not supported yet". In **Manage tag**: "Tag type not supported yet" with the tag's kind. | Nothing is read from such a tag yet. Use an OpenPrintTag on NXP ICODE SLIX2. See [Which tags work](../openprinttag/supported-tags.md). |

Other kinds of NFC tag (for example NTAG or MIFARE) are not seen at all.
The screen keeps showing "Place a spool".
NFC-B and NFC-F tags are not seen at all. The screen keeps showing "Place a spool".

![Browser Dashboard with a linked spool](../assets/images/browser/dashboard.png)

Expand Down Expand Up @@ -95,6 +95,7 @@ A similar name is not enough when you own several spools of the same filament.

| What you see | What it means | What to do |
|---|---|---|
| The screen stays on "Place a spool" with a tag on the reader | The tag is not an NFC-V tag, is too far from the reader, or the reader has not started yet | See [Tag is not detected](../troubleshooting/tag.md). |
| The screen stays on "Place a spool" with a tag on the reader | The tag is neither NFC-V nor NFC-A, is too far from the reader, or the reader has not started yet | See [Tag is not detected](../troubleshooting/tag.md). |
| "Tag type not supported yet" | The tag is an NFC-A tag (NTAG, MIFARE). The station names it but does not read it yet. | Use an OpenPrintTag on NXP ICODE SLIX2. |
| "This tag can't be used as it is" | The tag holds data that is neither blank nor OpenPrintTag | Use a blank NXP ICODE SLIX2 tag. The station does not erase unknown data. |
| "Spoolman unavailable; spool not looked up" | The station could not reach Spoolman | See [Spoolman problems](../troubleshooting/spoolman.md). You do not need to lift the spool: the station looks it up again by itself once Spoolman is back. |
2 changes: 1 addition & 1 deletion documentation-site/docs/getting-started/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ keep its own inventory.
| The station hardware | A WT32-SC01 Plus touchscreen board, an NFC reader, a load cell with its amplifier, and a platform you build. See the [parts list](../hardware/bill-of-materials.md). |
| Spoolman | Your own running Spoolman server that the station can reach on your network. The station is not useful without it. Weights are saved to Spoolman 0.26 and 0.27; see [Connect Spoolman](../inventory/spoolman.md). |
| 2.4 GHz Wi-Fi | The station cannot join 5 GHz-only or WPA3-only networks. |
| Blank tags | NXP ICODE SLIX2 (NFC-V / ISO 15693). Other tag types are not seen at all. See [Which tags work](../openprinttag/supported-tags.md). |
| Blank tags | NXP ICODE SLIX2 (NFC-V / ISO 15693). NTAG and MIFARE tags are found but not read yet; other tag types are not seen at all. See [Which tags work](../openprinttag/supported-tags.md). |
| A desktop computer with Chrome or Edge | Only for installing the firmware over USB. Afterwards any browser on your network works. |
| A known weight | To calibrate the scale once. |
| FilaBridge and a printer it supports | Optional. Only needed to assign spools to toolheads. Tested with a Prusa XL. |
Expand Down
Loading
Loading