diff --git a/__pycache__/web_server.cpython-313.pyc b/__pycache__/web_server.cpython-313.pyc new file mode 100644 index 0000000..c5a1b67 Binary files /dev/null and b/__pycache__/web_server.cpython-313.pyc differ diff --git a/logs/access.log b/logs/access.log new file mode 100644 index 0000000..f611b17 --- /dev/null +++ b/logs/access.log @@ -0,0 +1,17 @@ +127.0.0.1 - - [26/May/2025:20:25:21 +0200] "GET / HTTP/1.1" 200 12917 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0" +127.0.0.1 - - [26/May/2025:20:25:22 +0200] "GET /cameras HTTP/1.1" 200 192 "http://localhost:5000/" "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0" +127.0.0.1 - - [26/May/2025:20:25:22 +0200] "GET /favicon.ico HTTP/1.1" 404 207 "http://localhost:5000/" "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0" +127.0.0.1 - - [26/May/2025:20:25:27 +0200] "GET /cameras HTTP/1.1" 200 192 "http://localhost:5000/" "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0" +127.0.0.1 - - [26/May/2025:20:25:32 +0200] "GET /cameras HTTP/1.1" 200 192 "http://localhost:5000/" "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0" +127.0.0.1 - - [26/May/2025:20:25:33 +0200] "GET /add_camera/0 HTTP/1.1" 200 17 "http://localhost:5000/" "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0" +127.0.0.1 - - [26/May/2025:20:25:37 +0200] "GET /cameras HTTP/1.1" 200 3 "http://localhost:5000/" "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0" +127.0.0.1 - - [26/May/2025:20:25:40 +0200] "GET /cameras HTTP/1.1" 200 3 "http://localhost:5000/" "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0" +127.0.0.1 - - [26/May/2025:20:25:42 +0200] "GET /cameras HTTP/1.1" 200 3 "http://localhost:5000/" "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0" +127.0.0.1 - - [26/May/2025:20:25:44 +0200] "GET /video_feed/0 HTTP/1.1" 200 8815858 "http://localhost:5000/" "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0" +127.0.0.1 - - [26/May/2025:20:28:42 +0200] "GET / HTTP/1.1" 200 10364 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0" +127.0.0.1 - - [26/May/2025:20:28:42 +0200] "GET /check_model HTTP/1.1" 404 207 "http://localhost:5000/" "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0" +127.0.0.1 - - [26/May/2025:20:28:44 +0200] "GET /scan_cameras HTTP/1.1" 404 207 "http://localhost:5000/" "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0" +127.0.0.1 - - [26/May/2025:20:28:46 +0200] "GET /scan_cameras HTTP/1.1" 404 207 "http://localhost:5000/" "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0" +127.0.0.1 - - [26/May/2025:20:28:46 +0200] "GET /scan_cameras HTTP/1.1" 404 207 "http://localhost:5000/" "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0" +127.0.0.1 - - [26/May/2025:20:28:46 +0200] "GET /scan_cameras HTTP/1.1" 404 207 "http://localhost:5000/" "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0" +127.0.0.1 - - [26/May/2025:20:28:50 +0200] "GET /scan_cameras HTTP/1.1" 404 207 "http://localhost:5000/" "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0" diff --git a/logs/error.log b/logs/error.log new file mode 100644 index 0000000..9c000d1 --- /dev/null +++ b/logs/error.log @@ -0,0 +1,88 @@ +[2025-05-26 20:24:22 +0200] [824587] [INFO] Starting gunicorn 23.0.0 +[2025-05-26 20:24:22 +0200] [824587] [INFO] Listening at: http://0.0.0.0:5000 (824587) +[2025-05-26 20:24:22 +0200] [824587] [INFO] Using worker: gthread +[2025-05-26 20:24:22 +0200] [825529] [INFO] Booting worker with pid: 825529 +[2025-05-26 20:24:22 +0200] [825544] [INFO] Booting worker with pid: 825544 +[2025-05-26 20:24:22 +0200] [825556] [INFO] Booting worker with pid: 825556 +[2025-05-26 20:24:22 +0200] [825571] [INFO] Booting worker with pid: 825571 +[2025-05-26 20:24:23 +0200] [825584] [INFO] Booting worker with pid: 825584 +[2025-05-26 20:24:23 +0200] [825600] [INFO] Booting worker with pid: 825600 +[2025-05-26 20:24:23 +0200] [825601] [INFO] Booting worker with pid: 825601 +[2025-05-26 20:24:23 +0200] [825602] [INFO] Booting worker with pid: 825602 +[2025-05-26 20:24:23 +0200] [825639] [INFO] Booting worker with pid: 825639 +[2025-05-26 20:24:23 +0200] [825651] [INFO] Booting worker with pid: 825651 +[2025-05-26 20:24:23 +0200] [825666] [INFO] Booting worker with pid: 825666 +Found YOLO model in directory: mucapy/models +[2025-05-26 20:24:23 +0200] [825682] [INFO] Booting worker with pid: 825682 +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +[ WARN:0@58.649] global cap_v4l.cpp:913 open VIDEOIO(V4L2:/dev/video1): can't open camera by index +[ERROR:0@58.649] global obsensor_uvc_stream_channel.cpp:158 getStreamChannelGroup Camera index out of range +[ WARN:0@64.731] global cap_v4l.cpp:913 open VIDEOIO(V4L2:/dev/video1): can't open camera by index +[ERROR:0@64.732] global obsensor_uvc_stream_channel.cpp:158 getStreamChannelGroup Camera index out of range +[ WARN:0@69.536] global cap_v4l.cpp:913 open VIDEOIO(V4L2:/dev/video1): can't open camera by index +[ERROR:0@69.537] global obsensor_uvc_stream_channel.cpp:158 getStreamChannelGroup Camera index out of range +[ WARN:0@74.431] global cap_v4l.cpp:913 open VIDEOIO(V4L2:/dev/video0): can't open camera by index +[ERROR:0@74.431] global obsensor_uvc_stream_channel.cpp:158 getStreamChannelGroup Camera index out of range +[ WARN:0@74.431] global cap_v4l.cpp:913 open VIDEOIO(V4L2:/dev/video1): can't open camera by index +[ERROR:0@74.431] global obsensor_uvc_stream_channel.cpp:158 getStreamChannelGroup Camera index out of range +[ WARN:0@76.868] global cap_v4l.cpp:913 open VIDEOIO(V4L2:/dev/video0): can't open camera by index +[ERROR:0@76.868] global obsensor_uvc_stream_channel.cpp:158 getStreamChannelGroup Camera index out of range +[ WARN:0@76.868] global cap_v4l.cpp:913 open VIDEOIO(V4L2:/dev/video1): can't open camera by index +[ERROR:0@76.868] global obsensor_uvc_stream_channel.cpp:158 getStreamChannelGroup Camera index out of range +[ WARN:0@79.438] global cap_v4l.cpp:913 open VIDEOIO(V4L2:/dev/video0): can't open camera by index +[ERROR:0@79.438] global obsensor_uvc_stream_channel.cpp:158 getStreamChannelGroup Camera index out of range +[ WARN:0@79.438] global cap_v4l.cpp:913 open VIDEOIO(V4L2:/dev/video1): can't open camera by index +[ERROR:0@79.438] global obsensor_uvc_stream_channel.cpp:158 getStreamChannelGroup Camera index out of range +[2025-05-26 20:25:47 +0200] [824587] [INFO] Handling signal: int +[2025-05-26 20:25:47 +0200] [825556] [INFO] Worker exiting (pid: 825556) +[2025-05-26 20:25:47 +0200] [825600] [INFO] Worker exiting (pid: 825600) +[2025-05-26 20:25:47 +0200] [825602] [INFO] Worker exiting (pid: 825602) +[2025-05-26 20:25:47 +0200] [825584] [INFO] Worker exiting (pid: 825584) +[2025-05-26 20:25:47 +0200] [825639] [INFO] Worker exiting (pid: 825639) +[2025-05-26 20:25:47 +0200] [825544] [INFO] Worker exiting (pid: 825544) +[2025-05-26 20:25:47 +0200] [825666] [INFO] Worker exiting (pid: 825666) +[2025-05-26 20:25:47 +0200] [825571] [INFO] Worker exiting (pid: 825571) +[2025-05-26 20:25:47 +0200] [825651] [INFO] Worker exiting (pid: 825651) +[2025-05-26 20:25:47 +0200] [825682] [INFO] Worker exiting (pid: 825682) +[2025-05-26 20:25:47 +0200] [825529] [INFO] Worker exiting (pid: 825529) +[2025-05-26 20:25:47 +0200] [825601] [INFO] Worker exiting (pid: 825601) +terminate called without an active exception +[2025-05-26 20:25:49 +0200] [824587] [ERROR] Worker (pid:825651) was sent code 134! +[2025-05-26 20:25:49 +0200] [824587] [INFO] Shutting down: Master +[2025-05-26 20:28:26 +0200] [833260] [INFO] Starting gunicorn 23.0.0 +[2025-05-26 20:28:26 +0200] [833260] [INFO] Listening at: http://0.0.0.0:5000 (833260) +[2025-05-26 20:28:26 +0200] [833260] [INFO] Using worker: gthread +[2025-05-26 20:28:26 +0200] [833415] [INFO] Booting worker with pid: 833415 +[2025-05-26 20:28:26 +0200] [833428] [INFO] Booting worker with pid: 833428 +[2025-05-26 20:28:26 +0200] [833448] [INFO] Booting worker with pid: 833448 +[2025-05-26 20:28:26 +0200] [833464] [INFO] Booting worker with pid: 833464 +[2025-05-26 20:28:26 +0200] [833481] [INFO] Booting worker with pid: 833481 +[2025-05-26 20:28:26 +0200] [833493] [INFO] Booting worker with pid: 833493 +[2025-05-26 20:28:26 +0200] [833508] [INFO] Booting worker with pid: 833508 +[2025-05-26 20:28:26 +0200] [833509] [INFO] Booting worker with pid: 833509 +Found YOLO model in directory: mucapy/models +[2025-05-26 20:28:26 +0200] [833537] [INFO] Booting worker with pid: 833537 +[2025-05-26 20:28:27 +0200] [833556] [INFO] Booting worker with pid: 833556 +Found YOLO model in directory: mucapy/models +[2025-05-26 20:28:27 +0200] [833570] [INFO] Booting worker with pid: 833570 +[2025-05-26 20:28:27 +0200] [833585] [INFO] Booting worker with pid: 833585 +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models +Found YOLO model in directory: mucapy/models diff --git a/requirements.txt b/requirements.txt index 24c3e2a..b2ac9ff 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,14 @@ -opencv-python>=4.5.0 -opencv-contrib-python>=4.5.0 -numpy>=1.19.0 -PyQt5>=5.15.0 \ No newline at end of file +# Web framework and extensions +Flask>=3.0.0 +Flask-Cors>=4.0.0 +Werkzeug>=3.0.0 +gunicorn>=21.2.0 + +# Core dependencies +opencv-python-headless>=4.8.0 + +# Flask dependencies +click>=8.1.7 +itsdangerous>=2.1.2 +Jinja2>=3.1.2 +MarkupSafe>=2.1.3 \ No newline at end of file diff --git a/run_server.sh b/run_server.sh new file mode 100755 index 0000000..aed450e --- /dev/null +++ b/run_server.sh @@ -0,0 +1,235 @@ +#!/bin/bash + +# Exit on error +set -e + +# Function to print error messages +error() { + echo -e "\e[31mERROR:\e[0m $1" >&2 + exit 1 +} + +# Function to print success messages +success() { + echo -e "\e[32mSUCCESS:\e[0m $1" +} + +# Function to print info messages +info() { + echo -e "\e[34mINFO:\e[0m $1" +} + +# Function to check if a command exists +check_command() { + if ! command -v "$1" &> /dev/null; then + error "Required command '$1' not found. Please install it first." + fi +} + +# Function to compare version numbers +version_compare() { + if [[ "$1" == "$2" ]]; then + echo 0 + return + fi + local IFS=. + local i ver1=($1) ver2=($2) + # Fill empty positions in ver1 with zeros + for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)); do + ver1[i]=0 + done + for ((i=0; i<${#ver1[@]}; i++)); do + # Fill empty positions in ver2 with zeros + if [[ -z ${ver2[i]} ]]; then + ver2[i]=0 + fi + if ((10#${ver1[i]} > 10#${ver2[i]})); then + echo 1 + return + fi + if ((10#${ver1[i]} < 10#${ver2[i]})); then + echo -1 + return + fi + done + echo 0 +} + +# Check for required system commands +check_command python3 +check_command pip3 + +# Check Python version +PYTHON_VERSION=$(python3 -c 'import sys; print(".".join(map(str, sys.version_info[:2])))') +MIN_VERSION="3.8" +if [ $(version_compare "$PYTHON_VERSION" "$MIN_VERSION") -lt 0 ]; then + error "Python version must be $MIN_VERSION or higher (found $PYTHON_VERSION)" +fi +success "Python version check passed (found $PYTHON_VERSION)" + +# Function to install packages on Fedora +install_fedora_deps() { + info "Installing Fedora dependencies..." + # Check which packages need to be installed + local packages=() + local check_packages=( + "python3-devel" + "gcc" + "python3-pip" + "python3-setuptools" + "python3-numpy" + "python3-opencv" + "python3-flask" + "python3-gunicorn" + "bc" + "lsof" + ) + + for pkg in "${check_packages[@]}"; do + if ! rpm -q "$pkg" &>/dev/null; then + packages+=("$pkg") + fi + done + + # Only run dnf if there are packages to install + if [ ${#packages[@]} -gt 0 ]; then + info "Installing missing packages: ${packages[*]}" + sudo dnf install -y "${packages[@]}" || error "Failed to install required packages" + else + info "All required system packages are already installed" + fi +} + +# Function to install packages on Ubuntu/Debian +install_ubuntu_deps() { + info "Installing Ubuntu/Debian dependencies..." + sudo apt-get update || error "Failed to update package lists" + sudo apt-get install -y \ + python3-dev \ + python3-pip \ + python3-venv \ + python3-numpy \ + python3-opencv \ + python3-flask \ + python3-gunicorn \ + bc \ + lsof \ + || error "Failed to install required packages" +} + +# Check and install system dependencies based on distribution +install_system_deps() { + if [ -f /etc/os-release ]; then + . /etc/os-release + case $ID in + fedora) + install_fedora_deps + ;; + ubuntu|debian) + install_ubuntu_deps + ;; + *) + info "Unknown distribution. Please ensure you have the following packages installed:" + echo "- Python development package (python3-devel/python3-dev)" + echo "- GCC compiler" + echo "- Python pip" + echo "- Python venv" + echo "- Python numpy" + echo "- Python OpenCV" + echo "- Python Flask" + echo "- Python Gunicorn" + echo "- bc" + echo "- lsof" + ;; + esac + fi +} + +# Install system dependencies +install_system_deps + +# Create and activate virtual environment +if [ ! -d "venv" ]; then + info "Creating virtual environment..." + # Create venv with system packages to use system numpy and opencv + python3 -m venv venv --system-site-packages || error "Failed to create virtual environment" + success "Virtual environment created successfully" +fi + +# Ensure virtual environment is activated +if [ -z "$VIRTUAL_ENV" ]; then + info "Activating virtual environment..." + source venv/bin/activate || error "Failed to activate virtual environment" +fi + +# Upgrade pip to latest version +info "Upgrading pip..." +python3 -m pip install --upgrade pip setuptools wheel || error "Failed to upgrade pip and setuptools" + +# Create or update requirements.txt with compatible package versions +if [ ! -f "requirements.txt" ]; then + info "Creating requirements.txt..." + cat > requirements.txt << EOF +# Web framework and extensions +Flask>=3.0.0 +Flask-Cors>=4.0.0 +Werkzeug>=3.0.0 +gunicorn>=21.2.0 + +# Core dependencies +opencv-python-headless>=4.8.0 + +# Flask dependencies +click>=8.1.7 +itsdangerous>=2.1.2 +Jinja2>=3.1.2 +MarkupSafe>=2.1.3 +EOF + success "Created requirements.txt" +fi + +# Install requirements with better error handling +info "Installing/updating requirements..." +# First ensure pip is up to date +pip install --upgrade pip + +# Install packages with specific options for better compatibility +PYTHONWARNINGS="ignore" pip install \ + --no-cache-dir \ + --prefer-binary \ + --only-binary :all: \ + -r requirements.txt || error "Failed to install requirements" + +success "Requirements installed successfully" + +# Create necessary directories +info "Creating required directories..." +mkdir -p logs || error "Failed to create logs directory" +success "Created required directories" + +# Function to check if port is available +check_port() { + if lsof -Pi :5000 -sTCP:LISTEN -t >/dev/null ; then + error "Port 5000 is already in use. Please stop the other process first." + fi +} + +# Check if port is available +check_port + +# Start Gunicorn with modern settings +info "Starting server with Gunicorn..." +exec gunicorn web_server:app \ + --bind 0.0.0.0:5000 \ + --workers $(nproc) \ + --worker-class gthread \ + --threads 2 \ + --timeout 120 \ + --access-logfile logs/access.log \ + --error-logfile logs/error.log \ + --capture-output \ + --log-level info \ + --reload \ + --max-requests 1000 \ + --max-requests-jitter 50 \ + || error "Failed to start Gunicorn server" \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..447938f --- /dev/null +++ b/templates/index.html @@ -0,0 +1,321 @@ + + +
+ + +