nedo-vision-worker 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. nedo_vision_worker/__init__.py +10 -0
  2. nedo_vision_worker/cli.py +195 -0
  3. nedo_vision_worker/config/ConfigurationManager.py +196 -0
  4. nedo_vision_worker/config/__init__.py +1 -0
  5. nedo_vision_worker/database/DatabaseManager.py +219 -0
  6. nedo_vision_worker/database/__init__.py +1 -0
  7. nedo_vision_worker/doctor.py +453 -0
  8. nedo_vision_worker/initializer/AppInitializer.py +78 -0
  9. nedo_vision_worker/initializer/__init__.py +1 -0
  10. nedo_vision_worker/models/__init__.py +15 -0
  11. nedo_vision_worker/models/ai_model.py +29 -0
  12. nedo_vision_worker/models/auth.py +14 -0
  13. nedo_vision_worker/models/config.py +9 -0
  14. nedo_vision_worker/models/dataset_source.py +30 -0
  15. nedo_vision_worker/models/logs.py +9 -0
  16. nedo_vision_worker/models/ppe_detection.py +39 -0
  17. nedo_vision_worker/models/ppe_detection_label.py +20 -0
  18. nedo_vision_worker/models/restricted_area_violation.py +20 -0
  19. nedo_vision_worker/models/user.py +10 -0
  20. nedo_vision_worker/models/worker_source.py +19 -0
  21. nedo_vision_worker/models/worker_source_pipeline.py +21 -0
  22. nedo_vision_worker/models/worker_source_pipeline_config.py +24 -0
  23. nedo_vision_worker/models/worker_source_pipeline_debug.py +15 -0
  24. nedo_vision_worker/models/worker_source_pipeline_detection.py +14 -0
  25. nedo_vision_worker/protos/AIModelService_pb2.py +46 -0
  26. nedo_vision_worker/protos/AIModelService_pb2_grpc.py +140 -0
  27. nedo_vision_worker/protos/DatasetSourceService_pb2.py +46 -0
  28. nedo_vision_worker/protos/DatasetSourceService_pb2_grpc.py +140 -0
  29. nedo_vision_worker/protos/HumanDetectionService_pb2.py +44 -0
  30. nedo_vision_worker/protos/HumanDetectionService_pb2_grpc.py +140 -0
  31. nedo_vision_worker/protos/PPEDetectionService_pb2.py +46 -0
  32. nedo_vision_worker/protos/PPEDetectionService_pb2_grpc.py +140 -0
  33. nedo_vision_worker/protos/VisionWorkerService_pb2.py +72 -0
  34. nedo_vision_worker/protos/VisionWorkerService_pb2_grpc.py +471 -0
  35. nedo_vision_worker/protos/WorkerSourcePipelineService_pb2.py +64 -0
  36. nedo_vision_worker/protos/WorkerSourcePipelineService_pb2_grpc.py +312 -0
  37. nedo_vision_worker/protos/WorkerSourceService_pb2.py +50 -0
  38. nedo_vision_worker/protos/WorkerSourceService_pb2_grpc.py +183 -0
  39. nedo_vision_worker/protos/__init__.py +1 -0
  40. nedo_vision_worker/repositories/AIModelRepository.py +44 -0
  41. nedo_vision_worker/repositories/DatasetSourceRepository.py +150 -0
  42. nedo_vision_worker/repositories/PPEDetectionRepository.py +112 -0
  43. nedo_vision_worker/repositories/RestrictedAreaRepository.py +88 -0
  44. nedo_vision_worker/repositories/WorkerSourcePipelineDebugRepository.py +90 -0
  45. nedo_vision_worker/repositories/WorkerSourcePipelineDetectionRepository.py +48 -0
  46. nedo_vision_worker/repositories/WorkerSourcePipelineRepository.py +174 -0
  47. nedo_vision_worker/repositories/WorkerSourceRepository.py +46 -0
  48. nedo_vision_worker/repositories/__init__.py +1 -0
  49. nedo_vision_worker/services/AIModelClient.py +362 -0
  50. nedo_vision_worker/services/ConnectionInfoClient.py +57 -0
  51. nedo_vision_worker/services/DatasetSourceClient.py +88 -0
  52. nedo_vision_worker/services/FileToRTMPServer.py +78 -0
  53. nedo_vision_worker/services/GrpcClientBase.py +155 -0
  54. nedo_vision_worker/services/GrpcClientManager.py +141 -0
  55. nedo_vision_worker/services/ImageUploadClient.py +82 -0
  56. nedo_vision_worker/services/PPEDetectionClient.py +108 -0
  57. nedo_vision_worker/services/RTSPtoRTMPStreamer.py +98 -0
  58. nedo_vision_worker/services/RestrictedAreaClient.py +100 -0
  59. nedo_vision_worker/services/SystemUsageClient.py +77 -0
  60. nedo_vision_worker/services/VideoStreamClient.py +161 -0
  61. nedo_vision_worker/services/WorkerSourceClient.py +215 -0
  62. nedo_vision_worker/services/WorkerSourcePipelineClient.py +393 -0
  63. nedo_vision_worker/services/WorkerSourceUpdater.py +134 -0
  64. nedo_vision_worker/services/WorkerStatusClient.py +65 -0
  65. nedo_vision_worker/services/__init__.py +1 -0
  66. nedo_vision_worker/util/HardwareID.py +104 -0
  67. nedo_vision_worker/util/ImageUploader.py +92 -0
  68. nedo_vision_worker/util/Networking.py +94 -0
  69. nedo_vision_worker/util/PlatformDetector.py +50 -0
  70. nedo_vision_worker/util/SystemMonitor.py +299 -0
  71. nedo_vision_worker/util/VideoProbeUtil.py +120 -0
  72. nedo_vision_worker/util/__init__.py +1 -0
  73. nedo_vision_worker/worker/CoreActionWorker.py +125 -0
  74. nedo_vision_worker/worker/DataSenderWorker.py +168 -0
  75. nedo_vision_worker/worker/DataSyncWorker.py +143 -0
  76. nedo_vision_worker/worker/DatasetFrameSender.py +208 -0
  77. nedo_vision_worker/worker/DatasetFrameWorker.py +412 -0
  78. nedo_vision_worker/worker/PPEDetectionManager.py +86 -0
  79. nedo_vision_worker/worker/PipelineActionWorker.py +129 -0
  80. nedo_vision_worker/worker/PipelineImageWorker.py +116 -0
  81. nedo_vision_worker/worker/RabbitMQListener.py +170 -0
  82. nedo_vision_worker/worker/RestrictedAreaManager.py +85 -0
  83. nedo_vision_worker/worker/SystemUsageManager.py +111 -0
  84. nedo_vision_worker/worker/VideoStreamWorker.py +139 -0
  85. nedo_vision_worker/worker/WorkerManager.py +155 -0
  86. nedo_vision_worker/worker/__init__.py +1 -0
  87. nedo_vision_worker/worker_service.py +264 -0
  88. nedo_vision_worker-1.0.0.dist-info/METADATA +563 -0
  89. nedo_vision_worker-1.0.0.dist-info/RECORD +92 -0
  90. nedo_vision_worker-1.0.0.dist-info/WHEEL +5 -0
  91. nedo_vision_worker-1.0.0.dist-info/entry_points.txt +2 -0
  92. nedo_vision_worker-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,453 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Nedo Vision Worker Service Doctor
4
+
5
+ This module provides diagnostic capabilities to check system requirements
6
+ and dependencies for the Nedo Vision Worker Service.
7
+ """
8
+
9
+ import subprocess
10
+ import sys
11
+ import platform
12
+ import shutil
13
+ import os
14
+ from pathlib import Path
15
+
16
+
17
+ def check_python_version():
18
+ """Check if Python version meets requirements."""
19
+ print("🐍 Checking Python version...")
20
+
21
+ version = sys.version_info
22
+ min_version = (3, 8)
23
+
24
+ if version >= min_version:
25
+ print(f" ✅ Python {version.major}.{version.minor}.{version.micro} (meets requirement >= {min_version[0]}.{min_version[1]})")
26
+ return True
27
+ else:
28
+ print(f" ❌ Python {version.major}.{version.minor}.{version.micro} (requires >= {min_version[0]}.{min_version[1]})")
29
+ return False
30
+
31
+
32
+ def check_ffmpeg():
33
+ """Check if FFmpeg is installed and accessible."""
34
+ print("🎬 Checking FFmpeg...")
35
+
36
+ try:
37
+ # Check if ffmpeg is in PATH
38
+ ffmpeg_path = shutil.which("ffmpeg")
39
+ if not ffmpeg_path:
40
+ print(" ❌ FFmpeg not found in PATH")
41
+ return False
42
+
43
+ # Check ffmpeg version
44
+ result = subprocess.run(
45
+ ["ffmpeg", "-version"],
46
+ capture_output=True,
47
+ text=True,
48
+ timeout=10
49
+ )
50
+
51
+ if result.returncode == 0:
52
+ # Extract version from output
53
+ version_line = result.stdout.split('\n')[0]
54
+ print(f" ✅ {version_line}")
55
+ print(f" 📍 Location: {ffmpeg_path}")
56
+ return True
57
+ else:
58
+ print(" ❌ FFmpeg found but failed to get version")
59
+ return False
60
+
61
+ except subprocess.TimeoutExpired:
62
+ print(" ❌ FFmpeg check timed out")
63
+ return False
64
+ except Exception as e:
65
+ print(f" ❌ Error checking FFmpeg: {e}")
66
+ return False
67
+
68
+
69
+ def check_opencv():
70
+ """Check if OpenCV is properly installed."""
71
+ print("👁️ Checking OpenCV...")
72
+
73
+ try:
74
+ import cv2
75
+ version = cv2.__version__
76
+ build_info = cv2.getBuildInformation()
77
+
78
+ print(f" ✅ OpenCV {version} installed")
79
+
80
+ # Check OpenCV build configuration
81
+ if "CUDA" in build_info:
82
+ print(" 🚀 OpenCV built with CUDA support")
83
+ if "OpenMP" in build_info:
84
+ print(" ⚡ OpenCV built with OpenMP support")
85
+
86
+ # Check for platform-specific optimizations
87
+ machine = platform.machine()
88
+ if machine in ["aarch64", "armv7l", "arm64"]:
89
+ if "NEON" in build_info:
90
+ print(" 🎯 OpenCV built with ARM NEON optimizations")
91
+ else:
92
+ print(" ⚠️ OpenCV may not have ARM optimizations")
93
+
94
+ # Test basic functionality
95
+ import numpy as np
96
+ test_img = np.zeros((100, 100, 3), dtype=np.uint8)
97
+
98
+ # Test encoding/decoding
99
+ _, encoded = cv2.imencode('.jpg', test_img)
100
+ decoded = cv2.imdecode(encoded, cv2.IMREAD_COLOR)
101
+
102
+ if decoded is not None:
103
+ print(" ✅ OpenCV basic functionality working")
104
+ return True
105
+ else:
106
+ print(" ❌ OpenCV encoding/decoding test failed")
107
+ return False
108
+
109
+ except ImportError:
110
+ print(" ❌ OpenCV not installed")
111
+ return False
112
+ except Exception as e:
113
+ print(f" ❌ OpenCV test failed: {e}")
114
+ return False
115
+
116
+
117
+ def check_grpc():
118
+ """Check if gRPC is properly installed."""
119
+ print("🌐 Checking gRPC...")
120
+
121
+ try:
122
+ import grpc
123
+ print(f" ✅ gRPC installed")
124
+
125
+ # Test basic gRPC functionality
126
+ from grpc import StatusCode
127
+ print(" ✅ gRPC basic imports working")
128
+ return True
129
+
130
+ except ImportError:
131
+ print(" ❌ gRPC not installed")
132
+ return False
133
+ except Exception as e:
134
+ print(f" ❌ gRPC test failed: {e}")
135
+ return False
136
+
137
+
138
+ def check_pynvml():
139
+ """Check if pynvml (NVIDIA management) is available."""
140
+ print("🎮 Checking NVIDIA GPU support...")
141
+
142
+ try:
143
+ import pynvml
144
+ pynvml.nvmlInit()
145
+
146
+ device_count = pynvml.nvmlDeviceGetCount()
147
+ if device_count > 0:
148
+ for i in range(device_count):
149
+ handle = pynvml.nvmlDeviceGetHandleByIndex(i)
150
+ name = pynvml.nvmlDeviceGetName(handle)
151
+ # Handle both string and bytes return types for compatibility
152
+ if isinstance(name, bytes):
153
+ name = name.decode('utf-8')
154
+
155
+ # Get additional GPU information
156
+ try:
157
+ memory_info = pynvml.nvmlDeviceGetMemoryInfo(handle)
158
+ memory_total_gb = memory_info.total / (1024**3)
159
+ print(f" ✅ GPU {i}: {name}")
160
+ print(f" 💾 Memory: {memory_total_gb:.1f} GB")
161
+
162
+ # Check for Jetson-specific GPUs
163
+ if "tegra" in name.lower() or "jetson" in name.lower():
164
+ print(" 🚀 Jetson GPU detected")
165
+
166
+ # Check compute capability for deep learning
167
+ try:
168
+ major, minor = pynvml.nvmlDeviceGetCudaComputeCapability(handle)
169
+ print(f" 🔢 Compute Capability: {major}.{minor}")
170
+ if major >= 6: # Pascal architecture or newer
171
+ print(" ✅ GPU supports modern deep learning frameworks")
172
+ else:
173
+ print(" ⚠️ GPU may have limited deep learning support")
174
+ except:
175
+ pass
176
+
177
+ except Exception as e:
178
+ print(f" ✅ GPU {i}: {name} (limited info: {e})")
179
+
180
+ return True
181
+ else:
182
+ print(" ⚠️ pynvml installed but no NVIDIA GPUs detected")
183
+ # Check if we're on ARM and might have integrated GPU
184
+ if platform.machine() in ["aarch64", "armv7l", "arm64"]:
185
+ print(" 💡 ARM device may use integrated GPU (Mali, Adreno, etc.)")
186
+ return True # Not an error, just no NVIDIA GPU
187
+
188
+ except ImportError:
189
+ print(" ❌ pynvml not installed")
190
+ print(" 💡 Install with: pip install pynvml")
191
+ return False
192
+ except Exception as e:
193
+ print(f" ⚠️ GPU check failed: {e}")
194
+ # More helpful error messages for common issues
195
+ if "driver" in str(e).lower():
196
+ print(" 💡 NVIDIA drivers may not be installed")
197
+ elif "nvml" in str(e).lower():
198
+ print(" 💡 NVIDIA Management Library not available")
199
+ return True # Not critical for service operation
200
+
201
+
202
+ def check_storage_permissions():
203
+ """Check if we can create storage directories."""
204
+ print("💾 Checking storage permissions...")
205
+
206
+ try:
207
+ # Test default storage path
208
+ test_path = Path("data") / "test_permissions"
209
+ test_path.mkdir(parents=True, exist_ok=True)
210
+
211
+ # Test file creation
212
+ test_file = test_path / "test.txt"
213
+ test_file.write_text("test")
214
+
215
+ # Test file reading
216
+ content = test_file.read_text()
217
+
218
+ # Cleanup
219
+ test_file.unlink()
220
+ test_path.rmdir()
221
+
222
+ if content == "test":
223
+ print(" ✅ Storage read/write permissions OK")
224
+ return True
225
+ else:
226
+ print(" ❌ Storage read/write test failed")
227
+ return False
228
+
229
+ except Exception as e:
230
+ print(f" ❌ Storage permission check failed: {e}")
231
+ return False
232
+
233
+
234
+ def check_network_connectivity():
235
+ """Check basic network connectivity."""
236
+ print("🌐 Checking network connectivity...")
237
+
238
+ try:
239
+ import socket
240
+
241
+ # Test DNS resolution
242
+ socket.gethostbyname("be.vision.sindika.co.id")
243
+ print(" ✅ DNS resolution working (be.vision.sindika.co.id)")
244
+
245
+ # Test basic socket connectivity
246
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
247
+ sock.settimeout(5)
248
+ result = sock.connect_ex(("be.vision.sindika.co.id", 50051))
249
+ sock.close()
250
+
251
+ if result == 0:
252
+ print(" ✅ Network connectivity to be.vision.sindika.co.id:50051 OK")
253
+ return True
254
+ else:
255
+ print(" ⚠️ Cannot connect to be.vision.sindika.co.id:50051 (may be normal if service is down)")
256
+ return True # Not critical for initial setup
257
+
258
+ except Exception as e:
259
+ print(f" ⚠️ Network check failed: {e}")
260
+ return True # Not critical for service installation
261
+
262
+
263
+ def check_platform_compatibility():
264
+ """Check platform-specific compatibility."""
265
+ print("🔧 Checking platform compatibility...")
266
+
267
+ system = platform.system()
268
+ machine = platform.machine()
269
+
270
+ # Check for known compatible platforms
271
+ compatible_platforms = {
272
+ "Linux": ["x86_64", "aarch64", "armv7l", "arm64"],
273
+ "Windows": ["AMD64", "x86_64"],
274
+ "Darwin": ["x86_64", "arm64"] # macOS Intel and Apple Silicon
275
+ }
276
+
277
+ if system in compatible_platforms:
278
+ if machine in compatible_platforms[system]:
279
+ print(f" ✅ Platform {system}/{machine} is supported")
280
+
281
+ # Special handling for ARM devices
282
+ if machine in ["aarch64", "armv7l", "arm64"]:
283
+ print(" 📱 ARM-based device detected")
284
+ if "tegra" in platform.platform().lower():
285
+ print(" 🚀 NVIDIA Jetson device detected")
286
+ elif "raspberry" in platform.platform().lower():
287
+ print(" 🍓 Raspberry Pi device detected")
288
+
289
+ return True
290
+ else:
291
+ print(f" ⚠️ Architecture {machine} may have limited support on {system}")
292
+ return True # Still allow execution
293
+ else:
294
+ print(f" ⚠️ Platform {system} may have limited support")
295
+ return True # Still allow execution
296
+
297
+
298
+ def print_system_info():
299
+ """Print basic system information."""
300
+ print("💻 System Information:")
301
+ print(f" 🖥️ OS: {platform.system()} {platform.release()}")
302
+ print(f" 🏗️ Architecture: {platform.machine()}")
303
+ print(f" 🐍 Python: {platform.python_version()}")
304
+ print(f" 📍 Python executable: {sys.executable}")
305
+
306
+ # Additional platform details
307
+ try:
308
+ import os
309
+ if hasattr(os, 'uname'):
310
+ uname = os.uname()
311
+ print(f" 🔧 Kernel: {uname.sysname} {uname.release}")
312
+ except:
313
+ pass
314
+
315
+ # Check for containerized environment
316
+ if Path("/.dockerenv").exists():
317
+ print(" 🐳 Running in Docker container")
318
+ elif os.environ.get("KUBERNETES_SERVICE_HOST"):
319
+ print(" ☸️ Running in Kubernetes pod")
320
+
321
+
322
+ def print_installation_help():
323
+ """Print installation help for missing dependencies."""
324
+ print("\n📋 Installation Help:")
325
+ print("=" * 50)
326
+
327
+ system = platform.system()
328
+ machine = platform.machine()
329
+
330
+ print("\n🎬 FFmpeg Installation:")
331
+ if system == "Windows":
332
+ print(" • Using Chocolatey: choco install ffmpeg")
333
+ print(" • Using winget: winget install FFmpeg")
334
+ print(" • Manual: Download from https://ffmpeg.org/download.html")
335
+ elif system == "Darwin": # macOS
336
+ print(" • Using Homebrew: brew install ffmpeg")
337
+ print(" • Using MacPorts: sudo port install ffmpeg")
338
+ else: # Linux
339
+ print(" • Ubuntu/Debian: sudo apt update && sudo apt install ffmpeg")
340
+ print(" • CentOS/RHEL: sudo yum install ffmpeg")
341
+ print(" • Fedora: sudo dnf install ffmpeg")
342
+ print(" • Alpine: apk add ffmpeg")
343
+
344
+ # ARM-specific guidance
345
+ if machine in ["aarch64", "armv7l", "arm64"]:
346
+ print(" • For ARM devices:")
347
+ print(" - Jetson: Usually pre-installed with JetPack")
348
+ print(" - Raspberry Pi: sudo apt install ffmpeg")
349
+ print(" - Build from source for optimal performance")
350
+
351
+ print("\n🐍 Python Dependencies:")
352
+ print(" • Install all: pip install -r requirements.txt")
353
+ print(" • Or install individually:")
354
+ print(" - pip install opencv-python")
355
+ print(" - pip install grpcio")
356
+ print(" - pip install pynvml")
357
+
358
+ # Platform-specific OpenCV guidance
359
+ if machine in ["aarch64", "armv7l", "arm64"]:
360
+ print("\n🔧 ARM-Specific Notes:")
361
+ print(" • OpenCV: Consider opencv-python-headless for servers")
362
+ print(" • Jetson: Use opencv built with JetPack for GPU acceleration")
363
+ print(" • Build from source for optimal ARM performance")
364
+ print(" • For Jetson: Install with 'sudo apt install python3-opencv'")
365
+
366
+ print("\n🎮 GPU Support:")
367
+ if system == "Linux" and machine in ["aarch64", "armv7l"]:
368
+ print(" • Jetson devices:")
369
+ print(" - Install JetPack SDK from NVIDIA")
370
+ print(" - Verify with: sudo /usr/bin/tegrastats")
371
+ print(" - Check CUDA: nvcc --version")
372
+ else:
373
+ print(" • NVIDIA GPU (Optional):")
374
+ print(" - Install NVIDIA drivers from https://www.nvidia.com/drivers/")
375
+ print(" - Install CUDA toolkit if needed")
376
+ print(" - pynvml should work automatically if drivers are installed")
377
+
378
+ print("\n☁️ Cloud/Container Deployment:")
379
+ print(" • Docker: Use nvidia/cuda base images for GPU support")
380
+ print(" • Cloud: Ensure GPU instances have proper drivers")
381
+ print(" • Kubernetes: Use nvidia.com/gpu resource limits")
382
+ print(" • AWS: Use Deep Learning AMI or ECS GPU instances")
383
+ print(" • GCP: Use AI Platform or GPU-enabled Compute instances")
384
+
385
+ print("\n📦 Package Installation Tips:")
386
+ print(" • Use virtual environments: python -m venv venv")
387
+ print(" • Update pip: pip install --upgrade pip")
388
+ print(" • For ARM: pip install --extra-index-url https://www.piwheels.org/simple/")
389
+ print(" • Build tools: sudo apt install build-essential python3-dev")
390
+
391
+
392
+ def main():
393
+ """Run all diagnostic checks."""
394
+ print("🏥 Nedo Vision Worker Service Doctor")
395
+ print("=" * 50)
396
+
397
+ # Print system info
398
+ print_system_info()
399
+ print()
400
+
401
+ # Run all checks
402
+ checks = [
403
+ ("Platform Compatibility", check_platform_compatibility),
404
+ ("Python Version", check_python_version),
405
+ ("FFmpeg", check_ffmpeg),
406
+ ("OpenCV", check_opencv),
407
+ ("gRPC", check_grpc),
408
+ ("NVIDIA GPU Support", check_pynvml),
409
+ ("Storage Permissions", check_storage_permissions),
410
+ ("Network Connectivity", check_network_connectivity),
411
+ ]
412
+
413
+ results = []
414
+ print("🔍 Running Diagnostic Checks:")
415
+ print("-" * 30)
416
+
417
+ for name, check_func in checks:
418
+ try:
419
+ result = check_func()
420
+ results.append((name, result))
421
+ except Exception as e:
422
+ print(f" ❌ {name} check failed with exception: {e}")
423
+ results.append((name, False))
424
+ print()
425
+
426
+ # Summary
427
+ print("📊 Summary:")
428
+ print("-" * 20)
429
+
430
+ passed = 0
431
+ failed = 0
432
+
433
+ for name, result in results:
434
+ if result:
435
+ print(f" ✅ {name}")
436
+ passed += 1
437
+ else:
438
+ print(f" ❌ {name}")
439
+ failed += 1
440
+
441
+ print(f"\n🎯 Results: {passed} passed, {failed} failed")
442
+
443
+ if failed > 0:
444
+ print("\n⚠️ Some checks failed. See installation help below:")
445
+ print_installation_help()
446
+ return 1
447
+ else:
448
+ print("\n🎉 All checks passed! Your system is ready for Nedo Vision Worker Service.")
449
+ return 0
450
+
451
+
452
+ if __name__ == "__main__":
453
+ sys.exit(main())
@@ -0,0 +1,78 @@
1
+ import logging
2
+ import re
3
+ import uuid
4
+ import grpc
5
+ from ..config.ConfigurationManager import ConfigurationManager
6
+ from ..util.PlatformDetector import PlatformDetector
7
+ from ..util.Networking import Networking
8
+ from ..services.ConnectionInfoClient import ConnectionInfoClient
9
+ from ..database.DatabaseManager import DatabaseManager
10
+
11
+
12
+ class AppInitializer:
13
+ @staticmethod
14
+ def validate_uuid(value):
15
+ """Validate if the provided value is a valid UUID."""
16
+ try:
17
+ uuid.UUID(value)
18
+ return value
19
+ except ValueError:
20
+ raise ValueError(f"Invalid device ID format: {value}. Must be a valid UUID.")
21
+
22
+ @staticmethod
23
+ def validate_server_host(value):
24
+ """Validate if the server host is a valid domain name or IP address."""
25
+ domain_regex = (
26
+ r"^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*"
27
+ r"([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$"
28
+ )
29
+ ip_regex = (
30
+ r"^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\."
31
+ r"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\."
32
+ r"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\."
33
+ r"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
34
+ )
35
+ if re.match(domain_regex, value) or re.match(ip_regex, value):
36
+ return value
37
+ raise ValueError(f"Invalid server host: {value}. Must be a valid domain or IP address.")
38
+
39
+ @staticmethod
40
+ def initialize_configuration(device_id: str, server_host: str, token: str):
41
+ """
42
+ Initialize the application configuration using the provided token
43
+ and saving configuration data locally.
44
+ """
45
+ try:
46
+ # Validate inputs
47
+ AppInitializer.validate_uuid(device_id)
48
+ AppInitializer.validate_server_host(server_host)
49
+
50
+ # Get connection info using the ConnectionInfoClient
51
+ connection_client = ConnectionInfoClient(server_host, 50051, token)
52
+ connection_result = connection_client.get_connection_info()
53
+
54
+ if not connection_result["success"]:
55
+ logging.error(f"Device connection info failed: {connection_result['message']}")
56
+ return
57
+
58
+ worker_id = connection_result.get('id')
59
+ if not worker_id:
60
+ raise ValueError("No worker_id returned from connection info!")
61
+
62
+ ConfigurationManager.set_config_batch({
63
+ "worker_id": worker_id,
64
+ "server_host": server_host,
65
+ "token": token,
66
+ "rabbitmq_host": connection_result['rabbitmq_host'],
67
+ "rabbitmq_port": str(connection_result['rabbitmq_port']),
68
+ "rabbitmq_username": connection_result['rabbitmq_username'],
69
+ "rabbitmq_password": connection_result['rabbitmq_password']
70
+ })
71
+ ConfigurationManager.print_config()
72
+
73
+ except ValueError as ve:
74
+ logging.error(f"Validation error: {ve}")
75
+ except grpc.RpcError as ge:
76
+ logging.error(f"Grpc Error: {ge}")
77
+ except Exception as e:
78
+ logging.error(f"Unexpected error during initialization: {e}")
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,15 @@
1
+ # Import all models to ensure they are registered with SQLAlchemy Base registry
2
+ from .ai_model import AIModelEntity
3
+ from .auth import AuthEntity
4
+ from .config import ConfigEntity
5
+ from .dataset_source import DatasetSourceEntity
6
+ from .logs import LogEntity
7
+ from .ppe_detection import PPEDetectionEntity
8
+ from .ppe_detection_label import PPEDetectionLabelEntity
9
+ from .restricted_area_violation import RestrictedAreaViolationEntity
10
+ from .user import UserEntity
11
+ from .worker_source import WorkerSourceEntity
12
+ from .worker_source_pipeline import WorkerSourcePipelineEntity
13
+ from .worker_source_pipeline_config import WorkerSourcePipelineConfigEntity
14
+ from .worker_source_pipeline_debug import WorkerSourcePipelineDebugEntity
15
+ from .worker_source_pipeline_detection import WorkerSourcePipelineDetectionEntity
@@ -0,0 +1,29 @@
1
+ import uuid
2
+ from sqlalchemy import Column, String, DateTime
3
+ from datetime import datetime
4
+ from ..database.DatabaseManager import Base
5
+
6
+ class AIModelEntity(Base):
7
+ __tablename__ = "ai_model"
8
+ __bind_key__ = "default"
9
+
10
+ id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
11
+ file = Column(String, nullable=False)
12
+ type = Column(String, nullable=False)
13
+ name = Column(String, nullable=False)
14
+ version = Column(String, nullable=False)
15
+ download_status = Column(String, nullable=True, default="completed") # pending, downloading, completed, failed
16
+ last_download_attempt = Column(DateTime, nullable=True)
17
+ download_error = Column(String, nullable=True)
18
+
19
+ def __repr__(self):
20
+ return (
21
+ f"<AIModelEntity(id={self.id}, name={self.name}, type={self.type}, "
22
+ f"file={self.file}, version={self.version})>"
23
+ )
24
+
25
+ def __str__(self):
26
+ return (
27
+ f"AIModelEntity(id={self.id}, name={self.name}, type={self.type}, "
28
+ f"file={self.file}, version={self.version}, status={self.download_status})"
29
+ )
@@ -0,0 +1,14 @@
1
+ from sqlalchemy import Column, String, Integer
2
+ from ..database.DatabaseManager import Base
3
+
4
+ class AuthEntity(Base):
5
+ __tablename__ = "auth"
6
+ id = Column(Integer, primary_key=True)
7
+ username = Column(String, nullable=False)
8
+ password = Column(String, nullable=False)
9
+
10
+ def __repr__(self):
11
+ return f"<AuthEntity(id={self.id}, username={self.username})>"
12
+
13
+ def to_dict(self):
14
+ return {"id": self.id, "username": self.username}
@@ -0,0 +1,9 @@
1
+ from sqlalchemy import Column, String
2
+ from ..database.DatabaseManager import Base
3
+
4
+ class ConfigEntity(Base):
5
+ __tablename__ = "server_config"
6
+ __bind_key__ = "config"
7
+
8
+ key = Column(String, primary_key=True)
9
+ value = Column(String, nullable=False)
@@ -0,0 +1,30 @@
1
+ from sqlalchemy import Column, String, Integer
2
+ from ..database.DatabaseManager import Base
3
+
4
+ class DatasetSourceEntity(Base):
5
+ __tablename__ = "dataset_sources"
6
+ __bind_key__ = "default"
7
+
8
+ id = Column(String, primary_key=True)
9
+ dataset_id = Column(String, nullable=False)
10
+ worker_source_id = Column(String, nullable=False)
11
+ sampling_interval = Column(Integer, nullable=False)
12
+ dataset_name = Column(String, nullable=False)
13
+ worker_source_name = Column(String, nullable=False)
14
+ worker_source_url = Column(String, nullable=False)
15
+
16
+ def __repr__(self):
17
+ return (
18
+ f"<DatasetSourceEntity(id={self.id}, dataset_id={self.dataset_id}, "
19
+ f"worker_source_id={self.worker_source_id}, sampling_interval={self.sampling_interval}, "
20
+ f"dataset_name={self.dataset_name}, worker_source_name={self.worker_source_name}, "
21
+ f"worker_source_url={self.worker_source_url})>"
22
+ )
23
+
24
+ def __str__(self):
25
+ return (
26
+ f"DatasetSourceEntity(id={self.id}, dataset_id={self.dataset_id}, "
27
+ f"worker_source_id={self.worker_source_id}, sampling_interval={self.sampling_interval}, "
28
+ f"dataset_name={self.dataset_name}, worker_source_name={self.worker_source_name}, "
29
+ f"worker_source_url={self.worker_source_url})"
30
+ )
@@ -0,0 +1,9 @@
1
+ from sqlalchemy import Column, String, Integer
2
+ from ..database.DatabaseManager import Base
3
+
4
+ class LogEntity(Base):
5
+ __tablename__ = "logs"
6
+ __bind_key__ = "logging"
7
+
8
+ id = Column(Integer, primary_key=True, autoincrement=True)
9
+ message = Column(String, nullable=False)
@@ -0,0 +1,39 @@
1
+ import uuid
2
+ import datetime
3
+ from sqlalchemy import Column, String, ForeignKey, DateTime, Float, Integer
4
+ from sqlalchemy.orm import relationship
5
+ from ..database.DatabaseManager import Base
6
+
7
+ class PPEDetectionEntity(Base):
8
+ __tablename__ = "ppe_detections"
9
+ __bind_key__ = "default"
10
+
11
+ id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
12
+ worker_id = Column(String, nullable=False)
13
+ worker_source_id = Column(String, nullable=False)
14
+ person_id = Column(String, nullable=False)
15
+ image_path = Column(String, nullable=False)
16
+ image_tile_path = Column(String, nullable=False)
17
+ detection_count = Column(Integer, nullable=False, default=0) # Tracks total detections before saving
18
+ created_at = Column(DateTime, default=datetime.datetime.utcnow)
19
+ b_box_x1 = Column(Float, nullable=False)
20
+ b_box_y1 = Column(Float, nullable=False)
21
+ b_box_x2 = Column(Float, nullable=False)
22
+ b_box_y2 = Column(Float, nullable=False)
23
+
24
+ ppe_labels = relationship("PPEDetectionLabelEntity", back_populates="detection")
25
+
26
+ def __repr__(self):
27
+ return (
28
+ f"<PPEDetectionEntity(id={self.id}, worker_id={self.worker_id}, "
29
+ f"worker_source_id={self.worker_source_id}, person_id={self.person_id}, "
30
+ f"image_path={self.image_path}, detection_count={self.detection_count}, "
31
+ f"created_at={self.created_at})>"
32
+ )
33
+
34
+ def __str__(self):
35
+ return (
36
+ f"PPEDetectionEntity(id={self.id}, worker_id={self.worker_id}, "
37
+ f"worker_source_id={self.worker_source_id}, person_id={self.person_id}, "
38
+ f"detection_count={self.detection_count}, created_at={self.created_at})"
39
+ )