Skip to content

๐Ÿ‡จ๐Ÿ‡ฆ ca-transport-canada โ€‹

CountryCanada
Registration prefixC-
Data sourcehttps://wwwapps.tc.gc.ca/Saf-Sec-Sur/2/CCARCS-RIACC/download/ccarcsdb.zip
FormatZIP (fixed URL) containing two CSV files, carscurr.txt (aircraft) and carsownr.txt (owners)
Run frequencyWeekly (Sunday, 05:10 UTC)
Depends on Mictronics for ICAO hexNo โ€” the CCARCS aircraft file publishes the Mode S transponder address directly as a 24-bit binary string, which this runner decodes to hex itself.

How it works โ€‹

The full CCARCS database ZIP is downloaded from a fixed URL and both member files are extracted in memory. carscurr.txt (aircraft) and carsownr.txt (owners) are ISO-8859-1, comma-delimited, and end with a blank row followed by a record-count row โ€” parsing stops at the first empty row to avoid ingesting that trailer. Rows are staged into a local SQLite database (indexed by registration) rather than being joined in Python, since owner records must be matched back to aircraft records by registration mark. Only aircraft rows with an empty ineffective_date (i.e. still on the register) are written to Redis, and only the first Active-status owner per registration is used. The Mode S column is a 24-bit binary string (e.g. "110000000000000000010000") converted to 6-character hex via int(value, 2) formatted as 06X. 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 โ€‹

Both files are drawn from the same CCARCS ZIP and joined on the aircraft registration mark (carscurr.txt MARK/TRIMMED_MARK โ†” carsownr.txt MARK_LINK). Column names and order below match the archive's own carslayout.txt data dictionary, verified against the real downloaded files: 47 columns per row in carscurr.txt, 20 columns per row in carsownr.txt.

carscurr.txt (aircraft) โ€‹

Source columnImportedNotes
MARK / TRIMMED_MARKโœ…C- prefix prepended; TRIMMED_MARK (col 46) preferred, falls back to stripped MARK (col 0) โ†’ registration; also the join key to carsownr.txt MARK_LINK
REGISTRATION_SUB_TYPE_EโŒPresent in source; not read by this runner
REGISTRATION_SUB_TYPE_FโŒPresent in source; not read by this runner
COMMON_NAMEโŒPresent in source; not read by this runner
MODEL_NAMEโœ…โ†’ aircraft.model
MANUFACTURERS_SERIAL_NUMBERโœ…โ†’ aircraft.serial_number
MANUFACTURER_SERIAL_COMPRESSEDโŒPresent in source; not read by this runner
ID_PLATE_MANUFACTURERS_NAMEโœ…โ†’ aircraft.manufacturer
BASIS_FOR_REGISTRATIONโŒPresent in source; not read by this runner
BASIS_FOR_REGISTRATION_FโŒPresent in source; not read by this runner
AIRCRAFT_CATEGORY_Eโœ…Decoded (e.g. Aeroplane โ†’ Airplane) โ†’ aircraft.type
AIRCRAFT_CATEGORY_FโŒPresent in source; not read by this runner
DATE_OF_IMPORTโŒPresent in source; not read by this runner
ENGINE_MANUF_Eโœ…โ†’ aircraft.powerplant.manufacturer
POWERGLIDER_FLAGโŒPresent in source; not read by this runner
ENGINE_CATEGORY_Eโœ…Decoded (e.g. Turbo Fan โ†’ Turbo-fan) โ†’ aircraft.powerplant.type
ENGINE_CATEGORY_FโŒPresent in source; not read by this runner
NUMBER_OF_ENGINESโœ…โ†’ aircraft.powerplant.count
NUMBER_OF_SEATSโœ…โ†’ aircraft.seats
AIR_WEIGHT_KILOSโŒPresent in source; not read by this runner
SALE_REPORTEDโŒPresent in source; not read by this runner
ISSUE_DATEโŒPresent in source; not read by this runner
EFFECTIVE_DATEโŒPresent in source; not read by this runner
INEFFECTIVE_DATEโŒUsed to filter to currently-registered aircraft only (ineffective_date == ''); value itself is not stored
REGISTERED_PURPOSE_EโŒPresent in source; not read by this runner
REGISTERED_PURPOSE_FโŒPresent in source; not read by this runner
FLIGHT_AUTHORITY_EโŒPresent in source; not read by this runner
FLIGHT_AUTHORITY_FโŒPresent in source; not read by this runner
MANUFACTURE_OR_ASSEMBLYโŒPresent in source; not read by this runner
COUNTRY_MANUFACTURE_ASS_EโŒPresent in source; not read by this runner
COUNTRY_MANUFACTURE_ASS_FโŒPresent in source; not read by this runner
DATE_MANUFACTURE_ASSEMBLYโœ…YYYY/MM/DD โ†’ ISO 8601 UTC โ†’ aircraft.manufactured_date
BASE_OF_OPERATIONS_CTRY_EโŒPresent in source; not read by this runner
BASE_OF_OPERATIONS_CTRY_FโŒPresent in source; not read by this runner
BASE_PROVINCE_OR_STATE_EโŒPresent in source; not read by this runner
BASE_PROVINCE_OR_STATE_FโŒPresent in source; not read by this runner
CITY_AIRPORTโŒPresent in source; not read by this runner
TYPE_CERTIFICATE_NUMBERโŒPresent in source; not read by this runner
REGISTRATION_AUTH_STATUS_EโŒPresent in source; not read by this runner
REGISTRATION_AUTH_STATUS_FโŒPresent in source; not read by this runner
MULTIPLE_OWNER_FLAGโŒPresent in source; not read by this runner
MODIFIED_DATEโŒPresent in source; not read by this runner
MODE_S_TRANSPONDER_BINARYโœ…24-bit binary string decoded to 6-char hex โ†’ icao_hex
PHYSICAL_FILE_REGION_EโŒPresent in source; not read by this runner
PHYSICAL_FILE_REGION_FโŒPresent in source; not read by this runner
EX_MILITARY_MARKโŒPresent in source; not read by this runner

carsownr.txt (owners) โ€‹

Source columnImportedNotes
MARK_LINKโœ…Join key back to the aircraft record's registration
FULL_NAMEโœ…โ†’ registrant.names[0]
TRADE_NAMEโœ…โ†’ registrant.names[1]
STREET_NAMEโœ…โ†’ registrant.street[0]
STREET_NAME2โœ…โ†’ registrant.street[1]
CITYโœ…โ†’ registrant.city
PROVINCE_OR_STATE_Eโœ…โ†’ registrant.administrative_area
PROVINCE_OR_STATE_FโŒPresent in source; not read by this runner
POSTAL_CODEโœ…โ†’ registrant.postal_code
COUNTRY_Eโœ…Full English country name decoded to ISO 3166-1 alpha-2 (defaults to CA if unrecognized) โ†’ registrant.country
COUNTRY_FโŒPresent in source; not read by this runner
TYPE_OF_OWNER_Eโœ…โ†’ registrant.type
TYPE_OF_OWNER_FโŒPresent in source; not read by this runner
ACTIVE_FLAGโŒUsed to select the current owner row (status == 'Active', first match only); value itself is not stored
CARE_OFโŒPresent in source; not read by this runner
REGION_EโŒPresent in source; not read by this runner
REGION_FโŒPresent in source; not read by this runner
OWNER_NAME_OLD_FORMATโŒPresent in source; not read by this runner
MAIL_RECIPIENTโŒPresent in source; not read by this runner
TRIMMED_MARKโŒPresent in source; not read by this runner (distinct from carscurr.txt's own TRIMMED_MARK column)

See specs/data-dictionary.yaml (ca-tc 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 C00010 | python3 -m json.tool --sort-keys --no-ensure-ascii
json
{
    "aircraft": {
        "manufactured_date": "1966-01-01T00:00:00Z",
        "manufacturer": "Piper Aircraft Corporation",
        "manufacturer_model": "PIPER PA-32",
        "model": "PA-32-260",
        "powerplant": {
            "count": 1,
            "manufacturer": null,
            "type": "Piston"
        },
        "seats": null,
        "serial_number": "32-528",
        "type": "Airplane",
        "type_designator": "PA32",
        "wake_turbulence_category": "Light"
    },
    "icao_hex": "C00010",
    "military": false,
    "registrant": {
        "administrative_area": "Oklahoma",
        "city": "Stillwater",
        "country": "CA",
        "names": [
            "Roger D S Reetz"
        ],
        "postal_code": "74074",
        "street": [
            "2701 S Mar Vista Street"
        ],
        "type": "Individual"
    },
    "registration": "C-FAAP",
    "source": "ca-transport-canada"
}
bash
docker run --rm --network host redis:latest redis-cli EVAL "$(cat ./shared/lua/merge_aircraft.lua)" 0 C038AA | python3 -m json.tool --sort-keys --no-ensure-ascii
json
{
    "aircraft": {
        "manufactured_date": "2018-01-01T00:00:00Z",
        "manufacturer": "THE BOEING COMPANY",
        "manufacturer_model": "BOEING 787-9 Dreamliner",
        "model": "787-9",
        "powerplant": {
            "count": 2,
            "manufacturer": null,
            "type": "Turbo-fan"
        },
        "seats": null,
        "serial_number": "38356",
        "type": "Airplane",
        "type_designator": "B789",
        "wake_turbulence_category": "Heavy"
    },
    "icao_hex": "C038AA",
    "military": false,
    "registrant": {
        "administrative_area": "Quebec",
        "city": "Saint-Laurent",
        "country": "CA",
        "names": [
            "Air Canada"
        ],
        "postal_code": "H4S1Z3",
        "street": [
            "7373 de la Cรดte-Vertu Blvd."
        ],
        "type": "Entity"
    },
    "registration": "C-FVLX",
    "source": "ca-transport-canada"
}

Configuration โ€‹

Reads settings.json (mounted at /app/settings.json):

ParameterRequiredDefaultNotes
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โŒ14TTL applied to each aircraft:registry:{icao_hex} key written by this runner

MQTT โ€‹

Published once, at the end of a run, to SkyFollower/runner/ca-transport-canada/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_ca_transport_canada_{name}/config for each of the three stats above.