6e2ccc8b15
version: sunnypilot v2026.002.000 (staging) date: 2026-05-27T04:05:25 master commit: dfc3c98b226da57a653daf57131a8a3d66166fcb
517 lines
16 KiB
JSON
517 lines
16 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "https://sunnypilot.com/schemas/settings_ui.schema.json",
|
|
"title": "sunnypilot Settings UI Schema",
|
|
"description": "Defines the structure of the sunnypilot settings UI panels, items, rules, and vehicle-specific settings.",
|
|
"type": "object",
|
|
"required": ["schema_version", "panels", "vehicle_settings"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"$schema": {
|
|
"type": "string",
|
|
"description": "JSON Schema reference for editor support."
|
|
},
|
|
"schema_version": {
|
|
"type": "string",
|
|
"description": "Version of the settings UI schema format.",
|
|
"examples": ["1.0"]
|
|
},
|
|
"panels": {
|
|
"type": "array",
|
|
"description": "Top-level settings panels displayed in the UI.",
|
|
"items": {
|
|
"$ref": "#/$defs/Panel"
|
|
}
|
|
},
|
|
"vehicle_settings": {
|
|
"type": "object",
|
|
"description": "Brand-keyed vehicle-specific settings. Each key is a car brand (e.g. 'hyundai', 'toyota').",
|
|
"additionalProperties": {
|
|
"$ref": "#/$defs/VehicleBrandSettings"
|
|
}
|
|
}
|
|
},
|
|
"$defs": {
|
|
"Panel": {
|
|
"type": "object",
|
|
"description": "A top-level settings panel (tab) in the UI.",
|
|
"required": ["id", "label", "icon", "order"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Unique identifier for this panel."
|
|
},
|
|
"label": {
|
|
"type": "string",
|
|
"description": "Display label shown in the UI."
|
|
},
|
|
"icon": {
|
|
"type": "string",
|
|
"description": "Icon identifier for this panel."
|
|
},
|
|
"order": {
|
|
"type": "integer",
|
|
"description": "Sort order for panel display.",
|
|
"minimum": 0
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"description": "Optional description shown below the panel label."
|
|
},
|
|
"remote_configurable": {
|
|
"type": "boolean",
|
|
"description": "Whether this panel's settings can be changed remotely via sunnylink.",
|
|
"default": false
|
|
},
|
|
"sections": {
|
|
"type": "array",
|
|
"description": "Grouped sections within this panel.",
|
|
"items": {
|
|
"$ref": "#/$defs/PanelSection"
|
|
}
|
|
},
|
|
"items": {
|
|
"type": "array",
|
|
"description": "Settings items directly in this panel (no section grouping).",
|
|
"items": {
|
|
"$ref": "#/$defs/SchemaItem"
|
|
}
|
|
},
|
|
"sub_panels": {
|
|
"type": "array",
|
|
"description": "Nested sub-panels triggered by a setting.",
|
|
"items": {
|
|
"$ref": "#/$defs/SubPanel"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"PanelSection": {
|
|
"type": "object",
|
|
"description": "A grouped section within a panel.",
|
|
"required": ["id", "title"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Unique identifier for this section."
|
|
},
|
|
"title": {
|
|
"type": "string",
|
|
"description": "Display title for this section."
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"description": "Optional description shown below the section title."
|
|
},
|
|
"order": {
|
|
"type": "integer",
|
|
"description": "Sort order within the parent panel.",
|
|
"minimum": 0
|
|
},
|
|
"visibility": {
|
|
"type": "array",
|
|
"description": "Rules that determine whether this section is visible. All rules must pass.",
|
|
"items": {
|
|
"$ref": "#/$defs/Rule"
|
|
}
|
|
},
|
|
"enablement": {
|
|
"type": "array",
|
|
"description": "Rules that determine whether items in this section are enabled. All rules must pass.",
|
|
"items": {
|
|
"$ref": "#/$defs/Rule"
|
|
}
|
|
},
|
|
"attestation_required": {
|
|
"type": "boolean",
|
|
"description": "When true, the UI must show an attestation modal before any write to items in this section.",
|
|
"default": false
|
|
},
|
|
"items": {
|
|
"type": "array",
|
|
"description": "Settings items within this section.",
|
|
"items": {
|
|
"$ref": "#/$defs/SchemaItem"
|
|
}
|
|
},
|
|
"sub_panels": {
|
|
"type": "array",
|
|
"description": "Nested sub-panels within this section.",
|
|
"items": {
|
|
"$ref": "#/$defs/SubPanel"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"VehicleBrandSettings": {
|
|
"type": "object",
|
|
"description": "Brand-specific settings group inside vehicle_settings.",
|
|
"required": ["items"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"title": {
|
|
"type": "string",
|
|
"description": "Display title for this brand's settings group."
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"description": "Optional description shown below the brand title."
|
|
},
|
|
"items": {
|
|
"type": "array",
|
|
"description": "Settings items for this brand.",
|
|
"items": {
|
|
"$ref": "#/$defs/SchemaItem"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"SchemaItem": {
|
|
"type": "object",
|
|
"description": "A single settings item (toggle, option selector, button group, etc.).",
|
|
"required": ["key", "widget"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"key": {
|
|
"type": "string",
|
|
"description": "The param key this item reads/writes."
|
|
},
|
|
"widget": {
|
|
"type": "string",
|
|
"description": "The UI widget type to render.",
|
|
"enum": ["toggle", "option", "multiple_button", "button", "info"]
|
|
},
|
|
"title": {
|
|
"type": "string",
|
|
"description": "Override display title (defaults to metadata lookup by key)."
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"description": "Override description text. Rendered inline below the title. May be empty when only `details` is used."
|
|
},
|
|
"details": {
|
|
"type": "string",
|
|
"description": "Extended help text shown in a popover/modal when the user taps an info ('i') button on the row. Independent of `description`: either, both, or neither may be present."
|
|
},
|
|
"options": {
|
|
"type": "array",
|
|
"description": "Available options for 'option' or 'multiple_button' widgets.",
|
|
"items": {
|
|
"$ref": "#/$defs/SchemaOption"
|
|
}
|
|
},
|
|
"min": {
|
|
"type": "number",
|
|
"description": "Minimum value for numeric option widgets."
|
|
},
|
|
"max": {
|
|
"type": "number",
|
|
"description": "Maximum value for numeric option widgets."
|
|
},
|
|
"step": {
|
|
"type": "number",
|
|
"description": "Step increment for numeric option widgets."
|
|
},
|
|
"unit": {
|
|
"oneOf": [
|
|
{
|
|
"type": "string",
|
|
"description": "Static unit label (e.g. 'seconds', 'm/s²')."
|
|
},
|
|
{
|
|
"type": "object",
|
|
"description": "Dynamic unit that changes based on IsMetric param.",
|
|
"required": ["metric", "imperial"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"metric": {
|
|
"type": "string",
|
|
"description": "Unit label when IsMetric is true (e.g. 'km/h')."
|
|
},
|
|
"imperial": {
|
|
"type": "string",
|
|
"description": "Unit label when IsMetric is false (e.g. 'mph')."
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"description": "Unit label for numeric values. Use a string for static units or an object with metric/imperial variants for units that depend on the IsMetric param."
|
|
},
|
|
"value_map": {
|
|
"type": "object",
|
|
"description": "Maps stored values to display labels.",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"visibility": {
|
|
"type": "array",
|
|
"description": "Rules that determine whether this item is visible. All rules must pass.",
|
|
"items": {
|
|
"$ref": "#/$defs/Rule"
|
|
}
|
|
},
|
|
"enablement": {
|
|
"type": "array",
|
|
"description": "Rules that determine whether this item is enabled/interactive. All rules must pass.",
|
|
"items": {
|
|
"$ref": "#/$defs/Rule"
|
|
}
|
|
},
|
|
"sub_items": {
|
|
"type": "array",
|
|
"description": "Child items nested under this item (e.g. options revealed by a toggle).",
|
|
"items": {
|
|
"$ref": "#/$defs/SchemaItem"
|
|
}
|
|
},
|
|
"action": {
|
|
"type": "string",
|
|
"description": "Action identifier for button widgets."
|
|
},
|
|
"title_param_suffix": {
|
|
"type": "object",
|
|
"description": "Renders an extra suffix in the item title chosen by the value of another param.",
|
|
"required": ["param", "values"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"param": {
|
|
"type": "string",
|
|
"description": "Param key whose value selects the suffix label."
|
|
},
|
|
"values": {
|
|
"type": "object",
|
|
"description": "Map from stringified param value to suffix label.",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"needs_onroad_cycle": {
|
|
"type": "boolean",
|
|
"description": "When true, the device must cycle onroad/offroad for the new value to take effect.",
|
|
"default": false
|
|
},
|
|
"blocked": {
|
|
"type": "boolean",
|
|
"description": "When true, this item is treated as DEVICE_ONLY and the dashboard must not write it remotely.",
|
|
"default": false
|
|
},
|
|
"requires_attestation": {
|
|
"type": "boolean",
|
|
"description": "When true, writes to this item require an explicit per-write confirmation modal.",
|
|
"default": false
|
|
}
|
|
}
|
|
},
|
|
"SubPanel": {
|
|
"type": "object",
|
|
"description": "A nested panel that opens when triggered by a parent item.",
|
|
"required": ["id", "label", "trigger_key"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Unique identifier for this sub-panel."
|
|
},
|
|
"label": {
|
|
"type": "string",
|
|
"description": "Display label for the sub-panel header."
|
|
},
|
|
"trigger_key": {
|
|
"type": "string",
|
|
"description": "The param key that triggers opening this sub-panel."
|
|
},
|
|
"trigger_condition": {
|
|
"$ref": "#/$defs/Rule",
|
|
"description": "Optional rule that must evaluate to true for the sub-panel trigger to be active."
|
|
},
|
|
"items": {
|
|
"type": "array",
|
|
"description": "Settings items within this sub-panel.",
|
|
"items": {
|
|
"$ref": "#/$defs/SchemaItem"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"SchemaOption": {
|
|
"type": "object",
|
|
"description": "A selectable option for option/multiple_button widgets.",
|
|
"required": ["value", "label"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"value": {
|
|
"oneOf": [
|
|
{ "type": "number" },
|
|
{ "type": "string" }
|
|
],
|
|
"description": "The stored value when this option is selected."
|
|
},
|
|
"label": {
|
|
"type": "string",
|
|
"description": "The display label for this option."
|
|
},
|
|
"enablement": {
|
|
"type": "array",
|
|
"description": "Rules that determine whether this option is selectable. All rules must pass.",
|
|
"items": {
|
|
"$ref": "#/$defs/Rule"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"Rule": {
|
|
"description": "A visibility or enablement rule. Discriminated union on the 'type' field.",
|
|
"oneOf": [
|
|
{ "$ref": "#/$defs/RuleOffroadOnly" },
|
|
{ "$ref": "#/$defs/RuleNotEngaged" },
|
|
{ "$ref": "#/$defs/RuleCapability" },
|
|
{ "$ref": "#/$defs/RuleParam" },
|
|
{ "$ref": "#/$defs/RuleParamCompare" },
|
|
{ "$ref": "#/$defs/RuleNot" },
|
|
{ "$ref": "#/$defs/RuleAny" },
|
|
{ "$ref": "#/$defs/RuleAll" }
|
|
]
|
|
},
|
|
"RuleOffroadOnly": {
|
|
"type": "object",
|
|
"description": "Rule that passes only when the device is offroad.",
|
|
"required": ["type"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"const": "offroad_only"
|
|
}
|
|
}
|
|
},
|
|
"RuleNotEngaged": {
|
|
"type": "object",
|
|
"description": "Rule that passes when the vehicle is not engaged (matches Raylib `engaged = started AND (selfdriveState.enabled OR selfdriveStateSP.mads.enabled)`).",
|
|
"required": ["type"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"const": "not_engaged"
|
|
}
|
|
}
|
|
},
|
|
"RuleCapability": {
|
|
"type": "object",
|
|
"description": "Rule that checks a vehicle capability field against an expected value.",
|
|
"required": ["type", "field", "equals"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"const": "capability"
|
|
},
|
|
"field": {
|
|
"type": "string",
|
|
"description": "The capability field name to check."
|
|
},
|
|
"equals": {
|
|
"description": "The expected value to match against."
|
|
}
|
|
}
|
|
},
|
|
"RuleParam": {
|
|
"type": "object",
|
|
"description": "Rule that checks a param value against an expected value.",
|
|
"required": ["type", "key", "equals"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"const": "param"
|
|
},
|
|
"key": {
|
|
"type": "string",
|
|
"description": "The param key to read."
|
|
},
|
|
"equals": {
|
|
"description": "The expected value to match against."
|
|
}
|
|
}
|
|
},
|
|
"RuleParamCompare": {
|
|
"type": "object",
|
|
"description": "Rule that compares a numeric param value using a comparison operator.",
|
|
"required": ["type", "key", "op", "value"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"const": "param_compare"
|
|
},
|
|
"key": {
|
|
"type": "string",
|
|
"description": "The param key to read."
|
|
},
|
|
"op": {
|
|
"type": "string",
|
|
"description": "Comparison operator.",
|
|
"enum": [">", "<", ">=", "<="]
|
|
},
|
|
"value": {
|
|
"type": "number",
|
|
"description": "The numeric value to compare against."
|
|
}
|
|
}
|
|
},
|
|
"RuleNot": {
|
|
"type": "object",
|
|
"description": "Rule that negates a single child condition.",
|
|
"required": ["type", "condition"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"const": "not"
|
|
},
|
|
"condition": {
|
|
"$ref": "#/$defs/Rule",
|
|
"description": "The rule to negate."
|
|
}
|
|
}
|
|
},
|
|
"RuleAny": {
|
|
"type": "object",
|
|
"description": "Rule that passes if ANY of the child conditions pass (logical OR).",
|
|
"required": ["type", "conditions"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"const": "any"
|
|
},
|
|
"conditions": {
|
|
"type": "array",
|
|
"description": "Child rules; at least one must pass.",
|
|
"items": {
|
|
"$ref": "#/$defs/Rule"
|
|
},
|
|
"minItems": 1
|
|
}
|
|
}
|
|
},
|
|
"RuleAll": {
|
|
"type": "object",
|
|
"description": "Rule that passes only if ALL child conditions pass (logical AND).",
|
|
"required": ["type", "conditions"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"type": {
|
|
"const": "all"
|
|
},
|
|
"conditions": {
|
|
"type": "array",
|
|
"description": "Child rules; all must pass.",
|
|
"items": {
|
|
"$ref": "#/$defs/Rule"
|
|
},
|
|
"minItems": 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|