hobdrive-docs

HobDrive Layout Specification

English Russian

This document collects the layout tags, attributes and options used by HobDrive UI layout files.

Layout Contract

Top-level tags

Example:

<include file="default-tripcomp.layout" if='${!sexists("GasTrigger")}'/>

section

Defines a logical screen/page block. Common attributes:

Example:

<section name="GPS">
  ...
</section>
<section name="Fuel Trims" if="STFT1">
  ...
</section>

config elements

Example:

<config id="Layout_ECUFuel" type="bool" default="false"
        title="Use Fuel Level data from ECU"
        descr="If enabled - fuel level will be shown from ECU. Otherwise - estimated from fuel consumption"
        title-ru="Показывать уровень топлива из ЭБУ"
        descr-ru="Если включено - уровень топлива будет браться из ЭБУ. Иначе - показывается оценочный уровень топлива"/>

Layout containers

Example (cycle temperature sensors every 4 seconds):

<switch if='${Layout_RollTemp = true}' index='$${ svalue("DateTime") / 4000 }'>
  <item id="ATFTemp" .../>
  <item id="CVTTemp" .../>
  <item id="EngineOilTemp" .../>
</switch>

item

Represents a widget in a grid or stack. Common attributes and usages:

Example usages found in default-tripcomp.layout:

<item id="FuelLevel" if='${Layout_ECUFuel != true}' inherit="_FuelIndicator, _EditAction" onclick="NewFueling"/>
<item id="Odometer" if="${Layout_ECU_Odometer != true}" actions="SetupOdometer" size="large" inherit="_EditAction"/>

Examples:

Special item types

  • type=”button” — clickable button. Use action=”invoke(NAME)” to call ECU/service action.
  • type=”static” — static text block. E.g. type="static" size="micro"
  • gauge / chart / image decorators — declared either as item with nested decorators or in gauge/theme files; can accept decorators like image, and attributes image-path, image-scale, image-width, image-height, image-rotate.

Decorators and nested elements

  • item may contain nested decorators (per changelog). Example syntax:
  • Common decorator attributes: image-zorder, image-path, image-scale, image-width, image-height, image-rotate (can contain dynamic expressions).

Other decorators exist for progress/tile/padding etc., and many can accept dynamic expressions such as image-rotate='$${ Sensor_Value - 45 }'.

Layout-level attributes and features from changelog

  • if — conditional rendering for section or item. Can use sensor names, boolean flags like PortraitLayout, LandscapeLayout, or compound expressions.
  • ignore-gauges in section — ignores global gauge attributes for all elements inside the section.
  • gauge local definitions — gauge definitions can be declared inside section to scope them locally.
  • swap-direction on gauges: swap-direction="true" to change direction of bar or roundbar.
  • horizontal-offset in roundbar.
  • break decorator — <break/> splits rendering into independent stages.
  • maximize-focus, controls="autohide" — useful for dash panels.
  • time-scale — used in charts to compress/expand time axis.
  • text-evaluator — advanced gauge attribute (returns arbitrary dynamic text), used in tank/description rendering.

Additional attributes and behaviors observed in layout files and changelogs:

  • optional / volatile on section (controls visibility rules in some hosts).
  • period on item — refresh period in milliseconds.
  • precision — numeric formatting or special formats (e.g., 6fixed).
  • colspan / rowspan — grid spanning.

Example of a chart item with filters and custom description:

Sensor and expression features

  • Sensors can be referenced directly by id in if attributes or as item ids.
  • TinyExe helpers and eval expressions available in ecuxml. Variables and functions accessible include: Pi, E, PositiveInfinity, NegativeInfinity and other globals from themes or gauge definitions.
  • Filters for sensors (wrap) as above.

TinyExe / eval example (from changelogs):

image-rotate='$${ Sensor_Value - 45 }'

Sensor formatted access example:

<item id="TripTime[fillup]"/> — uses extradata from sensor history APIs.

Sensor lists and autogenerated panels

  • section with class="SensorList" and ns="<namespace>" generates a screen listing sensors for a namespace. Use exclude regex to filter out unwanted sensor IDs. Example:

Conditional expressions

  • The if attribute can be a simple sensor presence test (e.g., if="STFT1") or a full expression referencing theme variables, day/night flags, layout flags, and sensor values. Example seen: if="SY_ABS_TEVES.ABS_ControlModuleVoltage, Chery_A21_ABS_TRW.ABS_ControlModuleVoltage"

Notes: if can contain comma-separated identifiers which act as OR conditions in practice (layout files often list multiple sensors/namespaces separated by commas).

Interpolation in Expressions

In addition to unadorned expressions, two interpolation styles are available:

  • ${ } interpolation: Evaluated once when the layout is built. Use this form for static computations or one-time assignments. Applicable for any attributes.

  • $${ } interpolation: Evaluated dynamically, making it suitable for values that update over time (e.g., animations or periodic sensor updates). Only applicable to the selected elements/attributes:

    • text-evaluator, switch[index], visibility, image-rotate, image-path, crop

These forms allow embedding TinyExe expressions within attribute values to achieve either static or dynamic evaluation as needed.

Grid sizing hints

  • rows and cols accept comma separated values. Empty entries are flexible cells, numbers provide fixed size hints. Example: rows="30,,," cols="30,,30".

You can nest grid elements to create complex responsive regions.

Other useful attributes and behaviors (from changelog and examples)

  • period on item — sets refresh period for the widget.
  • precision — formatting precision or special tags like 6fixed.
  • description="aside" — places descriptive text aside.
  • inherit — reuses widget styling (colors/formatting) from theme or other definitions.
  • text-values and custom-units allow mapping numeric values to textual labels or alternate unit systems.
  • min-limit / max-limit — clamp values for charts.

Widget and decorator attributes (observed in user.layout)

  • type (examples): bar, roundbar, chart, text, static — many visual widgets are selected via type on the item.

  • cache-interval — UI cache/refresh hint (milliseconds or unit) used to control smoothing/plotting; frequently used on chart and gauge-like widgets. Example: cache-interval="6".

  • red-green — color threshold list; comma-separated numbers indicating color boundaries (interpretation depends on widget). Examples: red-green="100,5", red-green="10,120,150".

  • bars-count — number of bars or segments used by bar/roundbar widgets. Example: bars-count="10".

  • transparenttrue/false whether background is transparent for the widget.

  • border-width / border-opacity — visual border control. Example: border-width="3", border-opacity="1".

  • colored-value — whether value text is colored according to thresholds: colored-value="true".

  • fade-coeff — visual fading coefficient used on charts/gauges to control trail transparency: fade-coeff="0.8".

  • width-compression — compress drawing horizontally: width-compression="0.9".

  • item-size / item-width / item-height / item-spacing — sizing controls for roundbars and similar widgets (absolute/logical units). Example: item-size="25", item-width="10", item-height="10", item-spacing="20".

  • small-radius-delta / small-radis-delta (typo variants observed) — small radius adjustments used for roundbars.

  • start-angle / end-angle / radius / vertical-offset — roundbar geometry attributes to control arc start/end and offset.

  • item-width/item-height vs item-size — some widgets use item-size while others use width/height pair.

  • corn-angle / middle-angle — additional roundbar geometry attributes (observed in test layouts).

  • decorator-p (padding) and p-padding — decorator shorthand for padding decorator. Example: decorator-p="padding" p-padding="10 10 10 10".

  • decorator-i / decorator-iN pattern — numbered decorators for multiple images on a single item. Use decorator-i1="image" and i1-image-path, i1-image-rotate, i1-image-zorder, i1-image-rotate-align, etc. The unnumbered decorator-i="image" with nested <image> elements is also supported.

    Examples: ```xml


- rotate / scale attributes on nested `<image>` decorators — `rotate` can contain dynamic TinyExe expressions and `scale` applies an image scale.

- custom-units — used on `DateTime` to show time variants: `custom-units="time12"`, `time`, `timesec`, `datetime`, `seconds`.

- border-opacity used on static/test items to preview borders: `border-opacity="1"`.

- numeric `size` on `item` — static items can use numeric `size` values (e.g., `size="72"`, `size="32"`) besides named sizes (`small`, `normal`, `large`).


Common `type` values seen in dashkits:

- `type="text"` — textual rendering of a sensor with `text-values` mapping.
- `type="chart"` — time-series chart for sensor.
- `type="button"` — user-invokable action.

Example: `text-values` and `type=text` usage in dashb3 kits:

`<item id="RPM" wrap="predict(50, 0.7)" text-values="0:" type="text" description="hidden">`

## Advanced: ecuxml and sensor definitions
- sensor definitions and `eval` expressions live in ecuxml files. Key features mentioned across changelogs:
  - `<eval>` expressions for computed sensors
  - `base-data` / `base-raw` for raw bytes
  - functions `get(offset)`, `get_word()` etc.
  - `text` tag with offset/length for string sensors

## Best practices and tips
- Use `if` broadly to keep layout files modular; layout files are only loaded for relevant ECUs, but `if` helps avoid rendering empty sections.
- Use `SensorList` sections for generic sensor browsing screens and `exclude` to filter noisy sensors.
- Prefer nested decorators for complex visuals; they are simpler and localized.
- Use `wrap` filters on noisy sensors (GPS, speed, MAF) for smoother rendering.
- Keep gauges local to section when possible using `ignore-gauges` and local `gauge` declarations to reduce global side-effects.

## Appendix — common attributes quick reference
- section: `name`, `fixed`, `if`, `class`, `ns`, `exclude`, `maximize-focus`, `controls`
- grid: `rows`, `cols`
- item: `id`, `type`, `text`, `action`, `size`, `precision`, `inherit`, `colspan`, `rowspan`, `description`, `period`, `wrap`
- decorators: `image` (`image-path`, `image-scale`, `image-zorder`, `image-rotate`, `image-width`/`image-height`)

## Try it — ready templates
Copy these minimal examples into a skin file to try the patterns.

GPS panel (minimal)
```xml
<ui>
  <section name="GPS">
    <grid rows=",," cols=",,">
      <item id='Latitude' precision='6fixed' size="normal"/>
      <item id='Longitude' precision='6fixed' size="normal"/>
      <item id='GPSSpeed' precision='1' />
    </grid>
  </section>
</ui>

Fan control (buttons + inherit)

<ui>
  <section name="FAN" fixed="false" if="PortraitLayout">
    <grid rows=",," cols="">
      <item id="FAN_Status" inherit="_ColoredOnOff" size='large'/>
      <item type="button" text="Fan On" action="invoke(FAN_ON)" size='extralarge' />
      <item type="button" text="Fan Off" action="invoke(FAN_OFF)" size='extralarge' />
    </grid>
  </section>
</ui>

Hybrid summary example

<ui>
  <section name="Hybrid">
    <grid rows="30,,," cols="30,,30">
      <item id="Efficiency_Battery" size='huge' />
      <item id="FuelEconomy_NoBattery" size='huge' />
      <item id="BatteryCurrent" />
      <item id="SoC" />
    </grid>
  </section>
</ui>