Laufzeitanzeige meiner Waschmaschine

Hallo zusammen,

ich setze washdata auch schon eine ganze Weile für meine Spülmaschine und die Waschmaschine ein. Habe dafür auch eine Karte gebastelt. Mit der custom buttoncard.

Wer möchte kann sich den Code gerne mitnehmen.

Hier noch ein älteres Screenshot im Betrieb. Die Zeiten unter dem Fortschrittsbalken: Start / abgelaufene Zeit / vermutete Gesamtzeit. Zeit oben über dem Fortschritsbalken ist die Restzeit.

Der Code: (ich habe soviele Einstellungen wie möglich in Variablen ausgelagert)

type: custom:button-card
entity: sensor.waschmaschine_current_power
name: Waschmaschine
icon: mdi:washing-machine
styles:
  name:
    - justify-self: start
    - align-self: center
    - font-size: 19px
    - font-weight: 400
  icon:
    - width: 30px
  card:
    - padding: 10px 10px 0 10px
    - border-radius: 14px
    - border: 1px solid rgba(58, 66, 86, 0.6);
    - background: |
        [[[
          if (states['binary_sensor.waschmaschine_running'].state === 'on') {
            return "linear-gradient(180deg, rgba(255, 159, 0, 0.3) 0%, rgba(36,49,74, 0.6) 10%)";
          } else {
            return "rgba(36,49,74, 0.6)";
          }
        ]]]
  img_cell:
    - justify-self: start
    - width: 50px
    - height: 50px
    - justify-content: center
    - border-radius: 14px
    - background-color: rgba(255, 255, 255, 0.1)
  grid:
    - grid-template-areas: |
        "i . cycle_program"
        "n n n"
        "progress progress time_remaining"
        "remaining_bar remaining_bar remaining_bar"
        "start_time time_elapsed total_duration"
        "hr hr hr"
        "total_power total_power total_power"
        "current power voltage"
    - grid-template-columns: 1fr auto 1fr
    - grid-template-rows: 60px 50px 30px 30px 30px 20px 50px 70px
  custom_fields:
    cycle_program:
      - justify-self: end
      - align-self: center
      - font-size: 16px
      - font-weight: 300
      - padding: 0 25px
      - height: 50px
      - border-radius: 14px
      - background-color: |
          [[[
            return states['binary_sensor.waschmaschine_running'].state === 'off' 
            ? 'rgba(11, 80, 110, 1)' 
            : 'rgba(255, 255, 255, 0.1)'; 
          ]]]
      - opacity: 1
      - display: flex
      - align-items: center
      - align-content: center
    time_remaining:
      - justify-self: end
      - align-self: center
      - font-weight: 400
      - font-size: 14px
    remaining_bar:
      - margin: 0
      - border-radius: 16px
      - background-color: rgba(255, 255, 255, 0.1)
      - border: 1px solid rgba(145, 149, 147, 0.3)
      - opacity: 1
      - overflow: hidden
    start_time:
      - justify-self: start
      - font-weight: 300
      - font-size: 12px
    total_duration:
      - justify-self: end
      - font-weight: 300
      - font-size: 12px
    time_elapsed:
      - justify-self: center
      - font-weight: 300
      - font-size: 12px
    total_power:
      - justify-self: end
      - font-size: 13px
      - font-weight: 300
      - padding: 10px
      - min-width: 100px
      - border-radius: 14px
      - background-color: rgba(11, 80, 110, 1)
      - border: 1px solid rgba(225, 225, 225, 0.1);
      - opacity: 1
      - text-align: right
      - margin: 5px 0
    power:
      - justify-self: center
      - font-size: 13px
      - font-weight: 300
      - padding: 10px
      - min-width: 90px
      - border-radius: 14px
      - background-color: rgba(21, 21, 21, 0.3)
      - border: 1px solid rgba(225, 225, 225, 0.1);
      - opacity: 1
      - text-align: center
      - margin: 5px 0
    current:
      - justify-self: start
      - font-size: 13px
      - font-weight: 300
      - padding: 10px
      - min-width: 90px
      - border-radius: 14px
      - background-color: rgba(21, 21, 21, 0.3)
      - border: 1px solid rgba(225, 225, 225, 0.1);
      - opacity: 1
      - text-align: center
      - margin: 5px 0
    voltage:
      - justify-self: end
      - font-size: 13px
      - font-weight: 300
      - padding: 10px
      - min-width: 90px
      - border-radius: 14px
      - background-color: rgba(21, 21, 21, 0.3)
      - border: 1px solid rgba(225, 225, 225, 0.1);
      - opacity: 1
      - text-align: center
      - margin: 5px 0
    hr:
      - height: 2px
      - background-color: rgba(21, 21, 21, 0.5)
      - border-radius: 2px
      - margin: 11px 50px
    progress:
      - justify-self: start
      - font-weight: 300
      - font-size: 12px
custom_fields:
  hr: ""
  progress: Programm Fortschritt
  remaining_bar: |
    [[[
      var state = states['sensor.waschmaschine_progress'].state;
      var width = (state > 0) ? state : 0;
      var height = '20px'
      var accent_color = 'rgba(145, 149, 147, 1)'
      return `<div style="background-color: ${accent_color}; height:${height}; width: ${width}%;"></div>`;
    ]]]
  total_power: |
    [[[
      const val = states['sensor.waschmaschine_mit_offset'].state;
      const is_invalid = val === 'unknown' || val === 'unavailable';
      const icon = "mdi:lightning-bolt";
      var icon_width = '20px';
      var icon_margin = '5px';
      var icon_color = '#c1c1c1';
      const formatted_val = is_invalid ? "0,00" : parseFloat(val).toFixed(2);
      const display_val = formatted_val.replace('.', ',');
      return `<ha-icon icon="${icon}" style="width:${icon_width}; margin-right: ${icon_margin}; color: ${icon_color};"></ha-icon> <span>Gesamtleistung - ${display_val} kWh</span>`;
    ]]]
  current: |
    [[[
      const val = states['sensor.shelly_waschmaschine_current'].state;
      const icon = "mdi:current-ac";
      var icon_width = '20px';
      var icon_margin = '5px';
      var icon_color = '#c1c1c1';
      const is_invalid = val === 'unknown' || val === 'unavailable';
      const formatted_val = is_invalid ? "0,00" : parseFloat(val).toFixed(2);
      const display_val = formatted_val.replace('.', ',');
      return `<ha-icon icon="${icon}" style="width:${icon_width}; margin-right: ${icon_margin}; color: ${icon_color};"></ha-icon> <span>${display_val} A</span>`;
    ]]]
  power: |
    [[[
      const val = states['sensor.shelly_waschmaschine_power'].state;
      const icon = "mdi:flash";
      var icon_width = '20px';
      var icon_margin = '5px';
      var icon_color = '#c1c1c1';
      const is_invalid = val === 'unknown' || val === 'unavailable';
      const formatted_val = is_invalid ? "0,00" : parseFloat(val).toFixed(2);
      const display_val = formatted_val.replace('.', ',');
      return `<ha-icon icon="${icon}" style="width:${icon_width}; margin-right: ${icon_margin}; color: ${icon_color};"></ha-icon> <span>${display_val} W</span>`;
    ]]]
  voltage: |
    [[[
      const val = states['sensor.shelly_waschmaschine_voltage'].state;
      const icon = "mdi:sine-wave";
      var icon_width = '20px';
      var icon_margin = '5px';
      var icon_color = '#c1c1c1';
      const is_invalid = val === 'unknown' || val === 'unavailable';
      const formatted_val = is_invalid ? "0,00" : parseFloat(val).toFixed(2);
      const display_val = formatted_val.replace('.', ',');
      return `<ha-icon icon="${icon}" style="width:${icon_width}; margin-right: ${icon_margin}; color: ${icon_color};"></ha-icon> <span>${display_val} V</span>`;
    ]]]
  cycle_program: |
    [[[
      const cp = states['select.waschmaschine_cycle_program'].state;
      const icon = "mdi:progress-wrench";
      const name = cp === 'auto_detect' ? 'Automatische Erfassung' : cp;
      var icon_width = '20px';
      var icon_margin = '10px';
      var icon_color = '#c1c1c1';
      return `<ha-icon icon="${icon}" style="width:${icon_width}; margin-right: ${icon_margin}; color: ${icon_color};"></ha-icon> <span>${name}</span>`;
    ]]]
  start_time: "00:00"
  time_remaining: |
    [[[
      const s = states['sensor.waschmaschine_time_remaining'].state;
      if (s === 'off' || s === 'unavailable' || s === 'unknown') return '';

      const total_min = parseInt(s);
      const h = Math.floor(total_min / 60);
      const m = total_min % 60;

      const hh = String(h).padStart(2, '0');
      const mm = String(m).padStart(2, '0');
      const time = `${hh}:${mm}`;

      const is_running = states['binary_sensor.waschmaschine_running'].state === 'on';

      return is_running ? `Restzeit: ${time} h` : `${time} h`;
    ]]]
  total_duration: |
    [[[
      const s = states['sensor.waschmaschine_total_duration'].state;
      const is_running = states['binary_sensor.waschmaschine_running'].state === 'on';
      if (s === 'unknown' || s === 'unavailable') return '00:00 h';

      const total_minutes = parseInt(s);
      const h = Math.floor(total_minutes / 60);
      const m = total_minutes % 60;

      const hh = String(h).padStart(2, '0');
      const mm = String(m).padStart(2, '0');
      const time = `${hh}:${mm}`;

      return is_running ? `Dauer: ${time} h` : `${time} h`;
    ]]]
  time_elapsed: |
    [[[
      const s = states['sensor.waschmaschine_elapsed_time'].state;
      const is_running = states['binary_sensor.waschmaschine_running'].state === 'on';
      const progress = states['sensor.waschmaschine_progress'].state;
      if (s === 'unknown' || s === 'unavailable') return '00:00 h';

      const total_sec = parseInt(s);
      const h = Math.floor(total_sec / 3600);
      const m = Math.floor((total_sec % 3600) / 60);

      const hh = String(h).padStart(2, '0');
      const mm = String(m).padStart(2, '0');

      if (!is_running && progress == 100) return 'Ende';
      return is_running ? `Zeit: ${hh}:${mm} h` : `${hh}:${mm} h`;
    ]]]
section_mode: true
grid_options:
  rows: full
  columns: full
tap_action:
  action: none
hold_action:
  action: none
double_tap_action:
  action: none

Beide Geräte hängen an einem Shelly, der die Entitäten liefert.

1 „Gefällt mir“