Switching the schema per firmware generation
A single model often has units in the field on very different firmware. A newer generation may add a DSP block and drop a legacy audio section, so one flat schema either shows fields a device doesn't have or hides fields it does.
Instead of publishing a second model per firmware, keep one model and let the device tell you which shape of configuration it speaks. The device reports a schema_version value via set-config, and the schema swaps whole sections in and out based on it.
How it works
- Each firmware generation gets its own subschema under
definitions(v1,v2, …), holding only the properties that generation actually has. - One
if/thenblock per generation lives insideallOf, andthenis just a$refto that generation's definition. Adding a third generation is one new definition plus one newif/thenblock — nothing existing changes. - The trigger value is free-form, so
schema_versioncan be a version number ("2.0.0"), a plain label ("Old"/"New"), or a firmware/model codename ("Gen2"). List every accepted value in that branch'senumand they all select the same subschema. - Properties declared at the top level (outside
allOf) are shared by every generation. A device reporting an unrecognisedschema_versiontherefore still renders the common fields and simply gets no generation-specific sections. - Use
allOfwithif/thenrather than a singleif/then/elsepair once you have more than two generations, and avoid a top-leveloneOf— the editor rendersoneOfas an option picker rather than switching sections.
Every$idin the schema must be unique
$idvalues are registered document-wide. If two branches (thenandelse, or twodefinitions) declare the same$id— for example both defining"$id": "#/properties/about"— the schema fails to compile and the condition silently evaluates as false, so the form always falls through to the other branch with no error shown. Either give every branch a distinct$idor omit$idinside the branches entirely; it is not required for the form to render.
Draft supportConditional keywords (
if/then/else,allOf,$ref) come from JSON Schema draft-07, which the model's Config Schema editor supports. Drafts above 7 are not supported.
Config Schema
{
"type": "object",
"title": "Device Configuration",
"properties": {
"schema_version": {
"type": "string",
"title": "Config Schema Version",
"readOnly": true
},
"about": {
"type": "object",
"title": "About",
"properties": {
"model": { "type": "string", "title": "Model", "readOnly": true },
"firmware": { "type": "string", "title": "Firmware", "readOnly": true }
}
}
},
"definitions": {
"v1": {
"properties": {
"legacy_audio": {
"type": "object",
"title": "Audio (legacy firmware)",
"properties": {
"gain": { "type": "integer", "title": "Input Gain (dB)", "minimum": -20, "maximum": 20 },
"mono_mixdown": { "type": "boolean", "title": "Mono Mixdown" }
}
}
}
},
"v2": {
"properties": {
"dsp": {
"type": "object",
"title": "DSP (2.0 firmware)",
"properties": {
"eq_preset": { "type": "string", "title": "EQ Preset", "enum": ["flat", "voice", "music"] },
"auto_gain": { "type": "boolean", "title": "Auto Gain Control" },
"delay_ms": { "type": "integer", "title": "Output Delay (ms)", "minimum": 0, "maximum": 500 }
}
},
"network": {
"type": "object",
"title": "Network (2.0 firmware)",
"properties": {
"dhcp": { "type": "boolean", "title": "DHCP" },
"hostname": { "type": "string", "title": "Hostname" }
}
}
}
}
},
"allOf": [
{
"if": {
"properties": { "schema_version": { "enum": ["1.0.0", "Old", "Gen1"] } },
"required": ["schema_version"]
},
"then": { "$ref": "#/definitions/v1" }
},
{
"if": {
"properties": { "schema_version": { "enum": ["2.0.0", "New", "Gen2"] } },
"required": ["schema_version"]
},
"then": { "$ref": "#/definitions/v2" }
}
]
}What the device reports
The device sets its configuration through the Set Config endpoint, including schema_version alongside the sections that its firmware supports.
{
"schema_version": "Old",
"about": {
"model": "AVX-4200",
"firmware": "1.1.16"
},
"legacy_audio": {
"gain": 3,
"mono_mixdown": false
}
}{
"schema_version": "2.0.0",
"about": {
"model": "AVX-4200",
"firmware": "2.4.1"
},
"dsp": {
"eq_preset": "voice",
"auto_gain": true,
"delay_ms": 20
},
"network": {
"dhcp": true,
"hostname": "avx4200-lab"
}
}A unit reporting "Old" shows About and Audio (legacy firmware); a unit reporting "2.0.0" shows About, DSP (2.0 firmware) and Network (2.0 firmware) — from the same model and the same schema. A unit reporting "Gen2" resolves to the same sections as "2.0.0", since both values appear in that branch's enum.
Updated about 9 hours ago
