Flash an AOTA image
This is the procedure that worked on a 1.0.0.73 / JX402 unit. The prerequisites are
AOTA OTA flow and
Limitations & risks.
0. Rollback preparation
Section titled “0. Rollback preparation”mkdir -p backupscp firmware/JX402_V1.0.0.73.bin backups/stock.binuv run fwkit verify backups/stock.binuv run fwkit verify firmware/custom.binThe stock image is kept somewhere outside the watch. There is no guaranteed BLE unbrick.
1. Charging and disconnection
Section titled “1. Charging and disconnection”- The watch is charged; the procedure does not start below ~50%.
- The watch is disconnected from the phone app and phone Bluetooth is turned off.
- The host stays awake and close to the watch, with sleep disabled.
2. Pairing state
Section titled “2. Pairing state”If the watch was reset or the factory menu cleared app data, the old authkey is stale.
uv run python tools/cmf_watch.py pairThe session is checked before any write:
uv run python tools/cmf_watch.py info3. Dry run to A040
Section titled “3. Dry run to A040”uv run python tools/ota_client.py --stop-after-a040 --version 0100005a -vRequired checkpoints:
A052 01after INIT1.A040 01immediately after INIT2.- No immediate disconnect.
An A052 without a following A040 means the pairing state is not yet correct. A link that
drops right after INIT2 points to the client writing 0x9040 to ...ff01 instead of
CMD_W.
4. Full transfer
Section titled “4. Full transfer”uv run python tools/ota_client.py \ --image firmware/custom.bin \ --version 0100005a \ -vExpected behaviour:
- The watch requests ranges; offsets can jump.
- Progress is relative to the whole image and may finish well under 100%.
A041 01can arrive before the zero-lengthA042. The client sends0x9041 A5immediately.- The watch reboots when the update is committed.
The transfer is left undisturbed: power stays connected, the lid stays open and no other BLE client is started.
5. Verification
Section titled “5. Verification”After the watch reboots:
uv run python tools/cmf_watch.py infouv run python tools/cmf_watch.py ota-state --duration 5The changed item (animation, scene, string, picture) is then checked. A watch that does not come back is not reflashed; see Recovery.
Interpreting the summary
Section titled “Interpreting the summary”A successful run can end at 70–75% of the file because the watch only requests changed partitions. The important signals are:
A041and the end ack were sent.- Frames were served with no long idle gap.
- The watch rebooted and answers
infoon the new image.
Rollback
Section titled “Rollback”A published rollback image for firmware 1.0.0.57 is available under dumps/binaries/, so a
unit that was flashed with a modified build has an older firmware to return to. Its structure
matches the 1.0.0.73 image and every CRC verifies.
uv run fwkit verify dumps/binaries/firmware/JX402_V1.0.0.57.binuv run python tools/ota_client.py --image dumps/binaries/firmware/JX402_V1.0.0.57.bin --version 0100005aThe downgrade path has not been tested on hardware, and the image is a reconstruction from extracted parts rather than a vendor download. The risks of a full-image flash apply unchanged.
Failure modes
Section titled “Failure modes”- Disconnect during data: the watch is allowed to reboot,
infois checked, and the retry starts from pairing. A041but no commit: the0x9041payloadA5is confirmed written; the end sequence is retried only after reconnecting and re-authenticating.no framesafter a few requests: the watch aborted or rebooted. The log tail is inspected; repeated full transfers are avoided.