๐ฒ๐ฐ mk-caa โ
| Country | North Macedonia |
| Registration prefix | Z3- |
| Data source | https://www.caa.gov.mk/en/safety/airworthiness-and-aircraft-registration/ |
| Format | PDF (date-stamped filename, discovered via index page) |
| Run frequency | Weekly (Tuesday, 11:10 UTC) |
| Depends on Mictronics for ICAO hex | Yes โ this runner does not publish ICAO hex addresses; Z3- registrations are resolved via RediSearch against Mictronics records (idx:aircraft:mictronics). Must run after the mictronics runner. |
How it works โ
The CAA index page is scraped for the first link whose href contains AIRCRAFT-REGISTER (case-insensitive) and ends in .pdf. The PDF has no table header row at all, so pdfplumber's extract_table() output is read purely by fixed column position rather than by column name: registration is at index 2, model at 3, manufacturer at 4, serial number at 5, owner name at 6, and owner address at 7. Only rows whose registration starts with Z3- are kept. Model, manufacturer, serial number, owner name, and owner address are run through the same whitespace-collapsing transform, since pdfplumber sometimes represents a single cell's text with an embedded newline rather than a space (e.g. a wrapped manufacturer name). 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 column | Imported | Notes |
|---|---|---|
| Certifi. No. (position 0) | โ | Certificate/registration-record number; not read by the parser |
| Date of Registration (position 1) | โ | Not read by the parser |
| Registration (position 2) | โ | Z3-prefix; used as the Mictronics lookup key |
| Model (position 3) | โ | โ aircraft.model; embedded newlines collapsed to a single space |
| Manufacturer (position 4) | โ | โ aircraft.manufacturer; embedded newlines collapsed to a single space |
| Serial Number (position 5) | โ | โ aircraft.serial_number; embedded newlines collapsed to a single space |
| Owner Name (position 6) | โ | โ registrant.names[0]; embedded newlines collapsed to a single space |
| Owner Address (position 7) | โ | โ registrant.street; embedded newlines collapsed to a single space |
See specs/data-dictionary.yaml (mk-caa 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):
docker run --rm --network host redis:latest redis-cli EVAL "$(cat ./shared/lua/merge_aircraft.lua)" 0 512031 | python3 -m json.tool --sort-keys --no-ensure-ascii{
"aircraft": {
"manufacturer": "The New Piper Aircraft INC",
"manufacturer_model": "PIPER PA-28R-180/200/201",
"model": "PIPER PA-28R-201",
"serial_number": "28R-787120",
"type_designator": "P28R",
"wake_turbulence_category": "Light"
},
"icao_hex": "512031",
"military": false,
"registrant": {
"names": [
"TRANS INTER DOO / Aeroklub โSkopjeโ DOO Chucher Sandevo"
],
"street": "Sportski Aerodrom Stenkovec No. 151a, Chucher Sandevo"
},
"registration": "Z3-DAJ",
"source": "mk-caa"
}North Macedonia's registry has no jets or widebodies, so the larger example below is an Air Tractor AT-802 โ the largest type in the registry:
docker run --rm --network host redis:latest redis-cli EVAL "$(cat ./shared/lua/merge_aircraft.lua)" 0 512029 | python3 -m json.tool --sort-keys --no-ensure-ascii{
"aircraft": {
"manufacturer": "Air Tractor Inc",
"manufacturer_model": "AIR TRACTOR AT-802",
"model": "AT-802A",
"serial_number": "802A-0313",
"type_designator": "AT8T",
"wake_turbulence_category": "Medium"
},
"icao_hex": "512029",
"military": false,
"registrant": {
"names": [
"Protection and Rescue Directorate"
],
"street": "โVasko Karangeleskiโ bb Skopje"
},
"registration": "Z3-BGU",
"source": "mk-caa"
}Configuration โ
Reads settings.json (mounted at /app/settings.json):
| Parameter | Required | Default | Notes |
|---|---|---|---|
redis.host | โ | โ | Redis connection host |
redis.port | โ | 6379 | |
mqtt.host | โ | โ | Omit the whole mqtt block to skip completion-stats publishing entirely |
mqtt.port | โ | 1883 | |
mqtt.username | โ | โ | Optional MQTT auth; omit for an anonymous broker |
mqtt.password | โ | โ | |
redis_ttl_days | โ | 14 | TTL applied to each aircraft:registry:{icao_hex} key written by this runner |
MQTT โ
Published once, at the end of a run, to SkyFollower/runner/mk-caa/statistic/{name} (all retained):
| Topic suffix | Value | Format |
|---|---|---|
records_imported | e.g. 271 | Integer as string |
last_run_at | e.g. 2026-07-07T14:32:01.123456+00:00 | ISO 8601 UTC |
last_run_status | success or failure | String |
Home Assistant autodiscovery configs are also published (retained) to homeassistant/sensor/SkyFollower_runner_mk_caa_{name}/config for each of the three stats above.