{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "version": "",
    "type": "object",
    "properties": {
        "version": {
            "type": "string",
            "pattern": "^0x[0-9A-Fa-f]{4}$",
            "description": "Version of the CSTINFO structure as per -2-3. Note that this is not the same as the version of this JSON file - the value written here is sent on the wire."
        },
        "cstId": {
            "type": "string",
            "description": "Consist identifier, e.g. UIC number. User defined.",
            "maxLength": 16
        },
        "trnId": {
            "type": "string",
            "description": "Train identifier, e.g. UIC number. User defined and optional. Note that this doesn't get sent out on the wire in CSTINFO telegrams, but is part of the Operational Train Directory structure anyway. Using different values across different consists may prevent them from reaching the SHARED Operational Train Directory state together.",
            "maxLength": 16
        },
        "trnOperator": {
            "type": "string",
            "description": "Train operator, e.g. company name. User defined and optional. Note that this doesn't get sent out on the wire in CSTINFO telegrams, but is part of the Operational Train Directory structure anyway. Using different values across different consists may prevent them from reaching the SHARED Operational Train Directory state together.",
            "maxLength": 16
        },
        "cstType": {
            "type": "string",
            "description": "Consist type, e.g. EMU, DMU, etc. User defined.",
            "maxLength": 16
        },
        "cstOwner": {
            "type": "string",
            "description": "Consist owner, e.g. company name. User defined.",
            "maxLength": 16
        },
        "dns-local-address": {
            "type": "boolean",
            "description": "True if the local (consist scope) address is returned by TCN-DNS in default. False if the train-scope address is used. Optional."
        },
        "etbInfoList": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "etbId": {
                        "type": "integer",
                        "description": "ETB ID, determines the address space of related ECNs and their functions/groups.",
                        "minimum": 0,
                        "maximum": 3
                    },
                    "cnCnt": {
                        "type": "integer",
                        "description": "Number of CNs within the consist connected to this ETB. CNs are always numbered sequentially starting with 1, so this count is sufficient.",
                        "minimum": 1,
                        "maximum": 16
                    }
                },
                "required": ["etbId", "cnCnt"]
            },
            "minItems": 1,
            "maxItems": 4,
            "uniqueItems": true,
            "description": "List of ETBs. Each ETB is identified by its ID (0-3). The cnCnt indicates the number of CNs in the ETB. The list must contain at least one ETB and can contain up to four ETBs."
        },
        "fctInfoList": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "fctName": {
                        "type": "string",
                        "description": "Function or group name. Becomes the host part of the URI. -2-3 gives this some additional semantic meaning, as described in the TCN-DNS guide.",
                        "maxLength": 16
                    },
                    "fctId": {
                        "type": "integer",
                        "description": "Function ID. Must be unique within the consist. Becomes the host part of the IP address.",
                        "minimum": 1,
                        "maximum": 32768
                    },
                    "grp": {
                        "type": "boolean",
                        "description": "Indicates if the function is a group and will resolve to a multicast address. Optional."
                    },
                    "etbId": {
                        "type": "integer",
                        "description": "ETB ID to which this function is related. 255 for all-train groups.",
                        "minimum": 0,
                        "maximum": 255
                    },
                    "cnId": {
                        "type": "integer",
                        "description": "CN on which this function/group exists. Becomes the 'subnet' after inauguration, which then becomes the network part of the IP address.",
                        "minimum": 0,
                        "maximum": 32
                    }
                },
                "required": ["fctName", "fctId", "grp", "etbId", "cnId"],
                "additionalProperties": false
            },
            "uniqueItems": true,
            "minItems": 0,
            "maxItems": 3072,
            "description": "List of functions/groups. Each function/group is identified by its name and ID. See -2-3 and the TCN-DNS guide for descriptions of these fields."
        },
        "vehInfoList": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "vehId": {
                        "type": "string",
                        "description": "Vehicle identifier, e.g. UIC number. User defined.",
                        "maxLength": 16
                    },
                    "vehType": {
                        "type": "string",
                        "description": "Vehicle type, e.g. cab, trailer, etc. User defined.",
                        "maxLength": 16
                    },
                    "vehOrient": {
                        "type": "integer",
                        "description": "Vehicle orientation. 1 for direct, 2 for inverse.",
                        "minimum": 1,
                        "maximum": 2
                    },
                    "cstVehNo": {
                        "type": "integer",
                        "description": "Consist vehicle number (index), starting with 1.",
                        "minimum": 1,
                        "maximum": 32
                    },
                    "tractVeh": {
                        "type": "boolean",
                        "description": "True if the vehicle is a traction vehicle, false if it is a trailer."
                    },
                    "vehPropSlot": {
                        "type": "integer",
                        "description": "Vehicle property slot number, starting with 1. This needs to match a 'slot' attribute of an element in 'vehPropList' below.",
                        "minimum": 1,
                        "maximum": 32
                    },
                    "fctInfoList": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "fctName": {
                                    "type": "string",
                                    "description": "Function or group name, user defined. Becomes the host part of the URI.",
                                    "maxLength": 16
                                },
                                "fctId": {
                                    "type": "integer",
                                    "description": "Function ID, user defined. Must be unique within the consist. Becomes the host part of the IP address.",
                                    "minimum": 1,
                                    "maximum": 16382
                                },
                                "grp": {
                                    "type": "boolean",
                                    "description": "Indicates if the function is a group and will resolve to a multicast address. Optional."
                                },
                                "etbId": {
                                    "type": "integer",
                                    "description": "ETB ID to which this function is related. 255 for all-train groups.",
                                    "minimum": 0,
                                    "maximum": 255
                                },
                                "cnId": {
                                    "type": "integer",
                                    "description": "CN on which this function/group exists. Becomes the 'subnet' after inauguration, which then becomes the network part of the IP address.",
                                    "minimum": 0,
                                    "maximum": 32
                                }
                            },
                            "required": ["fctName", "fctId", "grp", "etbId", "cnId"],
                            "additionalProperties": false
                        },
                        "uniqueItems": true,
                        "minItems": 0,
                        "maxItems": 3072,
                        "description": "List of functions/groups for this vehicle. See above."
                    }
                },
                "required": ["vehId", "vehType", "vehOrient", "cstVehNo", "tractVeh"],
                "additionalProperties": false
            },
            "uniqueItems": true,
            "minItems": 1,
            "maxItems": 32,
            "description": "List of vehicles. A consist must include at least one vehicle."
        },
        "cstProp": {
            "type": "object",
            "properties": {
                "version": {
                    "type": "string",
                    "pattern": "^0x[0-9A-Fa-f]{4}$",
                    "description": "Version of the properties data. User defined."
                },
                "data": {
                    "type": "array",
                    "items": {
                        "type": "string",
                        "minLength": 1,
                        "pattern": "^[A-Za-z0-9+\\/]*={0,2}$"
                    },
                    "description": "Opaque properties data. User defined. Represented here as a list of base64 strings, which will be concatenated in order before being decoded for transmission. 43692 is the length of a base64-encoded string of 32769 bytes.",
                    "minItems": 1,
                    "maxItems": 43692,
                    "uniqueItems": false
                }
            },
            "required": ["version", "data"]
        },
        "vehPropList": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "version": {
                        "type": "string",
                        "pattern": "^0x[0-9A-Fa-f]{4}$",
                        "description": "Version of the properties data. User defined."
                    },
                    "slot": {
                        "type": "integer"
                    },
                    "data": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "pattern": "^[A-Za-z0-9+\\/]*={0,2}$"
                        },
                        "description": "Opaque properties data. User defined. Represented here as a list of base64 strings, which will be concatenated in order before being decoded for transmission. 43692 is the length of a base64-encoded string of 32769 bytes.",
                        "minItems": 1,
                        "maxItems": 43692,
                        "uniqueItems": false
                    }
                },
                "required": ["version", "slot", "data"]
            }
        }
    },
    "required": ["version", "cstId", "cstType", "cstOwner", "etbInfoList", "vehInfoList"]
}