Compare commits

...

1 Commits

Author SHA1 Message Date
Admin 5154464646 update(ttw): run send image in backgound 2025-12-11 14:47:34 +07:00
27 changed files with 95 additions and 48 deletions

Binary file not shown.

View File

@ -1,5 +1,7 @@
Run client: npm run dev or npm run build && npm run preview
==> Build client xong => coppy file asset và index vào folder static của server => thêm prefix static vào link của assets trong file index VD: /static/assets
==> Build client xong => coppy file asset và index vào folder static của server => thêm prefix static vào link của assets trong file index VD: /camera/static/assets
Run server uvicorn main:app --reload
nohup uvicorn main:app --host 172.16.6.38 --port 8080 > log.log 2>&1 &

View File

@ -6,45 +6,76 @@ from fastapi import UploadFile
URL_API = "https://ms.prology.net/api/v1"
def send_image(id, file: UploadFile, student_name: str, status: str):
# def send_image(id, file: UploadFile, student_name: str, status: str):
# id = str(id)
# # Tạo folder theo ngày
# today = datetime.datetime.now().strftime("%Y_%m_%d")
# folder_path = f"./images/{today}"
# if not os.path.exists(folder_path):
# os.makedirs(folder_path)
# # Tạo file name chuẩn
# file_name = (
# f"{student_name}_"
# f"{status}_at_{datetime.datetime.now().strftime('%Y_%m_%d_%H_%M_%S')}.png"
# )
# file_path = os.path.join(folder_path, file_name)
# # Lưu file UploadFile xuống
# with open(file_path, "wb") as f:
# f.write(file.file.read())
# # Mở lại file để gửi API
# with open(file_path, "rb") as image_file:
# files = {"image": image_file}
# data = {"id": id, "file_name": file_name}
# try:
# response = requests.post(
# URL_API + "/admin/tracking/send-image",
# data=data,
# files=files
# )
# response.raise_for_status()
# res = response.json()
# except Exception as e:
# return {"status": False, "message": str(e)}
# return res
def send_image(id, image_bytes, student_name: str, status: str):
id = str(id)
# Tạo folder theo ngày
today = datetime.datetime.now().strftime("%Y_%m_%d")
folder_path = f"./images/{today}"
os.makedirs(folder_path, exist_ok=True)
if not os.path.exists(folder_path):
os.makedirs(folder_path)
# Tạo file name chuẩn
file_name = (
f"{student_name}_"
f"{status}_at_{datetime.datetime.now().strftime('%Y_%m_%d_%H_%M_%S')}.png"
)
safe_student = "".join(c for c in student_name if c.isalnum() or c in ("-", "_"))
safe_status = "".join(c for c in status if c.isalnum() or c in ("-", "_"))
timestamp = datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
file_name = f"{safe_student}_{safe_status}_at_{timestamp}.png"
file_path = os.path.join(folder_path, file_name)
# Lưu file UploadFile xuống
# Lưu xuống
with open(file_path, "wb") as f:
f.write(file.file.read())
# Mở lại file để gửi API
with open(file_path, "rb") as image_file:
files = {"image": image_file}
data = {"id": id, "file_name": file_name}
f.write(image_bytes)
# Gửi API
try:
with open(file_path, "rb") as image_file:
response = requests.post(
URL_API + "/admin/tracking/send-image",
data=data,
files=files
data={"id": id, "file_name": file_name},
files={"image": image_file}
)
response.raise_for_status()
res = response.json()
except Exception as e:
return {"status": False, "message": str(e)}
return res
print("Send image failed:", e)

View File

@ -1,2 +1,3 @@
VITE_API_BASE_URL = "/"
VITE_API_BASE_URL = "/camera"
# VITE_API_BASE_URL = "http://127.0.0.1:8000"
VITE_API_BASE_MS = "https://ms.prology.net"

View File

@ -9,7 +9,7 @@ class MsApi {
Authorization:
"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL21zLnByb2xvZ3kubmV0L2FwaS92MS9hZG1pbi9sb2dpbiIsImlhdCI6MTc1Njg2MDQ1OSwiZXhwIjoxNzg4Mzk2NDU5LCJuYmYiOjE3NTY4NjA0NTksImp0aSI6IkRrb0NLbHBKV1pkNnZCN0QiLCJzdWIiOiIxNSIsInBydiI6ImQyZmYyOTMzOWE4YTNlODJjMzU4MmE1YThlNzM5ZGYxNzg5YmIxMmYifQ.DoHqHeAGGxpvzlNQ9dAZjZf2Yl573XCgNBT8ZiSx5N4",
},
baseURL: "https://ms.prology.net/api/v1/admin",
baseURL: import.meta.env.VITE_API_BASE_MS + "/api/v1/admin",
method: "GET",
url: "timekeeping",
params: {

View File

@ -114,10 +114,13 @@ export default function TabFeatures() {
} catch (error) {
const data = error as AxiosError;
toast.error(
const message =
(data.response?.data as any)?.message ||
"Error In Checking: " + JSON.stringify(data)
);
"Error In Checking: " + JSON.stringify(data);
if ((message as string).includes("No face detected")) return;
toast.error(message);
} finally {
setLoading(false);
}
@ -135,7 +138,7 @@ export default function TabFeatures() {
// ← cách đúng nhất để detect phím cách
e.preventDefault(); // nếu không muốn scroll
if (!loading) return;
if (loading) return;
captureAndCheck();
}

View File

@ -17,7 +17,7 @@ import TabFeatures from "./components/tab-features";
export default function Main() {
const [isSidebarOpen, setIsSidebarOpen] = useState(true);
const [isLeftSidebarOpen, setIsLeftSidebarOpen] = useState(true);
const [isLeftSidebarOpen, setIsLeftSidebarOpen] = useState(false);
// const { currentUser, setCurrentUser } = useUserStore();
const { setCanvasRef, setVideoRef } = useAppStore();

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

View File

@ -1,4 +1,4 @@
from fastapi import FastAPI, UploadFile, File, Form, Depends, HTTPException
from fastapi import FastAPI, UploadFile, File, Form, Depends, HTTPException, BackgroundTasks
from fastapi.responses import JSONResponse
from sqlalchemy.orm import Session
import face_recognition
@ -191,7 +191,7 @@ async def register_student(
@app.post("/checkin")
async def checkin(file: UploadFile = File(...), camera_id: str = Form("cam1"), db: Session = Depends(get_db)):
async def checkin(background_tasks: BackgroundTasks, file: UploadFile = File(...), camera_id: str = Form("cam1"), db: Session = Depends(get_db)):
image_data = await file.read()
path = os.path.join(UPLOAD_DIR, "checkin.jpg")
with open(path, "wb") as f:
@ -229,7 +229,7 @@ async def checkin(file: UploadFile = File(...), camera_id: str = Form("cam1"), d
"""),
{
"student_id": encoding.id,
"time_threshold": now - datetime.timedelta(minutes=5)
"time_threshold": now - datetime.timedelta(minutes=0.5)
}
).fetchone()
@ -258,15 +258,14 @@ async def checkin(file: UploadFile = File(...), camera_id: str = Form("cam1"), d
# reset pointer
file.file.seek(0)
send_image_res = send_image(
id=id_log,
file=file,
student_name=encoding.name,
status=status
background_tasks.add_task(
send_image,
id_log,
image_data, # truyền bytes, không phải UploadFile
encoding.name,
status
)
print(id_log, send_image_res)
# Insert new checkin
db.execute(
text("""

View File

@ -8,7 +8,7 @@
<script
type="module"
crossorigin
src="/camera/static/assets/index-NzXShqcn.js"
src="/camera/static/assets/index-Cs3L7CRl.js"
></script>
<link
rel="stylesheet"

11
TrackingToolWeb/ultils.py Normal file
View File

@ -0,0 +1,11 @@
from api import send_image
def background_send_image(id_log, file_path, student_name, status):
with open(file_path, "rb") as f:
send_image(
id=id_log,
file=f,
student_name=student_name,
status=status
)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 KiB

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 KiB

After

Width:  |  Height:  |  Size: 223 KiB