{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://opendeviceio.org/schema/v0.1/device.schema.json",
  "title": "OpenDeviceIO Device",
  "description": "An open, machine-readable description of a hardware device's I/O, power, physical, and compliance characteristics. Canonical source of truth for the OpenDeviceIO (.odio.json) format, v0.1.",
  "type": "object",
  "required": ["odioVersion", "id", "device", "ports"],
  "properties": {
    "$schema": { "type": "string", "description": "URI of the schema this document conforms to." },
    "odioVersion": {
      "type": "string",
      "description": "Semantic version of the OpenDeviceIO format this file conforms to.",
      "pattern": "^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?$"
    },
    "id": {
      "type": "string",
      "description": "Stable, URL-safe device identifier: slug(manufacturer)/slug(model)[@slug(revision)]. Slug rule: lowercase; '+' -> '-plus'; runs of other non [a-z0-9._-] characters -> '-'.",
      "pattern": "^[a-z0-9][a-z0-9-]*\\/[a-z0-9][a-z0-9._-]*(?:@[a-z0-9][a-z0-9._-]*)?$"
    },
    "device": { "$ref": "#/$defs/device" },
    "ports": {
      "type": "array",
      "description": "The device's externally accessible I/O ports.",
      "items": { "$ref": "#/$defs/port" }
    },
    "power": { "$ref": "#/$defs/power" },
    "physical": { "$ref": "#/$defs/physical" },
    "standards": { "type": "array", "items": { "$ref": "#/$defs/standard" } },
    "parameters": { "$ref": "#/$defs/parameters" },
    "provenance": { "$ref": "#/$defs/provenance" }
  },
  "patternProperties": { "^x-": {} },
  "additionalProperties": false,

  "$defs": {
    "device": {
      "type": "object",
      "description": "Device identity and classification.",
      "required": ["manufacturer", "model"],
      "properties": {
        "manufacturer": { "type": "string", "minLength": 1 },
        "model": { "type": "string", "minLength": 1 },
        "revision": { "type": "string", "description": "Hardware revision, if applicable." },
        "category": {
          "type": "string",
          "description": "Dotted taxonomy path, e.g. 'av/extender/transmitter' or 'it/network/switch'.",
          "pattern": "^[a-z0-9]+(?:/[a-z0-9-]+)*$"
        },
        "productLine": { "type": "string" },
        "gtin": { "type": "string", "description": "GTIN/UPC/EAN.", "pattern": "^\\d{8,14}$" },
        "sku": { "type": "string", "description": "Manufacturer SKU / part number." },
        "productUrl": { "type": "string", "format": "uri" },
        "datasheetUrl": { "type": "string", "format": "uri" },
        "releaseDate": { "type": "string", "format": "date" }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false
    },

    "port": {
      "type": "object",
      "description": "One externally accessible connector (or a group of identical connectors), the physical link it provides, and the logical signal flows it carries.",
      "required": ["id", "direction", "connector", "signals"],
      "properties": {
        "id": { "type": "string", "description": "Identifier unique within this device.", "pattern": "^[a-z0-9][a-z0-9._-]*$" },
        "label": { "type": "string", "description": "Human-facing label as silkscreened on the device, e.g. 'HDMI INPUT 1'." },
        "direction": {
          "type": "string",
          "description": "Overall port direction. Individual signal flows may override via signal.direction.",
          "enum": ["input", "output", "bidirectional"]
        },
        "connector": { "$ref": "#/$defs/connector" },
        "connectorOther": { "type": "string", "description": "Free-text connector name; required when connector is 'other'." },
        "count": {
          "type": "integer",
          "description": "Number of identical, separately addressable connectors collapsed into this entry. Use individual entries when labels or positions differ.",
          "minimum": 1, "default": 1
        },
        "poleCount": {
          "type": "integer",
          "description": "Physical poles/pins on a terminal-block-style connector (e.g. a 3-pole Phoenix). Independent of how many signal channels are carried; see signal.channels.",
          "minimum": 1
        },
        "poles": {
          "type": "array",
          "description": "Optional pole-to-function map for pin-level detail (e.g. Phoenix RS-232 pinout).",
          "items": {
            "type": "object",
            "required": ["pole"],
            "properties": {
              "pole": { "type": "integer", "minimum": 1 },
              "function": { "type": "string", "description": "e.g. 'tx', 'rx', 'gnd', 'audio-l+', 'gpio-1'." },
              "label": { "type": "string" }
            },
            "patternProperties": { "^x-": {} },
            "additionalProperties": false
          }
        },
        "link": { "$ref": "#/$defs/link" },
        "signals": {
          "type": "array",
          "description": "One or more concurrent logical signal flows carried by this connector. A single network or USB connector commonly carries several (e.g. Dante + AES67 + AV-over-IP + control + general LAN).",
          "minItems": 1,
          "items": { "$ref": "#/$defs/signal" }
        },
        "location": {
          "type": "object",
          "description": "Optional physical layout hint for rendering the device face.",
          "properties": {
            "face": { "type": "string", "enum": ["front", "rear", "top", "bottom", "left", "right"] },
            "group": { "type": "string", "description": "Logical grouping label, e.g. 'inputs', 'outputs', 'control'." },
            "order": { "type": "integer", "minimum": 0 }
          },
          "patternProperties": { "^x-": {} },
          "additionalProperties": false
        },
        "notes": { "type": "string" }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false,
      "allOf": [
        { "if": { "properties": { "connector": { "const": "other" } } }, "then": { "required": ["connectorOther"] } }
      ]
    },

    "connector": {
      "type": "string",
      "description": "Controlled connector (physical jack) vocabulary. Use 'other' with connectorOther when not listed. The connector describes the jack only; the transmission standard belongs in port.link and the carried flows in port.signals.",
      "enum": [
        "hdmi-type-a", "hdmi-type-b", "hdmi-type-c", "hdmi-type-d",
        "displayport", "mini-displayport",
        "dvi-d", "dvi-i", "dvi-a", "hd15-vga",
        "usb-a", "usb-b", "usb-b-mini", "usb-b-micro", "usb-c",
        "rj45", "rj45-shielded", "ethercon",
        "sfp", "sfp+", "sfp28", "qsfp", "qsfp+", "qsfp28",
        "fiber-lc", "fiber-lc-duplex", "fiber-sc", "fiber-st", "fiber-mpo", "fiber-mtp", "opticalcon",
        "bnc", "bnc-din-1.0-2.3", "rca", "f-type", "toslink", "mini-toslink",
        "xlr-3-m", "xlr-3-f", "xlr-5-m", "xlr-5-f", "mini-xlr-3", "mini-xlr-4", "xlr-combo",
        "euroblock-3.5mm", "euroblock-5.08mm", "phoenix", "terminal-block", "captive-screw",
        "trs-3.5mm", "trrs-3.5mm", "ts-6.35mm", "trs-6.35mm",
        "speakon-nl2", "speakon-nl4", "speakon-nl8", "binding-post", "banana",
        "db9", "db15", "db25", "rj11", "rj12",
        "sma", "rp-sma", "tnc", "n-type",
        "iec-c8", "iec-c14", "iec-c16", "iec-c20", "powercon", "powercon-true1", "nema-5-15", "barrel-dc", "phoenix-power",
        "other"
      ]
    },

    "link": {
      "type": "object",
      "description": "The physical transmission layer ('pipe') a port provides, independent of the logical flows it carries. PoE, link speed, USB power delivery, and fiber characteristics live here once per port rather than being duplicated across flows.",
      "properties": {
        "type": {
          "type": "string",
          "enum": ["ethernet", "usb", "thunderbolt", "sdi", "hdmi", "displayport", "dvi", "vga", "analog-audio", "aes3", "fiber", "coax", "twisted-pair", "wireless", "mains", "dc", "other"]
        },
        "typeOther": { "type": "string" },
        "standard": { "type": "string", "description": "Transmission standard/version, e.g. 'hdmi-2.1', 'dp-1.4', '12g-sdi', 'hdbaset-3', 'usb-3.2-gen2', '1000base-t'." },
        "speed": { "type": "string", "description": "Link speed where applicable, e.g. '100m', '1g', '2.5g', '5g', '10g', '25g', '40g', '100g'." },
        "bandwidthGbps": { "type": "number", "exclusiveMinimum": 0, "description": "Raw link bandwidth in Gbps, when useful." },
        "poe": {
          "type": "object",
          "description": "Power over Ethernet capability of this link.",
          "properties": {
            "standard": { "type": "string", "enum": ["802.3af", "802.3at", "802.3bt-type3", "802.3bt-type4", "passive", "other"] },
            "role": { "type": "string", "enum": ["pse", "pd"], "description": "pse = sources power; pd = consumes power." },
            "classWatts": { "type": "number", "exclusiveMinimum": 0 }
          },
          "patternProperties": { "^x-": {} },
          "additionalProperties": false
        },
        "powerDeliveryWatts": { "type": "number", "minimum": 0, "description": "USB Power Delivery budget on this link, in watts." },
        "usbRole": { "type": "string", "enum": ["host", "device", "dual-role"], "description": "Physical USB role of the connector." },
        "fiberMode": { "type": "string", "enum": ["single-mode", "multi-mode"] },
        "fiberStrands": { "type": "integer", "minimum": 1 },
        "notes": { "type": "string" }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false,
      "allOf": [
        { "if": { "properties": { "type": { "const": "other" } }, "required": ["type"] }, "then": { "required": ["typeOther"] } }
      ]
    },

    "channels": {
      "type": "integer",
      "description": "Number of independent, separately-routable circuits of this flow carried by the port (default 1). A 3-pole RS-232 connector has channels=1; an 8-pole GPIO block has channels=8.",
      "minimum": 1, "default": 1
    },
    "signalDirection": {
      "type": "string",
      "description": "Direction of this specific flow; overrides the port direction when present.",
      "enum": ["input", "output", "bidirectional"]
    },

    "signal": {
      "type": "object",
      "description": "A logical signal flow carried by a port. The 'domain' discriminates the attribute set; 'transport' names the protocol/standard carrying it.",
      "required": ["domain"],
      "oneOf": [
        { "$ref": "#/$defs/signalVideo" },
        { "$ref": "#/$defs/signalAudio" },
        { "$ref": "#/$defs/signalControl" },
        { "$ref": "#/$defs/signalNetwork" },
        { "$ref": "#/$defs/signalData" },
        { "$ref": "#/$defs/signalPower" }
      ]
    },

    "signalVideo": {
      "type": "object",
      "required": ["domain"],
      "properties": {
        "domain": { "const": "video" },
        "transport": {
          "type": "string",
          "enum": ["hdmi", "displayport", "dvi", "vga", "component", "composite", "s-video", "sdi-3g", "sdi-6g", "sdi-12g", "hdbaset", "sdvoe", "ndi", "ndi-hx", "ipmx", "dante-av", "av-over-ip", "usb-uvc", "h.264", "h.265", "mjpeg", "other"]
        },
        "transportOther": { "type": "string" },
        "direction": { "$ref": "#/$defs/signalDirection" },
        "channels": { "$ref": "#/$defs/channels" },
        "maxResolution": { "type": "string", "description": "e.g. '4096x2160' or '3840x2160'." },
        "maxRefreshHz": { "type": "number", "exclusiveMinimum": 0 },
        "colorDepthBits": { "type": "integer", "minimum": 1 },
        "chromaSubsampling": { "type": "string", "enum": ["4:4:4", "4:2:2", "4:2:0"] },
        "hdcp": { "type": "string", "description": "HDCP version, e.g. '1.4', '2.2', '2.3', or 'none'." },
        "hdr": { "type": "array", "items": { "type": "string" }, "description": "Supported HDR formats, e.g. 'hdr10', 'hdr10+', 'dolby-vision', 'hlg'." },
        "scaling": { "type": "boolean", "description": "Port performs scaling/format conversion." },
        "edidManagement": { "type": "boolean" },
        "notes": { "type": "string" }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false,
      "allOf": [ { "if": { "properties": { "transport": { "const": "other" } }, "required": ["transport"] }, "then": { "required": ["transportOther"] } } ]
    },

    "signalAudio": {
      "type": "object",
      "required": ["domain"],
      "properties": {
        "domain": { "const": "audio" },
        "transport": {
          "type": "string",
          "enum": ["analog", "lpcm", "aes3", "spdif", "adat", "madi", "arc", "earc", "dante", "aes67", "avb", "milan", "cobranet", "livewire", "usb-uac", "bluetooth", "other"]
        },
        "transportOther": { "type": "string" },
        "direction": { "$ref": "#/$defs/signalDirection" },
        "channels": { "$ref": "#/$defs/channels" },
        "maxChannelsPerCircuit": { "type": "integer", "minimum": 1, "description": "Audio channels within one circuit (e.g. 2 for a stereo pair)." },
        "networkChannels": { "type": "integer", "minimum": 1, "description": "For audio-over-IP, the number of network audio channels (e.g. Dante 64x64 -> 64)." },
        "levelDbu": { "type": "number", "description": "Nominal level in dBu (e.g. +4 line, -10 consumer ~ -7.78 dBu)." },
        "impedanceOhms": { "type": "number", "exclusiveMinimum": 0 },
        "sampleRateHz": { "type": "integer", "exclusiveMinimum": 0 },
        "bitDepth": { "type": "integer", "minimum": 1 },
        "phantomPower": { "type": "boolean", "description": "48V phantom power available (typically mic inputs)." },
        "balanced": { "type": "boolean" },
        "gainDbRange": { "type": "string", "description": "Adjustable gain range, e.g. '0-60'." },
        "maxSplDb": { "type": "number", "description": "Max SPL for a transducer, in dB." },
        "notes": { "type": "string" }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false,
      "allOf": [ { "if": { "properties": { "transport": { "const": "other" } }, "required": ["transport"] }, "then": { "required": ["transportOther"] } } ]
    },

    "signalControl": {
      "type": "object",
      "required": ["domain"],
      "properties": {
        "domain": { "const": "control" },
        "transport": {
          "type": "string",
          "enum": ["rs-232", "rs-422", "rs-485", "ir", "cec", "gpio", "contact-closure", "relay", "usb-hid", "usb-cdc", "cresnet", "knx", "dali", "dmx512", "artnet", "sacn", "onvif", "sip", "bacnet", "modbus", "mqtt", "http", "rest", "telnet", "ssh", "ip-control", "other"]
        },
        "transportOther": { "type": "string" },
        "direction": { "$ref": "#/$defs/signalDirection" },
        "channels": { "$ref": "#/$defs/channels" },
        "baudRange": { "type": "string", "description": "e.g. '9600-115200'." },
        "irCarrierKhz": { "type": "number", "exclusiveMinimum": 0, "description": "IR carrier frequency, e.g. 38." },
        "roles": { "type": "array", "items": { "type": "string" }, "description": "e.g. 'controller', 'controlled'." },
        "busAddressable": { "type": "boolean", "description": "Bus protocol where multiple devices share the line (RS-485, DMX, KNX, DALI)." },
        "maxBusDevices": { "type": "integer", "minimum": 1 },
        "notes": { "type": "string" }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false,
      "allOf": [ { "if": { "properties": { "transport": { "const": "other" } }, "required": ["transport"] }, "then": { "required": ["transportOther"] } } ]
    },

    "signalNetwork": {
      "type": "object",
      "description": "General IP connectivity / infrastructure flow (LAN, control network, management). Service-specific media flows that happen to ride Ethernet (Dante, AES67, SDVoE, NDI...) are modeled under their own domain (audio/video) with the matching transport.",
      "required": ["domain"],
      "properties": {
        "domain": { "const": "network" },
        "transport": {
          "type": "string",
          "enum": ["ethernet", "ip", "control-network", "av-network", "management", "vlan-trunk", "other"]
        },
        "transportOther": { "type": "string" },
        "direction": { "$ref": "#/$defs/signalDirection" },
        "channels": { "$ref": "#/$defs/channels" },
        "vlanCapable": { "type": "boolean" },
        "managed": { "type": "boolean" },
        "redundancy": { "type": "string", "enum": ["none", "lag", "smpte-2022-7", "parallel", "stp", "other"] },
        "protocols": { "type": "array", "items": { "type": "string" }, "description": "Additional transported AV/IT protocols not broken out as separate flows, e.g. 'dante', 'ndi', 'sdvoe'." },
        "notes": { "type": "string" }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false,
      "allOf": [ { "if": { "properties": { "transport": { "const": "other" } }, "required": ["transport"] }, "then": { "required": ["transportOther"] } } ]
    },

    "signalData": {
      "type": "object",
      "description": "Non-AV data payload (e.g. USB data, mass storage, generic file transfer).",
      "required": ["domain"],
      "properties": {
        "domain": { "const": "data" },
        "transport": { "type": "string", "enum": ["usb-data", "usb-mass-storage", "thunderbolt", "file-transfer", "other"] },
        "transportOther": { "type": "string" },
        "direction": { "$ref": "#/$defs/signalDirection" },
        "channels": { "$ref": "#/$defs/channels" },
        "rateGbps": { "type": "number", "exclusiveMinimum": 0 },
        "notes": { "type": "string" }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false,
      "allOf": [ { "if": { "properties": { "transport": { "const": "other" } }, "required": ["transport"] }, "then": { "required": ["transportOther"] } } ]
    },

    "signalPower": {
      "type": "object",
      "description": "Power delivery as a port's function (e.g. a DC output, 12V trigger, PDU outlet, speaker drive). Note: PoE belongs on link.poe and USB-PD on link.powerDeliveryWatts.",
      "required": ["domain"],
      "properties": {
        "domain": { "const": "power" },
        "transport": { "type": "string", "enum": ["ac", "dc", "usb-pd", "phantom", "trigger", "wireless-power", "other"] },
        "transportOther": { "type": "string" },
        "direction": { "$ref": "#/$defs/signalDirection" },
        "channels": { "$ref": "#/$defs/channels" },
        "role": { "type": "string", "enum": ["source", "sink"], "description": "source = supplies power out of this port; sink = draws power in." },
        "nominalVoltage": { "type": "number", "description": "Volts." },
        "maxWatts": { "type": "number", "minimum": 0 },
        "maxAmps": { "type": "number", "minimum": 0 },
        "notes": { "type": "string" }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false,
      "allOf": [ { "if": { "properties": { "transport": { "const": "other" } }, "required": ["transport"] }, "then": { "required": ["transportOther"] } } ]
    },

    "power": {
      "type": "object",
      "description": "Device-level power characteristics.",
      "properties": {
        "inputs": {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["type"],
            "properties": {
              "type": { "type": "string", "enum": ["ac", "dc", "poe", "usb-pd"] },
              "voltageRange": { "type": "string", "description": "e.g. '100-240V'." },
              "nominalVoltage": { "type": "number", "description": "Volts (typically for DC)." },
              "frequencyHz": { "type": "string", "description": "e.g. '50/60'." },
              "connector": { "type": "string", "description": "Connector vocabulary value, e.g. 'iec-c14', 'barrel-dc'." },
              "standard": { "type": "string", "description": "For PoE inputs, e.g. '802.3at'." }
            },
            "patternProperties": { "^x-": {} },
            "additionalProperties": false
          }
        },
        "consumptionWatts": {
          "type": "object",
          "properties": {
            "typical": { "type": "number", "minimum": 0 },
            "max": { "type": "number", "minimum": 0 },
            "standby": { "type": "number", "minimum": 0 }
          },
          "patternProperties": { "^x-": {} },
          "additionalProperties": false
        },
        "heatBtuPerHour": { "type": "number", "minimum": 0, "description": "Optional; derivable from watts (W x 3.412) if absent." },
        "redundant": { "type": "boolean", "description": "True if the device has redundant power supplies." }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false
    },

    "physical": {
      "type": "object",
      "description": "Physical dimensions and mounting. SI units; dimensions in millimetres, mass in grams.",
      "properties": {
        "dimensionsMm": {
          "type": "object",
          "properties": {
            "width": { "type": "number", "exclusiveMinimum": 0 },
            "height": { "type": "number", "exclusiveMinimum": 0 },
            "depth": { "type": "number", "exclusiveMinimum": 0 }
          },
          "patternProperties": { "^x-": {} },
          "additionalProperties": false
        },
        "weightGrams": { "type": "number", "exclusiveMinimum": 0 },
        "rackUnits": { "type": "number", "minimum": 0, "description": "Height in rack units (U). 0 if not rack-mounted; 0.5 for half-U, etc." },
        "rackMountable": { "type": "boolean" },
        "rackWidth": { "type": "string", "enum": ["full", "half", "third", "quarter"] },
        "mounting": {
          "type": "array",
          "items": { "type": "string", "enum": ["rack", "surface", "wall", "under-table", "pole", "ceiling", "din-rail", "vesa", "desktop"] }
        },
        "ipRating": { "type": "string", "description": "e.g. 'IP20', 'IP65'." },
        "color": { "type": "string" }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false
    },

    "standard": {
      "type": "object",
      "description": "A device-level compliance or interoperability standard (safety, EMC, environmental). Per-signal interop standards (Dante, AES67, etc.) are expressed as signal.transport.",
      "required": ["name"],
      "properties": {
        "category": { "type": "string", "enum": ["safety", "emc", "env", "av", "network", "wireless", "other"] },
        "name": { "type": "string", "minLength": 1, "description": "e.g. 'UL 62368-1', 'FCC Part 15 Class A', 'HDBaseT', 'AES67', 'RoHS'." },
        "detail": { "type": "string" }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false
    },

    "parameters": {
      "type": "object",
      "description": "Free-form parametric data with no typed home (operating temperature, latency, MTBF, warranty, etc.). Values may be primitives or { value, unit } objects.",
      "additionalProperties": {
        "oneOf": [
          { "type": "string" },
          { "type": "number" },
          { "type": "boolean" },
          {
            "type": "object",
            "required": ["value"],
            "properties": {
              "value": { "type": ["string", "number", "boolean"] },
              "unit": { "type": "string" }
            },
            "patternProperties": { "^x-": {} },
            "additionalProperties": false
          }
        ]
      }
    },

    "provenance": {
      "type": "object",
      "description": "Where this data came from and how trustworthy it is.",
      "properties": {
        "generator": { "type": "string", "description": "Tool that produced the file, e.g. 'genie/0.1.0', or 'manual'." },
        "method": { "type": "string", "enum": ["llm-extraction", "manual", "manufacturer"] },
        "sourceDocuments": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "title": { "type": "string" },
              "url": { "type": "string", "format": "uri" },
              "sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
              "retrieved": { "type": "string", "format": "date" }
            },
            "patternProperties": { "^x-": {} },
            "additionalProperties": false
          }
        },
        "validation": {
          "type": "object",
          "properties": {
            "status": { "type": "string", "enum": ["draft", "reviewed", "manufacturer-verified"] },
            "by": { "type": "string" },
            "date": { "type": "string", "format": "date" }
          },
          "patternProperties": { "^x-": {} },
          "additionalProperties": false
        },
        "confidence": {
          "type": "object",
          "properties": {
            "overall": { "type": "number", "minimum": 0, "maximum": 1 },
            "lowConfidenceFields": { "type": "array", "items": { "type": "string" }, "description": "JSON paths the generator was unsure about, for human review." }
          },
          "patternProperties": { "^x-": {} },
          "additionalProperties": false
        }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false
    }
  }
}
