Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions crates/client/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::time::Duration;
use std::{env, error::Error};

use axum::http::HeaderValue;
Expand All @@ -6,6 +7,7 @@ use futures::SinkExt;
use reqwest::{header, Url};
use serde_json::Value;

use tokio::time::timeout;
use tokio_stream::{Stream, StreamExt};
use tokio_tungstenite::tungstenite::client::IntoClientRequest;
use tokio_tungstenite::{tungstenite::http::Request, MaybeTlsStream, WebSocketStream};
Expand Down Expand Up @@ -39,7 +41,17 @@ pub async fn init() -> Result<WsStream, Box<dyn Error>> {

debug!(?req, "created request");

let (mut socket, _) = tokio_tungstenite::connect_async(req).await?;
let connect_result = timeout(
Duration::from_secs(10),
tokio_tungstenite::connect_async(req),
)
.await;

let (mut socket, _) = match connect_result {
Ok(Ok(res)) => res,
Ok(Err(e)) => return Err(Box::new(e)),
Err(_) => return Err("ws connect timed out".into()),
};

info!("connected");

Expand Down Expand Up @@ -113,7 +125,11 @@ async fn negotiate() -> Result<Negotiaion, Box<dyn Error>> {
],
)?;

let res = reqwest::get(url).await?;
let res = match timeout(Duration::from_secs(5), reqwest::get(url)).await {
Ok(Ok(r)) => r,
Ok(Err(e)) => return Err(Box::new(e)),
Err(_) => return Err("negotiation HTTP request timed out".into()),
};

// TODO refactor this
let headers = res.headers().clone();
Expand Down
31 changes: 25 additions & 6 deletions crates/client/src/manager.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use std::time::Duration;

use tokio::{sync::mpsc, time::sleep};
use tokio::{
sync::mpsc,
time::{sleep, timeout},
};
use tokio_stream::{wrappers::ReceiverStream, StreamExt};
use tracing::error;

Expand All @@ -23,12 +26,28 @@ pub fn manage() -> ReceiverStream<Message> {

let mut parsed_stream = parse_stream(stream).await;

while let Some(message) = parsed_stream.next().await {
if check_restart(&message) {
continue 'manage;
}
loop {
let res = timeout(Duration::from_secs(30), parsed_stream.next()).await;

let _ = tx.send(message).await;
match res {
Ok(Some(message)) => {
if check_restart(&message) {
continue 'manage;
}
let _ = tx.send(message).await;
}
Ok(None) => {
error!("stream ended unexpectedly, restarting client");
continue 'manage;
}
Err(err) => {
error!(
?err,
"timeout while waiting for next message, restarting client"
);
continue 'manage;
}
}
}
}
});
Expand Down
2 changes: 1 addition & 1 deletion dash/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "f1-dash",
"version": "3.1.1",
"version": "3.2.0",
"private": true,
"scripts": {
"build": "next build",
Expand Down
5 changes: 5 additions & 0 deletions dash/src/app/dashboard/settings/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ export default function SettingsPage() {
<p className="text-zinc-500">OLED Mode (Pure Black Background)</p>
</div>

<div className="flex gap-2">
<Toggle enabled={settings.useSafetyCarColors} setEnabled={(v) => settings.setUseSafetyCarColors(v)} />
<p className="text-zinc-500">Use Safety Car Colors</p>
</div>

<h2 className="my-4 text-2xl">Race Control</h2>

<div className="flex gap-2">
Expand Down
34 changes: 32 additions & 2 deletions dash/src/components/dashboard/Map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export default function Map() {
const [sectors, setSectors] = useState<MapSector[]>([]);
const [corners, setCorners] = useState<Corner[]>([]);
const [rotation, setRotation] = useState<number>(0);
const [finishLine, setFinishLine] = useState<null | { x: number; y: number; startAngle: number }>(null);

useEffect(() => {
(async () => {
Expand Down Expand Up @@ -91,12 +92,19 @@ export default function Map() {
const cWidthX = Math.max(...pointsX) - cMinX + SPACE * 2;
const cWidthY = Math.max(...pointsY) - cMinY + SPACE * 2;

const rotatedFinishLine = rotate(mapJson.x[0], mapJson.y[0], fixedRotation, centerX, centerY);

const dx = rotatedPoints[3].x - rotatedPoints[0].x;
const dy = rotatedPoints[3].y - rotatedPoints[0].y;
const startAngle = Math.atan2(dy, dx) * (180 / Math.PI);

setCenter([centerX, centerY]);
setBounds([cMinX, cMinY, cWidthX, cWidthY]);
setSectors(sectors);
setPoints(rotatedPoints);
setRotation(fixedRotation);
setCorners(cornerPositions);
setFinishLine({ x: rotatedFinishLine.x, y: rotatedFinishLine.y, startAngle });
})();
}, [circuitKey]);

Expand Down Expand Up @@ -161,6 +169,19 @@ export default function Map() {
);
})}

{finishLine && (
<rect
x={finishLine.x - 75}
y={finishLine.y}
width={240}
height={20}
fill="red"
stroke="red"
strokeWidth={70}
transform={`rotate(${finishLine.startAngle + 90}, ${finishLine.x + 25}, ${finishLine.y})`}
/>
)}

{showCornerNumbers &&
corners.map((corner) => (
<CornerNumber
Expand All @@ -174,32 +195,38 @@ export default function Map() {
{centerX && centerY && positions && drivers && (
<>
{positions["241"] && positions["241"].Z !== 0 && (
// Aston Martin
<SafetyCar
key="safety.car.241"
rotation={rotation}
centerX={centerX}
centerY={centerY}
pos={positions["241"]}
color="229971"
/>
)}

{positions["242"] && positions["242"].Z !== 0 && (
// Aston Martin
<SafetyCar
key="safety.car.242"
rotation={rotation}
centerX={centerX}
centerY={centerY}
pos={positions["242"]}
color="229971"
/>
)}

{positions["243"] && positions["243"].Z !== 0 && (
// Mercedes
<SafetyCar
key="safety.car.243"
rotation={rotation}
centerX={centerX}
centerY={centerY}
pos={positions["243"]}
color="B90F09"
/>
)}

Expand Down Expand Up @@ -307,9 +334,12 @@ type SafetyCarProps = {
rotation: number;
centerX: number;
centerY: number;
color: string;
};

const SafetyCar = ({ pos, rotation, centerX, centerY }: SafetyCarProps) => {
const SafetyCar = ({ pos, rotation, centerX, centerY, color }: SafetyCarProps) => {
const useSafetyCarColors = useSettingsStore((state) => state.useSafetyCarColors);

return (
<CarDot
name="Safety Car"
Expand All @@ -320,7 +350,7 @@ const SafetyCar = ({ pos, rotation, centerX, centerY }: SafetyCarProps) => {
favoriteDriver={false}
pit={false}
hidden={false}
color={undefined}
color={useSafetyCarColors ? color : "DDD"}
/>
);
};
6 changes: 6 additions & 0 deletions dash/src/stores/useSettingsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ type SettingsStore = {
oledMode: boolean;
setOledMode: (oledMode: boolean) => void;

useSafetyCarColors: boolean;
setUseSafetyCarColors: (useSafetyCarColors: boolean) => void;

favoriteDrivers: string[];
setFavoriteDrivers: (favoriteDrivers: string[]) => void;
removeFavoriteDriver: (driver: string) => void;
Expand Down Expand Up @@ -70,6 +73,9 @@ export const useSettingsStore = create<SettingsStore>()(
oledMode: false,
setOledMode: (oledMode: boolean) => set({ oledMode }),

useSafetyCarColors: true,
setUseSafetyCarColors: (useSafetyCarColors: boolean) => set({ useSafetyCarColors }),

favoriteDrivers: [],
setFavoriteDrivers: (favoriteDrivers: string[]) => set({ favoriteDrivers }),
removeFavoriteDriver: (driver: string) =>
Expand Down