Windows desktop app for ETI breaker-cycle testing. The UI is an Electron shell over a Flask + Socket.IO backend that drives two Festo motors, reads NI DAQ data, stores test metadata in SQLite, and writes per-cycle CSV files.
- Creates and manages test records.
- Stores per-test settings per circuit type.
- Runs single steps or full multi-cycle tests.
- Acquires force/contact data from NI DAQ during motor motion.
- Saves raw and analysed measurement files.
- Supports sensor zero-offset calibration and motor-rotation correction.
- Desktop launcher:
Start_App.bat - Electron wrapper:
electron/ - Backend server:
backend/app.py - UI templates:
templates/ - Frontend JS:
static/js/ - Hardware control:
hardware_interface/ - Database:
backend/app.db - Default measurement output:
Meritve/ - Default circuit settings:
default_settings/*.json
- Electron starts the Flask backend on
http://127.0.0.1:5050. - Flask serves the UI and exposes REST + Socket.IO endpoints.
hardware_interface/stepes_manager.pycoordinates steps/cycles.hardware_interface/motors.pytalks to two Festo drives over Modbus/TCP.hardware_interface/daq.pyreads the persisted NI taskCB_tester_NI_task.- Results are stored in SQLite and exported as CSV under the selected save path.
- Windows
- Python environment with packages from
requrements.txt - Node.js for Electron
- NI-DAQmx installed and persisted NI task named
CB_tester_NI_task - Reachable Festo drives at:
192.168.0.2192.168.0.4
Preferred:
Start_App.batManual:
cd electron
npm start- SQLite file:
backend/app.db - Main tables:
teststest_settingsapp_statuscalibration_data_zero_offsettorque_correction_coefficients
- Measurement files:
<saving_location>/<test_name>/<cycle_number>/*.csv<saving_location>/<test_name>/analysed_data.csv
Database note:
- Current schema initialization is in
backend/db.py. - Existing migration only adds
dmc_codeandcomments. - The production-safe motor fixes listed below do not require DB schema changes.
This is a code-based diagnosis, not proof of the physical root cause. The code strongly suggests that the app has weak detection and reporting of transient motor communication loss.
- The app connects both motors once at backend startup.
- After a disconnect, the app does not keep an active health monitor.
- On the next move or position read,
hardware_interface/motors.pytries:shutdown()connect()
- Only one reconnect attempt is made.
- After every completed or stopped test, motors are explicitly shut down, so the next operation must reconnect again.
- The underlying
festo-edconModbus layer stops its I/O thread on any I/O exception and closes the client. - The project code catches most motor exceptions and converts them to
False, so the real error is hidden. - The app usually notices the problem only on the next motor read/write, not when the link first drops.
- The step executor has a hard
7.0second watchdog for motor threads. If motion/recovery takes longer, the app stops motion and the failure can look like a disconnect. - The backend emits
motor_status_changed, but the active frontend socket manager does not subscribe to it, so operators do not get a clear motor-state event.
- Transient Modbus/TCP interruption, EMC noise, switch/cable issue, or drive reset.
- Drive becomes not operational or faults during motion, which the library treats as communication interruption.
- Lazy reconnect inside worker threads with no retry/backoff and no lock around reconnect/shutdown.
- Motor timeout in step execution shorter than worst-case recovery/reference time.
- Exceptions swallowed in
try_execute_operation(), which makes failures look intermittent and harder to diagnose.
- App startup connects motors:
backend/app.py - Motor wrapper and reconnect logic:
hardware_interface/motors.py - Step timeout and motor thread monitoring:
hardware_interface/stepes_manager.py - Modbus I/O thread shutdown on communication error:
venv/Lib/site-packages/edcon/edrive/com_modbus.pyvenv/Lib/site-packages/edcon/edrive/telegram_handler.py
- A disconnect during idle may not be visible until the next step starts.
- A disconnect during motion may end as:
- silent
Falsefrom motor wrapper - no data from step execution
- generic step/test failure in UI
- silent
- The current implementation is reactive, not robustly fault-aware.
These changes are safe from a database perspective because they do not require schema changes:
- Stop swallowing the original motor exception. Log the real exception and fault details.
- Add reconnect retries with backoff instead of a single reconnect attempt.
- Add a lock around motor
connect()/shutdown()/ reconnect flow. - Make the
7.0second step watchdog configurable and larger than worst-case motion + reconnect time. - Surface
motor_status_changedin the frontend so operators see motor health immediately. - Add explicit logging around:
- connect start/end
- reconnect attempt count
- fault code
- operation-enabled state
- timeout vs true disconnect
From the code, the problem is not the database. The main weakness is motor communication fault handling: the low-level library drops communication on I/O errors, and the app recovers only partially, with hidden exceptions and weak UI reporting. That is why the disconnect can appear random even when there was a real Modbus/drive interruption underneath.