Skip to content

Commit

Permalink
contols
Browse files Browse the repository at this point in the history
  • Loading branch information
jwmke committed Mar 30, 2024
1 parent 46e4e6f commit 36180b8
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 15 deletions.
29 changes: 19 additions & 10 deletions src/api/v1/api.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
from typing import Union
import json
from fastapi import FastAPI, Request, WebSocket, WebSocketDisconnect
from websockets.exceptions import ConnectionClosed
from fastapi.templating import Jinja2Templates
from fastapi.middleware.cors import CORSMiddleware
import asyncio
import cv2

app = FastAPI()
camera = cv2.VideoCapture(1, cv2.CAP_DSHOW)
templates = Jinja2Templates(directory="templates")

origins = [
"http://localhost:3000",
]

@app.get("/")
def read_root():
return {"Hello": "World"}


@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}

app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"], # Allow all HTTP methods
allow_headers=["*"], # Allow all headers
)

# https://stackoverflow.com/a/70626324
@app.websocket("/ws")
Expand All @@ -32,6 +35,12 @@ async def get_stream(websocket: WebSocket):
else:
ret, buffer = cv2.imencode(".jpg", frame)
await websocket.send_bytes(buffer.tobytes())
await asyncio.sleep(0.01)
await asyncio.sleep(0.03)
except (WebSocketDisconnect, ConnectionClosed):
print("Client disconnected")

@app.post("/command")
async def command(request: Request):
data = await request.json()
data_dict = json.loads(data)
return {"status": "success"}
116 changes: 111 additions & 5 deletions src/ui/v1/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
"use client"
import { useRef, useEffect, useInsertionEffect } from "react";
import { useRef, useEffect, useInsertionEffect, useState } from "react";

export default function Home() {
const ws = new WebSocket('ws://localhost:8000/ws');
const canvasRef = useRef<HTMLCanvasElement>(null);

const [left, setLeft] = useState(0);
const [up, setUp] = useState(0);
const [right, setRight] = useState(0);
const [down, setDown] = useState(0);

useInsertionEffect(() => {

ws.onmessage = (event) => {
if (event.data instanceof Blob) {
const reader = new FileReader();
Expand All @@ -27,7 +31,6 @@ export default function Home() {
}
};

// Clean up WebSocket connection on component unmount
return () => {
ws.close();
};
Expand All @@ -37,11 +40,114 @@ export default function Home() {
const canvas = canvasRef.current;
const context = canvas?.getContext('2d');
}, []);


useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
switch (event.key) {
case "ArrowUp":
setUp(1);
break;
case "ArrowDown":
setDown(1);
break;
case "ArrowLeft":
setLeft(1);
break;
case "ArrowRight":
setRight(1);
break;
default:
break;
}
};

document.addEventListener("keydown", handleKeyDown);

return () => {
document.removeEventListener("keydown", handleKeyDown);
};
}, []);

useEffect(() => {
const handleKeyUp = (event: KeyboardEvent) => {
switch (event.key) {
case "ArrowUp":
setUp(0);
break;
case "ArrowDown":
setDown(0);
break;
case "ArrowLeft":
setLeft(0);
break;
case "ArrowRight":
setRight(0);
break;
default:
break;
}
}

document.addEventListener("keyup", handleKeyUp);

return () => {
document.removeEventListener("keyup", handleKeyUp);
}
}, [])

useEffect(() => {
if (left === 1 || up === 1 || right === 1 || down === 1) {
fetch('http://localhost:8000/command', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
left,
up,
right,
down
}),
});
}
}, [down, left, right, up])

return (
<main className="min-h-screen w-full">
<div className="flex flex-col items-center justify-center min-h-screen max-h-screen overflow-hidden w-full">
<canvas ref={canvasRef} className="h-3/5 w-3/5" />
<div className="grid grid-cols-6 w-full">
<div className="col-span-4">
<canvas ref={canvasRef} className="w-full" />
</div>
<div className="col-span-2 bg-gradient-to-br from-red to-yellow">
<div className="flex flex-col items-center justify-center h-full">
<button
className="arrow-button"
onClick={() => setDirection("up")}
>
Up
</button>
<button
className="arrow-button"
onClick={() => setDirection("down")}
>
Down
</button>
<button
className="arrow-button"
onClick={() => setDirection("left")}
>
Left
</button>
<button
className="arrow-button"
onClick={() => setDirection("right")}
>
Right
</button>
</div>
</div>
</div>
</div>
</main>
);
Expand Down
10 changes: 10 additions & 0 deletions src/ui/v1/tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ const config: Config = {
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
},
},
colors: {
red: "#ee6352",
green: "#59cd90",
blue: "#3fa7d6",
yellow: "#fac05e",
purple: "#b678e0",
black: "#1e1e1e",
white: "#f9f9f9",
orange: "#f79d84"
}
},
plugins: [],
};
Expand Down

0 comments on commit 36180b8

Please sign in to comment.