JavaScript

AMMC is compiled to a WASM module that can be linked into your JavaScript application, published on npm as ammc-wasm.

npm install ammc-wasm

Converting messages

to_json takes the decoder's bytes as a hex string and returns an array of PASSING objects:

import * as wasm from "ammc-wasm";

const passings = wasm.to_json(
  "8e023300e5630000010001047a00000003041fd855000408589514394cd8040005026d0006025000080200008104501304008f"
);

console.log(passings[0]);
// {
//   msg: 'PASSING',
//   decoder_id: '041350',
//   passing_number: 122,
//   transponder: 5625887,
//   rtc_time: '2013-03-19 21:36:33.607 +02:00',
//   strength: 109,
//   hits: 80,
//   low_battery: false,
//   resend: false,
//   modified: false,
//   gps_locked: false
// }

Fields the decoder did not send are omitted, and messages other than PASSING are ignored. TypeScript types ship with the package.

Reading a decoder in the browser

A browser cannot open a raw TCP socket to the decoder, so run ammc-amb -w 9000 and connect to its WebSocket — the JSON arrives already converted and no WASM module is needed. Use ammc-wasm when you have the bytes yourself: in Node with a net socket, or when replaying a capture.

import net from "node:net";
import * as wasm from "ammc-wasm";

const socket = net.createConnection({ host: "10.0.11.10", port: 5403 });

socket.on("data", (buf) => {
  for (const p of wasm.to_json(buf.toString("hex"))) {
    console.log(p.passing_number, p.transponder, p.rtc_time);
  }
});

One TCP read can hold several messages, or half of one. Each to_json call starts a fresh parser and keeps nothing between calls, so a message split across two reads is lost by both. If you need every passing without gaps, do not parse the socket yourself — run ammc-amb -w 9000 and read its WebSocket, which handles the framing for you.