---
module: agent.atm-config-sync
title: ATM Config Sync — pushes ATM hardware/software/cassette config to the platform
tab: Internal
order: 20
audience: dev
---

> **Internal · ops/support.** Written 2026-07-01 from `hiveops-module-atm-config-sync` source. Verify against code before relying on specifics.

## What this module is

`hiveops-module-atm-config-sync` (Maven artifact `hiveops-module-atm-config-sync`, agent module id **`device-config-sync`**) is an **agent drop-in module**, not a backend service. It runs inside the HiveIQ Agent process and periodically **snapshots the ATM's configuration and inventory** and POSTs it to the HiveIQ backend so the device record (Devices / ATM detail) stays current: software versions, timezone, cassette denominations, and Hyosung MoniPlus2S settings.

Unlike the event-reporting modules (journal-events, tcr-events), it emits **no journal/incident events**. It sends one consolidated **config-sync payload** (`AtmConfigSyncRequest`) to a dedicated endpoint. Think of it as "device metadata sync," not "alerting."

## What it collects and syncs

Each sync builds one `AtmConfigSyncRequest` from whatever sources resolve on that machine (all optional — missing sources are simply omitted):

- **Identity / basics** — `atmName`, `country`, `agentVersion` (from the agent context), `timezone` (`TimeZone.getDefault().getID()`), and `institutionKey` (only from `incident.institution.key`).
- **Startup detection method** — read from `startup-info.properties` (`startup.detection.method`) in the agent's start dir, if present.
- **Software versions** — via the platform `ConfigurationReader`: `systemName`, `customizingVersion`, `hotfixVersion`, `countrySpecificVersion`.
- **Cassette denominations** — from `ConfigurationReader.readCassetteDenominations()`; if that yields nothing, it falls back to parsing cassettes out of the MoniPlus2S `HostNoteTypes`.
- **Hyosung version info** — parsed from the current applog file (`HyosungVersionParser`): application / SDK / GSDK / Nextware / component versions.
- **System info** — parsed from the applog header (`AppLogHeaderParser`): OS version, installed programs and packages.
- **MoniPlus2S config** — parsed from the MoniPlus2S directory (`MoniPlus2SConfigParser`): serial, model, host IP/port, plus a full **layered config** view (all config folders / XML files).

Payload is POSTed to **`{endpoint}/api/atms/config/sync`** via `IncidentEventClient.syncConfig(...)`. The backend resolves the device by `atmName`/`country`.

## When it syncs

Three triggers, all running the same `syncAtmConfig()` method:

1. **On agent startup** — `initialize()` runs one sync immediately (after the endpoint is resolved).
2. **On a fixed schedule** — a daemon scheduler (`config-resync` thread) re-syncs **every 6 hours** (`RESYNC_INTERVAL_HOURS = 6`), starting immediately at `start()`.
3. **On demand** — the module registers a callback with `ConfigResyncRegistry`, so a **`RESYNC_CONFIG`** fleet command (handled by the command processor) triggers an immediate re-sync without restarting the agent.

Every sync first calls `ConnectionStateTracker.awaitReconnectJitter()` — after a reconnect it waits a randomized jitter so a fleet coming back online doesn't stampede the backend all at once.

## Config properties it reads

This module has **no dedicated `enabled` flag and no `device.type` gate** — it activates whenever an endpoint is configured. Keys read from `hiveops.properties`:

| Property | Default | Meaning |
|---|---|---|
| `agent.endpoint` | *(none)* | Preferred backend base URL (agent-proxy). If set, HTTP settings use the `agent` prefix. |
| `incident.endpoint` | *(none)* | Legacy fallback base URL, used only if `agent.endpoint` is unset (`incident` prefix). If **both** are unset, the module returns early at init and stays disabled (`isEnabled()` → false). |
| `incident.institution.key` | *(none)* | Institution key stamped onto the sync payload. Note: this method reads **only** `incident.institution.key`, not `agent.institution.key`. |
| `applog.events.dir` | *(none)* | Directory holding the applog file used for Hyosung version + system info. If unset, version/system info are skipped. |
| `applog.events.filename.format` | `APLog{YYYY}{MM}{DD}.log` | Applog filename pattern used to resolve the current file. |
| `moniplus2s.dir` | Windows fallback `C:\Hyosung\MoniPlus2S` | MoniPlus2S config directory. If the property value doesn't resolve to a real directory (Java properties strip single backslashes, e.g. `C:\Hyosung` → `C:Hyosung`), it logs a warning and falls back to the hardcoded Windows path. |

Bearer token and other HTTP params come from the shared agent HTTP settings (`HttpClientHelper.loadSettingsFromProperties(props, prefix)`) — the same `agent.auth.token` chain every module uses. No config-sync-specific auth.

## How it's enabled / deployed

- **No per-device gate** — as long as `agent.endpoint` (or legacy `incident.endpoint`) is set, the module runs on that ATM. It is safe on any device type; it only reports what it can read.
- Delivered like any other agent module: uploaded to the fleet artifact store and pushed via an **`INSTALL_MODULE`** fleet task, which drops the module JAR into the agent's `modules/` directory (handled by `ProcessInstallModule` in `hiveops-file-collection`). Standard rollout order applies: lab ATM → pilot device → fleet.
- Can be disabled fleet-wide without removing the JAR by adding **`device-config-sync`** to the comma-separated `modules.disabled` property and pushing a `CONFIG_UPDATE`. (Disable string is `device-config-sync` — the `getName()` value — **not** `atm-config-sync`.)
- Force a fresh push at any time with a **`RESYNC_CONFIG`** fleet command — no restart needed.

## Common failure modes / what to check

- **Device metadata never populates for an ATM** — confirm `agent.endpoint`/`incident.endpoint` is set; with neither, the module is inert at startup (`isEnabled()` false). Also check the agent log for `ATM config sync complete` vs `ATM config sync failed: ...`.
- **Sync runs but versions/system info are blank** — usually `applog.events.dir` is unset or points at a directory with no matching `APLog…` file; the Hyosung/system-info blocks are simply skipped. Cassette/MoniPlus2S data can still be present.
- **MoniPlus2S config missing on a Hyosung box** — check the `moniplus2s.dir` warning in the log (`… not found (backslash escaping issue?)`). A single-backslash path in `hiveops.properties` gets mangled; either double the backslashes or rely on the `C:\Hyosung\MoniPlus2S` default.
- **Cassettes wrong/empty** — the platform `ConfigurationReader` is tried first; the MoniPlus2S `HostNoteTypes` fallback only fires when the reader returns none. If both are empty, no cassettes are sent.
- **Whole sync fails** — `syncAtmConfig()` wraps everything in a try/catch and logs `ATM config sync failed: <message>`; a failed HTTP call (`syncConfig` throws on non-2xx) is logged but **not** queued/retried — the next scheduled 6h tick (or a `RESYNC_CONFIG`) is the recovery path.
- **On-demand resync does nothing** — a `RESYNC_CONFIG` only fires if this module registered its callback (i.e. it's enabled and started). If it's in `modules.disabled`, the command center logs "no callback registered."
