type: custom:button-card
entity: sensor.l2_solarflow_2400_ac_electric_level
name: L2
theme: liquid glass
font-family: monospace
show_icon: false
show_state: true
state_display: |
[[[
const v = parseFloat(entity.state) 0;
return v.toFixed(0) + ' %';
]]]
styles:
grid:
- grid-template-areas: "'n s' 'batt batt' 'cells cells' 'bar bar' 'ptext ptext'"
- grid-template-columns: 1fr auto
- grid-template-rows: auto auto auto auto auto
card:
- padding: 8px
- border-radius: 12px
- background: rgba(0,0,0,0)
name:
- font-weight: 700
- font-size: 28px
- font-family: monospace
- align-self: center
- justify-self: start
- text-align: left
- color: '#ffffff'
state:
- font-weight: 700
- font-variant-numeric: tabular-nums
- font-family: monospace
- font-size: 28px
- align-self: center
- justify-self: end
- text-align: right
- color: '#ffffff'
custom_fields:
batt:
- grid-area: batt
- margin-top: 6px
- height: 120px
- position: relative
- display: flex
- align-items: center
- justify-content: center
cells:
- grid-area: cells
- margin-top: 4px
- font-size: 16px
- font-family: monospace
- text-align: center
- justify-self: center
- color: rgba(230,230,230,0.9)
bar:
- grid-area: bar
- margin-top: 8px
- height: 18px
- position: relative
- width: 100%
ptext:
- grid-area: ptext
- margin-top: 4px
- font-size: 28px
- font-family: monospace
- text-align: center
- justify-self: center
- color: var(--primary-text-color)
custom_fields:
cells: |
[[[
const c1 = parseFloat(states['sensor.fo4nhn4n2001108_min_vol']?.state);
const c2 = parseFloat(states['sensor.fo4nhn4n2400904_min_vol']?.state);
const fmt = v => isNaN(v) ? '-' : v.toFixed(2) + ' V';
return ${fmt(c1)} / ${fmt(c2)};
]]]
batt: |
[[[
const soc = Math.max(0, Math.min(100, parseFloat(entity.state) 0));
const flow = parseFloat(states['sensor.l2_kombisensor_laden_entladen']?.state) || 0;
const isCharging = flow < -20;
const isDischarging = flow > 20;
// Farbskala nach SoC
let color = '#ff0000';
if (soc > 20) color = '#ff7f00';
if (soc > 40) color = '#ffd600';
if (soc > 60) color = '#c6ff00';
if (soc > 80) color = '#00c853';
const segments = 5;
const segHeight = 100 / segments;
const filled = soc;
let segHtml = '';
for (let i = 0; i < segments; i++) {
const start = i * segHeight;
const end = (i + 1) * segHeight;
const segFilled = Math.max(0, Math.min(1, (filled - start) / (end - start)));
const segColor =
segFilled 20) color = '#ff0000'; // Entladen
return `
`;
]]]
ptext: |
[[[
const p = parseFloat(states['sensor.l2_kombisensor_laden_entladen']?.state) || 0;
const absP = Math.abs(p).toFixed(0);
let text = '';
let color = 'rgba(220,220,220,0.95)';
if (Math.abs(p) 20) color = '#ff0000';
}
return ${text};
]]]