Created
June 14, 2025 20:32
-
-
Save lsv/e617de8a36081e1e658a385f64e943e2 to your computer and use it in GitHub Desktop.
Le Mans 2025 - homeassistant component
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- id: '1749005648026' | |
alias: Update Bordlampe Color Based on Le Mans Flags | |
description: Change light color based on Le Mans flag statuses for 1 minute then reset | |
trigger: | |
- platform: state | |
entity_id: | |
- sensor.le_mans_main_flag | |
- sensor.le_mans_flag_status_0 | |
- sensor.le_mans_flag_status_1 | |
- sensor.le_mans_flag_status_2 | |
condition: [] | |
action: | |
- choose: | |
- conditions: | |
- condition: template | |
# Check if any flag is Red | |
value_template: > | |
{{ 'Red' in [ | |
states('sensor.le_mans_main_flag'), | |
states('sensor.le_mans_flag_status_0'), | |
states('sensor.le_mans_flag_status_1'), | |
states('sensor.le_mans_flag_status_2') | |
] }} | |
sequence: | |
- service: light.turn_on | |
target: | |
entity_id: light.bordlampe_light | |
data: | |
rgb_color: [255, 0, 0] # Red | |
- conditions: | |
- condition: template | |
# Check if any flag is Yellow (and no Red) | |
value_template: > | |
{{ 'Yellow' in [ | |
states('sensor.le_mans_main_flag'), | |
states('sensor.le_mans_flag_status_0'), | |
states('sensor.le_mans_flag_status_1'), | |
states('sensor.le_mans_flag_status_2') | |
] and | |
not ('Red' in [ | |
states('sensor.le_mans_main_flag'), | |
states('sensor.le_mans_flag_status_0'), | |
states('sensor.le_mans_flag_status_1'), | |
states('sensor.le_mans_flag_status_2') | |
]) }} | |
sequence: | |
- service: light.turn_on | |
target: | |
entity_id: light.bordlampe_light | |
data: | |
rgb_color: [255, 255, 0] # Yellow | |
- conditions: | |
- condition: template | |
# Check if any flag is Green (and no Red or Yellow) | |
value_template: > | |
{{ 'Green' in [ | |
states('sensor.le_mans_main_flag'), | |
states('sensor.le_mans_flag_status_0'), | |
states('sensor.le_mans_flag_status_1'), | |
states('sensor.le_mans_flag_status_2') | |
] and | |
not ('Red' in [ | |
states('sensor.le_mans_main_flag'), | |
states('sensor.le_mans_flag_status_0'), | |
states('sensor.le_mans_flag_status_1'), | |
states('sensor.le_mans_flag_status_2') | |
]) and | |
not ('Yellow' in [ | |
states('sensor.le_mans_main_flag'), | |
states('sensor.le_mans_flag_status_0'), | |
states('sensor.le_mans_flag_status_1'), | |
states('sensor.le_mans_flag_status_2') | |
]) }} | |
sequence: | |
- service: light.turn_on | |
target: | |
entity_id: light.bordlampe_light | |
data: | |
rgb_color: [0, 255, 0] # Green | |
- delay: "00:01:00" | |
- service: light.turn_on | |
target: | |
entity_id: light.bordlampe_light | |
data: | |
rgb_color: [255, 190, 135] # Your default warm color | |
mode: single |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"domain": "lemans2025", | |
"name": "Le Mans 2025", | |
"version": "1.0.0", | |
"documentation": "", | |
"dependencies": [], | |
"codeowners": [], | |
"requirements": [] | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
import aiohttp | |
from homeassistant.components.sensor import SensorEntity | |
from homeassistant.helpers.entity_platform import AddEntitiesCallback | |
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed | |
from homeassistant.helpers.typing import HomeAssistantType, ConfigType | |
from datetime import timedelta | |
_LOGGER = logging.getLogger(__name__) | |
SESSION_ID = "7608" | |
GRAPHQL_URL = "https://live-timing-api.sportall.tv/graphql" | |
HEADERS = { | |
"Content-Type": "application/json", | |
"Origin": "https://livetiming.lemans.org", | |
"Referer": "https://livetiming.lemans.org/" | |
} | |
QUERY = { | |
"operationName": "Session", | |
"variables": { | |
"sessionId": SESSION_ID | |
}, | |
"query": """ | |
query Session($sessionId: ID!) { | |
session(sessionId: $sessionId) { | |
id | |
liveStatus { | |
currentFlag { | |
type | |
} | |
} | |
sectorFlags { | |
sector | |
type | |
} | |
} | |
} | |
""" | |
} | |
SCAN_INTERVAL = timedelta(seconds=30) | |
async def fetch_le_mans_data(hass): | |
"""Fetch data from the LeMans GraphQL API.""" | |
try: | |
async with aiohttp.ClientSession() as session: | |
async with session.post(GRAPHQL_URL, json=QUERY, headers=HEADERS) as response: | |
if response.status != 200: | |
raise UpdateFailed(f"Error fetching data: {response.status}") | |
data = await response.json() | |
session_data = data.get("data", {}).get("session", {}) | |
if not session_data: | |
raise UpdateFailed("No session data found in response") | |
return session_data | |
except Exception as e: | |
raise UpdateFailed(f"Exception during API call: {e}") | |
async def async_setup_platform(hass: HomeAssistantType, config: ConfigType, async_add_entities: AddEntitiesCallback, discovery_info=None): | |
_LOGGER.debug("LeMans 2025 sensor setup started") | |
# Create the data coordinator that fetches all data every 30 seconds | |
coordinator = DataUpdateCoordinator( | |
hass, | |
_LOGGER, | |
name="LeMans 2025 Data Coordinator", | |
update_method=lambda: fetch_le_mans_data(hass), | |
update_interval=SCAN_INTERVAL, | |
) | |
# Perform initial data fetch | |
await coordinator.async_refresh() | |
# Create sensors and pass the coordinator to them | |
sensors = [LeMansFlagSensor(coordinator)] | |
for i in range(3): | |
sensors.append(LeMansSectorFlagSensor(coordinator, i)) | |
async_add_entities(sensors, update_before_add=True) | |
class LeMansFlagSensor(SensorEntity): | |
def __init__(self, coordinator: DataUpdateCoordinator): | |
self.coordinator = coordinator | |
self._attr_unique_id = "le_mans_main_flag" | |
self._attr_name = "Le Mans Main Flag" | |
@property | |
def native_value(self): | |
return self.coordinator.data.get("liveStatus", {}).get("currentFlag", {}).get("type") | |
@property | |
def available(self): | |
return self.coordinator.last_update_success | |
async def async_added_to_hass(self): | |
self.coordinator.async_add_listener(self.async_write_ha_state) | |
class LeMansSectorFlagSensor(SensorEntity): | |
def __init__(self, coordinator: DataUpdateCoordinator, index: int): | |
self.coordinator = coordinator | |
self._index = index | |
self._attr_unique_id = f"le_mans_flag_status_{index}" | |
self._attr_name = f"Le Mans Flag Status {index + 1}" | |
@property | |
def native_value(self): | |
sector_flags = self.coordinator.data.get("sectorFlags", []) | |
if self._index < len(sector_flags): | |
return sector_flags[self._index].get("type") | |
return None | |
@property | |
def available(self): | |
return self.coordinator.last_update_success | |
async def async_added_to_hass(self): | |
self.coordinator.async_add_listener(self.async_write_ha_state) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment