Usage

Decoder simulator

ammc-sim pretends to be a timing decoder, so you can develop and test your application without a physical decoder on the desk. It ships in the AMMC zip next to ammc-amb.

It is not a complete decoder emulator. It generates passing traffic and answers the handful of requests AMMC itself sends; a third-party timing application that expects the full protocol will most likely not work with it.

How it works

The simulator opens a TCP server and waits for clients — the opposite of a real decoder only in that you connect to localhost instead of the track. The port is fixed by decoder type and cannot be changed:

Decoder typePortProtocol
AMB (default)5403P3 binary
Vostok8899text lines

Inside, three independent tasks run at the same time:

A passing generator. Every --passing-delay milliseconds — a fresh random value in the given range for each passing — it builds one passing, encodes it in the decoder's wire format and pushes it to all connected clients. The passing number counts up from the low end of --passing-numbers; the transponder (and the transponder code, if you gave one) is picked at random from your list on every passing. --hits, --strength and --decoder-id are copied into every message unchanged. The timestamp is the current local time of the machine, taken at the moment the passing is generated.

A status timer. Every 3 seconds it sends a status message, the same keep-alive a real decoder emits. AMMC logs it and carries on.

A request responder. Anything a client sends is fed through the same P3 parser AMMC uses, and known requests are answered: VERSION gets a version message, PING is echoed back with its payload, a time-sync request gets a time message, and a request to resend passings is accepted and logged. Unknown requests are ignored. This is what makes ammc-amb -t (time sync) and the WebSocket PING round-trip work against the simulator.

Two things regularly surprise people:

  • The generator does not wait for a client. It starts at the configured passing number and keeps ticking whether or not anything is connected, and it does not replay what it missed. Connect a few seconds late and the first passing you see is number 4 or 5, not 1.
  • It stops on its own. When the passing number passes the top of --passing-numbers the simulator waits --shutdown_delay_secs and exits. With the default 1-3000 and the default delay that is roughly two hours; use a range like -n 1-50 for a short, repeatable test.

Every connected client gets the same passings, so you can point several applications at one simulator.

Auto-discovery

A real AMB decoder answers a UDP broadcast so AMMC's -a can find it. The simulator does this only when you tell it which address to advertise:

.\ammc-sim.exe -m 192.168.1.10

It then listens for discovery requests on UDP port 5403 and answers with a broadcast to port 5303 carrying that address and the decoder ID. Without -m it logs Use '-m <IP address>' to enable auto-discovery mode and simply ignores discovery traffic.

Note that the simulator holds UDP port 5403 while it does this, and AMMC's -a wants the same port. Running both on one machine will not work — use ammc-amb <ip> with the address instead of -a when the simulator is local.

Examples

Start a simulator and read it with AMMC, in two terminals:

cd windows64
.\ammc-sim.exe
cd windows64
.\ammc-amb.exe 127.0.0.1
[2026-08-09T08:17:07Z INFO  common] >>> {"decoder_id":"0A87E5","gps_locked":false,"hits":100,"low_battery":false,"modified":false,"msg":"PASSING","passing_number":4,"resend":false,"rtc_time":"2026-08-09 10:17:07.376639 +02:00","strength":300.0,"transponder":12345}
[2026-08-09T08:17:07Z INFO  common] >>> {"decoder_id":"0A87E5","gps_locked":false,"hits":100,"low_battery":false,"modified":false,"msg":"PASSING","passing_number":5,"resend":false,"rtc_time":"2026-08-09 10:17:07.684126 +02:00","strength":300.0,"transponder":7777}

Fifty passings, three known transponders, about three per second:

.\ammc-sim.exe -n 1-50 -d 300-400 -t 12345,23456,4554444

A steady one-second beat from a single transponder, for a scoreboard demo:

.\ammc-sim.exe -d 1000-1001 -t 232323 -c ID:232323

Load test — as fast as the simulator will go:

.\ammc-sim.exe -n 1-100000 -d 1-2

Vostok instead of AMB:

.\ammc-sim.exe Vostok
.\ammc-vostok.exe 127.0.0.1

Options

Usage: ammc-sim [OPTIONS] [DECODER_TYPE]

Arguments:
  [DECODER_TYPE]  Decoder type; AMB or Vostok [default: AMB]
OptionDefaultDescription
-n, --passing-numbers <from-to>1-3000Range of passing numbers to generate. The simulator exits after the last one
-d, --passing-delay <from-to>1000-3000Delay between passings in milliseconds, picked at random from the range for each passing
-t, --transponder <list>123456,87654321Transponder numbers, comma separated. One is chosen at random per passing
-c, --tran_code <list>Transponder codes, comma separated, e.g. x-1,d-345,aa-199. Setting either -t or -c replaces the default transponders
--decoder-id <hex>0A87E5Decoder ID sent in every message. Must be a hex number
-s, --strength <n>300Signal strength in every passing
--hits <n>100Hit count in every passing
-m, --my_ip <ip>IP address to advertise in auto-discovery replies. Off when not given
-x, --startup_delay_secs <n>0Wait before generating the first passing
-y, --shutdown_delay_secs <n>0Wait after the last passing before exiting
-v, --verboseLog every message, including the raw bytes on the wire
-q, --quiteErrors and warnings only
--skip_telemetry_uploadDo not send the runtime telemetry ping
-V, --versionPrint the version
-h, --helpPrint all options

Passings always carry the local time of the machine that runs the simulator.