Mentions légales du service

Skip to content
Snippets Groups Projects
Commit ae027665 authored by MOLLI Martin's avatar MOLLI Martin
Browse files

Fixed stuff

parent 0b84aa71
No related branches found
No related tags found
No related merge requests found
Showing
with 325 additions and 139 deletions
...@@ -12,6 +12,8 @@ WORKDIR /app ...@@ -12,6 +12,8 @@ WORKDIR /app
COPY . . COPY . .
# Install required Python packages # Install required Python packages
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && apt install -y libzmq3-dev && rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir -r requirements.txt RUN pip install --no-cache-dir -r requirements.txt
# Set environment variables with default values # Set environment variables with default values
...@@ -20,7 +22,6 @@ ENV CAMERA="false" \ ...@@ -20,7 +22,6 @@ ENV CAMERA="false" \
APPEARANCE_RATE=600 \ APPEARANCE_RATE=600 \
MDHOST="localhost" \ MDHOST="localhost" \
MDPORT=9998 MDPORT=9998
# Expose the port (if needed) # Expose the port (if needed)
# EXPOSE <port_number> # EXPOSE <port_number>
......
...@@ -7,4 +7,5 @@ opentelemetry-sdk ...@@ -7,4 +7,5 @@ opentelemetry-sdk
opentelemetry-exporter-jaeger opentelemetry-exporter-jaeger
opentelemetry-exporter-otlp opentelemetry-exporter-otlp
opentelemetry-exporter-otlp-proto-grpc opentelemetry-exporter-otlp-proto-grpc
pyzmq pyzmq
\ No newline at end of file cffi
\ No newline at end of file
import logging import logging
import os # Import os for environment variables import os # Import os for environment variables
import random import random
import time from time import perf_counter, sleep, perf_counter_ns
from contextlib import contextmanager from contextlib import contextmanager
import cv2 import cv2
import imutils # pip install imutils import imutils # pip install imutils
import zmq import zmq
from opentelemetry.propagate import inject from opentelemetry.propagate import inject
from zmq.backend.cffi import Socket
from services.common.camera_to_motiondetector_packet import CameraToMotionDetectorPacket from camera_to_motiondetector_packet import CameraToMotionDetectorPacket
from telemetry.tracerprovider import tracer, meter from telemetry.tracerprovider import tracer, meter
...@@ -29,23 +28,23 @@ logging.basicConfig( ...@@ -29,23 +28,23 @@ logging.basicConfig(
level=logging.INFO, # You can change this to DEBUG, ERROR, etc. level=logging.INFO, # You can change this to DEBUG, ERROR, etc.
handlers=[ handlers=[
logging.StreamHandler(), # Log to console logging.StreamHandler(), # Log to console
logging.FileHandler("/app/output/camera.log") # Log to a file #logging.FileHandler("/app/output/camera.log") # Log to a file
] ]
) )
frametime_histogram = meter.create_gauge( frametime_histogram = meter.create_gauge(
name="camera_frame_time", name="camera_frame_time",
description="Frames time", description="Frames time",
unit="ms" unit="ms"
) )
sleep_time_between_frame = meter.create_gauge( sleep_time_between_frame = meter.create_gauge(
name="camera_sleep_time_between_frame", name="camera_sleep_time_between_frame",
description="sleep_time_between_frame", description="sleep_time_between_frame",
unit="ms" unit="ms"
) )
frame_rate:int = 30 frame_rate:int = 10
MIN_FRAME_TIME:float = 1.0 / frame_rate MIN_FRAME_TIME:float = 1.0 / frame_rate
# Get environment variables (with defaults if not set) # Get environment variables (with defaults if not set)
...@@ -58,9 +57,9 @@ port = int(os.getenv("MDPORT", 9998)) ...@@ -58,9 +57,9 @@ port = int(os.getenv("MDPORT", 9998))
# Map animal to the appropriate video filenames # Map animal to the appropriate video filenames
animal_map = { animal_map = {
'bear': ('footage/bear/no_bear.mp4', 'footage/bear/with_bear.mp4'), 'bear': ('../footage/bear/no_bear.mp4', '../footage/bear/with_bear.mp4'),
'tiger': ('footage/tiger/no_tiger.mp4', 'footage/tiger/with_tiger.mp4'), 'tiger': ('../footage/tiger/no_tiger.mp4', '../footage/tiger/with_tiger.mp4'),
'wolf': ('footage/wolf/no_wolf.mp4', 'footage/wolf/with_wolf.mp4') 'wolf': ('../footage/wolf/no_wolf.mp4', '../footage/wolf/with_wolf.mp4')
} }
if animal_name not in animal_map: if animal_name not in animal_map:
...@@ -95,8 +94,8 @@ def main(): ...@@ -95,8 +94,8 @@ def main():
socket = context.socket(zmq.PAIR) socket = context.socket(zmq.PAIR)
logging.info(f"Attempting to connect to {host_ip}:{port}") logging.info(f"Attempting to connect to {host_ip}:{port}")
socket.connect(f"tcp://{host_ip}:{port}") socket.connect(f"tcp://{host_ip}:{port}")
stream_video_clip(socket)
logging.info(f"Connected to {host_ip}:{port}") logging.info(f"Connected to {host_ip}:{port}")
stream_video_clip(socket)
...@@ -105,7 +104,7 @@ def stream_video_clip(socket): ...@@ -105,7 +104,7 @@ def stream_video_clip(socket):
return return
# Initialize FPS calculation # Initialize FPS calculation
app_start_time = time.time() app_start_time = perf_counter()
while True: while True:
# Time no_motion_clip_length between motion to sample fivode # Time no_motion_clip_length between motion to sample fivode
with tracer.start_as_current_span("sending frame from camera") as frame_span: with tracer.start_as_current_span("sending frame from camera") as frame_span:
...@@ -116,14 +115,17 @@ def stream_video_clip(socket): ...@@ -116,14 +115,17 @@ def stream_video_clip(socket):
# Alternate between video with motion and video without motion # Alternate between video with motion and video without motion
for motion in (False, True): for motion in (False, True):
# Initialize FPS calculation
frame_beginning_time = time.time()
frame_number = 0 frame_number = 0
# Open the appropriate video file # Open the appropriate video file
video_path = with_animal_video if motion else no_animal_video video_path = with_animal_video if motion else no_animal_video
with videocapture(video_path) as video_capture: with videocapture(video_path) as video_capture:
if(video_capture is None):
logging.error("Could not open video capture.")
exit(1)
# Determine the number of frames to process according to the clip length # Determine the number of frames to process according to the clip length
if motion: if motion:
max_frames = int(video_capture.get(cv2.CAP_PROP_FRAME_COUNT)) # Process the entire clip to avoid creating incoherent clip max_frames = int(video_capture.get(cv2.CAP_PROP_FRAME_COUNT)) # Process the entire clip to avoid creating incoherent clip
...@@ -133,9 +135,12 @@ def stream_video_clip(socket): ...@@ -133,9 +135,12 @@ def stream_video_clip(socket):
logging.info(f"Motion: {motion}, Max Frame Count: {max_frames}") logging.info(f"Motion: {motion}, Max Frame Count: {max_frames}")
while frame_number < max_frames: while frame_number < max_frames:
# Initialize FPS calculation
frame_beginning_time = perf_counter()
frame_number += 1 frame_number += 1
success, frame = video_capture.read() success, frame = video_capture.read()
frame_start_time = time.time()
#Loop video clip if there are no more frame or if we cannot read the next frame. #Loop video clip if there are no more frame or if we cannot read the next frame.
# Used for looping the short clip where no animal are present # Used for looping the short clip where no animal are present
...@@ -153,18 +158,20 @@ def stream_video_clip(socket): ...@@ -153,18 +158,20 @@ def stream_video_clip(socket):
packet= CameraToMotionDetectorPacket(frame, str(camera_index), carrier) packet= CameraToMotionDetectorPacket(frame, str(camera_index), carrier)
socket.send(packet.pickle()) socket.send(packet.pickle())
logging.info(f"Frame sent: {frame_number}, {motion}, {frame_beginning_time}")
frame_number += 1 frame_number += 1
#Metric logging #Metric logging
frametime = time.time() - app_start_time frametime = perf_counter() - frame_beginning_time
logging.info(f"Frame time: {frametime}")
frametime_histogram.set(frametime) frametime_histogram.set(frametime)
#Sleep if needed to maintain frame rate
elapsed_time = time.time() - frame_beginning_time sleep_time = MIN_FRAME_TIME - frametime
sleep_time = MIN_FRAME_TIME - elapsed_time logging.info(f"fps: {1/frametime}, sleep time: {sleep_time}, fps at sleep time: {1/sleep_time}")
sleep_time_between_frame.set(sleep_time) sleep_time_between_frame.set(sleep_time)
time.sleep(max(0.0, sleep_time)) sleep(max(0.0, sleep_time))
except Exception as error: except Exception as error:
logging.error(f"Error sending frame: {error}") logging.error(f"Error sending frame: {error}")
socket.close() socket.close()
......
import datetime
import pickle
import time
from time import perf_counter
import cv2
import numpy as np
class CameraToMotionDetectorPacket:
def __init__(self, opencv_frame: np.ndarray, source_camera_identifier: str, telemetry_carrier: dict):
self._opencv_frame: np.ndarray = opencv_frame
self.source_camera_identifier = source_camera_identifier
self.timestamp = perf_counter()
self.telemetry_carrier = telemetry_carrier
def pickle (self):
#Make sure timestamp is up to date before sending
self.timestamp= perf_counter()
return pickle.dumps(self)
def decode_frame(self):
return self._opencv_frame
@staticmethod
def unpickle(buffer):
return pickle.loads(buffer)
\ No newline at end of file
...@@ -14,34 +14,76 @@ file_name = "Camera " ...@@ -14,34 +14,76 @@ file_name = "Camera "
index_value = os.environ.get("INDEX", str(random.randint(1, 10))) index_value = os.environ.get("INDEX", str(random.randint(1, 10)))
# Generate a random integer # Generate a random integer
resource=Resource.create({SERVICE_NAME: f"{file_name}{index_value}"}) resource=Resource.create({SERVICE_NAME: f"{file_name}{index_value}"})
DISABLE_OTEL = os.getenv("DISABLE_OTEL", "false").lower() == "true"
if DISABLE_OTEL:
class Dummy():
'''
Dummy that can be called and is also a context manager.
It will always return itself, so that you can chain calls.
'''
# Accessing attributes
def __getattr__(self, name):
return self
# Callable
def __call__(self, *args, **kwargs):
return self
# Context manager
def __enter__(self):
return self
def __exit__(self, *args, **kwargs):
pass
# Indexing, Subscripting, Slicing
def __getitem__(self, *args, **kwargs):
return self
def __setitem__(self, key, value):
self
# String representation
def __str__(self) -> str:
return '<Just a Dummy>'
tracer = Dummy()
meter = Dummy()
else:
# Set up the tracer provider for tracing # Set up the tracer provider for tracing
trace.set_tracer_provider( trace.set_tracer_provider(
TracerProvider( TracerProvider(
resource=resource resource=resource
)
) )
)
# Create an OpenTelemetry Collector exporter for exporting traces # Create an OpenTelemetry Collector exporter for exporting traces
otlp_trace_exporter = OTLPSpanExporter(endpoint="otel-collector:4317", insecure=True) otlp_trace_exporter = OTLPSpanExporter(endpoint="otel-collector:4317", insecure=True)
# Add the OpenTelemetry Collector exporter to the tracer provider # Add the OpenTelemetry Collector exporter to the tracer provider
trace.get_tracer_provider().add_span_processor( trace.get_tracer_provider().add_span_processor(
BatchSpanProcessor(otlp_trace_exporter) BatchSpanProcessor(otlp_trace_exporter)
) )
tracer = trace.get_tracer("camera_tracer") tracer = trace.get_tracer("camera_tracer")
# Set up the meter provider for metrics # Set up the meter provider for metrics
meter_provider = MeterProvider() meter_provider = MeterProvider()
# Create an OpenTelemetry Collector exporter for exporting metrics # Create an OpenTelemetry Collector exporter for exporting metrics
otlp_metrics_exporter = OTLPMetricExporter(endpoint="http://otel-collector:4317", insecure=True) otlp_metrics_exporter = OTLPMetricExporter(endpoint="http://otel-collector:4317", insecure=True)
# Register the OpenTelemetry Collector exporter with the metrics provider # Register the OpenTelemetry Collector exporter with the metrics provider
reader = PeriodicExportingMetricReader( reader = PeriodicExportingMetricReader(
OTLPMetricExporter(endpoint="http://otel-collector:4317",insecure=True) OTLPMetricExporter(endpoint="http://otel-collector:4317",insecure=True)
) )
meterProvider = MeterProvider(resource=resource, metric_readers=[reader]) meterProvider = MeterProvider(resource=resource, metric_readers=[reader])
metrics.set_meter_provider(meterProvider) metrics.set_meter_provider(meterProvider)
meter = metrics.get_meter("camera_meter") meter = metrics.get_meter("camera_meter")
\ No newline at end of file \ No newline at end of file
...@@ -16,17 +16,7 @@ class MotionDetectorToObjectRecognizerPacket: ...@@ -16,17 +16,7 @@ class MotionDetectorToObjectRecognizerPacket:
def pickle(self): def pickle(self):
self.timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return pickle.dumps(self)
data = {
"opencv_frame": self._opencv_frame,
"source_camera_identifier": self.source_camera_identifier,
"timestamp": self.timestamp,
"camera_timestamp" : self.camera_timestamp,
"telemetry_carrier": self.telemetry_carrier,
"contour": self.contour
}
return pickle.dumps(data)
def decode_frame(self): def decode_frame(self):
...@@ -34,11 +24,5 @@ class MotionDetectorToObjectRecognizerPacket: ...@@ -34,11 +24,5 @@ class MotionDetectorToObjectRecognizerPacket:
@staticmethod @staticmethod
def unpickle(buffer): def unpickle(buffer):
data = pickle.loads(buffer) return pickle.loads(buffer)
return MotionDetectorToObjectRecognizerPacket(cv2.imdecode(data["opencv_frame"], cv2.IMREAD_COLOR),
data["source_camera_identifier"],
data["camera_timestamp"],
data["telemetry_carrier"],
data["contour"])
# Use the official Python image as base # Use the official Python image as base
FROM python:3.12-slim as build FROM python:3.12-slim-bookworm as build
# Set the working directory inside the container # Set the working directory inside the container
WORKDIR /app WORKDIR /app
...@@ -13,6 +13,8 @@ WORKDIR /app ...@@ -13,6 +13,8 @@ WORKDIR /app
COPY . . COPY . .
# Install required Python packages # Install required Python packages
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && apt install -y libzmq3-dev && rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir -r requirements.txt RUN pip install --no-cache-dir -r requirements.txt
# Set environment variables # Set environment variables
......
...@@ -7,4 +7,5 @@ opentelemetry-exporter-jaeger ...@@ -7,4 +7,5 @@ opentelemetry-exporter-jaeger
opentelemetry-exporter-otlp opentelemetry-exporter-otlp
opentelemetry-exporter-otlp-proto-grpc opentelemetry-exporter-otlp-proto-grpc
psutil psutil
pyzmq pyzmq
\ No newline at end of file cffi
\ No newline at end of file
import datetime
import pickle
import time
import cv2
import numpy as np
class CameraToMotionDetectorPacket:
def __init__(self, opencv_frame: np.ndarray, source_camera_identifier: str, telemetry_carrier: dict):
self._opencv_frame: np.ndarray = opencv_frame
self.source_camera_identifier = source_camera_identifier
self.timestamp = time.perf_counter()
self.telemetry_carrier = telemetry_carrier
def pickle (self):
#Make sure timestamp is up to date before sending
self.timestamp= time.perf_counter()
return pickle.dumps(self)
def decode_frame(self):
return self._opencv_frame
@staticmethod
def unpickle(buffer):
return pickle.loads(buffer)
\ No newline at end of file
...@@ -3,8 +3,9 @@ import datetime ...@@ -3,8 +3,9 @@ import datetime
import logging # Import the logging module import logging # Import the logging module
import os import os
import pickle import pickle
import socket
import time import time
from time import perf_counter
import cv2 import cv2
import imutils import imutils
...@@ -12,8 +13,8 @@ import psutil ...@@ -12,8 +13,8 @@ import psutil
import zmq import zmq
from opentelemetry.propagate import extract, inject from opentelemetry.propagate import extract, inject
from services.common.camera_to_motiondetector_packet import CameraToMotionDetectorPacket from camera_to_motiondetector_packet import CameraToMotionDetectorPacket
from services.common.motion_detector_to_object_recognizer_packet import MotionDetectorToObjectRecognizerPacket from motion_detector_to_object_recognizer_packet import MotionDetectorToObjectRecognizerPacket
from telemetry.tracerprovider import tracer, meter from telemetry.tracerprovider import tracer, meter
# Configure logging # Configure logging
...@@ -22,10 +23,11 @@ logging.basicConfig( ...@@ -22,10 +23,11 @@ logging.basicConfig(
level=logging.INFO, # You can change this to DEBUG, ERROR, etc. level=logging.INFO, # You can change this to DEBUG, ERROR, etc.
handlers=[ handlers=[
logging.StreamHandler(), # Log to console logging.StreamHandler(), # Log to console
logging.FileHandler("/app/output/motion_detector.log") # Log to a file #logging.FileHandler("/app/output/motion_detector.log") # Log to a file
] ]
) )
fps_histo = meter.create_histogram( fps_histo = meter.create_histogram(
name="md_fps_histo", name="md_fps_histo",
description="Frames per second", description="Frames per second",
...@@ -73,7 +75,6 @@ def detect_motion(frame, source_camera_identifier, trace_carrier): ...@@ -73,7 +75,6 @@ def detect_motion(frame, source_camera_identifier, trace_carrier):
with tracer.start_as_current_span("processing the frame",context=extracted_context) as span: with tracer.start_as_current_span("processing the frame",context=extracted_context) as span:
try: try:
inject(trace_carrier) inject(trace_carrier)
logging.debug("Frame loaded for processing.")
logging.debug(f"FRAME RECEIVE FROM CLIENT: {source_camera_identifier} | TIME: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") logging.debug(f"FRAME RECEIVE FROM CLIENT: {source_camera_identifier} | TIME: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
...@@ -82,7 +83,7 @@ def detect_motion(frame, source_camera_identifier, trace_carrier): ...@@ -82,7 +83,7 @@ def detect_motion(frame, source_camera_identifier, trace_carrier):
if first_frame is None: if first_frame is None:
first_frame = gray first_frame = gray
logging.info("Initialized reference frame for motion detection.") logging.debug("Initialized reference frame for motion detection.")
continue continue
starting_processing_time = time.time() starting_processing_time = time.time()
...@@ -102,6 +103,9 @@ def detect_motion(frame, source_camera_identifier, trace_carrier): ...@@ -102,6 +103,9 @@ def detect_motion(frame, source_camera_identifier, trace_carrier):
cv2.CHAIN_APPROX_SIMPLE) cv2.CHAIN_APPROX_SIMPLE)
contours = imutils.grab_contours(contours) contours = imutils.grab_contours(contours)
if len(contours) == 0:
logging.debug("No contours detected.")
detected_cnt = 0 detected_cnt = 0
detected = False detected = False
bounding_rectangle = () bounding_rectangle = ()
...@@ -110,7 +114,7 @@ def detect_motion(frame, source_camera_identifier, trace_carrier): ...@@ -110,7 +114,7 @@ def detect_motion(frame, source_camera_identifier, trace_carrier):
continue continue
detected = True detected = True
detected_cnt += 1 detected_cnt += 1
logging.debug(f"Motion detected. Contour area: {cv2.contourArea(contour)}.") logging.info(f"Motion detected. Contour area: {cv2.contourArea(contour)}.")
(x, y, w, h) = cv2.boundingRect(contour) (x, y, w, h) = cv2.boundingRect(contour)
bounding_rectangle = (x, y, w, h) bounding_rectangle = (x, y, w, h)
...@@ -133,49 +137,53 @@ def main(): ...@@ -133,49 +137,53 @@ def main():
# Retrieve environment variables instead of command-line arguments # Retrieve environment variables instead of command-line arguments
or_host_ip = os.getenv('OR_HOST', 'localhost') # Default to 'localhost' or_host_ip = os.getenv('OR_HOST', 'localhost') # Default to 'localhost'
or_port = int(os.getenv('OR_PORT', 9999)) # Default to 9999 or_port = int(os.getenv('OR_PORT', 9999)) # Default to 9999
host_name = socket.gethostname() #host_name = socket.gethostname()
host_ip = socket.gethostbyname(host_name) #host_ip = socket.gethostbyname(host_name)
logging.info(f'HOST IP: {host_ip}') #logging.info(f'HOST IP: {host_ip}')
host_port = 9998 host_port = 9998
context = zmq.Context context = zmq.Context()
camera_socket = context.socket(zmq.PAIR) camera_socket = context.socket(zmq.PAIR)
camera_socket.bind(f"tcp://{host_ip}:{host_port}") camera_socket.bind(f"tcp://localhost:{host_port}")
logging.info(f'Camera socket bound to {host_port}')
or_socket_context = zmq.Context() or_socket = context.socket(zmq.PAIR)
or_socket = or_socket_context.socket(zmq.PAIR) logging.info(f"Connecting to {or_host_ip}:{or_port}")
or_socket.connect(f"tcp://{or_host_ip}:{or_port}") or_socket.connect(f"tcp://{or_host_ip}:{or_port}")
logging.info(f"connected to {or_host_ip}:{or_port}")
while True: while True:
try:
message = camera_socket.recv() message = camera_socket.recv()
camera_packet: CameraToMotionDetectorPacket = pickle.loads(message) camera_packet: CameraToMotionDetectorPacket = pickle.loads(message)
transmission_time = datetime.datetime.now() - camera_packet.timestamp transmission_time = perf_counter() - camera_packet.timestamp
transmission_time_in_seconds = transmission_time.total_seconds() c2e_transmission_time.set(transmission_time)
c2e_transmission_time.set(transmission_time_in_seconds) logging.info(f"Frame received with transmission time: {transmission_time} seconds.")
logging.info(f"Frame received with transmission time: {transmission_time_in_seconds} seconds.")
starting_processing_time = perf_counter()
starting_processing_time = time.time()
frame = camera_packet.decode_frame()
frame = camera_packet.decode_frame() cv2.imshow("Frame", frame)
flag, contours = detect_motion(frame, camera_packet.source_camera_identifier, cv2.waitKey(1)
camera_packet.telemetry_carrier)
if frame is None:
if flag: logging.error("Invalid frame received.")
md_packet = MotionDetectorToObjectRecognizerPacket(frame, camera_packet.source_camera_identifier,
camera_packet.telemetry_carrier, contours) flag, contours = detect_motion(frame, camera_packet.source_camera_identifier,
pickled = md_packet.pickle() camera_packet.telemetry_carrier)
logging.info(f"Packet size: {len(pickled)} bytes.") # Log the size of the packet #logging.INFO(str(flag),str(contours))
or_socket.send(pickled) if flag:
logging.info("Frame successfully sent to Object Recognizer.") md_packet = MotionDetectorToObjectRecognizerPacket(frame, camera_packet.source_camera_identifier,
camera_packet.timestamp,
processing_time.set(time.time() - starting_processing_time) camera_packet.telemetry_carrier, contours)
logging.debug("Processing time logged for frame.") pickled = md_packet.pickle()
except Exception as error: logging.info(f"Packet size: {len(pickled)} bytes.") # Log the size of the packet
logging.error(f"Error in event loop: {error}") or_socket.send(pickled)
time.sleep(1) logging.info("Frame successfully sent to Object Recognizer.")
continue
processing_time.set(time.time() - starting_processing_time)
logging.debug("Processing time logged for frame.")
......
import datetime
import pickle
import cv2
import numpy as np
class MotionDetectorToObjectRecognizerPacket:
def __init__(self, opencv_frame: np.ndarray, source_camera_identifier: str, camera_timestamp, telemetry_carrier: dict, contour: np.ndarray):
_, self._opencv_frame = cv2.imencode('.jpg', opencv_frame)
self.source_camera_identifier = source_camera_identifier
self.timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.camera_timestamp = camera_timestamp
self.telemetry_carrier = telemetry_carrier
self.contour = contour # OpenCV contour data
def pickle(self):
self.timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return pickle.dumps(self)
def decode_frame(self):
return cv2.imdecode(self._opencv_frame, cv2.IMREAD_COLOR)
@staticmethod
def unpickle(buffer):
return pickle.loads(buffer)
...@@ -11,42 +11,70 @@ from opentelemetry.sdk.metrics import MeterProvider ...@@ -11,42 +11,70 @@ from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
# Extract the file name without extension # Extract the file name without extension
file_name = "Motion Detector " file_name = "Motion Detector "
# try:
# with open('../index.txt', 'r') as file:
# index_value = int(file.read().strip())
# except (FileNotFoundError, ValueError) as e:
# print(f"Error reading index.txt: {e}")
# index_value = random.randint(1, 10)
index_value = os.environ.get("INDEX", str(random.randint(1, 10))) index_value = os.environ.get("INDEX", str(random.randint(1, 10)))
resource=Resource.create({SERVICE_NAME: f"{file_name}{index_value}"}) resource=Resource.create({SERVICE_NAME: f"{file_name}{index_value}"})
# Set up the tracer provider for tracing # Disable OpenTelemetry if running locally
trace.set_tracer_provider( DISABLE_OTEL = os.environ.get("DISABLE_OTEL", 'False')
TracerProvider(
resource=resource if DISABLE_OTEL:
class Dummy():
'''
Dummy that can be called and is also a context manager.
It will always return itself, so that you can chain calls.
'''
# Accessing attributes
def __getattr__(self, name):
return self
# Callable
def __call__(self, *args, **kwargs):
return self
# Context manager
def __enter__(self):
return self
def __exit__(self, *args, **kwargs):
pass
# Indexing, Subscripting, Slicing
def __getitem__(self, *args, **kwargs):
return self
def __setitem__(self, key, value):
self
# String representation
def __str__(self) -> str:
return '<Just a Dummy>'
tracer = Dummy()
meter = Dummy()
else:
# Set up the tracer provider for tracing
trace.set_tracer_provider(
TracerProvider(
resource=resource
)
) )
)
# Create an OpenTelemetry Collector exporter for exporting traces # Create an OpenTelemetry Collector exporter for exporting traces
otlp_trace_exporter = OTLPSpanExporter(endpoint="otel-collector:4317", insecure=True) otlp_trace_exporter = OTLPSpanExporter(endpoint="otel-collector:4317", insecure=True)
# Add the OpenTelemetry Collector exporter to the tracer provider # Add the OpenTelemetry Collector exporter to the tracer provider
trace.get_tracer_provider().add_span_processor( trace.get_tracer_provider().add_span_processor(
BatchSpanProcessor(otlp_trace_exporter) BatchSpanProcessor(otlp_trace_exporter)
) )
tracer = trace.get_tracer("motion detector tracer") tracer = trace.get_tracer("motion detector tracer")
# Set up the meter provider for metrics # Set up the meter provider for metrics
meter_provider = MeterProvider() meter_provider = MeterProvider()
# Create an OpenTelemetry Collector exporter for exporting metrics # Create an OpenTelemetry Collector exporter for exporting metrics
otlp_metrics_exporter = OTLPMetricExporter(endpoint="http://otel-collector:4317", insecure=True) otlp_metrics_exporter = OTLPMetricExporter(endpoint="http://otel-collector:4317", insecure=True)
# Register the OpenTelemetry Collector exporter with the metrics provider # Register the OpenTelemetry Collector exporter with the metrics provider
reader = PeriodicExportingMetricReader( reader = PeriodicExportingMetricReader(
OTLPMetricExporter(endpoint="http://otel-collector:4317",insecure=True) OTLPMetricExporter(endpoint="http://otel-collector:4317",insecure=True)
) )
meterProvider = MeterProvider(resource=resource, metric_readers=[reader]) meterProvider = MeterProvider(resource=resource, metric_readers=[reader])
metrics.set_meter_provider(meterProvider) metrics.set_meter_provider(meterProvider)
meter = metrics.get_meter("motion detector meter") meter = metrics.get_meter("motion detector meter")
\ No newline at end of file \ No newline at end of file
...@@ -11,8 +11,9 @@ WORKDIR /app ...@@ -11,8 +11,9 @@ WORKDIR /app
# Copy the server code into the container # Copy the server code into the container
COPY . . COPY . .
# Install required Python packages ENV DEBIAN_FRONTEND=noninteractive
RUN pip install --no-cache-dir -r requirements.txt RUN apt update && apt install -y libzmq3-dev && rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir -r requirements.txt
# Expose port 5000 # Expose port 5000
EXPOSE 5000 EXPOSE 5000
......
...@@ -8,4 +8,5 @@ opentelemetry-exporter-otlp ...@@ -8,4 +8,5 @@ opentelemetry-exporter-otlp
opentelemetry-exporter-otlp-proto-grpc opentelemetry-exporter-otlp-proto-grpc
docker docker
flask flask
pyzmq pyzmq
\ No newline at end of file cffi
\ No newline at end of file
import datetime
import pickle
import cv2
import numpy as np
class MotionDetectorToObjectRecognizerPacket:
def __init__(self, opencv_frame: np.ndarray, source_camera_identifier: str, camera_timestamp, telemetry_carrier: dict, contour: np.ndarray):
_, self._opencv_frame = cv2.imencode('.jpg', opencv_frame)
self.source_camera_identifier = source_camera_identifier
self.timestamp = datetime.datetime.now()
self.camera_timestamp = camera_timestamp
self.telemetry_carrier = telemetry_carrier
self.contour = contour # OpenCV contour data
def pickle(self):
self.timestamp = datetime.datetime.now()
return pickle.dumps(self)
def decode_frame(self):
return cv2.imdecode(self._opencv_frame, cv2.IMREAD_COLOR)
@staticmethod
def unpickle(buffer):
return pickle.loads(buffer)
...@@ -8,7 +8,7 @@ import zmq ...@@ -8,7 +8,7 @@ import zmq
from opentelemetry.propagate import extract from opentelemetry.propagate import extract
from model.model import recognize from model.model import recognize
from services.common.motion_detector_to_object_recognizer_packet import MotionDetectorToObjectRecognizerPacket from motion_detector_to_object_recognizer_packet import MotionDetectorToObjectRecognizerPacket
from telemetry.tracerprovider import meter, tracer from telemetry.tracerprovider import meter, tracer
from webserver import run_flask from webserver import run_flask
...@@ -103,6 +103,7 @@ def main(): ...@@ -103,6 +103,7 @@ def main():
while True: while True:
try: try:
logging.info("Waiting for new frame...")
receive_frames(server_socket, frame_queue) receive_frames(server_socket, frame_queue)
except Exception as e: except Exception as e:
logging.error(f"Error in server loop: {e}") logging.error(f"Error in server loop: {e}")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment