nedo-vision-worker 1.2.8__py3-none-any.whl → 1.3.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.
@@ -6,5 +6,5 @@ A library for running worker agents in the Nedo Vision platform.
6
6
 
7
7
  from .worker_service import WorkerService
8
8
 
9
- __version__ = "1.2.8"
9
+ __version__ = "1.3.0"
10
10
  __all__ = ["WorkerService"]
@@ -19,19 +19,22 @@ class PPEDetectionRepository:
19
19
  os.makedirs(self.storage_dir, exist_ok=True)
20
20
 
21
21
 
22
- def get_latest_5_detections(self) -> list:
22
+ def get_latest_detections(self, limit: int = 50) -> list:
23
23
  """
24
- Retrieves the latest 5 PPE detections ordered by the 'created_at' timestamp.
24
+ Retrieves the latest PPE detections ordered by the 'created_at' timestamp.
25
+
26
+ Args:
27
+ limit (int): Maximum number of detections to retrieve. Default is 50.
25
28
 
26
29
  Returns:
27
- list: A list of PPEDetectionEntity objects.
30
+ list: A list of PPE detection dictionaries.
28
31
  """
29
32
  try:
30
33
  latest_detections = (
31
34
  self.session.query(PPEDetectionEntity)
32
35
  .options(joinedload(PPEDetectionEntity.ppe_labels))
33
36
  .order_by(asc(PPEDetectionEntity.created_at))
34
- .limit(5)
37
+ .limit(limit)
35
38
  .all()
36
39
  )
37
40
 
@@ -67,9 +70,22 @@ class PPEDetectionRepository:
67
70
 
68
71
  except SQLAlchemyError as e:
69
72
  self.session.rollback()
70
- logging.error(f"❌ Database error while retrieving latest 5 detections: {e}")
73
+ logging.error(f"❌ Database error while retrieving detections: {e}")
71
74
  return []
72
75
 
76
+ def get_total_pending_count(self) -> int:
77
+ """
78
+ Returns the total count of pending PPE detections in the database.
79
+
80
+ Returns:
81
+ int: Total count of pending detections.
82
+ """
83
+ try:
84
+ return self.session.query(PPEDetectionEntity).count()
85
+ except SQLAlchemyError as e:
86
+ logging.error(f"❌ Error counting pending detections: {e}")
87
+ return 0
88
+
73
89
  def delete_records_from_db(self, detection_data: list):
74
90
  """
75
91
  Deletes PPE detection records from the database based on detection data.
@@ -77,6 +93,10 @@ class PPEDetectionRepository:
77
93
  Args:
78
94
  detection_data (list): List of dictionaries containing the detection data.
79
95
  """
96
+ if not detection_data:
97
+ logging.info("No detection data provided for deletion.")
98
+ return
99
+
80
100
  try:
81
101
  # Extract person_id from detection data to delete the corresponding records
82
102
  person_ids_to_delete = [data['person_id'] for data in detection_data]
@@ -97,10 +117,23 @@ class PPEDetectionRepository:
97
117
  if not os.path.isabs(image_path):
98
118
  image_path = str(get_storage_path("files") / Path(image_path).relative_to("data/files"))
99
119
  if os.path.exists(image_path):
100
- os.remove(image_path)
101
- logging.info(f"Deleted image file: {image_path}")
120
+ try:
121
+ os.remove(image_path)
122
+ except OSError as e:
123
+ logging.warning(f"Failed to delete image file {image_path}: {e}")
102
124
  else:
103
125
  logging.warning(f"Image file not found for detection {detection.id}: {image_path}")
126
+
127
+ # Delete the image tile file if it exists
128
+ image_tile_path = detection.image_tile_path
129
+ if image_tile_path:
130
+ if not os.path.isabs(image_tile_path):
131
+ image_tile_path = str(get_storage_path("files") / Path(image_tile_path).relative_to("data/files"))
132
+ if os.path.exists(image_tile_path):
133
+ try:
134
+ os.remove(image_tile_path)
135
+ except OSError as e:
136
+ logging.warning(f"Failed to delete image tile file {image_tile_path}: {e}")
104
137
 
105
138
  # Delete the detection record
106
139
  self.session.delete(detection)
@@ -16,9 +16,12 @@ class RestrictedAreaRepository:
16
16
  self.session: Session = self.db_manager.get_session("default")
17
17
  os.makedirs(self.storage_dir, exist_ok=True)
18
18
 
19
- def get_latest_5_violations(self) -> list:
19
+ def get_latest_violations(self, limit: int = 50) -> list:
20
20
  """
21
- Retrieves the latest 5 restricted area violations ordered by the 'created_at' timestamp.
21
+ Retrieves the latest restricted area violations ordered by the 'created_at' timestamp.
22
+
23
+ Args:
24
+ limit (int): Maximum number of violations to retrieve. Default is 50.
22
25
 
23
26
  Returns:
24
27
  list: A list of dictionaries representing restricted area violations.
@@ -27,7 +30,7 @@ class RestrictedAreaRepository:
27
30
  latest_violations = (
28
31
  self.session.query(RestrictedAreaViolationEntity)
29
32
  .order_by(asc(RestrictedAreaViolationEntity.created_at))
30
- .limit(5)
33
+ .limit(limit)
31
34
  .all()
32
35
  )
33
36
 
@@ -51,9 +54,22 @@ class RestrictedAreaRepository:
51
54
 
52
55
  except SQLAlchemyError as e:
53
56
  self.session.rollback()
54
- logging.error(f"❌ Database error while retrieving latest 5 violations: {e}")
57
+ logging.error(f"❌ Database error while retrieving violations: {e}")
55
58
  return []
56
59
 
60
+ def get_total_pending_count(self) -> int:
61
+ """
62
+ Returns the total count of pending restricted area violations in the database.
63
+
64
+ Returns:
65
+ int: Total count of pending violations.
66
+ """
67
+ try:
68
+ return self.session.query(RestrictedAreaViolationEntity).count()
69
+ except SQLAlchemyError as e:
70
+ logging.error(f"❌ Error counting pending violations: {e}")
71
+ return 0
72
+
57
73
  def delete_records_from_db(self, violation_data: list):
58
74
  """
59
75
  Deletes restricted area violation records from the database based on the provided data.
@@ -61,6 +77,10 @@ class RestrictedAreaRepository:
61
77
  Args:
62
78
  violation_data (list): List of dictionaries containing the violation data.
63
79
  """
80
+ if not violation_data:
81
+ logging.info("No violation data provided for deletion.")
82
+ return
83
+
64
84
  try:
65
85
  person_ids_to_delete = [data['person_id'] for data in violation_data]
66
86
 
@@ -75,11 +95,24 @@ class RestrictedAreaRepository:
75
95
  if not os.path.isabs(image_path):
76
96
  image_path = str(get_storage_path("restricted_violations") / Path(image_path).relative_to("data/restricted_violations"))
77
97
  if os.path.exists(image_path):
78
- os.remove(image_path)
79
- logging.info(f"Deleted image file: {image_path}")
98
+ try:
99
+ os.remove(image_path)
100
+ except OSError as e:
101
+ logging.warning(f"Failed to delete image file {image_path}: {e}")
80
102
  else:
81
103
  logging.warning(f"Image file not found for violation {violation.id}: {image_path}")
82
104
 
105
+ # Delete the image tile file if it exists
106
+ image_tile_path = violation.image_tile_path
107
+ if image_tile_path:
108
+ if not os.path.isabs(image_tile_path):
109
+ image_tile_path = str(get_storage_path("restricted_violations") / Path(image_tile_path).relative_to("data/restricted_violations"))
110
+ if os.path.exists(image_tile_path):
111
+ try:
112
+ os.remove(image_tile_path)
113
+ except OSError as e:
114
+ logging.warning(f"Failed to delete image tile file {image_tile_path}: {e}")
115
+
83
116
  self.session.delete(violation)
84
117
 
85
118
  self.session.commit()
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ import os
2
3
  from .GrpcClientBase import GrpcClientBase
3
4
  from ..protos.PPEDetectionService_pb2_grpc import PPEDetectionGRPCServiceStub
4
5
  from ..protos.PPEDetectionService_pb2 import UpsertPPEDetectionBatchRequest, UpsertPPEDetectionRequest, PPEDetectionLabelRequest
@@ -56,11 +57,23 @@ class PPEDetectionClient(GrpcClientBase):
56
57
  return {"success": False, "message": "gRPC connection is not established."}
57
58
 
58
59
  try:
59
- # Prepare the list of UpsertPPEDetectionRequest messages
60
60
  ppe_detection_requests = []
61
+ valid_records = []
62
+ invalid_records = []
63
+
61
64
  for data in detection_data:
62
- image_binary = self.read_image_as_binary(data['image'])
63
- image_tile_binary = self.read_image_as_binary(data['image_tile'])
65
+ if not os.path.exists(data['image']) or not os.path.exists(data['image_tile']):
66
+ logger.warning(f"⚠️ Missing image files for person_id {data.get('person_id')}")
67
+ invalid_records.append(data)
68
+ continue
69
+
70
+ try:
71
+ image_binary = self.read_image_as_binary(data['image'])
72
+ image_tile_binary = self.read_image_as_binary(data['image_tile'])
73
+ except Exception as e:
74
+ logger.error(f"❌ Error reading images for person_id {data.get('person_id')}: {e}")
75
+ invalid_records.append(data)
76
+ continue
64
77
 
65
78
  ppe_detection_labels = [
66
79
  PPEDetectionLabelRequest(
@@ -73,11 +86,11 @@ class PPEDetectionClient(GrpcClientBase):
73
86
  )
74
87
  for label in data['ppe_detection_labels']
75
88
  ]
76
- source = data['worker_source_id']
89
+
77
90
  request = UpsertPPEDetectionRequest(
78
91
  person_id=data['person_id'],
79
92
  worker_id=worker_id,
80
- worker_source_id=source,
93
+ worker_source_id=data['worker_source_id'],
81
94
  image=image_binary,
82
95
  image_tile=image_tile_binary,
83
96
  worker_timestamp=data['worker_timestamp'],
@@ -85,18 +98,24 @@ class PPEDetectionClient(GrpcClientBase):
85
98
  token=token
86
99
  )
87
100
  ppe_detection_requests.append(request)
101
+ valid_records.append(data)
102
+
103
+ if invalid_records:
104
+ logger.info(f"🧹 Deleting {len(invalid_records)} invalid PPE detection records")
105
+ self.repository.delete_records_from_db(invalid_records)
106
+
107
+ if not ppe_detection_requests:
108
+ return {"success": True, "message": "No valid detections to send"}
88
109
 
89
- # Create the UpsertPPEDetectionBatchRequest
90
110
  batch_request = UpsertPPEDetectionBatchRequest(
91
111
  ppe_detection_requests=ppe_detection_requests,
92
112
  token=token
93
113
  )
94
114
 
95
- # Call the UpsertBatch RPC
96
115
  response = self.handle_rpc(self.stub.UpsertBatch, batch_request)
97
116
 
98
117
  if response and response.success:
99
- self.repository.delete_records_from_db(detection_data)
118
+ self.repository.delete_records_from_db(valid_records)
100
119
  return {"success": True, "message": response.message}
101
120
 
102
121
  return {"success": False, "message": response.message if response else "Unknown error"}
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ import os
2
3
  from ..repositories.RestrictedAreaRepository import RestrictedAreaRepository
3
4
  from .GrpcClientBase import GrpcClientBase
4
5
  from ..protos.HumanDetectionService_pb2_grpc import HumanDetectionGRPCServiceStub
@@ -60,10 +61,22 @@ class RestrictedAreaClient(GrpcClientBase):
60
61
 
61
62
  try:
62
63
  human_detection_requests = []
64
+ valid_records = []
65
+ invalid_records = []
63
66
 
64
67
  for data in violation_data:
65
- image_binary = self.read_image_as_binary(data['image'])
66
- image_tile_binary = self.read_image_as_binary(data['image_tile'])
68
+ if not os.path.exists(data['image']) or not os.path.exists(data['image_tile']):
69
+ logger.warning(f"⚠️ Missing image files for person_id {data.get('person_id')}")
70
+ invalid_records.append(data)
71
+ continue
72
+
73
+ try:
74
+ image_binary = self.read_image_as_binary(data['image'])
75
+ image_tile_binary = self.read_image_as_binary(data['image_tile'])
76
+ except Exception as e:
77
+ logger.error(f"❌ Error reading images for person_id {data.get('person_id')}: {e}")
78
+ invalid_records.append(data)
79
+ continue
67
80
 
68
81
  request = UpsertHumanDetectionRequest(
69
82
  person_id=data['person_id'],
@@ -81,6 +94,14 @@ class RestrictedAreaClient(GrpcClientBase):
81
94
  )
82
95
 
83
96
  human_detection_requests.append(request)
97
+ valid_records.append(data)
98
+
99
+ if invalid_records:
100
+ logger.info(f"🧹 Deleting {len(invalid_records)} invalid violation records")
101
+ self.repository.delete_records_from_db(invalid_records)
102
+
103
+ if not human_detection_requests:
104
+ return {"success": True, "message": "No valid violations to send"}
84
105
 
85
106
  batch_request = UpsertHumanDetectionBatchRequest(
86
107
  human_detection_requests=human_detection_requests,
@@ -90,7 +111,7 @@ class RestrictedAreaClient(GrpcClientBase):
90
111
  response = self.handle_rpc(self.stub.UpsertBatch, batch_request)
91
112
 
92
113
  if response and response.success:
93
- self.repository.delete_records_from_db(violation_data)
114
+ self.repository.delete_records_from_db(valid_records)
94
115
  return {"success": True, "message": response.message}
95
116
 
96
117
  return {"success": False, "message": response.message if response else "Unknown error"}
@@ -118,14 +118,63 @@ class DataSenderWorker:
118
118
  try:
119
119
  while not self.stop_event.is_set():
120
120
  self.system_usage_manager.process_system_usage()
121
- self.ppe_detection_manager.send_ppe_detection_batch()
122
- self.restricted_area_manager.send_violation_batch()
121
+
122
+ ppe_pending = self._send_with_adaptive_interval(
123
+ self.ppe_detection_manager.send_ppe_detection_batch,
124
+ self.ppe_detection_manager.ppe_detection_repo.get_total_pending_count
125
+ )
126
+
127
+ violation_pending = self._send_with_adaptive_interval(
128
+ self.restricted_area_manager.send_violation_batch,
129
+ self.restricted_area_manager.repo.get_total_pending_count
130
+ )
131
+
123
132
  self._process_image_upload()
124
133
  self._process_dataset_frames()
125
- time.sleep(self.send_interval)
134
+
135
+ sleep_time = self._calculate_sleep_interval(ppe_pending, violation_pending)
136
+ if sleep_time < self.send_interval and (ppe_pending + violation_pending) > 0:
137
+ logger.debug(f"⚡ [APP] Catch-up mode: {ppe_pending + violation_pending} pending, sleeping {sleep_time}s")
138
+ time.sleep(sleep_time)
126
139
  except Exception as e:
127
140
  logger.error("🚨 [APP] Unexpected error in main worker loop.", exc_info=True)
128
141
 
142
+ def _send_with_adaptive_interval(self, send_func, count_func):
143
+ """Send data with adaptive interval based on backlog."""
144
+ try:
145
+ pending = count_func()
146
+ if pending > 0:
147
+ send_func()
148
+ return pending
149
+ except Exception as e:
150
+ logger.error(f"🚨 [APP] Error in adaptive sending: {e}", exc_info=True)
151
+ return 0
152
+
153
+ def _calculate_sleep_interval(self, ppe_pending: int, violation_pending: int) -> float:
154
+ """
155
+ Calculate optimal sleep interval based on pending data.
156
+ Conservative approach to prevent server overload.
157
+
158
+ Args:
159
+ ppe_pending: Number of pending PPE detections
160
+ violation_pending: Number of pending violations
161
+
162
+ Returns:
163
+ float: Sleep interval in seconds
164
+ """
165
+ total_pending = ppe_pending + violation_pending
166
+
167
+ if total_pending == 0:
168
+ return self.send_interval
169
+ elif total_pending < 50:
170
+ return self.send_interval
171
+ elif total_pending < 200:
172
+ return 3.0
173
+ elif total_pending < 500:
174
+ return 2.0
175
+ else:
176
+ return 1.5
177
+
129
178
  def _run_worker_source_updater(self):
130
179
  """Dedicated loop for updating worker sources at a different interval."""
131
180
  try:
@@ -50,14 +50,42 @@ class PPEDetectionManager:
50
50
 
51
51
  logger.info("📡 [APP] PPE detection monitoring started.")
52
52
 
53
+ def _calculate_batch_size(self, pending_count: int) -> int:
54
+ """
55
+ Calculates optimal batch size based on pending items.
56
+ Conservative limits to prevent server overload.
57
+
58
+ Args:
59
+ pending_count (int): Number of pending detections
60
+
61
+ Returns:
62
+ int: Optimal batch size
63
+ """
64
+ if pending_count < 20:
65
+ return 10
66
+ elif pending_count < 100:
67
+ return 30
68
+ elif pending_count < 500:
69
+ return 50
70
+ else:
71
+ return 100
53
72
 
54
73
  def send_ppe_detection_batch(self):
55
- """Sends a batch of collected PPE detection data to the server."""
74
+ """Sends a batch of collected PPE detection data to the server with dynamic batch sizing."""
56
75
  try:
57
- self.ppe_detection_data = self.ppe_detection_repo.get_latest_5_detections()
76
+ pending_count = self.ppe_detection_repo.get_total_pending_count()
77
+
78
+ if pending_count == 0:
79
+ return
80
+
81
+ batch_size = self._calculate_batch_size(pending_count)
82
+ self.ppe_detection_data = self.ppe_detection_repo.get_latest_detections(batch_size)
83
+
58
84
  if not self.ppe_detection_data:
59
85
  return
60
86
 
87
+ logger.info(f"📤 [APP] Sending {len(self.ppe_detection_data)} PPE detections ({pending_count} pending)")
88
+
61
89
  response = self.ppe_detection_client.send_upsert_batch(
62
90
  worker_id=self.worker_id,
63
91
  worker_source_id=self.worker_source_id,
@@ -66,7 +94,7 @@ class PPEDetectionManager:
66
94
  )
67
95
 
68
96
  if response.get("success"):
69
- logger.info("✅ [APP] Successfully sent PPE detection batch.")
97
+ logger.info(f"✅ [APP] Successfully sent {len(self.ppe_detection_data)} PPE detections")
70
98
  self.ppe_detection_data.clear()
71
99
  else:
72
100
  logger.error(f"❌ [APP] Failed to send PPE detection batch: {response.get('message')}")
@@ -50,13 +50,42 @@ class RestrictedAreaManager:
50
50
 
51
51
  logger.info("📡 [APP] Restricted area violation monitoring started.")
52
52
 
53
+ def _calculate_batch_size(self, pending_count: int) -> int:
54
+ """
55
+ Calculates optimal batch size based on pending items.
56
+ Conservative limits to prevent server overload.
57
+
58
+ Args:
59
+ pending_count (int): Number of pending violations
60
+
61
+ Returns:
62
+ int: Optimal batch size
63
+ """
64
+ if pending_count < 20:
65
+ return 10
66
+ elif pending_count < 100:
67
+ return 30
68
+ elif pending_count < 500:
69
+ return 50
70
+ else:
71
+ return 100
72
+
53
73
  def send_violation_batch(self):
54
- """Sends a batch of collected violation data to the server."""
74
+ """Sends a batch of collected violation data to the server with dynamic batch sizing."""
55
75
  try:
56
- self.violations_data = self.repo.get_latest_5_violations()
76
+ pending_count = self.repo.get_total_pending_count()
77
+
78
+ if pending_count == 0:
79
+ return
80
+
81
+ batch_size = self._calculate_batch_size(pending_count)
82
+ self.violations_data = self.repo.get_latest_violations(batch_size)
83
+
57
84
  if not self.violations_data:
58
85
  return
59
86
 
87
+ logger.info(f"📤 [APP] Sending {len(self.violations_data)} violations ({pending_count} pending)")
88
+
60
89
  response = self.client.send_upsert_batch(
61
90
  worker_id=self.worker_id,
62
91
  worker_source_id=self.worker_source_id,
@@ -65,7 +94,7 @@ class RestrictedAreaManager:
65
94
  )
66
95
 
67
96
  if response.get("success"):
68
- logger.info("✅ [APP] Successfully sent restricted area violation batch.")
97
+ logger.info(f"✅ [APP] Successfully sent {len(self.violations_data)} violations")
69
98
  self.violations_data.clear()
70
99
  else:
71
100
  logger.error(f"❌ [APP] Failed to send restricted area violation batch: {response.get('message')}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nedo-vision-worker
3
- Version: 1.2.8
3
+ Version: 1.3.0
4
4
  Summary: Nedo Vision Worker Service Library for AI Vision Processing
5
5
  Author-email: Willy Achmat Fauzi <willy.achmat@gmail.com>
6
6
  Maintainer-email: Willy Achmat Fauzi <willy.achmat@gmail.com>
@@ -1,4 +1,4 @@
1
- nedo_vision_worker/__init__.py,sha256=RU8uEjcEodK2R_F4Fg2qBYmhhJpvf-vQBA-Cjo9Dvf8,203
1
+ nedo_vision_worker/__init__.py,sha256=lM4SwuHDgc4TdI91GAS_FS--pQKK2RFKliCp8sJY1-o,203
2
2
  nedo_vision_worker/cli.py,sha256=ddWspJmSgVkcUYvRdkvTtMNuMTDvNCqLLuMVU9KE3Ik,7457
3
3
  nedo_vision_worker/doctor.py,sha256=wNkpe8gLVd76Y_ViyK2h1ZFdqeSl37MnzZN5frWKu30,48410
4
4
  nedo_vision_worker/worker_service.py,sha256=9zz8hKwDwqwpfS0KPQfftGJtRci0uj_wiwcr_TGf-E0,11039
@@ -40,8 +40,8 @@ nedo_vision_worker/protos/WorkerSourceService_pb2_grpc.py,sha256=23Zj3WSogfhmp_Y
40
40
  nedo_vision_worker/protos/__init__.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKrFn4TvPL-rYUUGg,1
41
41
  nedo_vision_worker/repositories/AIModelRepository.py,sha256=35cQ2EnJvMdArewumPrVIaiwueGy6cXU_g5J1Qcj6_Y,1415
42
42
  nedo_vision_worker/repositories/DatasetSourceRepository.py,sha256=MOUbXY1-7WUPhY15aMpdXl6rl0afSvu3Cq8jNtp9nzM,8595
43
- nedo_vision_worker/repositories/PPEDetectionRepository.py,sha256=oyQjIRyfa0pA-ErVtrKkCLMY521QIbz9ZqSXotC8nqY,4766
44
- nedo_vision_worker/repositories/RestrictedAreaRepository.py,sha256=y3n2ZfQbth1I_IjVYaT38qpRINQQC_dKeTf0yHPFNjw,3724
43
+ nedo_vision_worker/repositories/PPEDetectionRepository.py,sha256=WYPrmMs3wSsaALR4ixsgMNOUbHbmYDGPbjMQdjSnIE4,6161
44
+ nedo_vision_worker/repositories/RestrictedAreaRepository.py,sha256=nk8DV5dkBfAm2AT8wY9la6yv6Q7pFi00YXLbvofqNkc,5158
45
45
  nedo_vision_worker/repositories/WorkerSourcePipelineDebugRepository.py,sha256=kOlVEnPOoDRZdZIm8uWXlc89GMvBPI-36QyKecX7ucE,3350
46
46
  nedo_vision_worker/repositories/WorkerSourcePipelineDetectionRepository.py,sha256=cbgg_7p0eNUIgCHoPDZBaRZ1b2Y68p_dfSxpvuGMtRE,1773
47
47
  nedo_vision_worker/repositories/WorkerSourcePipelineRepository.py,sha256=xfmEvgnyt-DdfSApGyFfy0H0dXjFFkjeo4LMr0fVFXU,10053
@@ -56,9 +56,9 @@ nedo_vision_worker/services/GrpcClientBase.py,sha256=hPyxOGw3aGSW1FhmY3wp3Iq8U1M
56
56
  nedo_vision_worker/services/GrpcClientManager.py,sha256=DLXekmxlQogLo8V9-TNDXtyHT_UG-BaggqwsIups55k,5568
57
57
  nedo_vision_worker/services/GrpcConnection.py,sha256=UNjaUC4ZcXuteHQx8AAAL5ymYkT1OpoIvyCYPUc3tCI,4915
58
58
  nedo_vision_worker/services/ImageUploadClient.py,sha256=T353YsRfm74G7Mh-eWr5nvdQHXTfpKwHJFmNW8HyjT8,3019
59
- nedo_vision_worker/services/PPEDetectionClient.py,sha256=CC-b0LRAgrftfIKp6TFKpeBkTYefe-C6Z1oz_X3HArQ,4345
59
+ nedo_vision_worker/services/PPEDetectionClient.py,sha256=3oE_Y0Avw_kcWKgTA7qmChq32woW7JerWefrCxllUYU,5172
60
60
  nedo_vision_worker/services/RTSPtoRTMPStreamer.py,sha256=LtfrWDHNcm-Ky6nZLnFCF8xgqIm7VQmsWIenK2yKNfo,3804
61
- nedo_vision_worker/services/RestrictedAreaClient.py,sha256=AE9SOcVQca4zn5V96boho56EgN5BCIpV-8grvFBBnGo,3853
61
+ nedo_vision_worker/services/RestrictedAreaClient.py,sha256=TD2Y5UJ0NjXgNFNgwS5ze4P-5jWwgrP0j0Nlyyd7-6Q,4844
62
62
  nedo_vision_worker/services/SharedDirectDeviceClient.py,sha256=dylMhqpMsfK_UKLWIVL-ApJRP4g-NCP_55xvlGYBiwo,10760
63
63
  nedo_vision_worker/services/SharedVideoStreamServer.py,sha256=WMKVxkzMoyfbgYiJ0fQOT-Ujz9btz6FLlaDP738yfoY,11601
64
64
  nedo_vision_worker/services/SystemUsageClient.py,sha256=Yf77dooQeNh6CDL5FkWVrX9543OVz1wc3exCAg6GlWw,3273
@@ -80,22 +80,22 @@ nedo_vision_worker/util/SystemMonitor.py,sha256=2kkqj9mOlywAS2fHdN1TaIXSXvCApcIH
80
80
  nedo_vision_worker/util/VideoProbeUtil.py,sha256=cF-vJ7hIDlXfEJby2a0s9tqwkPGVz_6B3Vv4D5pMmIw,12876
81
81
  nedo_vision_worker/util/__init__.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKrFn4TvPL-rYUUGg,1
82
82
  nedo_vision_worker/worker/CoreActionWorker.py,sha256=lb7zPY3yui6I3F4rX4Ii7JwpWZahLEO72rh3iWOgFmg,5441
83
- nedo_vision_worker/worker/DataSenderWorker.py,sha256=9FudRRItiMOcQx5UfVyu4p0Enb9BbgwZZ5EgX6Ho2U4,7160
83
+ nedo_vision_worker/worker/DataSenderWorker.py,sha256=BNA5mL2guBVp0O5MKULEWd78dY32YjiyWZX7ECFjVFc,9089
84
84
  nedo_vision_worker/worker/DataSyncWorker.py,sha256=LmDPt2J1frmXwuR46L6b0MjlFOHfgG-4_0MGQa78zF4,6288
85
85
  nedo_vision_worker/worker/DatasetFrameSender.py,sha256=1SFYj8LJFNi-anBTapsbq8U_NGMM7mnoMKg9NeFAHys,8087
86
86
  nedo_vision_worker/worker/DatasetFrameWorker.py,sha256=Hh_wZuMjwovxsEKFqXSuTRin9eYRBZCbcFKm3CKLMbE,19335
87
- nedo_vision_worker/worker/PPEDetectionManager.py,sha256=fAolWlrsY5SQAWygvjNBNU56IlC0HLlhPgpz7shL-gk,3588
87
+ nedo_vision_worker/worker/PPEDetectionManager.py,sha256=sO0ygzUKNNkUsrv-QJk9b-r9QnTw80VsniD5--OQJi0,4569
88
88
  nedo_vision_worker/worker/PipelineActionWorker.py,sha256=xgvryjKtEsMj4BKqWzDIaK_lFny-DfMCj5Y2DxHnWww,5651
89
89
  nedo_vision_worker/worker/PipelineImageWorker.py,sha256=J8VBUG0cwcH3qOJp2zTl30B-XhmPFyvJLjxitKJYq0E,5642
90
90
  nedo_vision_worker/worker/PipelinePreviewWorker.py,sha256=owFiBbktcOZkdImQeykZSeBIR2-mpt6HNkmYIkLRKzE,6397
91
91
  nedo_vision_worker/worker/RabbitMQListener.py,sha256=9gR49MDplgpyb-D5HOH0K77-DJQFvhS2E7biL92SjSU,6950
92
- nedo_vision_worker/worker/RestrictedAreaManager.py,sha256=3yoXgQ459tV1bOa5choEzR9gE6LklrtHR_e0472U3L0,3521
92
+ nedo_vision_worker/worker/RestrictedAreaManager.py,sha256=Y739KzbPzm2UF1a9oT3YEk7trfKqQjGUQ6MTwEDMkj4,4463
93
93
  nedo_vision_worker/worker/SystemUsageManager.py,sha256=mkh4sT-HkIEY1CJHMEG6LP9ATu39YXvLRLyf995OkoQ,5315
94
94
  nedo_vision_worker/worker/VideoStreamWorker.py,sha256=5n6v1PNO7IB-jj_McALLkUP-cBjJoIEw4UiSAs3vTb0,7606
95
95
  nedo_vision_worker/worker/WorkerManager.py,sha256=2bxXi19fp3p1qjYBStYRdVVgko8dnevXx1_M_sqH5og,5521
96
96
  nedo_vision_worker/worker/__init__.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKrFn4TvPL-rYUUGg,1
97
- nedo_vision_worker-1.2.8.dist-info/METADATA,sha256=7MmzgVArAQxzCvxpcCr-LzPrFa0prCfOkaYCPLkmH_0,14728
98
- nedo_vision_worker-1.2.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
99
- nedo_vision_worker-1.2.8.dist-info/entry_points.txt,sha256=LrglS-8nCi8C_PL_pa6uxdgCe879hBETHDVXAckvs-8,60
100
- nedo_vision_worker-1.2.8.dist-info/top_level.txt,sha256=vgilhlkyD34YsEKkaBabmhIpcKSvF3XpzD2By68L-XI,19
101
- nedo_vision_worker-1.2.8.dist-info/RECORD,,
97
+ nedo_vision_worker-1.3.0.dist-info/METADATA,sha256=MiQg-EA4V0jEqMkrupbyhwLvIDD1UfTpQ_cub90gh8E,14728
98
+ nedo_vision_worker-1.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
99
+ nedo_vision_worker-1.3.0.dist-info/entry_points.txt,sha256=LrglS-8nCi8C_PL_pa6uxdgCe879hBETHDVXAckvs-8,60
100
+ nedo_vision_worker-1.3.0.dist-info/top_level.txt,sha256=vgilhlkyD34YsEKkaBabmhIpcKSvF3XpzD2By68L-XI,19
101
+ nedo_vision_worker-1.3.0.dist-info/RECORD,,