Skip to content

Add first-class ttl support for post-upload deep sleep #130

Description

@LordMike

Is your feature request related to a problem? Please describe.

I recently updated to the 3.x branch of the integration and am liking it so far. The new direct-delivery and sleeping-device support is a substantial improvement.

I am hoping ttl can receive first-class support again. Earlier versions of drawcustom exposed ttl as the number of seconds the tag should sleep after an image update. In 3.x, the service accepts existing automation calls containing values such as ttl: 21600, but the schema silently removes the field and it has no effect.

Reliable queued delivery solves getting an image onto a sleeping device, but it does not let an individual image update determine when the device should next wake. First-class ttl support would restore that useful per-update control while fitting naturally into the new 3.x delivery architecture.

The reliable-delivery work in #20 and #61 covers queued content delivery. The queue-expiry option proposed in #64 is a separate concept: it controls how long pending content remains valid in Home Assistant, not how long the device sleeps after delivery.

Describe the solution you'd like

Restore ttl as a documented, optional drawcustom field and map it to OpenDisplayDevice.deep_sleep(duration_seconds=ttl) after the image has been delivered successfully.

  • Omitted ttl: preserve current behavior and do not issue an explicit sleep command.
  • ttl: 0: enter deep sleep using the device's configured cadence, with no one-shot override.
  • Positive ttl: use it as the one-shot wake-timer duration for this sleep cycle.
  • Accept 0 or 60..65535 seconds. The protocol payload is an unsigned 16-bit value and firmware applies a 60-second minimum override.
  • Validate that the target is an ESP32 device configured for battery-powered deep sleep before beginning the upload. Timed sleep is unsupported on nRF, while Silabs ignores the duration and enters EM4.
  • For immediate delivery, upload and then issue deep sleep over the same connection.
  • For queued delivery, retain ttl with the pending upload and issue deep sleep after the image and any other required connection work have completed.
  • A dry run must never issue a sleep command.
  • If the image succeeds but the sleep request is rejected, do not queue or retransmit the image solely because of the sleep failure.

The required library API is being addressed by OpenDisplay/py-opendisplay#159 and OpenDisplay/py-opendisplay#160, which add deep_sleep(duration_seconds) using protocol command CMD_DEEP_SLEEP (0x0053).

Example:

action: opendisplay.drawcustom
data:
  ttl: 21600
  # Remaining drawcustom fields...

Describe alternatives you've considered

A separate deep_sleep service would require another operation after the upload and could lose the short connection window or require reconnecting. Performing the command in the existing upload session is more reliable.

Using the device's configured cadence alone does not support per-image schedules, such as a dashboard that should sleep for six hours after one update.

Reusing the proposed expire field would mix two independent concepts: expiration determines how long Home Assistant retains undelivered content, while ttl determines how long the device sleeps after successful delivery.

A newly named field such as sleep_for would be clearer, but retaining ttl preserves existing automation YAML and its former documented meaning.

Additional context

The former selector allowed values up to 86400 seconds, but the new protocol duration is a two-byte unsigned integer with a maximum of 65535 seconds. Values above that limit should produce a clear validation error rather than being clamped.

The integration currently removes ttl explicitly in SCHEMA_DRAWCUSTOM, while both immediate and queued image delivery already pass through shared delivery code. The pending-upload record therefore appears to be the natural place to retain the one-shot duration until delivery.

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions