Skip to content

Croatia ๐Ÿ‡ญ๐Ÿ‡ท CCAA Registry โ€‹

Namehr-ccaa-registry
CountryCroatia
Registration prefix9A-
Data sourcehttps://www.ccaa.hr/en/list-of-registered-aircraft-94674
FormatPDF (URL discovered by scraping the index page for the first /file/ link)
Run frequencyWeekly (Tuesday, 23:10 UTC)
Depends on Mictronics for ICAO hexYes โ€” this runner does not publish ICAO hex addresses; registrations are resolved via RediSearch against Mictronics records (idx:aircraft:mictronics). Must run after the mictronics runner.

How it works โ€‹

The Croatia CCAA index page is scraped for the first anchor tag whose href contains /file/, which is followed to download the current register PDF. Each page is parsed with pdfplumber's built-in table extraction (extract_table()), which works reliably on this PDF. Rows are matched against a strict suffix pattern (^[A-Z0-9]{2,4}$) before the 9A- prefix is prepended, filtering out header/footer noise rows that don't contain a real registration suffix. Every written record explicitly sets military: false โ€” this register is exclusively civil, and the explicit value ensures a stale military: true flag (from Mictronics or a prior record on a reused hex) is corrected on re-registration.

Columns โ€‹

Source columnImportedNotes
REG. OZNAKAโœ…Suffix only (e.g. ABC); 9A- prefix prepended โ†’ used as the Mictronics lookup key
REDNI BROJโŒParsed but not stored (row-number column)
PROIZVOฤAฤŒโœ…โ†’ aircraft.manufacturer
OZNAKA ZRAKOPLOVAโœ…โ†’ aircraft.model
SERIJSKI BROJโœ…โ†’ aircraft.serial_number
VLASNIKโœ…โ†’ registrant.names[0]
ADRESAโœ…โ†’ registrant.street (split on commas into parts)

See specs/data-dictionary.yaml (hr-ccaa-registry entry) for full column semantics and cross-source schema notes.

Example Output โ€‹

Read back the merged record for a given ICAO hex (combines this runner's data with Mictronics and any other sources that have written to the same key):

bash
docker run --rm --network host redis:latest redis-cli EVAL "$(cat ./shared/lua/merge_aircraft.lua)" 0 501C2E | python3 -m json.tool --sort-keys --no-ensure-ascii
json
{
    "aircraft": {
        "manufacturer": "Reims Aviation Industries",
        "manufacturer_model": "CESSNA 172 Skyhawk",
        "model": "Cessna F172N",
        "serial_number": "F17201978",
        "type_designator": "C172"
    },
    "data_sources": [
        "mictronics",
        "hr-ccaa-registry"
    ],
    "icao_hex": "501C2E",
    "military": false,
    "registrant": {
        "names": [
            "Vektra d.o.o."
        ],
        "street": [
            "Branka Vodinka 4b",
            "42 000 Varaลพdin"
        ]
    },
    "registration": "9A-DFK"
}
bash
docker run --rm --network host redis:latest redis-cli EVAL "$(cat ./shared/lua/merge_aircraft.lua)" 0 501C65 | python3 -m json.tool --sort-keys --no-ensure-ascii
json
{
    "aircraft": {
        "manufacturer": "The Boeing Company",
        "manufacturer_model": "BOEING 737-800",
        "model": "737-800",
        "serial_number": "29659",
        "type_designator": "B738"
    },
    "data_sources": [
        "mictronics",
        "hr-ccaa-registry"
    ],
    "icao_hex": "501C65",
    "military": false,
    "registrant": {
        "names": [
            "Horizon Aviation 4 Limited"
        ],
        "street": [
            "32 Molesworth Street",
            "2 Dublin"
        ]
    },
    "registration": "9A-ICF"
}

Configuration โ€‹

See Data Runners for the full list of environment variables every runner reads. This runner writes aircraft:registry:{icao_hex} with a fixed 14-day TTL (ENRICHMENT_TTL_SECONDS in shared/timing.py).

MQTT โ€‹

Published once, at the end of a run, to SkyFollower/runner/hr-ccaa-registry/statistic/{name} (all retained):

Topic suffixValueFormat
records_importede.g. 271Integer as string
last_run_ate.g. 2026-07-07T14:32:01.123456+00:00ISO 8601 UTC
last_run_statusSuccess or FailureString

Home Assistant autodiscovery configs are also published (retained) to homeassistant/sensor/SkyFollower_runner_hr_ccaa_registry_{name}/config for each of the three stats above.