Skip to content

Data loss & silent failure footguns: /sys/custom/*.LoxCC overlays wiped on push, PicoC Code attribute collapse, and TPDC sidecars #28

Open

Description

@joakimar

While using lox-cli (v0.12.0) in a Config-as-Code workflow against a Miniserver Gen 2 (firmware 17.2.x), we identified three critical mechanics where lox config either silently overwrites user changes made in the Loxone App or silently disables embedded logic blocks.

Sharing the root causes and exact protocol mechanics below in case they are helpful for hardening lox-cli.


1. Live App/Web UI Custom Changes (/sys/custom/<UUID>.LoxCC) Are Ignored by download/pull and Wiped by push

Problem

When a user modifies configuration settings at runtime via the Loxone App or Web UI—such as adjusting lighting scenes/moods (LightController2), modifying timer schedules (DayTimer), adding/editing AutopilotRule blocks, or changing room comfort setpoints (IRoomControllerV2)—the Miniserver does not rewrite /prog/sps_<ver>_<timestamp>.zip.

Instead, the Miniserver writes an individual LoxCC-compressed XML fragment for each modified control block to:

/sys/custom/<UUID>.LoxCC

When a new /prog/sps_new.zip is uploaded and loaded on reboot/reload, the Miniserver logs:

Loading sps_new.zip - Remove old custom changes

and deletes all files in /sys/custom/ (assuming the uploader already merged them into sps0.LoxCC, which Loxone Config does during "Load from Miniserver" when the Miniserver logs Read config: combine custom changes).

Because lox config download / pull only downloads /prog/sps_*.zip and ignores /sys/custom/*.LoxCC:

  1. lox config download / pull misses all runtime App/UI adjustments made since the last full save.
  2. Any subsequent lox config push (or patch) triggers Remove old custom changes on the Miniserver and permanently wipes all user scenes, timers, and rules sitting in /sys/custom/.
  3. Even if /sys/custom/ is pulled at the start of an editing session, uploading a full XML snapshot later without a Just-In-Time pull + 3-way merge overwrites any App changes made in the interim.

Format of /sys/custom/<UUID>.LoxCC & Suggested Fix

Each /sys/custom/<UUID>.LoxCC file uses the standard 0xaabbccee LoxCC header/compression and decompresses to a standalone UTF-8 XML fragment for that single <C> element, e.g.:

<?xml version="1.0" encoding="utf-8"?>
<C Type="DayTimer" V="178" U="00000000-0000-0000-ffff000000000001" Title="Example Timer" ...>
	<Co K="InputTrigger" U="00000000-0000-0000-ffff000000000002"/>
	...
</C>

To prevent data loss:

  • download / pull: After downloading the latest /prog/sps_*.zip and decompressing sps0.LoxCC, list /sys/custom/*.LoxCC via FTP, decompress each overlay, and replace the matching <C ... U="<UUID>" ...>...</C> block in the base XML (or for a newly created AutopilotRule whose UUID is not yet in the base XML, insert it into <C Type="Page" ... SpNo="1">).
  • push / patch: Immediately prior to compressing and uploading sps_new.zip, fetch the live /prog/sps_*.zip + /sys/custom/*.LoxCC state and perform a 3-way merge (base -> local_working rebased onto live_miniserver) so concurrent App changes are preserved rather than wiped.

2. Multiline PicoC (Code1 / Code4 / Code8 / Code16) Code="..." Collapse Silently Comments Out Entire C Programs

Problem

In released v0.12.0, running any XML-mutating subcommand (e.g. lox config room add, lox config add, lox config set-param, lox config wire-connector) parses and re-serializes the .Loxone XML via xml-rs, which normalizes \r\n newlines inside attribute values into spaces per W3C XML 1.0 Section 3.3.3.

For <C Type="Code16" ... Code="..."> (PicoC) blocks, it is standard practice for the C source in Code="..." to begin with a single-line // header comment on line 1:

// Custom RS485 / HVAC controller logic
char *buf = ...;
while (true) {
    ...
}

When lox-cli collapses \r\n inside Code="..." into single spaces, the entire 150-line C program is concatenated onto line 1 behind the leading // comment. The resulting file still passes lox config validate with 0 errors and compiles cleanly on the Miniserver, silently turning the entire PicoC program into a no-op comment.

Suggested Fix


3. Touch Pure Display Tree (TPDC, ControlType 544) Sidecar & Checksum Requirements (Related to #20)

Complementing the LoxAPP3.json and permissions.bin findings in #20, if lox-cli adds support for Touch Pure Display Tree switches (TreeDevice with SubType="32811" paired with a <C Type="TPDC"> block), four additional invariants are required for the physical screen to render:

  1. Bidirectional API Connector Loop (FLG="1"):
    • TPDC.OutputAPI must reference OutputRef.AI with FLG="1" (<In Input="<OutputRef_AI_UUID>" FLG="1" />), while OutputRef.AI references TPDC.OutputAPI, and the hardware ApiActor.I references OutputRef.AQ. Without FLG="1" on OutputAPI, the device reports Online on the Tree bus but displays a blank screen.
  2. Sidecar Payload (/prog/TPDISP/<TPDC_UUID>.json):
    • The screen carousel layout is stored both inside sps_*.zip at TPDISP/<TPDC_UUID>.json and on the FTP filesystem at /prog/TPDISP/<TPDC_UUID>.json.
    • It uses a 3-line hybrid format:
      • Line 0: JSON array of screen items ([{"U":0,"T":484,...}]) + \n
      • Line 1: 0x03 (ETX byte) + JSON array of referenced rooms + \n
      • Line 2: 0x03 (ETX byte) + JSON array of referenced categories + \n
  3. Signed 32-Bit CRC32 Attributes on <Displayconf>:
    • <Displayconf CRCS="..." CRCR="..." CRCC="..." CRCI="0" ... CO="uuid0,uuid1,..."> inside <C Type="TPDC"> must contain the signed 32-bit integer representation of zlib.crc32 over Line 0 (CRCS), Line 1 without the leading 0x03 (CRCR), and Line 2 without the leading 0x03 (CRCC).
  4. Miniserver Built-In <TechDoc> Schema (/sys/sys_THA.zip -> tdc_DEV.xml):
    • As a useful reference for lox blocks: the Miniserver stores Loxone's complete 522-block English <TechDoc> XML schema (tdc_DEV.xml, ~693 KB) inside /sys/sys_THA.zip on the FTP filesystem, including every block's LxType, numeric ControlType, ShortLink, and all Input/Output/Parameter pins with defaults and units.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions