OK cool, would it be difficult to make that option a choice as well as the number of message history limit that the user could select when re-configuring the F1 Sensor? I can manually edit the sensor.py and the entity.py but would have to make the changes every time you updated the integration.
I will add it to the features list and investigate the possibility. It would really help if you could create one or two issues about this as a feature on GitHub.
Until then, you can use the File native integration to write the state to a file. I have been using that for testing purposes and it works very well.
Thanx I will take a look and also familiarise myself with the feature request on GitHub.
For the team here is my latest and updated âRace Control Message Boardâ this version will display a default of the last 10 messages, with a counter at the top let stating how many session messages are in total and a toggle to display all session messages if you want to review the post session messages. Added a clear button to clear ONLY the board messages and leaves the sensor history untouched.
I created a new dashboard view and select the âPanel (single card)â option, then add any of the available card options (or add a manual card), select the edit in yaml at the bottom left and then paste in the below code:
type: custom:html-template-card
ignore_line_breaks: true
content: >
<style>
@keyframes f1-pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:0.3;transform:scale(0.6)}}
#rc-toggle{display:none;}
#rc-clear{display:none;}
#rc-extra-msgs{display:none;flex-direction:column;gap:5px;padding:0 12px 5px 12px;}
#rc-toggle:checked ~ #rc-card #rc-extra-msgs{display:flex;}
#rc-toggle:checked ~ #rc-card #rc-btn-show{display:none;}
#rc-toggle:checked ~ #rc-card #rc-btn-hide{display:inline-block;}
#rc-btn-hide{display:none;}
#rc-clear:checked ~ #rc-card #rc-messages{display:none;}
#rc-clear:checked ~ #rc-card #rc-cleared-msg{display:block;}
#rc-clear:checked ~ #rc-card #rc-btn-show{display:none;}
#rc-clear:checked ~ #rc-card #rc-btn-hide{display:none;}
#rc-clear:checked ~ #rc-card #rc-btn-clear{display:none;}
#rc-cleared-msg{display:none;}
</style>
{% set raw = states('sensor.f1_race_control') %}
{% set msgs = state_attr('sensor.f1_race_control', 'history') or [] %}
{% set session = states('sensor.f1_session_status') | lower %}
{% set session_name = states('sensor.f1_current_session') %}
{% set meeting_name = state_attr('sensor.f1_session_status', 'meeting_name') | default('') %}
{% set location = state_attr('sensor.f1_session_status', 'meeting_location') | default('') %}
{% set country = state_attr('sensor.f1_session_status', 'meeting_country') | default('') %}
{% set circuit = state_attr('sensor.f1_session_status', 'circuit_short_name') | default('') %}
{% set sorted_msgs = msgs | sort(attribute='utc') %}
{% set total = sorted_msgs | length %}
{% set limit = 10 %}
{% set show_session = session_name not in ['unknown', 'unavailable', 'none', ''] %}
{% if session == 'live' %}
{% set badge_color = '#00FF88' %}
{% set badge_bg = 'rgba(0,0,0,0.3)' %}
{% set badge_border = 'rgba(255,255,255,0.3)' %}
{% set badge_text = '#FFFFFF' %}
{% set badge_label = 'LIVE' %}
{% set dot_anim = 'animation:f1-pulse 1.4s ease-in-out infinite;' %}
{% set name_opacity = '1' %}
{% elif session == 'suspended' %}
{% set badge_color = '#FFD700' %}
{% set badge_bg = 'rgba(255,215,0,0.1)' %}
{% set badge_border = 'rgba(255,215,0,0.4)' %}
{% set badge_text = '#FFD700' %}
{% set badge_label = 'SUSPENDED' %}
{% set dot_anim = 'animation:f1-pulse 2s ease-in-out infinite;' %}
{% set name_opacity = '0.6' %}
{% elif session == 'break' %}
{% set badge_color = '#FF8000' %}
{% set badge_bg = 'rgba(255,128,0,0.1)' %}
{% set badge_border = 'rgba(255,128,0,0.4)' %}
{% set badge_text = '#FF8000' %}
{% set badge_label = 'BREAK' %}
{% set dot_anim = '' %}
{% set name_opacity = '0.6' %}
{% elif session == 'pre' %}
{% set badge_color = '#4488FF' %}
{% set badge_bg = 'rgba(68,136,255,0.1)' %}
{% set badge_border = 'rgba(68,136,255,0.4)' %}
{% set badge_text = '#4488FF' %}
{% set badge_label = 'PRE-SESSION' %}
{% set dot_anim = '' %}
{% set name_opacity = '0.6' %}
{% elif session in ['finished', 'finalised', 'ended'] %}
{% set badge_color = '#444455' %}
{% set badge_bg = 'rgba(0,0,0,0.2)' %}
{% set badge_border = 'rgba(255,255,255,0.1)' %}
{% set badge_text = '#606070' %}
{% set badge_label = session | upper %}
{% set dot_anim = '' %}
{% set name_opacity = '0.4' %}
{% else %}
{% set badge_color = '#444455' %}
{% set badge_bg = 'rgba(0,0,0,0.2)' %}
{% set badge_border = 'rgba(255,255,255,0.1)' %}
{% set badge_text = '#606070' %}
{% set badge_label = session | upper if session else 'OFFLINE' %}
{% set dot_anim = '' %}
{% set name_opacity = '0.4' %}
{% endif %}
<input type="checkbox" id="rc-toggle">
<input type="checkbox" id="rc-clear">
<div id="rc-card" style="background:#08080A;border-radius:8px;overflow:hidden;padding-bottom:16px;font-family:'F1Regular',sans-serif;">
<div style="background:#E8002D;display:flex;align-items:center;gap:16px;padding:12px 20px 12px 16px;margin-bottom:0;">
<div style="display:flex;flex-direction:column;align-items:center;justify-content:center;flex-shrink:0;width:52px;">
<div style="font-family:'F1Bold',sans-serif;font-size:48px;line-height:1;color:#fff;letter-spacing:-1px;">F<span style="color:#fff;">1</span></div>
</div>
<div style="flex:1;display:flex;flex-direction:column;gap:2px;">
<div style="display:flex;align-items:baseline;gap:10px;">
<div style="font-family:'F1Bold',sans-serif;font-size:22px;color:#ffffff;line-height:1;text-shadow:0 2px 4px rgba(0,0,0,0.3);">RACE CONTROL</div>
{% if show_session %}
<div style="font-family:'F1Bold',sans-serif;font-size:11px;letter-spacing:2px;color:rgba(255,255,255,0.6);text-transform:uppercase;white-space:nowrap;">{{ session_name | upper }}</div>
{% endif %}
</div>
{% if meeting_name %}
<div style="font-family:'F1Wide',sans-serif;font-size:12px;color:rgba(255,255,255,{{ name_opacity }});line-height:1.3;letter-spacing:0.5px;">{{ meeting_name }}</div>
{% endif %}
{% if location or country %}
<div style="font-family:'F1Regular',sans-serif;font-size:11px;color:rgba(255,255,255,0.65);line-height:1.2;letter-spacing:0.3px;">{{ circuit if circuit else '' }}{% if circuit and (location or country) %} ¡ {% endif %}{{ location if location else country }}</div>
{% endif %}
</div>
<div style="display:flex;align-items:center;gap:6px;background:{{ badge_bg }};border:1px solid {{ badge_border }};border-radius:2px;padding:5px 11px;flex-shrink:0;">
<div style="width:7px;height:7px;border-radius:50%;background:{{ badge_color }};flex-shrink:0;{{ dot_anim }}"></div>
<span style="font-family:'F1Bold',sans-serif;font-size:11px;letter-spacing:2px;color:{{ badge_text }};">{{ badge_label }}</span>
</div>
</div>
<div style="height:3px;background:linear-gradient(90deg,#E8002D,rgba(255,107,107,0.27),transparent);margin-bottom:14px;"></div>
<div style="display:flex;justify-content:space-between;align-items:center;padding:0 16px 10px;">
<div style="display:flex;align-items:center;gap:10px;">
<span style="font-family:'F1Regular',sans-serif;font-size:11px;letter-spacing:2px;text-transform:uppercase;color:#606070;">
{% if raw == 'unavailable' %}LAST SESSION ¡ {% endif %}{{ [total, limit] | min }} of {{ total }} message{% if total != 1 %}s{% endif %}
</span>
{% if total > limit %}
<label id="rc-btn-show" for="rc-toggle" style="font-family:'F1Bold',sans-serif;font-size:9px;letter-spacing:2px;text-transform:uppercase;color:#E8002D;background:rgba(232,0,45,0.08);border:1px solid rgba(232,0,45,0.3);border-radius:2px;padding:4px 10px;cursor:pointer;">SHOW ALL</label>
<label id="rc-btn-hide" for="rc-toggle" style="font-family:'F1Bold',sans-serif;font-size:9px;letter-spacing:2px;text-transform:uppercase;color:#E8002D;background:rgba(232,0,45,0.08);border:1px solid rgba(232,0,45,0.3);border-radius:2px;padding:4px 10px;cursor:pointer;">SHOW LATEST</label>
{% endif %}
{% if total > 0 %}
<label id="rc-btn-clear" for="rc-clear" style="font-family:'F1Bold',sans-serif;font-size:9px;letter-spacing:2px;text-transform:uppercase;color:#606070;background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.1);border-radius:2px;padding:4px 10px;cursor:pointer;">CLEAR</label>
{% endif %}
</div>
</div>
{% if raw == 'unknown' and total == 0 %}
<div style="margin:12px;background:rgba(232,0,45,0.08);border:1px solid rgba(232,0,45,0.3);border-radius:2px;padding:14px 18px;font-family:'F1Regular',sans-serif;font-size:13px;letter-spacing:1px;color:#FF6B6B;">
đ Awaiting race control transmissions
</div>
{% elif total == 0 %}
<div style="text-align:center;padding:48px 20px;font-family:'F1Regular',sans-serif;letter-spacing:3px;text-transform:uppercase;font-size:14px;color:#2A2A32;">
đ Awaiting race control transmissions
</div>
{% else %}
<div id="rc-cleared-msg" style="text-align:center;padding:48px 20px;font-family:'F1Regular',sans-serif;letter-spacing:3px;text-transform:uppercase;font-size:14px;color:#2A2A32;">
đ Board cleared
</div>
<div id="rc-messages">
{% macro render_msg(msg, idx) %}
{% set txt = msg.message | default('') %}
{% set ts = msg.utc | default('') %}
{% set category = msg.category | default('') %}
{% set flag = msg.flag | default('') | upper %}
{% set tu = txt | upper %}
{% if flag == 'RED' or 'RED FLAG' in tu %}
{% set bcolor = '#FF2222' %} {% set cat_label = 'Red Flag' %} {% set cat_color = '#FF4444' %} {% set bg = 'rgba(255,0,0,0.06)' %}
{% elif flag == 'YELLOW' or ('YELLOW' in tu and 'GREEN' not in tu) %}
{% set bcolor = '#FFD700' %} {% set cat_label = 'Yellow Flag' %} {% set cat_color = '#FFD700' %} {% set bg = 'rgba(255,215,0,0.04)' %}
{% elif flag == 'GREEN' or 'GREEN' in tu %}
{% set bcolor = '#00D2BE' %} {% set cat_label = 'Green Flag' %} {% set cat_color = '#00D2BE' %} {% set bg = '#15151A' %}
{% elif 'SAFETY CAR' in tu %}
{% set bcolor = '#FFD700' %} {% set cat_label = 'Safety Car' %} {% set cat_color = '#FFD700' %} {% set bg = '#15151A' %}
{% elif 'VIRTUAL SAFETY' in tu or 'VSC' in tu %}
{% set bcolor = '#FFD700' %} {% set cat_label = 'Virtual Safety Car' %} {% set cat_color = '#FFD700' %} {% set bg = '#15151A' %}
{% elif 'DRS' in tu %}
{% set bcolor = '#00D2BE' %} {% set cat_label = 'DRS' %} {% set cat_color = '#00D2BE' %} {% set bg = '#15151A' %}
{% elif 'PENALTY' in tu or 'DRIVE THROUGH' in tu or 'STOP AND GO' in tu %}
{% set bcolor = '#FF8000' %} {% set cat_label = 'Penalty' %} {% set cat_color = '#FF8000' %} {% set bg = '#15151A' %}
{% elif 'INVESTIGATION' in tu or 'STEWARD' in tu or 'NOTED' in tu %}
{% set bcolor = '#FF8000' %} {% set cat_label = 'Stewards' %} {% set cat_color = '#FF8000' %} {% set bg = '#15151A' %}
{% elif 'CHEQUERED' in tu or 'SESSION END' in tu or 'RACE END' in tu %}
{% set bcolor = '#0067FF' %} {% set cat_label = 'Session End' %} {% set cat_color = '#0067FF' %} {% set bg = '#15151A' %}
{% elif 'OVERTAKE' in tu or 'PIT' in tu or 'RESUME' in tu %}
{% set bcolor = '#0067FF' %} {% set cat_label = category if category else 'Info' %} {% set cat_color = '#4488FF' %} {% set bg = '#15151A' %}
{% else %}
{% set bcolor = '#2A2A32' %} {% set cat_label = category if category else 'Message' %} {% set cat_color = '#606070' %} {% set bg = '#15151A' %}
{% endif %}
{% if ts | length >= 19 %}
{% set time_display = ts[11:19] %}
{% elif ts | length > 0 %}
{% set time_display = ts %}
{% else %}
{% set time_display = '--:--:--' %}
{% endif %}
<div style="background:{{ bg }};border:1px solid #2A2A32;border-left:3px solid {{ bcolor }};border-radius:2px;padding:10px 14px;display:flex;gap:12px;align-items:flex-start;">
<div style="font-family:'F1Regular',sans-serif;font-weight:700;font-size:10px;color:#606070;min-width:24px;padding-top:2px;">#{{ '%02d' % idx }}</div>
<div style="font-family:'F1Regular',sans-serif;font-size:13px;color:#E8002D;min-width:64px;white-space:nowrap;padding-top:1px;font-variant-numeric:tabular-nums;">{{ time_display }}</div>
<div style="flex:1;">
<div style="font-family:'F1Bold',sans-serif;font-size:9px;letter-spacing:2px;text-transform:uppercase;margin-bottom:2px;color:{{ cat_color }};">{{ cat_label }}</div>
<div style="font-family:'F1Regular',sans-serif;font-size:13px;color:#FFFFFF;line-height:1.5;">{{ txt }}</div>
</div>
</div>
{% endmacro %}
{% if total > limit %}
<div id="rc-extra-msgs">
{% for msg in sorted_msgs[:(total - limit)] %}
{{ render_msg(msg, loop.index) }}
{% endfor %}
</div>
{% endif %}
<div style="display:flex;flex-direction:column;gap:5px;padding:0 12px;">
{% for msg in sorted_msgs[-limit:] %}
{{ render_msg(msg, (total - limit + loop.index) if total > limit else loop.index) }}
{% endfor %}
</div>
</div>
{% endif %}
</div>
Iâm either blind or the feature doesnât exist. Is it possible to âfast forwardâ in replay mode?
Not at the moment
would be something id really be looking for as well, had played around myself with a script until i saw there was know exposed seek/position control
This is so amazing, thank you for doing this. I have my light set up and built and anxious to try our tonight during qualifying. I am using this connected up to a WLED RGB strip. Iâm wondering if it would be possible to offer a variation of your code that can call out a WLED playlist preset rather than a solid color?
Started making my dashboard. Need to play around with it. Iâve set it up, so it shows slightly different on small (such as mobiles) and larger (tablets, laptops etc) screens to accommodate space. I am using 4.1.0-beta.1 of F1 Sensor, and 1.3.0-beta.1 of F1 Sensor Live Data Card. You also require to have layout-card installed from HACS.
Code is at the bottom
Smaller Screens
Larger Screens
type: custom:layout-card
layout_type: custom:grid-layout
layout:
grid-template-columns: repeat(12, minmax(0, 1fr))
grid-template-rows: auto
grid-gap: 8px
width: 100%
max_width: 100%
margin: 0
card_margin: 0
grid-template-areas: >
"card1 card1 card1 card1 card1 card1 card1 card1 card1 card1 card1 card1"
"card2 card2 card2 card2 card2 card2 card2 card2 card2 card2 card2 card2"
"card3 card3 card3 card3 card4 card4 card4 card4 card4 card4 card4 card4"
"card5 card5 card5 card5 card5 card5 card6 card6 card6 card6 card6 card6"
mediaquery:
"(max-width: 768px)":
grid-template-columns: minmax(0, 1fr)
grid-template-areas: |
"card1"
"card2"
"card3"
"card4"
"card5"
"card6"
cards:
- show_flag: true
show_lap_progress: true
show_track_status: true
show_weather: true
show_time_remaining: true
show_time_elapsed: true
type: custom:f1-live-session-card
view_layout:
grid-area: card1
session_entity: sensor.f1_current_session
session_status_entity: sensor.f1_session_status
formation_start_entity: binary_sensor.f1_formation_start
lap_count_entity: sensor.f1_race_lap_count
track_status_entity: sensor.f1_track_status
next_race_entity: sensor.f1_next_race
session_time_remaining_entity: sensor.f1_session_session_time_remaining
session_time_elapsed_entity: sensor.f1_session_session_time_elapsed
overtake_mode_entity: binary_sensor.f1_session_overtake_mode
straight_mode_entity: sensor.f1_session_straight_mode
weather_entity: sensor.f1_track_weather
- show_fia_logo: true
min_display_time: 3
type: custom:f1-race-control-card
view_layout:
grid-area: card2
entity: sensor.f1_race_control
- type: custom:f1-pitstop-overview-card
view_layout:
grid-area: card3
drivers_entity: sensor.f1_driver_list
positions_entity: sensor.f1_driver_positions
tyres_entity: sensor.f1_current_tyres
pitstops_entity: sensor.f1_pitstops
title: Pit Stops & Tyres
show_header: true
show_table_header: true
show_tla: true
show_team_logo: false
show_status: true
show_tyre: true
show_pit_count: true
show_pit_time: true
show_pit_lane_time: true
show_pit_delta: true
- type: custom:f1-driver-lap-times-card
view_layout:
grid-area: card4
show:
mediaquery: "(min-width: 769px)"
drivers_entity: sensor.f1_driver_list
positions_entity: sensor.f1_driver_positions
title: Driver Lap Times
show_lap_history: true
show_lap_trend: true
show_best_lap: true
show_last_lap: false
show_status: false
show_tla: true
show_team_logo: true
show_table_header: true
show_header: true
show_position: true
lap_history_limit: 3
- type: custom:f1-driver-lap-times-card
view_layout:
grid-area: card4
show:
mediaquery: "(max-width: 768px)"
drivers_entity: sensor.f1_driver_list
positions_entity: sensor.f1_driver_positions
title: Driver Lap Times
show_lap_history: true
show_lap_trend: true
show_best_lap: true
show_last_lap: false
show_status: false
show_tla: true
show_team_logo: true
show_table_header: true
show_header: true
show_position: true
lap_history_limit: 1
- type: custom:f1-sensor-live-data-card
view_layout:
grid-area: card5
entity: sensor.f1_tyre_statistics
drivers_entity: sensor.f1_driver_list
title: Tyres Statistics
show_tyre_image: true
show_compound_name: false
show_best_times: true
show_stats: true
show_delta: true
show_team_logo: false
show_header: true
- type: custom:f1-track-limits-card
view_layout:
grid-area: card6
track_limits_entity: sensor.f1_track_limits
drivers_entity: sensor.f1_driver_list
positions_entity: sensor.f1_driver_positions
title: Track Limits
show_team_logo: true
show_table_header: false
show_all_drivers: false
Interesting that track status during quali goes from Red > Clear > Yellow while the session is suspended. Is that just how the data reports from F1?
Probably. The track status is constantly updated during a session which is from the start of Q1 till the end of Q3. If they clear the red flag, but itâs still a yellow, itâll probably do that. However I donât know exactly, as I havenât looked at the API
I dunno whyâŚ
But dd try to test the lights today on practice and qualifyâŚ
But it failed totallyâŚ
Is it because the new core updates etc? ?
It did work always for meâŚ
Update: after reinstall everything to the latest betaâs etc
I gotta it kind of workingâŚ
But itâs not 100% yetâŚ
Yay
The lights automation kinda worked for me, except for triggering a few to many times
@Stimo and anyone who is using or willing to use GitHub, Iâve created a discussion thread there to have a central place to put things that happened during this weekendâs Australian GP. This includes, but is not limited to:
- Any interesting findings with data
- Bugs report links (please do not put full bug reports here, but youâre welcome to link to them)
- Cool things youâve created, such as dashboards or automations
Findings, Bugs and Cool things during the Australian GP weekend (GitHub)
Wow, so much work has been done. Nice and thx Profile - Stimo - Home Assistant Community !
I love the info in the card âF1 Live Session Status cardâ and therefor like all information shown. If I do that the flag and elapsed time pushes out the track status and other mode information. Would it be possible to make this fit by adding this info in extra rows? Thx in advance.
Rewatching the session this morning, it does appear this is how F1 reports it. The track status is red until all cars are off the track, then switches to yellow until crews have cleared the issue, flags waivers on the track confirm this in the broadcast.
here is the same but with a reversed order so the newest message is at the top and the oldeest at the bottom:
type: custom:html-template-card
ignore_line_breaks: true
content: >
<style>
@keyframes f1-pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:0.3;transform:scale(0.6)}}
#rc-toggle{display:none;}
#rc-clear{display:none;}
#rc-extra-msgs{display:none;flex-direction:column;gap:5px;padding:0 12px 5px 12px;}
#rc-toggle:checked ~ #rc-card #rc-extra-msgs{display:flex;}
#rc-toggle:checked ~ #rc-card #rc-btn-show{display:none;}
#rc-toggle:checked ~ #rc-card #rc-btn-hide{display:inline-block;}
#rc-btn-hide{display:none;}
#rc-clear:checked ~ #rc-card #rc-messages{display:none;}
#rc-clear:checked ~ #rc-card #rc-cleared-msg{display:block;}
#rc-clear:checked ~ #rc-card #rc-btn-show{display:none;}
#rc-clear:checked ~ #rc-card #rc-btn-hide{display:none;}
#rc-clear:checked ~ #rc-card #rc-btn-clear{display:none;}
#rc-cleared-msg{display:none;}
</style>
{% set raw = states('sensor.f1_race_control') %}
{% set msgs = state_attr('sensor.f1_race_control', 'history') or [] %}
{% set session = states('sensor.f1_session_status') | lower %}
{% set session_name = states('sensor.f1_current_session') %}
{% set meeting_name = state_attr('sensor.f1_session_status', 'meeting_name') | default('') %}
{% set location = state_attr('sensor.f1_session_status', 'meeting_location') | default('') %}
{% set country = state_attr('sensor.f1_session_status', 'meeting_country') | default('') %}
{% set circuit = state_attr('sensor.f1_session_status', 'circuit_short_name') | default('') %}
{% set sorted_msgs = msgs | sort(attribute='utc') %}
{% set total = sorted_msgs | length %}
{% set limit = 10 %}
{% set show_session = session_name not in ['unknown', 'unavailable', 'none', ''] %}
{% if session == 'live' %}
{% set badge_color = '#00FF88' %}
{% set badge_bg = 'rgba(0,0,0,0.3)' %}
{% set badge_border = 'rgba(255,255,255,0.3)' %}
{% set badge_text = '#FFFFFF' %}
{% set badge_label = 'LIVE' %}
{% set dot_anim = 'animation:f1-pulse 1.4s ease-in-out infinite;' %}
{% set name_opacity = '1' %}
{% elif session == 'suspended' %}
{% set badge_color = '#FFD700' %}
{% set badge_bg = 'rgba(255,215,0,0.1)' %}
{% set badge_border = 'rgba(255,215,0,0.4)' %}
{% set badge_text = '#FFD700' %}
{% set badge_label = 'SUSPENDED' %}
{% set dot_anim = 'animation:f1-pulse 2s ease-in-out infinite;' %}
{% set name_opacity = '0.6' %}
{% elif session == 'break' %}
{% set badge_color = '#FF8000' %}
{% set badge_bg = 'rgba(255,128,0,0.1)' %}
{% set badge_border = 'rgba(255,128,0,0.4)' %}
{% set badge_text = '#FF8000' %}
{% set badge_label = 'BREAK' %}
{% set dot_anim = '' %}
{% set name_opacity = '0.6' %}
{% elif session == 'pre' %}
{% set badge_color = '#4488FF' %}
{% set badge_bg = 'rgba(68,136,255,0.1)' %}
{% set badge_border = 'rgba(68,136,255,0.4)' %}
{% set badge_text = '#4488FF' %}
{% set badge_label = 'PRE-SESSION' %}
{% set dot_anim = '' %}
{% set name_opacity = '0.6' %}
{% elif session in ['finished', 'finalised', 'ended'] %}
{% set badge_color = '#444455' %}
{% set badge_bg = 'rgba(0,0,0,0.2)' %}
{% set badge_border = 'rgba(255,255,255,0.1)' %}
{% set badge_text = '#606070' %}
{% set badge_label = session | upper %}
{% set dot_anim = '' %}
{% set name_opacity = '0.4' %}
{% else %}
{% set badge_color = '#444455' %}
{% set badge_bg = 'rgba(0,0,0,0.2)' %}
{% set badge_border = 'rgba(255,255,255,0.1)' %}
{% set badge_text = '#606070' %}
{% set badge_label = session | upper if session else 'OFFLINE' %}
{% set dot_anim = '' %}
{% set name_opacity = '0.4' %}
{% endif %}
<input type="checkbox" id="rc-toggle">
<input type="checkbox" id="rc-clear">
<div id="rc-card" style="background:#08080A;border-radius:8px;overflow:hidden;padding-bottom:16px;font-family:'F1Regular',sans-serif;">
<div style="background:#E8002D;display:flex;align-items:center;gap:16px;padding:12px 20px 12px 16px;margin-bottom:0;">
<div style="display:flex;flex-direction:column;align-items:center;justify-content:center;flex-shrink:0;width:52px;">
<div style="font-family:'F1Bold',sans-serif;font-size:48px;line-height:1;color:#fff;letter-spacing:-1px;">F<span style="color:#fff;">1</span></div>
</div>
<div style="flex:1;display:flex;flex-direction:column;gap:2px;">
<div style="display:flex;align-items:baseline;gap:10px;">
<div style="font-family:'F1Bold',sans-serif;font-size:22px;color:#ffffff;line-height:1;text-shadow:0 2px 4px rgba(0,0,0,0.3);">RACE CONTROL</div>
{% if show_session %}
<div style="font-family:'F1Bold',sans-serif;font-size:11px;letter-spacing:2px;color:rgba(255,255,255,0.6);text-transform:uppercase;white-space:nowrap;">{{ session_name | upper }}</div>
{% endif %}
</div>
{% if meeting_name %}
<div style="font-family:'F1Wide',sans-serif;font-size:12px;color:rgba(255,255,255,{{ name_opacity }});line-height:1.3;letter-spacing:0.5px;">{{ meeting_name }}</div>
{% endif %}
{% if location or country %}
<div style="font-family:'F1Regular',sans-serif;font-size:11px;color:rgba(255,255,255,0.65);line-height:1.2;letter-spacing:0.3px;">{{ circuit if circuit else '' }}{% if circuit and (location or country) %} ¡ {% endif %}{{ location if location else country }}</div>
{% endif %}
</div>
<div style="display:flex;align-items:center;gap:6px;background:{{ badge_bg }};border:1px solid {{ badge_border }};border-radius:2px;padding:5px 11px;flex-shrink:0;">
<div style="width:7px;height:7px;border-radius:50%;background:{{ badge_color }};flex-shrink:0;{{ dot_anim }}"></div>
<span style="font-family:'F1Bold',sans-serif;font-size:11px;letter-spacing:2px;color:{{ badge_text }};">{{ badge_label }}</span>
</div>
</div>
<div style="height:3px;background:linear-gradient(90deg,#E8002D,rgba(255,107,107,0.27),transparent);margin-bottom:14px;"></div>
<div style="display:flex;justify-content:space-between;align-items:center;padding:0 16px 10px;">
<div style="display:flex;align-items:center;gap:10px;">
<span style="font-family:'F1Regular',sans-serif;font-size:11px;letter-spacing:2px;text-transform:uppercase;color:#606070;">
{% if raw == 'unavailable' %}LAST SESSION ¡ {% endif %}{{ [total, limit] | min }} of {{ total }} message{% if total != 1 %}s{% endif %}
</span>
{% if total > limit %}
<label id="rc-btn-show" for="rc-toggle" style="font-family:'F1Bold',sans-serif;font-size:9px;letter-spacing:2px;text-transform:uppercase;color:#E8002D;background:rgba(232,0,45,0.08);border:1px solid rgba(232,0,45,0.3);border-radius:2px;padding:4px 10px;cursor:pointer;">SHOW ALL</label>
<label id="rc-btn-hide" for="rc-toggle" style="font-family:'F1Bold',sans-serif;font-size:9px;letter-spacing:2px;text-transform:uppercase;color:#E8002D;background:rgba(232,0,45,0.08);border:1px solid rgba(232,0,45,0.3);border-radius:2px;padding:4px 10px;cursor:pointer;">SHOW LATEST</label>
{% endif %}
{% if total > 0 %}
<label id="rc-btn-clear" for="rc-clear" style="font-family:'F1Bold',sans-serif;font-size:9px;letter-spacing:2px;text-transform:uppercase;color:#606070;background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.1);border-radius:2px;padding:4px 10px;cursor:pointer;">CLEAR</label>
{% endif %}
</div>
</div>
{% if raw == 'unknown' and total == 0 %}
<div style="margin:12px;background:rgba(232,0,45,0.08);border:1px solid rgba(232,0,45,0.3);border-radius:2px;padding:14px 18px;font-family:'F1Regular',sans-serif;font-size:13px;letter-spacing:1px;color:#FF6B6B;">
đ Awaiting race control transmissions
</div>
{% elif total == 0 %}
<div style="text-align:center;padding:48px 20px;font-family:'F1Regular',sans-serif;letter-spacing:3px;text-transform:uppercase;font-size:14px;color:#2A2A32;">
đ Awaiting race control transmissions
</div>
{% else %}
<div id="rc-cleared-msg" style="text-align:center;padding:48px 20px;font-family:'F1Regular',sans-serif;letter-spacing:3px;text-transform:uppercase;font-size:14px;color:#2A2A32;">
đ Board cleared
</div>
<div id="rc-messages">
{% macro render_msg(msg, idx) %}
{% set txt = msg.message | default('') %}
{% set ts = msg.utc | default('') %}
{% set category = msg.category | default('') %}
{% set flag = msg.flag | default('') | upper %}
{% set tu = txt | upper %}
{% if flag == 'RED' or 'RED FLAG' in tu %}
{% set bcolor = '#FF2222' %} {% set cat_label = 'Red Flag' %} {% set cat_color = '#FF4444' %} {% set bg = 'rgba(255,0,0,0.06)' %}
{% elif flag == 'YELLOW' or ('YELLOW' in tu and 'GREEN' not in tu) %}
{% set bcolor = '#FFD700' %} {% set cat_label = 'Yellow Flag' %} {% set cat_color = '#FFD700' %} {% set bg = 'rgba(255,215,0,0.04)' %}
{% elif flag == 'GREEN' or 'GREEN' in tu %}
{% set bcolor = '#00D2BE' %} {% set cat_label = 'Green Flag' %} {% set cat_color = '#00D2BE' %} {% set bg = '#15151A' %}
{% elif 'SAFETY CAR' in tu %}
{% set bcolor = '#FFD700' %} {% set cat_label = 'Safety Car' %} {% set cat_color = '#FFD700' %} {% set bg = '#15151A' %}
{% elif 'VIRTUAL SAFETY' in tu or 'VSC' in tu %}
{% set bcolor = '#FFD700' %} {% set cat_label = 'Virtual Safety Car' %} {% set cat_color = '#FFD700' %} {% set bg = '#15151A' %}
{% elif 'DRS' in tu %}
{% set bcolor = '#00D2BE' %} {% set cat_label = 'DRS' %} {% set cat_color = '#00D2BE' %} {% set bg = '#15151A' %}
{% elif 'PENALTY' in tu or 'DRIVE THROUGH' in tu or 'STOP AND GO' in tu %}
{% set bcolor = '#FF8000' %} {% set cat_label = 'Penalty' %} {% set cat_color = '#FF8000' %} {% set bg = '#15151A' %}
{% elif 'INVESTIGATION' in tu or 'STEWARD' in tu or 'NOTED' in tu %}
{% set bcolor = '#FF8000' %} {% set cat_label = 'Stewards' %} {% set cat_color = '#FF8000' %} {% set bg = '#15151A' %}
{% elif 'CHEQUERED' in tu or 'SESSION END' in tu or 'RACE END' in tu %}
{% set bcolor = '#0067FF' %} {% set cat_label = 'Session End' %} {% set cat_color = '#0067FF' %} {% set bg = '#15151A' %}
{% elif 'OVERTAKE' in tu or 'PIT' in tu or 'RESUME' in tu %}
{% set bcolor = '#0067FF' %} {% set cat_label = category if category else 'Info' %} {% set cat_color = '#4488FF' %} {% set bg = '#15151A' %}
{% else %}
{% set bcolor = '#2A2A32' %} {% set cat_label = category if category else 'Message' %} {% set cat_color = '#606070' %} {% set bg = '#15151A' %}
{% endif %}
{% if ts | length >= 19 %}
{% set time_display = ts[11:19] %}
{% elif ts | length > 0 %}
{% set time_display = ts %}
{% else %}
{% set time_display = '--:--:--' %}
{% endif %}
<div style="background:{{ bg }};border:1px solid #2A2A32;border-left:3px solid {{ bcolor }};border-radius:2px;padding:10px 14px;display:flex;gap:12px;align-items:flex-start;">
<div style="font-family:'F1Regular',sans-serif;font-weight:700;font-size:10px;color:#606070;min-width:24px;padding-top:2px;">#{{ '%02d' % idx }}</div>
<div style="font-family:'F1Regular',sans-serif;font-size:13px;color:#E8002D;min-width:64px;white-space:nowrap;padding-top:1px;font-variant-numeric:tabular-nums;">{{ time_display }}</div>
<div style="flex:1;">
<div style="font-family:'F1Bold',sans-serif;font-size:9px;letter-spacing:2px;text-transform:uppercase;margin-bottom:2px;color:{{ cat_color }};">{{ cat_label }}</div>
<div style="font-family:'F1Regular',sans-serif;font-size:13px;color:#FFFFFF;line-height:1.5;">{{ txt }}</div>
</div>
</div>
{% endmacro %}
<!-- Latest messages: newest first at top -->
<div style="display:flex;flex-direction:column;gap:5px;padding:0 12px 5px 12px;">
{% for msg in sorted_msgs[-limit:] | reverse %}
{{ render_msg(msg, total - loop.index0) }}
{% endfor %}
</div>
<!-- Older messages: revealed by SHOW ALL, below latest -->
{% if total > limit %}
<div id="rc-extra-msgs">
{% for msg in sorted_msgs[:(total - limit)] | reverse %}
{{ render_msg(msg, total - limit - loop.index0) }}
{% endfor %}
</div>
{% endif %}
</div>
{% endif %}
</div>
Câmon, some feedback - youve got some real time data to work with over the last quarter hour - how is it going?
Great first race!! love the work that you have done to the integration. Coffee has been purchased for your great work.
Just one observation on the Driver and Lap card. It currently only shows the lap sector times but not the gap times from each car in front and the leader. Would it be possible to add this to the card? I checked all the F1 sensors for that attribute but couldnât find it.
Here is the drive card as it appears now:
Here is the example from the f1-dash.com/dashboard:
On the tyre statistics, it looks like all the sensors went off line. or is it my set up? I searched for an updated sensor, but couldnât find any:
I also note that the line height on the Driver & Lap times card is slightly smaller than on the Tyre card, which puts the bottom out of alighment when the two cards are stacked side by side. could you adjust the Driver & Lap times card to be the same line heights so they align?
My last bit of feedback, I see on the TV (F1TV) they showed a remaining battery and over take mode. Would you be able to add that one to your F1 sensors in a nice matching card?
On that note, would you consider using my Race Control message board to make it in to your integration and match the other F1 integration cards?








