documentation for menu.json
Signed-off-by: Peter Siegmund <developer@mars3142.org>
This commit is contained in:
@@ -0,0 +1,257 @@
|
||||
# menu.json Reference
|
||||
|
||||
The `storage/menu.json` file defines the complete menu structure loaded from SPIFFS at runtime.
|
||||
It is parsed by the `Mercedes` component and rendered by `Hermes`.
|
||||
|
||||
---
|
||||
|
||||
## Top-level structure
|
||||
|
||||
```json
|
||||
{
|
||||
"screens": [ <Screen>, ... ]
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-----------|-----------------|----------|------------------------------------|
|
||||
| `screens` | array of Screen | yes | List of all screens in the menu |
|
||||
|
||||
The **first** screen in the array becomes the root/home screen.
|
||||
|
||||
---
|
||||
|
||||
## Screen
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "main_menu",
|
||||
"title": "Hauptmenü",
|
||||
"items": [ <Item>, ... ]
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---------|----------------|----------|----------------------------------------------|
|
||||
| `id` | string | yes | Unique identifier, referenced by `targetScreenId` |
|
||||
| `title` | string | yes | Displayed as the screen heading |
|
||||
| `items` | array of Item | yes | List of menu items shown on this screen |
|
||||
|
||||
---
|
||||
|
||||
## Item (common fields)
|
||||
|
||||
Every item shares these base fields:
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|----------------|---------|----------|----------------------------------------------------------------|
|
||||
| `id` | string | yes | Unique identifier across all screens |
|
||||
| `type` | string | yes | Item type — see types below |
|
||||
| `label` | string | yes | Text shown in the menu |
|
||||
| `persistent` | bool | no | If `true`, value is read/written to NVS and broadcast via WebSocket. Default: `false` |
|
||||
| `valueType` | string | no | NVS storage type: `"bool"`, `"int"`, or `"string"`. Required when `persistent: true` for toggle and selection items |
|
||||
| `visibleWhen` | object | no | Conditional visibility — see below |
|
||||
|
||||
---
|
||||
|
||||
## Item types
|
||||
|
||||
### `label`
|
||||
|
||||
Read-only text. Can display a static string or a dynamic value via the `ItemValueProvider`.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "mac_suffix",
|
||||
"type": "label",
|
||||
"label": "Device-ID"
|
||||
}
|
||||
```
|
||||
|
||||
No additional fields. Never persistent.
|
||||
|
||||
---
|
||||
|
||||
### `action`
|
||||
|
||||
Executes an action when SELECT is pressed. Fires `action_manager_execute` with the `actionTopic`.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "ota_update",
|
||||
"type": "action",
|
||||
"label": "OTA Einspielen",
|
||||
"actionTopic": "home/settings/ota_update"
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---------------|--------|----------|------------------------------------------|
|
||||
| `actionTopic` | string | yes | Action key passed to `action_manager_execute` |
|
||||
|
||||
---
|
||||
|
||||
### `submenu`
|
||||
|
||||
Navigates to another screen when SELECT is pressed.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "menu_lights",
|
||||
"type": "submenu",
|
||||
"label": "Lichtsteuerung",
|
||||
"targetScreenId": "lights_menu"
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|------------------|--------|----------|-----------------------------------|
|
||||
| `targetScreenId` | string | yes | `id` of the screen to navigate to |
|
||||
|
||||
---
|
||||
|
||||
### `toggle`
|
||||
|
||||
Boolean on/off switch. Toggled with SELECT. Displays an indicator when active.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "light_active",
|
||||
"type": "toggle",
|
||||
"label": "Einschalten",
|
||||
"persistent": true,
|
||||
"valueType": "bool",
|
||||
"actionTopic": "home/lights/activate"
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---------------|--------|----------|------------------------------------------------------------------|
|
||||
| `persistent` | bool | no | Saves state to NVS and broadcasts via WebSocket |
|
||||
| `valueType` | string | yes (if persistent) | Must be `"bool"` |
|
||||
| `actionTopic` | string | no | If set, fires `action_manager_execute` on change |
|
||||
|
||||
---
|
||||
|
||||
### `selection`
|
||||
|
||||
Cycles through a list of options using LEFT/RIGHT. The selected `value` is used for NVS storage.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "light_mode",
|
||||
"type": "selection",
|
||||
"label": "Modus",
|
||||
"persistent": true,
|
||||
"valueType": "int",
|
||||
"items": [
|
||||
{ "value": "1", "label": "Tag" },
|
||||
{ "value": "2", "label": "Nacht" },
|
||||
{ "value": "0", "label": "Simulation" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------------|-------------------------|----------|------------------------------------------------------------------|
|
||||
| `persistent` | bool | no | Saves selected value to NVS and broadcasts via WebSocket |
|
||||
| `valueType` | string | yes (if persistent) | `"int"` or `"string"` depending on NVS storage type |
|
||||
| `actionTopic`| string | no | If set, fires `action_manager_execute` with the selected value |
|
||||
| `items` | array of SelectionItem | yes | At least one entry required |
|
||||
|
||||
**SelectionItem:**
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---------|--------|----------|--------------------------------------------------|
|
||||
| `value` | string | yes | Value written to NVS (converted via `valueType`) |
|
||||
| `label` | string | yes | Text shown in the menu |
|
||||
|
||||
The **first** item in the array is the default when no NVS value exists.
|
||||
|
||||
---
|
||||
|
||||
## `visibleWhen`
|
||||
|
||||
Makes an item visible only when another item has a specific value.
|
||||
|
||||
```json
|
||||
{
|
||||
"visibleWhen": {
|
||||
"itemId": "light_mode",
|
||||
"value": "0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|----------|--------|----------|----------------------------------------------------------|
|
||||
| `itemId` | string | yes | `id` of the controlling item (must be on any screen) |
|
||||
| `value` | string | yes | The controlling item's value that makes this item visible |
|
||||
|
||||
Works with `toggle` (compare against `"true"`/`"false"`) and `selection` (compare against the selected `value`).
|
||||
Hidden items are skipped during UP/DOWN navigation.
|
||||
|
||||
---
|
||||
|
||||
## Complete example
|
||||
|
||||
```json
|
||||
{
|
||||
"screens": [
|
||||
{
|
||||
"id": "main_menu",
|
||||
"title": "Hauptmenü",
|
||||
"items": [
|
||||
{
|
||||
"id": "menu_lights",
|
||||
"type": "submenu",
|
||||
"label": "Lichtsteuerung",
|
||||
"targetScreenId": "lights_menu"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "lights_menu",
|
||||
"title": "Lichtsteuerung",
|
||||
"items": [
|
||||
{
|
||||
"id": "light_active",
|
||||
"type": "toggle",
|
||||
"label": "Einschalten",
|
||||
"persistent": true,
|
||||
"valueType": "bool",
|
||||
"actionTopic": "home/lights/activate"
|
||||
},
|
||||
{
|
||||
"id": "light_mode",
|
||||
"type": "selection",
|
||||
"label": "Modus",
|
||||
"persistent": true,
|
||||
"valueType": "int",
|
||||
"items": [
|
||||
{ "value": "1", "label": "Tag" },
|
||||
{ "value": "2", "label": "Nacht" },
|
||||
{ "value": "0", "label": "Simulation" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "light_variant",
|
||||
"type": "selection",
|
||||
"label": "Variante",
|
||||
"persistent": true,
|
||||
"valueType": "int",
|
||||
"visibleWhen": {
|
||||
"itemId": "light_mode",
|
||||
"value": "0"
|
||||
},
|
||||
"items": [
|
||||
{ "value": "1", "label": "Standard" },
|
||||
{ "value": "2", "label": "Warm" },
|
||||
{ "value": "3", "label": "Natur" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user