Custom Card "Senoro.Win Door/Window Sensor"¶
This is a custom card for the Senoro.Win door and window sensor that combines a reed contact with a handle position sensor. The card displays the current state with visual indicators and optional battery monitoring.

Credits¶
Author: T1ppes - 2026
Features¶
- Dual Sensor Display: Shows both the reed contact status (open/closed) and handle position (closed/tilted/open)
- Smart State Detection:
- Locked: Contact closed AND handle closed
- Closed: Contact closed, handle tilted or open
- Tilted: Contact open AND handle tilted
- Open: Contact open AND handle open
- Manipulated: Contact open BUT handle closed (security alert)
- Visual Indicators:
- Color-coded icon and background based on state
- Lock/unlock badge icon on the sensor icon
- Optional battery level monitoring with warning indicator
- Customizable:
- Custom name and icon
- Optional background color highlighting
- Configurable battery warning thresholds
Requirements¶
- Senoro.Win Sensor: A door or window sensor from Senoro.de with both contact and handle position sensors
- Home Assistant Entities:
- Binary sensor for the reed contact (e.g.,
binary_sensor.door_contact) - Sensor for the handle position (e.g.,
sensor.door_handle) - states should be "Closed", "Tilted", or "Open" - Optional: Battery level sensor (e.g.,
sensor.door_battery)
- Binary sensor for the reed contact (e.g.,
Variables¶
| Variable | Default | Required | Notes |
|---|---|---|---|
ulm_custom_card_senoro_win_handle |
yes | Entity ID of the handle position sensor | |
ulm_custom_card_senoro_win_name |
entity.friendly_name |
no | Custom name for the sensor |
ulm_custom_card_senoro_win_icon |
entity.icon or mdi:window-closed |
no | Custom icon |
ulm_custom_card_senoro_win_color |
blue |
no | Color for open/tilted states (blue, green, yellow, red, etc.) |
ulm_custom_card_senoro_win_force_background_color |
false |
no | Enable background color highlighting |
ulm_custom_card_senoro_win_battery_level |
no | Entity ID of the battery level sensor | |
ulm_custom_card_senoro_win_battery_warning |
20 |
no | Battery percentage for yellow warning |
ulm_custom_card_senoro_win_battery_warning_low |
5 |
no | Battery percentage for red warning |
ulm_show_last_changed |
false |
no | Show last changed time instead of state |
States and Icons¶
| Contact | Handle | State | Icon | Color |
|---|---|---|---|---|
| OFF | Closed | Locked | Lock | Green |
| OFF | Tilted/Open | Closed | Lock | Default |
| ON | Tilted | Tilted | Unlock | Blue/Custom |
| ON | Open | Open | Unlock | Blue/Custom |
| ON | Closed | Manipulated | Alert | Red |
Usage¶
Basic Configuration¶
- type: "custom:button-card"
template: custom_card_senoro_win
entity: binary_sensor.front_door_contact
variables:
ulm_custom_card_senoro_win_handle: sensor.front_door_handle
Full Configuration with All Options¶
- type: "custom:button-card"
template: custom_card_senoro_win
entity: binary_sensor.balcony_door_contact
variables:
ulm_custom_card_senoro_win_handle: sensor.balcony_door_handle
ulm_custom_card_senoro_win_name: "Balcony Door"
ulm_custom_card_senoro_win_icon: "mdi:door"
ulm_custom_card_senoro_win_color: "yellow"
ulm_custom_card_senoro_win_force_background_color: true
ulm_custom_card_senoro_win_battery_level: sensor.balcony_door_battery
ulm_custom_card_senoro_win_battery_warning: 25
ulm_custom_card_senoro_win_battery_warning_low: 10
Multiple Windows in a Grid¶
- type: "grid"
columns: 2
cards:
- type: "custom:button-card"
template: custom_card_senoro_win
entity: binary_sensor.bedroom_window_contact
variables:
ulm_custom_card_senoro_win_handle: sensor.bedroom_window_handle
ulm_custom_card_senoro_win_name: "Bedroom"
ulm_custom_card_senoro_win_battery_level: sensor.bedroom_window_battery
- type: "custom:button-card"
template: custom_card_senoro_win
entity: binary_sensor.living_room_window_contact
variables:
ulm_custom_card_senoro_win_handle: sensor.living_room_window_handle
ulm_custom_card_senoro_win_name: "Living Room"
ulm_custom_card_senoro_win_battery_level: sensor.living_room_window_battery
Template Code¶
Template Code
---
### Custom Card Senoro Win ###
custom_card_senoro_win:
template:
- "icon_info_bg"
- "ulm_language_variables"
- "ulm_custom_card_senoro_win_language_variables"
variables:
ulm_custom_card_senoro_win_entity: "[[[ return entity.entity_id ]]]"
ulm_custom_card_senoro_win_handle: ""
ulm_custom_card_senoro_win_name: ""
ulm_custom_card_senoro_win_icon: ""
ulm_custom_card_senoro_win_color: "blue"
ulm_custom_card_senoro_win_force_background_color: false
ulm_custom_card_senoro_win_battery_level: ""
ulm_custom_card_senoro_win_battery_warning: 20
ulm_custom_card_senoro_win_battery_warning_low: 5
ulm_show_last_changed: false
triggers_update: "all"
name: >
[[[
if (variables.ulm_custom_card_senoro_win_name) {
return variables.ulm_custom_card_senoro_win_name;
}
return entity.attributes.friendly_name;
]]]
icon: >
[[[
if (variables.ulm_custom_card_senoro_win_icon && variables.ulm_custom_card_senoro_win_icon !== "") {
return variables.ulm_custom_card_senoro_win_icon;
}
return entity.attributes.icon;
]]]
label: >
[[[
if (variables.ulm_show_last_changed) {
return states[entity.entity_id].last_changed;
}
const contact = states[variables.ulm_custom_card_senoro_win_entity].state;
const handle = states[variables.ulm_custom_card_senoro_win_handle].state;
if (contact === "unavailable" || handle === "unavailable"){
return variables.ulm_unavailable;
} else if (contact === "off" && handle === "Closed"){
return variables.ulm_custom_card_senoro_win_locked;
} else if (contact === "off" && (handle === "Tilted" || handle === "Open")){
return variables.ulm_custom_card_senoro_win_closed;
} else if (contact === "on" && handle === "Tilted"){
return variables.ulm_custom_card_senoro_win_tilted;
} else if (contact === "on" && handle === "Open"){
return variables.ulm_custom_card_senoro_win_open;
} else if (contact === "on" && handle === "Closed"){
return variables.ulm_custom_card_senoro_win_manipulated;
}
return "Unknown";
]]]
state:
- operator: "template"
value: >
[[[
const contact = states[variables.ulm_custom_card_senoro_win_entity].state;
return (contact === "on");
]]]
styles:
icon:
- color: >
[[[
const contact = states[variables.ulm_custom_card_senoro_win_entity].state;
const handle = states[variables.ulm_custom_card_senoro_win_handle].state;
if (contact === "on"){
if (handle === "Closed"){
return 'rgba(var(--color-red), 1)';
} else {
var color = variables.ulm_custom_card_senoro_win_color;
return 'rgba(var(--color-' + color + '), 1)';
}
}
]]]
img_cell:
- background-color: >
[[[
const contact = states[variables.ulm_custom_card_senoro_win_entity].state;
const handle = states[variables.ulm_custom_card_senoro_win_handle].state;
if (contact === "on"){
if (handle === "Closed"){
return 'rgba(var(--color-red), 0.2)';
} else {
var color = variables.ulm_custom_card_senoro_win_color;
return 'rgba(var(--color-' + color + '), 0.2)';
}
}
]]]
card:
- background-color: >
[[[
const contact = states[variables.ulm_custom_card_senoro_win_entity].state;
const handle = states[variables.ulm_custom_card_senoro_win_handle].state;
if (variables.ulm_custom_card_senoro_win_force_background_color) {
if (contact === "on" && (handle === "Tilted" || handle === "Open")){
var color = variables.ulm_custom_card_senoro_win_color;
return 'rgba(var(--color-' + color + '),var(--opacity-bg))';
} else if (contact === "on" && handle === "Closed"){
return 'rgba(var(--color-red),var(--opacity-bg))';
}
}
]]]
custom_fields:
notification: >
[[[
const contact = states[variables.ulm_custom_card_senoro_win_entity].state;
const handle = states[variables.ulm_custom_card_senoro_win_handle].state;
if (handle === "Tilted" || handle === "Open"){
return `<ha-icon icon="mdi:lock-open-variant" style="width: 12px; height: 12px; color: var(--primary-background-color);"></ha-icon>`;
} else if (contact === "off" && handle === "Closed"){
return `<ha-icon icon="mdi:lock" style="width: 12px; height: 12px; color: var(--primary-background-color);"></ha-icon>`;
} else if (contact === "on" && handle === "Closed"){
return `<ha-icon icon="mdi:alert" style="width: 12px; height: 12px; color: var(--primary-background-color);"></ha-icon>`;
}
]]]
notification_battery: >
[[[
if (variables.ulm_custom_card_senoro_win_battery_level !== "") {
if (states[variables.ulm_custom_card_senoro_win_battery_level].state <= variables.ulm_custom_card_senoro_win_battery_warning) {
return `<ha-icon icon="mdi:battery-low" style="width: 12px; height: 12px; color: var(--primary-background-color);"></ha-icon>`;
}
}
]]]
styles:
grid:
- position: "relative"
custom_fields:
notification:
- border-radius: "50%"
- position: "absolute"
- left: "28px"
- top: "-6px"
- height: "16px"
- width: "16px"
- border: "2px solid var(--card-background-color)"
- font-size: "12px"
- line-height: "14px"
- background-color: >
[[[
const contact = states[variables.ulm_custom_card_senoro_win_entity].state;
const handle = states[variables.ulm_custom_card_senoro_win_handle].state;
if (contact === "off" && handle === "Closed"){
return "rgba(var(--color-green),1)";
} else {
return "rgba(var(--color-red),1)";
}
]]]
notification_battery:
- border-radius: "50%"
- position: "absolute"
- left: "-6px"
- top: "-6px"
- height: "16px"
- width: "16px"
- border: "2px solid var(--card-background-color)"
- font-size: "12px"
- line-height: "14px"
- background-color: >
[[[
if (variables.ulm_custom_card_senoro_win_battery_level !== "") {
if (states[variables.ulm_custom_card_senoro_win_battery_level].state <= variables.ulm_custom_card_senoro_win_battery_warning_low) {
return "rgba(var(--color-red),1)";
} else if (states[variables.ulm_custom_card_senoro_win_battery_level].state <= variables.ulm_custom_card_senoro_win_battery_warning) {
return "rgba(var(--color-yellow),1)";
}
}
]]]
Language Variables¶
The card supports multiple languages. Available translations:
English (EN)
---
### Custom Card Senoro Win - English Language Variables ###
ulm_custom_card_senoro_win_language_variables:
variables:
ulm_custom_card_senoro_win_open: "Open"
ulm_custom_card_senoro_win_tilted: "Tilted"
ulm_custom_card_senoro_win_closed: "Closed"
ulm_custom_card_senoro_win_locked: "Locked"
ulm_custom_card_senoro_win_manipulated: "Manipulated"
ulm_custom_card_senoro_win_battery_is_at: "Battery is at"
German (DE)
---
### Custom Card Senoro Win - German Language Variables ###
ulm_custom_card_senoro_win_language_variables:
variables:
ulm_custom_card_senoro_win_open: "Offen"
ulm_custom_card_senoro_win_tilted: "Gekippt"
ulm_custom_card_senoro_win_closed: "Geschlossen"
ulm_custom_card_senoro_win_locked: "Verschlossen"
ulm_custom_card_senoro_win_manipulated: "Manipuliert"
ulm_custom_card_senoro_win_battery_is_at: "Batterie ist an"
Note: Only include the language file you need. Delete the others to prevent loading order issues.
Troubleshooting¶
Handle States Not Working¶
Make sure your handle sensor reports states as "Closed", "Tilted", and "Open" (with capital first letters). If your sensor uses different values (like "closed", "tilted", "open" in lowercase), you'll need to adjust the card's label section or create a template sensor to convert the states.
Battery Icon Not Showing¶
Verify that:
- The battery sensor entity ID is correct
- The battery level is a number (percentage)
- The battery level is below your warning threshold
Icon Not Displaying¶
If you see a generic icon instead of your door/window icon, check that your contact sensor entity has an icon attribute set in Home Assistant.
Support¶
For issues, questions, or feature requests, please open an issue on the UI Lovelace Minimalist GitHub repository.