Skip to content

v2.7.0 - Custom action buttons, iOS audio + push fallback

Choose a tag to compare

@eyalgal eyalgal released this 28 May 22:54

✨ New, custom action buttons (issue #110)

You can now add your own icon buttons next to the built-in start / pause / cancel controls. Configure buttons: at card level (applies to every row), per entity row, or per pinned timer. The most specific list wins, the same way tap_action resolves.

type: custom:simple-timer-card
entities:
  - timer.ac_bedroom
buttons:
  - action: finish        # complete the timer now (native timer.finish)
  - action: add           # extend the running timer
    amount: 5m            # required, e.g. 5m, 30s, 1h
    icon: mdi:timer-plus
  - action: reduce        # subtract from the running timer
    amount: 30s
  - action: restart       # restart from the original duration
  • Shorthand presets, finish, add, reduce, restart, and pause (pause / resume is handy in the circle layout, which has no inline pause control).
  • add and reduce take a required amount (5m, 30s, 1h). For native timer.* entities, adding above the timer's configured duration restarts it at the larger value for this run only, without overwriting the helper's saved duration. Reducing below the time left finishes the timer.
  • For anything else, pass a full Home Assistant ActionConfig (perform-action, more-info, navigate, url, toggle). A perform-action with no target defaults to the timer's own entity.
  • show_when controls which states (idle / running / paused) a button appears in. Defaults to running + paused.
  • The visual editor hides presets the selected entity can't perform, so you never wire up a button that would silently under-deliver. Read-only sources (Alexa, timestamp sensors) are offered custom on-screen actions only.
  • Placement keeps tile height: bar and fill styles place buttons left of the start / cancel controls, the circle style uses a small corner button.

This covers the long-running "Finish" request: Cancel stops the timer without firing its end actions, while a finish button completes it now and fires the ring / timer.finished event (turn the AC off, run automations, etc.).

See CONFIGURATION.md for the full schema.

🐛 Fix, iOS / iPad alarm audio (follow-up to v2.5.0 / #107)

v2.5.0 added a Web Audio context unlock on first tap, but the alarm itself still failed on iPad in the "tap the card, then start a timer" case. Root cause: iOS gates audio playback per <audio> element, and the alarm was created as a fresh element when the timer fired, so it had never received a user gesture.

This release reuses a single shared <audio> element for all alarms. The same element is touched during the unlock-on-tap, so when a timer later fires, the element is already authorized and audio.play() is allowed.

On iPad after this release:

Scenario Result
Load dashboard, tap card, start timer ✅ alarm plays
Load dashboard, tap card, start 5 timers over 20 min ✅ all 5 play
Reload dashboard, tap card, start timer ✅ alarm plays
Cold load + voice/automation timer with no prior tap ❌ silent (iOS rule, unfixable in-browser, see notify below)
Locked screen or fully backgrounded tab ❌ silent (hard iOS limitation)

No behavioural change on Android, desktop Chrome, Firefox, Safari, or Edge.

✨ New, notify config for hands-off cases

The card can now fire any HA notify.* service when a timer ends. Push notifications go through iOS / Android system channels and are not subject to the in-browser autoplay policy, so they ring even when in-page audio cannot (locked screen, backgrounded tab, cold-loaded dashboard with a voice-triggered timer).

type: custom:simple-timer-card
audio_enabled: true
audio_file_url: /local/sounds/done.mp3

notify:
  service: notify.mobile_app_kitchen_ipad
  message: "{name} timer is done"
  when: on_audio_fail            # on_audio_fail (default) | always
  data:
    push:
      sound: chime.caf
  • service (required), any notify.* service.
  • message / title (optional), supports {name}, {entity_id}, {duration} placeholders.
  • when: on_audio_fail (default), only fires the notify when audio.play() is rejected by the browser. Avoids double-ringing on devices where the in-page audio works.
  • when: always, fires every time a timer ends, alongside the in-page audio.
  • data, raw object merged into the notify call. Use for iOS push.sound, interruption-level, Android channel, etc.

See CONFIGURATION.md for full details and common patterns.