From 7bc8138f243b46988cfa2e801b407b0b1b638809 Mon Sep 17 00:00:00 2001 From: Alireza Vaezi Date: Mon, 28 Jul 2025 17:33:49 -0400 Subject: [PATCH] Add comprehensive test suite for USDA Vision Camera System - Implemented main test script to verify system components and functionality. - Added individual test scripts for camera exposure settings, API changes, camera recovery, maximum FPS, MQTT events, logging, and timezone functionality. - Created service file for system management and automatic startup. - Included detailed logging and error handling in test scripts for better diagnostics. - Ensured compatibility with existing camera SDK and API endpoints. --- .gitignore | 4 +- .vscode/settings.json | 2 +- README.md | 46 +++++- camera_sdk/README.md | 66 +++++++++ {python demo => camera_sdk}/mvsdk.py | 0 container_init.sh | 29 ++++ {python demo => demos}/cv_grab.py | 0 {python demo => demos}/cv_grab2.py | 0 {python demo => demos}/cv_grab_callback.py | 0 .../demo_mqtt_console.py | 0 {python demo => demos}/grab.py | 0 .../mqtt_publisher_test.py | 0 mqtt_test.py => demos/mqtt_test.py | 0 {python demo => demos}/readme.txt | 0 .../API_CHANGES_SUMMARY.md | 0 .../CAMERA_RECOVERY_GUIDE.md | 0 .../MQTT_LOGGING_GUIDE.md | 0 .../PROJECT_COMPLETE.md | 11 +- docs/README.md | 49 +++++++ .../camera_status_test.ipynb | 0 .../camera_test_setup.ipynb | 0 {old tests => notebooks}/exposure test.ipynb | 0 .../gige_camera_advanced.ipynb | 0 {old tests => notebooks}/mqtt test.ipynb | 0 python demo/__pycache__/mvsdk.cpython-311.pyc | Bin 144006 -> 0 bytes python demo/__pycache__/mvsdk.cpython-313.pyc | Bin 126551 -> 0 bytes setup_service.sh | 61 ++++++++ start_system.sh | 16 ++- check_time.py => tests/check_time.py | 0 {old tests => tests/legacy_tests}/01README.md | 0 .../Camera/Data/054012620023.mvdat | Bin 0 -> 55 bytes .../Camera/Data/054052320151.mvdat | Bin 0 -> 95 bytes .../Camera/log/error_20250728-153215.191852 | 4 + .../Camera/log/error_20250728-153233.191852 | 4 + .../Camera/log/error_20250728-153234.191852 | 4 + .../Camera/log/error_20250728-153239.191852 | 4 + .../Camera/log/error_20250728-153245.191852 | 4 + .../Camera/log/error_20250728-153340.191852 | 4 + .../Camera/log/error_20250728-153418.191852 | 4 + .../Camera/log/error_20250728-153428.191852 | 4 + .../Camera/log/error_20250728-153453.191852 | 4 + .../Camera/log/error_20250728-153500.191852 | 4 + .../Camera/log/error_20250728-153532.191852 | 4 + .../Camera/log/error_20250728-153534.191852 | 4 + .../legacy_tests}/IMPLEMENTATION_SUMMARY.md | 0 {old tests => tests/legacy_tests}/README.md | 0 .../legacy_tests}/README_SYSTEM.md | 0 .../legacy_tests}/TIMEZONE_SETUP_SUMMARY.md | 0 .../legacy_tests}/VIDEO_RECORDER_README.md | 0 .../legacy_tests}/camera_capture.py | 0 .../legacy_tests}/camera_video_recorder.py | 0 {old tests => tests/legacy_tests}/main.py | 0 .../legacy_tests}/test_exposure.py | 0 .../test_api_changes.py | 0 .../test_camera_recovery_api.py | 0 test_max_fps.py => tests/test_max_fps.py | 0 .../test_mqtt_events_api.py | 0 .../test_mqtt_logging.py | 0 test_system.py => tests/test_system.py | 4 +- test_timezone.py => tests/test_timezone.py | 0 usda-vision-camera.service | 26 ++++ usda_vision_system/camera/__init__.py | 2 +- .../__pycache__/__init__.cpython-311.pyc | Bin 604 -> 603 bytes .../__pycache__/manager.cpython-311.pyc | Bin 23671 -> 23670 bytes .../__pycache__/monitor.cpython-311.pyc | Bin 15382 -> 15381 bytes .../__pycache__/recorder.cpython-311.pyc | Bin 40948 -> 40946 bytes usda_vision_system/camera/manager.py | 4 +- usda_vision_system/camera/monitor.py | 4 +- usda_vision_system/camera/recorder.py | 6 +- usda_vision_system/camera/sdk_config.py | 28 ++-- .../core/__pycache__/config.cpython-311.pyc | Bin 12410 -> 12711 bytes usda_vision_system/core/config.py | 131 ++++++++---------- 72 files changed, 419 insertions(+), 118 deletions(-) create mode 100644 camera_sdk/README.md rename {python demo => camera_sdk}/mvsdk.py (100%) create mode 100755 container_init.sh rename {python demo => demos}/cv_grab.py (100%) rename {python demo => demos}/cv_grab2.py (100%) rename {python demo => demos}/cv_grab_callback.py (100%) rename demo_mqtt_console.py => demos/demo_mqtt_console.py (100%) rename {python demo => demos}/grab.py (100%) rename mqtt_publisher_test.py => demos/mqtt_publisher_test.py (100%) rename mqtt_test.py => demos/mqtt_test.py (100%) rename {python demo => demos}/readme.txt (100%) rename API_CHANGES_SUMMARY.md => docs/API_CHANGES_SUMMARY.md (100%) rename CAMERA_RECOVERY_GUIDE.md => docs/CAMERA_RECOVERY_GUIDE.md (100%) rename MQTT_LOGGING_GUIDE.md => docs/MQTT_LOGGING_GUIDE.md (100%) rename PROJECT_COMPLETE.md => docs/PROJECT_COMPLETE.md (93%) create mode 100644 docs/README.md rename {old tests => notebooks}/camera_status_test.ipynb (100%) rename {old tests => notebooks}/camera_test_setup.ipynb (100%) rename {old tests => notebooks}/exposure test.ipynb (100%) rename {old tests => notebooks}/gige_camera_advanced.ipynb (100%) rename {old tests => notebooks}/mqtt test.ipynb (100%) delete mode 100644 python demo/__pycache__/mvsdk.cpython-311.pyc delete mode 100644 python demo/__pycache__/mvsdk.cpython-313.pyc create mode 100755 setup_service.sh rename check_time.py => tests/check_time.py (100%) rename {old tests => tests/legacy_tests}/01README.md (100%) create mode 100644 tests/legacy_tests/Camera/Data/054012620023.mvdat create mode 100644 tests/legacy_tests/Camera/Data/054052320151.mvdat create mode 100644 tests/legacy_tests/Camera/log/error_20250728-153215.191852 create mode 100644 tests/legacy_tests/Camera/log/error_20250728-153233.191852 create mode 100644 tests/legacy_tests/Camera/log/error_20250728-153234.191852 create mode 100644 tests/legacy_tests/Camera/log/error_20250728-153239.191852 create mode 100644 tests/legacy_tests/Camera/log/error_20250728-153245.191852 create mode 100644 tests/legacy_tests/Camera/log/error_20250728-153340.191852 create mode 100644 tests/legacy_tests/Camera/log/error_20250728-153418.191852 create mode 100644 tests/legacy_tests/Camera/log/error_20250728-153428.191852 create mode 100644 tests/legacy_tests/Camera/log/error_20250728-153453.191852 create mode 100644 tests/legacy_tests/Camera/log/error_20250728-153500.191852 create mode 100644 tests/legacy_tests/Camera/log/error_20250728-153532.191852 create mode 100644 tests/legacy_tests/Camera/log/error_20250728-153534.191852 rename {old tests => tests/legacy_tests}/IMPLEMENTATION_SUMMARY.md (100%) rename {old tests => tests/legacy_tests}/README.md (100%) rename {old tests => tests/legacy_tests}/README_SYSTEM.md (100%) rename {old tests => tests/legacy_tests}/TIMEZONE_SETUP_SUMMARY.md (100%) rename {old tests => tests/legacy_tests}/VIDEO_RECORDER_README.md (100%) rename {old tests => tests/legacy_tests}/camera_capture.py (100%) rename {old tests => tests/legacy_tests}/camera_video_recorder.py (100%) rename {old tests => tests/legacy_tests}/main.py (100%) rename {old tests => tests/legacy_tests}/test_exposure.py (100%) rename test_api_changes.py => tests/test_api_changes.py (100%) rename test_camera_recovery_api.py => tests/test_camera_recovery_api.py (100%) rename test_max_fps.py => tests/test_max_fps.py (100%) rename test_mqtt_events_api.py => tests/test_mqtt_events_api.py (100%) rename test_mqtt_logging.py => tests/test_mqtt_logging.py (100%) rename test_system.py => tests/test_system.py (98%) rename test_timezone.py => tests/test_timezone.py (100%) create mode 100644 usda-vision-camera.service diff --git a/.gitignore b/.gitignore index 2303924..88dc0d8 100644 --- a/.gitignore +++ b/.gitignore @@ -59,8 +59,8 @@ config_production.json .DS_Store Thumbs.db -# Camera library cache -python demo/__pycache__/ +# Camera SDK cache +camera_sdk/__pycache__/ # Test outputs test_output/ diff --git a/.vscode/settings.json b/.vscode/settings.json index 7fa27ff..806bf53 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { "python.analysis.extraPaths": [ - "./python demo" + "./camera_sdk" ] } \ No newline at end of file diff --git a/README.md b/README.md index 86df0d7..770e690 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ This system integrates MQTT machine monitoring with automated video recording fr - **🔄 MQTT Integration**: Listens to multiple machine state topics - **📹 Automatic Recording**: Starts/stops recording based on machine states -- **📷 GigE Camera Support**: Uses python demo library (mvsdk) for camera control +- **📷 GigE Camera Support**: Uses camera SDK library (mvsdk) for camera control - **⚡ Multi-threading**: Concurrent MQTT listening, camera monitoring, and recording - **🌐 REST API**: FastAPI server for dashboard integration - **📡 WebSocket Support**: Real-time status updates @@ -19,6 +19,38 @@ This system integrates MQTT machine monitoring with automated video recording fr - **⚙️ Configuration Management**: JSON-based configuration system - **🕐 Timezone Sync**: Proper time synchronization for Atlanta, Georgia +## 📁 Project Structure + +``` +USDA-Vision-Cameras/ +├── README.md # Main documentation (this file) +├── main.py # System entry point +├── config.json # System configuration +├── requirements.txt # Python dependencies +├── pyproject.toml # UV package configuration +├── start_system.sh # Startup script +├── setup_timezone.sh # Time sync setup +├── usda_vision_system/ # Main application +│ ├── core/ # Core functionality +│ ├── mqtt/ # MQTT integration +│ ├── camera/ # Camera management +│ ├── storage/ # File management +│ ├── api/ # REST API server +│ └── main.py # Application coordinator +├── camera_sdk/ # GigE camera SDK library +├── demos/ # Demo and example code +│ ├── cv_grab*.py # Camera SDK usage examples +│ └── mqtt_*.py # MQTT demo scripts +├── tests/ # Test files +│ ├── test_*.py # System tests +│ └── legacy_tests/ # Archived development files +├── notebooks/ # Jupyter notebooks +├── docs/ # Documentation files +└── storage/ # Recording storage + ├── camera1/ # Camera 1 recordings + └── camera2/ # Camera 2 recordings +``` + ## 🏗️ Architecture ``` @@ -46,7 +78,7 @@ This system integrates MQTT machine monitoring with automated video recording fr ## 📋 Prerequisites ### Hardware Requirements -- GigE cameras compatible with python demo library +- GigE cameras compatible with camera SDK library - Network connection to MQTT broker - Sufficient storage space for video recordings @@ -90,7 +122,7 @@ pip install -r requirements.txt ``` ### 3. Setup GigE Camera Library -Ensure the `python demo` directory contains the mvsdk library for your GigE cameras. This should include: +Ensure the `camera_sdk` directory contains the mvsdk library for your GigE cameras. This should include: - `mvsdk.py` - Python SDK wrapper - Camera driver libraries - Any camera-specific configuration files @@ -519,13 +551,13 @@ python check_time.py # Check camera connections ping 192.168.1.165 # Replace with your camera IP -# Verify python demo library -ls -la "python demo/" +# Verify camera SDK library +ls -la "camera_sdk/" # Should contain mvsdk.py and related files # Test camera discovery manually python -c " -import sys; sys.path.append('./python demo') +import sys; sys.path.append('./camera_sdk') import mvsdk devices = mvsdk.CameraEnumerateDevice() print(f'Found {len(devices)} cameras') @@ -579,7 +611,7 @@ df -h storage/ # Test camera initialization python -c " -import sys; sys.path.append('./python demo') +import sys; sys.path.append('./camera_sdk') import mvsdk devices = mvsdk.CameraEnumerateDevice() if devices: diff --git a/camera_sdk/README.md b/camera_sdk/README.md new file mode 100644 index 0000000..c507622 --- /dev/null +++ b/camera_sdk/README.md @@ -0,0 +1,66 @@ +# Camera SDK Library + +This directory contains the core GigE camera SDK library required for the USDA Vision Camera System. + +## Contents + +### Core SDK Library +- **`mvsdk.py`** - Python wrapper for the GigE camera SDK + - Provides Python bindings for camera control functions + - Handles camera initialization, configuration, and image capture + - **Critical dependency** - Required for all camera operations + +## Important Notes + +⚠️ **This is NOT demo code** - This directory contains the core SDK library that the entire system depends on for camera functionality. + +### SDK Library Details +- The `mvsdk.py` file is a Python wrapper around the native camera SDK +- It provides ctypes bindings to the underlying C/C++ camera library +- Contains all camera control functions, constants, and data structures +- Used by all camera modules in `usda_vision_system/camera/` + +### Dependencies +- Requires the native camera SDK library (`libMVSDK.so` on Linux) +- The native library should be installed system-wide or available in the library path + +## Usage + +This SDK is automatically imported by the camera modules: +```python +# Imported by camera modules +import sys +import os +sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "camera_sdk")) +import mvsdk +``` + +## Demo Code + +For camera usage examples and demo code, see the `../demos/` directory: +- `cv_grab.py` - Basic camera capture example +- `cv_grab2.py` - Multi-camera capture example +- `cv_grab_callback.py` - Callback-based capture example +- `grab.py` - Simple image capture example + +## Troubleshooting + +If you encounter camera SDK issues: + +1. **Check SDK Installation**: + ```bash + ls -la camera_sdk/mvsdk.py + ``` + +2. **Test SDK Import**: + ```bash + python -c "import sys; sys.path.append('./camera_sdk'); import mvsdk; print('SDK imported successfully')" + ``` + +3. **Check Native Library**: + ```bash + # On Linux + ldconfig -p | grep MVSDK + ``` + +For more troubleshooting, see the main [README.md](../README.md#troubleshooting). diff --git a/python demo/mvsdk.py b/camera_sdk/mvsdk.py similarity index 100% rename from python demo/mvsdk.py rename to camera_sdk/mvsdk.py diff --git a/container_init.sh b/container_init.sh new file mode 100755 index 0000000..f7c792d --- /dev/null +++ b/container_init.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Container initialization script for USDA Vision Camera System +# This script sets up and starts the systemd service in a container environment + +echo "🐳 Container Init - USDA Vision Camera System" +echo "=============================================" + +# Start systemd if not already running (for containers) +if ! pgrep systemd > /dev/null; then + echo "🔧 Starting systemd..." + exec /sbin/init & + sleep 5 +fi + +# Setup the service if not already installed +if [ ! -f "/etc/systemd/system/usda-vision-camera.service" ]; then + echo "📦 Setting up USDA Vision Camera service..." + cd /home/alireza/USDA-vision-cameras + sudo ./setup_service.sh +fi + +# Start the service +echo "🚀 Starting USDA Vision Camera service..." +sudo systemctl start usda-vision-camera + +# Follow the logs +echo "📋 Following service logs (Ctrl+C to exit)..." +sudo journalctl -u usda-vision-camera -f diff --git a/python demo/cv_grab.py b/demos/cv_grab.py similarity index 100% rename from python demo/cv_grab.py rename to demos/cv_grab.py diff --git a/python demo/cv_grab2.py b/demos/cv_grab2.py similarity index 100% rename from python demo/cv_grab2.py rename to demos/cv_grab2.py diff --git a/python demo/cv_grab_callback.py b/demos/cv_grab_callback.py similarity index 100% rename from python demo/cv_grab_callback.py rename to demos/cv_grab_callback.py diff --git a/demo_mqtt_console.py b/demos/demo_mqtt_console.py similarity index 100% rename from demo_mqtt_console.py rename to demos/demo_mqtt_console.py diff --git a/python demo/grab.py b/demos/grab.py similarity index 100% rename from python demo/grab.py rename to demos/grab.py diff --git a/mqtt_publisher_test.py b/demos/mqtt_publisher_test.py similarity index 100% rename from mqtt_publisher_test.py rename to demos/mqtt_publisher_test.py diff --git a/mqtt_test.py b/demos/mqtt_test.py similarity index 100% rename from mqtt_test.py rename to demos/mqtt_test.py diff --git a/python demo/readme.txt b/demos/readme.txt similarity index 100% rename from python demo/readme.txt rename to demos/readme.txt diff --git a/API_CHANGES_SUMMARY.md b/docs/API_CHANGES_SUMMARY.md similarity index 100% rename from API_CHANGES_SUMMARY.md rename to docs/API_CHANGES_SUMMARY.md diff --git a/CAMERA_RECOVERY_GUIDE.md b/docs/CAMERA_RECOVERY_GUIDE.md similarity index 100% rename from CAMERA_RECOVERY_GUIDE.md rename to docs/CAMERA_RECOVERY_GUIDE.md diff --git a/MQTT_LOGGING_GUIDE.md b/docs/MQTT_LOGGING_GUIDE.md similarity index 100% rename from MQTT_LOGGING_GUIDE.md rename to docs/MQTT_LOGGING_GUIDE.md diff --git a/PROJECT_COMPLETE.md b/docs/PROJECT_COMPLETE.md similarity index 93% rename from PROJECT_COMPLETE.md rename to docs/PROJECT_COMPLETE.md index 33f5bf9..0f4df48 100644 --- a/PROJECT_COMPLETE.md +++ b/docs/PROJECT_COMPLETE.md @@ -9,7 +9,7 @@ The USDA Vision Camera System has been successfully implemented, tested, and doc ### ✅ Core Functionality - **MQTT Integration**: Dual topic listening for machine states - **Automatic Recording**: Camera recording triggered by machine on/off states -- **GigE Camera Support**: Full integration with python demo library +- **GigE Camera Support**: Full integration with camera SDK library - **Multi-threading**: Concurrent MQTT + camera monitoring + recording - **File Management**: Timestamp-based naming in organized directories @@ -50,11 +50,16 @@ USDA-Vision-Cameras/ │ ├── storage/ # File management │ ├── api/ # REST API server │ └── main.py # Application coordinator -├── python demo/ # GigE camera library +├── camera_sdk/ # GigE camera SDK library +├── demos/ # Demo and example code +│ ├── cv_grab*.py # Camera SDK usage examples +│ └── mqtt_*.py # MQTT demo scripts ├── storage/ # Recording storage │ ├── camera1/ # Camera 1 recordings │ └── camera2/ # Camera 2 recordings -└── old tests/ # Archived development files +├── tests/ # Test files and legacy tests +├── notebooks/ # Jupyter notebooks +└── docs/ # Documentation files ``` ## 🚀 How to Deploy diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..6dc6beb --- /dev/null +++ b/docs/README.md @@ -0,0 +1,49 @@ +# USDA Vision Camera System - Documentation + +This directory contains detailed documentation for the USDA Vision Camera System. + +## Documentation Files + +### 📋 [PROJECT_COMPLETE.md](PROJECT_COMPLETE.md) +Complete project overview and final status documentation. Contains: +- Project completion status +- Final system architecture +- Deployment instructions +- Production readiness checklist + +### 🔧 [API_CHANGES_SUMMARY.md](API_CHANGES_SUMMARY.md) +Summary of API changes and enhancements made to the system. + +### 📷 [CAMERA_RECOVERY_GUIDE.md](CAMERA_RECOVERY_GUIDE.md) +Guide for camera recovery procedures and troubleshooting camera-related issues. + +### 📡 [MQTT_LOGGING_GUIDE.md](MQTT_LOGGING_GUIDE.md) +Comprehensive guide for MQTT logging configuration and troubleshooting. + +## Main Documentation + +The main system documentation is located in the root directory: +- **[../README.md](../README.md)** - Primary system documentation with installation, configuration, and usage instructions + +## Additional Resources + +### Demo Code +- **[../demos/](../demos/)** - Demo scripts and camera SDK examples + +### Test Files +- **[../tests/](../tests/)** - Test scripts and legacy test files + +### Jupyter Notebooks +- **[../notebooks/](../notebooks/)** - Interactive notebooks for system exploration and testing + +## Quick Links + +- [System Installation](../README.md#installation) +- [Configuration Guide](../README.md#configuration) +- [API Documentation](../README.md#api-reference) +- [Troubleshooting](../README.md#troubleshooting) +- [Camera SDK Examples](../demos/camera_sdk_examples/) + +## Support + +For technical support and questions, refer to the main [README.md](../README.md) troubleshooting section or check the system logs. diff --git a/old tests/camera_status_test.ipynb b/notebooks/camera_status_test.ipynb similarity index 100% rename from old tests/camera_status_test.ipynb rename to notebooks/camera_status_test.ipynb diff --git a/old tests/camera_test_setup.ipynb b/notebooks/camera_test_setup.ipynb similarity index 100% rename from old tests/camera_test_setup.ipynb rename to notebooks/camera_test_setup.ipynb diff --git a/old tests/exposure test.ipynb b/notebooks/exposure test.ipynb similarity index 100% rename from old tests/exposure test.ipynb rename to notebooks/exposure test.ipynb diff --git a/old tests/gige_camera_advanced.ipynb b/notebooks/gige_camera_advanced.ipynb similarity index 100% rename from old tests/gige_camera_advanced.ipynb rename to notebooks/gige_camera_advanced.ipynb diff --git a/old tests/mqtt test.ipynb b/notebooks/mqtt test.ipynb similarity index 100% rename from old tests/mqtt test.ipynb rename to notebooks/mqtt test.ipynb diff --git a/python demo/__pycache__/mvsdk.cpython-311.pyc b/python demo/__pycache__/mvsdk.cpython-311.pyc deleted file mode 100644 index 9c7f50cbdb3087096bb82ef3792986b990e4b22b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 144006 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 Ug`_?sKP{aP=%OiMY?}T51A|!`Qvd(} diff --git a/python demo/__pycache__/mvsdk.cpython-313.pyc b/python demo/__pycache__/mvsdk.cpython-313.pyc deleted file mode 100644 index a1b88dbc3c516383df65e7fa38f70cc574c2221e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 126551 zcmeEv34B~t_5aLdCYdCYrD@WA-&4BN4GM+s4Rj-~X#)*}Nit2QO(x+@(uFlFLQB!6 zB0qwnl%ET&pj3-m1+@zPL`9u2)yA>#Lvf+5m5AW}|DJQ-yYId?FKq?eQvbjA`OJCe z-nYy>=bn4+x#ymHUr%0Mjt9rwFBf0m+T``TN(uAGHjtje5|8HrkLJ<5S9)|h`>yoP z@r@uX<4WHZ8F~hA?+t$Z0-Ar2N6)Ov9Oap1JWluNSz163YMFYrmZj%tK|NQ?)PqZeyMdWqIo@23^({k0N(fYwhRsP)$eX#@1Z z+CY7XHb@_;4c3QgL-gU=P<@0pOdqKY*GFk1^wHW#eT+6rAFGYl$7y5q@!D8@f;LVs z)yC@+wF&wKTB$xso2XCLF3_iFlk}~B5jU-u{Kwqr(L99qFtD8RRhSS%{^af5>BVEqdt2li<(pPc%T26=M_3JoYBd=F;x>jDlp3`+Q9p-cd zY4QIxoZcwYwVbY(={im~$aI9$QKZ)prfuZ(CYi41^k$iE;B=!*M>*Yuw4iSjr(-g` znbXZO-N@+{nQr3r4Klr!)4EK@I31ViW=^-tbPK23kQV$D<=-OHqWoKBT9kjAOpEew zm+2e$eK*Rq&gq+EI?m~vWxAEqw;(O(Z{zf>GQEYqa+q}LIq-NNa+W%^c5-y_qvae9YLw{v=@OyADwdyy9Z zcL%3;$@HC^z7OdN!nC_M{a&O6{qN!Q`(*lVPVYuq)XzPf?vU4aaC(nS@8tCRkrw>8 zm(%yl^e#?+K;C~Jryr2%_j3BbkQV>$epIF(;`D#Z^anZpQSBQ2W7-D& z}p;&V3xYPbj%x<=jsp_tQ%5Va|OLxd)Wo zuW{~Yko#FB_v@T{5V=n&xzBR$=aBn(CHFbb{Q`0iDY@U^+%F>cOG@tlaPHH{eMZUs zCg*+`xnEIopXc1KBKNS8`z_A>8gjp`IcfzAKI?Ii1*-K^4X)-RsIjR|H(A|r`x(0C89U=R-zwOWmq$@uQ6YTpdUHds;kM;||KWe`Od_#K;@K4%tz&EvD0luaE8t~8BZvg+I{TA@A+V24Wru`o9 z@7f8#e`tRI{HON%AkQ){Y{(uyd$m9E*{8k1=M3#neD-T^@;RWr#pg`z&wS3({=(;= z_E$b0U$V1OpV1vY@Oali&LHXhg@#wGw8%vdR~A&gA~ zHk7dofDL1860qTnO$IiCu_?etGBy?1D8{A%8_n2sU}G4Y0c|$V(8Jh=e3S*Z5o66Xwz@{-aAJ}xpE(11$vCDy7 z$k+m4GZ|Y5Y!+jSfX!xXF|av|Ede%{v8BK+Vr&_(iy2!EY#w7}z%F6z3SgHqb|tX+ zjI9868DlGfUC!7lU<(*q4QwG}Yk)0c>?&Z387l|2gfR`+QpVN-TgF%gu;q-c16Ib^ zdSF*DRtfA%#;yjog0X9Wtz>KiuvLsz0b9-3wZPUeb{(**7^?ZDgz!SUqEH(2ZG0HIQ~hYu^Gq%2&1m+r-#5 zV4E4+4y=)}8-X=3b`!7|V>bh9X6zPVEsWg?>;}ee1Ew?94lK^t?Z8?Yy8~DoV|N1E z!q{EFwlek}VA~kG8`yTn?g4fqV>^J|#Mn+?H#2rGuv-}01?*PF?gMrkWA6pl&e;2a z-Oku z0lSZ}4+48HV;=(cKE@sfwwtjJ1M6VyBf$1B_6V@|GqxAl{fs>d>;sJbH?Rj7`zWyg zV(eqU9%Ss}z&aWG1h9t~dkokI8QTZ!LyYYQ_Aq0g1omOZ9tZXj#-0H72xFfDwwJL_ zLw|>057TCubI|%F(j6DVHF~&XzY#(Ev2ezNFF97=_ zV~6lhexx2Z{^^UrpWrKB0`@7!o(A@5#-0K8Bx7F&c7U<30Q(GMUj_DA#ts8J$k^9_ zJ;m79fqjm#XMug5vFCt&fw6A@JH*)k0Q(|i-vst0#-0cEG-KZa_6%d+2KHsfz60zl zjJ*KttBidY*kQ)L2kdK%eIMA@8A||rma#5i&oTBQux~Jy1ol6S9Rc=D#(n_odB%PS z>|2Z-1@>*mx`BO%u^$0@fw2^@?=tpdVBcfx7_jd%_7boJV=n{iV(fo`y~x-rz>=jCx)#{LNGmyEpu z>@~*z1nf9tZvy)jV{aL>{@S4R&qn$;M*1&C`nN{R%bl z2KG0`a)AAvv0PyPU@QdepN!?9&d|oXE>_J) z;~p)8pYm3CCKxw|r+7RSUYRQNcs3XV7muernEuAq1^wBTIWWU>{miTMTxnocDr&8^KXRSj+7 z)<~?rx@CK7LvyT3oJQ0|nwqPcwxB>$TDGSG)n&10tKJ`P3gH*8259&EG3W^u@4oEb z%aXZ6_GWkGmbUjhmfQDe?uZw2MM|Js%f0mthG<#rI_Q1}`$?OS~I|8{q_zTbRf8sd)4+4KD@HYZ~ z1&IEIz@G`cMc_>We#8sLVSDxfq?`D5g1J1LIOhw3?(p= z0I96wvk43%Fr2^)0wV}qOkf^?MFcJ(a4CWL1QrvxjKJjt77$oMU?G8#1V#}UO<)W_ zEq?MKUeeJ+e|H_Uag|4hdq9Vx*E2Mq?yvC7WQV|}pl(cKVbUtA!gHxt503GaW~K@j zg_|OJc*(ZfNK0$9Id=S4c+-tT>zZrht$H+8KLV<1gyWuC^Ka>|sV3>yvkqXsSM3ls z$onch*P;@MPjrm%R2DYUGkjRyrV6jATq`_{Bo}s0ajX1X}QLGTpw?|y@;ajKNJ+C9g7S@#um7I*o^AMurT7Z1B@>ajj! z_ijq|nchC;J(F}2o?0(}d62X-qgDaI)T6gty=vT5;c@FlkxNfIj#&nKQIEb=Hx95E zaq&&Jj4+4>3c53?zX`W8<$4US+3(exaf(w3Mlj*2EO4S#2S@v-6VDg^Ko5}6w|ly? zM<30e*p)qT-^?d3+ke@i#a~_V#TCiyvV^aU=`QtIe^r`IwH1SuQEgRMH#OI_H4+}G zuD+oy+-O`WsIJ}^)#I&=(O4wbjLRqwgs{4rYea9u|E5Z)h~d^~ZFRU6bz9Tc8bSS~ z@{FpijWjk^SA(<`Dk+h6xu{bT8I~K8?Km~k+J72Xpbf?RmM zvlchW!>p$s(m~EP1{a{8OenQ|)n}GwrE*tpfdsa3uYUZGc+w^fq~}-~-r{#o^~7M~ zlmmAjeLc%7VK@0I(59(P#4Ephl3}KBl{%@9tafyQMwSom0@^-8rFs=CRzOj+x2aVePYy zWfpdnJnZk(K9qelb5vL6sAHj#d&ee26WW(_XJp+o@Ai2+w(h=l=dGP}$%2VL%(&nW zxt_wICqkZ_{M`e04(yn@Yk0ypAYG48t7pj>1>^w_q{fs_q|L)rwPQRwI%ZF)ms^nD z3S4dUXqkGXg<5^Fomi2Je%uqMu9c|G+dX9GkX^$PzW(WDlG3~dH=_%XC93e4a$#Ba zF|Q@TiquNwujI+6Es3_?XilMwz<9u<)34uy5|GYsYHHqs>aE$XM>fLLj@}q)-Uz)! zYA==1T(ilrc!lx{)HXK9BB?$q6FAEUO5$WgK;H*LJJ#Npvn$j-`j{{KzOfw{yC!}h z(z*El%^#b+Z_Gz8IpUkvogHeQ$lTeFAyiP`iU;*=1hx~nkpPL7zK1|3ftv|@kiY-} z+y}K2Mu4TO#x^sK7cADJTO#^8jBH@!V8~UgMPl)0eJ$w`+`6V& zZ)Mz%E3s5|TbZG1Y)YG&9XCC)CGBGF)@_@jZwjYR-+|}!4-;^<#6nmtHX>7_(zr3j zc~4((r-#g3NN4u2&eo&DFYFqAVKRGW!Z$O$k^Xy1{}H#+=UXLXhL1Q|+3Ajww31Kn z8a_RlJtN_pai&WCh+D}EP;#5xjC3u!dP{%O2{x|J=o&sFnSEixcj1{T`(C%Q=c4RV z#)rC=+q^uG_)VI`kd#Mmd+4@g_SA%L>X|C>qi!W8DYv&ocPY2sGZ{2kk-#$qzDmHYCw`bN5TJf2{t%G6J>B`k_x9U2>e0c8yvf~x z;*O1-`ku`R|ETUjNynDGzCAZ3{G+=AeL7}$F5ELO;UC@|=+~LKx9FkVgnvwTpl`>z z&YC?N68@3)dvbTI>!{g@{DIwp!j5q`pXd|J8{9sC`uth1`@Oyk3CtugjR5D(;N%-f z3bTXDT8m=JgS;qo^ehKRw+LVhWK{WuMF0p}05Fq!axIHtkYP6W?LqYIIeJ!oF5H-X zsrt$z@#e-havPL~WA%~fSa1n;`tnG$zM*wxc$F6O5?WJ1aurbWFKvgDJ3&AYLgA8GcAqPenU@pTD!#sxh3=0?* zGVH^!h~U&hm}q2v1z~<=v-!nUTGj+cTlE^9Mpc>_EsNDfwvovNhj6VPWml0f!*Z1x z6V<2G77Qt~di57TX(~6meD%hSarC*X*CDaaN*FRh`KAOBo++dzm1Rg(DkL(lX>M*> zUYE)b{zW+ORftfrCD-h3n^R@cASH)WXUP_EC!SHPtnVG5J1C$ zRr_iAsjzg zp9Kek=w6x|Vd6)c;5Q7@vMAq%8M_+MPb;OBIe0MXt~HCvHuk?$b&^ZWUaLpz z>*0ZDAn7<4DrAsS3WvnTs7wyE;VQ9zCY}>uDlCbmEO(a8#+6rR+$`}-0sH7SBYzmw*Pm^V}K{v zN$9Rt&EE7xmY>yYNUB$Q*q!HZv)9Wb0a>F*U|_9)U4BbCv(FBPhuF&DVDO!840cnl zAGXyL;gC2_Fsy;QE#Y2}%8BLSww zVjX4uTUj@N3cN79J)$p;&?KzI!#z}lbHT&$y%ov9%m=A}r^8GNbkYehNft9H%bl4t zW6+Drl$|`3WdM`$nLJroL}eD{2+eTDG07SI5MGb*&)VkJFv5YNi^44&AQXtMXvSQW z7$ju%ZW#93>*f&kK$h(a)S|}ynYrHnEX$N;Czxw=oFk+sW))+5XE#O0ix-oJw!oAKa8)^dkA{i z#_|mO4IMpW0D2cOjEK-TL%0HnoXBlm7H(<^3m?s=@y3)tN+unkX~*eB$aWT=oW?o< zdZvfw%}G$Qcg$*^+AU5zVlc&n?tI5(&2L@Q41Y~H-YSawIV!^-0_+B6sdp{xFuI2T zKQV+-Y>88rtyJdRc+Vv#<)Fh7r)G;8G1%al;4D00_1UF4sl3+m`WiB-MPZ-8f5Dn5 zH_dDlWtZ17D_5YLyU@xN=t*m21d&C6{waQuQ6uJH{PfNz^0F*LncijN&fAf%!d8uj z*U($0Bk-G4&eN&233MX?e!{9X%6iA;LbncYa7zsFKcarVce=%zNH-GTC#+&omaSNF z!c_$I*u$@QDCg#0mBJ*3b(-SG!vtyo`v+v!hf4EOY?qY9TcG;Gwb9n?(I4RdQ@J%O zn`6yl>LHa?v%Y3Eg+yf4ENE+OUSE^SV}!?Q6i-@Evoah*oQ=%LsaX(fjV^7B)^1Ma z)L^1DS{uQCq>5^mHtV$!M1NX&SvBlfTP%7T*LF9FSVe%!7Qf06Nz-3s`h(1~=?^OI zfS+iHnH=WaE*?c zzBLGhBd;mW7-ZvGmhBq*SaA(g;J6mFU1Ogsu3-?4YuUDI*~UBJg~hcT+qGQd8oaW& zmTS9~XI#rS&IQI9o?6@+vfbOqxK?DG`x@tBzBkWyZ;5fOpUbuW#IM`!GKF-9LyKelw7 zm_86w{SfY&Xd_AYtEj6~sKpp&lYbQ6UNx29!hTd5De~3)s68EOS=7k>KI2(6mER(} zbK_Zix}e4K2JsCAQAb9o#TYXhZ&yLlYu1F}BP)xEmI$8E;G{|0YW%Y;C9W;6Q?D7Rq88IKx1KJF zy5y<%na`^C8F{&J;R52nDvVpx1gu_Dd2zKjOcll*-9joiZW$t}{J5>BPZh-N+By}A zE2>XupwfYE_HHU`&FZpMYnPO>UqiUa$)U_XPqx3m6Dz|xaUI3oGI^_Mahdj{yrUG#n2P;D0zv;-!IXhS#v3+=X?BpJ60xq zqfT5#$;-Wboojl5mvR;&r%wkc8Fpe3XJC#8ReN2+H|E3=&RB|!l8)wtZyXjk(Id-| zQPgo+!Z-Rv8D*GuH3^rkO{0V6aRWSq>o%uLcbb!jG_@Gw zJM$RkGvrQ5D04S1>(?B#E{}xkq9MpW`JJU+O=Y$%+>RJs{YTUo zQv_Zj@G<~QkFvO-+u2zSH?!7?IbBQ{lINM+&Z%6*D~*vbD-YP$rry8=qNQOFDV?W z*$O)#IG7|epEvDz(}>F5v7U$I_A^hSnKD9Uv&l#{%1Fn*Ht(+*rX)M*^Zsm-F4My` zH4y~Z!{i@HwI1N9{Zyuy`A_*5M`2KAnH~#2IV@5E4$4nu(Y2*5@l+-*<80KA>+JpM zRLv%;8Uj?1_%e`8RU^C?7E6smt7(QBN%OAI4$LTEHd8S8M4xP{@zI-YjK#n3(K8b# z=aLIvZh@6`SZEm|`(r{&p5qOhY_yqhFNJ?t(s81|gzSY$Ou@GVtpu0(gK{g5WHU3almKaOM5pl&`kNh}P9_ zLZNKYx`ruGjG0uX5Z;D> z$}rDb*YNwb9CSa%Gty(NX36q|u?#4dQGt+sG!m?-+!T!Y@w_=AG5-hW3K>{`sW%qr z?LWrToq@P-IQEr`Wh}@TW1Kg7H+nA381C8V#S#yj7!nEOk?A2<<9y!(p0z%=)dQnE zYrRuZ%&WX}GH09Y)o%nxX*mpL3*-8Oc!5|ALM$24-Y!C-eYK6LL9)s*t5{t<E z8lOLmUBgz@d)}eQ4-jJvnefW(XE7NbLo7e$=GbL{!a4UeiHig?H0n!EL+7w!tQuKO`&zJvZFv}M@;QN+C+0{ksiq~Di&466-> z@1*q)ZygKv>+$$}x!uJjca6astL&V=o(LfQmv|xWzoVeY^ZuOa84u@9%6K9$J)>5Z z9vAUa(afn%X{Cf4m8OpL>AUc(ejfnVJqJMxFDkQ@TT{zTlL6OKxv8r~Bj`K$uHyF$ z7s^I01xYj4P!PHHpmA#*geF%%nCodK;4wPF_=^h9>Rk6VU@>g`gB3zli@sr42T^W% zH^svYE94rWn0JI{wU5^3Y>*|a@NO`jSRU8^_KuT>S$mR%w=gH~xVaa_H{^mddQ-sijm= zMJ!5lOk$>qr6-laD}Ev|$}jb&GO!dV<;5BwO4ka>BXO6?M1y?sAab~H4uD>UwQZQr6N%l4PG_jxscSbGIz63Qhjc+a-mw{-;Wysdruk1~RP z$nq2n|6{%zFW0u$IZ`g&gDWvuM7mU`)r;J#+6z{MaD73dG{=zC|`2Z}pt?;rT0e^7U3 z_C1?!-_%i(%mmi9*Kqze+f-tp6qu$|Q zhyExs7;GWphvPjYy@f|Z!@5GlI&V&fCbbVZ=FQvDaKzicJ6PCm(1n}jLG6_3qORyv zbSbo0Yq2DKZW3V1rm0I}K4q1m)I{Ki&s-K05d0`I_<`u~?eWzj!j!662nMq!BbC$4 z7ib9y>juFgA_py8te*N9JwxCoVi8&C28%{_g+?D4bJ3xR$uUcgEUP+l?e&T9#^km2 z$z=`6P}G%gc#Axw9{&=u+}k7SUUC{b(=VTu2nF;iE8%>~-W2ADP2P)E?AriMDh^AQ zBxf@=NUdBUbun>P^Sb}LpDe(8K@@Z>k9r@*y9FOvBuhjUEQz(zn($U*B0ztD?&1pY zV_S;wHg<8Q{HxlU;;CFrPSDLOFlQ|)gQ!Mj7`5>j)dqofs*Njg4Yd)3fbJ@2FFsZ{ za_{2Du6Xo{7YnB(3#PXZW>F>uy!WQ3mK+*$@XBQ9aEn1kqdoZRf%g5%DI>uzq+_r)dWU_Yi61lp)eWM}uR! zf@6}waS89ZlUM^E6a~aP#9Wf8KK0@0(>nKkdD^p0;!l zQj#g8gk>XN)N>h{W+WD=vxI`>2bQ2I3AAo6mDOV0#v07lK4~&pCvY#ZZ65v`Y|Aa& zHK)BlSO4&?(D081_HIs&m;o6We{fYYv{;pag57yL^E&%<1qUU(g9L-={pKOn+actr z%~Uct!)m0b%izi)h3&Gb&GL&s#o}w(c&+gs8X|TNzj&*$)Y@vuazq&MR%DdZXw`9; z>^B-Ivp>gRKkcw0+aoVk7yJ+CPlBbXf=Clj9niinv|J*U8EIM@2{)zkjCQ&_j1`g* z(Nal|Q%g0P>Sw892y`e-wNJnM`?n88#q3_abM?bZ_Fj-2GUY(Q3nkCrk}SJ68M;oX z8Goq5d*{ky!Tz1WB$}shWOuOSXmD^>aB#vq_#_qe2^8b)R8*xG`q7g7b5boKt6HES zTq_1$x-p?jYbf-C#O0?5e2xIO4@X6Ofi4i}q>5M$_MnBxiZ~h?+7%kw*?4H(a~02D znp|>qGIY(qRttEuJY=s%OQKwBLFv;@x49_IL0X2g*HZg5n?0a37OP*Acc8I&%c&_i z4zsZY6!^tOjv&DjQ0rv2h`8#&rvRcPZ3>;HO?)xJ{cN!N@`^L+Xu4VPW!9yC^hWX+N`cg%7?HK zFRnz_gcvEbD;GFK2s}o2Ft-FMTa9?HZ!$YTc z`p0ighAvb1ExMzQ`Uji#GYS*=vgztBOMjnh6f;$R1C5>ShPCjBeK7}?=qhZE*xprvMe8Ro!nLO=o- zi_ddV9k_KfFVGtZe2G{~<`Gy+t&#>xdzU>?c_8w5^)n5Jw4POb0U!=~S7CuG_)REYae>ODy6T zu3`l##`h;f_vIJu+ppay_VQY5hZP4^2qQ_^brc4 zrs^8Q5GWX(VgN3rEVp5Otj@UT(q?}^loNQ4C|A_tsIJhcy>pVGxvm5fLFOSl!5DJh zrU+T4p(NGZG6tI{S!z+XOE5xqi}sdh&|1E1;f$G1QSl3&ghc$%Lf(ozej~$MOg7YHlCI zJ-oDThHObHhrA?-f=d+7wR<3hmA~-hT9V=`o*LuAiB~aU|;&G96 zXjCOmZhJw>T36gxGVc@~oC=RptFqRWJSiQjBvkk(7)1)hq}U++GOGjD2Ennw1~d2y z^Yx06VLc0jx^iJT1vfYj_BU9h%7tJW$OEn1>!sebnCwPh=pRIjdB%gtZ-fj8o5 zOwb=DIeHBMCZw?gL$JlzYeD}JU1Z%rwik77rp@ykx@sw@EYz9W5?I>NMj@%k0{McG(W}o)oB-F7o+zL$|mqv;@LPM`ZSs< z?FyCd8~@bYLuJVemnK8Y72a6ABc787(a!WQ1#)WoO)YfV6OV?^YYi-W(eS^4e^)16 z^*4zY0#uHkp*XXZN-p5eWy#Q(b5268Fx%FI+b{&9%F)wk_zUF{2!IB45Hh4IG^7)r zrm^Ro3Zo)4Y_Q%75q~2h2;_hW{VhtNfAQ2(6EP1t+P)4srxF);e_`cJbUem8F^;yH zjO#esXflPO4rp*#j`$3{PWV~5sfgh-HtjJ6%Q-EzT6jxjO}Moo6|9-DY(=ywiXn8} z)~m2G2}?h)z>^nSlw;CSv@I$FcPwVt@(&`OKmpa~WL!2zP9wXpt?KwAGs~Wzn4DRW zSYMrJ+>#7!J?FJ+@P}&G;E%hY2B0r=0>utN6@(>26J1Hc&GL};^f?|a8=Hx*X^S^- zb@nn;&L=08VgmOzSk5BO5Ew|DQ3lH+xn*%dm8DCD{B@))2$BJ!J~7slhyIC(IntoLv1mhn%qpfb*r zYxmI4W0QMfM;rbe!?7iq49_3Om@u1Jb!7|NH zfuXQWl~q6&35+HNFUAc9gM}aL$fN~_CnYDXK62I7iEA2?S49(>iMI=VWj>tN`>tme zhuv8WMJNxFab~g6{N*({U^>Md9%S8;Yd0gxl5i>YV6N9szjUg=plMqG9;i21!4g zg9B)Q-0X5ivrC{DDL+Rp1PPK{q`ccwUVL6=D{UW{%531>B~#h7GFdD;$>BxHoGscS zDO}kW&DJ=OxJKYY;#w(gFun$5jA;AOMIqf(0QKmvS|*Uog4 zbDOF&d98-)7{fm_L%AHwYJf(_4znC_JJyOV!9EfQuun{5j3%}bn2T&)^a8dO6z|$< zL~F@G;JoDI%aWl5s>t;{8XVXa9GLJ9OmByN{0U3mQo%t$ak!20-o_M$IsR1{z>+2! znqGn`b0K#;kxO7ck*j#E1)aUkUEl$EoN3BT!!pvkfR@a`Vpiyad2QyVD~^do9Dzk3 zP8}1Orshnw_N2m)!VMDN^@4A32ZC?%fgECDeDywH=A3g7>!tyj(|Z6O5dwm7h-XG$NV6Dv+#C zpcIcZ&#St(l%7SZd+kH%S+}Hf<3ggJfJWRHE4cwg9%s5ft!9p`+~l;IDZbf}CNn#| z__L|N1g`F-ox4xHomX{jwR4jX?lqm$axzX`M4TdU9dXJC7SHdytKOI>ku7~t@`6i} zq4{c4FFG0=&=nkz@ERX!!CT~UriH_Z)W#YCd^Qja5SvMGdp9jfe^jm@0Bu%>PAm6x z0(B1I;J9nd-~9&&hru3n0+Khx47-Gwj0!*(m}@O;oVuJiMIcI?GP;56{9XOqOL*`h z81_`)K;&S^AsczSb9d$@ynTfdrMH@goYTG@IjY62dBx&@3g2w{$P@ln9Bx6EnCs4v zbKT14p6t=bV?0=>7sdDbuqcOOwBVM(XHJB-!Rjp*wZ&VTNtuY=!kBx+esc}sSS-?* z^0(j`CLRG-A(9JQv9rPUaTTs5V+|iycp9J8nbu(p`2uBkt!m+^WseFTGKHX zX22do%R@iu z%MiV;vCEW@`b$BKv3Y_qfTp$0I)VEff*|68lA+luS?8x97%YJx*jZwi2Yo>rb1I2B z1okKbpmec5m{vKVyV*2Lyl3GBS-Bx++7Qmqm^(VQmlM9yHepsHr!c; zlM@a-+PTXR0NTmX)`wmu_KLJ|9K5Dg202sh><9Q;hhp5&O@^u&P`W2 zkyC*lsF7a0Qc}Svy=QvfDeR95SBJ6UM3!!1B~SLY3cD@GvW%@lU+fx?Ug2}|eIcqw z^=BHDM^QDR!c?D_<(hWZnq5xKU}}WEhzbNEY7j{8Rai|`NZ?_r!fQnp8VlR(C)HPb zsQtnY(dP^cWE8(4W62<47 z36`d%7pCQ@j3u88o;bO6!2hVa!Q_!_ z7N?jqvAHBIlTr#kiLo>(>p+1UtDrD@VU^*ftS9=@2l!FSCh$pO%QTPzZ6Vll|L~LX zq-0MxagK(pR^X|jFQqM|AAqhy4=F`5IGoR*WZ>PBJ}fp3FVE`V8>~c~B=p z=^kSmUtVxCTcNuwQ&mpcD|xabl76C-bmziWvd2QgxLpu2ca0Vsyuyc6*W6Zv_2V?- zWVk<4g&VP%ym=$<+lZX-HZ{l1F>(vBkwAjjXn2ei%V=)mk`>7dIsBv{xjLE*Z9b(g zkR1Fvc!$niYCNS!NY6WkLFC>`D0ZzIr!BiyTD`sX9PV~4uOo8tBv;fXLlK4l*#nPe z5AVtzo)|g(=*T%;Bj+T7a}(aVLg%SMEge;-Hx_#vOL#1+6Wb!ouUxUf+Qc-UzIkBX zfE}74q*mHZMBhU!BXEpZHd3&RSS0Mt!&su_9(5*#43GSW3gve}n$7HIwQBKGRDfN- z>UV>e4zawKcue3Y#A6CWAyc;h{S@J2oGgxGk-+@qtSd++uTQRU4wU*I%^up7J+$*y z@g3|$aAv}5d6X!&&{PeE)KH><0*N7vE=g?d@ zcd^nC-HoF2$TU`YC<)67N&Jgj$jmL*NeBvL-Ok^28GEf zJnT_{kNDwR4b*oEWv>Qw@X*lYG=%M!ov&hJ z^?$}L6;L%MPw;_r!8g0?SeD#Ic}F_u9w5#UcuN(he!Dgq(=uXv3hY9J$nqu0&{CCw zPH|FIz7(fBP#L}0A^2BuxXoC(+Z^w7WNPuznjba!$g=0o!~B+0Ng(Z0qZ9at!pEXP z_fIsUH04BTEIG}|$9_kHL%M=P65b){BmDpKXBsl1`ZKLsG%O#bHBc?Ob-d<^(m)H@ z>M1(m>qD6>8|ho0!tx^{2&VeZ>FW|lmA$&stpCDvb?yvng*M0Wn}!8-?cL>}C{XY=0Kk6rTUC5hm)gm>E6A1oUa zmo&%cO)L^|k&hCC2!y~O)pa4}FO#AFfL_{~+*Nqwt|USjGFyC1 zSG6A}b`j`9>@s@p!jk*5+J|soCAjuPL9rf}ClBk)F=c@>Xi%TrtYrF~XV?UetoGcg*C+L>5YWtmn= zRk`&g`omOTj_%?~sxbnisK$)BuWV6c#wn-Iu2Q4BkapGBgDbH6K;YR)yuVOYa*bn4 z!IO6v_$zrxJ#cz{hPN^2Ywp(@!PgYiCweK5K2c(v`CERj9qVU^Qv@awrxc$8@8G-j zK&HcE=sJt_f3oZ%%a%vNs45snTvd)9%ZPBJ*Sq!6_xo!U|;>?`OgFn)jys8Lg4xO@8sKe27DV+yG!xM7*R;Mck>O~rY5PO@?o39 za&Gu!?CuI{h(EHU8bUhlO73C+JxvTDFozhTxG87@*S%T)5dlsHTUe0r1yx7SWeze) zfan9OE=>9|F^Rw>#3Z99Q{+VO>WPwlTOS|hSX;vT+`0z;;Z>(UdG|Ji!J0=hzqDkN zhdOt8I83AxScvlJ+bDJZtstNp=5GN}YdoZ;f^o;@xW>qaEd*bPNBR!~p`d2fY56eBmBkRyZ*HRU9gtxkiM>eF z5vX+tg1KVwLe(egYO6}i{0<2GyT=)7S&P<6B9j?*DbT;4#+D<*76J|Kl`fYJ@dCkl zHXfa`O1GAL$PYlXKG4&v{f9&!ftaJ(%~i1f0c(V;#ex<)PFeBY#25lJi|NwZnH?-lCOWS*~hx1#on~!me`^u^mv5~-b zVxwUnDYLy3xHK(=_(5PN@#EYWgvz=V`nq@o8wZ>$1edmO)CufHk<|$fbKS}un|3olHFaJoHf7z4 zjV11tj2$qIu*&obK2F>s@BwPm>1Lo@$g=I=a7SRmxibUZBqAK&Y-{L&ww08XPVsMu zVger|k^Uv6&U(bFsit^uIYXvxW1K*gzJB9U`rlJ|2|VJEZgYg=z7+-@kcaHH&*IdR z`I!!t;I+-P=a;qno;hmCj>{dw(rfRJL_dL#k-UxvQN|pU@Xgb9dZo#kYfonn@^it5 z!D0914j{BytzbFL+pWG~a3+gf_DHnDP| zmp1-4VgrGLRM&=1R#ulz?Fvmjko8Q-p)F4jO@?SYV)^An`^pKtLLO(j)~&FxwR$)f zUxSb9tcV!v3Ju?5FiN@Zmi0f0W&&R%nibEDh{16zqLsGgdDUxM(MvWKxp&&xEhpiY z4L3a)G3>J)IX%RQptqRa7F z4?3^ISw8{x>VF`>(oWV5g1&HwxUXEQcLLu>z4zRJt1z65PQ^Hx^Ly5YVRF7_+~X^s znRU3|)0e(5HnC>?ccvVogDqZcu@$mvha zNc6%f+TK|w@KfSc`q)`84EroK94v4;$Ih8I-I9#*X1NKYIrQ>Jk?At(988oFc#SAk ztTS`H>r_PvSfdW9@KKF&wAHIboMPd6h3no8?=-gDnohAK!eESDBJ?33-##WAPFx}I zTc!SkdAqXkg=n(E1aqDkd%*wr1&-}fLc4Qz<|MpD=|N=_jc^QXU5y>T-VpY zf;>s*y2j{S*Kog(%35Q7O$HZ~9ebU<>_`#`0zD83J)crMo|Rn{h?BbUtaN&kQ0nyb zJ}6P#S?KXpOagzSLeqBs>0;@%JBQtv0Mq*5ZD zfEP7ps&r-OEr$iXX@PB??A*ZcK_HQ2YM%}9s9YEiSaeRirFo1Ge%Ij;4ZwvMI5r^r-7y==Z1mz9%^?rx>LEsBrxhgJJ4gGv$l)=6IY|kO{-j_^wGH z%2`9mo*4>|%4}QI+}NyR^JTNaaFd|gAcGKxXcjYx83g(eGe+aGVfPyQA}%;IE*ZMg zl?V76dC-nWc*#iyj_!j*dWH`LtyI9j~1qWCX;Lw4_Ct}HzPWf84 z;kO-Q$Xb>Ie6jE3f^ZR@(h2k!0A>}iB-PYhkRXju#Ugha&0Z@mdnk4en`-|bDi}Vg0*yh%i z4T_SG3Whhc)oEo3wrBf@6cgiX?KBYt{;+MfgYGfLor{Tj+U?$LguaaO2}~r`7~@Xt zA5fFb9%-yJ5+8Ek2j(adPsf5oJ0r>9n1pwXXhbTDi2Hb@r)MbuSOh4Je^aEsIRhAJ zU8_gy>m&N&2s&t9zN;E4p*ERc5qD`JWkfrHX`o%TSH%3EbBfx{eJNYS9UxE@hBK`$ z+?;@>3dz(hC2lQgN@JBnmmAhyUdt)C#+&04An%#Eim^}s`v(|%uE~W>lan*?IU3uF z`;w!TTT&}1T(;sYY$q+bDe-LYdE>kT%`+5&3IC|1p#%67% zXSaEysZ)d^P1~-mlBgrF)S)zl+cp`xKqW{{E}l*GXsyjPBwdC$nS<6KZ?xw=d%A%L zBygoe)WvwUH;=7aS?^M+$9~8r^G*ZX3-}TbOLLLS?QCfa*TgnRvQ`9u9R;k$_X@rayO&dwiUtoDK3`LoW>=0c?q_)^vbXnVi5VG_xb^yk7b)yM0VR6Gdta4ZY8n_ zY;~v=Gr<2pKu)YRAr3CtrNrb{PFu@K7`BxdM&M>erQ{dyYA`n9lIuZok~0=L1jV@# z*V!~Cti30fY-8J5i`HXH82bLMO{X9XnX=L)rC!Q%V}zS`n};#YDde z6xl74JBUyM?{x@!-3u#mV5?fwG`qqUN4?&V z#-RI%K?L?G?N_l4r7E9$5KC#7^llrTSEI2smbuMt*}l(Q*wSX*)5}_{_Yp4%e42PU z8~#E}@)Qrce>v^#O@_9~%*4Dale1Phrg{b(4G!xH4oi54rK=Xa^Nji)4Ks30xGf&x zIV{5|C7M;52XYS)O5iC+t1>O?={7kz>9j=*q@B%a3v-Ghpno6#EM_?^aj?GlzO-4_ zVqtZ;OF!s3yHdQL_(0%`O5-UWpDZpty&8A@XsNU$&*FkMg8{IO{xt?XKnx)8Rbs$+ zA@Qe_^pmUEcY{C}J*D{2Wc0>}#T9Gv+ZZ#9d z!dS_(;!LcGWf^Cp+$W=dW*PUzvXn{ZtXW3cXhz;`w$VLSvLfJmZ>C$W6?>vaQybb) zsr`)+9RZeB-HWavC}#hI2&RnDC?b{BfVFb?`lcSDI?p3;0yHS=7$|Ovq5|j;!AKvZ zy9j)n#N$p}N2g(orHqp~b7ie$5PJ5|vgazEpZ)B$N7i1QxaRug+VGLuhD5X_S$o5g z__h-s&yC)Nz8;UK)w_sJd5e9DRz97z4QJD~Gv`JT$OtXe8jaPj31eEF&AQ3pj$QG7 zgqTJk38v{&DaGbE=}z;Ip~pIMP8|ZEgo?;$hYB?^LJBq3XBhtz%T&Zw3Nyqt)9PjN z@$V^9qVz}@5hMzIkC1q9SRYYZYD6>9r|VL|780w-wpM(gZBe+fu?DLRm$t=fQz4mL z)VfVi(i_;NL2ZZy%M`7>#1{hHBw9;x*$6rj;&Wu)n#5ICC+A(0sEQuh9EZTPc^8nR zG(v8WTI^fNa4`DParKyY_tn@iuakH{qOQ>tMlC}2ugXv#i(MclTho$Pn< zfIRS^sJb(@ddD&@6v;OfB}=^-$7*QL^|88CU} z=7YatRAbEzh)r>@J}Me-jn-NsWa^i~mbl}VbV>RGv5CN&iX;_}OBPQs$2#WpKw|Fl z6tPUXf>rf6if^twIemx*5ld=Pt6x0tr7I;}YV;3~%~z`2XEGD6DBX&QI?t=!2X(fdRxJ!{K2M=r&_kmE~Bc7tY=4lpRS5BHr?jr9x&czlPiyz>n2x5*Q3>K##G}vYmpte7^{d^(YU>OvdH|>6?@d?+dlq7;uT8^E$NN(2yu_V1;oAdonmA} zq1%$2qrrh)!GQ_yz;qVAt5ldZdRiLQo3_FyXULQ#Y5NT=7Bt1pW$<*Actv13c-3Pl zve1aVMaj?@v`X@Gn-PjiC=p3oLozr%;T@mOCMju7O)ovNr_l2iZ*$)ObC4O(ABM0C z)n#qYvLx2lR2JLVtjN^mpxf?rqtCDE1m=+F80;t*kt`TxEa#H@t6Y$rgw|(^tGAYO zNhO4Gyi28~3@c4HhHKNMM(^F?P{OIbo)|R%`vejkeNWwx{aSy8pdr$NV5kO!ORq{v_+A#RUX4;2lJH86$YU-VN zdQBTQ0-Bf>(-Zg;6y5P{+n*Cj1eQBUGVC;LGiZxTkt9i56kMRL53lg_^x8$7<1JvU zO;l0WYpAY89ovU>hD7K;1udzpmfq#ym&7yzD~V}_<476YiJerRD>=ONS$r~OjXD&v z5AMz@CR!bbjfoI0I~(=az!`^_{hByNKy&Aq=qg;7*q_H7Q?~6tnZTv;qGd5l1L?!A#i^nUJbX=IWP?v>0p=punl4l>2i`EbDDT#%g>b?4@RNBM;8Ed-qgyqtlfQu(a0Empi+kbRKZ$b$wiD-!!L0HD3&Fr=B8OKc=WEH(T9u2= z4_M$W@;LK?WX*{#3~#6118OC$syOM)iM&%XA_Eeo6S&PGLdK-%%HH<$Ij=;>3e!tx znxng6e7RlEjP; z%L5K~zVoAyR!^d879l0ViNR9h;=c$I#RTppij^4*)BWlm9e|Ek9(eE+!=5wbuQ>Tc zx#bzNywx`D*u}wgSwp4R?n-x$~U94s zr0Iyc?|LYEO}795_t_7`qgxZVG890`ld=OYTfE=I*8H35vZ9=^is0nA|;02yzx%cP`mB!?C}oz7aQzxjkdY z%N()PfP*z&r0RW*zzG6>Aix@fJk>O_j6+0BjzYEQ1inJmyBU|^(l=eX&Y1G2CLFpr zIb-SbIUH0TPOhyvQWs5Z(vx-ZMB7ct(9Mcj><@K#?_7B-*uOKF4313rMs^#YQV%|o z|4@EHnF3Pz2nOyJhZLYwEL3=>!lDR}tbPcPF$s>P3YGw=OBJ$Q1xViU zuL)2^rmI-d28E|9Ru}dzR$>8zKAHr?MV?Z*ExZc{bO)lOShy&niA76F*I0U(z&A;{ z-jC~P(xrTe#E22>UC55K-H6cho4v~@^n8nVIR&C$;akIj=vS$M=qDGxeYr;`T+}t; zqD1iGg!kg~d03)@^|+@uA@sVejB(%3^=)V@C3Hzf=qPzI_(TbIa?x-YEWYE9dCZi1 zU8*Z!tjQ#6(IY7+M=xxI+-A3|3~%EtTv9oNiY>*lY@vqt;}vo4u5P~xBs>JVNO)?6 z@ECio=J(xIkBuk#^t->mv9F)}df)csblR(UP;$}QBkML``9gBtretWdqMEXcb`Re< zymR8wK@+mNUU58wq{h}H%0Y*XBM&i8{b}AK?z{^zF ztHCHySe0XE-j8PapI1ccj7U{w=3C#7;-oSo$`{sAV%A`yZ=6n45O|dYa3ro7)7`@F zd|+uZrlzTOB{Q) z)_fyqUEHQ)6-2Z6lAk%;bd+A+~XD zXpLdkE?ryXwkcO#q+=1$Pr#3!K5p*ES<=P_XHlz@g2_xmP$M70%_?35^9*!mQwrTw)z~d2^H{#GF&eZ4=jf z*%PFUXeUrWv@3HkVkFet3QaU5dC0NK8T{6Ur6kknG}a`ulJr$hPx-FKuW|;?GkS42 ztRR{R6cf#(L5N{g8QQYuP>pjd8FPyewM9rr!TjFFXzt^&bVtG4@HDx9vCVCarsP?^ zClD?U>tlY3=gAt&Nyh?B{JG6}z4M(9)IAQY)@(nN4(!aGw8MO0xzal{a>28cSu zQyj8%kK;I9$E~{j#+t$PD=T^plWRdE_9k43<^0XH?4d2qNcm|oNh%PgEBf7#UVGSe zC9#vhC}QVW6cDXx)I{>m_V4ocKjIyJERcOPFt{r)xN~tbFrmFqcQCtsK>E;8np&6R z9V!dlM!Cw!R<7zWS9gr?)O++OUIHD+4ozcx%d{=kBM~OM)SJp~iZs=He zkyS(xf$>C82`+#jZ{Vo6q|00KfrifQ$$q6j@J>8Q9WFf$0@NB&h>`9VYH*HWx}^jc zw6!+d#_H*-MXQMl0uw=n{xnRNbdHl2C!41Cpy6{odv0j~m14UV(7%s%WEaUW(N170 z)nNM6ifGJFv>m8?{5Gd$Z2MHCRMlY8yPjEAaIkdb@COLuPPdp`T7vIU;bRVNAO5H% z4iX@DvI__0y8HnLv1z+)2Ti-l?5g9=Q2Q|KAsEaWR&6y#mg(Ud8P%w#H<67*B!PKE zq>Jryv7*pVv7r7A(d4DT%tD%u*g0-N)*^ccPfpp08i+dtE_W9Jb2` z$jUv%*Ry*u(k$~zI?|Q79BHH}-(I$6a^zGY`UlsKn3;V>mVPVRp6LIKtz4FD2{*Q3 zWggG!EskuA#-i+N;Qf8<@=$7guQ?<``zXZmyWoIMpYTf+SdXv6ON~v7NkwAf1&8on zHWHHwTuCCd1Xt0M_8olx#qGm+b(+`(=DCLF+n#Mcvc4*DZC!GG6C>D>yXa9V$99^&%P6S`nRSyXswH2{JS^73TWKF9Wgd*TUE)xhJbeZT6HL!*S=tFE zTB@7Mrj#+QL8vjU5oqB}nfxmv8(UKuYnxm2%~WlTRBhRGNqmGbvrXB;h9;7^-b^6s zuZ8N5z*SU#wW9vW8Xn#i8ve21zCpnT;^+eoJ-pH8QneM>TMEpJtZTFI`CDLKI02pZIOXekKGO14&0&-BehiNlZ$ zt9CW-APQnIdZn0Wbx5gCX-LlW#ymxO@_fbN`1FaefMnoZdm~ez=yRU z8DRy5GS^>TWa8FYyjSX&z=mS;T6upHv(A+>Dgqk@nrVEo9Xz5#PR(U*7%Xx;N|*q& zM?lMf266d+zh?}#C0JE!yoevB#?=?U9$Gu-UInIbd-?lw`@K4S_)@W}Q^89b!%a1H z;rXcxgy1iW)<w8{_kVh?^@(^k}Hv?m04W%Dx+p44j^B z$o?zEOJ#?#sRV_;Z`5ysY%4|7Zzh4i1)z%lmE^A7^F;KJ_lZXSPnz=bl;-RA;FR(= zVz-)9ptY?9O9wKVuoWk_+GnY`vPS(b?h>n6-$xjaM9lq7(kZu$wEtJ#w?@ZtTxVkN z8~_6lBtd{A0FnR+f)rl@_yQ?X5*`C^D7-Yl;6YLZK@g-MfdDfEB~r4qknK2>m{?R2 zM{w+{=txeeNQse1Nw}80!P?#vI@WP|)JQy@C_3Euk(0HvmPP1z*Xv#H_f>aSSI_hS z6qlCd{_#yuRdsdOty{OMZr!@IJ_{%HooYeu;md5a8QlEZferen0!HYI2o3)UK`8t1 zsaE4Pn(Zf83PLwa@hqYtcGJD*i$2lvyIr5(ez8?gFMlgHKeC{DYKNY?`-!#R^Oax1 zk)rFh+zk_J-^%u#@4iq1rFq_x$&5Gi%3er|tl52~Nnh2V`M43$n|J>H3k%?&si6E) z;~($;!u~f4HtP$jO=X$b+g^L+o;Q|U9sedAZ-mt5z4&6?#beJt@XP}m>@hs$i4`fk z+yf|{%4dp40A=M{2~~70N~q#zQVCV`ElQ~3Yf=fF$B4rgEw(V~UDUg+w_7p9useKd zW&ythcBgK4Id+)ra+GxTaKTO|8@!TEc1%i`)Z}b~^S>8imDL5lKsRrDAF+;P2XE5! zM|CZGo@u?}9L-n;8gJlKEDJx>DaLYe(~Jh(GjJ}J?#FYnO#iru$@Y(%5eB2OJvlp= zC&{UVL2~LP#Di09R~)%3FQw|at0#)z%CERoqvx;1db_uDGN^l3f&JjrB&_FD@buI2 zOBH%v<-{^Es^CHJFD$wAs9wHxDl~mS>w%B|VVetS7mP9wQOePwyAD?<(`>4JGHL+^g9o~ljg}D@Vt}aNgePQEK5~|b;;i8_YiW+ z#vW|c;<9b;6;_js0C{hI3tXkzY$h3ia^4cm=E2QMHDjh^RkJnp6?B@JpJ`nJNuq1*2);G~GX+8XJYzC=QMjXLX-r@d+Pe@s%093paPv{ejjG0DP=ZD`~e zG*V`TL+Tm~Z7^}7Ug`@hFX1=ixOi*Cw{;3GxShuwSZhKuoLvr$9>|v5;UdDKy zgd#lS&KL&0UJp&zzJ|jgoCjAs^t@_+E{C8u(w~Q1kMLId5PKLW-(mY0Rno~}-23j& zE9YV~;a+rzP9>d69!tNo2!2Py4_XW=6hpDajpMv)bBntb9hiY_OO2VER+b3!Y?=!1&ygaR3bd;=}ko- zRSF0^k~+@71F2_(2^V-UVZ&#N*A;dexQcL@LQJHK{V3mw*d z{YuYknBmVX-E?_aUs|i$K&w5mlwlv>K@%I3lCu-;DkVL;#z-Y&!Y_>XtX+(!PCsJl z=M4Ihr7-6)MrU6l`3TRGeCrJIaU`}k;@f-WgqVrkuQw0tz6TU)+5G%rQ)hEh>dn}*IW|g%`ZjwRP1Uq!&jODzI+lM1qv10nM6k z>#@TD>sieAmn1mhPf2iNY7pJtFg>7eZ=ONp-8_?5eYMMMzJ?#0nGJVO7wa1WS9dv# z8{XcyeFjeChIKD|EAPEh129IU$Xs5sPW}QxW}UnasvsQole&9%O3E?RKyeB-oY*v5 z0U2o5n3R{H)ZM*ydb{Qelr3RMczw-0~VOTGvR`=p0k#^=WP4N_=^EBLJJ% zgj(;X3=n!eb7F#_T;tFvT{mxS6zp$U=b620_ze^=mN_a`Sz}o}L+n9M$MVdZHduN- zlw{@P%d9NIE37P|yNr7CFP2}(oy@#c{y7+{uF<@!-%ih^x~}I!>12_fy;4hErDd;t zYw_~Q?l%{&zH~xcwE2lm*A^8`Y*L&7LX+nUx;80Ecob7=H5w6`WI`d+%Snc!gp*-P zL+kX!>9*&oEceb;>2PHysf5`~qv}TNhN$XBTsvVHI=OVsFm!SWJykQRvM-rCy%P+c zF4>XFK$cK&6Xhip& zRJds6+UFko>|>XYe`(~!kt_SZy{9Fzr{&^p6UA?*=SPuk^Tlq>SNcTNHDAF*6}I6` z-llmsYo5)9+@P$mE@@S_N-&-!%Pm=%i!lff31B$}&TC%oi9He)Ui9gAT&}C-!fW!30yqeB9+6#%$I|W&LBS z*di+j{xb#ISNNphL{dfcKz1+mRYnrtATvIX1QRI~Yzr^s!2bSx&RgEx^DVk}*<`ow zU2O=tsCU7W3qHSf^5M_zxx7O!sn$F-nz#C`;+2=yzFEBP@*b_I7LUGNUHiLLlTB|f zs<_k>S-9!SF>_NEw^6@v=JFxEYPYthP3tw*m(S@Z9>HwlF^`|KiKf&brxA~NI>l_F z%Y8N>#|!vq6ySr<63HW;q>{)q|27?~d>*49mvQDdNMyo4g2+iUMpD4XFRDtxJ+H=y zj?CRgNwR-c_dQEd4bFAl6^Jn#79$7H>QAI7%dD1h>&$ zZ#ouDK^x<;$9MC7IY%xSi434cx|d?qgHcE-It6wEo^&p=ieE8{!<0r{^Y-jhZD&pzT0^$9SZ=8E{xP`A4~MY|lW{6I_V8)^V5R@` zX$mQ$5gL<_H^>}>e_{*#BgCRRF!wZ4>Kn#!m&d2NUf({wOvh1>z7|E$r|11f`xEUK z2lVvfXm;LP3yLS#Key$xTOteAPn3KoyYNEU#1ivI^dUxWQ$tX~?9%sQAC~GW%-ACv z%`bj>?8&hw)?dqCFtI+Goqzt3i`iQC@=5=t+b-?WN;j!p1-@HeEE%T(miurS5lRyb zk{(L00P!KzGsImg#rr&rkDN+Mues}6dYKf)S#Ffn!A|) zo^;m$F|VwRhU@GrI7jDRr9SQ1B{G!PM~bxO&W_;F$+3rECt#|}4M`Z*@!4Xf-btee?P9sz9^cC`J6dsut9uQZBB^_gG}RZ& zAv9S-V=smWCh0LlR2;H&goo+h^PD}RR~)h!=9|L*O3W)${&!~kZv@wg;=iz-2nDPs z$}=!%e#wO~m|f&8xp2VL4H>oe>X|DC^qu?OsMI?8^!+%a5qqZ8389Ps3)AO;=B?B` zm4;|?t=qftg{nMNx@>%0{H1Jxk+U#a^U89)44cPj7fJ`aW^Hb;!(6!`l(EkIFlxB$ z@oRg=K~|x-F!;dC)VOSqJ>(hrEaY`>r<+lpyQv<%V;o$PnCFnk*#DBNFwqL5{kk&| zJctW_Ou}aEGsrOfKgcFOCWxi>Pc!T|z}j>rT>E^N9PbJo&Dp-zwo%0y+cdg@jcu9kHK=X^Tjui zVMG_6)CrVg6ebyHo-rgCh{YF|J+*K+fs*1t5i-(1t9P4XI%cz-V+86dWMm2m8CQ2t zNxbz?9i8BcRrEgP4Z6G`{;_~;1IlH^MTDfc9`THC7t93@DmA*Yc#1UN#Q4Z2~sMX z1V0rRd8i0}atqCJ3l)xh1eawS3ec}2Cu8a~539}LASydNO_8&jTw^m|bWp_LwGM5lu zzohwxxtFG4WN094_<&1db@fBikWdR6Dtl?v5i4SE{9|vztjcmmI(B@#3$7AyG`D%; zin$Lye3l<6xPUZ6-(>Vl|IT2-Ue>>2F=ot`b>DW^G3f_cG@l`fvDUP&F(|6wMN|DJ zI_1PN{g`DU)W?;nEaEGhJfZtGxt0knNnUbZ^>GBbjT zmGbOA=-xO73 zp9$;ac=Lcz?C-J;jg95V+ZN@1pCJM{wt)z=gy7Fu$%IZ;vN`cHXMFiZ-_Eay!2W)h zp1%nbLHqyZ0X_eAgiwVcH-qNrH4R@6UEQtwacotO+Kv`Jjb$9oQ*5wy=`iTJ&MjnP=4^`+Nl z8ee2xQto~nA*c!~JjG38t!Sy``n5uIyCUQpYzr$)In2---j-r6S93G0pqe@26y%pQ z#`2fYF=Qb3@D#W#mTjL)vK%tS5N~XsLcE!SJTH?IMo8VAhy`^iw#4G_*(sl1wfFTi z(+BjsI%a|gw1fS6@Q8L4ivVGju5uATkg*EBM0 zFr7R3(iQUkDT-l`i!FrYGDgI?Bo^VtO&qCK%`CuhT;om{^&X=iH2;7|qTSjJGvAfM^zK8^N1=w6O)JEXxQpz>6ktY|m!nH+N_IaN9a`Y^38GHf9UMR=5isv6PG zn-s3?)Lhgvbsd<@34406D+F8V#ztUHEQcl5L36^fRr<-XW2Tj$v)n~2H(`S1F1O2V zXep)(<9!)g8%5L#|K*o>m8{;x5*v2utXM~pGvK`gdlp2)aF%%)%S`z7xH4BqeAQD` z)0Mh!pKC3DkmF5ziV*-gn7v!Gu8cu?-!V$bDv>R}l!YWb#X>4N31g#^ z$5C~REz<`by=V9DZQS10E&hOLWCAxY?#8x1aCY(YC*#r8%? zDRVVbrVC>X)~>kR*5zQUTZwfNvs`d!pH!T`2+JBa{O~$}Wvy%bKe4TKL!-yAc@>s2 zs9ScQ^=2~V?L z%{36q-tAu9yF&A<)VwQb0=NIdg2`&#TMBO{nzt0TZZE99G@@5*eY1G$)QDEp0E4%; zmSAW8rTxz@cyq~?soS)|y_#pC7}OYMn^)Fq2_r)}f|2Y1a!FPxLa53r+eO7-+~_j>j-pV+%$E#}@LzpC^Jc@ci*Kf|l zOpD!x%O>l7yHqb&HBm~_pYo?ZrsuCPC*#s?7mki`0`fy&E7Lj-IrhLu7ZyER@=VF( z@#jW9J90iVT2T7gdoM1SD2?VX{p`Z?CnuJ}3Tx5_D@)B|dfSkVA0NX;D|*Q$+|1ug zO7+W)o+#(iT<6{}xsLQAya0M#R|KZD?bqE$y4nilIR4{CnPi;g+z(mdX%aLD- z?mvgq7&tzNlO>k(J{d10h-3V)g=Htas?@h~vXtQn{bm2ux|iDH)HqJhZFpQ>atU zC*Q{JhBej^W7#6z=&_-*!qpjeRB?*O{jcF~K_Eb(Bc^yFKrA=v2sK1FKM4ak<1!|2 zHLM20mst%#Brqp%=1HF3t4qGNVCLR#t>=h-@4(F9gW5<~A3SZHFw?|2+e0{L1{1je zY>M$Ouit$JC+h+?c%LDh{}4B>-FeE~8gqsEQtxBgL}4gk(_U(T*wrcv$aZHeQ(yr( z#clfxYRufhV5`~8o#FJ|cXTM+Z>Za7XJ&Ya>cELqN}D*2Qi@LY#nf1q`HWE`6js(; zdMB%b@LyOJb%;S#i4O0;8AjwTQaDi*-N9hO zH%Rz~1j28O_%^;An%eo&;VUqFylK+Q-utg^A?X!Xw;O`l1!CFBW^+kuGz7IW>}@+T zg{TbIr6J1#$8HGLal(#UKQE`>G7Q#ON3>>z{Yju5`;b@0(*{ zbOLr2NI}I;!0Le0jm1k-Cv8cSMjqBQc1}^|)#95RCp|Wj9EATya;!1Pp(yIJ^s3q$ zIp9Vz-pEasRVlwLp~7T#`5jC)cll|+(KC9?E_GOB z2!tP!2y1O3P#1>vux5S3o+~)srrDJMCdc9_WnlDy@xQfrZxx>|iCehkTNXZ?&;s_e zyo7h+S^!trUtT&@rLW(e?98tZx3t#zE3&j>@D4L~VOv;O!h3OrzG$jSGg@QD|$-F?~0I?Kaw`S?l^qypmP|!iq&5vj~@WTSf zzT-o5wc=cZ#IbDbwqsr^3cgU`ew!Y=1>u~nt%sB&_(-`eHs$Cc>GgfnJ^G&3t7m8W zgaLbB+%ci^EYg0+)QjgZ)69^bi-$%nmt*GQo8){Ir9RrkikC`5;vHiIarMdpbh;o!fA(Vh9;UoOF6phQ_wOo!1;0(%rTyWzW8GBrS_ZgRM zo}!G5U1pb@8YR(w4I?LOVJRQ?G4rSfOCmwtZ>VJU4U8UxiGUE=wj$=!eB2yBPovj0 zniOkV_V&j}8Nw=j_vsyo;taFk!cJ55#WNUQK6@og-*Pw3waWS$CKHbB;mNIdC3Po| zsq3ig1Ea1r@yZN8Kq?4I#?3xKNm?7kQPAr9(rIzvLcQap9$_u1S7T7mTMP#!a6lb5 zF@3#qI{mc`aYh%uiIO?^@}opK9-U!OE>5mX9<+2BPA0TSm}NyLjvj_dMZ!jfin*nF z?h2C$73mH~L&aZ%DY?T%)q;r?1{Ga}*q1>b<}UqV&(XJo|%AD2Eg=({XDM! zf5TGq_+v5bF!kNa5MQ+M4BK!omVsl-Pn`>Qkf?&zxM6#@#`hzPAZ#PG>kx?+uZ-_` zF7gZh%azZ!yt?kn9=%5F;XR=5hxcvl;T=>v59hF+rL``;la+CO0^r*Ce;LaRDK~1X zYfhb1lKM}ca%`3+U0+O9$jBkQMZ+=Dkg%IHG)HX;4aFR3$>lRImFm77$tm{XPK3-o zQ3eqbwQr|TJcsrz%t90HW}#Pu9OfXOd!b(Fy*%_hyy&{`hf)j5RwY=&i%?hAn8%>R zwXMoG*jis@hA!Ks5+-NuH#BF5R%ih88h5Wg_I~c5+#ZQinwR^@nAVyZ_w}Dhr9VM3 z*m|6PgP%5daus4!bXAUug18lvFlR3xrb~dBPizn|&o6<=9A!W(hsjNw(=7Vv>KG5Z zjjhL7y#zn2cMxBJ>dh~@@Bqw4l(jIsvY~R`ukUEaNgfY>bA{78gP{V5<`jNAXL%%N z`R7}|UAiMu3P-+w{n(#BrkDD)>}D;s`C9g(IXb_a9+cf6D=3396xg_I6Lm2t%dx`k zUwbHF*N;P*pnl{;*;z*~rWw*CL_#O_g69}aXea%*Jvz9#~_<+Xyj;0?tZFEx30hVDyX7E-l%Sw~TUyqZPgaZnHDIyl(0MF<4C6@KH}M(|O_WlxzLw$nD*1eU%3;m%Hq7m zTio_hB#VQE#QvFKbDAR>-N#YjIEBI|NeIGF93d1Ix&O-eE2GnJMctteZ=?mOtT9j+ znHU{DOVcPh#n3 z8*z+R`Z;38p!kz9$bSY0K}9Y&$mXI?@lnD9B%WzaNBJ$*YVW^%=J~N#&rYYk^4RpS z)^kuhmeiZKEYL@cgbqP24krW&n;bm#8z{bu)3x6sX$WI+q;W{|t*>pmx=cH8SUVBt zL)KQ{k?PjPK3WVXZ#8#0Ov+?sgj`L^Ozv{b)Ucheene?$>$4RZbe^PmlJFGa0sySm z86E_y0S)G2!y#jd%UGOwnyCrnaU>M8wtd*2-u`Oum1D0Qp6=3MI@Uj!%vbzJm4xOp zq0vAM5;~ixMMlv?UC0=|ND@6m5Hj9{h`+-~!nrsin(K;7URr?dQ>$MqyPB?b^=U`3 zgHm-}W%J>!9c9@(CZ{X&j!`jrFkCq~_xTy*<6=eK>H3qW3;`$Yfy{wu%saSJpZtY}6<~FxVWL_EL>SEcFJDCQ-gr34NxC(R(500M+tH!vW zM*Dy|SZF0O+lC%S3ZqexJ=pFb%i?no9Y5B{>E6TGc?fFnQS^@_Uz0w)oQ5VEl;hp_~ zwr(V8jIBwQpgq*p-`><;-yUjfj1@amh1&dWb@eRIvbcy&WZh8L*5Gf6FKS0!*S>y! zdy~j9u27x$+Wy8sXKP(o!#?3bFjnNuI?!$sX{j^3p}n=$jEVcodXU|qYXXt_8~xpZ z2EX|&tDQNvwfDEQHwPM=iB>ohnHdB+``bJGZJ;c zX!WaASk zJ_rTr>Tj&;s*C3bKN!WJ^djeXpbGk8abZ1mfv#9wB?j8~K@I-S&iJeYs0SnKxR2@V z2$&IZJRa(-?{8>t>k778%_^?ZF+qK(+ZxS0;)rZ=4+$FIPDtPWpueHJzlG$ea1yjB)Yi}yXm10D)-_ty6vrM7 zsNg^Ygo@x3@s79@_^{4)$bd%KW4VAWhCQF9>&wA;Bq`^#nv@8BHvEO`y6cU zh^YtVAp4rz_&!IB{p|sK#{!e|{0_m$OO${{e+McFEzlOhN-0Bab=_!~l#!C587(Te zy&DW2YLg95E$2ReU86r3vm}y|C8^X0rm{2MtbC41-8wKFzN;Gy)QZ=DLxSzCmK3Q> zOz)P=lDm92L{QM*)ZZ0o^~csHKHlYTMK@Fz47Bw1t3_U{BxPxvTF{ND`PP|C4En_i zl*C3$w^Fu3IM(%d^>z6BTie^(V;23D@L+SjB(M_P(B6XX)M}DSM0-O+sH3mC9wI1d zY|Wgp+vbd|WvnG|6W@FL+|lCA$)Daa=hHRf%aT65b?(f!&Yk%-QLqhWRVfAYH#MOf z33Q`J3H16~`b9_HTGx3`Y~u|k?%Wq>>XMB?$r|EGWMm0`C8_~q2)pSj5#*EV4%w*V zVrr7cZ0m4iBj#3{EVEi$-o(A8`gS?)N{BJ!U}LgOt80=zS~K6H+mdFw!!4%1uCF=h zS~|o8o0G*f*C&gq$1~O_NGZ2?PxbBnt$~g}lK5cr-0{uzbH~@q=dFG=@%?TbCJKt$ zO7axmnk0%ZOcK=`L>;Yc1jcvlNKX4?QFwE*D7eR`Cw928g?M>)wMA@eZ0ICF_3a(-KIy`C;zR7G zU8)Kxw(r>9;aXMAK@nw5my~z*g}S#@SNGTUhx+=u`}*7jC6mumQ_S~eBB7IJ zE+ZiDTWxyU!C3$usBkJFIxGn04*%Xoe!4^Yr@G4)ZQp*JIvwv^B@_ ztk`}rv@-r8!uXpnV(~nn($@9 zR|sDxe1q@?Awu{ELX_}NglmNF5q?1U5#c)FJ;F~3KO_8{@P7#zRG4NFatI3uLW#PB zcgqN?2~~vK2%8AE6Sfj|5Oxvv5bh>45$++h5jqH+gl5qb$cKq-8fFhCe2 z3=vKc9weM1j1wLvJVJP!@NvQ?37;aICp<;?O~R)M&k%lx@EO9hgx@FpN5Un-7YUaM zFA=^(_zS{c6TVFN3SpY?Rl?sA{*Lf1LWD3w_%`7!!rO#vgzppnmGDEtzY~5!xK4PF z@KeJ7Cj5eshP8okCc#U{A>5Sj@ALJJ{C=p`H?^b-aMgM{OR`w0&aMhK?}pCCL*c!uyS;d6vPAUsF-0^xbW z7YQ#BzC?J1@Rx)y6aI$qRl+w2;uy&{c_)tA^r{1GR*h*LJi zF%jat1#v)uaLF&+%M178!tb_lKrMVB3zxmZ6|L}tDtvqjhnKeL*m6lQx zT~(o_ltnAnXeleBRqM5sHPPjzT1s)WbcL3(EV>f0rO_35swBD$;YB8vAa-eVc^Ol# zTFo5R;@Q>Fa^$nZ#5Gk~O1YV4^;#`uRkRFmTyCZ>UCI2791L8t6h(*{sOE3PR#fr} zjqfq;t8U}h8X-n*#(m{FEu|uAyit9xlJZ&!O0+auhA&?pU5T7a&3hwU#YIae7DSh# zxJ#m|P>8bVaufpO0b!O!*KTB?t9NQCo1^PCYblk{WhhorbYqQ{vOZb_f-N>f7K8i+ zsGsE^P*HR#o?a5=eQ|Up2v_QYt5CeM=#Aj!S}kQmbW63CvN2kUZv+Fk^^oi2CJ{63V2DQ+^Na;c5yn2_mr!TU) z4~N1DTVn?m85yJf!sxMJk6VPFIVXUM*^RHEMdL%i9v) zUm@CNg=m`ebW@|&d@Qo* zn0Df1WYbAX##@vRD1?%sMVE^fU5*xwt}MQ+Hxh!Je0dYzXs*uz1&b!~q5>8!p2$Zc zqc0^EMT?3l-j@`y*D6NeRfu^0TWI`?E?SJ9V{swmezb52f@i&6&wkIv;n@`a&K558 z{5m!y-4FV(%@&dh~f7r&no#$K5B+%c+w`34}N9~_$<wNRu{O#Bk&z(;$CwpNnwZ<7c*XE%HY`_?ZoQ78wuYXZE%nBN2XPmoN1A z&Uce2zS(stg=;SzyX>E;{ZBp9_vw2(wa|U~Vzj4%+02y6om1miLeouGo3yS&`Wm#L zax1iV`Yf$vdynXAzz_^B-#WGZ%DQR))!Intkaph#dgwvzjIDY%Gu>12o-fl=`d$IxUBY_>R=Rg{GLeh&*N%w0%kr#!cTo;9MTO!nE_Uv} z>7L?ueO8j|Iq9C|*ZKE4zm$KA&A)a;x@VaTE4=PYM>;@}33zN4k1d&HF1#x=?=n3* zW($yb7KxY1SSy`KY(8PdW_WhZl4`Rc*mm#J82mobg^eLcH8e zQY4dDFH#>Xma&dI@gk8y!i%hQcC3A;5@IPoce$B;mZ#A(%bJ=cq50)jHtC+lvpyx- z&caTe<=Hd4$R=&Nr&4}(sl2nwY37gDn|Bt?(>-=#`|UPS>~!{>|8$CPYj@7GA!{>$zjLFw;}#F_})y+9s66_G-mil`o#i@@)Sp7$9dh$K%;Bn<>IX zV)Y5TT2=^({WK@nQ!%?d$1~uWT`C$=hNszMwhcRrxVsE|vC)vsh&yL}*&u6?&$DH= z)Qh`95wQS&D>CsHf(RhO;s63>mZFAzheeCHBxdEHA~HQoWy2H|X7Ql)ggbj=;pKQo z&FoT)ql=xh$4!vlSg=)1R Qv7P;m-Mxo*7{}cGKRj7g00000 diff --git a/setup_service.sh b/setup_service.sh new file mode 100755 index 0000000..325cfb6 --- /dev/null +++ b/setup_service.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +# USDA Vision Camera System Service Setup Script + +echo "USDA Vision Camera System - Service Setup" +echo "========================================" + +# Check if running as root +if [ "$EUID" -ne 0 ]; then + echo "❌ This script must be run as root (use sudo)" + exit 1 +fi + +# Get the current directory (where the script is located) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SERVICE_FILE="$SCRIPT_DIR/usda-vision-camera.service" + +echo "📁 Working directory: $SCRIPT_DIR" + +# Check if service file exists +if [ ! -f "$SERVICE_FILE" ]; then + echo "❌ Service file not found: $SERVICE_FILE" + exit 1 +fi + +# Make start_system.sh executable +echo "🔧 Making start_system.sh executable..." +chmod +x "$SCRIPT_DIR/start_system.sh" + +# Update the service file with the correct path +echo "📝 Updating service file with correct paths..." +sed -i "s|WorkingDirectory=.*|WorkingDirectory=$SCRIPT_DIR|g" "$SERVICE_FILE" +sed -i "s|ExecStart=.*|ExecStart=/bin/bash $SCRIPT_DIR/start_system.sh|g" "$SERVICE_FILE" + +# Copy service file to systemd directory +echo "📋 Installing service file..." +cp "$SERVICE_FILE" /etc/systemd/system/ + +# Reload systemd daemon +echo "🔄 Reloading systemd daemon..." +systemctl daemon-reload + +# Enable the service +echo "✅ Enabling USDA Vision Camera service..." +systemctl enable usda-vision-camera.service + +# Check service status +echo "📊 Service status:" +systemctl status usda-vision-camera.service --no-pager + +echo "" +echo "🎉 Service setup complete!" +echo "" +echo "Available commands:" +echo " sudo systemctl start usda-vision-camera # Start the service" +echo " sudo systemctl stop usda-vision-camera # Stop the service" +echo " sudo systemctl restart usda-vision-camera # Restart the service" +echo " sudo systemctl status usda-vision-camera # Check service status" +echo " sudo journalctl -u usda-vision-camera -f # View live logs" +echo "" +echo "The service will automatically start when the container/system boots." diff --git a/start_system.sh b/start_system.sh index b1c3f25..db61d06 100755 --- a/start_system.sh +++ b/start_system.sh @@ -38,10 +38,18 @@ python test_system.py if [ $? -ne 0 ]; then echo "❌ System tests failed. Please check the configuration." - read -p "Do you want to continue anyway? (y/N): " -n 1 -r - echo - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - exit 1 + # When running as a service, don't prompt for user input + if [ -t 0 ]; then + # Interactive mode - prompt user + read -p "Do you want to continue anyway? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi + else + # Non-interactive mode (service) - continue with warning + echo "⚠️ Running in non-interactive mode. Continuing despite test failures..." + sleep 2 fi fi diff --git a/check_time.py b/tests/check_time.py similarity index 100% rename from check_time.py rename to tests/check_time.py diff --git a/old tests/01README.md b/tests/legacy_tests/01README.md similarity index 100% rename from old tests/01README.md rename to tests/legacy_tests/01README.md diff --git a/tests/legacy_tests/Camera/Data/054012620023.mvdat b/tests/legacy_tests/Camera/Data/054012620023.mvdat new file mode 100644 index 0000000000000000000000000000000000000000..2d2bce706a67fe8afdf5358c32b58d378832ce38 GIT binary patch literal 55 pcmeYbb9Xf~HgR`em&RPk&cMu&&C7rTNU(%6JZC6k%3`u)1_0l@2GRfk literal 0 HcmV?d00001 diff --git a/tests/legacy_tests/Camera/Data/054052320151.mvdat b/tests/legacy_tests/Camera/Data/054052320151.mvdat new file mode 100644 index 0000000000000000000000000000000000000000..367dfb3ee8d32888d30828e22a4ae8bdfe5f5e8f GIT binary patch literal 95 zcmeYbb9Xf~HgR|EE}Y89&cMsS<;;KsWHWtY$N}P9rq2v{K%C3;1xSBk=wwl4>R?f0 T>IC8r7Ih%44x}}Jv<4FZ6dw_V literal 0 HcmV?d00001 diff --git a/tests/legacy_tests/Camera/log/error_20250728-153215.191852 b/tests/legacy_tests/Camera/log/error_20250728-153215.191852 new file mode 100644 index 0000000..1f3054f --- /dev/null +++ b/tests/legacy_tests/Camera/log/error_20250728-153215.191852 @@ -0,0 +1,4 @@ +Log file created at: 2025/07/28 15:32:15 +Running on machine: vision +Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg +E0728 15:32:15.057651 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023 diff --git a/tests/legacy_tests/Camera/log/error_20250728-153233.191852 b/tests/legacy_tests/Camera/log/error_20250728-153233.191852 new file mode 100644 index 0000000..a32f33b --- /dev/null +++ b/tests/legacy_tests/Camera/log/error_20250728-153233.191852 @@ -0,0 +1,4 @@ +Log file created at: 2025/07/28 15:32:33 +Running on machine: vision +Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg +E0728 15:32:33.490923 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023 diff --git a/tests/legacy_tests/Camera/log/error_20250728-153234.191852 b/tests/legacy_tests/Camera/log/error_20250728-153234.191852 new file mode 100644 index 0000000..f6c89e6 --- /dev/null +++ b/tests/legacy_tests/Camera/log/error_20250728-153234.191852 @@ -0,0 +1,4 @@ +Log file created at: 2025/07/28 15:32:34 +Running on machine: vision +Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg +E0728 15:32:34.649940 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023 diff --git a/tests/legacy_tests/Camera/log/error_20250728-153239.191852 b/tests/legacy_tests/Camera/log/error_20250728-153239.191852 new file mode 100644 index 0000000..72724ef --- /dev/null +++ b/tests/legacy_tests/Camera/log/error_20250728-153239.191852 @@ -0,0 +1,4 @@ +Log file created at: 2025/07/28 15:32:39 +Running on machine: vision +Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg +E0728 15:32:39.753448 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023 diff --git a/tests/legacy_tests/Camera/log/error_20250728-153245.191852 b/tests/legacy_tests/Camera/log/error_20250728-153245.191852 new file mode 100644 index 0000000..5eb54c0 --- /dev/null +++ b/tests/legacy_tests/Camera/log/error_20250728-153245.191852 @@ -0,0 +1,4 @@ +Log file created at: 2025/07/28 15:32:45 +Running on machine: vision +Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg +E0728 15:32:45.492905 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023 diff --git a/tests/legacy_tests/Camera/log/error_20250728-153340.191852 b/tests/legacy_tests/Camera/log/error_20250728-153340.191852 new file mode 100644 index 0000000..e43eb01 --- /dev/null +++ b/tests/legacy_tests/Camera/log/error_20250728-153340.191852 @@ -0,0 +1,4 @@ +Log file created at: 2025/07/28 15:33:40 +Running on machine: vision +Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg +E0728 15:33:40.702630 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023 diff --git a/tests/legacy_tests/Camera/log/error_20250728-153418.191852 b/tests/legacy_tests/Camera/log/error_20250728-153418.191852 new file mode 100644 index 0000000..37c64fc --- /dev/null +++ b/tests/legacy_tests/Camera/log/error_20250728-153418.191852 @@ -0,0 +1,4 @@ +Log file created at: 2025/07/28 15:34:18 +Running on machine: vision +Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg +E0728 15:34:18.442386 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023 diff --git a/tests/legacy_tests/Camera/log/error_20250728-153428.191852 b/tests/legacy_tests/Camera/log/error_20250728-153428.191852 new file mode 100644 index 0000000..623da2a --- /dev/null +++ b/tests/legacy_tests/Camera/log/error_20250728-153428.191852 @@ -0,0 +1,4 @@ +Log file created at: 2025/07/28 15:34:28 +Running on machine: vision +Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg +E0728 15:34:28.207051 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023 diff --git a/tests/legacy_tests/Camera/log/error_20250728-153453.191852 b/tests/legacy_tests/Camera/log/error_20250728-153453.191852 new file mode 100644 index 0000000..fb774ca --- /dev/null +++ b/tests/legacy_tests/Camera/log/error_20250728-153453.191852 @@ -0,0 +1,4 @@ +Log file created at: 2025/07/28 15:34:53 +Running on machine: vision +Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg +E0728 15:34:53.315912 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023 diff --git a/tests/legacy_tests/Camera/log/error_20250728-153500.191852 b/tests/legacy_tests/Camera/log/error_20250728-153500.191852 new file mode 100644 index 0000000..b2feb5c --- /dev/null +++ b/tests/legacy_tests/Camera/log/error_20250728-153500.191852 @@ -0,0 +1,4 @@ +Log file created at: 2025/07/28 15:35:00 +Running on machine: vision +Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg +E0728 15:35:00.929268 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023 diff --git a/tests/legacy_tests/Camera/log/error_20250728-153532.191852 b/tests/legacy_tests/Camera/log/error_20250728-153532.191852 new file mode 100644 index 0000000..089956a --- /dev/null +++ b/tests/legacy_tests/Camera/log/error_20250728-153532.191852 @@ -0,0 +1,4 @@ +Log file created at: 2025/07/28 15:35:32 +Running on machine: vision +Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg +E0728 15:35:32.169682 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023 diff --git a/tests/legacy_tests/Camera/log/error_20250728-153534.191852 b/tests/legacy_tests/Camera/log/error_20250728-153534.191852 new file mode 100644 index 0000000..cc94c46 --- /dev/null +++ b/tests/legacy_tests/Camera/log/error_20250728-153534.191852 @@ -0,0 +1,4 @@ +Log file created at: 2025/07/28 15:35:34 +Running on machine: vision +Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg +E0728 15:35:34.519351 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023 diff --git a/old tests/IMPLEMENTATION_SUMMARY.md b/tests/legacy_tests/IMPLEMENTATION_SUMMARY.md similarity index 100% rename from old tests/IMPLEMENTATION_SUMMARY.md rename to tests/legacy_tests/IMPLEMENTATION_SUMMARY.md diff --git a/old tests/README.md b/tests/legacy_tests/README.md similarity index 100% rename from old tests/README.md rename to tests/legacy_tests/README.md diff --git a/old tests/README_SYSTEM.md b/tests/legacy_tests/README_SYSTEM.md similarity index 100% rename from old tests/README_SYSTEM.md rename to tests/legacy_tests/README_SYSTEM.md diff --git a/old tests/TIMEZONE_SETUP_SUMMARY.md b/tests/legacy_tests/TIMEZONE_SETUP_SUMMARY.md similarity index 100% rename from old tests/TIMEZONE_SETUP_SUMMARY.md rename to tests/legacy_tests/TIMEZONE_SETUP_SUMMARY.md diff --git a/old tests/VIDEO_RECORDER_README.md b/tests/legacy_tests/VIDEO_RECORDER_README.md similarity index 100% rename from old tests/VIDEO_RECORDER_README.md rename to tests/legacy_tests/VIDEO_RECORDER_README.md diff --git a/old tests/camera_capture.py b/tests/legacy_tests/camera_capture.py similarity index 100% rename from old tests/camera_capture.py rename to tests/legacy_tests/camera_capture.py diff --git a/old tests/camera_video_recorder.py b/tests/legacy_tests/camera_video_recorder.py similarity index 100% rename from old tests/camera_video_recorder.py rename to tests/legacy_tests/camera_video_recorder.py diff --git a/old tests/main.py b/tests/legacy_tests/main.py similarity index 100% rename from old tests/main.py rename to tests/legacy_tests/main.py diff --git a/old tests/test_exposure.py b/tests/legacy_tests/test_exposure.py similarity index 100% rename from old tests/test_exposure.py rename to tests/legacy_tests/test_exposure.py diff --git a/test_api_changes.py b/tests/test_api_changes.py similarity index 100% rename from test_api_changes.py rename to tests/test_api_changes.py diff --git a/test_camera_recovery_api.py b/tests/test_camera_recovery_api.py similarity index 100% rename from test_camera_recovery_api.py rename to tests/test_camera_recovery_api.py diff --git a/test_max_fps.py b/tests/test_max_fps.py similarity index 100% rename from test_max_fps.py rename to tests/test_max_fps.py diff --git a/test_mqtt_events_api.py b/tests/test_mqtt_events_api.py similarity index 100% rename from test_mqtt_events_api.py rename to tests/test_mqtt_events_api.py diff --git a/test_mqtt_logging.py b/tests/test_mqtt_logging.py similarity index 100% rename from test_mqtt_logging.py rename to tests/test_mqtt_logging.py diff --git a/test_system.py b/tests/test_system.py similarity index 98% rename from test_system.py rename to tests/test_system.py index 5c7deb1..cda4f6c 100644 --- a/test_system.py +++ b/tests/test_system.py @@ -64,7 +64,7 @@ def test_camera_discovery(): """Test camera discovery""" print("\nTesting camera discovery...") try: - sys.path.append("./python demo") + sys.path.append("./camera_sdk") import mvsdk devices = mvsdk.CameraEnumerateDevice() @@ -82,7 +82,7 @@ def test_camera_discovery(): return True except Exception as e: print(f"❌ Camera discovery failed: {e}") - print(" Make sure GigE cameras are connected and python demo library is available") + print(" Make sure GigE cameras are connected and camera SDK library is available") return False diff --git a/test_timezone.py b/tests/test_timezone.py similarity index 100% rename from test_timezone.py rename to tests/test_timezone.py diff --git a/usda-vision-camera.service b/usda-vision-camera.service new file mode 100644 index 0000000..8f39f91 --- /dev/null +++ b/usda-vision-camera.service @@ -0,0 +1,26 @@ +[Unit] +Description=USDA Vision Camera System +After=network.target +Wants=network.target + +[Service] +Type=simple +User=root +Group=root +WorkingDirectory=/home/alireza/USDA-vision-cameras +ExecStart=/bin/bash /home/alireza/USDA-vision-cameras/start_system.sh +Restart=always +RestartSec=10 +StandardOutput=journal +StandardError=journal + +# Environment variables +Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +Environment=HOME=/root + +# Security settings (adjust as needed) +NoNewPrivileges=false +PrivateTmp=false + +[Install] +WantedBy=multi-user.target diff --git a/usda_vision_system/camera/__init__.py b/usda_vision_system/camera/__init__.py index 205313d..df9d25f 100644 --- a/usda_vision_system/camera/__init__.py +++ b/usda_vision_system/camera/__init__.py @@ -2,7 +2,7 @@ Camera module for the USDA Vision Camera System. This module handles GigE camera discovery, management, monitoring, and recording -using the python demo library (mvsdk). +using the camera SDK library (mvsdk). """ from .manager import CameraManager diff --git a/usda_vision_system/camera/__pycache__/__init__.cpython-311.pyc b/usda_vision_system/camera/__pycache__/__init__.cpython-311.pyc index 372f908080b73bb7e6f3876da8fc56111201e478..6e8702c8b5698f87e3492c7502df6e2c6980bcd8 100644 GIT binary patch delta 41 ucmcb^a+`&BIWI340|>ls&xoDK8^*Y5VoD!Za$;_3QKCYyi}%LA@r(chHVt$D delta 42 wcmcc3a)*U?IWI340}$-`+ME$LkvEKS^~97u?t;pajQl)>l+@h(jep`90V?YcG5`Po diff --git a/usda_vision_system/camera/__pycache__/manager.cpython-311.pyc b/usda_vision_system/camera/__pycache__/manager.cpython-311.pyc index b7f9101aad465c86e371ec2ee368f048e0ac4c76..22c54b789a996532dd305000c921be8754b8b4de 100644 GIT binary patch delta 2623 zcmaJ@TWnNS6y?sV)5p;1W2Vp+Y3XxlY0Im%rL?tBXerdT(jqU%>CBxnIK8(y_ZC_t zRy0y08pRVdYLrBRT0cziN`m4C#1HjDgoGb&^h0Ch0~2FHFfsA5*SRy((iG-n%{lv= zz0clj@3YVS>ymW$lH~c&HP6?e}vKdA&9rbCnC(fJ#V@7?A0!T_wU zg4ML6A*RHXQPUAqqAIK4o~-hmI$F^rf)ZAbosGOR>kDbE@lRHRtt6$(He#)UfR54C zaaN6aIp3ANu^1LiHsRE=V$WIy5Ixb$Xk4?q%wZcw@E7E zZ~5w^I{uCCAy+RJxAWh9t6jp4HAb=jnzM8ViDwao;oL2l z?;!}}SdJC)nc|vJVN;yCA*C>ckq-c(Svf$&HjEK$n08HP0VhLPYy=>VYscsyf#xJA z!OtSB$ymPPs!ck;)$Zl|&dTpx`PiAkzbc;AmFg<9pK(le|`^1GzY<)l_+m1 zeUWJYs`Rv7+QWw`)~{EfY>|eMsDKEKOwU*-d?=>KK}tj{%tUY^kY0YdqH0$vl7QPf zbR6mon(2ysG^ptzUA7_O9(;m2lpA}rKQD50&liH2L)jc+83;%5OPH!vB&H0tb zy*0i9FvoCmAT1Fo1ns=FW>tY;Esf^FaMJXoF;UZHmyYwxb;tXW!GMb`FufTz<}4?2 zazI!HJO@}TCsW2u{l8L!AO$p<8Kbf;0-w-k?eiU^Ma@niBIXy@PD*Qe-MTxCR((U& z8Pnx4jlDqQWEOYQn5Ep9mr3LC^_h}%!ia46Q*xccu9x}##;w!OK-q0o+gw^jwfQH; zBb1L|vLnd4PFGa3vYH1I(@;*I=ky6kE$bM)0zeW?ua?jbT1F%6SrTjMO9>O)gMFj6 zsac{prR`UEWpicytF*k0Dn3P*m0dx+NWn>1nPchc=Cf3(MJ=yM4?RLFtdoHHk29u3 z=fq4d;k%cF)>y`)0wzRX)^F+3^4#%xqoO^dR*g zMGosRRblsXLI;|D{&R<)-{?3=NG5n+T#6w-y&*UitCeTYgI(KGjw05r?z$w5gAMz(4J(-n7_JS&Tvp zF+DiSLL+mhvDpR2ecNsevTiNAA5pJ&`|=j!rLWu1+q!F9=ioTVIV3Ic?bn{F=EZ!= zh)%@gL2^*mAK=;69k(d#+TL>xYA4qpEh`M-peF%%Kv)O>8i)l?|2iqmJNnC}QJB`N zk(+omAQ1H?GL$MsCSw8anc2Z`Tn;G{qx6F;OL`Ypo*39j-jgQOgQ2JWCI!qOvi|-##tlgEdX&% znlOSp%n3kWwxY{`jM?QM|W z=Kt+oG2MsdOkz&1OMDv$9 lavQtGf7thtcjpc7z)kPKjU|IOmkeHCGRRNw|HXmr{{#OsMIitH delta 2627 zcmaJ@U2IfE6z1+SomZeajS&B<3wzP$oLZJ~#SeM<~c6ImOGWXV& z`csHne=r6eG-_0$Vx$iylI4NmgFg@I3kV4h=Hi3VL>@>?hz1j5(DTjR?zTf{zH{cx-n%UQeOYpU=62^Sq3`UimqsQox=&l&lewcO^bu7ljmil%dESz1Z&*nS zSTUf4z*rgyCu9~5CBjO0SY|#io3nu5%Bqu!xWhRld3eIvwZcnVd^W?T$?>7N3zOHJ zmDb`~SS^Fqtnn~YV#=^#iz!1YtK=?MW&S#v(IkRW=Eus-e243b)R_F&)o3YA?`4}X zS4lv}=;|n|!MK9&@oZiN3x<=)5tT({rdeoMnlcthe&D%hla}$bh36dbfod)GL+G1Ygbmp@&gvG)Daa<76 z5dzIlP>RnaYzqx1D|U*6^_cnchhj=hPd2Weu}Fhl>0HVGTzl2A3>LEaccsk*dm)w+ z_-y7mgWOYARM<%x%|?*1F7rUy%ao39%igd`1N=Z$Q&R$)O)?>g%7~C;xD(;XNKBDK zl%QCIiJ(P*-TX>bO;0*PpVK^4#rEUanXSm0#pzD+V>a7+j zn2gnSS)?|etlN{mu+mZN@s+L7LR8 z1R`R7X~Trn$k%QBtHrE)Y_-R9Iiax^NS@8&ZjxErjro~0y!=#?mmhDsE1gV6Hrb88}Df zS-ka(w5FA2*bV|}M)sHzl_!{at)bt=e`u*ZihTBxvwcwE0vL|)=%}nj**<9Y1Ns4? zSVb}6TlG`y-&? z8-Ad*y7eJ67#>~L^bqwTMULn(Rblffq4SI){!42Szur1c+$fzviNDoWyH?mVvQr!7 zXfKtVAV}2B0ROqo-?a$sMmBn@ILvH%=wUOnjRV1on~I{JQ*yk2=kK$JPqa6<#o_Ec zE$U^T@{8@YEsGuHVia1K>7ij3K9)I+U07heu;UK6y1n8-Jn{c_d6&-Tg_n1BI6j8I z;ABKv;L>khHG#!k${8Aq$3x_otUtt|o!z%7+WOs}*r;>-xVNJCC=Ln%@P@F*0f?T0 zclB+Qj`8h%6;mij^Wi8+JsePoDieuG7a)sb0`3`}P$Vvgm9f#(m1Hue9{9p!9+x3n zH`{telL(7B^l!tZ#-kLY`GhWfaOSt)q<3G5&9i}a_4;hR^!aL7Dc^puW-14cxByE5 z>j@0oF;$JT%@_v&;&N<(1b3JnfEH{bpx4B&IX7l2EE%LFr23y}SQ6#|lV1J7Gag%%25HT#l&=utkQ z85UJzRamu#Up>?)z02<(T0PZ+>0Dw?_NV?H2p)2wE)Z(*u+9FLG6`~LHpx%PimsWI zd0$;MTw|i=iW>)xj9^wmrN>@n%!^@;7JU+}0e@49U`<5z w6{K{e|2VfL)aY1T4zjEKr^6TWdT!+HznQoH#*+SE~w#f3;!x|JOW4u>b%7 diff --git a/usda_vision_system/camera/__pycache__/monitor.cpython-311.pyc b/usda_vision_system/camera/__pycache__/monitor.cpython-311.pyc index 38e71e8f187ce55bda24a896da9e98fe2865b536..77c29e3abe497425006f32bcc71e3a1381458ef5 100644 GIT binary patch delta 1597 zcmZuxU1%It6yDj{zwBRk+f*e;zDPyHC&55{xsU2gDG1`5Po8sUn@yzi@XfvF-t&EP z{^ok?lUCvDLLnQ&=i$R^tMF~%Xgn{omf2un8r*(2JQcsBr!sgBMe$AY4Xs<~DOc+a z*HZaJuAl4!1cTyQ_P2o@domtE;7No*df;IAe(v-5>Jd5`Mv&?EOz<3UMJ60?*@p@p zjL|{Ta+wKml-8;9tH4ZKmW+n)Ie`!8V7R`&2G6RiJTM{H)L;^KTth%1M3@&J6z^%Z z@WnlMwApPa*|OML;P@U)&_2lke2{v>@hWlk;ZkEfjz^Rw za-Ius?a%32zqor~a^@^qlxiJU6+QAOw2Nf<-mxlk@a2MXn(c} zlA3X_h+)zbrE4ktzVBX2tBZ}N|3F_C!hGD$i;`%>YFC*)p%L7dW>8p-AUvB5~qY^mufYm!B==1Ikw{oOB0LnX*I9s ziTgEzj|iyVk9sT(j5pnY!|Q15beFhs?7CJH6SZIV7V+SLia7-|4)O`Hm3>l-Och_E zR#&4S^So(UjB^99ODfUDXxgiEr*lznn62H@cXjFkDp|*0DXU@IHJLvipW9bMf{Iqh zF`B|vz0w0iV&C*gt&51W1bKpE2r}`u@4GNh`%?sS1ZM~+09X><^uemiIj6nK#>ce! zl;8%!W(-I$YPvpJ^@ZO}|Dg>lD;X*S@EN|O&aZMP(+&EGMWs6|et2$n<0KuYZ3jI3 z$;ymjEITeU3}}!&hkeM#+9ORd$i2!!{m+bs>6t57P!(6MbDyo_@bD}zc2xgno^SYe(`EB;OME%|Rq5re(z*Mkb6c^6`>};z NV+-QqiMt89{vX>ZeCPlG delta 1572 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 S_sT}El#PlNFaD8!B>V@ah*N3+ delta 3460 zcma)8YitzP7541x3$NGM4%o(EW1C{L!NGQG9s05D^+e1S~RUh(x~JYky;=H(WagJXew2xQBkCxk8jVMd+)jDeeOT520pnOi2pbq&(Fi(;0NbUUb`Ism7;uCURQE4Ysxuk8r5l$ zHDynrJ3hUf3$OLj@32L+M@(~Xgg6Q1SHf82>=tIN@^R*_B}$Jhq|<^0Igd%U7Dq( z^o;II!46s}un*c6F-MT)#Zre&!yFQZjprL(cSDb&G|SH_%9JKqwy{fTlP5MdD3$K{ zjV{gledywI`)odo$RMq_}ljKFzJAo z#TvTsvi^pxkKBJ5d;{0#0(_A#FTnDAX_M~7hMTIAkyg_tB`Pm8rBLeMn<^Hh7BxS< zERv)=%Y*Ys*~h#GPu0zTTTAFjx z3!XA{1JmK&p_ZB!+OU&gEx|5=y$D`tBqKC{J+il_vTHYUY)1o!Yu#JRbP~jf32Dqy z;My&q)9lkiI-uGPBtpK4Ka#KaY+ldigm7)i7I57Ud(;p*_b*54F?Iz56%|}EC4Pn+ z%xYue2$&p39W|3q;5O57a0?dtxpTzJB7AmT1(C;_8lCj zQ+}h9jmOvT=K!%S6rhDVkEU~=Il5_hYew~qNV3#bOuOcuJ^q_0rhLD4@zA0(ypklv z&B!gg-tVw%Zy2p4lY2>(D+HX!ZxYpn;FZgpNxlGfiQ z387KYvSss4ZAGG7mLK-4b3aWDhA~Q$OdA} z`z>LJv|l=0CW}EyMEu0{b(7<#wv=%cBB&;3??SV^E-yB$ci%a6JA^G#S~Zx%zp%FS zlRJHn(ZuiqhUMjtf|*U_Mn?sB;T-n==3P8kya)*Uq-G(T4*ik#hc(-ove3u0Zx6gL z>&G8ReC!_b*mz^h9Xf!*aX2RTq;v-}hw0Q9d`<&__fY9__x5f~lQL&nX&z?Kc zK$fhqnO;QjF2OB=+XPF^oy?wZApYAaV&_J8w|vVS~8I1 z#f5jDc=zcSCX`~9ltt5QJd}sYA)_yK`fsf2-K8@9((h;1;)+)=k^>Nilca{}_bck( zUdaeQ7n8c7J32P^X{_|u$y00Q+c468!gE*WDaZ%c=(ag(LRNG9{z!*lxgsPzA6veB z^W{I4x8qkr=}QEl1F61*+Sk{YNWjDLXWy%zS%WMH5zy-!Vg&mUykN>SGkys9$?znt zoFJGam?D@ac#41$8JlCqM3sI>3~Ha?5?mtSy0}c#b%MJHUc^XiLjc+oyhpqn1pgxV zl;AUh07WB2z^N4{id+ixo`m&C&E-Km(Uk<%4DQ_bo7LUz3yj1zD94RB?Wb&5N8CLG zoTl4|dLO|H8M&-A1$Slf?A{rFbZQnh-!#u#FOt^5z-W2VBu6os^s79E?+dX5NAIXU z2INZ&Dsiwb9g)mx20jjeUF-Q<#RMjT?fbcaZjTf2bL1gDiIYqIdbXgSpF2e)G2c#q zJvo0x2{8)s!x59tg7_*DQBAOkeA7-8`QzWw)~uP%Wkefnms?-?L($<|MT2*W25;pJ S-N_sJZQhWKzxrp+*Z%^=fKqV) diff --git a/usda_vision_system/camera/manager.py b/usda_vision_system/camera/manager.py index 56dd589..84def7b 100644 --- a/usda_vision_system/camera/manager.py +++ b/usda_vision_system/camera/manager.py @@ -12,8 +12,8 @@ import logging from typing import Dict, List, Optional, Tuple, Any from datetime import datetime -# Add python demo to path -sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "python demo")) +# Add camera SDK to path +sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "camera_sdk")) import mvsdk from ..core.config import Config, CameraConfig diff --git a/usda_vision_system/camera/monitor.py b/usda_vision_system/camera/monitor.py index b7f6b22..71fac9f 100644 --- a/usda_vision_system/camera/monitor.py +++ b/usda_vision_system/camera/monitor.py @@ -12,8 +12,8 @@ import logging import contextlib from typing import Dict, List, Optional, Any -# Add python demo to path -sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "python demo")) +# Add camera SDK to path +sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "camera_sdk")) import mvsdk from ..core.config import Config diff --git a/usda_vision_system/camera/recorder.py b/usda_vision_system/camera/recorder.py index 80c6fde..187754f 100644 --- a/usda_vision_system/camera/recorder.py +++ b/usda_vision_system/camera/recorder.py @@ -1,7 +1,7 @@ """ Camera Recorder for the USDA Vision Camera System. -This module handles video recording from GigE cameras using the python demo library (mvsdk). +This module handles video recording from GigE cameras using the camera SDK library (mvsdk). """ import sys @@ -16,8 +16,8 @@ from typing import Optional, Dict, Any from datetime import datetime from pathlib import Path -# Add python demo to path -sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "python demo")) +# Add camera SDK to path +sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "camera_sdk")) import mvsdk from ..core.config import CameraConfig diff --git a/usda_vision_system/camera/sdk_config.py b/usda_vision_system/camera/sdk_config.py index 9bf97d9..9965244 100644 --- a/usda_vision_system/camera/sdk_config.py +++ b/usda_vision_system/camera/sdk_config.py @@ -8,8 +8,8 @@ import sys import os import logging -# Add python demo to path -sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "python demo")) +# Add camera SDK to path +sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "camera_sdk")) import mvsdk logger = logging.getLogger(__name__) @@ -21,62 +21,62 @@ _sdk_initialized = False def initialize_sdk_with_suppression(): """Initialize the camera SDK with error suppression""" global _sdk_initialized - + if _sdk_initialized: return True - + try: # Initialize SDK with English language result = mvsdk.CameraSdkInit(1) if result == 0: logger.info("Camera SDK initialized successfully") - + # Try to set system options to suppress logging try: # These are common options that might control logging # We'll try them and ignore failures since they might not be supported - + # Try to disable debug output try: mvsdk.CameraSetSysOption("DebugLevel", "0") except: pass - + # Try to disable console output try: mvsdk.CameraSetSysOption("ConsoleOutput", "0") except: pass - + # Try to disable error logging try: mvsdk.CameraSetSysOption("ErrorLog", "0") except: pass - + # Try to set log level to none try: mvsdk.CameraSetSysOption("LogLevel", "0") except: pass - + # Try to disable verbose mode try: mvsdk.CameraSetSysOption("Verbose", "0") except: pass - + logger.debug("Attempted to configure SDK logging options") - + except Exception as e: logger.debug(f"Could not configure SDK logging options: {e}") - + _sdk_initialized = True return True else: logger.error(f"SDK initialization failed with code: {result}") return False - + except Exception as e: logger.error(f"SDK initialization failed: {e}") return False diff --git a/usda_vision_system/core/__pycache__/config.cpython-311.pyc b/usda_vision_system/core/__pycache__/config.cpython-311.pyc index d9b3a971c6e60c857fa2ba9d5bdc0663105ae37c..2770314ad71fd16b2104e4bbc56ac7acac2b3546 100644 GIT binary patch delta 1558 zcmaJ>ZEO=|9DknY?i#yx!wJkQxV3DfT{FRR8z`Y7sI;Lkwv9fpz2y;%D?cpOm)JReo9uJs#*S z4wpjZnA)Z0)t=cGOn0{~_QGw5y_U!%EWABxze|$>_42558(r02c7Dp}5O=%rA>iJ_ zfW}*j0)0{Ysr4K2f%nm&-*%{XrE2%0d@-VTKLPg_kJh*z(td7xn>tQm(IY%A`yHK5 zuf^K6lFX=Y#cptILLWb79!f%u(Umg0Qsu$fNI9~)Mb@r({$hnWEWTz>T$8&m2lf49 z%bBd1Iq^d#_gyBZ=V#1(p-RX!4ddoS*ilv?a$VdyX3V$P=68<1zn;|DBoW@{II8&pL2x3?~B0}f15EJdf7>eWUD2hlR zB7rC?qULMA&Yt@O-zRFn56EX|5)EvmC>uqO1v-SWVRiuB7vTM%9a2L9mh)EMuZ54X zd5+=%TJ!F_kotVe@b;PBz6E7*a4BN!8!`8dEGLqBDr=@*Hxeh!#L0$c3VR+0DeTy- zK`4oFnv?)~)4~*`|%{xGvDkTIWucI^F{>xe{OWKjpZBw)%NT zkB9pLS80j=7C+!X&WiT4zlH$ zcR(-Dr*V7Ur2EkzQbRJ9=47-}fIs-ZJca}cD@2Kn6m!(RN5 za_12CBAiDM5F7|9-_f#p(_vg9#Nn5JnEQ4;HsqJQ7TE}gDU%d9V-0whQyQTbX}~uA z;jYqyOiD0yi<-RfkeZ$Ez;g8af5;E*o^6^3FL1y}evaSReYW7D_}6lKtk`#WCOcItibV6jfR-6D-pL9L2VFT$iSwTm3oZ;?6_>dOkQstENe%(}-ea?$|oLjzP$ bt0L5EFiC!cQrwF>Q>7NG67QXJ>=XANC*Q1u delta 1259 zcmbu8T}TvB6vyYzm+h=G8MC?fvZpmLxE@b2j~_)shCg>$A$K=-5qO-w4CN@NUN_ulE8C!KmtHnTOD~^uyfe)^b81WRc9se+Dlrb7P?t8n z=9_MUzE0QEo;>DXn5*Z6nVg+wBiW=ql3sss}$#li{td{w=!zX z{*v`Sq4gIWdJ}0&yNYPTe(wMb05`$oo=nh+?xREHT=KjE; z=jvN;5{a-u{X@9V-;CbjDgQ?_gs%pg(2V*ba1@~tTpFsQp?#sl=%YFj`ie~RV2A;% zfNK;%0snB7V|Htx^Anv$_f!0L!zIwL4ugazw;ps3L%9(^1K>6Q{*rzXFou=tN)f)y zXb6X^>zjjulhDq7M< None: """Load configuration from file""" config_path = Path(self.config_file) - + if config_path.exists(): try: - with open(config_path, 'r') as f: + with open(config_path, "r") as f: config_data = json.load(f) - + # Load MQTT config - if 'mqtt' in config_data: - mqtt_data = config_data['mqtt'] + if "mqtt" in config_data: + mqtt_data = config_data["mqtt"] self.mqtt = MQTTConfig(**mqtt_data) - + # Load storage config - if 'storage' in config_data: - storage_data = config_data['storage'] + if "storage" in config_data: + storage_data = config_data["storage"] self.storage = StorageConfig(**storage_data) - + # Load system config - if 'system' in config_data: - system_data = config_data['system'] + if "system" in config_data: + system_data = config_data["system"] self.system = SystemConfig(**system_data) - + # Load camera configs - if 'cameras' in config_data: - self.cameras = [ - CameraConfig(**cam_data) - for cam_data in config_data['cameras'] - ] + if "cameras" in config_data: + self.cameras = [CameraConfig(**cam_data) for cam_data in config_data["cameras"]] else: self._create_default_camera_configs() - + self.logger.info(f"Configuration loaded from {config_path}") - + except Exception as e: self.logger.error(f"Error loading config from {config_path}: {e}") self._create_default_camera_configs() @@ -151,66 +149,50 @@ class Config: self.logger.info(f"Config file {config_path} not found, using defaults") self._create_default_camera_configs() self.save_config() # Save default config - + def _create_default_camera_configs(self) -> None: """Create default camera configurations""" - self.cameras = [ - CameraConfig( - name="camera1", - machine_topic="vibratory_conveyor", - storage_path=os.path.join(self.storage.base_path, "camera1") - ), - CameraConfig( - name="camera2", - machine_topic="blower_separator", - storage_path=os.path.join(self.storage.base_path, "camera2") - ) - ] - + self.cameras = [CameraConfig(name="camera1", machine_topic="vibratory_conveyor", storage_path=os.path.join(self.storage.base_path, "camera1")), CameraConfig(name="camera2", machine_topic="blower_separator", storage_path=os.path.join(self.storage.base_path, "camera2"))] + def save_config(self) -> None: """Save current configuration to file""" - config_data = { - 'mqtt': asdict(self.mqtt), - 'storage': asdict(self.storage), - 'system': asdict(self.system), - 'cameras': [asdict(cam) for cam in self.cameras] - } - + config_data = {"mqtt": asdict(self.mqtt), "storage": asdict(self.storage), "system": asdict(self.system), "cameras": [asdict(cam) for cam in self.cameras]} + try: - with open(self.config_file, 'w') as f: + with open(self.config_file, "w") as f: json.dump(config_data, f, indent=2) self.logger.info(f"Configuration saved to {self.config_file}") except Exception as e: self.logger.error(f"Error saving config to {self.config_file}: {e}") - + def _ensure_storage_directories(self) -> None: """Ensure all storage directories exist""" try: # Create base storage directory Path(self.storage.base_path).mkdir(parents=True, exist_ok=True) - + # Create camera-specific directories for camera in self.cameras: Path(camera.storage_path).mkdir(parents=True, exist_ok=True) - + self.logger.info("Storage directories verified/created") except Exception as e: self.logger.error(f"Error creating storage directories: {e}") - + def get_camera_by_topic(self, topic: str) -> Optional[CameraConfig]: """Get camera configuration by MQTT topic""" for camera in self.cameras: if camera.machine_topic == topic: return camera return None - + def get_camera_by_name(self, name: str) -> Optional[CameraConfig]: """Get camera configuration by name""" for camera in self.cameras: if camera.name == name: return camera return None - + def update_camera_config(self, name: str, **kwargs) -> bool: """Update camera configuration""" camera = self.get_camera_by_name(name) @@ -221,12 +203,7 @@ class Config: self.save_config() return True return False - + def to_dict(self) -> Dict[str, Any]: """Convert configuration to dictionary""" - return { - 'mqtt': asdict(self.mqtt), - 'storage': asdict(self.storage), - 'system': asdict(self.system), - 'cameras': [asdict(cam) for cam in self.cameras] - } + return {"mqtt": asdict(self.mqtt), "storage": asdict(self.storage), "system": asdict(self.system), "cameras": [asdict(cam) for cam in self.cameras]}