A web-based timing control system for bike races, training sessions, and competition result management.
The project is designed to run on a local server or on an Orange Pi single-board computer. It provides interfaces for managing participants, RFID cards, events, race attempts, final results, ratings, and basic administration.
Timing Control is a local web application for organizing race timing and result tracking.
The main goal of the project is to provide a simple and convenient tool for operators and administrators during racing events. The system can work inside a local network and, if needed, can be temporarily exposed to the internet using a tunneling service such as ngrok.
- Public results page
- Final results page
- Attempts history
- Ratings page
- Admin panel
- Participant management
- RFID card management
- Event management
- Active event support
- Operator mode
- SQLite database storage
- Excel-related functionality using
openpyxl - Serial port support using
pyserial - Support for running on Orange Pi with Armbian/Linux
- Python 3
- Flask
- SQLite
- pyserial
- openpyxl
- HTML / CSS / JavaScript
- Orange Pi / Armbian Linux
Approximate project structure:
Timing control/
├── bike_timing/
│ ├── timing_v1_1.db
│ ├── admin_password.txt
│ ├── flask_secret_key.txt
│ ├── schema.sql
│ ├── schema_v1_1.sql
│ ├── seed.sql
│ ├── seed_race_event.sql
│ ├── seed_race_event_v1_1.sql
│ └── db_templates/
│ ├── timing_empty_template.db
│ └── timing_schema.sql
│
├── timing_web/
│ ├── app.py
│ ├── controllers/
│ ├── services/
│ ├── repositories/
│ ├── templates/
│ └── static/
│
├── requirements.txt
├── setup_local.py
└── README.md
After starting the application, it is available at:
http://<server-ip-address>:8000
Main routes:
/ public main page
/public public page
/public/ratings ratings page
/public/ratings/attempts rating attempts page
/public/results results page
/public/results/final final results page
/public/results/attempts participants attempts page
/admin admin panel
/admin/login admin login page
/admin/db database management page
/cards RFID card management
/persons participant management
/events event management
/operator operator mode
/health application health check
Install Python dependencies before the first launch.
python -m pip install -r requirements.txtsudo apt update
sudo apt install -y python3 python3-pip python3-venv
python3 -m pip install -r requirements.txtUsing a virtual environment is recommended:
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtRun the local setup script:
python setup_local.pyThe script creates the following files:
bike_timing/admin_password.txt
bike_timing/flask_secret_key.txt
bike_timing/timing_v1_1.db
bike_timing/db_templates/timing_empty_template.db
Default local administrator password:
admin12345
Important: change the default administrator password before exposing the application to the internet.
The administrator password is stored in:
bike_timing/admin_password.txt
From the project root directory:
python timing_web/app.pyThe application should become available at:
http://127.0.0.1:8000
http://<computer-ip-address>:8000
Go to the project directory:
cd /root/timing_controlActivate the virtual environment, if it is used:
source .venv/bin/activateStart the application:
python3 timing_web/app.pyThe application should become available in the local network:
http://<orange-pi-ip-address>:8000
Example:
http://192.168.43.252:8000
These commands can be used to verify that the project is installed, starts correctly, and responds to HTTP requests.
cd /root/timing_controlls -la
ls -la bike_timing
ls -la timing_webThe project directory should contain:
requirements.txt
setup_local.py
bike_timing/
timing_web/
timing_web/app.py
python3 --versionpython3 -m pip show Flask
python3 -m pip show pyserial
python3 -m pip show openpyxlpython3 timing_web/app.pyExpected terminal output:
* Serving Flask app 'app'
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:8000
* Running on http://<ip-address>:8000
Open:
http://<orange-pi-ip-address>:8000
Example:
http://192.168.43.252:8000
On Orange Pi, run:
curl http://127.0.0.1:8000/healthExpected response:
{
"ok": true,
"service": "timing_web"
}If curl is not installed:
sudo apt install -y curlss -tulpn | grep 8000If the application is running, the command should show a Python process listening on port 8000.
From another computer, phone, or tablet connected to the same network, open:
http://<orange-pi-ip-address>:8000
Example:
http://192.168.43.252:8000
If the website does not open, check the current Orange Pi IP address:
hostname -IAlso check whether the application is running:
ps aux | grep app.pyTo temporarily expose the local application to the internet, ngrok can be used.
Start the Flask application first:
python3 timing_web/app.pyThen start ngrok:
ngrok http 8000ngrok will generate a public URL similar to:
https://xxxx-xxxx-xxxx.ngrok-free.app
The application will be available through this public URL while both Flask and ngrok are running.
Important: change the default administrator password before using ngrok.
Short version:
cd /root/timing_control
source .venv/bin/activate
python3 timing_web/app.pyHealth check:
curl http://127.0.0.1:8000/healthStart ngrok if internet access is required:
ngrok http 8000Admin panel URL:
http://<orange-pi-ip-address>:8000/admin
Example:
http://192.168.43.252:8000/admin
The administrator password is stored in:
bike_timing/admin_password.txt
Default local administrator password after initial setup:
admin12345
For security reasons, replace it with a stronger password before real usage.
Before exposing the application to the internet:
- change the default administrator password;
- do not publish secret files;
- do not commit the working database to a public repository;
- do not share the admin panel link with unauthorized users;
- use a strong administrator password.
Files that should not be published:
bike_timing/admin_password.txt
bike_timing/flask_secret_key.txt
bike_timing/timing_v1_1.db
.venv/
__pycache__/
.venv/
__pycache__/
*.pyc
bike_timing/admin_password.txt
bike_timing/flask_secret_key.txt
bike_timing/timing_v1_1.db
*.log
.DS_StoreCheck whether the application is running:
ps aux | grep app.pyCheck whether port 8000 is listening:
ss -tulpn | grep 8000Check the current Orange Pi IP address:
hostname -ICheck the administrator password file:
cat bike_timing/admin_password.txtStart the Flask application:
python3 timing_web/app.pyThen run:
curl http://127.0.0.1:8000/healthCheck which process is using the port:
sudo ss -tulpn | grep 8000Find the running application process:
ps aux | grep app.pyStop the process by PID:
kill <PID>The project is in working condition and is intended for local deployment on Orange Pi or a regular computer.
The main goal of the project is to provide a simple local timing control system with optional temporary internet access through ngrok.