| Device ID | Owner | Serial | WiFi SSID | Country | Status | Firmware | Variant | First Active | Last Seen | Flights | Actions |
|---|
| Date | Needed by | ↩ Return | Source | Ref | Name | Phone | Amount | Address | Device | Notes | Status | Tracking | Actions |
|---|
Parts flow from Raw → Acryliced/Flashed/Encoded → Plated → Boxed → Shipped
| Item | Qty | Quick Adj | Set / Add | Notes | Hist | |
|---|---|---|---|---|---|---|
| No manual parts — click "+ Add Manual Part" | ||||||
| Time | Device | Type | Message |
|---|
Last 14 days — FA calls per day
Cache source breakdown (all time)
Pin a callsign to a specific route. Overrides all API lookups permanently — use when a customer reports a wrong route. Enter IATA airport codes (3 letters each).
Release a file to your fleet in paced waves instead of all at once — the safe way to avoid overloading the server. Custom devices and No-Update groups are excluded automatically, and you can see exactly who has it. (code.py is refused — it can brick devices.)
Activating a version pushes it to all devices on next check-in.
Queue a specific file for delivery to chosen devices only. Files are delivered one-per-check-in, so multiple pushes queue safely.
Push one file to every device of a given variant. Devices in No Update groups are automatically excluded. Use the panel type filter to split RGB and GBR pushes.
Fleet Firmware Builds
Fleet Breakdown by Variant
| Version | Uploaded | Notes | Status | Actions |
|---|
Loading push log…
Every file this server has ever pushed is still stored, in full, alongside the
delivery record — nothing is deleted when a push is cancelled or completed.
If you have lost a local copy of a .py, download the exact version
that shipped from here.
Click Load to list stored versions.
| Airline | Look up again every | Note | Stored now |
|---|
Groups let you target or permanently exclude devices from file pushes. Groups marked No Update are always excluded when using group-based pushes.
Loading groups…
Sends to all devices active in the last 24 hours.
Fix an airline name or colour instantly — no firmware update, no redeploy. Look up the code, correct it, Save. Changes go live on every device within about a minute. Ideal for when a customer spots a wrong name (like PVL showing "Porter" instead of "Provincial Airlines").
Fix the city name shown for an airport in "City names" route mode — instantly, no redeploy. Look up the IATA code, correct the city, Save (like NOC showing "Connaught" instead of "Knock").
Fix a wrong aircraft type name (e.g. an A330-200 showing "Voyager"). Corrections reach devices when they next reboot — no firmware update needed. Look up the ICAO type code, correct it, Save.
Give a specific aircraft its own name on line 1 — matched by registration (e.g. G-MPSA → "Police Helicopter") or exact callsign (e.g. AF1 → "Air Force One"). Works for any aircraft, any category. Applies on device reboot.
One per line: KEY, Name — e.g. G-MPSA, Police Helicopter
Some GA operators (flight schools, air-taxi, charter) hold real ICAO 3-letter codes, so their callsigns look exactly like an airline's (e.g. AOS58) and slip past a customer's "hide GA" filter. Add the operator's 3-letter code here to fix it for everyone. Verify the code first — e.g. at avcodes.co.uk — a wrong entry would hide a real airline instead. Applies on device reboot.
One per line: PFX, Operator Name — e.g. AOS, Aeros Flight Training
Matches each unlinked device to its nearest unlinked order by GPS coordinates. Delivery addresses must be geocoded first (cached in the DB — only needs to run once per new order batch).
Searches the devices, checkins and orders tables directly by device ID, WiFi SSID,
owner name, email or order/shipping address — unlike the search box above, this finds devices that aren't in the loaded
list at all, and flags when a device's stored WiFi name looks out of date (e.g. after a router rename).
If a customer's WiFi name doesn't turn anything up, search their name or email instead — their order
record doesn't drift the way a device's stored SSID can.
Groups every active device by how long ago it last checked in. Ordinary dropoff (customers switching devices off, shipping delays, etc.) spreads out gradually — a tight cluster of devices all stuck around the same number of hours ago is the signature of something (like an OTA push) breaking connectivity for a batch of devices at once, even though they're still running fine otherwise.
Groups every device stuck more than 24h by the calendar date of its last_seen.
Check-in history itself is purged after ~24h, so this can't show a precise timestamp that far back —
but last_seen isn't purged, so a spike concentrated on one specific date is still a
strong signal that a deploy on that date is responsible, versus stuck devices spread evenly across
many days (ordinary attrition).
Every file queued to devices, grouped by the day it was queued — including staged-rollout waves released at runtime, which never show up as a git commit. Use this to confirm or rule out whether anything was actually pushed to devices on a specific date.
Designate "what every device should be running". Any device that checks in reporting a
different build gets the right file for its panel queued automatically — including stock
arriving from transit weeks after it was flashed, which a staged rollout can never target
because those devices don't exist yet when the rollout is created.
Delivery still goes through the normal path on the device's next check-in, so this inherits
every existing protection: the weak-signal deferral, the remote_manager version guard, and
the no-update / custom-device exclusions.
Cancels every pending push of that file across the whole fleet, at any age — unlike Stuck Queues, which only clears things older than a few hours so it can't disturb a healthy rollout. Devices that have already received the file are unaffected; it cannot be recalled once handed over. Removing a slot above stops future queueing; this stops what is already waiting.
Every build is read from the file itself (rm_build / FT_BUILD). Any slot left empty keeps whatever
is already stored, so you can fill them in one at a time. A device only ever gets the flight_tracker build for
its own panel — an empty slot simply means those devices aren't auto-updated yet, never that they get the
wrong file. Order is enforced automatically: a flight_tracker build can depend on remote_manager APIs but never the
reverse, and landing r28 on remote_manager 1.2.1 is exactly what bricked devices before.
A new device — set up in the last 24 hours, or one that has never managed a
check-in before — draws on its own reserved budget, so it can't end up queued behind hundreds of devices
that have been quietly out of date for a month and are in no hurry. Leave the reserve blank to keep it the
same as the main cap; set it to 0 to switch the priority off. It's a reserve, not a free pass:
new devices are still capped, so a whole pallet powering on at once can't flood the database.
A device restarts a few seconds after each file lands, and the two baseline files
arrive on separate check-ins — so without a delay, a brand-new device goes dark and reboots twice within a
couple of minutes of first coming alive, while the customer is stood over it and possibly still finishing
setup. The obvious reading is "it's broken", and the obvious response is to pull the plug, which during the
write is how a device ends up needing a USB re-flash. Waiting costs nothing: the device stays in the
priority queue the whole time and updates the moment the delay is up. Blank uses 30 minutes;
0 updates immediately. Updates also hold off for 3 minutes after any restart, so a device
someone has just moved and plugged back in doesn't immediately go dark again.
The cap only counts automatic queues, so a deliberate rollout won't starve it and it won't silently cap your own pushes. Devices already holding a pending file, or that received this same file in the last 2 hours, are skipped rather than stacked.
There are about a dozen reasons a device can sit on an old build, and from the outside they all look identical. Put an ID in and this walks the exact same checks the server applies, in order, and tells you which one is stopping that device.
Parcels you have packed and bought postage for, that Royal Mail hasn't collected yet. They are already marked as sent so they are off your to-send list — the customer just hasn't been told, and won't be until 8am on the morning it actually goes.
Worked out from the first two letters of the tracking number. These are your services and
they change with your Royal Mail contract, so edit them here rather than asking me — a wrong row
puts a wrong delivery date in a customer's inbox. A prefix that isn't listed simply gets no
estimate, which is much better than a wrong one.
Set days to 0 for anything whose timing you cannot promise —
international (LO) is seeded that way. The service is still named in the email, but no arrival date
is given. The carrier column matters too: a prefix registered to Royal Mail is never applied to an
Evri or DHL parcel that happens to start with the same two letters.
Open a return against an order, put the customer's tracking number in when they send it, and this keeps track of who still owes you a parcel. Adding a tracking number moves it out of "chase the customer" on its own — and if it still hasn't turned up a week and a half later, it comes back onto the list.
The usual way to open a return is the ⟲ button on the order itself, over on the Orders tab — nothing to type, and it links up automatically. This form is for the odd case where there is no order row to work from. If you generate the return label yourself in Click & Drop you already know the tracking number, so put it in here and skip a step.
Paste Royal Mail's delivery confirmation email, a list of tracking numbers, or a column out of a spreadsheet. Anything mentioning one of your open returns gets marked arrived, and you get told which ones are still owed to you. It looks for your numbers inside what you paste, so there is nothing to format and no way for it to invent a match.
Everything sent to any address at the domain — hello@, harry@, support@, anything — gets forwarded to one inbox. Replies go back to the original sender, so you can just hit reply.
Mail from these is never forwarded. Block a whole domain with
@spamdomain.com — spam comes from endless
different addresses on the same few domains, so blocking one at a time
never keeps up.
Adding Resend's MX records sends all mail for the domain to Resend. If the domain already receives mail anywhere else — Google Workspace, Outlook, your host's webmail — that mailbox stops receiving the moment the MX records change, and anything sent in the gap is gone. Check where the domain's mail goes today before touching this. If it is already on Google Workspace, you do not need any of this: add a catch-all routing rule there instead, and it will be more reliable than forwarding through a webhook.
email.received event pointing at the URL shown above.RESEND_WEBHOOK_SECRET.Attachments are not copied into the forwarded email — it tells you they were there and you open the original in Resend to download them. Auto-replies and anything already forwarded once are skipped on purpose, because forwarding those is how mail loops start.
Both /device/register (which runs on every boot) and /device/checkin
refresh a device's "last seen" time. So a device stuck rebooting — for example r28's watchdog
firing every 15 minutes — keeps registering, keeps looking ● Online,
and never completes a single check-in. That means it never gets settings, never gets OTA, and
never reports its real firmware build, while appearing perfectly healthy everywhere else.
These devices cannot be fixed by pushing files at them —
OTA delivery rides on the check-in they aren't completing. They need the underlying cause fixed,
or physical recovery.
Read the rate column, never the raw count. The biggest ISP will always have the most losses simply by being biggest — that is not a finding. What would be a finding is one group losing a much larger share of its own devices than everyone else, concentrated on a few days: that is the shape of a router firmware push, and it would mean those devices were never faulty. Groups under 15 devices are shown but never flagged, because a rate off four devices means nothing.
Devices with a command or OTA file push that's been sitting "pending" for a long time. A large pending file push in particular has to ride inline in the device's next check-in response — on a marginal connection that can be exactly what stops the device completing a check-in at all, ever, until it's cleared. This does NOT delete the device or its history — it just cancels the stuck item so the device's plain, lightweight check-in has a chance to succeed again.
Plots a device's reported free memory across its recent check-in history — tests whether it trends toward exhaustion the longer it runs without a reboot. Note: check-in history is only kept for ~24h, so this only shows a useful trend for a device that went quiet recently, not one that's been silent for days (its older history is already purged).
| Qty | Last seen | Progress | Outcome | Code |
|---|
The auto-update baseline picks a device's flight_tracker from panel_type.
When that column is wrong the device gets the wrong build, and every colour on
the display comes out rotated. Which way it rotates tells you which mistake it is:
| BA blue | Yellow line | White | |
|---|---|---|---|
| Correct | blue | yellow | white |
| RGB panel sent the GRB build | green | magenta | white |
| GRB panel sent the RGB build | red | cyan | white |
This works out what each device really is by reading the flight_tracker
files it was actually sent by hand. The three builds are distinguishable by content
(fix_color → GRB, rgbmatrix → H16, neither → RGB), so a
hand-picked push is a record of what the panel was known to be. Baseline pushes are
ignored — they're the thing under suspicion.
Reads a few hundred file bodies, so it runs in the background and takes a minute or two.
It never full-scans device_files.
| Device | Owner | Server thinks | Files prove | Running now | Action | Evidence |
|---|
Reverse-geocodes every device's GPS coordinates to determine its country, then assigns a variant like
UK-RGB, GERMANY-GRB, or
UK-Custom.
Devices flagged custom (word found in any text field or in a No Update group) get a -Custom suffix.
Devices without GPS get UNKNOWN-RGB/GRB.
⏱ Takes ~2 minutes for 100 devices due to Nominatim's rate limit (1 req/sec).
| Device | Owner | Old Variant | New Variant | Reason |
|---|