Skip to content

Keep an EUD's team colour current for the whole connection - #349

Open
texaskst wants to merge 1 commit into
brian7704:masterfrom
texaskst:team-color-live-updates
Open

Keep an EUD's team colour current for the whole connection#349
texaskst wants to merge 1 commit into
brian7704:masterfrom
texaskst:team-color-live-updates

Conversation

@texaskst

@texaskst texaskst commented Aug 3, 2026

Copy link
Copy Markdown

Problem

eud.team_id is only written in EudHandler.parse_device_info, which handle_cot calls behind:

if event and not self.uid:
    self.parse_device_info(event)

So it runs once, on the first CoT of a TCP connection. If an operator changes their team colour while connected, the database keeps the old value until they reconnect, however many SA updates arrive in between.

The web UI map reads team_color off that row, so the marker keeps the old colour, and refreshing the browser doesn't help — the stale value is in the database, not the page.

How I ran into it

I use team colour to carry live state during airsoft games: a player who's out switches to a reserved colour so everyone can see they're out. The web map is what the game master watches, and it kept showing the pre-change colour for the rest of the session.

Measured on 1.7.11 — the device was broadcasting <__group name="Cyan" role="Team Member"/> while euds.team_id still pointed at the colour it had when it connected, the last connect being 9 seconds before the change.

Other clients were never affected. EudHandler.on_message relays the original CoT verbatim, so ATAK/iTAK parse __group themselves and always saw the right colour. It's only the server's own view that goes stale.

Fix

cot_parser already sees every position update and owns both the EUD rows and the socketio emits, so the refresh goes there.

  • Compares against a per-uid cache and only touches the database when the colour actually changed, so the common case is one dict lookup per position update.
  • Emits the eud event on change, which is what makes an already open map recolour without a reload.
  • Team creation mirrors parse_device_info, including the IntegrityError fallback for when another cot_parser process creates the same team first.
  • The cache is only written after a successful update, so a failure retries on the next position update instead of being swallowed until the EUD reconnects.

Testing

Running this on my own server against ATAK-CIV 5.7.0.10.

  • Changed team colour mid-session with no reconnect: euds.team_id follows within one position update (measured about a second), and an already open map recolours without a reload. Before the change the same test left the row stale indefinitely.
  • Verified in both directions, including back to the original colour.
  • No extra database writes while the colour is unchanged — the cache short-circuits before any query.

Note

Callsign, ATAK version and team_role are set in the same connect-only block and go stale the same way. I left those alone to keep this focused, but happy to extend it if you'd like the same treatment.

eud.team_id is only ever written by EudHandler.parse_device_info, which is
called behind `if event and not self.uid` - so it runs once, on the first
CoT of a TCP connection. If an operator changes their team colour while
connected, the database keeps the old colour until they reconnect, however
many SA updates arrive in between. The web UI map reads team_color from
that row, so it shows the stale colour and refreshing the browser doesn't
help, since the staleness is in the database rather than the page.

I ran into this using team colour to carry live state during airsoft games
(marking a player out of the game), where the map is what everyone watches.
Peers were never affected - EudHandler relays the original CoT verbatim, so
other ATAK/iTAK clients parse __group themselves and always saw the real
colour. It's only the server's own view that goes stale.

cot_parser already sees every position update and owns both the EUD rows
and the socketio emits, so the refresh goes there. It compares against a
per-uid cache and only touches the database when the colour actually
changed, so the common case is one dict lookup per position update. On a
change it also emits the 'eud' event, which is what makes an already open
map recolour without a reload.

Team creation mirrors what parse_device_info does, including the
IntegrityError fallback for when another cot_parser process creates the
same team first. The cache is only written after a successful update, so a
failure retries on the next position update instead of being swallowed
until the EUD reconnects.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant