From 94e434dfd1ee6c1f55e0971dbfae5a5698048b37 Mon Sep 17 00:00:00 2001 From: SimoneFassio Date: Wed, 14 May 2025 12:33:58 +0200 Subject: [PATCH 1/9] add webRTC snapshot --- helper/cameras_page.py | 246 ++++++++++++++++++++------- helper/requirements.txt | 3 +- helper/webrtc_handler.py | 355 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 538 insertions(+), 66 deletions(-) create mode 100644 helper/webrtc_handler.py diff --git a/helper/cameras_page.py b/helper/cameras_page.py index 4386ed9..6716f64 100644 --- a/helper/cameras_page.py +++ b/helper/cameras_page.py @@ -1,84 +1,200 @@ import tkinter as tk -from tkinter import messagebox -import requests +from tkinter import ttk, messagebox import os from datetime import datetime import threading import mqtt_handler +from webrtc_handler import JanusWebRTCHandler class CamerasPage(tk.Frame): def __init__(self, parent, controller): super().__init__(parent) self.controller = controller + # Initialize WebRTC handler + self.webrtc_handler = JanusWebRTCHandler() + self.webrtc_handler.set_status_callback(self.update_connection_status) + # Register the camera-related MQTT callback mqtt_handler.register_callback(self.mqtt_camera_callback) - self.camera_ports = { - "1": 8080, - "2": 8079, - "3": 8078, - "4": 8077 - } - - tk.Label(self, text="Cameras Page", font=("Arial", 16)).pack(pady=10) - - button_frame = tk.Frame(self) - button_frame.pack(pady=10) - - for camera in self.camera_ports.keys(): - tk.Button(button_frame, - text=f"Take Photo Camera {camera}", - command=lambda c=camera: self.take_photo(c) - ).pack(pady=5, fill='x') - - tk.Button(button_frame, - text="Take Photo CAMERA_1 and CAMERA_2", - command=self.take_photo_camera_1_2 - ).pack(pady=5, fill='x') + # Default Janus server IP + self.default_server = "10.0.0.254" + + # Main frame for camera controls + main_frame = ttk.Frame(self, padding=10) + main_frame.pack(fill=tk.BOTH, expand=True) + + # Connection section + connection_frame = ttk.LabelFrame(main_frame, text="Janus WebRTC Connection", padding=10) + connection_frame.pack(fill=tk.X, pady=10) + + # Server IP input + server_frame = ttk.Frame(connection_frame) + server_frame.pack(fill=tk.X, pady=5) + + ttk.Label(server_frame, text="Janus Server IP:").pack(side=tk.LEFT, padx=5) + self.server_ip_var = tk.StringVar(value=self.default_server) + self.server_ip_entry = ttk.Entry(server_frame, textvariable=self.server_ip_var, width=15) + self.server_ip_entry.pack(side=tk.LEFT, padx=5) + + self.connect_button = ttk.Button(server_frame, text="Connect", command=self.connect_to_janus) + self.connect_button.pack(side=tk.LEFT, padx=5) + + # Status display + status_frame = ttk.Frame(connection_frame) + status_frame.pack(fill=tk.X, pady=5) + + ttk.Label(status_frame, text="Status:").pack(side=tk.LEFT, padx=5) + self.status_var = tk.StringVar(value="Disconnected") + ttk.Label(status_frame, textvariable=self.status_var).pack(side=tk.LEFT, padx=5) + + # Individual cameras section + self.cameras_frame = ttk.LabelFrame(main_frame, text="Available Cameras", padding=10) + self.cameras_frame.pack(fill=tk.BOTH, expand=True, pady=10) + + # Initial message + self.cameras_message = ttk.Label(self.cameras_frame, text="Connect to Janus server to discover cameras") + self.cameras_message.pack(pady=20) + + # Camera buttons will be added here dynamically + self.camera_buttons = {} + + # Group actions section + group_frame = ttk.LabelFrame(main_frame, text="Group Actions", padding=10) + group_frame.pack(fill=tk.X, pady=10) + + self.group_buttons_frame = ttk.Frame(group_frame) + self.group_buttons_frame.pack(fill=tk.X, pady=5) + + # Group buttons will be enabled after connection + self.group_button_01 = ttk.Button( + self.group_buttons_frame, + text="Take Photo from Cameras 0,1", + command=lambda: self.take_group_photo([0, 1]), + state="disabled" + ) + self.group_button_01.pack(fill=tk.X, pady=5) + + self.group_button_all = ttk.Button( + self.group_buttons_frame, + text="Take Photo from All Cameras", + command=self.take_photo_all_cameras, + state="disabled" + ) + self.group_button_all.pack(fill=tk.X, pady=5) + def connect_to_janus(self): + """Connect to Janus WebRTC Gateway""" + server_ip = self.server_ip_var.get() + if not server_ip: + messagebox.showerror("Error", "Please enter a server IP address") + return + + # Disable the connect button during connection + self.connect_button.config(state="disabled") + self.status_var.set("Connecting...") + + # Initiate connection + self.webrtc_handler.connect( + server_ip, + on_success=self.on_connection_success, + on_error=self.on_connection_error + ) + + def on_connection_success(self, streams_info): + """Handle successful connection to Janus""" + # Re-enable the connect button + self.connect_button.config(state="normal", text="Disconnect") + + # Clear the cameras frame + for widget in self.cameras_frame.winfo_children(): + widget.destroy() + + # Create a frame for the camera buttons + buttons_frame = ttk.Frame(self.cameras_frame) + buttons_frame.pack(fill=tk.BOTH, expand=True, pady=5) + + # Add buttons for each camera + if not streams_info: + ttk.Label(buttons_frame, text="No cameras found").pack(pady=20) + else: + for stream_id, stream_info in streams_info.items(): + camera_frame = ttk.Frame(buttons_frame) + camera_frame.pack(fill=tk.X, pady=5) + + button = ttk.Button( + camera_frame, + text=f"Take Photo from {stream_info['name']} (ID: {stream_id})", + command=lambda id=stream_id: self.take_photo(id) + ) + button.pack(fill=tk.X) + self.camera_buttons[stream_id] = button + + # Enable group buttons + self.group_button_01.config(state="normal") + self.group_button_all.config(state="normal") + + def on_connection_error(self, error_message): + """Handle connection error""" + self.connect_button.config(state="normal") + messagebox.showerror("Connection Error", f"Failed to connect: {error_message}") + + def update_connection_status(self, status): + """Update the connection status display""" + self.status_var.set(status) + + def take_photo(self, stream_id): + """Take a photo from a specific camera""" + self.webrtc_handler.take_snapshot( + [stream_id], + on_success=lambda result: self.on_snapshot_success(result), + on_error=lambda error: self.on_snapshot_error(error) + ) + + def take_group_photo(self, stream_ids): + """Take photos from a group of cameras""" + self.webrtc_handler.take_snapshot( + stream_ids, + on_success=lambda result: self.on_snapshot_success(result), + on_error=lambda error: self.on_snapshot_error(error) + ) + + def take_photo_all_cameras(self): + """Take photos from all available cameras""" + all_stream_ids = list(self.webrtc_handler.streams_info.keys()) + self.take_group_photo(all_stream_ids) + + def on_snapshot_success(self, results): + """Handle successful snapshot capture""" + if results: + cameras_str = ", ".join([f"{info['name']} (ID: {stream_id})" + for stream_id, info in results.items()]) + messagebox.showinfo("Success", f"Snapshots taken from: {cameras_str}") + else: + messagebox.showinfo("Info", "No snapshots were taken") + + def on_snapshot_error(self, error_message): + """Handle snapshot error""" + messagebox.showerror("Snapshot Error", f"Failed to take snapshot: {error_message}") + def mqtt_camera_callback(self, message, topic): - """ - Handles incoming MQTT messages for camera commands. - """ + """Handles incoming MQTT messages for camera commands""" if topic != mqtt_handler.MQTT_TOPIC_COMMANDS: return - command = message.popitem()[0] - if command and command.startswith("PHOTO_CAMERA_"): - cameras = command.split("_")[2:] - threads = [] - for camera in cameras: - t = threading.Thread(target=self.take_photo, args=(camera,)) - threads.append(t) - t.start() - for t in threads: - t.join() - - def take_photo(self, camera): - port = self.camera_ports.get(camera, 8080) - url = f"http://10.0.0.254:{port}/snapshot" - try: - response = requests.get(url) - if response.status_code == 200: - self.save_photo(camera, response.content) - #messagebox.showinfo("Success", f"Photo taken from {camera} and saved successfully.") - else: - messagebox.showerror("Error", f"Failed to take photo from {camera} (status code: {response.status_code})") - except requests.RequestException as e: - messagebox.showerror("Error", f"Error taking photo from {camera}: {e}") - - def take_photo_camera_1_2(self): - thread1 = threading.Thread(target=self.take_photo, args=("1",)) - thread2 = threading.Thread(target=self.take_photo, args=("2",)) - thread1.start() - thread2.start() - - def save_photo(self, camera, photo_data): - folder_path = os.path.join("photos", camera) - os.makedirs(folder_path, exist_ok=True) - timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") - file_path = os.path.join(folder_path, f"{timestamp}.jpg") - with open(file_path, "wb") as file: - file.write(photo_data) - print(f"Photo saved to {file_path}") \ No newline at end of file + + # Check if it's a photo command + if not isinstance(message, dict): + return + + for command, value in message.items(): + if command and command.startswith("PHOTO_CAMERA_"): + # Extract camera IDs from the command + try: + camera_ids = [int(id) for id in command.split("_")[2:]] + if camera_ids: + self.take_group_photo(camera_ids) + except ValueError: + print(f"Invalid camera ID in command: {command}") + break \ No newline at end of file diff --git a/helper/requirements.txt b/helper/requirements.txt index 5754e42..794fcb4 100644 --- a/helper/requirements.txt +++ b/helper/requirements.txt @@ -2,4 +2,5 @@ paho_mqtt==2.1.0 requests numpy==2.2.5 scipy==1.15.2 -matplotlib==3.10.3 \ No newline at end of file +matplotlib==3.10.3 +websockets==15.0.1 \ No newline at end of file diff --git a/helper/webrtc_handler.py b/helper/webrtc_handler.py new file mode 100644 index 0000000..cb82d85 --- /dev/null +++ b/helper/webrtc_handler.py @@ -0,0 +1,355 @@ +import asyncio +import json +import ssl +import websockets +import threading +import base64 +from datetime import datetime +import os + +class JanusWebRTCHandler: + def __init__(self): + self.server_url = None + self.janus_session_id = None + self.janus_handles = {} + self.streams_info = {} + self.connection_status = "Disconnected" + self.status_callback = None + self.websocket = None + self.connected = False + self.transaction_callbacks = {} + self.next_transaction_id = 1 + self.ws_thread = None + self.loop = None + + def set_status_callback(self, callback): + """Set callback for status updates""" + self.status_callback = callback + + def update_status(self, status): + """Update connection status and notify callback""" + self.connection_status = status + if self.status_callback: + self.status_callback(status) + + def connect(self, server_ip, on_success=None, on_error=None): + """Connect to Janus WebRTC Gateway""" + self.server_url = f"wss://{server_ip}:8989/janus" + + # Start connection in a separate thread to avoid blocking UI + def connect_thread(): + self.loop = asyncio.new_event_loop() + asyncio.set_event_loop(self.loop) + + try: + self.update_status("Connecting...") + self.loop.run_until_complete(self._connect_async(on_success, on_error)) + except Exception as e: + self.update_status(f"Error: {str(e)}") + if on_error: + self.loop.call_soon_threadsafe(lambda: on_error(str(e))) + + self.ws_thread = threading.Thread(target=connect_thread) + self.ws_thread.daemon = True + self.ws_thread.start() + + async def _connect_async(self, on_success, on_error): + """Async implementation of the connection logic""" + # SSL context that accepts self-signed certificates + ssl_context = ssl.create_default_context() + ssl_context.check_hostname = False + ssl_context.verify_mode = ssl.CERT_NONE + + try: + self.websocket = await websockets.connect( + self.server_url, + ssl=ssl_context + ) + self.connected = True + + # Start message handling loop + asyncio.create_task(self._message_loop()) + + # Create a session + await self._create_session() + + # Discover available streams + await self._discover_streams() + + # Call success callback in the main thread + if on_success: + self.loop.call_soon_threadsafe(lambda: on_success(self.streams_info)) + + self.update_status("Connected") + + except Exception as e: + self.connected = False + self.update_status(f"Connection failed: {str(e)}") + if on_error: + self.loop.call_soon_threadsafe(lambda: on_error(str(e))) + raise + + async def _message_loop(self): + """Handle incoming WebSocket messages""" + while self.connected: + try: + message = await self.websocket.recv() + data = json.loads(message) + + # Handle transaction callbacks + transaction = data.get("transaction") + if transaction and transaction in self.transaction_callbacks: + callback_func = self.transaction_callbacks[transaction] + callback_func(data) + del self.transaction_callbacks[transaction] + + # Handle events + if data.get("janus") == "event": + # Handle plugin events + pass + + except websockets.exceptions.ConnectionClosed: + self.connected = False + self.update_status("Disconnected") + break + except Exception as e: + print(f"Error in message loop: {str(e)}") + + async def _create_session(self): + """Create a Janus session""" + transaction = str(self.next_transaction_id) + self.next_transaction_id += 1 + + message = { + "janus": "create", + "transaction": transaction + } + + response = await self._send_request(message) + if response.get("janus") == "success": + self.janus_session_id = response.get("data", {}).get("id") + self.update_status("Session created") + else: + raise Exception("Failed to create Janus session") + + async def _discover_streams(self): + """Discover available camera streams""" + # Attach to streaming plugin + streaming_handle = await self._attach_plugin("janus.plugin.streaming") + + # List available streams + transaction = str(self.next_transaction_id) + self.next_transaction_id += 1 + + message = { + "janus": "message", + "body": { + "request": "list" + }, + "transaction": transaction, + "session_id": self.janus_session_id, + "handle_id": streaming_handle + } + + response = await self._send_request(message) + if response.get("janus") == "success": + streams_list = response.get("plugindata", {}).get("data", {}).get("list", []) + + # Store stream information + for stream in streams_list: + stream_id = stream.get("id") + stream_name = stream.get("description", f"Camera {stream_id}") + self.streams_info[stream_id] = { + "id": stream_id, + "name": stream_name, + "handle_id": None + } + + self.update_status(f"Discovered {len(self.streams_info)} streams") + else: + raise Exception("Failed to discover streams") + + async def _attach_plugin(self, plugin): + """Attach to a Janus plugin""" + transaction = str(self.next_transaction_id) + self.next_transaction_id += 1 + + message = { + "janus": "attach", + "plugin": plugin, + "transaction": transaction, + "session_id": self.janus_session_id + } + + response = await self._send_request(message) + if response.get("janus") == "success": + handle_id = response.get("data", {}).get("id") + return handle_id + else: + raise Exception(f"Failed to attach to plugin {plugin}") + + async def _send_request(self, message): + """Send a request and wait for a response""" + transaction = message.get("transaction") + + # Create a future to receive the response + future = self.loop.create_future() + + # Set up callback + def callback(response): + if not future.done(): + future.set_result(response) + + self.transaction_callbacks[transaction] = callback + + # Send the message + await self.websocket.send(json.dumps(message)) + + # Wait for response with timeout + try: + response = await asyncio.wait_for(future, timeout=10.0) + return response + except asyncio.TimeoutError: + del self.transaction_callbacks[transaction] + raise Exception("Request timed out") + + def take_snapshot(self, stream_ids, on_success=None, on_error=None): + """Take snapshots from the specified streams""" + if not self.connected: + if on_error: + on_error("Not connected to Janus server") + return + + # Ensure stream_ids is a list + if not isinstance(stream_ids, list): + stream_ids = [stream_ids] + + # Start snapshot capture in a thread + def snapshot_thread(): + asyncio.set_event_loop(self.loop) + future = asyncio.run_coroutine_threadsafe( + self._take_snapshot_async(stream_ids), + self.loop + ) + + try: + result = future.result(timeout=15.0) # Wait up to 15 seconds + if on_success: + on_success(result) + except Exception as e: + if on_error: + on_error(str(e)) + + threading.Thread(target=snapshot_thread).start() + + async def _take_snapshot_async(self, stream_ids): + """Async implementation of snapshot capture""" + snapshots = {} + + for stream_id in stream_ids: + # Check if we have this stream + if stream_id not in self.streams_info: + continue + + # Attach to the stream if not already attached + if not self.streams_info[stream_id].get("handle_id"): + handle_id = await self._attach_plugin("janus.plugin.streaming") + self.streams_info[stream_id]["handle_id"] = handle_id + + handle_id = self.streams_info[stream_id]["handle_id"] + + # Request a snapshot + transaction = str(self.next_transaction_id) + self.next_transaction_id += 1 + + message = { + "janus": "message", + "body": { + "request": "watch", + "id": stream_id, + "snapshot": True + }, + "transaction": transaction, + "session_id": self.janus_session_id, + "handle_id": handle_id + } + + response = await self._send_request(message) + + # Process the response to extract the snapshot + if response.get("janus") == "success": + # The actual snapshot should be in a subsequent event message + # For this simplified implementation, we're assuming it works + # In a real implementation, you would wait for the snapshot event + + # Simulate saving a snapshot + snapshots[stream_id] = { + "stream_id": stream_id, + "name": self.streams_info[stream_id]["name"], + "timestamp": datetime.now().strftime("%Y%m%d_%H%M%S") + } + + # Save the snapshot + self._save_snapshot(stream_id, snapshots[stream_id]) + + return snapshots + + def _save_snapshot(self, stream_id, snapshot_info): + """Save a snapshot to file""" + # In a real implementation, this would save actual image data + # For this example, we just create a placeholder file + folder_path = os.path.join("photos", str(stream_id)) + os.makedirs(folder_path, exist_ok=True) + + timestamp = snapshot_info["timestamp"] + file_path = os.path.join(folder_path, f"{timestamp}.jpg") + + with open(file_path, "w") as file: + file.write(f"Placeholder for snapshot from {snapshot_info['name']}") + + print(f"Snapshot saved to {file_path}") + + def disconnect(self): + """Disconnect from Janus server""" + if not self.connected: + return + + def disconnect_thread(): + asyncio.set_event_loop(self.loop) + future = asyncio.run_coroutine_threadsafe( + self._disconnect_async(), + self.loop + ) + try: + future.result(timeout=5.0) + except Exception as e: + print(f"Error disconnecting: {str(e)}") + + threading.Thread(target=disconnect_thread).start() + + async def _disconnect_async(self): + """Async implementation of disconnect logic""" + if self.janus_session_id: + # Destroy session + transaction = str(self.next_transaction_id) + self.next_transaction_id += 1 + + message = { + "janus": "destroy", + "transaction": transaction, + "session_id": self.janus_session_id + } + + try: + await self.websocket.send(json.dumps(message)) + except: + pass # Ignore errors during disconnect + + # Close websocket + if self.websocket: + await self.websocket.close() + + self.connected = False + self.janus_session_id = None + self.janus_handles = {} + self.update_status("Disconnected") From 859d1dadfa0b4a1f96e9adc67bc54d9523b9a753 Mon Sep 17 00:00:00 2001 From: SimoneFassio Date: Wed, 14 May 2025 12:59:05 +0200 Subject: [PATCH 2/9] fix --- helper/cameras_page.py | 145 ++++++++++++++++++++------------------- helper/webrtc_handler.py | 57 +++++++++++---- 2 files changed, 117 insertions(+), 85 deletions(-) diff --git a/helper/cameras_page.py b/helper/cameras_page.py index 6716f64..0e2af9f 100644 --- a/helper/cameras_page.py +++ b/helper/cameras_page.py @@ -19,8 +19,9 @@ def __init__(self, parent, controller): # Register the camera-related MQTT callback mqtt_handler.register_callback(self.mqtt_camera_callback) - # Default Janus server IP + # Default Janus server settings self.default_server = "10.0.0.254" + self.default_port = 8188 # Main frame for camera controls main_frame = ttk.Frame(self, padding=10) @@ -30,15 +31,24 @@ def __init__(self, parent, controller): connection_frame = ttk.LabelFrame(main_frame, text="Janus WebRTC Connection", padding=10) connection_frame.pack(fill=tk.X, pady=10) - # Server IP input + # Server settings input server_frame = ttk.Frame(connection_frame) server_frame.pack(fill=tk.X, pady=5) - ttk.Label(server_frame, text="Janus Server IP:").pack(side=tk.LEFT, padx=5) + ttk.Label(server_frame, text="Server IP:").pack(side=tk.LEFT, padx=5) self.server_ip_var = tk.StringVar(value=self.default_server) self.server_ip_entry = ttk.Entry(server_frame, textvariable=self.server_ip_var, width=15) self.server_ip_entry.pack(side=tk.LEFT, padx=5) + ttk.Label(server_frame, text="Port:").pack(side=tk.LEFT, padx=5) + self.port_var = tk.StringVar(value=str(self.default_port)) + self.port_entry = ttk.Entry(server_frame, textvariable=self.port_var, width=6) + self.port_entry.pack(side=tk.LEFT, padx=5) + + # SSL checkbox + self.use_ssl_var = tk.BooleanVar(value=False) + ttk.Checkbutton(server_frame, text="Use SSL", variable=self.use_ssl_var).pack(side=tk.LEFT, padx=10) + self.connect_button = ttk.Button(server_frame, text="Connect", command=self.connect_to_janus) self.connect_button.pack(side=tk.LEFT, padx=5) @@ -50,40 +60,17 @@ def __init__(self, parent, controller): self.status_var = tk.StringVar(value="Disconnected") ttk.Label(status_frame, textvariable=self.status_var).pack(side=tk.LEFT, padx=5) - # Individual cameras section + # Cameras frame - will be populated after connection self.cameras_frame = ttk.LabelFrame(main_frame, text="Available Cameras", padding=10) self.cameras_frame.pack(fill=tk.BOTH, expand=True, pady=10) - # Initial message - self.cameras_message = ttk.Label(self.cameras_frame, text="Connect to Janus server to discover cameras") - self.cameras_message.pack(pady=20) - - # Camera buttons will be added here dynamically - self.camera_buttons = {} + ttk.Label(self.cameras_frame, text="Connect to Janus server to discover cameras").pack(pady=20) - # Group actions section - group_frame = ttk.LabelFrame(main_frame, text="Group Actions", padding=10) - group_frame.pack(fill=tk.X, pady=10) - - self.group_buttons_frame = ttk.Frame(group_frame) - self.group_buttons_frame.pack(fill=tk.X, pady=5) - - # Group buttons will be enabled after connection - self.group_button_01 = ttk.Button( - self.group_buttons_frame, - text="Take Photo from Cameras 0,1", - command=lambda: self.take_group_photo([0, 1]), - state="disabled" - ) - self.group_button_01.pack(fill=tk.X, pady=5) + # Group actions section will be added after connection + self.group_frame = ttk.LabelFrame(main_frame, text="Group Actions", padding=10) + self.group_frame.pack(fill=tk.X, pady=10) - self.group_button_all = ttk.Button( - self.group_buttons_frame, - text="Take Photo from All Cameras", - command=self.take_photo_all_cameras, - state="disabled" - ) - self.group_button_all.pack(fill=tk.X, pady=5) + ttk.Label(self.group_frame, text="Connect to see group camera options").pack(pady=10) def connect_to_janus(self): """Connect to Janus WebRTC Gateway""" @@ -92,59 +79,76 @@ def connect_to_janus(self): messagebox.showerror("Error", "Please enter a server IP address") return + # Get port number + try: + port = int(self.port_var.get()) + except ValueError: + messagebox.showerror("Error", "Port must be a number") + return + + use_ssl = self.use_ssl_var.get() + # Disable the connect button during connection self.connect_button.config(state="disabled") self.status_var.set("Connecting...") - # Initiate connection + # Initiate connection with the new parameters self.webrtc_handler.connect( - server_ip, + server_ip=server_ip, + port=port, + use_ssl=use_ssl, on_success=self.on_connection_success, on_error=self.on_connection_error ) + def update_connection_status(self, status): + """Update the connection status display""" + self.status_var.set(status) + def on_connection_success(self, streams_info): - """Handle successful connection to Janus""" - # Re-enable the connect button + """Handle successful connection""" + # Re-enable the connect button and update UI self.connect_button.config(state="normal", text="Disconnect") - # Clear the cameras frame + # Clear and update the cameras frame for widget in self.cameras_frame.winfo_children(): widget.destroy() - # Create a frame for the camera buttons - buttons_frame = ttk.Frame(self.cameras_frame) - buttons_frame.pack(fill=tk.BOTH, expand=True, pady=5) - - # Add buttons for each camera + # Add camera buttons if not streams_info: - ttk.Label(buttons_frame, text="No cameras found").pack(pady=20) + ttk.Label(self.cameras_frame, text="No cameras found").pack(pady=20) else: + # Add buttons for individual cameras for stream_id, stream_info in streams_info.items(): - camera_frame = ttk.Frame(buttons_frame) - camera_frame.pack(fill=tk.X, pady=5) - - button = ttk.Button( - camera_frame, - text=f"Take Photo from {stream_info['name']} (ID: {stream_id})", + camera_btn = ttk.Button( + self.cameras_frame, + text=f"Take Photo: {stream_info['name']} (ID: {stream_id})", command=lambda id=stream_id: self.take_photo(id) ) - button.pack(fill=tk.X) - self.camera_buttons[stream_id] = button + camera_btn.pack(fill=tk.X, pady=5) + + # Update group actions frame + for widget in self.group_frame.winfo_children(): + widget.destroy() + + # Add group action buttons + ttk.Button( + self.group_frame, + text="Take Photos from Cameras 0,1", + command=lambda: self.take_group_photo([0, 1]) + ).pack(fill=tk.X, pady=5) - # Enable group buttons - self.group_button_01.config(state="normal") - self.group_button_all.config(state="normal") + ttk.Button( + self.group_frame, + text="Take Photos from All Cameras", + command=self.take_photo_all_cameras + ).pack(fill=tk.X, pady=5) def on_connection_error(self, error_message): """Handle connection error""" self.connect_button.config(state="normal") messagebox.showerror("Connection Error", f"Failed to connect: {error_message}") - def update_connection_status(self, status): - """Update the connection status display""" - self.status_var.set(status) - def take_photo(self, stream_id): """Take a photo from a specific camera""" self.webrtc_handler.take_snapshot( @@ -184,17 +188,14 @@ def mqtt_camera_callback(self, message, topic): if topic != mqtt_handler.MQTT_TOPIC_COMMANDS: return - # Check if it's a photo command - if not isinstance(message, dict): - return - - for command, value in message.items(): - if command and command.startswith("PHOTO_CAMERA_"): - # Extract camera IDs from the command - try: - camera_ids = [int(id) for id in command.split("_")[2:]] - if camera_ids: - self.take_group_photo(camera_ids) - except ValueError: - print(f"Invalid camera ID in command: {command}") - break \ No newline at end of file + # Process camera photo commands + if isinstance(message, dict): + for command, value in message.items(): + if command and command.startswith("PHOTO_CAMERA_"): + try: + camera_ids = [int(id) for id in command.split("_")[2:]] + if camera_ids: + self.take_group_photo(camera_ids) + except ValueError: + print(f"Invalid camera ID in command: {command}") + break \ No newline at end of file diff --git a/helper/webrtc_handler.py b/helper/webrtc_handler.py index cb82d85..dc4c8f6 100644 --- a/helper/webrtc_handler.py +++ b/helper/webrtc_handler.py @@ -32,9 +32,18 @@ def update_status(self, status): if self.status_callback: self.status_callback(status) - def connect(self, server_ip, on_success=None, on_error=None): - """Connect to Janus WebRTC Gateway""" - self.server_url = f"wss://{server_ip}:8989/janus" + def connect(self, server_ip, port=8188, use_ssl=True, on_success=None, on_error=None): + """Connect to Janus WebRTC Gateway + + Args: + server_ip: IP address of Janus server + port: Port number (default: 8188) + use_ssl: Whether to use secure WebSocket (default: True) + on_success: Callback for successful connection + on_error: Callback for connection errors + """ + protocol = "wss" if use_ssl else "ws" + self.server_url = f"{protocol}://{server_ip}:{port}/janus" # Start connection in a separate thread to avoid blocking UI def connect_thread(): @@ -43,26 +52,44 @@ def connect_thread(): try: self.update_status("Connecting...") - self.loop.run_until_complete(self._connect_async(on_success, on_error)) + self.loop.run_until_complete(self._connect_async(use_ssl, on_success, on_error)) except Exception as e: - self.update_status(f"Error: {str(e)}") + error_msg = str(e) + if "WRONG_VERSION_NUMBER" in error_msg: + # This typically happens when trying to use wss:// for a non-SSL server + error_msg = "SSL Error: The server might not support SSL. Try connecting without SSL." + + # Auto-retry with non-SSL if we were using SSL + if use_ssl: + self.update_status("Retrying without SSL...") + try: + protocol = "ws" + self.server_url = f"{protocol}://{server_ip}:{port}/janus" + self.loop.run_until_complete(self._connect_async(False, on_success, on_error)) + return + except Exception as retry_e: + error_msg = f"Failed again without SSL: {str(retry_e)}" + + self.update_status(f"Error: {error_msg}") if on_error: - self.loop.call_soon_threadsafe(lambda: on_error(str(e))) + self.loop.call_soon_threadsafe(lambda: on_error(error_msg)) self.ws_thread = threading.Thread(target=connect_thread) self.ws_thread.daemon = True self.ws_thread.start() - async def _connect_async(self, on_success, on_error): + async def _connect_async(self, use_ssl, on_success, on_error): """Async implementation of the connection logic""" # SSL context that accepts self-signed certificates - ssl_context = ssl.create_default_context() - ssl_context.check_hostname = False - ssl_context.verify_mode = ssl.CERT_NONE + ssl_context = None + if use_ssl: + ssl_context = ssl.create_default_context() + ssl_context.check_hostname = False + ssl_context.verify_mode = ssl.CERT_NONE try: self.websocket = await websockets.connect( - self.server_url, + self.server_url, ssl=ssl_context ) self.connected = True @@ -78,7 +105,9 @@ async def _connect_async(self, on_success, on_error): # Call success callback in the main thread if on_success: - self.loop.call_soon_threadsafe(lambda: on_success(self.streams_info)) + # Using a local variable to capture the streams_info + streams = self.streams_info + self.loop.call_soon_threadsafe(lambda: on_success(streams)) self.update_status("Connected") @@ -86,7 +115,9 @@ async def _connect_async(self, on_success, on_error): self.connected = False self.update_status(f"Connection failed: {str(e)}") if on_error: - self.loop.call_soon_threadsafe(lambda: on_error(str(e))) + # Fix the variable capture issue by using a default parameter + error_msg = str(e) + self.loop.call_soon_threadsafe(lambda error=error_msg: on_error(error)) raise async def _message_loop(self): From c2d01c5140a0df652db6492c69627beb797c6210 Mon Sep 17 00:00:00 2001 From: SimoneFassio Date: Thu, 15 May 2025 10:26:18 +0200 Subject: [PATCH 3/9] add observer to status page --- helper/debug_mqtt_viewer_page.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/helper/debug_mqtt_viewer_page.py b/helper/debug_mqtt_viewer_page.py index 413ec42..0fa5a2e 100644 --- a/helper/debug_mqtt_viewer_page.py +++ b/helper/debug_mqtt_viewer_page.py @@ -55,6 +55,9 @@ def __init__(self, parent, controller): self.error_integral_pitch_var = tk.StringVar() self.error_integral_roll_var = tk.StringVar() self.work_mode_var = tk.StringVar() + self.obs_z_var = tk.StringVar() + self.obs_roll_var = tk.StringVar() + self.obs_pitch_var = tk.StringVar() # Create a structured layout with frames for different groups of information @@ -118,6 +121,7 @@ def __init__(self, parent, controller): ("Z Speed", self.Zspeed_var), ("Force Z", self.force_z_var), ("Err Int Z", self.error_integral_z_var), + ("Obs Z", self.obs_z_var), ("Ctrl DEPTH", self.controller_state_vars["DEPTH"]) ] @@ -127,6 +131,7 @@ def __init__(self, parent, controller): ("Angular X", self.angular_x_var), ("Force Roll", self.force_roll_var), ("Err Int Roll", self.error_integral_roll_var), + ("Obs Roll", self.obs_roll_var), ("Ctrl ROLL", self.controller_state_vars["ROLL"]) ] @@ -136,6 +141,7 @@ def __init__(self, parent, controller): ("Angular Y", self.angular_y_var), ("Force Pitch", self.force_pitch_var), ("Err Int Pitch", self.error_integral_pitch_var), + ("Obs Pitch", self.obs_pitch_var), ("Ctrl PITCH", self.controller_state_vars["PITCH"]) ] @@ -241,6 +247,11 @@ def update_data(self, message, topic): self.error_integral_pitch_var.set(error_integral.get("PITCH", "N/A")) self.error_integral_roll_var.set(error_integral.get("ROLL", "N/A")) + obs_states = message.get("obs_states", {}) + self.obs_z_var.set(obs_states.get("z", "N/A")) + self.obs_roll_var.set(obs_states.get("roll", "N/A")) + self.obs_pitch_var.set(obs_states.get("pitch", "N/A")) + self.work_mode_var.set(message.get("work_mode", "N/A")) def update_motor_thrust_bar(self, motor, thrust): From b5ff11c13144e353f313211855024ca357967dec Mon Sep 17 00:00:00 2001 From: SimoneFassio Date: Thu, 15 May 2025 17:13:30 +0200 Subject: [PATCH 4/9] add RTP support --- helper/camera_5004.sdp | 9 +++ helper/cameras_page.py | 160 ++++++++++++++++++++++------------------- helper/rtp_handler.py | 50 +++++++++++++ 3 files changed, 145 insertions(+), 74 deletions(-) create mode 100644 helper/camera_5004.sdp create mode 100644 helper/rtp_handler.py diff --git a/helper/camera_5004.sdp b/helper/camera_5004.sdp new file mode 100644 index 0000000..e589678 --- /dev/null +++ b/helper/camera_5004.sdp @@ -0,0 +1,9 @@ +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=No Name +c=IN IP4 127.0.0.1 +t=0 0 +a=tool:libavformat 61.7.100 +m=video 5004 RTP/AVP 96 +a=rtpmap:96 H264/90000 +a=fmtp:96 packetization-mode=1 \ No newline at end of file diff --git a/helper/cameras_page.py b/helper/cameras_page.py index 4386ed9..13cf6e4 100644 --- a/helper/cameras_page.py +++ b/helper/cameras_page.py @@ -1,84 +1,96 @@ import tkinter as tk -from tkinter import messagebox -import requests -import os -from datetime import datetime +from tkinter import ttk, messagebox import threading - -import mqtt_handler +from datetime import datetime +from rtp_handler import RTPStreamHandler # Updated import class CamerasPage(tk.Frame): def __init__(self, parent, controller): super().__init__(parent) self.controller = controller - # Register the camera-related MQTT callback - mqtt_handler.register_callback(self.mqtt_camera_callback) - - self.camera_ports = { - "1": 8080, - "2": 8079, - "3": 8078, - "4": 8077 - } - - tk.Label(self, text="Cameras Page", font=("Arial", 16)).pack(pady=10) - - button_frame = tk.Frame(self) - button_frame.pack(pady=10) - - for camera in self.camera_ports.keys(): - tk.Button(button_frame, - text=f"Take Photo Camera {camera}", - command=lambda c=camera: self.take_photo(c) - ).pack(pady=5, fill='x') - - tk.Button(button_frame, - text="Take Photo CAMERA_1 and CAMERA_2", - command=self.take_photo_camera_1_2 - ).pack(pady=5, fill='x') - - def mqtt_camera_callback(self, message, topic): - """ - Handles incoming MQTT messages for camera commands. - """ - if topic != mqtt_handler.MQTT_TOPIC_COMMANDS: - return - command = message.popitem()[0] - if command and command.startswith("PHOTO_CAMERA_"): - cameras = command.split("_")[2:] - threads = [] - for camera in cameras: - t = threading.Thread(target=self.take_photo, args=(camera,)) - threads.append(t) - t.start() - for t in threads: - t.join() - - def take_photo(self, camera): - port = self.camera_ports.get(camera, 8080) - url = f"http://10.0.0.254:{port}/snapshot" + # Initialize RTP stream handler + self.rtp_handler = RTPStreamHandler() + self.stream_ip = "127.0.0.1" # Default IP for RTP streams + + # Main frame for camera controls + main_frame = ttk.Frame(self, padding=10) + main_frame.pack(fill=tk.BOTH, expand=True) + + # IP label + ip_frame = ttk.Frame(main_frame) + ip_frame.pack(fill=tk.X, pady=5) + ttk.Label(ip_frame, text="RTP Stream IP:").pack(side=tk.LEFT, padx=5) + self.ip_var = tk.StringVar(value=self.stream_ip) + ttk.Label(ip_frame, textvariable=self.ip_var).pack(side=tk.LEFT, padx=5) + + # Cameras frame + self.cameras_frame = ttk.LabelFrame(main_frame, text="Available Cameras", padding=10) + self.cameras_frame.pack(fill=tk.BOTH, expand=True, pady=10) + + # Add camera buttons + for port in self.rtp_handler.stream_ports: + camera_btn = ttk.Button( + self.cameras_frame, + text=f"Take Photo: Camera on Port {port}", + command=lambda p=port: self.take_photo(p) + ) + camera_btn.pack(fill=tk.X, pady=5) + + # Group action buttons + group_frame = ttk.LabelFrame(main_frame, text="Group Actions", padding=10) + group_frame.pack(fill=tk.X, pady=10) + + ttk.Button( + group_frame, + text="Take Photos from Cameras 0 and 1 Simultaneously", + command=self.take_photo_0_1 + ).pack(fill=tk.X, pady=5) + + ttk.Button( + group_frame, + text="Take Photos from All Cameras Simultaneously", + command=self.take_photo_all + ).pack(fill=tk.X, pady=5) + + def take_photo(self, port): + """Take a photo from a specific RTP stream.""" try: - response = requests.get(url) - if response.status_code == 200: - self.save_photo(camera, response.content) - #messagebox.showinfo("Success", f"Photo taken from {camera} and saved successfully.") - else: - messagebox.showerror("Error", f"Failed to take photo from {camera} (status code: {response.status_code})") - except requests.RequestException as e: - messagebox.showerror("Error", f"Error taking photo from {camera}: {e}") - - def take_photo_camera_1_2(self): - thread1 = threading.Thread(target=self.take_photo, args=("1",)) - thread2 = threading.Thread(target=self.take_photo, args=("2",)) - thread1.start() - thread2.start() - - def save_photo(self, camera, photo_data): - folder_path = os.path.join("photos", camera) - os.makedirs(folder_path, exist_ok=True) + file_path = self.rtp_handler.take_snapshot(port) + messagebox.showinfo("Success", f"Snapshot saved to {file_path}") + except Exception as e: + messagebox.showerror("Error", f"Failed to take snapshot: {str(e)}") + + def take_photo_0_1(self): + self._take_photos_simultaneous([5000, 5001]) + + def take_photo_all(self): + self._take_photos_simultaneous(self.rtp_handler.stream_ports) + + def _take_photos_simultaneous(self, ports): + """Take snapshots from multiple cameras at the exact same time.""" + results = {} + errors = {} timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") - file_path = os.path.join(folder_path, f"{timestamp}.jpg") - with open(file_path, "wb") as file: - file.write(photo_data) - print(f"Photo saved to {file_path}") \ No newline at end of file + + def capture(port): + try: + file_path = self.rtp_handler.take_snapshot(port, timestamp=timestamp) + results[port] = file_path + except Exception as e: + errors[port] = str(e) + + threads = [] + for port in ports: + t = threading.Thread(target=capture, args=(port,)) + t.start() + threads.append(t) + for t in threads: + t.join() + + if results: + msg = "Snapshots saved:\n" + "\n".join([f"Camera {p}: {f}" for p, f in results.items()]) + messagebox.showinfo("Success", msg) + if errors: + msg = "Errors:\n" + "\n".join([f"Camera {p}: {e}" for p, e in errors.items()]) + messagebox.showerror("Error", msg) diff --git a/helper/rtp_handler.py b/helper/rtp_handler.py new file mode 100644 index 0000000..ec988d8 --- /dev/null +++ b/helper/rtp_handler.py @@ -0,0 +1,50 @@ +import cv2 +import os +from datetime import datetime + +class RTPStreamHandler: + def __init__(self): + self.stream_ports = [5000, 5001, 5002, 5003, 5004] + self.streams = {port: None for port in self.stream_ports} + + def start_stream(self, port): + """Start capturing from an RTP stream on the given port using GStreamer pipeline.""" + if port not in self.stream_ports: + raise ValueError(f"Invalid port: {port}. Valid ports are {self.stream_ports}.") + gst_pipeline = ( + f'udpsrc port={port} caps="application/x-rtp, media=video, encoding-name=H264, payload=96" ' + '! rtph264depay ! avdec_h264 ! videoconvert ! appsink' + ) + self.streams[port] = cv2.VideoCapture(gst_pipeline, cv2.CAP_GSTREAMER) + + def stop_stream(self, port): + """Stop capturing from an RTP stream on the given port.""" + if port in self.streams and self.streams[port]: + self.streams[port].release() + self.streams[port] = None + + def take_snapshot(self, port, timestamp=None): + """Take a snapshot from the RTP stream on the given port.""" + if port not in self.stream_ports: + raise ValueError(f"Invalid port: {port}. Valid ports are {self.stream_ports}.") + if not self.streams[port]: + self.start_stream(port) + + ret, frame = self.streams[port].read() + if not ret: + raise RuntimeError(f"Failed to capture frame from port {port}.") + + # Save the snapshot + folder_path = os.path.join("photos", f"camera_{port}") + os.makedirs(folder_path, exist_ok=True) + if not timestamp: + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + file_path = os.path.join(folder_path, f"{timestamp}.jpg") + cv2.imwrite(file_path, frame) + print(f"Snapshot saved to {file_path}") + return file_path + + def stop_all_streams(self): + """Stop all active RTP streams.""" + for port in self.stream_ports: + self.stop_stream(port) From c0fc556d63b42c0b6253325d8d74606222fdeeac Mon Sep 17 00:00:00 2001 From: SimoneFassio Date: Mon, 19 May 2025 18:25:02 +0200 Subject: [PATCH 5/9] uodates --- helper/camera_5004.sdp | 9 - helper/cameras_page.py | 92 +++++++++-- helper/rtp_handler.py | 272 +++++++++++++++++++++++++++++-- helper/sdp_files/stream_5001.sdp | 10 ++ helper/sdp_files/stream_5002.sdp | 10 ++ helper/sdp_files/stream_5003.sdp | 10 ++ helper/sdp_files/stream_5004.sdp | 10 ++ helper/sdp_files/stream_5005.sdp | 10 ++ helper/webrtc_handler.py | 0 9 files changed, 385 insertions(+), 38 deletions(-) delete mode 100644 helper/camera_5004.sdp create mode 100644 helper/sdp_files/stream_5001.sdp create mode 100644 helper/sdp_files/stream_5002.sdp create mode 100644 helper/sdp_files/stream_5003.sdp create mode 100644 helper/sdp_files/stream_5004.sdp create mode 100644 helper/sdp_files/stream_5005.sdp create mode 100644 helper/webrtc_handler.py diff --git a/helper/camera_5004.sdp b/helper/camera_5004.sdp deleted file mode 100644 index e589678..0000000 --- a/helper/camera_5004.sdp +++ /dev/null @@ -1,9 +0,0 @@ -v=0 -o=- 0 0 IN IP4 127.0.0.1 -s=No Name -c=IN IP4 127.0.0.1 -t=0 0 -a=tool:libavformat 61.7.100 -m=video 5004 RTP/AVP 96 -a=rtpmap:96 H264/90000 -a=fmtp:96 packetization-mode=1 \ No newline at end of file diff --git a/helper/cameras_page.py b/helper/cameras_page.py index 13cf6e4..a968ea1 100644 --- a/helper/cameras_page.py +++ b/helper/cameras_page.py @@ -11,7 +11,7 @@ def __init__(self, parent, controller): # Initialize RTP stream handler self.rtp_handler = RTPStreamHandler() - self.stream_ip = "127.0.0.1" # Default IP for RTP streams + self.stream_ip = "10.0.0.23" # Default IP for RTP streams # Main frame for camera controls main_frame = ttk.Frame(self, padding=10) @@ -28,14 +28,24 @@ def __init__(self, parent, controller): self.cameras_frame = ttk.LabelFrame(main_frame, text="Available Cameras", padding=10) self.cameras_frame.pack(fill=tk.BOTH, expand=True, pady=10) - # Add camera buttons + # Add camera buttons - now with both snapshot and preview for port in self.rtp_handler.stream_ports: - camera_btn = ttk.Button( - self.cameras_frame, - text=f"Take Photo: Camera on Port {port}", + port_frame = ttk.Frame(self.cameras_frame) + port_frame.pack(fill=tk.X, pady=5) + + ttk.Label(port_frame, text=f"Camera on Port {port}:", width=20).pack(side=tk.LEFT, padx=5) + + ttk.Button( + port_frame, + text="Take Photo", command=lambda p=port: self.take_photo(p) - ) - camera_btn.pack(fill=tk.X, pady=5) + ).pack(side=tk.LEFT, padx=5) + + ttk.Button( + port_frame, + text="Preview Stream", + command=lambda p=port: self.preview_stream(p) + ).pack(side=tk.LEFT, padx=5) # Group action buttons group_frame = ttk.LabelFrame(main_frame, text="Group Actions", padding=10) @@ -43,7 +53,7 @@ def __init__(self, parent, controller): ttk.Button( group_frame, - text="Take Photos from Cameras 0 and 1 Simultaneously", + text="Take Photos from Cameras 5001 and 5002 Simultaneously", command=self.take_photo_0_1 ).pack(fill=tk.X, pady=5) @@ -53,16 +63,49 @@ def __init__(self, parent, controller): command=self.take_photo_all ).pack(fill=tk.X, pady=5) + # Status variable and label + self.status_var = tk.StringVar(value="Ready") + ttk.Label(main_frame, textvariable=self.status_var, foreground="green").pack(pady=5) + def take_photo(self, port): """Take a photo from a specific RTP stream.""" try: + self.status_var.set(f"Taking photo from port {port}...") file_path = self.rtp_handler.take_snapshot(port) messagebox.showinfo("Success", f"Snapshot saved to {file_path}") + self.status_var.set("Ready") except Exception as e: - messagebox.showerror("Error", f"Failed to take snapshot: {str(e)}") + error_msg = str(e) + print(f"Error taking snapshot: {error_msg}") + + # Create an informative error message with debugging help + detail_msg = ( + f"Failed to take snapshot from port {port}.\n\n" + f"Error: {error_msg}\n\n" + f"Debugging steps:\n" + f"1. Verify camera is streaming to {self.stream_ip}:{port}\n" + f"2. Try using the 'Preview Stream' button first\n" + f"3. Check network connectivity\n" + f"4. Ensure no firewall is blocking UDP on port {port}" + ) + + messagebox.showerror("Snapshot Error", detail_msg) + self.status_var.set("Error taking snapshot") + + def preview_stream(self, port): + """Preview the RTP stream using ffplay.""" + try: + self.status_var.set(f"Starting preview for port {port}...") + self.rtp_handler.preview_stream(port) + self.status_var.set("Preview started. Close ffplay window when done.") + except Exception as e: + error_msg = str(e) + print(f"Error starting preview: {error_msg}") + messagebox.showerror("Preview Error", f"Failed to start preview: {error_msg}") + self.status_var.set("Error starting preview") def take_photo_0_1(self): - self._take_photos_simultaneous([5000, 5001]) + self._take_photos_simultaneous([5001, 5002]) def take_photo_all(self): self._take_photos_simultaneous(self.rtp_handler.stream_ports) @@ -72,13 +115,16 @@ def _take_photos_simultaneous(self, ports): results = {} errors = {} timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + self.status_var.set(f"Taking photos from ports {ports}...") def capture(port): try: file_path = self.rtp_handler.take_snapshot(port, timestamp=timestamp) results[port] = file_path except Exception as e: - errors[port] = str(e) + error_msg = str(e) + print(f"Thread error taking snapshot from port {port}: {error_msg}") + errors[port] = error_msg threads = [] for port in ports: @@ -88,9 +134,29 @@ def capture(port): for t in threads: t.join() + # Update status based on results + if results and not errors: + self.status_var.set("All snapshots successful") + elif results and errors: + self.status_var.set(f"Some snapshots failed ({len(errors)} errors)") + else: + self.status_var.set("All snapshots failed") + if results: msg = "Snapshots saved:\n" + "\n".join([f"Camera {p}: {f}" for p, f in results.items()]) messagebox.showinfo("Success", msg) if errors: - msg = "Errors:\n" + "\n".join([f"Camera {p}: {e}" for p, e in errors.items()]) - messagebox.showerror("Error", msg) + # Create a detailed error report + error_report = "Errors occurred while taking snapshots:\n\n" + for port, error in errors.items(): + error_report += f"Port {port}: {error}\n\n" + + error_report += ( + "Possible solutions:\n" + "1. Verify all cameras are streaming correctly\n" + "2. Check if GStreamer is installed and configured\n" + "3. Make sure ports are not blocked by firewall\n" + "4. Try restarting the application or the camera streams" + ) + + messagebox.showerror("Snapshot Errors", error_report) diff --git a/helper/rtp_handler.py b/helper/rtp_handler.py index ec988d8..3e6e834 100644 --- a/helper/rtp_handler.py +++ b/helper/rtp_handler.py @@ -1,21 +1,106 @@ import cv2 import os +import subprocess +import numpy as np +import platform from datetime import datetime class RTPStreamHandler: def __init__(self): - self.stream_ports = [5000, 5001, 5002, 5003, 5004] + self.stream_ports = [5001, 5002, 5003, 5004, 5005] self.streams = {port: None for port in self.stream_ports} + # Check GStreamer support + self.has_gstreamer = self._check_gstreamer_support() + if not self.has_gstreamer: + print("WARNING: OpenCV not built with GStreamer support. RTP capture may not work.") + + # Create directory for SDP files if it doesn't exist + self.sdp_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "sdp_files") + os.makedirs(self.sdp_dir, exist_ok=True) + + # Known working stream info + self.stream_info = { + # Default values based on test + 'width': 1920, + 'height': 1080, + 'framerate': 30 + } + + def _check_gstreamer_support(self): + """Check if OpenCV is built with GStreamer support""" + # Check if OpenCV has GStreamer support + build_info = cv2.getBuildInformation() + has_gstreamer = "GStreamer" in build_info and "YES" in build_info.split("GStreamer:")[1].split("\n")[0] + + # Also check if gst-launch is available + gst_available = False + try: + if platform.system() == "Windows": + # Check for Windows gst-launch + result = subprocess.run(["where", "gst-launch-1.0"], capture_output=True, text=True) + gst_available = result.returncode == 0 + else: + # Check for Unix-like gst-launch + result = subprocess.run(["which", "gst-launch-1.0"], capture_output=True, text=True) + gst_available = result.returncode == 0 + except Exception: + gst_available = False + + print(f"OpenCV GStreamer support: {has_gstreamer}") + print(f"GStreamer command line tools: {gst_available}") + + return has_gstreamer + + def _create_sdp_file(self, port, ip_address="0.0.0.0"): + """Create an SDP file for the specified port with known video parameters""" + sdp_content = f"""v=0 +o=- 0 0 IN IP4 {ip_address} +s=RTP Stream on port {port} +c=IN IP4 {ip_address} +t=0 0 +a=tool:libavformat 61.7.100 +m=video {port} RTP/AVP 96 +a=rtpmap:96 H264/90000 +a=fmtp:96 packetization-mode=1; profile-level-id=42e01f +a=framerate:{self.stream_info['framerate']} +""" + sdp_path = os.path.join(self.sdp_dir, f"stream_{port}.sdp") + with open(sdp_path, "w") as f: + f.write(sdp_content) + print(f"Created SDP file: {sdp_path}") + return sdp_path def start_stream(self, port): - """Start capturing from an RTP stream on the given port using GStreamer pipeline.""" + """Start capturing from an RTP stream on the given port using ffmpeg as fallback.""" if port not in self.stream_ports: raise ValueError(f"Invalid port: {port}. Valid ports are {self.stream_ports}.") - gst_pipeline = ( - f'udpsrc port={port} caps="application/x-rtp, media=video, encoding-name=H264, payload=96" ' - '! rtph264depay ! avdec_h264 ! videoconvert ! appsink' - ) - self.streams[port] = cv2.VideoCapture(gst_pipeline, cv2.CAP_GSTREAMER) + + # Try GStreamer method first if available + if self.has_gstreamer: + gst_pipeline = ( + f'udpsrc port={port} caps="application/x-rtp, media=video, encoding-name=H264, payload=96" ' + '! rtph264depay ! avdec_h264 ! videoconvert ! appsink' + ) + + print(f"Opening stream with GStreamer pipeline: {gst_pipeline}") + cap = cv2.VideoCapture(gst_pipeline, cv2.CAP_GSTREAMER) + + if cap.isOpened(): + self.streams[port] = cap + return True + + # Fallback to ffmpeg (check if installed) + try: + subprocess.run(["which", "ffmpeg"], check=True, capture_output=True) + print(f"GStreamer not available. Using ffmpeg fallback for RTP stream on port {port}") + # We'll use ffmpeg when taking the snapshot, not keeping a continuous stream open + self.streams[port] = f"ffmpeg_rtp_{port}" # Just a marker that we're using ffmpeg + return True + except subprocess.CalledProcessError: + raise RuntimeError( + "Neither GStreamer nor ffmpeg are available. Cannot capture RTP streams.\n" + "Please install either GStreamer or ffmpeg to continue." + ) def stop_stream(self, port): """Stop capturing from an RTP stream on the given port.""" @@ -23,24 +108,179 @@ def stop_stream(self, port): self.streams[port].release() self.streams[port] = None + def preview_stream(self, port): + """Open an ffplay window to preview the stream""" + if port not in self.stream_ports: + raise ValueError(f"Invalid port: {port}. Valid ports are {self.stream_ports}.") + + # Create SDP file + sdp_path = self._create_sdp_file(port) + + # Construct ffplay command + preview_cmd = [ + "ffplay", + "-protocol_whitelist", "file,rtp,udp", + "-fflags", "nobuffer", # Reduce latency + "-flags", "low_delay", # Reduce latency + "-framedrop", # Allow frame dropping if needed + "-i", sdp_path + ] + + # Launch ffplay in a separate process (non-blocking) + print(f"Launching preview with command: {' '.join(preview_cmd)}") + try: + subprocess.Popen(preview_cmd) + return True + except Exception as e: + raise RuntimeError(f"Failed to start preview: {str(e)}") + def take_snapshot(self, port, timestamp=None): """Take a snapshot from the RTP stream on the given port.""" if port not in self.stream_ports: raise ValueError(f"Invalid port: {port}. Valid ports are {self.stream_ports}.") - if not self.streams[port]: - self.start_stream(port) - - ret, frame = self.streams[port].read() - if not ret: - raise RuntimeError(f"Failed to capture frame from port {port}.") - - # Save the snapshot + + # Create folder for saving snapshots folder_path = os.path.join("photos", f"camera_{port}") os.makedirs(folder_path, exist_ok=True) + if not timestamp: timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") file_path = os.path.join(folder_path, f"{timestamp}.jpg") - cv2.imwrite(file_path, frame) + + # Start the stream if not already started + if not self.streams.get(port): + self.start_stream(port) + + # If using GStreamer backend (regular OpenCV) + if isinstance(self.streams[port], cv2.VideoCapture): + # Try to grab a frame first (this is more immediate than read()) + grab_success = self.streams[port].grab() + if not grab_success: + raise RuntimeError(f"Failed to grab frame from port {port}.") + + ret, frame = self.streams[port].retrieve() + if not ret or frame is None: + raise RuntimeError(f"Retrieved frame is invalid from port {port}.") + + if frame.size == 0: + raise RuntimeError("Captured frame is empty (zero size).") + + save_success = cv2.imwrite(file_path, frame) + if not save_success: + raise RuntimeError(f"Failed to save image to {file_path}") + + # If using ffmpeg fallback + elif str(self.streams[port]).startswith("ffmpeg_rtp_"): + try: + # Create SDP file for this port + sdp_path = self._create_sdp_file(port) + + # First, try to verify stream is active (similar to preview) + print(f"Testing if RTP stream is active on port {port}...") + probe_cmd = [ + "ffprobe", + "-v", "error", + "-show_entries", "stream=width,height,codec_name", + "-protocol_whitelist", "file,rtp,udp", + "-i", sdp_path, + "-max_probe_time", "3", # 3 seconds max + "-probesize", "5000000" # 5MB probe size + ] + + try: + # Just check if stream is decodable + probe_result = subprocess.run( + probe_cmd, + capture_output=True, + text=True, + timeout=5 + ) + print(f"ffprobe result: {probe_result.returncode}") + print(f"ffprobe output: {probe_result.stdout}") + print(f"ffprobe stderr: {probe_result.stderr}") + except subprocess.TimeoutExpired: + # Timeout is actually OK - means stream is flowing + print("ffprobe timed out - stream is likely active") + pass + + # Create a temporary ts file first (TS container has better error recovery) + temp_ts_file = os.path.join(folder_path, f"temp_{timestamp}.ts") + + # Use ffmpeg with SDP file to capture a short segment of video + # This method is more reliable than trying to grab just one frame + capture_cmd = [ + "ffmpeg", + "-protocol_whitelist", "file,rtp,udp", + "-i", sdp_path, + "-t", "2", # Capture 2 seconds of video + "-vsync", "2", # Passthrough vsync mode + "-c:v", "copy", # Don't re-encode, just copy + "-y", # Overwrite output without asking + temp_ts_file + ] + + print(f"Running ffmpeg capture command: {' '.join(capture_cmd)}") + + # Run ffmpeg with a timeout - this captures a segment of the stream + result = subprocess.run( + capture_cmd, + capture_output=True, + text=True, + timeout=10 # 10 second timeout + ) + + if result.returncode != 0: + detailed_error = f"ffmpeg capture failed with error code {result.returncode}:\n" + detailed_error += f"STDOUT: {result.stdout}\n" + detailed_error += f"STDERR: {result.stderr}\n\n" + detailed_error += "Possible solutions:\n" + detailed_error += "1. Ensure the camera is actually streaming H.264 to this port\n" + detailed_error += f"2. Try previewing the stream with: ffplay -protocol_whitelist file,rtp,udp -i {sdp_path}\n" + detailed_error += "3. Check for network issues or firewall restrictions" + + raise RuntimeError(detailed_error) + + # Now extract the first good frame from the captured segment + extract_cmd = [ + "ffmpeg", + "-i", temp_ts_file, + "-vframes", "1", # Extract one frame + "-q:v", "1", # Highest quality + "-y", + file_path + ] + + print(f"Extracting frame with command: {' '.join(extract_cmd)}") + + extract_result = subprocess.run( + extract_cmd, + capture_output=True, + text=True, + timeout=5 + ) + + # Clean up temporary file + try: + os.remove(temp_ts_file) + except OSError: + pass + + if extract_result.returncode != 0: + raise RuntimeError(f"Failed to extract frame: {extract_result.stderr}") + + # Verify the final image was created successfully + if not os.path.exists(file_path) or os.path.getsize(file_path) < 1000: # Minimum size check + raise RuntimeError("Extracted image is too small or not created") + + except subprocess.TimeoutExpired as e: + raise RuntimeError( + f"ffmpeg timed out: {str(e)}.\n" + "This usually means no video data is being received on port " + str(port) + ".\n" + f"Try previewing the stream first with: ffplay -protocol_whitelist file,rtp,udp -i {sdp_path}" + ) + except Exception as e: + raise RuntimeError(f"Snapshot error: {str(e)}") + print(f"Snapshot saved to {file_path}") return file_path diff --git a/helper/sdp_files/stream_5001.sdp b/helper/sdp_files/stream_5001.sdp new file mode 100644 index 0000000..7a55745 --- /dev/null +++ b/helper/sdp_files/stream_5001.sdp @@ -0,0 +1,10 @@ +v=0 +o=- 0 0 IN IP4 0.0.0.0 +s=RTP Stream on port 5001 +c=IN IP4 0.0.0.0 +t=0 0 +a=tool:libavformat 61.7.100 +m=video 5001 RTP/AVP 96 +a=rtpmap:96 H264/90000 +a=fmtp:96 packetization-mode=1; profile-level-id=42e01f +a=framerate:30 diff --git a/helper/sdp_files/stream_5002.sdp b/helper/sdp_files/stream_5002.sdp new file mode 100644 index 0000000..f995825 --- /dev/null +++ b/helper/sdp_files/stream_5002.sdp @@ -0,0 +1,10 @@ +v=0 +o=- 0 0 IN IP4 0.0.0.0 +s=RTP Stream on port 5002 +c=IN IP4 0.0.0.0 +t=0 0 +a=tool:libavformat 61.7.100 +m=video 5002 RTP/AVP 96 +a=rtpmap:96 H264/90000 +a=fmtp:96 packetization-mode=1; profile-level-id=42e01f +a=framerate:30 diff --git a/helper/sdp_files/stream_5003.sdp b/helper/sdp_files/stream_5003.sdp new file mode 100644 index 0000000..449c1f4 --- /dev/null +++ b/helper/sdp_files/stream_5003.sdp @@ -0,0 +1,10 @@ +v=0 +o=- 0 0 IN IP4 0.0.0.0 +s=RTP Stream on port 5003 +c=IN IP4 0.0.0.0 +t=0 0 +a=tool:libavformat 61.7.100 +m=video 5003 RTP/AVP 96 +a=rtpmap:96 H264/90000 +a=fmtp:96 packetization-mode=1; profile-level-id=42e01f +a=framerate:30 diff --git a/helper/sdp_files/stream_5004.sdp b/helper/sdp_files/stream_5004.sdp new file mode 100644 index 0000000..2f660d8 --- /dev/null +++ b/helper/sdp_files/stream_5004.sdp @@ -0,0 +1,10 @@ +v=0 +o=- 0 0 IN IP4 0.0.0.0 +s=RTP Stream on port 5004 +c=IN IP4 0.0.0.0 +t=0 0 +a=tool:libavformat 61.7.100 +m=video 5004 RTP/AVP 96 +a=rtpmap:96 H264/90000 +a=fmtp:96 packetization-mode=1; profile-level-id=42e01f +a=framerate:30 diff --git a/helper/sdp_files/stream_5005.sdp b/helper/sdp_files/stream_5005.sdp new file mode 100644 index 0000000..1b9d695 --- /dev/null +++ b/helper/sdp_files/stream_5005.sdp @@ -0,0 +1,10 @@ +v=0 +o=- 0 0 IN IP4 0.0.0.0 +s=RTP Stream on port 5005 +c=IN IP4 0.0.0.0 +t=0 0 +a=tool:libavformat 61.7.100 +m=video 5005 RTP/AVP 96 +a=rtpmap:96 H264/90000 +a=fmtp:96 packetization-mode=1; profile-level-id=42e01f +a=framerate:30 diff --git a/helper/webrtc_handler.py b/helper/webrtc_handler.py new file mode 100644 index 0000000..e69de29 From ee490b271713f2e57afed71963c47e03e11e6edf Mon Sep 17 00:00:00 2001 From: SimoneFassio Date: Wed, 21 May 2025 15:22:25 +0200 Subject: [PATCH 6/9] rtp fix --- helper/camera_5004.sdp | 0 helper/cameras_page.py | 78 +++++++- helper/main.py | 18 ++ helper/rtp_handler.py | 335 ++++++++++++++-------------------- helper/send_test_mqtt_page.py | 11 ++ 5 files changed, 239 insertions(+), 203 deletions(-) create mode 100644 helper/camera_5004.sdp diff --git a/helper/camera_5004.sdp b/helper/camera_5004.sdp new file mode 100644 index 0000000..e69de29 diff --git a/helper/cameras_page.py b/helper/cameras_page.py index 659edd8..6511e9b 100644 --- a/helper/cameras_page.py +++ b/helper/cameras_page.py @@ -3,6 +3,8 @@ import threading from datetime import datetime from rtp_handler import RTPStreamHandler +import time # Import time for delay +from PIL import Image, ImageTk # Import Pillow for image handling class CamerasPage(tk.Frame): def __init__(self, parent, controller): @@ -13,6 +15,10 @@ def __init__(self, parent, controller): self.rtp_handler = RTPStreamHandler() self.stream_ip = "10.0.0.192" # Default IP for RTP streams + # To store thumbnail labels and their PhotoImage objects + self.thumbnail_labels = {} + self.thumbnail_images = {} # To prevent garbage collection + # Main frame for camera controls main_frame = ttk.Frame(self, padding=10) main_frame.pack(fill=tk.BOTH, expand=True) @@ -47,6 +53,11 @@ def __init__(self, parent, controller): command=lambda p=port: self.preview_stream(p) ).pack(side=tk.LEFT, padx=5) + # Add Label for thumbnail display + thumb_label = ttk.Label(port_frame) + thumb_label.pack(side=tk.LEFT, padx=10) + self.thumbnail_labels[port] = thumb_label + # Group action buttons group_frame = ttk.LabelFrame(main_frame, text="Group Actions", padding=10) group_frame.pack(fill=tk.X, pady=10) @@ -71,9 +82,15 @@ def take_photo(self, port): """Take a photo from a specific RTP stream.""" try: self.status_var.set(f"Taking photo from port {port}...") - file_path = self.rtp_handler.take_snapshot(port) - messagebox.showinfo("Success", f"Snapshot saved to {file_path}") - self.status_var.set("Ready") + # Call with silent=True to suppress rtp_handler's print + file_path = self.rtp_handler.take_snapshot(port, silent=True) + + # Display thumbnail + if file_path: + self._display_thumbnail(port, file_path) + + # No success pop-up: messagebox.showinfo("Success", f"Snapshot saved to {file_path}") + self.status_var.set(f"Snapshot from port {port} taken.") # Update status except Exception as e: error_msg = str(e) print(f"Error taking snapshot: {error_msg}") @@ -91,7 +108,32 @@ def take_photo(self, port): messagebox.showerror("Snapshot Error", detail_msg) self.status_var.set("Error taking snapshot") + self._clear_thumbnail(port) # Clear thumbnail on error + def _display_thumbnail(self, port, file_path): + """Loads an image, resizes it, and displays it in the thumbnail label.""" + try: + img = Image.open(file_path) + img.thumbnail((100, 75)) # Resize to 100x75 or your preferred size + photo_img = ImageTk.PhotoImage(img) + + if port in self.thumbnail_labels: + self.thumbnail_labels[port].config(image=photo_img) + # Keep a reference to the image to prevent it from being garbage collected + self.thumbnail_labels[port].image = photo_img + self.thumbnail_images[port] = photo_img # Also store in dict + except Exception as e: + print(f"Error displaying thumbnail for port {port}: {e}") + self._clear_thumbnail(port) + + def _clear_thumbnail(self, port): + """Clears the thumbnail for a given port.""" + if port in self.thumbnail_labels: + self.thumbnail_labels[port].config(image='') + self.thumbnail_labels[port].image = None + if port in self.thumbnail_images: + del self.thumbnail_images[port] + def preview_stream(self, port): """Preview the RTP stream using ffplay.""" try: @@ -114,12 +156,15 @@ def _take_photos_simultaneous(self, ports): """Take snapshots from multiple cameras at the exact same time.""" results = {} errors = {} - timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + # Use a common base timestamp string for the group, ffmpeg_rtp_handler will add port and microsecond for uniqueness + base_timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") self.status_var.set(f"Taking photos from ports {ports}...") def capture(port): try: - file_path = self.rtp_handler.take_snapshot(port, timestamp=timestamp) + # Pass the base_timestamp, rtp_handler will make it unique per port/call + # Call with silent=True + file_path = self.rtp_handler.take_snapshot(port, timestamp=base_timestamp, silent=True) results[port] = file_path except Exception as e: error_msg = str(e) @@ -127,13 +172,27 @@ def capture(port): errors[port] = error_msg threads = [] + # Launch threads as concurrently as possible. + # rtp_handler.py uses unique SDP files for each call, which should mitigate port conflicts for SDP. + # Underlying UDP port binding by ffmpeg for RTP data (5001, 5002 etc.) is the main concern for "Address already in use". + for port in ports: t = threading.Thread(target=capture, args=(port,)) t.start() threads.append(t) + for t in threads: t.join() + # Update thumbnails for successful captures + for port, file_path in results.items(): + self._display_thumbnail(port, file_path) + + # Clear thumbnails for failed captures + for port in errors.keys(): + if port not in results: # Only clear if it wasn't successful despite an error log (shouldn't happen with current logic) + self._clear_thumbnail(port) + # Update status based on results if results and not errors: self.status_var.set("All snapshots successful") @@ -142,9 +201,10 @@ def capture(port): else: self.status_var.set("All snapshots failed") - if results: - msg = "Snapshots saved:\n" + "\n".join([f"Camera {p}: {f}" for p, f in results.items()]) - messagebox.showinfo("Success", msg) + # No general success pop-up for group action + # if results: + # msg = "Snapshots saved:\n" + "\n".join([f"Camera {p}: {f}" for p, f in results.items()]) + # messagebox.showinfo("Success", msg) if errors: # Create a detailed error report error_report = "Errors occurred while taking snapshots:\n\n" @@ -160,4 +220,4 @@ def capture(port): ) messagebox.showerror("Snapshot Errors", error_report) - + diff --git a/helper/main.py b/helper/main.py index 4a46016..414e32c 100644 --- a/helper/main.py +++ b/helper/main.py @@ -19,6 +19,8 @@ def __init__(self): self.title("Modular GUI with MQTT") self.geometry("800x900") self.mqtt_connected = False + self.reconnect_scheduled = False + self.reconnect_delay = 5000 # 5 seconds # Create a navigation bar nav_bar = tk.Frame(self, bg="lightgrey") @@ -72,8 +74,24 @@ def update_connection_status(self, connected): self.mqtt_connected = connected if connected: self.status_frame.config(bg="green") + self.connect_button.config(text="ROV Connected") + self.reconnect_scheduled = False # Connection successful, cancel any pending reconnect else: self.status_frame.config(bg="red") + self.connect_button.config(text="Connect to ROV") + if not self.reconnect_scheduled: + print(f"MQTT disconnected. Scheduling reconnection in {self.reconnect_delay / 1000} seconds.") + self.reconnect_scheduled = True + self.after(self.reconnect_delay, self.attempt_reconnection) + + def attempt_reconnection(self): + """Attempt to reconnect to MQTT if not already connected.""" + if not self.mqtt_connected: + print("Attempting to reconnect to MQTT...") + self.connect_to_mqtt() + # Regardless of outcome, allow update_connection_status to reschedule if needed + self.reconnect_scheduled = False + def connect_to_mqtt(self): """Connect to MQTT using default values""" diff --git a/helper/rtp_handler.py b/helper/rtp_handler.py index 3e6e834..81aec91 100644 --- a/helper/rtp_handler.py +++ b/helper/rtp_handler.py @@ -1,55 +1,42 @@ -import cv2 import os import subprocess -import numpy as np -import platform +import platform # Keep platform for _check_ffmpeg_availability from datetime import datetime +# Removed cv2 and numpy imports as they are not used if GStreamer path is removed +import time # Added for retry delay class RTPStreamHandler: def __init__(self): self.stream_ports = [5001, 5002, 5003, 5004, 5005] - self.streams = {port: None for port in self.stream_ports} - # Check GStreamer support - self.has_gstreamer = self._check_gstreamer_support() - if not self.has_gstreamer: - print("WARNING: OpenCV not built with GStreamer support. RTP capture may not work.") + self.streams = {port: None for port in self.stream_ports} # Will mark if ffmpeg is to be used + # Check ffmpeg availability + self.has_ffmpeg = self._check_ffmpeg_availability() + if not self.has_ffmpeg: + raise RuntimeError("ffmpeg is not installed or not found in PATH. Cannot capture RTP streams.") + # Create directory for SDP files if it doesn't exist self.sdp_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "sdp_files") os.makedirs(self.sdp_dir, exist_ok=True) # Known working stream info self.stream_info = { - # Default values based on test - 'width': 1920, - 'height': 1080, + 'width': 1080, + 'height': 720, 'framerate': 30 } - def _check_gstreamer_support(self): - """Check if OpenCV is built with GStreamer support""" - # Check if OpenCV has GStreamer support - build_info = cv2.getBuildInformation() - has_gstreamer = "GStreamer" in build_info and "YES" in build_info.split("GStreamer:")[1].split("\n")[0] - - # Also check if gst-launch is available - gst_available = False + def _check_ffmpeg_availability(self): + """Check if ffmpeg is installed and accessible.""" try: - if platform.system() == "Windows": - # Check for Windows gst-launch - result = subprocess.run(["where", "gst-launch-1.0"], capture_output=True, text=True) - gst_available = result.returncode == 0 - else: - # Check for Unix-like gst-launch - result = subprocess.run(["which", "gst-launch-1.0"], capture_output=True, text=True) - gst_available = result.returncode == 0 - except Exception: - gst_available = False - - print(f"OpenCV GStreamer support: {has_gstreamer}") - print(f"GStreamer command line tools: {gst_available}") - - return has_gstreamer + # Use 'where' on Windows and 'which' on Unix-like systems + command = "where" if platform.system() == "Windows" else "which" + subprocess.run([command, "ffmpeg"], check=True, capture_output=True) + print("ffmpeg found.") + return True + except (subprocess.CalledProcessError, FileNotFoundError): + print("ffmpeg not found.") + return False def _create_sdp_file(self, port, ip_address="0.0.0.0"): """Create an SDP file for the specified port with known video parameters""" @@ -71,42 +58,22 @@ def _create_sdp_file(self, port, ip_address="0.0.0.0"): return sdp_path def start_stream(self, port): - """Start capturing from an RTP stream on the given port using ffmpeg as fallback.""" + """Mark that ffmpeg will be used for this port.""" if port not in self.stream_ports: raise ValueError(f"Invalid port: {port}. Valid ports are {self.stream_ports}.") - # Try GStreamer method first if available - if self.has_gstreamer: - gst_pipeline = ( - f'udpsrc port={port} caps="application/x-rtp, media=video, encoding-name=H264, payload=96" ' - '! rtph264depay ! avdec_h264 ! videoconvert ! appsink' - ) - - print(f"Opening stream with GStreamer pipeline: {gst_pipeline}") - cap = cv2.VideoCapture(gst_pipeline, cv2.CAP_GSTREAMER) - - if cap.isOpened(): - self.streams[port] = cap - return True + if not self.has_ffmpeg: + raise RuntimeError("ffmpeg is not installed. Cannot capture RTP streams.") - # Fallback to ffmpeg (check if installed) - try: - subprocess.run(["which", "ffmpeg"], check=True, capture_output=True) - print(f"GStreamer not available. Using ffmpeg fallback for RTP stream on port {port}") - # We'll use ffmpeg when taking the snapshot, not keeping a continuous stream open - self.streams[port] = f"ffmpeg_rtp_{port}" # Just a marker that we're using ffmpeg - return True - except subprocess.CalledProcessError: - raise RuntimeError( - "Neither GStreamer nor ffmpeg are available. Cannot capture RTP streams.\n" - "Please install either GStreamer or ffmpeg to continue." - ) + # Mark that ffmpeg will be used for this port. No actual stream is started here. + self.streams[port] = f"ffmpeg_rtp_{port}" + print(f"ffmpeg will be used for snapshots on port {port}") + return True def stop_stream(self, port): - """Stop capturing from an RTP stream on the given port.""" - if port in self.streams and self.streams[port]: - self.streams[port].release() - self.streams[port] = None + """Placeholder as ffmpeg calls are per-snapshot.""" + if port in self.streams: + self.streams[port] = None # Reset the marker def preview_stream(self, port): """Open an ffplay window to preview the stream""" @@ -134,154 +101,134 @@ def preview_stream(self, port): except Exception as e: raise RuntimeError(f"Failed to start preview: {str(e)}") - def take_snapshot(self, port, timestamp=None): - """Take a snapshot from the RTP stream on the given port.""" + def take_snapshot(self, port, timestamp=None, silent=False): # Added silent parameter + """Take a snapshot from the RTP stream on the given port using ffmpeg directly to JPG.""" if port not in self.stream_ports: raise ValueError(f"Invalid port: {port}. Valid ports are {self.stream_ports}.") + if not self.has_ffmpeg: + raise RuntimeError("ffmpeg is not installed. Cannot capture RTP streams.") + # Create folder for saving snapshots folder_path = os.path.join("photos", f"camera_{port}") os.makedirs(folder_path, exist_ok=True) + current_time = datetime.now() if not timestamp: - timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") - file_path = os.path.join(folder_path, f"{timestamp}.jpg") + timestamp_str = current_time.strftime("%Y%m%d_%H%M%S_%f") # Add microseconds for uniqueness + else: + timestamp_str = f"{timestamp}_p{port}_{current_time.strftime('%f')}" + + file_path = os.path.join(folder_path, f"{timestamp_str}.jpg") - # Start the stream if not already started - if not self.streams.get(port): + if not self.streams.get(port) or not str(self.streams[port]).startswith("ffmpeg_rtp_"): self.start_stream(port) - - # If using GStreamer backend (regular OpenCV) - if isinstance(self.streams[port], cv2.VideoCapture): - # Try to grab a frame first (this is more immediate than read()) - grab_success = self.streams[port].grab() - if not grab_success: - raise RuntimeError(f"Failed to grab frame from port {port}.") + + sdp_path_for_cleanup = None + + try: + sdp_filename = f"stream_{port}_{current_time.strftime('%Y%m%d%H%M%S%f')}.sdp" + sdp_path = os.path.join(self.sdp_dir, sdp_filename) + sdp_path_for_cleanup = sdp_path - ret, frame = self.streams[port].retrieve() - if not ret or frame is None: - raise RuntimeError(f"Retrieved frame is invalid from port {port}.") - - if frame.size == 0: - raise RuntimeError("Captured frame is empty (zero size).") - - save_success = cv2.imwrite(file_path, frame) - if not save_success: - raise RuntimeError(f"Failed to save image to {file_path}") - - # If using ffmpeg fallback - elif str(self.streams[port]).startswith("ffmpeg_rtp_"): - try: - # Create SDP file for this port - sdp_path = self._create_sdp_file(port) - - # First, try to verify stream is active (similar to preview) - print(f"Testing if RTP stream is active on port {port}...") - probe_cmd = [ - "ffprobe", - "-v", "error", - "-show_entries", "stream=width,height,codec_name", - "-protocol_whitelist", "file,rtp,udp", - "-i", sdp_path, - "-max_probe_time", "3", # 3 seconds max - "-probesize", "5000000" # 5MB probe size - ] - - try: - # Just check if stream is decodable - probe_result = subprocess.run( - probe_cmd, - capture_output=True, - text=True, - timeout=5 - ) - print(f"ffprobe result: {probe_result.returncode}") - print(f"ffprobe output: {probe_result.stdout}") - print(f"ffprobe stderr: {probe_result.stderr}") - except subprocess.TimeoutExpired: - # Timeout is actually OK - means stream is flowing - print("ffprobe timed out - stream is likely active") - pass + sdp_content = f"""v=0 +o=- 0 0 IN IP4 0.0.0.0 +s=RTP Stream on port {port} +c=IN IP4 0.0.0.0 +t=0 0 +a=tool:libavformat 61.7.100 +m=video {port} RTP/AVP 96 +a=rtpmap:96 H264/90000 +a=fmtp:96 packetization-mode=1; profile-level-id=42e01f +a=framerate:{self.stream_info['framerate']} +""" + with open(sdp_path, "w") as f: + f.write(sdp_content) + print(f"Created unique SDP file for snapshot: {sdp_path}") - # Create a temporary ts file first (TS container has better error recovery) - temp_ts_file = os.path.join(folder_path, f"temp_{timestamp}.ts") - - # Use ffmpeg with SDP file to capture a short segment of video - # This method is more reliable than trying to grab just one frame - capture_cmd = [ - "ffmpeg", - "-protocol_whitelist", "file,rtp,udp", - "-i", sdp_path, - "-t", "2", # Capture 2 seconds of video - "-vsync", "2", # Passthrough vsync mode - "-c:v", "copy", # Don't re-encode, just copy - "-y", # Overwrite output without asking - temp_ts_file - ] - - print(f"Running ffmpeg capture command: {' '.join(capture_cmd)}") - - # Run ffmpeg with a timeout - this captures a segment of the stream - result = subprocess.run( - capture_cmd, - capture_output=True, - text=True, - timeout=10 # 10 second timeout - ) - - if result.returncode != 0: - detailed_error = f"ffmpeg capture failed with error code {result.returncode}:\n" - detailed_error += f"STDOUT: {result.stdout}\n" - detailed_error += f"STDERR: {result.stderr}\n\n" - detailed_error += "Possible solutions:\n" - detailed_error += "1. Ensure the camera is actually streaming H.264 to this port\n" - detailed_error += f"2. Try previewing the stream with: ffplay -protocol_whitelist file,rtp,udp -i {sdp_path}\n" - detailed_error += "3. Check for network issues or firewall restrictions" - - raise RuntimeError(detailed_error) - - # Now extract the first good frame from the captured segment - extract_cmd = [ - "ffmpeg", - "-i", temp_ts_file, - "-vframes", "1", # Extract one frame - "-q:v", "1", # Highest quality - "-y", - file_path - ] - - print(f"Extracting frame with command: {' '.join(extract_cmd)}") + # Direct capture to JPG + capture_cmd = [ + "ffmpeg", + "-protocol_whitelist", "file,rtp,udp", + "-i", sdp_path, + "-frames:v", "1", # Capture a single video frame + "-q:v", "2", # Output quality for JPG (1-31, lower is better) + "-y", # Overwrite output file if it exists + file_path + ] + + max_retries = 100 + initial_retry_delay = 0.5 + retry_delay_increment = 0.1 + + capture_success = False + last_capture_result = None + + for attempt in range(max_retries): + print(f"Running ffmpeg direct snapshot command for port {port} (attempt {attempt + 1}/{max_retries}): {' '.join(capture_cmd)}") + # Increased timeout as establishing connection and capturing one frame might take a moment + last_capture_result = subprocess.run(capture_cmd, capture_output=True, text=True, timeout=15) - extract_result = subprocess.run( - extract_cmd, - capture_output=True, - text=True, - timeout=5 - ) + if last_capture_result.returncode == 0: + # Check if the file was created and has a reasonable size + if os.path.exists(file_path) and os.path.getsize(file_path) > 1000: # Check for >1KB size + capture_success = True + break # Success + else: + # ffmpeg might return 0 but fail to produce a valid file in some edge cases + print(f"ffmpeg command succeeded (port {port}, attempt {attempt + 1}) but output file '{file_path}' is invalid or too small.") + # Continue to retry if attempts are left - # Clean up temporary file - try: - os.remove(temp_ts_file) - except OSError: - pass + if "bind failed: Address already in use" in last_capture_result.stderr: + if attempt < max_retries - 1: + current_delay = initial_retry_delay + (attempt * retry_delay_increment) + print(f"Port {port} in use (ffmpeg stderr: {last_capture_result.stderr.strip()}), retrying in {current_delay:.2f}s...") + time.sleep(current_delay) + continue + else: + break + else: # Different error, fail immediately (no retry for other errors) + break + + if not capture_success: + if last_capture_result is None: + raise RuntimeError(f"ffmpeg direct snapshot command for port {port} did not produce a result.") + + error_description = "ffmpeg error" + if "bind failed: Address already in last_capture_result.stderr": + error_description = "Address already in use" - if extract_result.returncode != 0: - raise RuntimeError(f"Failed to extract frame: {extract_result.stderr}") + attempts_info = "" + if error_description == "Address already in use" and attempt == max_retries - 1 and max_retries > 1: + attempts_info = f" after {max_retries} attempts" - # Verify the final image was created successfully - if not os.path.exists(file_path) or os.path.getsize(file_path) < 1000: # Minimum size check - raise RuntimeError("Extracted image is too small or not created") + # Add info if file was not created or too small even if ffmpeg returned 0 + file_issue_info = "" + if last_capture_result.returncode == 0 and (not os.path.exists(file_path) or os.path.getsize(file_path) <= 1000): + file_issue_info = " Output file was not created or is too small." + + + detailed_error = (f"ffmpeg direct snapshot for port {port} failed{attempts_info} due to '{error_description}' " + f"(code {last_capture_result.returncode}):{file_issue_info}\n" + f"STDOUT: {last_capture_result.stdout}\nSTDERR: {last_capture_result.stderr}") + raise RuntimeError(detailed_error) - except subprocess.TimeoutExpired as e: - raise RuntimeError( - f"ffmpeg timed out: {str(e)}.\n" - "This usually means no video data is being received on port " + str(port) + ".\n" - f"Try previewing the stream first with: ffplay -protocol_whitelist file,rtp,udp -i {sdp_path}" - ) - except Exception as e: - raise RuntimeError(f"Snapshot error: {str(e)}") + except subprocess.TimeoutExpired as e: + raise RuntimeError(f"ffmpeg timed out for port {port}: {str(e)}.") + except Exception as e: + if isinstance(e, RuntimeError): # Re-raise our specific RuntimeErrors + raise + else: + raise RuntimeError(f"Unexpected snapshot error for port {port}: {str(e)}") + finally: + if sdp_path_for_cleanup and os.path.exists(sdp_path_for_cleanup): + try: + os.remove(sdp_path_for_cleanup) + except OSError as e_remove: + print(f"Warning: Could not remove sdp file {sdp_path_for_cleanup}: {e_remove}") - print(f"Snapshot saved to {file_path}") + if not silent: + print(f"Snapshot saved to {file_path}") return file_path def stop_all_streams(self): diff --git a/helper/send_test_mqtt_page.py b/helper/send_test_mqtt_page.py index cbabb84..a9ef991 100644 --- a/helper/send_test_mqtt_page.py +++ b/helper/send_test_mqtt_page.py @@ -7,6 +7,7 @@ class SendTestMQTTPage(tk.Frame): def __init__(self, parent, controller): super().__init__(parent) self.controller = controller + self.slider_labels = {} # Main container with some padding main_frame = tk.Frame(self, padx=15, pady=15) @@ -22,6 +23,7 @@ def __init__(self, parent, controller): ttk.Button(rov_frame, text="ARM ROV", command=self.send_arm_rov, width=20).pack(pady=5) ttk.Button(rov_frame, text="Change Controller Status", command=self.change_controller_status, width=20).pack(pady=5) + ttk.Button(rov_frame, text="WORK MODE", command=self.send_work_mode, width=20).pack(pady=5) # Quick Movement Panel movement_frame = ttk.LabelFrame(control_row, text="Quick Movement", padding=10) @@ -102,6 +104,9 @@ def create_styled_slider(self, parent, label, row, col): value_label = ttk.Label(slider_container, text="0", width=8) value_label.pack(side=tk.RIGHT) + # Store the label for later access + self.slider_labels[label] = value_label + # Bind to update the label when slider changes slider.bind("", lambda e, s=slider, l=value_label: l.config(text=str(int(s.get())))) @@ -122,6 +127,9 @@ def send_axes_zero(self): self.slider_pitch.set(0) self.slider_roll.set(0) self.slider_yaw.set(0) + # Update slider labels to 0 + for label_widget in self.slider_labels.values(): + label_widget.config(text="0") def send_axes_x(self): self.send_message(MQTT_TOPIC_AXES, {"X": 10000, "Y": 0, "Z": 0, "PITCH": 0, "ROLL": 0, "YAW": 0}) @@ -132,6 +140,9 @@ def send_axes_z(self): def change_controller_status(self): self.send_message(MQTT_TOPIC_COMMANDS, {"CHANGE_CONTROLLER_STATUS": 0}) + def send_work_mode(self): + self.send_message(MQTT_TOPIC_COMMANDS, {"WORK_MODE": 1}) + def update_depth_reference(self): try: depth_value = float(self.depth_entry.get()) From 22ab134a5236cd1a5d44f1612129d433c198a58b Mon Sep 17 00:00:00 2001 From: SimoneFassio Date: Sat, 24 May 2025 16:56:47 +0200 Subject: [PATCH 7/9] add change controller profile button --- helper/send_test_mqtt_page.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/helper/send_test_mqtt_page.py b/helper/send_test_mqtt_page.py index a9ef991..709e2cb 100644 --- a/helper/send_test_mqtt_page.py +++ b/helper/send_test_mqtt_page.py @@ -23,6 +23,8 @@ def __init__(self, parent, controller): ttk.Button(rov_frame, text="ARM ROV", command=self.send_arm_rov, width=20).pack(pady=5) ttk.Button(rov_frame, text="Change Controller Status", command=self.change_controller_status, width=20).pack(pady=5) + ttk.Button(rov_frame, text="Activate PITCH", command=self.send_activate_pitch_profile, width=20).pack(pady=5) + ttk.Button(rov_frame, text="Deactivate PITCH", command=self.send_deactivate_pitch_profile, width=20).pack(pady=5) ttk.Button(rov_frame, text="WORK MODE", command=self.send_work_mode, width=20).pack(pady=5) # Quick Movement Panel @@ -140,6 +142,12 @@ def send_axes_z(self): def change_controller_status(self): self.send_message(MQTT_TOPIC_COMMANDS, {"CHANGE_CONTROLLER_STATUS": 0}) + def send_activate_pitch_profile(self): + self.send_message(MQTT_TOPIC_COMMANDS, {"CHANGE_CONTROLLER_PROFILE": 7}) + + def send_deactivate_pitch_profile(self): + self.send_message(MQTT_TOPIC_COMMANDS, {"CHANGE_CONTROLLER_PROFILE": 3}) + def send_work_mode(self): self.send_message(MQTT_TOPIC_COMMANDS, {"WORK_MODE": 1}) From 75474622cc70bc3eaac917e2dbed7f2552e70cd0 Mon Sep 17 00:00:00 2001 From: SimoneFassio Date: Sat, 24 May 2025 17:16:27 +0200 Subject: [PATCH 8/9] add 3 buttons for controller --- helper/send_test_mqtt_page.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/helper/send_test_mqtt_page.py b/helper/send_test_mqtt_page.py index 709e2cb..78d4882 100644 --- a/helper/send_test_mqtt_page.py +++ b/helper/send_test_mqtt_page.py @@ -23,8 +23,18 @@ def __init__(self, parent, controller): ttk.Button(rov_frame, text="ARM ROV", command=self.send_arm_rov, width=20).pack(pady=5) ttk.Button(rov_frame, text="Change Controller Status", command=self.change_controller_status, width=20).pack(pady=5) - ttk.Button(rov_frame, text="Activate PITCH", command=self.send_activate_pitch_profile, width=20).pack(pady=5) - ttk.Button(rov_frame, text="Deactivate PITCH", command=self.send_deactivate_pitch_profile, width=20).pack(pady=5) + + # Frame for controller toggle buttons + controller_toggle_frame = tk.Frame(rov_frame) + controller_toggle_frame.pack(pady=5) + + # Adjusted text and width for the three buttons + # Aiming for the total width of these three to be similar to a single width=20 button. + # (6 * 3) + padding should be visually comparable to a width=20 button. + ttk.Button(controller_toggle_frame, text="Depth", command=self.send_toggle_depth_status, width=6).pack(side=tk.LEFT, padx=2) + ttk.Button(controller_toggle_frame, text="Roll", command=self.send_toggle_roll_status, width=6).pack(side=tk.LEFT, padx=2) + ttk.Button(controller_toggle_frame, text="Pitch", command=self.send_toggle_pitch_status, width=6).pack(side=tk.LEFT, padx=2) + ttk.Button(rov_frame, text="WORK MODE", command=self.send_work_mode, width=20).pack(pady=5) # Quick Movement Panel @@ -142,11 +152,14 @@ def send_axes_z(self): def change_controller_status(self): self.send_message(MQTT_TOPIC_COMMANDS, {"CHANGE_CONTROLLER_STATUS": 0}) - def send_activate_pitch_profile(self): - self.send_message(MQTT_TOPIC_COMMANDS, {"CHANGE_CONTROLLER_PROFILE": 7}) + def send_toggle_depth_status(self): + self.send_message(MQTT_TOPIC_COMMANDS, {"CHANGE_DEPTH_STATUS": 0}) + + def send_toggle_roll_status(self): + self.send_message(MQTT_TOPIC_COMMANDS, {"CHANGE_ROLL_STATUS": 0}) - def send_deactivate_pitch_profile(self): - self.send_message(MQTT_TOPIC_COMMANDS, {"CHANGE_CONTROLLER_PROFILE": 3}) + def send_toggle_pitch_status(self): + self.send_message(MQTT_TOPIC_COMMANDS, {"CHANGE_PITCH_STATUS": 0}) def send_work_mode(self): self.send_message(MQTT_TOPIC_COMMANDS, {"WORK_MODE": 1}) From e6f3bb8da32feb9a9f755eeda36e459b097d5176 Mon Sep 17 00:00:00 2001 From: SimoneFassio Date: Fri, 6 Jun 2025 00:14:48 +0200 Subject: [PATCH 9/9] deleted camera page --- FLOAT/Images/Deploy_image.png | Bin 33704 -> 0 bytes FLOAT/Images/sd_AM_inconsistency.png | Bin 100383 -> 0 bytes FLOAT/Images/sd_CS_ESPB_stale.png | Bin 58708 -> 0 bytes FLOAT/Images/sd_CS_fresh.png | Bin 71572 -> 0 bytes FLOAT/README.md | 148 ------- FLOAT/espA/espA.ino | 559 --------------------------- FLOAT/espB/espB.ino | 272 ------------- helper/camera_5004.sdp | 0 helper/cameras_page.py | 223 ----------- helper/main.py | 4 +- helper/requirements.txt | 1 - helper/rtp_handler.py | 237 ------------ helper/sdp_files/stream_5001.sdp | 10 - helper/sdp_files/stream_5002.sdp | 10 - helper/sdp_files/stream_5003.sdp | 10 - helper/sdp_files/stream_5004.sdp | 10 - helper/sdp_files/stream_5005.sdp | 10 - helper/send_test_mqtt_page.py | 4 + helper/webrtc_handler.py | 386 ------------------ 19 files changed, 5 insertions(+), 1879 deletions(-) delete mode 100644 FLOAT/Images/Deploy_image.png delete mode 100644 FLOAT/Images/sd_AM_inconsistency.png delete mode 100644 FLOAT/Images/sd_CS_ESPB_stale.png delete mode 100644 FLOAT/Images/sd_CS_fresh.png delete mode 100644 FLOAT/README.md delete mode 100644 FLOAT/espA/espA.ino delete mode 100644 FLOAT/espB/espB.ino delete mode 100644 helper/camera_5004.sdp delete mode 100644 helper/cameras_page.py delete mode 100644 helper/rtp_handler.py delete mode 100644 helper/sdp_files/stream_5001.sdp delete mode 100644 helper/sdp_files/stream_5002.sdp delete mode 100644 helper/sdp_files/stream_5003.sdp delete mode 100644 helper/sdp_files/stream_5004.sdp delete mode 100644 helper/sdp_files/stream_5005.sdp delete mode 100644 helper/webrtc_handler.py diff --git a/FLOAT/Images/Deploy_image.png b/FLOAT/Images/Deploy_image.png deleted file mode 100644 index 9baa626b4cd380b1c04396146486d55a3baedc2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33704 zcmd?Rc|4SF|2I4-2}x2ZvXn#$Eu?6WwUn(CVMww>$Tk?+DkPy4m3^0O?1o_|Dyi(t z*k#E!#y+;O+@I6;x_-~~+^_rj=f0ocU-uuqWSlc|p2v9{pU-*bE5q{FZ$5a~c>h#Fu%b#(;ln1mCHZOl(HpL*vUJk<(LQ%H zf9O!`JbG08e56zVl85{#U4zB^9Gn5lw=l?+6@Ci%?1FPgDfn=7Y(t@ZP=dMJ;n!`d z_n6=Z!>iAG;Kzg%G%$!H9Q58;8Rhp_ z?6f3_p-|XA>ukID7(6(}9z?{(PDQx2l{#5!TBCd(t>wl>Mo!obaZKA^Ro=09tdUtm zxPY1Sgqzr`ppeiv!=dDzs2}37{rwBE7d#dpbr(M5gd;D)k-Ov*goK4XvS*K;JXsrZ zdG2bIlubnU2pm82ZJr(_liZ$TVlTh3ESSK{91x`WD?U=nhRFGGVXC*A=sZ5yz76%l zGW?WY@f$%kgKsYnxO*!p9?gBPGvOjoxE-~xPK67jY^7EOFPT2aq7;rDD->+n+wtq7 zqAW^)gQM%s)m@WY2kuMY4Sf1}Pe9`y)K%r@*y9WgviW)jkVyCz?}_}5#$3Npw#s#r0hjvrH$9c1(6bw7rj0Y?Jw?DNkdPdNVlVOQ>{ z`To}@E5I-R{!6@IZj$ycD#}M0&iJ*E-#K@RNPJ+$Gsh zu4qBQ>hPM${9oebl?l2W9YF%IT2@V|uf4t>w(KZz7|ObtqCN$8?1ff&B{hCex@~uH zXGfk{FWs=z@oza=p;i!cRJ4^f&$N0ctUrZB?aI`?{{4Nv&5HNbTK_#3&8qj*bpJgT z&C2kX|M~?EyYXL#!I1s__b*}ao*Vx@EDYZB`@epH_XKX;S-1g0zMn((CFNF_|2k;T zit_my-&jxQxgYp{`#S&ctY!K)McxuZ7}T#{FKBJmjXGoclzbDLlAPRe*fQFb|H+Im zIgG$^KvW-=EL0YS*E1W%&%C(0i)~NM(7W+vQ`TkF;wS>6GM6uD*BU2xF_dV9`+wHO z%BspMIXXD5Z`GLWGYhBs%H0bH;UA_dH@)n|?4e5U!dF#P2KM#uyQIE6d z<;S;nE73IASHN3^{^A^+645+I+-qf#~o7b-J5nx$N6Bv~B zs+blJoVuewKT;=l@?^TgFIz%y1eIOWMB#TVx|28qU zoa}XyC2j6Lbmp^o`HW(wF$ve6$Hp!Bcv}8e>W#ctuXaz5QRh4~dzYrlrm@pe115he zXTS4sgf4NRD~$t;wd|&Y6z;0Bd+-(8^;&DmuNO)^>S*M1ALgJ>WagBkEo{j6B6zuV zinL^G)0`YgqED6e#jdR^k>=}VsZUwO9}5>pACxeDWa7PEL?~L9%a#do-b*6FsS%J?LGpp_^6ZDT&-|>nXA3*%JAD>FTc5| z-m>nD+nGJZ$hSMuoj1=nTy7~!Cnz)TvEE9q0Rh80gr>msFo@p-Q~WZub+lwI`WGS01iD_lm4c9cuQH5nFJ|6LsSEHEV4 zU2vJuCGbu~7~0ih<;9*cvDYtFEdM-}qpisNyhSA~@bvtS{nqVSALRxE&MCQC)kj}~ z0Y)!&m`!;Z`0qYESTr>Q1NOWN`mD^*tMffniORLXF4nndr_p*gDeKlByak&Z^ni0( z5q+`RR=q@*soBEmxnC0O!H3QsqqvkW^?CH^FcM&DYmYGbXpaO+zH{G)4Rxww7JhzC z>u17mc2u8^?1Kjno~LTX@ex->qLc#oy-H+_ms-|qf_b>QN*t10hxg#>JXaTLWi}=Y z8ukS9p=Bh^zVBX=)i#9Ns|eqp;~Gl!+FW01e8w*K!KJdR$Rb!rkiWhtd8DL~fV z`Y_x@a%APnTdB{_JtLOI)z4GNIZKO=(w2O-ZQoh46bKXM;=*FLy@$t~w`RR@c2`jFWyfM~I3~TlL9px1j};zm&NZ!W%(`1po}`o@ zW?1|jN1F(DITu>!JlWBN#%oci-Gu(}i|FsXu00$wBOlCqu=Q^{N8`L>UH1Jd9ZN<~ z6E8FBNBSpU&%v*OcbCdWB5f2i^>P*$hjRoP4)fI?(3H0A(vANt=dn1MwZ!Uj=fJSb zEMGwWQ|`sf5BzQI>rT&e=F?eb$tK<|MbxG{={JR3qgFP*h7XRN`t`ffE|^EUczvLFUQyJUH(4b_CYniOm- zv}oCxl&Az9ylZWpL07+16e6PB_TDN8VooG=pKTYWODmyj* z>f0`1q_*>D2+51Gw$Z~jy%LuA*@|ED_YG-VJlNQ-ZZ$yaT@kzFQ9Zw^+gt8FuRYyI zQo5C<=@QpbeIPji6SrKXRnwYd((jpl!h3U_;PI%)#IaT=0Z<@u@i(VZ`@CiBRU<>M zR@nq&mfkcdZwXK>-8~fX?~O^cuCzY-@3+^AhuW%ha)hg4tnBdwMS9c)TW*7LHwTgV z9dT4wN$jLP6v2h?gi49>rK9DT{$tO*J!Wf#;~vnw#zuFdCQp|WWGjWrrHw|rf5-FX zy}z4s9IBMJ$oXVqena#e#gt69uy|ZA^WD3WW!kjCMklmz>eg%fF!xZUyNXacMfLEL za@#_=rGD059NL}ZLjNYo@3oxZGS$-=T$vHef;k?!LSG2!I65Cn_GHk~(rPeR7$><< z+83+Y=D&>DyMu--Sx{StNoEsLA$fL-c{(- z?`|))sN>ENaxJe(IBojwL$1)8C@yYeOrmV^ob-+e&0{RTwB%Njc`SS7Ydz^y0=7j% zTBV%ZSUA8Yhtz)a=FR*F%@`STPruZh?^C6td`p+P^L2zIRu$qM53zBLw*-Eb2x=lb zIgR{wpt#?yc;en3zz`#_(DuN%DwG^(ztrpMN|DppJ+S#37mOoO+OwS~iJVk9`s7f% zrznlt`}}KIR7B1+EtBi3X0z6p244u~8wXU#wa%h^dj3kQzxsKqdfX@zCG+6N>#QbI z-JOorY|>H<+#W`+wmsH5hq%@Ute;?Y*vgDEH<|F9fjIPyRe2nF z`YP;$k%$jP@gU8IU_%za&-@birHyAGXyMvj^q~nhy^=*P&$hJB-n2HovV5L6+?W&3 z^aWwsLS~J;MC7IV%?wShj1kvkHyeD7bH+|7&`v|wyRcz4W~pbd8ZLS}UvpwYN1I*s zB5&M$rUvcm5w}0SeG#Shrx&uXB&!H-tl>0JD8{6@gLNkzhk~WM?pnr}pSP@ESe%S^ zT1a_s9O+`3Arp9v5$kEjyU~|w4t>(@wLf&B4%v)9t(Q{vamI=N_-%6<3pFWXZ^wLm zW^KRsrYF6Bb7S;`SaYpN+Kjxe=gmc7jOghYWmF-sY_d)yX?&9_2> zv;lVnXAIb-Ql&kQt-5x5+;Kc0jL$p6+^uE3nUf zG)DX@EHaQTe$*{_z6M4aQB35=(&mXr2Ew+OT4gBT0 zmP3Oxn)b)-tdbC&Xh{q8IIo@a!Z^;NHb|L^k};yAE1e#P&`Z*_v8O`e%<29nTxYkT z=2D%U>zDGQgX;SybejofUV*=1ARoOq@hWBGm64>Byf?7Yb^OS;)L%EzwBrtS=xQ> z!SvWu4beA|k&(8JyV%g_hX)<`(rSKO-bVa*ugLQYBi94ATPHsXKa_S?uBWeDudfAZ zOm@G8zM7bf@xn&pVYE|JtMHT3DIz7m?qFnpZb<3LvD}c2#M;*^jvJ$ZQ5b#ERf9~} zra%p|R2%DoTUux-%AxfH3$KYiXh5QNF9&9PFdd&`olbW`&-l_^P>^j%@CSmBkVQ_& zGoCMS7*ch06rU`tgH>E7(>ZphTV@vdudHJL5RB(=$9=PgXk{zQL!rGx^h(y=30F?d z$}({b@d3$USQ;&fx>uIC6B}1w1F+HY6Vl+P*$fso;?Mr38IQRtuiQV}u|8Ty^*kYs zl&h=F-sd(sKuJUG5)hX`w7&l~4ef`;K$YJjg7*wjsCN~NtOq-QMEtegX3p-*+gWHs zuE#@%0RSCCW6(PE4Uw34|OLied4ig!jCty}P7r+MNjtxk;x5 za|NS*iI@Gx_PXft$UQ09dh_gddcOIu9x?5M935{opz377KrF&ULpVVB9TZBv2C2z1 zVY?d)`S>WwU1$@z@g8U}#X=l-U2*isGA0K-~=! zZJCyp>x)syDbyMgozqj&($3=!|2z%qQW3Q44nRa7Fndti87H)2ADujTauHC88(bR* z9{8}gZ*BWMmx{hTWAXsK?%ib)7jr>OV%D)-LA`6&u3`U%>viQ+Zdl8&FT5qQz!%&v zzV*&!2X=ToBNOjP;1t$$CcxVy8DxLTFv!le=9((eheG8iVZfIR23!2uczSl@Yxup( z*8w6M+dLX~UwDEuM$4n(trmNnv}Ea%1-5YV^9DZoexP}^W!(N{xE&SmJodB&Q~($T z!~a=xNct?dzHloF#4N&r8vw%c2dV?Q)6-%nR7;UYI~gb(n+tQ+O>Oeg#@Y%NhPTXY zoo;1F9axK8h(&vJ{R}@v1q53t<1$e~A6r={$8D^QeP~Kj>xLRP`khE#=aIDfV>}A= zo62jxxIv#T^K6i#XZa}}&2b4RvLPef&pw!2Djz13TQ+FCpbzQ@aChYaXoQPua2NYh z;6k}Wf#QYnq_q{3jXgRI?Mdbhm*-!x765f}Ix3q6WUD7wdJ{m9K}`s+ZPjz;c05Lw z{^uF{cTgzwaZj$)F-D59jOur0=IFff6%)F=Dy@GDY8Sf2T>h(=b4^1T@V&a9Sa2Jm9% z_Xqgz;f>6;{r>830-QjAL6P-=pSwr#8qSY4H`d!!cx9$ah7=L-L=EDS*kitPP`lcn zO{u`5&e2xRHj|_gbs+&@Y3YStttIl%*z7_{h5Y8)`FCMqgHvx04`ZUdpKLKmo>w*= zaQBoxUO@w-SPHmc*E802{QOLSYA7Fd5xvl;H07FA{G0sC3s=mryq;^{t)h>*;*e*_X;%hF=Kl8JBi@|n&t4A*xNh_OQq{Z5_ z`tsP9H=TP{K_#l`cKSwY^MxB{R&pkah%?K{x_ zMvZTr!SN!m_a9#-qDwftO5$s@P5WtCpbC>PI~NUHwa>`I;M+DOs^BM8ogcxC?V)W4 zu_Vogv+{_lukl~`M0VaB(qg0-hS(ZD{%K9s{xRT&5}WJSuRG;zLk)7g6;6N(n)G@9 z1`$iO<}!AJyI?pWrbi-(FFaWu2*`H)`;()aB~j6jgm{STWK<9eY{{BY17gW&u+MS_qNOq)U0YsfMu+^MRAx~e3n42;Oo}z zEDrtF^Z3_zumvS58Kk;C)Utysk(W0C(YDdU21$v>R}KBZbh`kxWckaoO$88=9*uQkM7R$CKao zP+j{yxg4VBd#o;FF;Aje2EPUM+9n&@>y&IXcyA0%#myJJ@H)t5m`cwSu1(v=O%qL5 zHOaaC_e@5uUW13GSM6(titj-Znuj@{k_C=yf$`O_kiSn7Jl!tn~?#UM} z&3@&?*e`ExEXljRNztN9ouISJul*@{ls1!NY#prl*6H{mnh)iYUFqM5n5rV28&Ix- zM@LN>(pZ&l6CHn_t#Qll9FOv46)*YRRzj)5&_2-@^hMou(u2GzqD@w;j~^nngQ(CA zrOV7R#-&}83okm^@6>?C?=d#TBp4^1w0eH1h_p8MOXrjz0}3USW|YB#@m0L(ri;?e zc0N7+RNZd|z0}h}%gW@!`0CrTB!pg`dtq~H`Hn){b8ZRJLYU`#owT@Brn7Q_7f5$g za@?LNw=?e)Ljx(v=j?Uu$ThVa(V;y)^~okN5m5(0l`GxH|>+E8mt|jkI=RT{p4a5IHa(iZoUIUS@-yZBs2az57uUNcx z;nYVIXB+078VBDU?&y7R1?LIMoSVq`VgEZh#=Jjw4|JZ;oLh%Jm;iXM#LOk`_ugr* z3b>-v-NRQ0IFHuF$@gnK9_}9n(GJVW|1eD0BsuV{GUtil!{<-DJ3QF?RgJj$(K7b% z1Ubi~{kX=PWlp7WuaDb$Z5Vy>l}5jS3~eEs#$bLWY~$_WLq3W+cm4fcTe&1Bg2h>N zJ^F|)HnOzVTbR%i9O-)4_h2$%yLA7P0uVkf4K{|MUjNu)xWW5USI#;^LDJcHFU+l0IVNxlzWj7ke<08MCeY2n%9Kau}l> zO$U*rj{~J$d>`@W#L-np}W0ch3w|+k#I}-XH%P8lX;s zX|beTi9C-m`0alhuwabdbmg%D-QT(3x>lrQtxX`Q*-di?k1wx|L)&e=&a&wW8))1# z0~G3ooQ15)U9iq{Ct)qMgLEgo^)XeC(nNv~v?gF@714qyEqgA{DC96+eF6>&YOgf6 zl=TCpfIUS+A+q&0Co8};phFopx|?QQLupMn1LY$RKuWdjeM>~6LqjcSkH7LPi{A5O zz7El_^y_CY>%R5+mnHEi&U5i@`@C+BajzYTb|*^SyTbKBpL0*IYd=-4aCxb6@a3sT zfU2e}Uqkip0)hP=uPn9@uA#K}G2He7yIx|cne*wv?Qn?%>o!rtN-q+D5vB0>q>+vO z;B^U7YkSsRGZ4~?^^D!WiQdk55F_J~-|t07NKt2jWjAQ?V!P*>`<19zz8f=3;8nkUrY}nGJ+=TFA>u#IP8ti|S_Le{xT{&n?NL9=y{M za@J@ov8tr%33Ss*KzO0cR}_ji!Ci5v8PosD%tqOze0_vjxtApY(Bu|Z7&Zqj9iR|z z2Br-A2|8i|a5`c!*eH^Q-B6#E;8GFcUSxqjUFosZ=e3zlLJ|fCa;c;K||(@5FH(9JjecF++pauZ(~n1>ur!w>ttO)~7F0vyDm}@zm5PyPxf; zd<(!rx&S5JXX15!?P~8NBs{^~aA~zO`jS)6-tXM(6;LFNDOhgDbLaKT`lb>5Y}0#% zGzY_+3y#sHg=O5dZVmzWOR&l2_wH$Y!1`EH=%N7u@l`MYm+)khnjg%<(SP`Ebr1Br zWilE6J>TWpe%G=z&ZLq_!{^hv!|Pth=ePUNd;JIrunswH-_Fp@3lb;(K=_Cr_jZ&* z;YsC+)rri$_WJ$C(_m%kNpH+lvl{|V5iAb;sR{t!Mvd3y9c%7@^DFC?>N+U95vT9& zn{`V!B;apn8?;%}M~@dxJ{}Ad#@WbD7LkpSzR>|U)0Q^TW^999eH}mAYLla#@RUq^ zwi(TO@bu#ZBYqYHkuH5vT%xV~J;O4YVam1s3ebxq|NRAe({%cil{o-`0a?Y!jWN@~ zK>|T0xE9a3lQfC)(RUk52$)3lkK+7WA|$X_dRJj4PvJ;{MF*Z&%>uii+S(F;&bVg2 zv2In0b-DzWVh*ODsi^G8bOJipMBjK{&s1Pg1q!3-fuGpatl{uuFglA^E z{flo-{ApXj3z%m%O^JTDv-F#a0u{^TzFNH)0TZEyadYMZ=0>JKXfx35RsXtlij&R8?Z5b%{4#ZEYCOoOh$!WMgvWTqnzEsIimpyzfse(BF+(VB5E&gkpqU}H{ME_8!C7fbDC zdAEl_Rz2GLKsgRzkjQC2&G6*O($QGs>sXfeEFXy%rKF_V{2H#>CeCD^djo}~Ys)TF zMlU0j%CKsjK}(}AIj_BPb>dWxi){GQjA-SQge?()SPl5D@)3Fw7Xt5T22EnJVjDzA z(B0E2sgg!^kYcbBv*I-q%td2%Ig+ygt%egLZS^tLw{obaY6I7uvYqq0@;cz!T>2t7^V8F#XxJ3``9P5$ z9OF;!^CRNNDehp99x*^%|6%MKhBB*WAx{Nut0falXo5;DX<7|Z`gFi!+pD3Hmf!gr zb$nfT-djfd0k;#zgjH_l^LFE3*wwU@$TH}xXhXL6?|yB=?A%MYi=LxU$IoF((vR+w zdh_PzL-nxl_GA?Tx0LF1*+BKBV_w?TA@@7;&4V(XJZ8QyWqWUKz?~$1QaS$x!IF5n z1~oR2wS<%etF2DxX;@#?4>bW$_6wpM6Abk6v^YD&{wtdiiaw#U4>LJ9zulw0Rs<%a z2u38G_1GI(Hm>xuW3+7Svz=^k-jJnwsZnkI@Q?`RVNT#N-D5*r9=v`LakX!hX%PfC zA_#yiHh(_*wx?orE!6SeM5}1$e?~?L=1jY^( zaL@eWqd3zk(6APY0p0ivX2SgV>d^6v2na^+R8FKj8|Mnh{A7f}Q&q|b6K^SpYwji+ zIR&qe%5ORh)lFPTLxA()F-cY1pWT*YZ8xV2n^xFDu;`oyM2f}%xT+I z*!fW1G9iE$rEN4}suwo|VioD2fCID}7X*GFpygDHed*tW(m@6nA!rz1A{q6`LbmQw zo!sjeB7s+a_uwemi$Ib~W=&j#Hmm$tsUZBj*uFiXk&i@0{8$c@Cjq$J%k0a0)}>bH zeFuWIS95EL)BHlrj96U!+5_ftmJ@+3f~uX)t(@4Yo$J|Du9w2s6Np!JsqMo5Z3 zf|f)QM2_HMkiD;&^v&uOmR9&)!lW;}3MmzR#_+dc5cNJFEf(o4cCQuzqI9KdM18_A zq4pa>i>HEcH&^WQRRywF7ZLRiq^J4f-x<2;gW20q+LDn}$tPG_0Udz7_a$4pKt=o8 zzSL>SkA%W>ctMq31Y6tPP+{=?yAOvDP0(em@k{s9(*}hZha-M+)jG1+ZBW0ys%IsK8gB`IJ~FaCTS%YOwm%;q$vF3ehEFi9txFB;w7R zfg)63;AcL;0aLV?SRJ3&vZ+10k3cE7{XMx!Fs{yA%1-J#25TV028hrF3&sg>>-)!Y zYZTn{y}=Bf^kw3kSw!vH7kp;6`MN}DZeOvjAtV#{Av3!7qLDMV`GDyD7G-H`|I zw+xbj)HXd67_YC&_astha`A6Y$Y3YOsN41)*TcAklOWOa+(qC^`P|P_7tDX|w`aY2 zW5?qCUF;NY%v0ttpL<~2heH_TY3`omAK*52L+qmV4ltM?M#<=z!&Dzd3@q#vkSq(}_SPfk3o@SF z(D&e^-8)gQ&+M9H+{@Pv7}gG1;>b`&gQvOJq{hzy(NboilkaK`)poFqiy0K=uFQ`b zE=~2?f*3Z3-2Cu#Pf#*d_E3N@L_|hf+q7rR8qDcI;K!Z~<x1f`V=qrvI%k< zr2;&o5?cYdmpUiFV5zIWGPI%d%NGqVw(B9*#XrG1X$uI9^u_+D*xc}-LoI=z z$6Gf*KkR)6QSrx-PK0f|!qkZb@2Xb0OrDssU!L*FG>b!f6k|Y|?t7!K1}bo?%XD9F z+p!T4Bzihz^R1i*?VwDzPr8BCQVgY#$QrhD&yg|B2{4D8=sVfChjBIQ#*xvIbw!)E zGZ{9{)*LZ|0HF()?0BMZI&dS8S2J+~kXFe@d}!)>NN$;T_Y>?*WdHbVFDIdV))4c5 zib2=q^W~);rzw)+=!4B8*$V8(Spf6KRCKjIHYyck=}<}W>4l(G7M}wxK9jHxohtvj zcy#6jOQr_=FP(( z1i#7(N*o59TUTsiFA0($ZIJ=RqL@$)r#E$ZdVYIZpP`R3h_Q-D8>93_AfZMiLxyXq z<^|clJxMJztMRhM?+;lhK252ai9GP9)~S#_`yDxjn;Wj(3IOgwi5y0fJ!L4D*}-p% zUpci(?A0pQ=B}#-T!BctU_yG|liDyLI}%_+_r>inez$oUA=N}(js&BWs= zxI|DW`is(cb6h>X1AF{54J!ftyZdLHb;GIK8N;^bX*g_n`xx67i2$8tvgcaO~qtxpm!8U0p<+%H`)t2F^{AVdv^zt#B@ zs*t8(jo~xXcBl1i)W^t{kp&Uc^b3De6LjMxdK*((;zo9AN(z#Q%f4Ii-KI9G!c^z* zfxX8C)j|r9*h06c2gF!~r3(e`YbB*3?zDC5r-6;$qs3#UYKpR;&l|mn_%{b@7hD1F zwZOX7Wm|@~?*xFYp4?!@1XiO1-&c<8j!%XTU1dP9vqdyE^3BENQID??7HfCzL10Wc z>-~OOuApmeZLQrEXWCekQee9nRMvTe`P88``q&2J>~!U(KZGvdyHo-<@`Ko;mi_b| zsBsvGv03s;-}~&Nt*YwZEp1sJ-3Uc8z-HfX1(DutSFQMkmC+iQj-p5sH0QvJ3Wze5 zdE0=n^_U=Xcp+C%{NWBR&-@14k8+;GGHqR#Ns#$|NA4d-2xN)~Eb!2+2t+9eGnnzW z@<+ogRBlJfC%(e{_Ff)fBH(MoAR4!p#T>e(!YMMYsM|DTrF(n!5+o07x1XxY) zIrn7wvGi(?Gi0^eO7-wYowk{ng7}ve)@_eN-uU~s=HA~JqR5FR1WMi#MJd0nw*@qd zHsw8=W3xK4ooy)vk;RR9Agp&e|@7CoE)ps^aXm?KRyxzAnR z?a)v>a55`t80oJsI3fGx9K=87GCYAW1qWxjl|bBAJ=_O z`y&9&bnj!Nee{CW4u9zZv+*Istd3_f?FK;MgQE175u&u7=7#9Eys$2?Y&em{v={k< zPjfT}2*gL>0ygI3Hap-mjK+}d84(O(JkoXxQ@)8?AFdF|rC4x|6HX?87yF?uMwS3T zk7bbY?*1+vXXLCHMgU|JphUjU4f!AoHYOE@JZ1NZKZtO>;|J(R_W{2P!uLS@(X0|0 zTi|or+}~dwHXeOdACZtov%Ef23W zd}Nt~^v7JWw*HRACwn`5|3F-XLu5@Piyb5in{D?qp}30|axwan9&mKbU%AKhH1u8>!Hh8hnGHn_z;1yiZb_@xE=IrsseoS! zfr@mzJaDQ!iQob0xqP%m{ofaYA-RbBg2wapr`0@!T^C>J%R$D^jIYG46xw zp6|KTOAf~`0F*^E+w0e^(0;W!^R)qx}bZy8M?K5 zt=NobPJ-4mViVAu5i`z%shdGO8QSCewA zbUt2Rej%Y};#pLLbVG__Q`r>p7cGMfX$E}BAd6mC;$qcKH%9xmWIB>JR=-!3egTtI z`@FIO5Mo>S!jp9x84Ctf=_r}9O`Qc{9XnoHw@E1{iHo2id|cj675rKb+!cI(LaBDP zw!G)6v%Ni5)b$#YfOhtM2r^eTxFdGn)UG0GVvu+~B4ALTHhSuEa|ZQ!2}o=af?F%W z``!X0L)cPCA0CduLU6c@ZyHJ97_TBuEjXCtyry<;YQcTyASa(=9)K7_;rQhs)d+Vu z&E9XR8S+SQ{#ZnjGPjUw&{QTnGbC~xxDwA53aa0{c~#F$ z_9bDUy{iArvv{pIIeh(X`$Uy>!?qtBENuUf!_=Hwr=7dwFSfE~A;m%WOt7oy-G_+l z)C2yq6M7_a;ZwGdP3$Iv$`Be&ws;g0s9eaC*R<&JN# zP4wSC_TjvxrpWmKd7syNOAO~ zOP$#i26<1vxE9cdCxL~yQi#E=E!nIqg<1t@YxQNMDApZHkEQlvyX$1F%RnvY--;W= zLQc+zE4VY~Y~egE`e~!p5pEtjgbo%AQ1O${suiNO*-Iy$ST@8`iyox$Sp^#>B+Rrc zfB3DOWNT#tIE@M;3SrR*cMoi%2ruZ6NghXnKfmE>WAArv(XewP^+aUii9bC*fDgp$ zi{6PuUG7UDc}HL_!h;o6;;4Pkei}zlWA_u_a9C&}TsArlWW-LII`#XUW&M%q+uNG*z#HT`!kWMT`01lK z*rf6(Ef$x-qh{cHIa)Da9V2O66rxjly}tP{?GF;(zXM{I4WwY+Sl3;DR^g!irw{Z> zOrR#X<+gwk@Jrs%2l{m0WSdm>-Mn>cYkwa?g0|H4Z9ae@YhG(^q?Dra;sx;bJ}mk1 z!-z?QFE$#w6|gC<4@L*;(1dReII66Zm#$l`aW5fgcF(2Zy*X0L3)$7M1J6tgO?!8$ zx`~P?6BXt^s0>C;0SypC>4LlnHLr%xsUP+ASHOOhIjb+)AJIRSX!Z|JM`m2=TQTva zuoVhiuOH}ZbwZ%U60NdgVlh+}5w8JaJKGOmQcBr8;9(auRp<)Gtd-i3W6n)=O&t zBfGgakE!##==nCDU1;^=vGw)wC_mV}PP~_+cZ7%L`oM{?2>ES8?#Z@hwuCKLPmoba*BAgr68iqZK&uEa2U1y6?Y z`+0c2s9Q0pdO!Fo%2=D&abc9w=42yMdv(Ee6_!QGQE{pLBW%(=_n@CHEix#~z-C%5 zT`f8|LEX=pIUORkynbYC_1<UO0^*d&8mK``<)Fj3|bjc%(C(h-(8= z*xhxFk;~{0LvUY-Q}c0&flzPoTT1#g(6LtK*1;kiUM3iktk=g`)+WB~*Kp6)@%E`| z)E^sAI^G9&0K3qnR>n62XDrk1+Nz^g>Rqrk{)qxp?0KIYnhyLq&HXrGl)y#ffD$zYx3&F)zyB9+qKj|HQL%q zqtL_WztbYQoTIHgzu~#>#rcQLQ_K$Zv<=|}a`@^IuFcMp*yk1Af)cty8XJ(B0Ji2# z-C(+^!yH&uitB)i;i@N>bdI}MOKK``5^~kf2^hhjR%2@61cx`0J_5je29TW4T~e@# z*GdZOu;{Ho6?VeYU=!goKp$Lg%Dxz`*oi?j=^$-2lwZD&HnKf0l|4Q~k318y8vm&_ z;+V$s-Y+qUB%a%W7kGs$Px z?ibIfROhWgTRc6ohgar-A7`(gRHbNU6AulxS`JJM2-eMg;HULu#`dOtPLlT0(TCus zB(DcFR}6Cq?ySn+^8-m(R9^C*?ALh5)1Fbuu}#EB61Q{<4Fdl z5)|gitb+P{Ud_gGihmQh7j$}hJ1uEWl_f%2`zxr;rwM7(0l=i`#6t+ zTctsK)h4=A&7glTeHUku<-$0>IVINUhmSmSUDqb3Poqi2-RthFs`96t+PbT%YFrvf z_SX3N)B;-r6e=57nU4Ghg28KvA8#D!xXqWyo@bzEcsFt2l&tI2BaknPnfTm3*WsW* zK(@l@hyA-lb-GYv4!~x`R(dZ;P_9=#T02X9$AKGHp!!)mdj-PO<0oze>Q-h1jc@Ih z1B+WPG&XowQ8x zz{#>6ok5N#S5*u?!Qj*SiRn#~W=)#owQFl8j=Ast;FSXDbPMt=;WvbjB1$GR)t<=vTU0DBskv!Wk7Qd?W)# zNpThZhI`0>i*WEcZb0f4A8__7uu()?Hz~8rsV&_`eYRS!a(Yg_dcllKQii$Fc zh_JjH`^VM%pJI6Wsz8^Ucgrj5&@JFvO~CvWC3dvRPl4p`del(T_a^An zSwNZW%5t5rWSZlnjf5>DB=qK8%=&Um65JTEgLJnO$XiJbzJgm ze6kY0Rq#}XlDG)1Lk=RdeRsxjkb1{VpVKy4B_!LQ{T{+gk$bZLxqsK`KvM>(Cu#nF zZ>{K|upz?(EW)^7@S9qEq1>caGm%|6`Hl6{KMEMCBu%d=f{9`r3j-DwjGGU98 zk35S>au%2nc*ECJeMXJ=dpWcH6cY%%RRE)TW*v^7D>0SE{vPS$hsB}4-X&P z{7?1S_EfGnKm5EW|M>y>`uk0DAUg0%KFQp|l4O7AnxC1p{?8Br@`i%cKxCk9deFG>!M)4A{f_ zXtE;@+0&6DWsgJ#lar6zpThpf9Z+1)_J^$z$YW0o3oL@kVbbeHt1CWMpkTO8Us`qT zAbGfg@-6rOMavBVGM0<&Kj@3*|HeFd1+2ruy&VP6c)K7`b`k_arF#u(It+BERpmvA zu$8_$3!Xx-2>C~xn2PJl-}fFi3QZjUi+6ZP{!bH1oWTRT1FHH|L7;Q7ap<&fxJZ&A}>Nd@D03l9fq#l`yC?6kfZeUWrj>8c>8k#DrLE-VpR#+JC|F}V-!K0#Jci3>z!H~^EjA%`?Ik=1ibT*$fKdc8PIp1f{h6>;1IjeSs01`BPEveDj<-%`V2)dnFj@P zgixH0JXmZk~ZeZLsQ$?0RyaHoKtpn_ z=RUM(%GPyrqPeSiRn(C45lMp6FT>ix+rSZ~2J-oB*#(CGeq$kyX3f>k4)l}fvRiHp zFzLS7v7=dPOvtdt??xVXM0BALbG?wzZ+4TCerRm6_6d7lj^yOzl5Tj4SBW9&3&iyJ zDLthHJYHF!yfbk_>hORs=m&0M?l8|CZ@Fx53Iq7m=X6MwJ?{eY43AG1p0HUD3sRrE zM`A!OALc)Nh-F`1k&~c86#=H}>wd{sg8-rljG2y#moee%$5uWPia## zSr+;8oEEk<^331Zx1Q5OcmXFjj?6Hh=Zb6|kM_1-hpoLRpNpxeZ(*KIyUyN(F7twZ zm!%T^qIXlIT!dK`ObrKuO3c&|g-P0YOASOMAA#$svSFz4pLLi3r8*OK>Jb;2NSlBf_b3`slPyfWJT;_K~G+lL>A&}ZE$!KVZDpYLp1y$7{Uw1 zsIRjB`pBP>el%o<8l0Lr=*+VQ+rFOv_n)$&P1nP&i_b2?!|uH9rNKwTv+Ck+9Lw4s z_)8)X`6}f1-;k{e4F2b2e9rkna!XEJMrG>@&qERmCWxj!)4u&&F~^W|e8=20b(h^w zv5(s){$D36Frc$@`#Z6JUBq$8DjDs?#_HHZup7V>;_Za)|Iyx;$K|-b`@TgBg_07{ zV2GE3c%2~pBZlT~OQlqMye@AX)} zv(Inu-#MSN&)$EY|CUv~!}HwFeP7piy6m|xK$`r;?4+g{(ulufiO#Z=V&C2h?Loxu z#x=nKl=uBk{|04+%F1x{2_0|K zqQ)RI@l|M%$J)G3uFUDmt+ENIjyxOE5yvPye@6A`boo%vw?s~pvWNp*l&~k_Wf_k! z3D3J8!mrTcNwsh3;l{ml)0T-H_9+q7; zgMcAoU6Y^3gr{f(IS~smLuX#&88>x)Psjbw$nEU$A#>MIlEM8;^|0KiT>EsE7nhLV zTy5syBDdZlzgIiUt5Kpv6NUT_yHIVw`!}~V4DDCm>!m`D0 zma9XD^iY16zSjx$HZ#5zKvy3c!L4KS!ral~S?9Y43~>m~+>DAQG@WTkE*u3UnFLfc z`H1QguhMp~!SX3&I7r-jZCOKTr`Vr57iTxBE^qCn3g${EdhKfL6Ay^U_u$wWdeB@eh3F-HTYCRalT>cOKJ8J% z?nvQz#9|L>Hp{I1J|4BjuGe3BkZr(vn`JjwNNC#>g?4pO0T+*IKFuh<`joIeIRg>` zI|jbT`zhyhDqmgHikUxk5`?ops60MohP((_T{0jm zKYVUz5O(ScS9pyyWBfRx0tda!!UNRa)N-tz&*qtZM|Erp<4*l*Z(&dSmxv!THP%r* zP{hi%R=gQm+LJlVY5iI;iB(|brE$wl*v+2Px$LF>-4UPh(fuc`v|;J@)Of`^VB=-+ z`-i%)3a$GQKB5!2vq?B8R*Tb3wxo{3(;bXWg5=(~${Z`=>;8E?%vutC;@4lleqFGz z@4iJB(dPq~g5XXT7>;DO+O#zkaDOD!$#`7Ytkg$gK`|Sj-B_88G@!$rW;|jJ&2L@H2XDBG-@{&^;>mP!jp~JrjCKmk++V&IZYH(@(#|E_$iy9 z6C`!LlU?pjc=xyiC64Nl%$8zvT+gcw<#`2sF@;~WM>|BnO;1rf_o?ou4I`(*Z=JZC zP}0_7P~f!yb)wpA-0pEYN)*Q)mT6hIH43ahYE=FzevUdhAl6T8grd1?v7+c3pM*iv z%rDE<>Zg|L7Bol>>IEg~n%V3Yy~!@We{*U2up2Vz|t{R$A0JdmL#Ku>o#A0U9fOq*k-VD%gedCjuru- zJw!V^oMb*J{J8kEso|D$-+Oeduz6otFgL+mW@=v^Td`8>etQK^E6HQJIox5g1AjC^ zR_$0TS#Izlzhi;Pv=>QNqo^3!-OQsUw5P$m>TYh zw6NOI^uf=0Q@)Mp{DI>-%eGax>qZzX3}=hjT$&#fOztJ)xIOx6rVhz-@K;8T!IOXq)mX zm+W}%Op05W7CMpOa4o3is%fc{F{n`%>T!)Q~8H83UBZmDy{`T{tT7V45qp* z{_Od7N+$^*>77D0OgZn*)Pg^u7S#OlKk4~2zYvyDIP6fC}|R5Eu% z=N$m(qXU~;wy!mPK@r(TOLM--ljGs6cuUw9Bwo(7nq?5k zlo}5`L3%GDaSi{#|?vc-;f zu*pfpT1{V0PuLBbtS*#~7xvD%C{umno$v5olW%`QvCdbl-1Hb>aEYkRvz*&1L;PIC zcI<9m8T1}Vwtn>GP#8XpOj#3=C;R$>QhDC@BrqV{C;p3$m>3It;w&v#AvTe&BAdW2 zGCkiqAS*rZM4jV0((EK0>l5s};!!=N(^p4#Dn3qlYI4I?U-4Pj!xadsAGbg_^#}W? z^J_w=00x{8Ke?lVX*JcVM5?2L7%(ALHu1?%^yIM~Ynuc~(f49q2uzh$p^N^%;*an^ z{hwmoCssnvmWVpU{-i_wQI!VTkeNy_tSzh7{sB%|H_uabbjK!7_RWUJxi)ZpgSE~) z$Fo8%rqIS60Ck&9wZ@t?Yx1MEg<6DdzQ=$6%n?1}wY4wKwnPJvg(CLQnDl_kn;vqH zX94?m*Xj9;?L6m$v)MkfY$2evgtT{=ECy|mWkHo`MP5ikgF)}!Ss?-jZitSF8q&d& zG+8J*#*%^@>7vSq^n1SU`HZZlbP&chWa{G74z-;iL7XXyn)HFU@I4O3*}o-l|i(3H59ZeWST4lP(yyS zj%qC#ZOS!pNN^()K5X#4S?QFA+yy}fCBoE_Xdp=SvJBnem@OP`O5w=SJtBp4swSiq zrbB~JmW=;pQ=63}bPHT;E=dEWm>?kOug3%vD5^uruBPhR!QmK1%J5jRFXt5m9-ozu zUbAI?gH*1zyYQ$Aj--00k%2egdx^QLMbVUin=?%!TgY!kMUYzikCI6IDiCO_ASSxcIsp@P90 zoB9sHl-0bB>hb$u%2if&xP*DM$8{f>GXAH=LqGid85rzOS#Z}{o=DvPo6L7^kYR~M z$opMxfe)p(4ZV5zJ9!i8jW_+S`d8Av+)D1GCUIuRQgmqed9I3UqM7k!!4WRr3WO4X~ZZli_o7^ik~;u97o7$n*2;;TLp4c*!}S* zOgUeH;yBp}#5CAmyWX1F?$~cxl)_zE-m!dg!JhHkle|PO7~W5A34!<@R;xel3%^<= zz?PA{%ki-hXWZ2aS05 z`)%dIKlw8~*_IOI?;aJ`lnr6XL6Xk)Vsg%O{~0AH<5QDw(YBJ?(9RnnS}I;8*s~h6Frh8%+sn2E!#8`M?h@K#+xi0X;pch7IG6&kbC z%xU`W-LKw;oM}gy-TmYGoUUbYeM4;%W;IDL>n*zBRg)ekwBcQ`M277lo?mwb_*S+~B!jA1py`QINT%}SEiJq~a z&s$4B5~LW1*K~tne1{#RRkgGZfJyFm`+gHZ#)DacDLD^i0%e^sTOj8bt&~y5;OXzf z9J3V>e$wqp;-T$VC03Yzw7bbIUA1K36|&#I+naNWmc5*Of3!8kx-aadL?CbPY>#hr zEY*BLMNn@(JE5p6NF>TZ$xt;?XwAYmxh>JZpa>RTu*^oET}|4(9{;BEfA;9e?RLLb zM|>2HZ!K)h{ngI{`KjaeFsq0NHMyqwQJa(Iono6ICbyw^NI77$27B4JctuUQ6}Q~B z%B}W(`g}>)$*T?p`3eV(hGEuuX1;=}eMf)T*!^Oe!`7|p-#2xq3#BRO_xj922@>5m z)h9>$MbS;( z^^##r5-X)q)TK8$cBnJSxNwkibe`*& zIj!V=qe#h-mj1XM5{}blRO?dWasLv*s zcV9i0=6zQ%)#qEUUxES8_vVP+OmFp+T`tX%?plUH-9i2{%iphrGND}Z@qM6d-Nk$K zb+@W(Tj=K^rRiJnpW`}@gnw-7>IMbH-=j4t{QovvCn_Pf+%%y2%{{Nkt5YAIFqV+a z!fcA9huAyqw`lDMkJ4(isEurB{E-vv%OB}8qopp_i9}vbr*pz3{H{Ohs5+~Di><4u zktn_Gcab>beF5imY@zqBKD0|2G zvC*X;Mg%{Lp@HuaiP#J~suGl=G8d;rJgdO^=BboeI&hnKEE zdP?>p4gZ)rfd5a_3F=N|b|6qsO_sa*7MfQRVr8#A+S{F#7eTvdhuXmyIi1LOtzU z(Jl3MiwmOgSZIiJGTSGuCmx_wdj%FHEXjPE68wRs#; zYIYsg3otdl{il{sqpw8zG-I~pnC35+66R@^NRDJAe|WPtWzB`A-6@4zUB3ma8_0u< zPzD*}a=pp}JI;n`6jU1TbJVJ~5$8O#a(?5zLr`2*^8?9OwF7%omb@A>G)_)?MTVO7 z^RLuYc_uryzxV9ntS^aM{Cgf`-}R{%NHR0(6D9o>;f_`VXA^e(64is~BYTzgas%Tt zdY9|lyWmIj}n znCks#hK`%3h!9i4iV@G%3E3RnTCz-eEBFyOLKv*fta)eW!8ba>xDi6~{3(?Lb@ zFf!vC8XCyjP<6*6Fz`TrrNB=f8N|>v~n6H+Tw0G5i6=A?fxim z@>--XAjDHYN;@~N^>b0OwClA;?2HMArRY{Xs-hr@t(J;~dBr0N+(SV!Bz`ZzObcR- zQXbplpU&CX@Q-C<>%~5w0U)%(MnGf=ZDrw)yby2KeP;KL$ceHJ%nLVBnyUSjPPOmM z3VamjItJHp2JF){Hhh=o9;Ijb6e|iiHYL?D8_qwCHVc0=RZ_7u)T4bVA`8@!L5DYA zEh%mVmvI(?kVuDN%J&h3CvNnDS<6ihKtP%S))FxhVvMvP*q`!%x(6{!c5F-$SMz2*pyoG#`ZN)YlB9V2q*G(IXno>i|9LQve;neM-ECMG zn2qXSJo@V_&^PX8EWrSJ7!Fzilvrn3Jdx~Y1+!Sb%r3YZ?N<*dj#`>t^~ID0T@Bsx z=dBe{NysC01!3a8;vcVY51oc9RA*c>mR89lUFMT8%?T83L%`xecG*JZ6O&;cliSnRBl{ zy?TnxV2!brhjfoa!-G%on8@W|cR+EJ@N9yE-Mqj9n?)it=45(9ByuOJQdgH6%Jk@v@V|va?3>ok6<;lJ{^E$tf)_p?|;| zG@SWg)lPN5TC!*)Qt90`r9wP~t`ytWl7qjXT;*=C$HrT(Qw*}#=T~1e^Q@`k%m!jm zM&`l_%SPBo&e%6J$H_u5CP)j=;IuUw>4Y-&Qh=%q%%1f5QW@v1UmNK~u*}gBT zv#5HqDq=GBg6CKjcse{BNB)Zjyf#MbU92&!CD{wLWdtm{IZw7g%Vk#>v+c&YH50g= zKXa0o?=SqhDsk`Hq1pH_KGxu}lFf1D!}P4&7{3yO#bkbcVpEaV>e4oVL0D(;^!!zG z5?(x)(QhqP9pzJ>b-Nt#zWn)8O@z<*_r0V2Upj`uyI@Q$sW(3NKQs1NF@AXX)HaX6 ztF>?MGbqvzP>vPn;Zbhez1!)Tag#V}mzxpPPLaUfcFBn!DYdZRO(R<2U&ua4A=Zq3 z&4r7ToCjLslSds85;JU&&-J<$iW5!JB6$b10Q=-fe}yIS<3`(PkBZFw1tUar@$$@Z z8O)yshB_g4wcDk`#VBs~;{oRc&BynT&*oh6UVN>uwT0Kyh(qB41suH(iXGhdko$QZ zK02P$EgP2Y)z2-((dz(DLaGsVgM+u915g%tN7@vDx5t#V56d@_1CHM{`hyl94Uk#q z)Vw|Au!>aJTH9yLa3$k{{Bs%?HI>>U^FH4Zdqt^f)nk299AgSx#Qn^qQ!Mj5#H(r# zak%EL`%2r*dPvX%2Hyuw{X0mQd#dqFI`TTC;*w;c(>g$BZgyrp6u0$c3GFC8 zUj8ZL^-d=lR>s*Od-=Ma^k?M`T#s+Wg+fgH-u8)(XxoG{!$v$d7>RoyCMS!$fj20`BcFQen$2|Rb`JqJ->^TvpN-hNE|cxn&c97SH*h%eotBZphwQi`rgBRt=s;s( zyu?12I>C6!yIPz|oE%Oi>dQLgC4kBbpIDfh-(R`SK3z`0W!ki_uovb`xgr*7RFeFQ zxW9Oa(bW$r2^cB)q}?6T{FZa)t2#ah%@FXpR@SQ2ex$;W&+C+4c=eY;nmkzX~di0WuTt5Tepw%i(TGmHLt@wL1| z+n1H_iJ0q3UZiF&eEV+Jo}Lp}=levAH&nZ|6WY$T{z94!3}>_I5HQ~R0yywdiqOD$ zrJ7I|je|qs%$Vs=&RQhUh`<*4I1# z&g1`~3=J-Rrp{@)EFhn3W(Ng`Smb(1HZgWve*%u<M1Gw<(S173yHXQ?0$-l6`w%DhAFE$EXe)}HKYC=+y^wqa65@Kf1w>Nqp=bv=CB%hbQVWj;q5|>7km1aGQ@+w3D!Y z`&}D9iJcG%M^4977VE7poIbXHoDqNxW(}IkJ3PT~MGEC$rR(d#iQGe~Da5leUApYt z7q;=zgA|*EPkxJi9yL6!&EJ>m?}C}>(*LHwj-WkpCAT7|yZl)!NXT(D%gJRoVbXM( z%Y};f%qgmw?_d?0Aw;ll7!i6*OKA(#iZpCCkmFK@E$$POv2_4|d@`~K0#T~64mK@< zrk5Pk5KWh3=tvT-mWBK&S%%x32vFoY%yV{+Z{R6?2N3I5lw+v9C(fZOD0a2j1K>=y z`2OaXVGbaJ(#Qk!*L2xox+me6zZGGW@KI#84w-)Vtx)_`$Mp%*HxzkeCSAh5-1OR? zM7Gnq(ff&FD`_dc71soZe<Fm$v1ANI zD`HRVg_QfpD|8De{*NJe&wLAq-YvaWeWKHM_2Ro9M47f=3_wS<)L?qeK z!+~Hv=Hjk9_LmwL2#NWMQG^a303OZ7M)E7Q@vI{RvA_>eOOr~d8N+ts;mHbKOiy0v znnR@`Gz5^a12T-hg_N#>K6e-s%R_7s{48)tS zkJ}Bixh*^h_&{=jbYmAtZaf}M(YrKSjRccafYeS1U&M6L$ykwxsR~C)Z%P{nJ|6uk zBeU-72Z~vPt%!=_2L!(ogwe(KcP7PtY8dX~g3}~H6_A${fsHIge$uhC5)IFqjn?DjvH7fP{U*+|8sE=>$tUh(8o({xFzWSDMp>-6WNAn0?(?Y19Hi zRlRlVvg)QACAM`r6$-f@MQN+8Uw5i?o8aL-1W&2)MZ=qiB?ZZ(Dd~Buhc9FKS@>jF zZMylW|_VP5Rrr+~bkA_kgiQ=%0&ZM;&{+3j0M{D>rDanzg zDG(v$&wxDslABeS3V|hJbkBOg7nZ`e4e#V5yjG%e7mi43y zRPnM7UV1ehu5Y|x@Z`-Z$Xvi)p?8p|WF?jW)205)t?vKLgMpjy|NrnGquiI1rwW^& zz-4eza8_NvbEh*i*lxrNuJ=D{%WBF00PE&p7VC$WVRPRE6<6HH9}90H@?rj<1z~s1 ze4=ak=h*-4sq}w&#c%Eer^I)wO%cdy?XudCHZk_R|9Jj}2P1U!4P?}Zz@BBmRA;h# z_f<2RGC)H)@envBM=xGd|76o3vEi6QrFl3&QQwmlo|(KfNo_ABL4*ghnISXlpqb1z2lj>Y{w~IUz8dgG zZt)v5&0T|WH}Y``bgQz;m?tUb0IEv@duq`?b!8FgO2Wedi0}lypk%8dC`qCU+JLr8 z6=~#M#9!yyu@2J?c53%3xEp9}K%EE4RN#Pp*1kjd1SnEd%tzYyZabBPA;vE@o=T^~ zNo}c~*9e-%zp8H|IUZZ0Q^%Eg2tuHFV71uNyEl(1a6b=D3zqx#m{dHZeMqwF(IS^h zwgBrL?R{(k)Z@3aXYC!|`2N=WA+H zXbvS1RUgNZ>V}OQ!zKW|{sF_V70?{#4#^dZPZlr2Hs`e*-IC2l0-ZT3owzxa*UcRO zr1A#zc2~92Elj1z&hkne!sKf=GgcEHa}kcg?OltA-Hz%TP?h7@iG6W%?Gw9}=&>tD z8}&5ck*V%xRx}_ItGB$CUqqO>>HNOUD&08?ZFVp6?ZOuS zjs}te7>TF3%l5Xefe(}WLLkxReyEb~x$&BYEhK{(&sIQCaT=(BH67on@+R(f@9%5T zHI-2&sq(4eD`I6Ik*;@2Gz-y!mFyC8Bh4O?`OomxFyvd+3p1uN+-CUcX88I z@0{@g<@8`jc|R)fx70XSD{XvDttcG#LIhq0FA!)Y5eu;SE`&s<&)m5IlkCQd4F*Ew zOkpm3XQ@$1@bAjke~H=s rCp1I<5+D8VVvqjomd0nD<9vrUACO)0OuiXkou#X_Q!{z>-UTf_uSnGi*CD~;%0s;ccyJ||02nfz& zz?UC{82seu#ttL+=bY0cRRx0l9_BUh;)2DU`*#QkiXzBQOo+g1QhPN$CjtVhX8hN= zcDt+>1O&J*ca`oufg5ckk<>gmU~8{O&maQdXZ7`6*H`EEzQ6gtOufHvM)}K~=$Pvt z9&(DStMi2rheXz5STVSo`kqSJd_)1FG8QX?+1qkDvZ-X_|MP5w-(8ZnE!c$>;K;y(Oet~sBMj3Yndr!Hj`yU-obFQ)(|?E zwJ)&~MeVFsZo5mQDkb#ZxYP35y&mbZ*TdhQD>18uFbLa%U;lpX>9-49oFi_F?=FYI&u@wXWUS4B_DIiY;w%o=#Qsliwt}O(EI~-3_4xO@^ z&D3No=drlq!xn{q}vq<7T=SWbw5W=6UTV#3><3PONwLX&Pf|+(T$kYGs`>?3~ z=wz=qPc?$o<@8|m-c%?B7cB;SD$MBR8?P@owVV;Fb_TI|t-_+gZXzw0R2VL)WIjle z8A^Z_!MIe$mVbWollr^OVl=^sD3d2yT8%S^ZCU=O-#!>b2T?Nd`1}nD>^blYsn@N? z`rI*Fn{J!_M%0(Yln9OgjV7^6;O%*4?~|R8ayw&wm>_J8?fy!u?yh_4oik%5J=vn^9JTU3aqF z&Q4<1qeRf4tQ)Pk=My)Nhv77C(G#UMlQ)%{Aw>+R+IejB6y}=y`<-XV zG5_sD@NuF~jZ`(=1L-*tQNLPbIWTOV`%%*_lQu3tZ;X!h%Hyo>#R}a&I44gr2*MoW zIZa4JHYUAYvncP5nsVyZJ3BcNR1IgAGjyGHE_3|VX;}8-rclKkVOKP-=7QsNwJV0L z&C&=yPsFcV__83SArG&cl z2X^_B-A11x_4iM!5$`<#c~-(5634*(h>z%q+s$MBd{NbzP4Y+=VLw9AN9d&v#tfE?FG< z{Y-M5c{S^W&HEWA+8ofd`>V^)f7W%@^Q<$1tBEN>%+zyp;=3Gr)Yx0EH(54Mr@$zf zuwFAo4t=;7QN0pxgWDg}Jligxaqn{a5ekkzi1yvZ)5QpR7pa%%2+XlR%>(=M3N9Hh ze!NGYVrC7JZaHs^7}$N+ls~<0aQPPcg2WPUGQ3GWRw&8R()8BRQuJo5vDf(KOIZZk zTEaF!CDZ=aT1NELVaBIwr0QW_o36S}_-e1`K=!M_uV`=`o-@`xrZ)@0yjx{c+_BFV z>L)p_3Nk!kw5nVoz#v&=-79v)D$U~`$e+HMeW|}?uJA%a1YLiMo=onHox%hKZy!f% z%B^7ZmYebe3srNSzE-qWzIP z?qpD?dZXB|EPhJq%I{`s`NZE|Af&lE9xWuZVKn8ATEgXyEvbLyKh23r@;*Dd>2(4( zsQ2(o+7%rn=1=X5TQ8_DGieU2 zWb6ca&n`#(<29ElhxW?1#^tt2xQfC0qy@LkM8^gon1cGVs?e;< z;xEGty^em>{j?w7P)k(^IJv{5NH!XdF(AarA5JlQ9nPPj-f~<^C^Bn5cJ&LQ;M9DM znrl3B%g{9$P=n-)r`)G_;t?3o(Zk*_>#=vA;rtZCd*2;&2!Fo)q6l%B?44@Om`qDc z{TQ|zuRq|Hvu|WUu?$;Zz~(xhXYEDw3+NTMB;B+~a*n|f`@>TDH9p<^nIg;}^lY_j z&v5zZ5rm_dQ%`-W_mf0#fXvJ`r*g<4V^e@VqG=Dav}4)#*@wZlE8c14l_yA`+TWgJ zD^XiQ%yi!tEpRp*HMYYWA`pBvur0<5l05#fkEme2&%22HXO$k8J`Wp|KBvYl!<+dC zD9+1haF$9IteOS$3f1mE(hPU zhMiMTf~0U5xe?5lVCVd(tKuxAjE+2}9lHe2<{FDNl)glsX_Z<&WT5GOjI2iLR9MV8 zQ_JJ}X<(1xb30o*C^@HP4V+NGnvsS~&7xk4j9W32`%xZsqn1X(C@4)du`4q^qH!cA zsft0z82+Ww!3R!eLYNqPH?Kux&CzE0>{M0_NPf>>aVR~4Z*eV%ot*j8%-*Y+l^Og( zmn>ePS%=-KK9jBe{VnIjh{;xbf0>4|FV8>%x24j2tmIhypgE9ovs=7(AF(}@{dijR z&K1rFA@+z9s`($nkH3b=?)NF$Qan%8Nuy$9P(XHHxfhI3nA*`03m~jDs&#j1rj$5r z?oVzZHBIbWvMelH2(Un;Rw%JQ{4P785IRN?;3_$d*siU1Q^Z_QImdd%O>OCAgDB1W z-uqu{r>h*+zw>_cNj%=y7<&5IkW~fBnqN}gu#!s9D{JZ-6xQ~R$)L{T$b+>YPQh08OK$ZK_UXQyul&d4L3Ne4Elek;X=3$ZIX!J#Rmor`OeyW_ zPgmW(cq?MZqsgE2tmd#DciPL#OsmwkGY#%PS0%=6Vuj>Gq1i6|4?}9Ao2E%Yf)~hQ z2KL?AcG|j=q(?`|1#{;2L5{ft@Pr1{3(#Ngw#r;Y_wGfV=F z5bSD}FWgU`P&|W&Ti89g&&$G!czC&g&y*ED7Qk4@4xK;%`{RAc&=i!$uib z{h{&Xy~aocvmoQBeyQa==4ZxGzTspFU2x|TBE&+@e-@JF3IA%wlwq_hpn3(mr~ru? z?hsRt?z^jW*HIzS4fyt zz7pwCWC!I?AcM@n$SvPJNgKgm57}$BX2m4?wn-*ICV7*H?c_H- znspQoqTP=Ipq%`X+%2+AfrSXi;ppXd#ntK7<~sO}DZ|MtpTd`39@#H13l5O>DjY`o z(FNY5F}kG9M8etvX(bDQNf7Ps7mcW_oN;xe#gfm@3w5`@V1w_KlvwD$ph89q*Bv&o z88wk%IZ_`66TX+pfJ99hn2RsP>NEUiPD`Xv05(* zS;Cs&SiTSHzekhjX8ONd=`aXg%i>j9_KW0gPkIwqdv1~C0XM}K{B&n#&(4b%nQzA0 z`xfld$Bv5&$uee5J3F>Y3^}31{6efz`~J((40l7T@ioyqLzL{f8hrEn=t*igGk%}(QWDeuDsd( z3P`BTwh2;}SfEAOJx%2>G0?{4Fp*a?8Ed3IY-gfGrmWG zyn(9(tOJlw8-1yM2Creqx|XDkN*j;i+!V8!x8zNdpBO!GFCisgFJd-2+4uJi-XK{x zi8Bk|>4hC|BVXLjkK-cr>17i{8M*zUi;%qY>1fC$yP62p3Ql!~~+^51lAbYyK6X#ED?!QR$m2Qii<80ub@KH1UUUq^; z95*qM5`9{hUdc{EV)I=*#0PlbCOBzCui~P;qL)s_3T?~)^}tRKs9mmH`sSgv5;ZD zKIGZdF`99grr!7>cc&d;Z_v=noDs8};x2`nAT{UhwUhK@(Dmdh#X!0uRH094-O_B- zU#pOFD8RKo`$|Od$Y`;nt`4hPCn3?A;ArEArCSOF6ks0lKb# zqW7`xlL)nMM>&%NFCvS^RfnDeONO0Oy8WOZBa;U@^9u0#^4mc#KneEXUTffo~%^hTj! znz)0yL%q3lzw9oMmOwgwa4p%wVn_`?yaeGHADTvFxA9ak@zMDPrRb#6& zyAmTt7Q6i+pHHIoy^W)V{r4o0N$a&rK^?h<+ls4{){$ggvJvWhls4x%pK zoGiyyJ$d-`u+P~0)ZBH(&0?XdlsBF8+Fo{AH{);sribwx5_rccULFR&01%>AU#)9naKg}?R|9deo z3J3pD8JJ}BZSgpczA#K05nGM zoDY^FGJPy>zxD5Pt7dR*7{liST154~qB`ZWuiZCZ0&SsSzg7cUl+T~gyDjXJORp?u zOt5@vq4k(CUB_v%%*IvR>t9a6zr*VVsY68E=~A@j2B2Tc@o29nQOfYjpwRlHUA?o( zgRSFsHt!ADYCRt7b)QVxjRTetg#Ru8;kLX5=H!8PZszO#Ps_3on(OwgEdVoA zcWQ4KcEKXq?dvcAIiq=cC11(i(D=gZZXhIc%t(c#ijzgSm=4``j~6o!VWPIA(f$7V zsr>duZuK$oUYSMW;JeX0l`y}$73EO+gVpmCtoA)pD`S)rQ;~7R?EeNMC-yye%js05 zQ!N1tVQl0cRAv`~8`PAae%X__#<5SybaU#9G4DbdzWeif!-wFDNjC|bnaFl%fvLjz zJO`ZDn!^jj=H8R!|K%V#Li+XS>7J8XcLGfSu zLjk#QFNU;hmSL4Q{dWhD(+*O>)f+(R6kTS-WA`*WmO^T#Q$))$~&MT7F!=L$vg#Ud@CR`(x}{aS_a4bFv335 zT`u+atS81WjqxkXbdB3yu6b8XjI^sQn{=Pn2Gt!_Lz1_mWH{xB{`8a>#D4Ayv!tC8 z_LE)RTI*hqN#^l3i3)wUoW`2XR z-11Y!?m=Ag*_kS)uK4PWqc^Pgr#vOdz($fCVDz8(ak#SepU`Af{qHx5lPWS}Ay`V+VMIqueoJE@FvV2^Y z`~3*dze!v#*7{P6=H!jzRW2jp%B73=vc>{vF}-h^UMhP4Jx${InN3Kv88}Za)6S#g z#pYc#=FAT%#9ww78hahJZq@8PFsQIk-3-bP{`)b|z5=N)cd}+3+F8&oG@4@|pw~=x z_Lr1AF>rdkULf>@v>o3% zW3)3@epPooPyMUjGCVQX1b^;k97i zWJ~$e{l_63I2s;}LX~%ykJdq(YNs4Rdv|K4!RNe9SBzledjxT#*SLA?QRNH(9opc? z&?2h6v76;LUALZD4Ss!R%!_tKHIhu)lus|4dXMDlsXzW(G6d9P9G^z8NRP~bqs1g@ z>QDZI&HJPuPdTm+=Zp#|9GA~}l`t54^w%B#=C=Y|ITIliJ^IY)o#)Z7*g65<%gqgd zkbeP6+jo2th!HY;4fsAMhX}^{`9LN#V+@=7!8kgQlF6fbgFHgM{YTx{2&g!g>!Ss( zK4DP=eytBxS+t6*~<9zQ7h_B5v|=ol1|GLR~I6Ry8n zFl7UoK&E=9jcMA7&4yWxAL-(_ztiFLELEfqbn~YbsEh)m+6f}rWVBg??9Kkc@N(um za&XjhK++~e7{2LOwk>SvgR+{b4}E*uMM;yolL}}#+mqXeyskpb>$R8}s{k^(V$etT zCAW)+ye^DMqq)TE0ow%7Waj=@vA4p}PRJs+ zuugtr(6q3ADc>~qE>(+%x)FLQPTspNsE5W#^RgnS(5EMu01*7+$!^P+q)+z;qic!( zo{?f=J)=C1v}pGv*amIOJ#zR@%+n7uZwBut=kz%E)0iCj&!1m7OGa$%Kz!`IAq%S> z*zT{OjM+js63*G-tO{zEv(F*AR#Loeeiy~PCxC9c7@It0|t!$Do2n!A0u8HhAXzKL&q z_f=@L-k>I|3J!ez7;j$L_$wS(MgMB`bPw(4<`&>7uZK8o!j3$T_jeXt{L$O@dvG(3 zjYJG^7Q&DnSQ?uO4F#hJ`|xY*(&pewG8Lg>5Y<5f(bcD;|H4d2lye6R))UVvaRzuE zM1Z?{E|*udFZ3(p3@Dg(+x56Q7EtJeQ}^)z@!A$V3YJj%Iz8kBkT;QW(c#E1stCtL z0pkKA*=pPw)^KT0ol%xEX7k|@tLRx9lilGlyf(Y9cb4{h^ZA~gC`6CDNeDq#?LdIetLD2)Jme+7xj;1Dy=?mw|h*2 zSe73O4LPZi)}?!pG;M$AnCN4aWcE+dCI-NNTSssRIQNY2iysoNFM@dyB`VMC>fiqGizwY#0hG-VH-F!cGy z7U-4m=)tJ_^H9)%lStUta13)Zf$R)yehr3UB;vak#Qq{o%Nc#wrw(AV!SV<=4lMEM zM-SI%>!dgM4_jE4Ws1a)qfi0>{{XM`?(eRd9s3>u2)01mG9mgaJ$fUlj8E$*af3#91 z2uyP*S8vdYp%rnTl0yl7<=)a%=ti*PR%^0WkEh4`k4{@9G@b2q@ygmgmAwyErG=Ex ziphw-WuLPxs^aef z-(F(hSO+|3?r4c- zeX_g&FQmB42QUz)D?ngud;)(}RDb0E!b=wQA&6bSAGrRE;NZg1r#ae0DO6F~;edO~ z(J4rN^vu8G0>F3HpqJPmV&G6ZX>?7*TDoLqbAZliBQ_DcU59-j+pHXtXx~J7@!P*S zx`=v%;eQl;WVfQ!|JM4I!bHtGX+PbxNx*<6{Dr{17=a=@B#IFqM(RtE@P8gNaqkoVm8^nnbBSHc^SP|oBz=^oEgrQnO; zg+dGU>j2)rkhw*2_y3Bve{cIw7{bg1bPF4>d$yBhg5Yz!palouJHT8M#|P_vFb*Y| zqL)7}e*(qMdlb+wGm#YxoNbnXDv$+TZW*Yzf9{Tg<<`(d>8r(4fNXc#b&NgDU8fv^ zDB0v>{vU45Z>9!7wW36+g9AFw^s8E*-(nhjVug+WEYt2v?>6S4Q3=@)0sB*SpaKU! zu5~}ib={sR1JwQV?6DP4Im%SoJcmF9l^VVQyTJ}FuJ`pXf)@S(#jHggw{a?I1qIqK10a7~ zjFrOoBtWX%-KpNH>SA?Uf>nc%+yo0%1QyM!yzm6{o#VJOOnu7%({;-^7RtAq-g`eK z(0Dqus0;x2SdPxr$C(exY^QG-KY;A8{fTV=GRuJPAWrPHe+L{iR9n>bHDpnj*jMu_ z7Ran7%kmI6ThE9ZJ3RMqd$+^-0r)Oqk#^C|e)Pq+{{v~jKFEwFc-}^y1jKGrkIbG1 z^*RnvUVhv^mG|p$XI7_JO!+$|iK%-$`O2Qz50U}-I^jz+auj>Y2+)6Q!!oiHN_X;_KP${18aNl1w0lpL$j@dd- z1YUF809Pyr$%zOtOWJe>Qj&ui5q3^;s}^IlKA5SQ)Mnol)@Z-ebhPr`Tp5W4yCpxKU>hET8|Z)G^%+hBnwk-!pGrp40_QZ1C8Oa+X9Il zujzvgCP;giaQ&3>uFnOI>K8vQVw4`YIBDh@R*!&>Y(~QJCNjzEcx~%PrpO$=Q}}W( z*2T_k)ma{(@9C}w*9ij7Q%fyDCD@@0Y)xVe04@u46|%(Kv5Xee0woFej_*lUoH0b@=%zA5BiiuQ%kaos60Z9UN)Cuw&WdZ=0nn+It~ zZGVdmu~Fm#`tD=Vi~Vm`>OkVMWeyI%4psOkrpH5oyQFFq{>Mku5i%FQ0SY5N3EZ?A z$$kFhg$}*2k+suG&v(G1RY9rlFmvsT($4)10>^7h^zz$$>8qFM#^{?aDJqnzSyY4i zc3>7SVV4|=xD}=)B3zrR|GiW3L~42U;7DSnL$0Y15l*M*2Q}^e_v!?!X|uqEL+$E$ zveUkaC*XimPvrDCD9GBMXTHII;4AS=g@{BnZ5j0F>CX$qfXY7(iVpIi1as^OL zkIu^%QtJCTZ%z#F`H>!&OF1G)8QSgzkBUA^vE)(k^+7EG%gLakE9nvUY@B(IEaus) z@ZP5zR?B8!CCl*2P;Df~l5li8v+XC8sbkd6bwY(tr?sHBK?CpB)_a@>Kty%!wSM0#K0>z7KnN3bv zZoRQDV)3f88vbSuOc@k09n6vp=pPtCTEN+t{$n_ML4#_U|E_w4W+tJZy%TmJh}AtS z)P{l#q_|p!X3k$eBrX?jN>%yK7E>$)x`7JyMHVnw)fvnj{y*OF_$N3hM8c{8(v8Pc zrgcJ6^+=~(JH>NUC-=w1@+u^SYJ3=PjN$kTY8Kj6vaqGE20bVi&o?EXnD55Ho>`}u ztAd*4iACR^k~?Y#S=e#sew;)X$nsOot9mh!R%iFQ_b-XR9K&;8^UcqK?)VXpYhZgqJ64J!fxcJQsM5eWJOuD4JYjOZbW*ReIxx ztB*H;E>=YIK(ev--LnM%wXiqtQpT9Y!)ef@(q)rh}J%d znGjT9ZoG-J_Sjfz7s{vchiqQ*l5rR482>Sd~1{$Atu}LIe>~@mw1`Ui|U+LW% z%3!Q;T-qHic677>gXWb~6nvO8g*w(G(P_@fC-(XUAeD-9^J%nwzkLDb%cAg5BwSE? ztjx4XaP27Zba3mL!SN6NGUxH0{h<9~vqg6UsY5O-rpU_XmrkuU_V`9j!6V8pog$UO zmNO21&-SCl0V$t1wAUt7N40N{(I_{qL=w6~u(zClSD?&UeOb-uTQ`vkjghSwKCatO z%${?$r(9=5(`ondijkb>>q1GjJy#tf>q4D=Nsv=MY%)b?{AhHI-lm&{rCF<8ZLq?D zRDI|ggnk=O$HJ~8!xeyM6p-hsd|7&reJ=R;#?nSyTZkZ~Ucgh|L~X@f2K1*^OkQku z>%0-)TeoFc;**O7_g)e^4Yr{VtZa@Lw#OD+Q_6liSsdyn7k|uqJ{>KfdGvwu%J{jo zTQgo*8wtYsA5`+L$W?ronCx}@DkZ2R^8wL;0P=I=y@)y0)yFAmKvQX?$FQJ>OJ6<4 z^Hr+k#ljRM8BO*SN;iurSR{}xzh`Qzg%$lNU-6aZDpr`)G_b4Gl3$PythPiFnzAvT zh|oX3kS;H8=#y2#;jbqDkD;{#Jtvj1$xPG?3E-KEV>ToE_>hZWQPG9hWK!Ee{P>>1 z&M?VVzb5(8P{EPy=RD>q{^Fh<``tt$a)YABXBNs#H_8)_T;An(gtPnJEf4LnQAKeU zrr*(`dD>KCFV*78x3LpQLwY+Xz_Lj5HF*F_@2zzKgf+M$*>=)mVY=Zyn5gG5wZ z-`N{4wnxlzn_s;y8QF7DNbv(z6RVmbhbb?!#pF=!=UC6xkE(OgG0=R?pCMXfC8v)y zWrtZo%`$9}>lbE}2cEJCicoDRr_mpXTCr8Ne$v))J`>7mmYT&R8%rurhh>miT%u;< z>oEKJmhFH5N^7DfpT-tp=5jE#a!tR}k&geqOf|07v-y^R^qCcAX%daQ#ePM#DV(Kj zD^|43v=1B1ie+}&)hpt`mAqe3_SefELZn&{pB^8SSmjr?Dd+qL|I>zZu7u0n002QD zUt(6YsYLmhT`A7qrOEzPI$c>^GxRR25Y1?eg2PFma(S5IZ5+_!gO4_82c)4|%n{EP zSDB9h5}NGgt<_?Bd(6j3i6n$@SW8vC)z#+JT-(+DtbK}v&gz{&Z}uj*iss@wEGd^De2hXFtcbJIb9{7GM?2;&}Ur7ZNh?(HEQ0AMo- z6qfH)qr|`MXO=@)SA2{7Y$6%n75S~BfLYc}*Eu&*-1`o{$HrA{6ms!mEryg-+WORP z(Rw>Y*(%4w~*~WS>b6<^xC6ErD-vI{DvW_+1hVYVSfB9l+%EbNT}}6)T%!%AgC%D zhXwY>N|I0JV-lVv2H#(sOHA1-h75lfX9|fa^1kNscqwer9gwrNuO+fCFA+XIAvYu1 zJVak$IcHfNSj5>)S$DMj=~U*bM%&pV)1{86k*tSY^2Cns5&Nt2&IIsnq|j%1?>7c@ z-8{y_3CV0J+n@Ctk>ev@$T=5kXM0d5$gzmFy^VH?;$dS<(WaG-Te#2N~hr1@q?NZVjH6R=V_rfoH(}8f95-Z5OT5LXV?~Zs%&haP+Wv|c<@a69X z4M-8qwV47&RJhjn$hFQu{e}1vIuvll-jL3>@G1*gpChzi2yx?i+C!2VA;7jPS zY1ORn=zKN~wqHu*;iY~Qiv{N+#k>)v>lx-SWu?-dU$Msda#&8DzZ?PL#rm#t*~Xxb zP3!06GPCAeY>IO$R}FrUDYba!r*T^kcFS8YhRq6aKt?T?cZ`<~zs7J`5EF+5HqsP3 zgi;W$+y&^`X87CF86&L)qZUrGu79`(gnyd*lS<){)n}NF^G6s1`rhxuvtB0rbsoJp zPeeH$jy=9z&=NVKR54U8HE7?(UHvUseyz7fbxU8A`^Cj z)A+)@4YF5~;7_yItbp-57l6pR2XE{UWRC}M$saC;?*MMH93aOlJ=K68rolK*yvlT& zl>Pn01N22RXj@?Dt+R$)RRRr7Dd5y*dqYpB;EV5qCqI+Oe-~1S!_z^>I}fMCpM|rY zY@|4)(>=$t!!ke&W!_HaP|D@_muDEb@N}!|S^rE(lFOa62F>7St@jLOI&TPA%$qi< z5npuQ=&!9;{+b;XY#Sgtv1$rLnVFF21hO}A?1e4>f(zZ22fPXB#FERm(;p~Hra&EU ziFp8MocubH9y)~gVJx_0O}~xw1U`7fIkPK_VlR+_hE+r5yeXZx8m7Y~DMmcY8h_Gcn$jOa{$>n;|s6S((9bsa;W2oq{O$ zo&+Tsf^dFs!_R84&_odnT*sSuf9>^9z!+9J__{L;(FW5W0xx@soaZrImb{0&Q4{A; zbHJ#cWp#(`3^cD3Kwz{6wq(=7uh1gDKP*^4W<{{WA|2pZ_RBL@$KyoJd|@0dLP{5& z)?K@i*ZpNP*K(0Qo9qN+VcnjZBk>t4>Wr>Yq{ac~v341|_TH@+k8-tDzW*JtO;UV!zzM(Y3PIo4~nq*2iMRz+*a?J5Lh%1@iqY{#H z?>-AYO!EhVa<}sJdIV7VTw(Wjy6itO67n_Nb?64sbfo);4~>kP!#hA1qK0#HFq;=A zSj)U#Oft(WUmL&K?$@w98~e;L*zS{=8B=bAgWr0i!$7#$M!pYRwZ#lNcL+NcP%Y{N zHgGH)tk87D+ZFliWY6JqHNg}F;qfD}&#?BFI80fB5geuzw(oWOn^^}GkYRp7Dy+0u zzw!F3`5+s5jcdz3R-@~l$R19{2$kL!_bRu^i6!BRzdh5TMDC?@78RAP_ClXA{;Sg0 zS5dFbUxZv+?sZL!@drd1l}a%&^07>Rsd~#>w!noT5w^Gp3#qk}(ziN^rVbDcXr_tN zmx+`vH8=N^5cwvGcqt4W$!d@zU0U1*WDdaEzzsAS-r5h`<*g(LLSb$i*LesPD~=IQ zlBZt~akTe<&-hrd_xu7w38+PLCPv!#w&&B&jb5eQQX(j{tAayd1^+T7$bBD@`roNr zjlzxtr!GrBQ&t{P&Bz;jQR| zc3|F(_%YVeN63x9Z@f;C=R}zrRlMw^JNtf@H_B=9b-xkyk$X z$a$jFxh40Z7Gzi7*<4^c<-{iX1^3!C&;f|`BlHKG2METweqt> z)^W*)8S8a=?3OHDxlFsmB^IpU#Yi$hc!YNix~BegXCzKDkxTZHSuCG&3}xeGbq<4` ze0?Mnv4`C#>6I})1C{c?98$7!q9&fvVK}fE`25A^&#Y31Krh5t1xlQiP1^1~380oc zY^Xh2>JEB%?k>lPcf;FrwpZ|@I8zACePXkWYxWw96mlmhMF|bSbR(Yv1`{dz^+D2W zq7nK+^+|rc>3Gky0c=p_jBdGj0ahxVL83E#o38c-c+^nQT!u z%Atr0XrN2rM~#Fw41jG{`3N4~@K!IKSeYD6v5;Wu_9Vh$lJfF($nwSohuL&hYMg|# z4|FY8vA+gTVl$&0l6D>*K+~(Vgj=UAi(}oNZI5#k+P#;UmE8P zYN_oI`WwWxrh6ye);|zQ*2ANozOa%h?oM4$Fl{EkeJS%i2zh>e)y?~9P?GGnlX)>o zO7Zm^PMRBIsEO#8hCE{Pxk8NbR3djSBzS2byogc5oMe95OKy}`g62}0CPUiIMgM>H?5?Fzt(PK_Gh-DEc42S1{y_vU{5u&8G| z|A;IpQ`ZO(k~UzZh!yrWOXd2Y=anzcZ;?dbPR-aM5kY%l^yu3}9*)1SmbQzk1kEnC z*01MR%P^!M`O6w_kOz3`ldlF~KOeA<#&n$LFr{?+$I8)SROB*cZ*byeF)3;D9%r~Q zv{xJARp<9w+27gMCh;ss@Mu-p0K3?S{5(7UD*$>b7CXE45&i08d9QVZ27K*meh>eh zb6+@VjNHvfU)=if3lR2H6o9senL&@yK;48J6@o_Q2)MX5@Z%K1AHnHC)!7+T4wV%s zKK%5nBYM=4LD*c1oG9d$Diy!|*hB5qO>ynwR_B~pSUxd&{?m}7|b@So-3RF zfK8Z&6W3rtRIt#iF)FotnS!iqlRqGc-Lh9V+FcESra}3q_Izu7ucJDXfN!D}#N5&m zgNpjd4dTtsGC^bO$_P_JG=qCmujEl@` ztH;aeq_OdtoEUts2*+!VS^a9ly=P*(7pru=~hS(jqmu{d9n|_8`BV^8$`up@rZ{ z-WPAdVbkVo#UQu&_-f&qd7W@=pg=sb*vri>b2))bR=udhB~`z1<9D38r2YA&VONy6 zo5U^It-YsGExX#^OeSNxOY%ZjlxfeXCdIsCY!Z&De+e12$zreO)fdnT>JRZ3?a5}| zs_MAh=M{eK;7QiX=|iSlpx}VuLyE3ChgM|r=7Sw-v~>BMommCD4~Y_^9ptj}!oGe# z>-wHcb*bq6D@~;fUh`%Nx&a0$#cA(88H7(sQw}rX60FIMy*soiJZ4?2pKY66qC6d9 zy777`ZxYN{;kBMWO3@l;(WA2o+_!120jK4kD>Fx>k+?p0?fjpL+9zT6JY>hJR*ff7 z?V4rIb|D+297;F;nwl~~S(rxLK4LAY5#b(00v0|^QJGz(K|_Okb& zGY=xP-7gK`GY*h(Tn=7fTyz8UEM*7lu0|Lz zm^SXzD{CQKgYunrU(c%+Xm-i3T)xaE4F&*f8BXycCcsv#g!q}lNxa7m<|E*=9B(lJ zP^E_va2a@P0K--(V7J;aM5Uy%+ckS0tTb0O0JFKf*@PE8+nYpzW+3EH38a--yh*W( zpdF2$ZCQbdw(hQvYzlPq`Hvy~lsde?P>aBn4d-A|CBR|TgU@YDe9t)r{y)4tC*@*2 zGdH~DYCTRHw$Yu*yChe;bXBLd^O;-h$EsC&{x?s!_&vI>##AfCKeuh$1RN5KO78Z3dcaGS(d!~>1Z;W{g~J8XK=#7X*sI6YY z)CL?Vkh#Y7UP3Vvwo{hiol;ML?nl5-Z8ez7^Q^{CQaGhZyXF_1-#<=~MU)+E&(4S~HdnFYg zi&vnpLW2TK%%y-_QX4C3zF1}#ak5yCcCHMGDV2xXL$txTTmxBa;svs0X!NO|EtQ^1(23nc7K;Px&Bz8~zi7BH@EfV!|( z?^EWa;k4ZC&`&)CvmE~R5iz$1M8>qE!e%O`0(Y?cHIjVEhd^Gf>Z6td`pYI5#V7`D zxMP2kTJ1djkqQShyH`4uj^;U9slI|nHDm9nH!y$=RH2>JtT1zn2FfL7n0Z6{l_H!)p?bw#)?c%ZI!nj=>;~T$HbA= zHG80MyjLb6le)*qshbacT8&wiq68dNsal!m3C!^NNxjeOJ)jfKe956Q+5r*|iTCCP zmG2xiX*r9hjO0ZT&J0?y-n#S%>M@}-*<-kZq;WWt*|{|ND>6nLEp`8CM2Sw<;uRd1 zI&CV+=)NZ&krQ)qiZ>X9#{m)@INLnEqpq*8_Id$VwQnVYdIr%V*G35DV*hZ)4y|-L zaHAx5d-ABANCtP%Y9iEfpq!iRznx+QN=iN((SHTF)Mfaoj+;-V?uA~7wB$l`2J2oo zu?Y@{;XKPz(VF%4^9t*IsfvXyGm05a17GfabP{fn`=hh<7n|S1o9TiINjb#mckln8 z%X^rv0%Tz|D(c3Fi@UT9T?R!eG1OfJpskx#{lO+538m6xl}$br(UH9@Gakh3hzu%w zY%i3nqB-LpXT`?yC}rIL6`}tT*H&}iDOkg!oiB7fv5U(!&^-=Da=e_6S8)ygvn%Wu zQnFdOI`S@>OM3{nom0@j!oqG+fd8f zY9&3u54l3Ljb=c)a}q&UQXwn4S>H5`yQmvx_R+tuu-$j1QRrMvPOIEv$VT@%bc&wPpX zRDV8Hu|IIH*5LNh?l0L8LI>}iRtEkRBc$gQRYFp61!SC$ToDmD{eFxD*-r*eGrUPg z{>1_v*A;CD%oq?3Y+!i&x-@WmJ~dE;z+5|=fR?ZW^f@@&7Ra6W10A*in38hvC2uH| zp@1AS>HKgN4gRpY1Iz}(|6%z4IAi{|(}Q=^4Cd=i&S6UMt^binpo<*%faEFx&`XVA zpK4lZh;sN$x&4t~{`_%4pn^TE6U~~R5yr6E<=_krdbk}01n~O%k^Lt9#|z`aW$haD z*yr^T`02Z*-G41^)rDYg{gb#wIGD@k!rLF5|J{54u?Xv_ihe-4n^Vi~N7e#1$OWL| zNg$4y0#|1F{ZBW?K?YvUJ6`2A1~!ZqHx7QC{L)w>_aESq3?C}GfrOA)K{5H6pWv#; zyhjZ63Yg}eX7xHWNx^#rbDmWe3#;Nz@Wp3zdoVKstW{6PoOulpy>7biTW;6(7THZ# z4O0^AFWXI36czNo!RLH`QW_6=>lH9ORD$y+nAQ(> z7Ec>*L!yf2zFY=&RnW+R2Qw(N(13bTY*&9eQol~}UItJoz(bFR!gAAK0$3;`oAm7% zK8At1^s^%wxEM8SC2(M&egT z&p^Sn0S%`n?O`qsWZkhlBrHp#M2!(J0$82pNPBhQ1U<#7f2 z-|-KRctI-@CI?!j8FB*%%sY%pqDNUgV7{1;woMiQ0Z(5rkT4!X$Da%8gbUy+j&wnW z-vHf1*?5UXb%${cya-VfA-yGusW^|@0-Cle0ec~EpKPrcvSb;Q=i`{t+rW&kC&gk@ zy_2>+?5J;k@OPMzMkh%Vyw2zVTt%d`D7)W+XvhXn$KF416=L?2xPa zrCCgZlG-&#S{Z6Ec_R*`Wspn%Tt|uCWMiyoiR{Npa_j-yM3D7s$SUG_5bg~F0csJz#EW4$$;vuVv4Tv)$;mfIo{^4XC3)D?x zq$VH-nTotWn3J#sr9GLSO*SA+UJ!a&{>^INbQvtuqVV%cgz= zGy666iF9HA4v#}iQ zI>2|}IQz$=BSyQsZ5gjfWz0yW=4>Qz#OVfyq$$Jbf-tJ7Ei<(U1K^FTQE+l+cYW_0 z{>1j{Tr>~>!vYlEK;BGr0rUjsh<$2+k)4U{|bBgs2cG9k&G2$chz$hn;vaBToR@INrV6$gi0r zyG5x)S4g>KqD1ms1C_K*zi9p76ZG*3T*sTxg1iZg}5#l4Ivpqa)VyQVW-Nyns=`;NbVL zXFM>djD$-rK=7i8uoHMJj4nuJHQX%OBzTJx=2JZwfWKINr%u*pGb@A|0-qRhsDD|V zt0^j%c3za7eXIGV+tg$*{Ii-7WKZe=#W7>p&VZ9OBb^AR7R(q@loBlC0TMV8KjCC@ zyuU^Ywg68(0<)7k93b(FoYX|5z+ZHK4487hE#AF!(^^+yX`W*qBu@=ssZkWE;(z>A z<8B3L^DoMQgyav5Uf1!ya8hHBodDrpuUoELiCW;v3m3d5;(!4y8tP_AIx=$?JVS#9 zZwT7sqGlxpb|Ou{(My1<$<&?F@oQgEVpYF*>&u%J{=A4SsS51cW_@Ff$W zdC;If&;^g1@JpXJ^@E(~1;95fxJgtLfg~fU3At{)Y!yEt`$;xOI zIC8;z($2p>6nY#v8cW0=Wh!{^&L~oFU2+wF=uQjx|4&>IKmHG0?;THd|NoEMJ3Ew3 zlCm2JN9jb9G^EHZ6cUPKuM;Q9XprJa6pD}?*)t+4dt`;|b&O;D9?#Qty}zH&_xJw( z)2*w^c%9el`FcJdkNbK&mI9f@b+|dqaFCtThC*%~Y7PR&a3Lu9aBzaB!{y(+bs<|T zVd^WC<&G3_oNI?g)c(bFGhiBy3E_;ENRzvqi@zGmcSh|#8{@eW}y_#HjdL0oH zZt{}y41Ba)P-%339)`S|V3cx_A7~@-`Hm1QsE_Y6O1kp-SI;haO(BzB5ZjKy+G@;f zrU`u9={f5d!Yj9Ch8fAer*Ny9Sv9zN%ak6ohVbJ>%4r$cW)~6;a(A1@L3@Dd)Hqc< zk2;xVN!iEVEvV64k;` z4o=Y1eMBNdlnVihNAW?>xQb)n1{B0X?$PLMi-oU4#X{fFI5%Scx0B3Os`P%G z$q)_m>(--m<%`l zQhXUUf(4hdbKIo8VL?ivydbYe*?OWwaQA+X%XM)Vl;nU)4}R40FvP0Bwpoh^d?^W$i*NCe7Tl+ zvF1BaL;FmNaf6tcJ?6ZIlDk7cLp_8nUdyff;}`D(yS27Hd?bnIi~fO%o5^v%2UkHZ znF}w??n?>bqw6p1J~#zZrT6S{#d7VE;3w@`_ zwYJt>GO?3Klu|(Wv|Gm#RuyY#V~_4nJt(ciDWBo)bWi8Lwn46@cbp;NuWGZ;HhDq` zr+lU(nQnVv{i;sY<7HvZfw;0`@jD_KM1FVc>f@T3^`(Er*&Q9Gs%-~#1;-QAAmmG( zO4Y_BkcYjW*y+F2IM2nocJYwTo#b6@T*DVDM>T)B1eEEFS;>lFF=~V~v0SPdjfUV+ zKPCT^AkFgCuaK4#ypch@}!GoTIACuprs2{3c^4zDNcJhuxs_yrpv ziPHl#2ni+9uXm}H~?z+UsIV2FBIDVPM93yOI{)LA4RIC9|tb{T9a%`+{W-@4-@O;8@kAC z_|%|-tiT%DLFANPZkJ{?o0`aZw&$;xS7GCG5C08ElGMwLzjc-}9|bzaN|+jTJ-Z>r znM<&x6DjPjzvQp~XrMCKQ;G~q%C|*S-OvNgY#&eErT>8p>P(ZgQV{dXPs{w)O;F9# zuU-fFT%mY?m9=kiQ2JV3u1+SmbrZh8+V}^1S%XNx5pd9Df40PQn|u0+={848n&70I4>mvSb5YWzea=1Q<@ zAXXGVHD^g5dXV?Xu2awe``!`#G?mxA?q&e5^CKbVi<;cpRcwm}wd6Hu(%yEf%eyj` zcR^aoOEs6bxencJ^uE@~+=MjNnn)C)b(A(Rj8mdS>`MyxN{NT={>Kn8#%u_BoypmI z*VhgzJIw#}_hbDir1`+_VdI7(*^hE@k{62V4u~ngF`0495Yr6&ao^}2j~M=hIzriX z+J(VpfIDgd9k4xgz*cM;%QM)wYMaql3hVCPx_($e`O>2^>JK+4&Xnuwlt#FUJ)vML z!>L@4bE)?DTfWHg=XFoL@{gd#g-}32)3K8gj|;-z>Rdm(U-{s}GdL3Eo&88nk%}*h zCHERZQ?+r4V1N8-m8Kc%v^~A#h03}g%E~{(&TQRNKNE?Z|5eMU$9HH~i4Fiioq7fg zAo`T;?;A^oYfG1_XLfh`nHJ^p6wXe(mc;k`$eXEK&#X(D7e0Sga}K-GTPJ$oEljEw znq&JPDF#sR?+06?kKzjr>3FY?pxl>RInBhynzEe;E(wsjNYotZiO(JqDzaTYZg~A6 z_rv3dtQ2O9dim~U%d-}Blp1et(;+AEy0O~Csdv_j1JQF0Dt>Y@K8>|xtR+%wHDMX6f+3`0ekx{u3UQKB`z_0uuM{a zs)#J{eIj!FZQVsBWq|3q#{v>=3&4^%UTP1&(~{@K@dM#!6tHjgBFBsCE-J&;!s zclmj=lLC<;6%2?DP&EJbr+CP6OVk);TR%!SEA4Zg?BD`V3vdo{_I<^jGl|74;@IMU z5lXm-|6lqhHnauyAds=trrCFXL_ZQVR2A-{aW*KL4fF}J|K~O&f&tv{)7_gh_s|6s zaxN6yu>h7uK(6#BRShwn!&t$&Jf0I*OL8!9sK zoHqxM9tkD)?Nqrf1V0nIE{4Rq2FZHD2%ATiUib*`?^pMLvtAey=L{j>@jn$R{8*4y40JZF_Yz@IO~;iL%Sc z$4>gw(Eod*p*>#p&VfJwb3OmuK5Xd!oxxfq0LWIJ_u6ov5@M;9h_F_qRwBWx-HGxyTQn=PEV1Lg zMfq}OB^m;MlWKR|N4rYR_RA&~a#wRQA>@xvk}O)>gM7cUH6Va*I*!sl)(eoX7!hh` zSl0J9sa7(u3yl$HpmJwOyb=rs>K?fHqwOUCz~q5Hg$yntq~t5-j%fzXI$YX~acIir(U|yl*QqY|l{LU#(&6?$XvjK?b#mUtAJv>y zJX^tP2qvT|hn(BJUDnOSsRjQVpYD!Zf>}V%qNn zp3(`O-*wni5V|X4keTgJynrxaL6M5gbtt0BGkgJWm;#nQ2kvth=ufzpYdtcG=R-=h zg!BO_?6D(WP1%G)e+u5BeAq^I6Kjzjj6MaYRdjE{8qycz9hVD+!cKc}%zY^ZkCq`| zlvPWL+GhbX&VQJ{g?d`c2v{adR&QMCChm)Phbfpu-$;fKmkHP^bzHjrMD9alNo{${&U> z1Qq^Y8qeWAHgI!u+XI%@289Y4fI%L5jF=c#hZ*3mgU;XpSyCkB+!Zu8CR}q~kSW9B zX@cnK4$uhthZA%VaabAwQ~BgYmr zz1ENkF{|{8dI>huTv#T3+gK%aLNmYXseeT-xdk=dPziXKk{xNSYGG+i1gIC@@xW`| zki46^J<1DZc=kQwR_VR_B-u;@`u0uY-I>1Lj1~Yne{%_@T~5Dx&=Uz8 zeF0@BEoT9VL;~g0S{CtM+Z7)ZeT_LhH2QtWiE74gMQtD>a6plT^4=11;1I&bev~Y? zuTsu_>ATuJn;1i~<&fWc7m#Yy!WC zR*-c&?q}dX>x;Jr_R)(?Ur|EHQK4_+T=5{i4p!nw0+^LbXXi-pVl0rw@Ai3 z*&n#PO~h%1r*Ni~uRU-J89>_4hzhX`c+(%FmQZT+)n$6z9F9A)Q^{|S)FrhD62Li^2dn?ZhWn%OQX`wLkv{pT{{Cfy+Ua{mA&xh z*jEQ7BiUMNb~Y&-xVlSvdPikl#l1H^M;4bxHb&MgRXfb?)7g`$nx2#q35NYs> z=4s}=`O-NJn~T+68s$tsl7eWo3lkSAVp5JpLa5neUnNki=Aa54;)mE-R~; ziwx9{R4ZO2oS&cKBBwHYhq4m}z@Uv2P!FPOdZN@;dG6>BD*8!9lg#Fv5b|g0@Kx|W zO^wsz#zE&B_uR2mIzgX~CX!d+XocO~FEYt1pFC-fZBM12gw4dxFLIAuDnxokili_f zW8qK5LK*Ie%J9mxu(8o*z841t9bLP^tu;qut{KS8&$g;6`-EO;n76*~!pLf)OfX?d zGZ<#Kcp0<3M-;54%eW`}BAVi7ww6n`ZrHx@oF{X2F!dyn6Zcbz+p>dGw;Ta|FM>H+55B&+2SfM1OdsxxV>R3(e4@E$vYciakSjQc4nvgODpwR{mnk zG+904lIYF0Tdz9Myrr5NK|*XD9+398xyJoUVVSz;o;d0!9kuqDdZKNl zaeoFUT3NCvpz!!KefjKBUK$3fR%&g+?-S|DzE^)))r`s&Hd}Zk=N7Vb{SJ__Z+rKM z)ZHT`qv!k8%zlASe*OiE%-NWwRa7bAJNQu}AigH2Odjo0u`jD%Hp)2o#{LH9(uOfs z9i!1Znd$iTOL$$+_&c*k5$`2o$I7S!>mo-(QY5d7B)n`fSABItNPL2+**08Nh8i@< z_3}T*D=XXw`UQkkG0w$G*d#-KzoFW|u+dn8pY2gyRcX_k@9GvD&+|Mstgh{DT1(B9 zy}sk>G}mMO9O~l>bs3`?YPud>JdgD~i^oo_#!y#J?QuSlbo8zOMur*W2<)4uMEYjN zirvrabg=9AKNa)#f59Xh$R#<+PQ|OUD+H9C@p%h6a{45f=Y8Yl?;PywZp?K3Z2R#? zPyXfL#fhIYXVM#t1_I?>0#}T$VYcJfk*7kK8bTb^*V}k zQFEzKpP5d@{nuh=^3>HmB3yGhafuQA;=w|X$3|*akcUNz^jP|uAIZrg;q#cp?fRof zweoZy1BRb-#lp5uCjE4&%5yDxuif!VVs+vijqEz?)sVQ!zW7XMNu)jRe~UUbet zSbLvp;w+z!-CvuT0ilI%0T79`>dD0W8PYI^YB`Vop})WJ+K%szJ@1diTFi{x#J3<& za|S(#$TSzt5Kod))albqCn@eV7kEXa9$106c8lJyeZa9Z5Q+#QSO2~+@^8QBJTWfV`hG)vujrm z$ymE0=@K*Z%X~)G>k`nVoGMsqGv<*92p_u{uctbI$IlJbN@KAOnLnm8`yd!8>JDVn z?SjN!6@lJofbvOc00_kl2k!-K?4lGFYo=%;4bqyEAgj5gjlH{jnhbUGX#(MNeDj2` zTTkR2D0QSEcW+Mu+=vGa$cD6^xmsP!&r*-Fs=TQ%oK0^$I8vUUG63m7lL)0F~r!A&3ZK zRsc^>1u(GQq2BXu*x?yvsKH95Q7S+4wNH0X0*!LK0vHt@(O(z@D0)5Af*jYpwia}2T6t0Iy7p`C=}zyCiDh) zKo8c6;Xu$pv{y++CA)fKEh3~wb0Ccw52vhR0+iIufbw6i2;H%N{qX+yREW`ln=vz5 zhQscWo?Za?`q}5u0nF%AN|B^TLhB0iilBI~$eUIa%xj#ibhi$SelBd*Gx_I>wcMAN z+q?DYmp*di+My=3SPtQldi5Ih^>9S>85otIh>;NxsDGDN`{FLqKm7Z~R}WE#L-W{d zE6KrlE)m;z>JghY+ zmRH-!yWf+fm@TSzsOWuAXTdY;T5rd;`BB1(nR%Xde|Ix0SN^xC3^;vEXN~|kb}k#N z^QKOch5s7mWPY+d?=}2tKQ?DADtyE600hAct+oEmM&Sw{Q!^u|CY#G=FEqULcFyUn z-rmS!6DZ`h_v28EJD5_RIsQdlKhjgmj-0uKZN}D%kc^K@jif?-W`|?9P@P-&-B3}8Rr>0sZJ@cx-?+XT=%SB2`Wh{s%dEiQmkjmj zQeut%11~uBdoOpwZ?=~@9mS^e5yRw(y$)T$wG*vLwEn23aM!}k$8x=Z)_S&Ywy|_1 z%6Jl(!+elr7M5wjga~^SbHAMDP{hw(W_zS`5sH+R`ID>tTbrXBv*T}?NHK`7nd#gd zOAPmLbPr_?4W?Ov+nEPx{a?uA+44*5@KTL5n5Vp&QKxya#yD`OehBn9S<78B9a)LX z9US=&<`N(TM5gUD0mNj`dv!ox<#jEu{2unH6>oyVCiDciA;u&RN^Gg7TBD<8K6F0d zB|~`_&T~RL>0Un|#y@@zev#Sf-Xd~t@{DF}V9Rv~Mk0ZDWrb9K50rfcrK1C0*mV%4 zA>axF&`5lt#r=gE+wXue&Uj>&s=~~KNr3T}gMCrf%*+DZg_-_)fZtJ+eKG8VJTuCD zOYj580=}i-D5NNKaSo8ljIbJc!vrYer!c;kgE<0cOV5Z72Z+C4BV$DqDxZ z5Vg627+;vMflH#*VZxJ;dWDrwHWO~jCksiL##*Y#*7clq*oyhaN`QT0Hqcp{ib;=A}$L4$acz0{Wcks$@F_cb$REjkHDi#v{t z9WtFsy^uWJ%A$xr=c6%+W#pvh+-B-hvFS4MWu$LVaZ$wJ6fd2~`sV~dex@I>AFDUc zzdcoPSdFtED-2#6@y@XT+u24dBlEaeHMgx)YaeJlyfCA@+ApYvO!ikD_I2qq;cq*6 zN;Q6w;WZ73PlBN!s9u;uf;gnM(73;M*6;E<3Va0r-sF>`M=9IpI#N!+);C0G--rn= z&WIR#&UKKcLkCQi8jG5Rvz~Y<;uvJPe#%#Ukz}!od#uEOjtx(_N%5OTm_kxQvbR~8 zpxLV<{=YK317|O=v3R*YZdkR!)NqIH9)I9*LV@7bDx|1`inTzY-N|SNyFdh`M5x zxm{moov7`N`vk!#qWn3Y0alV{h)e;ELARnhYdJd`eu-t zQMFxm@zsK3#d4?b`9ww#$Ly3+(ULpoCm&jI!b1aS{@xKBRUpS;2_Ol#jm%@xsP5AM zKy+Kb9rj~U05caYQ+P4k|CU)yk>lssI0jDS;;@*AcyHKwJhO7)eC&kN>sQ5IHt^@| zWMHfEX!Ww!n1)F)^XKN1M9i?mfF+C`ADnHPk(mU!X%N-kwqT11ri<@JeHUAFePVY| zt4$>_+`(9cdEEkFsYa3-2|KD3ec41V)+S4M3w&%o7zbkH=FtLAh>aY@E*{CDP5}JX z^e$)13lp3V1Sfi966SGvt*l&}0=sZpm4DWmTtA32@ZMrSXXPIdkYEwAdRI9j+5{~C z%YI~Ty?&Tbf((cBnC%PoXOnLTsdeBxhYr5|+=W`P*UwfjhM*mD3M9bYUmL!XQgES} z`b|S&1;-n;1-3;T7$v4cwPP9^{%4Hf*k-W~+ZJic3Ttkb3hG#*i4Pk+uIDCgaOREJ z3V-`2ig#agk?3?-4l|s4?{}}0!GIk%CvzU55Jga4^)hibjT+6payiTO=VUn{AWQPi zH?rnej)AL@zsr<9_Jg>u`}pDZCkt;XG=~I46&uefhC8uPTShQv>|ZG4Yn0x3jIy#P zHPyK9Y-1L;3P7Cg;F=pEHY*{@A!c#s9F9bk!PM@p0^W#tha7I3CdK zADpocydX+&ZSB1kG~u?b{<3pR}udL+zZFQ z80g<$Ob=IQ0R?mHCD_27hwHK$fS!^RRCB(bIb4!uUQSaq6sGP~1gK)_66Cm|crY>u z6YW8=Ljr*3D(Kf8fXyo3NsforSLjbCT?yJ3-cV~<1$Zi8~-BZwC0?U=;1DeMh=@(x(EUxB0Bv>y z9D5t_9KVx9|4<>?!|o3%%#9zoLkI#w(L(2-pX)rW@cBAu)zO{WQBBWpVjjq_?IWD^ z^dJ<*4L&|C@6?Qgx;rq^o7O+v%^d=~^3Vh`IAbZHKX5b_CZn+be5BsQiE7|7<8Xry z9*A!sI2qJ7_3cu0TOW$1KZ4A%1N_K^#zsEQ2Gsbvg)@Fm{!>uxeMJzvR@hT>;k?UW z0k0ZTok+`eWz8C$fvR3wzEbH8Z&0|w5L7u!{rXKxJ4wrM?4t-f+x<38i%Pc`2A-iZ z+5v!jOpP<-VP-Lk;L7ZXc#GB4xQCpUZj_Ze|NH9%pZD!NPz_35{$R2x+z@jiUsrrE za#p>`PKPsO?c6XwWIEQ?ag;)WP`XVs(Gd6pL5x=cii~xI(z6R>&Kl9{FuNvOr4LsL zR?0t?B9-1CrSQ6f*R<4>nw`&qL{KJYf0T=Sn`Hav$vi8`My`1tq0eeIb**^#P+^j9jO1Ize0F(!$6LcTc zM%hph9MZEU1dH4PS@Mz+8y&%?W~7+Ya;D|`!@n=rI2{)nfl;KYHAs*&c}`Qf0&eJh zC_XwL%|R|y7ApJ%0*F~i-{@t^RWtsz9Vu=fj-Up~^%XqMO_fL*p$q3ZyKuiAurnn- zfjVT6==!j2j&cp{Q5l5@l9nUM0@FH+C#oBcldS% z&EvFc#4)S0ED~{h{6Ga%Q#k?h#+{9w!fZ@%EYSvq!5#H*p#H$c#etiW*-aSJn#`<( zHPXRIStu!ur^f_UPQpu~4EtbneYGI}>0S1H*VWrHa`6si!*pW;E?AKSF2p7~yQF9| z2m>*UbgmS1%8Yh&|ok{bqKT3oOGF~OEpYP0|4}2M@mw-_`LZL#c zvz9JGpyxjO^E8p0cT}=pv#XHfF_r4umG}raH_r(HRE`PyrE3y=e_mCu_>YkOtrj}ajpjfk zqNgf`ix$NzSRPy-7CYtd@KN;jcBWDkUG2!26`qN5ub02niQ`u|{=HE5CbPVOX6C%j z_8CcuEmPyRqW2EhK8Zblc_=UA+Ktl~TvL<}_Z7E#FVP0$Rr7sDGuIogeT;?F_qxMk z_H%c6?&)s#u2Q}9hdExiCmv!eAFQt3r1x(+oWyxHM!C9{b0()E@r{TCMh5qdtC^Q( z*r-D#eFa#x$pBAa?fQ=Yg6K%6#Bxw8570o=S;#mv7#{hqIDGeoOQMl_Uyhw(pvG&o z`)?TdQgLY3(uNwyh?Xn-H79|;Fpdn>&f25%;3kL#ZyrqDoVfz!UO;4{q{RfEu~JHM z`sQz!?h@-8iZ2ciw`HuqYj3*OHfo3XE~ZuBa|)SkG;i_tfFFXwDBEovwI~KYvuGe7b8A?FnR8x1 zQc-qx=3LL^)brIY^C$10KT*O-)(fM1>_FkZ$L(LN2FrPEh#RZiyo*hpDc;~qb4hzv z1aVU)r3qJ>o_ab;Pj=jXue+2lC0b(p(nfzFD|VH|D3$eg=ou9wqVhAZGpJnZrY7}?{nzC{hla-x)1$Jrkc^^Q9Ae1%TXES(EcSVyG~Rb_ z;43!?6%K#*DiVJo3t!&rM=y*w|KxrJ|8y1}FP!JvGfSx3>g3MbWmf*O!n1*~#Bst` zaP-o=%XT@78ySVQr_Am?9Fe((F*-%L92h|f2@+jRNJz-q53!+qAs0Y(bm%9hg?!5Y z#l3Xfq2E!-CeO^P>>C0)^PKBy^PGOqJQ!FLAMVW9IUkw6;q-i}BeTh6vcbeB`kBV) z-iAw)rA$=fRm6mQJ(|lsL#xC8frY;5ScBH*=523DkQ`lniGa4x$1hn&O1g>c>s#dB z*OpQ^viH1(z(M2X?|Y2=P6&r1YIM%$allW1~<-{rZSM4XS93 zKwdqWk{HIK!=bU*Ts!L*nE+BGSJ0_2xSW3r#}oRb?09&2o%A`3J%%CCly9w@$I=tj-i#3D zEH5#foUxzmT8I$4Y)KklE9_Wu@H(TY#mEQW4i?exy9|CMW2cozZbCs1HN-Zo?gB6-j6<7(k5 z70Q8Y2C zP*RRyJ2d<0j~>EDI$A5^_3aA}^gvUbfre{_Aa- zX{X&xzV?#f+r6_c!}T_5k~|Y|u!W)Q7Vn%hG0Np9YP2`kK_50aKpq}zPd9EySu_Ak z+{+3l5Fu9Qnf$e`X^7zJrNfjS#s3&>j_;3Vy#l3+Bl%Sz`}_@U=h3Dq9a=0I1=FK> zrrThS(_X_gTf~lEZaWKJTsS2f`Q)x%M^**rKlce2{yuNb%!B3jeY>-j_BHCrsTgN= zPJYw2wmH67J}2cGvS#A>zEINgv-y-&+WOh>IPAKk3gAMC>1md z*-&@AmC+J02w&cUvi9r&1~3;@LtAwVW_22WVqswsw?xu*0FCL}9Q${8Xj!Iqx^Wrk z`)oK>H@=8Eq+U$8lJG-v{5!kI`mu>Z#?oH{^~rSh{RK^w;IYk>dhWb>$a*#mxZ|zy z8@wI4u;``ux`DHe(EH=0022sV-L+@xpM}3gvaFBSPa^kSvssaA`qs-4t}##67AmYP zuMGF<90(_+D7fzMkI&FIfBeK6$s7u1WC(pz62#noy^+&pe**hM|B9WVa(HLV4cDN) z%W}3+($33CSFY*ktIcQ66-WAxo^b6_9C9Pe=drZ!qr-+dE$$F_cy9zIy|McU zlM25IwDf=Yl=9{p3=S%{{ljUfKjT(0t^mU}!QL5xihvKr^QV^UkbbyNaueB=Q8%~H zL-f`nkcT8J7J2a z1sGo+BPTxKTL!$j1Wi6gfI6}n$AKE8gpKGGwyj0)r#HL=gW)FOT*r37BjpqY*+1zJ z=F3YS39EqtQoCqr{%Ju`t1b0UZ-a+2x;|xxZ~PXvmRfjmsm{i5@BCE_Wrf7#_3XDs zO`;4&o2%c`>wX_Jd~10_eKE*$>YH7+aq8f4x&B78w6fMKk?!y1wtBSE%LZc%^KKp7 zcP;Dj_U4!SI~{JdCXJWgtP#Cn|3}of17$%c%-y8cSFt35=b|4;II1S(aO0Xn_)N*w|!1u?sGP-ulaprklaD?z1+?hgt6waZ}|@UqB}_2wni%X-uZqU z(HcI{aOG9RGh5ffOT`QB`!3ETRfVig_-^#^m5^Sg$Ia$S+4tt|iH7zYcuTtFFiGqE zv{*H=>Ttxd9@b5ex8YPZ3uk6NFB607hq!zpD5EDa%tlixs4fjpoixR?yi!y*;r;?lpsssU;LI+P@TiATH*R))!h&K+;Q>d9I} zsRwtiT(Yi=jyZcJ`@-yu9Me+zY5rZme~vaj>vsNK@2K{8`1|O4XTl|0@)_)6exAwk z(`y}3_p==gmZj|}iK;vAwQ@?diI4gKAO&i=o&(Ey5cTnQ-;X<|S$c~)JBZ7{`>IU# zsa4mYv6&7v&y0=|>-!GZ__&t+RWQ2c+EMSZHydIUO1Fg1PCvepKA9_=zF3_P;fCt0 zcDIeQI{21w6;WP`uN|&wG}nTDn*KFW!VM_iWkYw~sne<2FbrYWanPby2>=59fxk}t za`+$y(2~H4ON*bhAl7>liZc$K?=@|8y}S?IKYW%=E%o`LYW!nEse6{(RAF3r`dRk8 z3g%X|zGnZi#V3L1HlI~$K-Pwi(K9wn_*0eeT zq7Qexm|^G$`}*>4YcYomSYWL1>&&{B?Qkut&eeWhK?1JDYdR*G1Nvgw3n|kN3^&`7 z)9Reg%IQwW$z>nfB1bzsKimS1<^WjfkwTMFRTV&umIjOg(G489M#uqLgy3(evq1XJ zq289B=g<({5hl0g-r>TxXY7eoYE--gm%qNP&#G~Jj^){_MosJVvbudg5f^qz)j9)0hiYW@2outVf!7{0f735wk`-{4y$swm|@zBrif~Zcnk** zA$$lWP}hWumUgSwmOBBlSpQ(?$L}4GC6jTidSh&kOHyYA14AJut!{jInuUDxNOB7D zSbY-`)N%+Z#CuUKS6sB$Va`)L6yTagf z8Tau59`Vy9sGVvNBt#zckWy(<0v)@OlVBsvgnp84oS*%jz}dND`wuiGkzMhnwSM;T z49)9yz9KjHdZJiGJ>NaETX?lSEpGEvr*U*6^p*Fr92)qIQ&}BdGkn4>Ixiz91s53- z6`(~GvUQ!z#0z(G-`5h#m-c!UBr*UK7l{ZDEIf2BrIu_BNCn{jjN;Fc?15hza z^m@&TubT!17d&^y=Tj4HlZK1(mm@8sBz^sVDZoE!6Mj%u0|1Z;8khA7VQ9O?FwO^P zPJ|VLiZ~emRq$(`!?sOj1w!=uJ5CKTDrhQ09TNg0mkq8Cf{Osj^#5YJ?*Aw8!4gG0 zfJ?d?GQ#m}%IX0V!_kvzp*71Iz zEHX>Looglhv+V0H<={v58df+D_gz`}V4l7fmC;(h7mvnV5Drj)`lDOd)_(HI8YzMZ z_Bt=nRGG`EZ-W;$cj*_tGfcB^X)sO=+MaUn>2|x;*7>Iy+>MYk$%{flmfbV{28)1{ zeT{Oz;1^r6UmXA%zYdJ_17R3HIMf2-3?1@{ukv zra9^4lS#;=%LHF)InV%Hp(3g&oLi-k9Rx&x1(K?I9tO0~dIHu8%8)@%%opXaQN-Zs zw5&fTQT66IUoY)|wAU%nn5eVRLtQ!OUR?pbbuW)55Ig2g(_&*N zKCnCAkwa%QaPIR#^D1sM0Sxtz_sJ+>#R{$}8W}FOw&9kuE0^|M`Iz)(I-4JOr2o=hFPMdH`iIm6@2gH5C>qZVk8h=NVP z?Bi^AB^Vh3)szMt4CVdd(iIwL_}1y?j@@rS9jEk~Pch(wNuhJ}U*S0hruh{C@sS4b zyw8-vr!k4rDCCaT7t(6TmS=-)QSb10QkB(VaFC-u2%+?5g8=NN}>~4 zLPZ>&K3=emHNTvsIE-(AAZ@!6q1tBh9W)jdqBtyorq6{C*A57CdR8zEIDjK9Bm1IN z)rsmnRbTDd!rLb+=P#TR6yqiC;nmn2$UAxP#KT%o*aM1+qj}XPAeKD-G*j&|2rG<$ z?%|F`8JW7xNmW2zQ8Hu0lmw(-=c6~7lF!y*!-*6E_sTa zreBtjM51z)U1Fgp11nBctO*DZzL|Fm+%O7q;E^fMavS?r{)j*J*wyE%POn8-$v3>` zmpb_aFo%@`C%(){3?m^I3Yju9t5Nh4yQ}6K$`AjPAZi0u`nm?ej9y1|UyecaTX(R0*UEcUrpsM#ln1P{5Fp<9YD+XRv2joa| zl$0rE^y+(Fn_ICbF)CA=DQh34=hjf1J4aM7E1`h@V$V5W5*Bj;6pyBe88uJ>1;nA8ob-7v;Aa=jut7UD<9V+G`nHYcYh4rBMLpa6i4un&!y1${E7smcNj6aGDkI9 zTT)085UUspVHm*N?okbA_$BZVeEpzY!MsoUY%cceMHa_vSrlbb`_(P{1RLq$Q5g^N zy5KRsc41o97S^foH7Jq zmR>H)(C1%mIgjBEafN~0G8^=gpZqEVL(H#2oJHoaZ>A8<7`T~EvOTg96jIR6g$Pkh z)K0>&cTq#$a_5syDBhA!Vg#Flsk2ykjDtk1c83bNOg%hWbFpm5J-m-ku?9bSND9J? zkZb4LZ3gD5-I3g>=`T(9nA9CSZmTmB?s7eJ-K*)rM5SlBdywUm%b_rvEvJlp5iIIe z8=07Pn#e~^L6=jm=DuUK4&70rYvX+`I_*J6OcTl_AD%OH>+%@1)26d?|O6Abyractzt!Z(SP zS&W7b{pI)G$?yDn;C%h}=B7_voo!!Sh2<2xp;qm`BuJ zo7+R6fRlj=1@^Z|dK|o15>G*uI(T3tV`dwZ+k9yKv)u;{^Pa(#ih`xI`I5Ak`b~9p ztcZBC?89@_Oh=jynz|Klws0{tN@j=zQZ)=o?M}w1&Dgv8FFz~3=luDB34yrhUGO)E zXFiXY3wUXFnoiqr+&6w_k~iK!u!YB97p^2RkzRY2R03qWR+nN?l^~_H5AzXh5yXFV$y=`Pu zFF#i*P88tokRKo?ZB4#kj-EI!G$BcJG1->us0`#r!T?3XXB6lQ+v zlQ5k`pOqco9E<2~_IxC+_9;`C zL85D*MO;jyFUfq5L@DO5mxx6(FE?MukZR)bLltqc-Wppi-O>jG41=-nzxDcsv3j!p z+SQ6J54_7u}N&iacBJUk<&qIowq!RSUxxKi?B69Pv{M zUQ!y47$Tkz)2wDq-5EYdT^=G(b4+hQE$rFeEw9_HtnGy5XD)B=3D4}C^;w?m{4U9| zXD~V^Q~b`h7{xz|)b0K*p_@YZXLGCTtt=5k)wn8mNm8m=$=jhH(*9couTJ*f4=Vw7nwi#or--I)pzH(4LDw--amD zza!;+j^dPXxAoPr%ZFlN`n={fCN5E!Q1N=j{M7Ni$0uK9dWpLp2mH&DZSNj522Ccf ziCcS8bMZ}bmx@CVxQ=UKlf8)|>LUafYC_4E1LJMdg(U)5M9avHO!tO0=&Z048K% z#t7zrqx?~gNSKzZ2xx@AT(hAMUe(A|G*PYi6QX| zXkz9jOtjQm6b8ufuMrM~AECTEK6w)XaBnMzpq2-2qXUemLpI|%>`dS1DNsFSfzyFe z654&Ozsr?!36#m8e=p|$9vKQmHvo%u5m2z_5G2onU3gaFEPRO-6kR@|BbTZ$>xRp) z*bci++JcgeN#}lD$^Y|Xqu2(e8n7uBYdL~2ZsQVDq*KKFM;L9q(SPA&>~OD-84OuP}RxD^rV*-d{|WumDSEKuQK=b>TtKEDspS zKR5Zmnet!NqQQ!e|DB+mcW$^{u0XCQG(qPstYnop7;-#Q6;eG6bH1HL+_`9 z6f9z~0HUQnrJH^}4F6fhgW@<^CtxBxC1v~Xn*9%+K>1Hgp(Pa0g)9r;@o$GF^ERy6 zzwwvQpxOiZ+Q*&&B^>|*kTa8G8|m8&lPYE$ZXCBy#K21#@)tb;nBq5}29}q3qfq%l zc|rb5n8F+cAsa#D-H#ew!kJ&tpyr^=0RaEesvUfwWL49FqLx98hoZ&)v3U!?2>G)_ zjZSc_@=_Kz0E$RmS_Wh@ zpm56oyu9jQeu88K9~XUZrXZ@eE2Tc4n|fuLX|9T2Wgp*az-!YSy=Yw)nU0-o$!cP z7J3m@Bjt8Kf{dsq%^8$7AQ`4w0Zh09R^6-oKw1!-RooBl!7^W&P2I~V!;I5)EP03Kz?TyUH#l3+$S&ls2Jcls%LeVzmAcQ;QfO39TalaNvNbHP_Hu5S zC;KkTFMDXgT6G1Rd?y;0knx%H0_JRr8(ChS&1;U?Uwa%AAb5;MLU_hw&%0x2TJ2x~ zL?{&De=9&f>V37Ei627PN!moJzEybi(}TG-A`DDGLJ9!-Hd@>GG4u_6(*_8v@<5Bw zO7DX*zhP03tkyu|s(E$*)CJjiJRKRfppBvst|K&B4*%IHv4_#f!d{q6B%jBXh9(;Z zS4yVL9kJOZu#Iz6;1z&EQ+@7Lvq0x+>=ctBOat8F*`c1WYOzN%E{by`)!&apU0Ldy zD+FlYzHaV`0MqSz&XrX!gCuylu;3R+2{gV^N%IA9i0$?B9je}f_rv>466y*5?j%Wp zuq29BLakwAAnJ<7O_XGa<;`8akU;#ih-;O3N1-G;^yO{hS3y3vI8??e8Z^8=tX=CM zA*hTsyhD%WwP>>@d89|_Rs@Y7m!F=Vr)Qr9mg**hy-FybIT43 z`Hp5=34Aad2o~V`{B?2ObKogE6RXt!yD4QqO}!XubBzE2<-Kv0?Tw0Jde$CY+KB)+sJD!*PwcFf;N+__UJBZwFMaB zSU>yCy-Kt896W2S;3OHQe{{Vd6PcXSuPfz-tH5tW9y_`68X4qHbimN#-2R2^= zKXQf`>n4=&39^c-yhu5Ib-R;^oU2KzGXh+DI8WLY4{I;T6ragbuUH*F9{$ayi^o3t z8!k_9n`QjBRrsDMS07pZokvb3tPT{q$kzJ@6RmE9^f630eXf|;OVNT-9=1fcKkn^e zb&KEdIwXciE^olD)PV}k*N<-y#zIUPP7J+%Bg|zcdu;Bo#4*l+iyxCMz4sI|OG_8~ zR1vuPXgD}?8l{spq-L)^*{^SVcu-A-$&_V+D^IkS#NGj5RYa$B?K8e+x96km7P;PG z@!B4-$IeUAijl^Zc}P>qbs_;;_L0GvqXM>(j1~o&?J{^fgEyzPmj)s4iBhQax?siz zgm(^ENuUg8g3?tO`Uc3)?HA5(@tosL-#!uKcykU@D4JA$4<`fK6pwCt!s-5b zo9NW&bm6FoU2D<&FbWVDLpIPM#%DOWp{y(C=J)Y@! z|KHt2wjt)yTt-xKN#!<|SSW=`B}p!cidwz0CrfDLPS zVBR^fJ7_!^0V*=Lx*A|8%cl;VdWH$c{Wr*(KoqAZ!vQf-*LL)u-h^i%O>7Dr>Gwf4 z=+~4--@bD$MfPg%^Tzw18#nrK-#n#KIu%_gZ^OJ#@$Ub5q$$u$UuDgCx(8?&!;vP~ zKI{k4TmnXyfqUX4x{q~b`nUAofpZ{tOm}w?w2gXxcjDKPGzMCj%7T$kUx!}3v+*0P z+2>w5K|o@DpU|MMDJ)*mWG=a?7QAQsIixIy+MuL1(=FHNS>}d5kXd~~-cR6qlktJZ zArL_H7bF{17=GEV3@-5ml9p$~_P<6svKO}jGhqeANq?oL{##A`4Z4v2eVRxf3f%LD ze}PV9C&1X&K6}a8vkdUxWt%Ukp8ub8OlU4?1(6s~ST$`7eW`c!5tL}uyc?$D>0zM5 zcU46}!=w^jR|C{N^Didv+v=BNac7XPO>^406m+aqrhwF3m@lUw5L`ayAlgNPNBgcE zczgDzC!!;iPh{co%U$EWy_itj7HVrdhMK{{Sw5>`UPzE7?X@z_&FaP4pxv9tS<# zPNSaq#{EIHY%-iR))^eq(-$~lb&C+JEDU17q0DiT|LV>5^rnaD7G|23YvQ`$_`nT1 zJ{GW_fGDMfNO|h~>jMp1CH*ItKR~L9iW3yTYdAr-DL`m%L|Si%=mQtUEY!`1(S}`S z1!&7Vh%$L2qr#o20l;>@El89oLzsGuTiid$p~Ae~P;*fJ{U2qym@A;3zGdUUSw6z} z)_Dye@P}hy*4Hy}9AH|1=KD{VrZOs$uYq>%BcJ2#wx_rgMg~CEZ$ve;M6hlH4>)AT zfD(er0jKDHi+GKT6^gtsIOJ~2B!OZyY{qWsk5mC?WF(U)@OeUEVEKpQEp7*OHNRBK z7M6zSWN6o!16Bqv>-1By>9!=0>$+B=?! z-TlDp-ZuZ@JUsLS<~Rnv%Y}d+UiUG9AZd~<%j*My&A|ETPo_66IRQ=TeisGg)rt#! z&JiQ*c!Npn|I+3WitLmLeER|$?~B5(1!+)H_)=Y6$F|87<_y@Mrfd;W0ptyNz%$&5 zSXt=U2j6=I;MHB8Y5~zXPDyj)AU{0q3|Nl}z;3LuS zxrW6YGk33_wTpqF7-iPII?oAgpe|>ES{1i3c50Y@8Zijeman_IS*Gq?yK#F$b)^et zaImE5^r#;>Gm&xzxn`luB}NR)WG7}ZM=>lq>+DDafsn0)_kRHaAb=Kf>-=60*Ih!c zf$gsQUVtFeZ$`}FeBb{S z9rX`RQ!KSwIz&`!0Z_feO$|MeCQK&gHl! z5_Zc$(YUJ)ga^OEbK#VqUQzOxGD(;J&x;s?8fu^*QBP%FAf05*?)H6HEtHkjS<+zc~+Q*&ab2QlK6Eli_U#AJ`i%|TNHN4 zA!<6_+4zyS%4I9=&Nyk`z~BPuLqVfn)@>TU0m?tEqy9$hdHTZ(2N_eZp$3Q^Vv<^f znb@=9o39k&*M`9)2Li@K{{I;Uiac19S*b9sriV{ZPr^HV$WxF$7a;cs^t=vuy#p9R znaibr4cS(Q#dq*C!7g4U30i@>d>T8Q1tONT=UnVt2byYBd2d4%fE#AXa8dr>w!>XV z#Jn_5G^O%*pmRVvoxZ+8VLO;}eb+VE4(4&9{a59GL3Z5#&J&@{lA3Yv^)tHd-rwp5 zp9{{lQL&i2>tN8f7;zr} zBI3_bFn`jyb!jKzWWGG59%6-WcO>`s>`cu@CKn+uzqm0qpcg#?K_sqJwxPj>0^3mZnd~jnpTkix8d;1F7VY z8u#U>8#^G$xZrqx#jnaC$A}@CDIPfQQnZSI*@EH&)-RS@it^q1Gb)?YMTZw#fd0Zy z`Iv?8+!wi0wY$x=K?Xn|Kew7Abc;~H~agzur(~JD-2z7Lx8d?vV!l`dN14_|8{xi$hRF?s{WS%^Xr~~fz0RVA2(C* zadDKe0}|F6sOuWK=@fBOwYy;d9*8cNpQC?1hVN9>$8N%=6yTzTajuNU-e7I;msLM| zidl7wPrF`5+*6|ce~ZCgMS94G2QR6&Q_6dsunu%0prth`CZ-r zjVQQQB#pEMuJk(h{x@~YVFpmC8d0&}ip~3j(YXLL<0gxECm;AI2qrg9$X^7?8PGAX z_{SME&AFSk*T@B|mbpRJByu<(_vQR!#^y{qFD@+l_IsffjmxXRCh$1jr^lX^*m`yZGpRW8#i5h@ zL>x>_EoW}O`@fSC#E`}S_I9`gpg2~NJ0?%|fEwV!tgYxrle=;55FGI0#H};^?-chh zO=w#C_;wP|&ijB8D1j;h1}$IX+rU73HXYzB%T#`*>-m;W&Xp^PfpReFJAHNUdFx*F zkV4>E(YKp#k9vE~$zTizg!f{6d$(7+3A{C=v58BT-1k3G=R<^xHvG#4BN z#5cjq>&L`lN4Ef7740wRGXq6g05c)G`dEw-PhHD~aAw`&{U=SwcSb~kDq9_ZG5#s| z{OR-U-!4jBcupVM1U@^u6K)AG@0*J8zuS**i74H>2r9kOq&EkO4u4qW6-V4&I_jed z=_almoPc05eYA@oMR74L3nfvxZ4ENap%gkT<=AQP^m@u;duAc=3vfxRy9QFQv5`00 znDaH7o`XwUCL#*}8h?OCeIgCkYY7!T0khJ|8ut1=L@@R1ZSW0yPp^N1Mz6 z-P6}{b)bNqgF@?0G?5TH06y#|`TRR7um(nWuQ7(lQUEobvUxcMxiUY2Xtn@nLm|(& zvu}WVqAKu#T46eUw@FbfO3_Fx1_>s;fl^nw;-)xJnjS)pPb|FbIv~g0ZFL_oi842U zDbof*21G^sDc>MrM}Xh*T+>Y3t{}C~{bGeaWPya1odB$C^x3yS=W)h!){OQz4jGQ{ zD`__a68MnHd2Vz--VVV3s69cplmQ@6n(R4sowW*_`!Ke5-2FS(uOyR7qbXWnxJ`wNstoT zp*JG_!B~Cn6eQ8`3jkkne{Y=Fs4zV?9VoNq>N$Zsd1w!;b!A`6LEbircF7bqqZd(K zln<>D+@Rbb?ufPbv2l!PJF}px(79r|N4KsY*-OMNRmx_M(Spufy zFSj03tmqhH#y0S%79Yz{Q7f`{t>8@Q7+R$CL&ls1OZk$AiFmSxK-rGmY}IjC?9vbIpK#i$fQ0yc>{ zZCRVk;O+cy>v3U7IB()Gm<-tsqa2!F)Jaro5j5b(%!bz9{kerteZUKZFcRGqRXbp& zl9Tb)Jpby=Prpg2G-GqgOm!fQiUjoeCb*#IBuL0~U;rJqD;GZF=t4mqxSV))RxdQ@ zNo-sFOx$au=u-VINS*>7UQW2Yu^gY)r;)S9K91s8c9+|Ttt?@J%Pi_B(V?c}sfeRM z-ML>(UKS}G^xA-hZd*x4!a4xQ{L-eL3zdAy-jQOb&4F2Rd$TM5j+Sc*>bLk#^ntG!3&w;Oh!GBtP zKCDBz5g}&}Ura|37@Iz932RWg~HZ_^KxjrB#$}raKf=em@L({cT zgc)m>mtda1!`YV5p`A$CM1BkJ31L5|!^pA3*#iZb4xWUg93j8}(jrsme^CBP2vsH zut8DM%-eRV3h)ay@H_gjh_wLHO(O0h+`>2(smmUsu3=?LsT?s|JrYB*A%L64dvw9J zR6H&a|{7| zVy&2VvyhF@%pTZDs1#=)Nyrq%YBxHzWA@%!Uw`y5!c7ntRpXhu8#17 z^+&JWTre4XG1;j7!gR44_E9JKnQi!umm6lGe>FQ9fy{92!<5+|^4)lewW1MxpcSto zDNO^^-NGE>A?NQ%j9;3tNIrz2M) z)fsex-a+}-yy5K&RaTCaS4DI9=#zkWdp_cYYM0XMa(MuW>dw0kYuA|6rWkyhvMarF zPQaWwQR>wRi^M6#m~x8qu{C9`uburI(wTJzwKjq=O@Qm(m#VRNHdM;z<^S3>L zF3ul}C0;j=q!O9N(7vxnhMHYn(lKt}`;F8R7?SnulXr$RB$L9h{B?K`;h0>ToQkPf$DdqMUhR*K?88UwSWDvhN zbVv)xLnA=dNOJe_0WSR0+8<~qtd;t}@~?*rQbIuo@*K5%dj zZ|sDxH7}5#T{-7rRcxZy>}nLlo5o)$T9I<|r+XS&f#ANEdDz@c`yht1hj4*D{s+Sp z>4>pGAey&<Xd0MqE-(q_^@jxR&eV}r?}c- zen(s_p7t3mTV4=*_x_5gUOPQkJG#81V2(--}pW1n8v7$<^W$Yse)Wap|lfNv@jXR>r`EcD?eKWXs2L(xm= z(utNH2iedruA+KeE@K%d{T!Uyxtgux+D_X`44?4R#>5=XKd8E5eTumU^F`+b(F46q zPc+F$625M}I9GPm66hozAzpuwhkIIA?T`qX$~Q6*rGLYyX9*0W{>E0Nly@R|O}JAm z%7bR14==Ik%4+2v5WjNdl-_(hO=SybDxPWZ;sW=ik~P=Fnh^7ewK6E7DKLpq@%#=y ziSe0IVi7mn>hsn3%VK=?oK zq0?c*j1SP(%^7deP2{cf;|Ig@y85QXa`|US#qT3_$ zal>CeVZuBlJ2DUQ_qO&DbGpTps-*{+ePI)0Q`aHiEqxbR$E?iHa#B2Uz~B+kmsfKz zcHft!IHtIAu?^HWf7LgMfZur^%r2VIu8VYGwieDPn5+%nKym7*XjW*!93Hh1AG`gf z^W*f7N`{R!%xE)Wv9lJ+L(DO9_&YMknl;NZY|}vcmSUnf`@w>H5tLVeC8X~pY-*b` zw=5xklo$k$R9^Z%DhH4v4lF%OYN5ZmlC98)MNqt6AMKqL4cl!rYti5+HI{gVqzy1< zQuX(`$8JiVAjwGLeQCDX>a!s&g(FvG`D>qB;MKRJ z%%2>ah3T^hu4z{6>0}+!?7{h2VJY4cl|!C|_Mr6&q(MzPUFOLLk*@e_u>AVtZFQy( zEFb6oHfvNgdOF;ui$QN|Oq4D>)#sL=IP*oH9kK1CGM+e!HRYKI$_Va3RGh>DeFecl z6t8qNDBAV;H(9U>yBCV;r6G@9QoJ^)xKJKjV0@ISa(e2xky*emmreh$t=|9$;=wQ~ zu-W38rVQ`ixE^HBd4&Z?AW99>7{otAs#_vgaH_Q1Uh~0=LUKfV@m9{3DH8+qbJ!o9 zWjF9_ON>l6>DKDPNjz9Cky{?zDx(7NmC}VGlf4n%OV}*ryC%HHIsB?|SU@HxVlj)A z&LA*2#0n~I^nIt^P%K~^hUSOT{gk>5k2*eCdVN^TMx)Ovh$<~xki>&Ed3Hn4#~l`r zp(%WMuvU>S0&f(4H|78A_xUy5Y+{EkM+(}L|I*NO+aO=D@Pi7%K zcS&7nm)rf$g;&@0>|B2J=TM*VW#-d!vZbCm-Vx&x(Ir%@>fF`XU(q47GVI@HA-o@l zpfrv&kYDhWb2Rn?eZ20f2{AQy+`uq>>-mUvxKq&`@=}=|malTZ6zBb9Y*X;uRmDJ% z!#5wPO)S!~tm{xfMV7fLcrEQK^R9neNe~R|K>oyt?Sm!Kd-95f>Rn?NH zQCq~#x@X{QY7lS)x#7yIQ;!h1?QvNLp!mG|wvM|e!nqH>LLmFFr#B#hErGaxi3sbr ziX4w54idlyC%s>q=lb{P)pwFzpKd8r!18EJ#Llw3QIEu$NrC_fRdESD-nBvC?j(Sf zhsAI<3#1NlfJJR-L&P4ZEsX_d6~~@EO}6IkhrTo0zXk`zLJT-_P(e0cR_roSVZkec zImAJmH!{Z#uo1;V#AJxY&m|6D`8BAqHxOOfrX@nWoy8AT062bd z5iHbmiGz8!%T3n9T7G%~*d>C@q`C|wCj^k4DGJ@2A#cNUK+zw^X`rULpC(%b><<}W z;$n9v=s-#-$f0o`{SGSsn-=*z2Vp)rz&)M;299IPfG!Uw>!>b+&n|*2?{a?FTEm(V zeIVL-t|XlHs?N z`2*f_txR>+ISt#!Y49J2-tGWUJn9vwb(WFs(*?kY+Y*SD*C+<5k{uu$X|RwxdN=EF z6==}S0KrG)D-FCNTSaYZ$GfTn_aJt|z{R;7_-F?G)s#litvjiY6*TBI%o)IvCOH^b zW)G+fWsjLpU%$1#^aA>x`Jw_7?#JMhS_ZJyH>!@=Km?SF(gEdcOil!V#@4&a@-DPF z&`0{~8~zdSy7XP-5FknqDfi|Yl=JK&`AgBOcR%)i(pyS9fxDCmcs-`$Fq#|N93 zDr>>XN)*jWdhRC30Ll4grMtv4>2hD93`8%+6%5}oxI7E|Bp>ZP#H^ma=4ZX1fjSm@ z*BZVLZI815Kznc*JBMWllCS=o+ky;q@!T?#2L9|1)J)u^mE1>f3Ox34Xz&#)5cwxz z{q!~I>EgN+fE(4J9r;E)$;M7cBt92rd?zAXxbF8JnOASGazz-P+#*-r3YFGUQ{4e) zOfZmy3BH?}l1j4Ri6LSRA6OUypHtpP?yKNKoC7$o!9UX=<;B?l(v3c&gm}sw@NCVS{VpTAH=^`dxEOh*jXWA&>?|Jr)_O9C>BqL# zU~I3amS~zR(PpFwz;9)W2UM?KTzA0%Qbq*>1c;ADCndN=J~Tq+tJcNAv}?Lssi=Z?!_sAbp{jT8}T*Xq@QW-Mx*7r=Kekaz?@yEOKm&Y6l7|a7Re@ zM*L$HtzJ69X%fU`;A1LP)Alo>ra}1}k+u)GMn*Dzo?v4s`B}GiQ#$iB=I|lBfEobI z(~zOBl*ZdJ_Yxu|it+)2Rt#Yq-Q^D_x4CtIAzsQX~{)44>TCqi_{X&YVLu2 zyYYXLE~$#9h|@J?BW8tnW|dYHb0X{UZuDQaK{X>#wr<&qt>gXPf{ZOkKw`Iv>Evjx zusG0KDrTh{xwsG@!#i0i93Kq#2tu8_OH?Yh5-S7TeJNw45 z=8GkS?DV?dw<+(P@c#~zOoNPJuCN744W0wZ569Ajmi(?zG)_{JpN<1%NZZdkLK3gB ztWE)l=vf7(M)mwp0(`PwfMtBN4R-X;0LcFXGGGF>01Q58AJj~7CP-v7;t3nV#@Tn^ zyu+B{S2Xb|gjsz0R^;OmYooh}*6~!#hz3yyryQav1k+?00s5%4sj*b?BdR2#ZerLv z)o=90Jv2@+U6BSHN(qxq4v2&GGW`>jEtDjpD)mOS1q*1;u?sD;;q3q6W2QXAh*Jqa z5NmuP%bw)0K1RBHKtOIbQ()UmF%{ujTei}F5XgldQ;%H9DKc7Zuk$i98m9$&mvO7` zM+k!>v0iXoMq`h@RPvzySW$Hy^Q%*b&;QP(KTpgU@LkG|$i7kc`^&u|=M*PfpO`|$ zH{{>R&!yd#VSjxAaP}qut-5d$YFLLoKGNe|6U10+Fd1T|>xVq{Bh7R>b2Y7m`QsXH|+0nUYC6JCU@LryV+K z!g$6u>{Q2P5?U^Do;vm>LCMJIlmwSzou|q7R9}hr4$UwS20+UCpq5Ar)o2kg}VYW(W$Dshd+VTgsg+Ie?l z_#>PES^5|AcNGZ)@;V4E&f1fX>kI8k+rGoa(5kC)%9}DSsU%9WJU|jh2#(#UM_QiK zi2~2M8THfMzpxg-=FrCCaVF35Zx`A$_%{liFdsLMrd-pLJy|Fl!_qma^}HaT{TCH| z`Qo}t#tKReK_U7q&O}H%=c(_$EM*MQ;MQ;%Ws_l72A15k;cW!o^{#X98Itb+wciN^D))r?w=&OwSL z@$N>ZY~csGWhm#1I%%jenHsPhBpR!;pNn72I->Nifeg zUed!F_a`X(n4ANX4OXEFcPnAH+T>Z6d(m!G#eYy;{Jd{aJgifcgDR@ad07+?U~Vlx zTdBO&`rXLs=}DDm*K1Z8_l!L_*w`|88OAuan)wdq@p2skwVpj|5+vKO5ls`KY>iCA z#%jEL&6g(c$z){VGZ+NPN6a>(18&L)o*di#bpChzsRizo>*Bt{224#2%#`UCIw4eU zJD}bWVI9MMazo&RI6&>}-4RuEyz2U{1>H~T3JXve4p6bU`K8^OLP@uYE7 z(pb1}-K2W&*3`2a_0#?7GBQ+PHNb5vNMikYNR#E&yTgWeG_aSc)2Z}g=er+6bxg)v z|R$5YJCkaP#FTTP0nnc!pQv7}N7WVTX%B;8IZ5a6BwkE4ADc?>E-IUQ(BBuwPcyG}x*nv6~=w>5BOpckF) zZ=Jh!Qrw1dqklZ&>Yudh9_)3t##wCQ>sgmNK3pPO;vwurX=>&B&s6@SkUGOat5|hR z^}_l$Vj%rh!jGWZaMO?&o$3vHl6NC$lxX0()~Gd*ag~X6DrZ_dSnZ0ejJf{0rsW>c zl?({7uYP@|*%URj2*pr<3O)=jRf|HtPK=}c@GBzWQ$GcKgpmumkBAk4*goq0)q;o%9IPaY_I zRwf6L6ZY!{c|^gtVU+7YNipcm1$lMmFwlcHTX%AySB8_VCSxJlC{Z(zI&G#_Pt5|7y32L*+ zW8VWFyt!}E1>EF+An5sO4>O5I$*2YaycQ32xel}%H~aVG-JS!v%v;800jJFFeSI{T z3t0L`FN<$w3HV>gnC~PnZX^Y4?k5RL!AjkoEymRm9$bQ4+@>L*u z>hgLEgLC9P6DZf9Da{bYo|JJOju_ z&$C!;073QI^3`Jn5jD7G5>TK%QY}`?Iw&5_TrZbFBVH((25N8*rleu{Ym4{4M$pH7 zK~FZY#zd8^h-X2m3(`URRS&=4=cJog`*SftDiz*Q*ftpS$~rvzlmh@NH2uR42=e23 zdy21&qY7idz~6T`8?0+A?sH-OS${B1QMT;4p|rxZS@l3?pz~Ov+gE_(@OkyFRB}!5 z<@$(GW+yRFa5?(zZ^1B1NyQ#@2C*84T?ETLY&()y`kU=J4W>5v6=etH_qB=|_J2q& zG`9Dx61ZuOzIGS|Z8xE++{XKlI;4NnKSgW<|9si@EF=|s0wpa^JYSM0!!sh2gxRA7 zT7lrwBSgqG&g!CkYjjRM20k9Qw1;CG35x*6yPLo^HwUUdJ#_fRqr{|`Sl=*+tt0nf z{s&m@@#%Db1v3+NKsI8`1k@ATKSwD)viO!*=Dl?9>unLvk_5W~Q2nrwDIMVv42XVJ zkhYevQnW+FbFpR}63bEL7kNm~=#Y918ZO(uf6;QmDyod6Isf_a;+9-I+(TUjh;ved zL)^J=iVDU6kw{x$XxFeM?25Mi{|Ead;ysA8^JGFGUcp*{D^bl@UdJ`C)+$J0ZO9(3 zBj^g|dWlQ)R^FT1wJH^ViMD%{VA(Ezx(n^+-sIn$I{eNmwYJo(b)Jm z%Nfp&9q-gxNT_o|cIO5H8d&ZSW2hd;{ID=Rm`NgrG(-!O?@*JOn?hmTJFLtsP5D4P zZB*K3ILZ?P05v_pbc0cwG=a=N)m|xp{AFjoW(Pi$8KgwRL?^BGw(9Y*(E{90+B^7w5xnR_8R zLeN#s?g!ruJa@%q2G{gX1ve}e=BU%9B=jp?2!(1+Z-VI{)fWFH=#DcF`TSy1;l~*w z%4#&9g|?&m`CB{#@H6k7MwT{sk^l1;)FTh-2oy#(>%~ZPBRdJX7@R-13hP=<*L>yj zkWA3}yAdJu>@w_1mGOk{vCqsy4fiOMKpCmt@#3Lddi#*2)(94&n8g~nwV1DUJq8v>ewk#yylJvO|lpC6u zn{h}iM5{6$=9g5lVZf}v2#V>@2JAHmopDx)bf>o=0l?#Cpl&v&ow_{tf+BL$T0IVg;!GSLJK^O#w#PXibSl9Gkg4&dqp1D_K z)~@v$Pc~d_uTpF*)Xl<_D)B_tcqzIdHndlK51{jIeQi4@Wu>hOko`eb@vu=SNe$={ zRCGgzuVn)xs{(tIE7?S#b2Mqz?3i-uc8=)@Ns36G) zFN~qLwn!{)4REoK4^@Pzn0Dpe?uTlylJ4X`^+Ou&KVX|{G-sf9dwfC%8bsm)?zN>( zyA@x3=yU{(ge6c7T`Gi-p8qs|G6AZcvT@_9UE&RA|FG^mCDH--j~)&&H_fP_K~Myi z_t{^MqUJbURr#@*c8jr*rzCPy1$ggsK5p-U;imV**MVotyW7C@SUT!G8<_cjjVDC) z9M7T5bDWSua`auY<%5o%ok(et%ZrVxACg5mbAD)n7HI(umsZ85QU{X!c*Qc!Xs5TRhO1hr(qxcg7B9Hw@4zb)m*5 z!)cM}M9XDeXfAba1Ok3LK&=G4Gxq>EI1!fxP}jV#c<`!1k*--qP^$)jbw7biT5dq3 z^TO~NuxXUF-vE^*;JX;S#8SP`C=B^TmG6Mf6tXuzB8`ig0pXPwHQ4^|@;ja(PjO8u| za#5QX)Hwxm7O0vw8UQ5DOA1^ZTA$TIKQ2-KgkGzNCVBSV&-2;_GwW=33fj+1vtI*L zBtRYy2xE8I+5ngxtw@Bts(8xEK+KH+VsRw6%xKWOiCRJiw7UZQ)ZmKQZv6E(7of*` z47g=IMm0Bnnn7pddtFUMrqN#8xPy8)tS(CRTsYEoKmPGIoD9{6dFrHM9mzkZU#5e6 z0D;f3`hv}r`Tno@z*f=x=b;%eAK&);Yd2pWKync410vfw!f`z&pFS|=^|!U`02e?X zFap^E$q#7<2*@wH&mw7rkC?u{H%gMQUQs#{Pmw*q82ea!75G^z4gx7Dhg&R1=F7(g z#?bJ@BXvPVmw_pL2S|1HFr&YZ|9DgT8Rkz-zH4egZH})C+v3$UHo_tqL_Riq4S-`^ zb&O@}hnf}GqaRfOdE|LLl-o1_k?w*4pa__d$_p{^rMzq4R{GqMztH`$Ia0I%G#G}c z!qEd43x=!<0UminLCCi|@AgdYPjF@bcs|Pe@+U|YnuR*G03}fikQaW4_y!N8D?OuE zD6;^7k47>~8-0X#OGa_hhoKy4C~V0+5AiLwSqt>0r>?1gA$tL%hC6x*AYAH<7Qp!o z< zIrf4)AZzajN-2vxEE#314d_uPkkj?3%;9L2l5Hc`TH11m+}M^w0<$7d7EAw+RV64L z`BOwOQyZKbv}0WvvmoDiuw>dm3V1$2M5CupkAR2OD8Z()*3GMcRg)E4uzuMjWZ*@e zV63q9xdGYIn%|sZrwc^T24S9Z+T;gNwzHQKAGCrYMoqM*uq4Z?u}hSohH&L$kH5yaRsg(y)sqQt}>b<@Dwetxyg|69!HU2=@B;hpw z5x1&sH4gR*^OvOWgr{((Ct$*Bj0~UKQZQNJoUP8sRdu%M-#1jjdSW3S2N7eyluVOA zuXE4DZ5sjk_&~!C&u8;=5XD#)2x)gyK$Ky>k(^v?_HYD*Ki>Q$v8MiP+oz27;I?%F} zyL)FHf<+z@QO;X~WQ@17zwc=dSZxtYyy>;TIp*^7QGh0UDhK3hSFFPit99KBLpb^cfSQ9+#F7Csg9z|<8#!DV zmsnKNxrOL9wVz;*WDJT97jW(Nri2N6JNA^w*&VDH6e0+LyIUDHe6N`#^}@!x&%j$U z7bUmG){-Vn{fjHD#IM{9X|;f0$KqljY#uXJEu(eO}tdiSn-tBf`=Putn< zojAdREtW%qSWq(gees`-hLS@+&Kcs(ZvX1)xz@cEhjSt8pDOkvyNn4aX8Xg_f4 z{=@!+*#)3L7hPg-@9NT1dz~SU>&NRQYy^UhgV_jN>0^hFHnb={_BUV>Kh8IW}66xRJ)Dg~>hDy@1L{81>1qcOtrZ z;<1N%;Nb<}%p6Kfz=yK4hQI2u^!<6009WqS>?<32K~-*{rTI43=AIzyrnt}0?oWr! zgblN;9f3}K7v=~t8v)li6dTEFTZ`ra>(*uUVWs>iO7eP4I7MSH{n7M&s-Ggoez>M& z?73vrA$;}3Afvt@6Y32c>xPRtrC@NF`wnQ=H;eOffshj-IZ6TMDSdk6TE5zBsRdbjA$c z9{CV&j(iO}DH?DPcAEC&9E%Nu_G`Rzpxb(Cdntp&Ibn&Q=yXw+tWx_8m=U($EPkD< zwnYsVMrArTHAbPb|2tPYELU;M61%8+{aE#Fi`;>`nUNkN?j`YbS99wuse-FyXTu9K zXSEX~Mo!!d*iw-mI8_>q(>s9+73L?cKz+7hHASt(RvRMn1g1p&7&#nrM3I{88l(8Z z1Xk}m$7oGEC}6gwQew6u(Jrlgww`CmUVeVzqI(^Yt-nQc@zzpPq`%GH)lH+^*Yd}z z6|0TeA@;Yxq>Crx`^Jbl9%QXqm@_pg3ZYmXj_P)CDQ`Z%!f)Ut{vxCp^`YgNXRYdl zSrJ!vZP|o!6X7fe^I^KG1gcK>lRchpEoq|}vSa@AGl_XLUH-(U}TR-fhFy(ri*R}4;n0P~|2eNOXz=<$nn^QN{RpxFlaFhJS zXa*gyhqh!WmD^smDmIweBxB+fmE5!p&W)PeZlo%scTwdEF-RVENBEzx9WTH1Tk{$N zqUSGDNZVl4EOVN$rfFaRSLqRdakm_I=B@OK0f>iYA>Gd68-?+NteFi7;Poh`W8MUV ziNRQ^(<%GkwFED&R7;d7-pkH6GW<;&YPzb^N>jw8LO1?oi{^q{t1pbk>(^FquX0c3 z)!bFbjU+F32}^Hy^m6@DEA?={)>qfpi>=a6Q0(KoJFKkKaRT0tY>>GMp zou`j$+#7_xa9>a%Casij?fb`x-?lu+I04l%u?hX?o+U931qyyoDp6s>%$oV2bh(>HOCMU2L{58@7ZVH*ga63jzgsLsF4VYbG`^Qf&zv3GflD+fzG z5i_`;0yznD#JVH94u~8?pK_G9#d>U5x&^ndG;0Jo-7Bw%XE@t_dTfuiB-m+!(h~aP z&XUL)q$GIzz2jq|FQ+_az%Xc&2bGHW?g(!Rei*ux_^ju!b$ft|-`_J;5lD6n<9#eH z%VV~;^X)txL?s3-1VwB^xwA3cyS^xyW;?r=sB5b1Sh{MQ>#-4Qs@M00 zwlhOW16$UrQ2fN{R z*W~!I%N4Kn!^eH`9IGK>Zi|^(LWJs$Dha9lY<77``4(CDLm{+^<@_7(-^f+Gmg04M zZA{H;gS6`RSuA=yqGbqG@y)A!5#w~1hJ?1YUj9ci7LJ`)zAKKXnV$9lO1^Tl2Vn*ZO?}bIZXlVb5Pb z%BbdbzR^vBADu6-9n(&B`$Tsc`!-ptFT_A4@(H5>I5owS=Zsy$_2R8#z6!#Ns?RJ$ zxnH8EP?Vo_Z&;&Cf?ZAqq&sr<*PL9Jvw7(+)panG7k(&RuC6Y0SfP8@p-~{l&!R3j zbZ$b;uKzrz&iLjskJ})MD&D>$Sy|9tQM#zkmie&Mt1#E0hpz|G2)DGrzo+XdZce+k zkJO@^c8K1Y#}yJk@9p}EJPg#la+2FEjrVbA@aXfaMy~LO=nm8;m003d=u0=q0!-|! zEoaqZ9b&KO&PBX0r= zqfDqvIct%F%^4i;=#@yFpp$KL#2x#Eg`U-23URN+j{hl`!^^x#H!~N)Z9?p zXm(WLKT5eQC*>8|wOw()l{y6RH) z@~v1l8#L!*AM0DaaO?_B=A5B4kpi#4gTR&Y_(3*`3$6P89eY^N` zIxx+dHxC(>3XD-w2;1dAeKWC&H~s?a+%^P+WJT6Co0^M%z3u+u5O)(xoN-J%T;vb4SCN9?(A$v-E|51oA9Ug z!mRx=wuvK@JMA#cK5Chp_tg`Jr9&6tEP00m0>58%G>|`A>K>p{eK9qET$S26qPE)j zak+-}l${qYQ!Q7oVLgsYVsKU$w;y2Nrk#H4=L=tBoHrztxDLjbx6xQ>DlH@H;_HgZ z3eH(Kutl%mz*was=?h=<{i^&QxX>ihNn3BU^ahM!zJ@IZL51NK+FZiBqI7DG8XhLj6Hh>{RWKxc4R)AhO%*VM z%Z1lU@)=*o=Ou!WD6rzVr9&a6TljK`v&GMvLf35sWs@eXh_5>i*+f2Gk_Yimz9q-SZ4zCAm z#}$?<7dS>ri!=%Bdzksq;}tLR%tr{y`G8S^MIo=G_^&tGMiskM?L(_%-6HVd9$3L%biWXoJGs8poM4RKGE+bxwYmv}LgPINm+>^~6`50F=$J zKsQE;^$lFF(VVJjS4_OViC zWv_6I78%)FR#wPf;o#Uwk&Kg3R5l%CZxTX@?7bcP*sj-GpU?OE`~9x#`jZ>yyvOVH zd_Cv=F_r#Y1HLJ4Ly&rJEhsO+o@n~wZ%JJ0E6vA3?_611-YKWE5s1ZJK2%&|`)&TD zi0o4GiElhr=zn>KvxQ5&e^#Ow?1ILLr>9BZ>%BU&wN)hz zLi$=Dr-oB|-sBuOSur)EFps$YipS#KNQ5sQuM7k1O2?$t8#t9$U-dcV$J4Ksko!q0 zn=TwRr9>hEW$kniu8FBcA_87i=Nx?-f8@n$Z2||~Xz-EEqm!#aT zX(q3HbDwoY$)aI8ap&3=>M`%R*Ebput!^k`_AP6wr8(g1-5VC_>}0I3Z=;0U;@wM` zTt5r@ykPAd*S^c6p18`{%&akuW8W;b6_O*ktbmo6bLa%%>f#=k_ix3gc^h!+Yp}HE zIirP9R+@ZxaV2tsN6J^%T5LLEgoyl*xu$~ize#-u8e-B7@Z#a2TTQ#(>Rg>|_d2@b ztk#ETPC2q@-y|7XMAIg>Y_FFt><^hY+!|R4yJIa;@@D6W+3sP7HTffv>kP6xz0>qJ z2-@&3>fWuZX=3Q((u{g0{?M;LhJ`)a+en4i`rm0TuKFO$DLOYOQVJgdk=x&~$5cVCFxTNS^aN)3;= zk#c>F2TdMycUx^!`oOj*E*nd6g>}*2=J*+J{Z}BsyA={HtJ!`~bof*HcXmY)KZ3#K zlCaOd&jmy_MM<|aVV1cMsn(hxf}27#UB zHbd0Y&rOOU8W8Xc;sa;tNw_5_!W6SkJbHg1mB}m&TGsie+WWa@ST_i~a1optzmy-B zwV#xjeIDw*$6C^(9ysQtul?tMkMy*r&0#~dRCn&pFZw4sPv7aEpe>|cGg|E0=t*hS zu)rc;Gmzg@zKpo0K-U}gFot^#_GfX?4NXb?lv5<^DwD#(o^0k@9Y>VirE9XULssFA z4L#u#oHxRKE+O7$bFC$ZpA;b8KYaR9^%7=$e%I0%M>7*4ZGP%sMxcBiZb`A<`|10| zR+2vYTrqhrUp(o$%XlKe3_W7KH+X5nI2)0(ZGC#pq8u35VZHFe`GRzC4yy>m-2g?XQhdBs*0v_E=(bfY@h@2iE^B0b297l`@BBE-oU6sDH-iW zvSnXOPy3Q1@y^ZBIqIC1I6p`4PhwB!L&vqtBHCH{=%Mo%ryHF#l7d{Hh@PzcUYfLU z-)EHS^2(&la|3;9w>h`;>1Shi`Cp;26du^RCTy&g*U@~u`99)&pF-k(vKJ5ggWq!K zI}bSd6Fncuk=r#_OPy18%hd4)k`=w7@#rl-o-eO{o`bu4=UDDnqvPLpda9CUGow9I zz4ih?Z^?+1;MT@icu0#g>%*BhxT~`Bl3Ar1*}|r0OtKXo(3K{|qRu)7#F?I$3}1Y& z$x`a1i?&rC5PaM=Lq1;CWI5aTb+M$+y63l$Z>i4QeL-ZBv1~QVZp=?S7E$Rviucla zs;d+7@%oE|c}ce@U5mX@#U_`)@Z!g<+qG3a4|tj{b6l7waOqHdedN-|*O!nKXB)7P z5pHyiWObdQICXilDZI*EV}&wE<B`v{CN_3B)|j-@!%y>i!KdxG~+4*yv!@J zjnsVC-YnF$9H;%6duu7?kY*<4l=5cjnR9;dZXd^L9+;EpzWS=KIf|5kfgRx||E(94 z9Fl+X7!kqSya-_V$}_BX?$XP(CkOUPn-TT1mC9YrV;8+xGzXJk$&J%WN}!&?#ejN( z8Kh-LwVD0F0&)AkN(j+ICQ@m_Wb}e8QnE)AuBgv#_i?7slEO?%Rd{x&(_`I#?9rR> zGJ{iz9=CKm=_>EBmoGa5rp(y7-dGh2t_WfUn8@MOcf_nEWEJACC?XCu?gPHW?j%z^ zEVvXuNPUL6v*EVdE0(~7^zXjs4h3$Y`6j9A(8h(K6ya}OfRrg+RM*#2`$U<%?Lq^(`4`M5J&?(3UKE>8n=E@mZsi9YK;}WbWHRl%rNn3<3qaV+7b_#El9i+MmW<7j zDl=1h@16<}1dK^g>^(EhWV>mc4F{}%Z;TgM!_VW_=nM3oC_gyu$2#PBR>JdPmodp}`acWdjj)EE4YmvCDfUr;(FECJlW!=J!^ix{VMt*W zT6d|3?dNmea_O|Z`m@zS$>-@cUUcC@*>TzV=0@)#e)k!q+s!%a={S6LMX%SyDLgX~ zjQa4W3X|(D1&+JAr8Vh?#LHc3SL{3*Drz#(Bxg^80xnsb%bzJjsnD@8!lCA!r1b32 zTUDO3B&J<9nAe&1d ziY=S2p#xuD^?G6rNN-DY1&mJBJ#FGbx8W}FkfTHm^<*l|wqjU$= zoz~*T{1xVgwQn)Hl<3z{eUI(7@fg=GJ!tAW5gT2>#`wBzg@WqlAUpeu!;~d9qWe@oeS|hj)o+QlF?F02Ye+rR(%&T|MKzV~Bj+`C^TGvLu8e!>(mN5kiwIe{W%YD7 zG%YmEao#=RQGBDff{<%g?Fvml$g6d|XScg{3}M3=z8Tk{nB2O9u1T`Mp@{q*$>- zpNJs>@2yZ(SfdbeRWx5VCsLKE-52TzyUF*hd6JmLO7b^_raFr^U%dv>5@kiT6Cu9S zvX0V;NnLoV7!cso@Hx#uUPpQpD(IQGX1addP*~P)+~~hx-cwxPFzdF~5tVa}btm!$ z$ya19vc2Fob=UjnPMg!usbUQ7_pWzJ48~WhT%*J-K2O1yxT;rI{XX*OO}ma6bweY3 zR*vUq=-nT@p@D}*ek2bjS^}pcc#Iz1{S@pLgg9gwmS?BO`(&zK7jS%HNxd*yRZiM4 z>2~mNtEPQvhWb}M$$XN0?ES|g_cs%XD|xEJNNFj4%n)c~bG$`y+e9!D(n=>LYX-%u zwx4EDFpAyV3_IF=c$Kq+M?$8q1G|BC+j^HH+lIQ9MQ8Lhs1w`3(Nn8YGZH?lPYOqWC4xOnHcfG&O8vK9W&-|NaWO&izb+H*u(F zMHj`-`t>XEpR7aFZY}GK^96d8I+$;ubLnL2WE6%ZJ=dz$gJhrzFX|OrC>76(KkT(X;v>&#MKF>5!MkJ>7`shxiJ}5FHN0p#?tJ2D`SD(c@AU@-4xJp zDth9p9`Vu+sf_1Y3>Dlf2KBg=&s{@tT&u}A?-KcflP*1lrnAv!zUdfN=fD%3>}Ye^ z&SfFd>qNa6VR7bb4C8UC$gkaaGj zL`=uiNr%X{@%7acc>$T$;C5-wKR?aQ5i6G4YxuV`?MFe<|{ z9?<`i=jCjSdAnM#TK`p|ZOkiJ_`KppUOFbX+O`AX?e!W(`AH^g-PaA27-!7NL-BeQh9!DDR_w9_8;ixUG%SsygFLNCHb%jmp+@M<{iSCK4ZZcgY@Jpz zh}fdknRVH3Qk=$*pQ`N(WAL+ru?01yDcxV|;#J&R%{N!wOvtDQ8omy))R8Gz zQnY#}RYBeHVB^ZM*B z=ukaNwDjtaxA%IZo8o$KY6@LjG9%rvf-Rqz+MnPexq6=>gO|SPnpXp!{76V}r5oi!8|T)V=WMxz-W4 zzX;SZ-F_Qy?mXtMezm?i6U9x;PDxtelAg85ugXoynt8*8b7N&j-xzdY;Ku5uNG)EE zlVAt51LxCTfuR$QRAuc(6*^ABhUkzO(WlgJTDQ8Y_~0o6ZXM_= z>wi#iNbYETEL}D->mO|Ova?%?aGd=ceSFW&B>yS>uy$+z?@^^M7g}wx-PI}-8J$&E z#%GQzqqwJxQysV4NOHKxr~g<;RQIe0G>_9i7_^=pVP)c6!(GJVlk>qE z&$q?SMl*)sP;FNR8V)GX*?8I8C7q!w<<}*uCpa1_RcnIIRqR#3ipUQ+){3d&gGCMp z?i@>%@A@g<BC*%V${#@1)ov+J10$|+D?7oUIC<4vzY zO|UFfcQ0UAnr#o@(_5RIUl79VXnF(MjL^t0F8(Ec+?n=5S2i9_;Ua~DTm+vNdr;|z zxWr&LpL2ggdV4Ln@w2~+I9l(V5sT`L9OsjGE?X07W#RYk)ZVA>7R7FM1pN7sXwRHbdE*sHx4&^G57%H_Ak)(#Fb!-NX=P5r^@^ zUG-#JB?}n4D^F9CF1l{0`kJqRsT}t(nq9`M%gPGQ52fgT{7xD-zgr1VR(k}+p&HZ~ zTzIY4mv#^nFS(;`2HC){jPaSwF8AeSm|&o&bm(=<96Kqs{SG&tvA`6I_W>a8DsZN< z^ZIc@^T!E+-lyx!6KTXb@quJF$niIY8V|kSpgr~2F1#kvYxO=|7%a}Z_h^Qhl=-DewI81v7?Qw{O2v zrh02(N`ag8TI(O06D*{$`#FFvV|oc+zH?{cmM_+vms( zQjIKIl0h^|%w+rmaJ1|J&|q5>T>3!v%It0PWR(9J<07nY#FL`VfiC@Ny>Go@BH?uc zLfQGTnet&@IxmUIhR&V)OC-uNeJYuwaeJxuyzhJZN!ysGFU+ItS-ps%x$M!+8W-Uk zl0iKZ+|@!IS^%5^y06S2D=e5@&1dPdDS<;CTexqTPt~7Nku7gE?vo9al)0|mBw6N) z3$vp9cCX$3arg1bgp&W`_CQw(Exqx+!_BzolcBOYtud;4qHQ$ii|c-2iybI+;@BDt zqk@{lmsKvB$I0{Dm}hCa{rE0Yl|i8rwnP8^Wz#+)8@>jQGA3XgD#9ZiU|Erc}?Pe+s2%!}1K%We8}6KU(TF|NkQB0sa|Wd-fc8O)lz zOk|H)zT9+SJi^0xQ=;{%Y}~C(*ySeiw&>-!x*_LS((ya7r>WZnd^?Avu!~Ghw!x$zLPke8Mm!UzJ!uF90`Wr}Vua^mq#g_lClOzvt?{q)MDV5j!)MVB{QX%j6o^uV>&$~)E{CtlmdY~?sqgwM&&4EHGW-qBv1&?tdpALMDEJSLZ1cYHso?odPGz z2&uPegf$y2(BOe?oQQdjy&n1Eww}lGK-cW)fsl?tIXe^FFgIQ|#Ecuw#or^)*hpt~ zk2snbd885+#GytZ;4C*kh*BkMDC9rNqQ6ADE#eOz|k={GR-ldePIfVaA&2y$=Q`+%s9=fr0d? z^z(1LEon~G_hgsVowm=NO2Ei_W!1^Gdv`SGJIcdtv)WhB7Z^6nIEq!O@9D^gUy1h5 zrbK+U=0l$uSom?eZ{uWMzWyCvX~emBwycfuAHUine#97xt6Q-fU>xqR4Stq zIm1!kUOI~f?F~qOs<+=etz6ZmX~gtdL(M2k_!5LaO;deM9sBXrpryEm$kL=t`1ZPH zPiI~ae`{8k?4kR{=?bg)ahwpRBs353F(jZqyXyeCR6 z>TrTR#_0=V&teH%9`+^lTtZ1UhI~YP6ISi=1svetlJT=W!ejc4g&*(U)u1NHk9X$F z3=zIGiHawRCub`3U8`(ka27H$zm;{NN{q;yt?^y39$@2jIlmMQ>BxF`4(1IgWR>H@ z1Vv?+1nEhI@LtSKH4VUWv+E(EiS;~|^quU)q7 z84w&=bHf~h*)GpR#P;p%^9|+R&9~|KrO^tKezEK>ftOT_!s$81(M+DVi`*_%4ph)- zS_WCjr0SkZJn}dmKijEO=ZNa0Nn8+=wDB2$D{!c+d$Ly#YKhz$aG#N)5X+CX5i2Cg~RxP1t(9RFKc*lrCLotWGpykvl1wgIK zdv5GI={*exQ*es7)A(u7(s2p&J9YTWQO>anTQmpCS~7!{XKV1e35i>v0XQ6LPnIQ* zIzIL57Tu6Q`)~KEWHf{j^6+~C;i?QE-M~vtJCp$)$=C6KnR!S=38Gnp8=mm6>@a7E zHEamRPZ;n9$lfr}1v}r()s_o}gYKYf0Gszt=O3^ibAkG82H=5k`=3B`9e_%hl??~? zF1if}2H2Y(LgvRdY3@3?fu|=B_%?n4DD5nOu|-duG3<0bb;d{*XhdfWmD&(yDKJ$& zo|K!U<71B%S5<#^n}z@3x`A@kU2&!iO-U2uOi@)jiVbp&i>dc~HgX1vqJwZqgIGh*RDQy4t4PkLSCDb79j;QM{sg$yn)xUXU3p(pKScV#FRZ?kA2L!)&e8U zO!t#&L@n}PQExQi}IJY#sOfbRvk=xKGH~a1ftX$q~7~*zcK?06B0co0l|GlonNG(#=B3TLAyXx8ozl^ zw6SC;r=8@0#mV)1&qmZy^fw%Jc$SyZj1Q59)C(Q$6+xv^c+#Et+IF`FQMYP8SkX)y z-BkzWt9&g>S8um^^4x#(LR(tU^~s;IkM^stbsBD+MSEb9^Vw9Ufo%R*Zf-P6aYacj zgpk~W|8*|YXoe!8u1MPM-S}T~AN!6W5;MdWNu0f|%E9(AFLqG9b_A4yWIy^y!e4zG z(pJrpEJveBdddf*A>S1&W~Pc0Z`Ei`DZ_*Q&ach-0@9#gEnqS}m`bpdDy)2;cyysbGqB*3AH`@H&F+Fu6t3)Q(Gs z!AO3kxwJCuf=2wW3m5SujJzg8MM00aA;uy3<}0rSy14oeHAX(0-W`WlRd(zs4YnJ> zaE>3p8M7WJ_prjKwyER>AL1@#zwj|5jep|@lrILrT!^j~0@QS4 zkd(L|0M5yCZNqvx^aLowr4}junEKUo)vJQoabEs*!*#(G86rOuf<=4vH>V9@W52w* z2+5eiO+J92mv-G4Yzjx1nbL+Q=#u z8P*$>3QkPb31{h}ldbLBtbUgy>rPLqK$fWN6il7ef=+a4-t5!2_607zw8$egG(ho0 z*6vca#fxpiTISA0s|oM=Q%chYqnoZ=<0qh6?^lf z`du6aSfJso)qTw=El;~)Qnv9j`LF2~tZ0g^|Ac*c{(PPu=G5al--E`Q z?B03JreFbd+MF05V$LYQ+Nh0K>ebseIIz4r#euKtth=sAjFLJI!Bq(q{$x243 zLqJH=0}24C6I&+Qa{d4Tamvd*-?RmL3~VNe5!>c-QN!Xt53z}cP7&AmIx1DRArAWobu`PP^$*$)$t@MYyvEcg zoJ89Kq#6`Y@{CNC9N9pnsZL)j=0K5HE2p$`gG6SIcp8_nFUyJEIKG2cy)3z@En1MP-Zd9U604_h$2}N{He^=_+0f8JHmloB*FlW*aAyF z4&r6kT-PWE3aeoKU+UyhNq=a6@}7AZG=nZkR~?4n27Sp-CP}6e6zrifE|!^gTLRgp zt@~<{CN_1fM0TdP;~wq+_*k=dc|UOQiSB3Ozf@7r#@|1cHrqf_y~QeS!hSG32z)nc z0$3`kNiuKc=Q5)NTz~CHklpqx^+UU%`y^r#-LQuAA6h|o`0`iAJ?zsJKp3~9o29sZ zH4N1|@$>-|44&Sw&@PhLYs(4BJQIZ*Gw#6%zhJk}DHLL*Pt*X#k%rVF^qS)R1YVh^ z9?AnfM)=mxRN}PvRglhq z%6P4nN$|KkX9q2$I~H6cMC%h|-RAE9?!$t)8CMHQjv_R2%aVSg;sdoKBv^F_X(}8M zIbxWz$me+_hz=n^!!%E{TMrUf2c+W~jC$E6>pcljsS6b^20Z^+xfX$U#9gqyBOKHl z)!LtRx@dkb1G@5cudpBAh)}-O)nEa*Ubs~mbgmdh!70ax6$`~(r48qi^rjb8cxf9P zO&i@wgiM}{!Ts8(@l49}^@=B6jD2({ni#%;q|n(FGa!{g0Qbu=%~NK-cwT(sSmjx1 z8dFuYPiOnE4VnVC*!63^;zuAWsbF2i%={}0F9*T84B&Kq6~;RSgMslDRWhHxyiADO zK=N`m#r|ElpjVNYYYo;-tpMzJ+SXT}9&z&_Ast>3r&Y7 zkm~}!X7V&gn;*RhrpWJKs|_Pk%1cO4Q-6lXyj3(}87tB1U2y%;r9>fR>G3 zVue=X-#NxtB!-YShu$|YR&RqLneITJ7AlPTtk*7``8QFaUbhzA`J89eB1DK9f;gH(RUNc|7Ys5w~ z(NpZP%wLA7smaWvE#>c3-xH{8Ho!P6?y{cma+L^tW|XUu74|t;UFE{btXPEk#SmCn z6!0Q$ESk!4kOaBMlRYmcB{O%5cI-e0P?tfIef|J$~wq%djj& zEM@#1YF@JIz{8{zfY>L0?WlO)i+PhHLf3Uj%tI0{`)5j;pL?|-HMzD_a!4njIU4^V zUSxjqn+xGERAe6Vxm^C*BjqYj(48H)u-1e~V>P{{+bp;VnkoeUBcxNI2<8g?HS}u# zS@Hj0qpt)qYo>w6?uH=m3ebTln(gws{|d&!{CpDYx2)?{dd9_6#nf%6Y&=Sl!7Ez^n}51tnbPGyklSXowIO*9t?-p zfYT0WObh}zCOah|#Po;;G8{wA5mb=%f&NSfKs(zZ`2gK#_lV-X_>3xk$f)q9@=me3 zu7TNaDaeI%1nLXmW>o&8$_Cvs(4hk_x>+J)b=aY2E{68cmz&^e0SWMUWlT;J-l-rG zbup6Wx-~HLsgRhf>r6Wgj5Auu1Bnq}_@C(Hs4-s$(?mi(UX*`ohB0brvwLIy-%tFf z1BQ?0uXY-L{5pG8U*L@*Q9M(D%b)k)p>~1^R?6r|FDuVIS#cnqYFP3(0^*xNfD%7= zb9@ANjNmB|Mx5?YgTds@f}-FDf@LeAk@)Bj=+P9hKW}T%gG;ik;Ys_2 zRvj;YMH+j2rl~t{>eTq8Ae2O*z$pr-WX-jIm9@oH9ZZEfG4~m5Qh4HuxSUUWbo`Go zt45Wad$;^o#wxmXp82-u1kju~=?yA&Z$9F8uF>N2?bTd!hTa#G_utX%@aI3enK5&1 zJ&wmeu#UK}?JpS4@&LzE!QB9x=`rl%PSf^Cqo*OWas?4q9r693jS-B$v_q?1JPV*a zAemIabx}N9(7^WQ_yY}IQU8N&GfvEeeotcI3;jgCHS8$k@8JV;e~0DNy6?Ly9+tc? zlEB&%TmZ(}ERHkIf56B)Z$U{+fAXe*9wzu3D=nNKD5yOK#=P=)M|bZn;9TSV{Yr?? z2d3}-%yp$e%C>p$gs5Z^PQgeW_`aE|S{<8ATH_^jN2i(UhB@kGmpKRqV`)By&pV^V zx&|(v40!OpT|Mc3%Tq^F_bH#o-X(nYY6jd#Av>Jmru87X+>u$S4Ynp0n3njz`oUzB zLz{Eu!4Cw=MjpjJ*c=O2@O7AegKmNcR)=~xcv^N0eF^xIzlKY8Ouy0ksH5$kY00l9 zouf!8ewB^B1|w*fh`;>1UC7|xpMJSN+T{5B2dj5ueBk6~6Q=u^@e6D8TB!7)yPSJ@ zOcvo#I)92$tbfGvT6yODxa|e@E$3!-5&MB>H5G1H;>CUEbp0wuFzxvD++?=u9p7@|o5o@ZZBYI7J^Fu13vO zGS*JG41dej(&~6d@gn_~_39BTTz3s)T^|{}KC7*wX29Bq*=%FS#{o?F6R?nv zFO;<{0hP(f{B@7;?}?6Lha7x!;bBV0--{{)UpB3jSy(@4(kf1Eh+gEnN2_aAIP)M* zzxE*K!?pF&nRYAvri8*0AX*>}3Dud8oDGkIMfBH%@2!;f7_qJaK|Q=PYY5=I%OjPg z574qQ^h2GAqtU0pP5qykt$%GLr#)(1*=w|JY08uxK6$cMq}Su?pm^Qiw@q7S zPb!J82w0Ax^scYFp@XJCm)jPS(m4j}A6QHUPO>x0k08k#VxYaa+!bI_`P(q=xwBF8 zO7xVq2NQ|FNqB8E29e#?jMddeUt_(PWKu^X$bM=i(LkV_d$rVcoWO`cx3&=uU?zn6V z&vRu^*zV}3miiYSplj~2`o{|381iD6r3PZQE(JhB*dQ$39dYX!dLwK(vWHJ+WCjKn z>mIzl)iLI`_2744TEGFoG*pcOHMfC6(>niFX8_Ny0uaPJ;M(qXOJOUlw84=AX6S8z ztY9%TQV6199=N?*W%H^l{5&%M$90wDaOKw z8NrN@DC(%FD_>CEP%8+&E8R=$0#c{n2%5^4^PdSz0Zw5#6mk8!?X}TD=Li5rz=8b(%;w!V8+<^%#b!f2>97?QHCgiXlib^cW^WGXR5V`Kqleiv+Kl9o5 zC1inTKbnm5+2?IuM5;P$A_Zv*W>-ogfGt>bC6WGtH=(x|*GnB|cH9B7T`DdACIi~#R^4lTkkool+D}M1gew@>_m87qW8l8qY zE^qUS{4@C<>6L|tgvqS)l25wB)3co?6XOOSkK#yhP*0%e zK%yAimkldj-_!7FHqZVhX15^pPAhANV?}Rx-t^SFr=?w}kX~b6a}Sg9VE8fS+L1F* zTW{N~qA@u)<=2li$5?%{9WJ#>uUp%Qh18&0t9(Xf74ylvPrfnIhX>c#?g(h`o+(9rpkvg*F?4TkLO}?fxtZ zM&QgKeLj~~aEv;k{Wc@=jjKd~f7BcalE77&`rD1M%40<+xodf)DYPO|yhq(?UMG9* z)`~jG$2GkU{RL*N$7Vgd`53oZN}d&Vd(29rh>BC^OFp!$ZfI8i{b9Pig%+`Je19*+ z#uYuu@kIaa=={~w(ABYbz9AI6AR|tsd#;thDb+Rk0x@b(iZj{jR+i^Mj{ERg9PMW=H(i$__ zU^+0%VAy+ndAQQAm=UCjfwva|62ln;FT3d%KXLD#-tUyfiW(L5% zD7_-`q$1S}WKc51+(4ji)H5IblA|+db`)z+^L^K0jN-^DvF2fMjX7>evmjqSKqhqe z?icUAP3_Oio12Qh9>ZTvYfHJXvQJV@n5;5Jt3oQtS%~IA0i2^+LO)Xt>eq+3_HPVP zAu7O=A9X7O$N7IwhGqsR8XX1lwK`=BV@8HR&e;}Zp=&_0(W8-=2aki0FmiF#sJ7k1 z*?=_~+3`|@57{4ZUrVCyVM0{i_fbKElY<;(?LJn!dt-h-L@#0OeKF2%mV~6S;~=WD zcs3l9I`=(!dd(CPUwD*nAo50PdIk_mAYm@(#7hI}ZPx^@^>u;7hm*R@&MOhSK2EUm zP|fmZ2aI_0%24H~M}fYzFUE;XdHvhGYr41es2ycGkLhSa-nMa%eh^i63Ez-g#pEif z%~0YZl>@F-WDTp>0o=iSATNNi>0yyt%udkEgLnH;O9SoW{1{d_S^CkWSB;w>(`p;T zDCW_Y2P6Xo@B%@tXRY)ns1UtK^V{rL^Sz&w>KbXNb9eHD1+xRj8^tWc*6SzJnqT%Mfs8wZZ1afeXXa57H!mePQR2 z%mn3{2HTZ-iggfhOUBne?w~vb3I05QcImD<1;-Jg+bXGYFpG>&1sNwjm8~VluAdtc zF9Ttrlj!627u5LTjVBQ9zc)h0amwa|^)7>jCK1 z3RKHmwodDSq|t8P2f52O2FWJ_c?^CKFfcnB>>`&|zT=`dsdT@`~f6FqP?{{QWm@E!U8BDqr6kp&;HQ!%KcNijJ`eQQOnIu>a30oPk z|Gd?nc38)JP8#CTKs5uX*UTPZg@oQp60Jfl@4K2zt|iF3FSf> z+<9!&2hjEHJ?g}*6#qy!_B~w0e=MlkSTf5`ar9c)^%bAZ>{?*cHJRU|o2v5vIxox)aKg&*Non!il)`_U+80!EFZ$l6CS{UveJrGM(9nMSjcgi$ z5Yyu@7zo!97JnmbCJTk(^0%u8r`n7pQ&yd(gC%p(r-?~KzTDN*_rn?6SbX!YcdHQj zZ!Vp9%@JqBwSwS2&6C*@A0K<DZ6m7D~HpbLjdn_zAKgU8f<7yxqi*rYY$?EnC_A^+mapVubXewR}AP|}K8;c{==srjkFkU)| z&*AI5STUJvBUF|!* z)T7(lHgOvz7enQ(j{r9a5pfsc0Q8-!Dq8E@hE&vWv2oo+(R!Buj;U*Ro~X z`FaBB*%iJo6M=#eo!G znZy^iAIMu%N~V(oryyG%BROCC#801MAT3N);KF_BYO+gA=?Y}9$|8X|R*E?S?%j9b zuAsy(s*~@3_R9JOrgosD(RsmH^Pt<2;X%;Suss{gnP%z&I8xit6 z|C5$F`|&JA2blasnlBq4Z?@>{8_qy}|6B@eKG&cY zoDbjt=D(N7mk2Pioo^rQO0ZjW0EuEppxv1Wv@tv5IaGwMAyug%)u)0jkcqVZCQ|TZ zUjd~U@hXVIMY+~*pAWn-N+1t)p?U?B^-LR0PH&wu66!FK_*VC~Gw6ROIRAU+XKpm0K=A|eq)sM+_{$~? z-kN7xHwHR9ETNd~0zS##v?}ClND3NN6ai-3Rr(lakjDG_(h#W{#TH7}LBbVTLy>$= z@DN~%jlIuAj9s5t|1<^_U%Ll0RLu=@E-|5@)~ z_5ZI&aF%@pqg%Vcll=53i6XfkU|k^=U=g6T;)5&;!U8y+yP)xB5U8zzgB(nffDb_3 z^b$@MG7knG0{_`P1M)3smuYeUzVd(W`R?R>@aMPw&-eZJLP}(qx%UFu5lj!uY&AZc z*3~}xsM+$L6f$(y0~pzVQpnJvuV@7XC|l@o0s$c>c>BQVDgms@A*i>h^y|~f#s(g+ z(Drlx1!oH1_6OTLoHBIw|7Yc$rLO?pn{F3s2LUhk%vae1Mmq0ak^pFKhz9F9UiCgm zTY&Gdh7`5_yTd_(mURUT85KjqT4xz4P^C-~lmh$j?7z$^mI2%l;2{BO>_5KwKQ`#! zr-C|P_Q!sxN1_}`QJkq)YyqIWGPptt zc=5Z7&%hEeLLY+KIYAbtae$6(sK5X{ zpRvGG{}fS21F&;cIiZ9aRJj1WMyO=)Z(#C&ZXT>q@iR*7G;lG>A+>Ly6hj4NWbt3; zgM5<1b<jS$H62E8B6U!`GYOlMjpB3ib@si8#V85i(VP~eJ!6@Rq#R*ny zysRaJa5&w#D!5mXe0ZygH)rq%2wU7i*phYHg8^o)F+u%Lb1bvtR^2HHW4x@mKFS%TqVPkOlgR76l z_>7<6U)RO-;zn&wx7Qr2%ALt;VdHrzBAufACQL_GIup5BE8k6O@-`Tq^~P>kfh%i! z3AUQX=?TWa>#Z55m51Yyh1R(L?|{pshZZ}_hMm7Yk5*cK-9-mFw1r(BsPlG9*%`9I z*e?%E7y_HyT>JM3a_Jrb=48nitDjz!D+40$>-~AjR$Yl*{)suy>^|e#IdrP!FQyFF zRPnRQ{MlU@Ta`5wwvImb`eS#8WvcL+PT3+zmq`s2dZL}*+-y_EINJA*2aeAn>kj?1 zl<#cCk_sm5G)B5iJN%TvRd`$bZO89`CEeAZrGTG8OPen>kngtDke()$c0N-#-{4N? zm1i3*7}ujcv)CGkRH@%#09}4dy^j0A%6LOaT1DE{Y?A0M$miYFYd?LqJ0yCPXz0)j zvXMM|X!qg=Ve^s7@X%j~zxS!dI#fv$34 zzLG#7FU9DNt-)AzP>Ll|TB*s6enOV}`|s_!L~BLynK9DsF57eloQ^&j@kseqedyHr zsLXc#qyEXa*ZFt$-VBfwCas!)E}!s6*}-5DH~lTUxlAT4bR_VAs@w2iGXi{NM_@iN zd=&W`7pAU|yM%7_lsAez!OJ=&zi^uSxzJ-O@NnrDP{mV3%vY$ee$nJfdn|^;(Ftxa z$oT#lajyF!2g=YG0n@eGD(_x+N<^F2mbFxQV4&Ezgxra(VIx}bGHKsvLyhfx*k!dc zo1UZ|0S1w8PD8~_v4JPvhFiFCjB6tvkE&-_(gx1Zd1xx=;%fGKT{$w8e_6oqyRhhL z4elkLY-7OpCUPlrUw=K-(!49><4*lea8G%(tj@;EdwBs~!*Q46(r{Zn1KSDeBRAmk zw|Ypiox!#K`D2!G`pfx-qpnZD%fH#Q)pIzPayq^n!|13M$CAipC|U(ryd!=*)w^%= z(ITBX(ab64!dg zAVET1bmkNU#h!`=zS%FJOKoY$=#_w^D7Mtrdj&kB z-kru+IuEBmkL`2RzWhj+NvzTn?tCfZyWUaz%3)+s%^PPtuc5q0DQc4Kv09T^r_C!y zK6bp6Z=iqm=ro0+S$(X;D&I@b>tJ7qZG~t&WZlQNP?~*n|J&=*mprLv5>1(+_OVP( zvdFcA#ePR!FR9<5rsTUNwxWsnH%*qx@BpwI`g_vUpG-zS znfT_D7Tf5f3`w!m-{el7Ld+XV`U{(3|^d@YE@3%Fa+)6~}3RTvy}*oA^|tbhrT;@-*ex417 z>)yz;p`A%27hmQ(j0B)K=b{z_v6mw{!L`)v+PN>(t1730&h3Z z`~4(6kjqa-eYR*M-Iw%05|Q6#5C0Jn%n&F|SV0wRXyA@Mf|ck|Th?;aEOWstr@rQH zR_Vdn;ls%FfG5C35@3>xzdfim@#0pv?c{zX%A)-(_*Omhs(uY(w1qFi7IhqApE_>~ zP8Lv8{nu4W_gUht0v({!ntnts75!y)TE6?UNvlBL;gT|0Ad#J*=I6vtQl9LzkzL!0 zZ#d5}yM8H8wNGKJmk)|c^AJ|JSZ0g}U$&i~XVF#n&5rI|d2{*S`D}1$^fLn2RWZU! z9Pgy8>DOo2qeazw6uow1)s-^G+x-KaezL%^@BLeUonnd{)L3_HVGSH?-QNo7Jq^$F z-SXKjV>a(K$yL65-D|s7XX%yJ$as9q(3`lWUC_ujoenx2CK4{T(R|#(-+jrzF8V#q zK18r?ze`QO>fiKa(Y#h2-e47gmMvhFo#!uk1cjKB ze?8?XCWFymPlg9DVfb*F;iQvYLrpK)VE-jh94h{1e*VF7Rca`S{!qV~8~>m!@%-=@ zKeOm}ntQjW1~Ruiuey= z!^jPO7U@CJ?yMLw$w?jwD(%R2qQ?`-Se?E!UBHYa+kD;i!vCc6 zrM0kj3F(L{8a(B+QA;^$BrS+Bo$VBGb6j2jK0S20xKg@0UxaE?WF?NjpaQ7=kLqS= zZAKQZ&>H70gEKncqsl|)B-L%?D;YO(Ubp7p3C}i%xnUe=J(H?ZXVn$UP}$$S(?U@9 zNwbCKG)wDt3#owk!f>iBsJ;J@QTe5&1H$9S#G%9|rbIA8Bk$SQ1#AyN;F}-4DG-X{ z1@i!90>)qUs*3ic0PsBo3V$Fvygu+mSH3P6lmZYc2oixS{C{KkvzVj#IY{doK+-an zZLy+qcU|s*9NGP|VCGvQ|MJ0>weHw^3gMjFK^Jst{k%Jq?q-Mrji*Mac`ESa2)L7= zEc~zM3@4bV%<*W0aO9xTMYF|^y;)ufP;mYe!2KKQ0jqNsXHP|g?&={BU^w)o%bdBU z4#SwPov$Dp>3ile6Q$&|fo_3+jB+yrXbdg}81oUJ90LaYK#u|#h+hG1$i=1s`&_`K z=A;C@A;pHyHNODZpY?xuntyNhf3+@wEF&T{{%`sq9JIqg|KA)5sgKz6+3U!#gsLJy zWI0#hazXIf^078{6EpP$iMgXe_EpcW-tHyh0P4x6Sct7IsOv{>i7XDzX!n4 z4*@p~@`foRAPpL*7jYT%2tWx0Vm$mEgrBg}NX0`C*zzJ5K7ce8|1F#D)E}V7koMZc zcenfYn#kptplOT+ASf_ma|ARONb>cH;oEhm$AYf}O>46^Kq*>#xI! zaHUAjm~nvR&j3mAFmUy0r_qA?C7eG&^5Y>iG13Z>1TjBA`Itcx^aCn@_{`N3v>g+H z#)R+rV*7hPG87d-BR1J1kgT+0$VvBkVhfU7YvQ0d?1FaLO>pEjsrKsI1L8zffDmrA z076gl*H<+x&>Koow4va*_~?&0exGDQ0;=V_&l>RQkgoIHtF5sTb8mi3G=z+bnmp@O zI*bN;peF-lACRAP^52$41Kf(lEtje0AD}D&lRQ|+!Z8%;7N#GHfyH}g8gR>OY(d#2 z1L#>-9W6 z&wZEcI?wYskK^-suaBl{k7N}Npr}jzC>;8Am`#Z{IAjWNy?}<^0lwiaqU*EKz~*bf ze13DOf^k-d?V*n*tTtHw{9e|;X5MD-MOsdOMD6V%@T#%51Lm>};G8YT_zXXqs$<9$70a`#|W9r6kZ zO#Fl=EO&)1tQwR%c}Ds`e6$p9h?XcgABOj4!=(x^s#d2)D*&MStoi_(1BpT5Le+PG zX8N-BuNI8kW5eOymC5h_eDBj<7zdl$yO0k#o&G5&svMSn4yCxgmA!IWpPBa1CDW2t zsOt*`ltu+gTG9OHsajtRWR11;&C90r$PZ0P9m2d+kj;DV8fgyl!qfm zgYFhs8xe$Nx-#O0N}M3_|KL1W=&Uj(K$0B#PBE7JiS;)Xo;eL z=WLmYWSdYvB;siM6K1;H&Zjd!VnJ(Gc&s{a)~@kZFn8Ie^~S{&C!A0?pV9jQ!iw4K zkoPtW*jQKPMI#X$@TS7y=C!A9j9_BWOz-Utz7(*l*|6CH32_aLlF|n5Yd2AOaoDc$ zI2-n`N$$||k2>}&~6^-#WG=2yIhvh=^F{dBcni5`eSp?O2hiX+0??8&0S2s z8%C;TUk}WN)LK*xe70+Z?H*@**e*rF2e{#oTt}Rix|9RVpwDW~3 zD|UHw*1y`m^?io>#<{RQwt*rFZ;T{i2TR>%AC}r5tL_TC`fS$>&f&3Wr(F9`q>(Ch zA)9%j?ej&Z>N$Ynm-P|ccP@|cvixADci49xV zA1(5n8UjGXqU1*VTs0adHhW@PVKjG}77)u5lSTd$JK<`|+y#P(__yTB*Sd19JMC~R zQkQ&0n6Hvpz|=hTdk+oz^Bd+Yz!dEDfXP+0u-OwO%2^=M03^t>;R$HB#@!AC-5G(*@ABtq3-L;Spl&;%Uq1)aQUXD9rU?lBDWC}Z)FxnC zZ@GNIU0UETRQCt1A|7{MOdrCCNGnefIw{d{NtDYYJ;bQ4f-o(aPfZCr! zjrixo{?|C5#4!-z)klgBq+^?m0TD|Fx{-M6(v17A1mWcYQ9rAcrb#3YU>b?RR7YwK zoN`LAPd#n!jQULUHg{R;=RR_x8)(3#l9)Q4lx5LrB`z3^%n(OKDe>{WeVta8D zwW2e_b6j6~Cf-89^Nfpjn9$B-B=NL7E(w(01^$* zMHIp4lM7r*(Bwhor3+i^hu6%!C!xtZc_C6SXeqC)`2AKuQR~L}9>)R69^X zDh3?goZWO5>s@i-p-<)Ti-g3InSzG{4?V~ZB;D@gdys5;nO{9eLT$?Fo6W4_^-vKZ zg2HF@kNHLeMScAtODS2KW5x#e^8L=|&P0B++m*HQ?VyqB;|_dDf3k`M7A#qKn9k4* zjP}2Y2d6d5P$8R?nNBlX+e83eAEc=2148`;#I4BiTe!U4X)vOZbHu^An*!^k8Fas( z-u!W&N>GeU)EWH7r>5>tW3pLf2mcWZ%b2c4*H` zF>CZZKXQ2bhp4*66my|wTGra6Zb9_Gef+m~a$EZX!9&Ssqk6{ao}j*9wPo_7zIYqC zMf^5qdt%=Hf?3Z}{ZDKK?tvNZfMa}`u*mRkm2A7bP?Or))7B3M(rnqYLE%?31u zpU=rkamr9LZCjn~+{*sB9dm-ua6nVTBgds7JF7i=OU+uotE!B168kkUfX`{!QYcQ( zs$lx(&7@n!7t1(x;}tP|#;G<1I(7aH&$+hx0u9wcmVRvLP$ZmDP)(fq7ufA(@%$Xq z@XjsTYIT$9AV7n+L@7563{2e7yyY${qSfTs}@+`L{RAcmH(oDS$~Y4*pKg{qgNn(I(-X zLVMje3*Po;aK$<4)A8AVZ|^VaK0lG2pCdR@O5tLi-5|uz+0dg?TiwWh5x>S`TpTZF zUn{vO)WS@EaW7tjTk&c^T-A>U0*)-jp_}0i>OwuQw^!tprny*+8Ck8|E`R>s_IidZ zb}=x0*zP5T%ciIzn?=BDYLjh)A#D{t@fF~41TOx8G=i;q+67Y=XN3!rlxCv?IaHQp z4>8^^`u@VAyo{k+w26)7V6?~d;*;}9@?|o{5xi&ka&Gz**Bmrb4jT>dOee2Z#?4~` zsAr6(etc*%d$ge3xut&j#J97)3?Hl)y4wrIEzXAIxQ{hP^mv3~8~hvMl0$~FEk^zC z@^Nfzd*P^k^S_(xHs}XbOcj@uIXx;IzJZ|%#NcwU??yu{CqEcI$joxKu!r36@=`G?OzdqIhce3+0ZVmd9 z`q|u(JsqGiVNj73UcTo5jY0C=m~HzKI-8g79!|}eul@)eOtY$-`*Pj)%NaLKPfQn1 z=|y3z;p+I9Y_NT*V}(C$l1y3Kx)rW(?ZlMID%sdGKc_OGt&ZA~u$)4r2&dQd9u|zd zU(Ib?7n9qHLB7h*JjhRdO9Ayf@iI)G{^~d z*R^MIN4&xkoy@(R)(F@O10ssqsu#3|zQ%ENRvvhpgvVO-VLsAhmU_1Lzl_}Tp3mr4 zL<}S-n4_ljH>-`NY$icr162HPRvVf)ZBRQ$2b_C&kx6jz)V_n|l!NtJ{cCpCBd!ku zx09dVAj`H_D#Zu)k9@dS)D$2b6i}n0RZ=toqahvTkDk)aecbAQuVO*rY=Ts6WkZ&U zd3nD@1CL^lM)JvmCeA*Avc^x2*+s$&MxQtC9uOiF;MCmRy=0*h30v?nP=o%N7642D z^+=Tpj2ikK*FGrq4^chBYlLm*)#b=tc)YHLu*NJq(hy1ZyRRSke)dk-B$0#vEa`+kV*>L^K712JmvkHoG)RNng zRy`eESOw7>7yiwuN{wg!)q--1OP6_PBE8D(>IsC}(}AK`XT^>4CO(B_oD_Sm|DqIa z3cMV8TcaqaGy=Q$@|*RexmVMTM{T+S!$T|9KeOfe61?(RF>Q&GY8CHC&(RCvNb zdW+S$Qw*{1i@9NXq#ygD1!w`$WCJAaQ@@qL z1o8XRQId4ZjY)#jjb%37gp3k7swSy4(aY)2mLvH~v)qJI7xOMmY)sc;yPl^pO$)CJ zaoR>rB+aQ7WXFw#=9|tbS;%y~t%xotHmKmYZ2tZcZ=3m9C0i%t^4WoUp9|)h;R=&1 zjO8MR%_iBlty+rSbD<#v-IZf+RsHfuWLU8$aDkTBSLDe?uD@NpZ8)87W;}3uv^wAZ z)^_bdlZ}qC62((@js^=EwX{x%WC(62;HGDCD7UxjqYFV8a;F_Vz zUoQR_l=aEMz@I;Y%w*|vWS(yJ=bFYsIUn1W*+iFk;m&#IvwrdJp`AV?t@(T3;xCHe81(PN7~DR)Vh#M&#$n_2(-)*v3f6|~ z(sjRSB|GPLy?5-Z&+>fbE=@|q3P)C{$i@`M*+pZXoD>a4+N_CC47P*Kp$Ilt-r)7` z{>oX7anChaO<<&~9=XNAOswprUTQc#k#-IH=KflOObbTJ$uYA*jlW3*vwqD$tzcP% ze5JB%M}@;*XwhYBTk0#&tYz#sPu-f|29A3W+^3lUb36nv^ZtyY7gK8nR&EMLX#>F2 zh`LH*+d<4gfcO+>@TZah2?9BXSg!>eNTXen04Jy|U=(M$_aD(juIZ!yh$f^9BC}w; z>UXX5e>4-PaNT9QkM5yW9g#X>_3j^QU6l{;@?Dwwt*UA)5kD{)umfoRGia1Y3@}X4 zj|dX}M_2O))%=bARWbu~mjhFzJO9chf-ma4bb|QJwVn8~uS(>wt)81c^Xhq^Jw* z*U9;h&zhtk1ZrT%!q^5u>46|0s|2o{Q$nN-$*41C@jQTWd46tV4lw=oC&ji zDao8Y3|;LRU>~;z1TMF&71tEGEBuu6I$_cGsi4$_L zpi{uZKhO7}_?~c=LkQ+h_lkgi>6;PVI)wI|5rPSjy?nlh`5QO40s5X9XFTRdRBkZ| zn0^@h_O@F117tohB0XIhV0A{n+CC8_BhjbarOzR)Yzi70iIp*WU2*;#8Yj)?vgHW9 z;h+n?!{s@>D8Po{Vv;OeU>JQdg*-1`1TDq|?lw3v+>K-j{9@R3Q8A;EdR0$*@)7K9 z#g+ah2mt_+g;Y7Nq&vcfhSPySn7eK`2l!z!z)5@#ctZjK z;6F{IOddFJ%nx~e&8pz+9ad-IGweiOZmqANa3yL^$uz*RiohVm@`hsU;C#k(rR!Lb zQvhl=49v9%2gs8v`h*sWu}cMMFif!rx@TVY!7o^5P@|YfGMq?*!K|Fa40uZCO5q*{ zz$jIa#@Ugz_|<$+8l%*24iqhM&R~W{FYQWed(Hl+Yo0`%8z>ULAQM6jr}zf%a2Dq~ zRx=HdnQ_i8l#hI+X#WD*;g2)8dH!&^Mhx!OSHvf%1&KxK0oqhM;?*vXJgv7cf5+FE&pOK()9GB>pfI-M|~y=p(NYZ_h8&z<%(cB zyQ!G0@*VEmFyb*XF;^-~!PQrXee~fREr0J|b{4o?k(3GRC@_=RI*mlT11}6cJQrNw zk%(xkNP08*wNa(QY*%Ys1HaI-9U~z4`hrGhLOu9?sD|w5FgdZ{f}KOFbf_JMewsaw z0^nzu=3KAK=5o->3QE7-^!`_#w4G7`&WH%{%!{Mf^Iug#Avg-~fN?f+TzzrgNb0z}J*9Z{UyF10~ zOuE8rVug6W4pH4`tySL4a|(CUnAJWMmLYxz85a zI-CM3!RM;XqRxd*a063xBH~r^%#E4rWAN7EzePqMM%y?1=>RL43rIP$oz|_fT>A@HZu#Q_FALy#bLn zN+yK7M%A+od-A5Z53E48oClCnJ5)fQ`KG0|v+Lo+lRO-u8^_dFVS)Q!u%9AtIG zJMu_ck^TJc=0c=WwM;##37cc11FInGYe?O=k}5Rp09j>adbPldRU@9E5U1XGE##uk zwEI5Uw2f7q&{a0t@vjM`7}k~JPhy)Qi~wJwgU9)z z625$|#r}meTXisxFzk)grIBw^VcWo4SOc=J1S3wvJd0qLZ3k`TaXDvm;QD5dF(%Nu zm&#FllT$iimb{jvx%ZFO2GpJBJ)uOwx(@0xNCIHVBfj$($QDcKaFTgoc(ihh_i+t9 zvgu6OaJfrkcF`Vs3^tXtO%N%S)%elwY5>}z3k|S7ubi0%98lGZQ6!*iVrW1n#{aSP z?5$h{1}hm@1!Ly$D^}(VBtU^sj)Q#m+~3y`@)PAhdS$`fvI7M$U43pEh`CI-#4D*z z$8Cou+gl;8VtX`;cMchpkPZ;he!Dkd>GAh5+;J2IfpcSm*r?d?!+eIOmq|f^alm^c z2>DGYcVM=~StkE3o}(?~{m!6Vu;mgIG#@qnItx=MAAz8$u=T09o%pyVr|H_$2bABS4S|^>qRw|nUOG4Zayu`fwFu;5f%7z2S+)P^Z2#;q{{fL1 zc1TZ6wkL;LfpluTDUuCtOJx~Y$-D%>Maz=HW*B(xAyLs*14JCqsS3;I+@D9-WS1~WiIWk5>bE)Gvdw5y_8^}q(MRf^5& z@nL>rnsNGXU2v!(Ft;7*W9Y8bxZm43ZZ3DU$KGT_htD&=r7zmmdmMmno`KK|A_5xo z;`&^F(F_~W5H)$ID2F;kvuz3p zR?(T6oPlg`lvIFw;XwWAV-LZO3cT#(2TF&=y3ucMi862LwS}HM(Sg^Dx!KmUy_3!b zNcj#G;J=mcT4enbAn4Aoc?v&ufNKA#!75+Dai#)@?@;?lIxG^)mhTAHK#6s!OfI^m`7BEl~jzQS7Aw! zo82hG*}KsaEd&9!u){v&>#IO5<=P22Bl|N{`CWEnJmq(~x?JWUN-PaZ#Jn*WF5PEW zkZ(Qn1SqTcaG>D$Z09uz!pBGi+Cfk*yEY4FV^~_h6Ix7O6-eG07iX>@#c9&7K)PL6@CD_}1Sg>CkexI4=dSDpNLDg` zgyYq%H?5+^V?p9+%aF#P^3-dYgXazWCJj>e zfK@X-LfMLhCw2h~%8*}Ee?HQvaK4;6`A(F$aVSGve7N=dv8G5-rE6Lhm3hLSgS>AmE%~Dmy}l{j zX`!nTVbDGGKz-3?cHu!%@ZoEgIEPhu1^WcOtTzPXMx)GWlr-S!sg7QUu(@6l%~NI9 zB3Y`q-DbuL#>6_-#4G8 z^3bt!C;S}Yhj_oKx^~O<%1{@CCq~qLm9kyGv$=!3`Cq;|x2qIbB8`3MR`tbU<+7aFJqbJ(`Z>VylI;& zi}=My>qB_InGOvVFg=)Gi+`tUCQ!aQVpAak-hN;PX9NCW29N2o4=>1Y=q+^ajqU>u za^l-b7R&?k<@pPoEnZ08x@pFoK zzuh=t-Id2J;d!R!HYmk1o3?lvgvG*Lz2h*yDP3=(Ov=qRPVcbRoGF=~Os9kWwHjXu z`e`p`cfvC|k)IG~Oi;ij?u!yj5k9&#nxlPO%tbO>L{sPg~!~2 z=ooutUP@A0!rF*^{9~Jg^w%l+O|iRT5XW^@Di9zZ7)K6+43Q^MBJ8T)#qyrkP`U7* z?9Qhjz~FY?+djFTFV`ILuyGW?+`m#mYrp0lUK$eC%356$o$G~mRQRC~EGB(UXo^#Q z2+2FHS59Q3#Sj(5abipN}a#&q5s0Vy8c1ZjVmo^ zuLR$IFwuO{B_(G-N}_w8`xNTm%pCpddfGfZ^K2o2P^yWNnU0$k2jm4hgE$%zAP9i0 zL*RLx-g8;dhS{K6kcZTlYqjrQEn#TXb!8I-I%-k;?wT?I^R0j%o{+^XNGSS6$SjWL zx87v?B8w%h6#mhBdVlrer{HY>Ij+nJiia&Pq;h?bY!vLd5iGcG_`Oc^fN*+=Fxh4y zuF)bwy@f%EmA!@mxBt^M@74!C>WkhEWsuUnbS!~K;QJomk$tDT1&x_@t#n*F;g}tu z<ky~ zQ+Od9$j-N*#E~#rKEeC4>+S*8RKfCnzI+igH7^OHS#S3>l~5{l zM?cE_AnH6S!tFyj3qd6EcZHS9?_%cLRZOh3N5d>`F~vk7b9VH>mu@5`tkb$tQe9&#^8JQysb(Owa zHBL0SJSYEoC8q}`g+X)6vU`5| zk6;4e`xGR!s4P2r(<@O*+$-1Zn9jYc)n^ag9(>{Lrs)J~8zaEDQqo1AZkrnNp4zjg z&4=CU+0R|a4nWsKu76K;;^WcScZW{Ethbl_nqU`81hA$sb}xR|>#?-$dzJ{iu2Uro z1dckq0gE2b)ixYUKpLtfiDmNetDuTjr=d?KwlaDBk?_?l6PT|h9@Kx}XQd1gN}5EQ z?6Ixjy%F@QIqvZ}6|JH}H)xNe!qRLf@g=_cC<8Ev6IqYj0+p9dq%5}_wo!h@ONT*`?z9fqtLROcRBfWo5_aDcHZ?x1yuj>=Jj zlDylexk)&}-jmvIaxjbSa0DxzT#jdaQ+aE@u`9C{xa0918ZNQj10Y^4`F`7d;?zHC zPB?R(2@mZy5z$X!^N61+SMZ#_bQ+^0Pm1IUP}z`YmG6U67$pzrmc6$oblIr9AVdB> zANn{C&S?GCDa*QaLgYaDmM+e~^S(>?JliV4=Q_MXTWJH%>kSA8{R}5D_n~lT!txV) zU=YR7=hWhKP{wtks2kYsC?&Ni$d~Q$)05rp*-w7R6v69DaR5rHVef^JYL#!IGRj?B zI_KBdrcn$WCFV<^r^t@NjOim&nT2o9cW0eq66BV>GI`tqGQxXH&ClV*9!?Rb_o!Yem6t^e@Qr>nNL3=zcEVJ{N#!!jdPU+W&4 zjGA{(m>7tu*f&C~kaqhJ2`3l;t_{U>-fzNbm@;0;HlH0+bl{flG&97dJobiKt>1p? zydp;7Z$03R0uzGvF0Q!?Xq6q-;KgLo%8d?+GDIAD9*-GPcKx2 z41Kb)wHL$;#g-h!1W?HlzlW5-pOu_Z-gVYSE zgb0=sjjapF5(#=!BdD&CR*CXxO9k)-Nr3+RH%PBl3cDHH?*E6Ul?a#QPN&yRLyT)W z04m^_Bwi8dRWjj)>qP?Be{SutH+Yd7FXWBxJqsFObW6m&mhOO>5j9N7P|N%ypF;N! ze$d~zLgN4Z;|m7{Hyxg94^%LShky_cPe>H)DRtZNhj;j$^i|0Wg3&K%Tg!&#{m)%_ z1o~CfUjm{n|IZU4-rav2Ea8U|UEF4pZ^5VrCtwcr>0q5EURVJ5`rw6B1~J&bXb{ND zS4SC92QH`zKvxRi++F~pR;Hl~wvaUce_CeY1@Yq58{yTd-488@%AdP34?@gtxPnJu zSw+0#pSUzz2V3UGN!()QlH0Az-TqN)Z8&2NDdS5rPCC zIzz6WH3)g`1~TGVvr`Dbs+Wy>JNv<99gBr4-*xI?`bT7ReaXm$WbP8fzn321;X+@O zA#O$UxCJv%8wgoRfBbDY4y_a2#xQ*_itiq$54jDic^dXX5k2w`klt(zX(3@}`*RV( zcge{S9w>T(DuuRY=vH~sVZ+Rx3$IUS02Z0?&q|Yc2?}P;6xRW?YrqP&IpX@}-zzc;JM{&Py-)t#2_J3zY`ewSQs3%~%nM9(es zG67vj?h+dbXkGqXih9u%;$sGnH#KTu?*X`|xnmbi8Z}qpcT^+Qg$w1t@llsjvSkkj zf6vbXVe(2q752=4`Z7~!Hn&2zKG-ih$mRQotJWj0`SV@o3URW;1cLfto<_aWi`?hl zomMz``pE~_D}ahUMo<%R84FM(TKOR{p!;%%sy0e1!69|>g`J{@PJ4{mz;qKhmi;qR zUU3z7X0dqp;*VZ?o|{Q2O4kaR^+%Qk(wy8IL>DUe;o*{Y#^^$#*(*3gfoGfk;)Gd1 zEFfTiP0rh!HjMsFOYnEPK+>)qE@Wf9D*%D$#jE3ofsL`4Kc9gVo8V=R$P{KGm*?Gy zC>tXSP%8Qtw}P%e$An1L2m||shf1gmQZ`I{F^gUXN63L~v%sy*p?-E3B+vzZ!vNe< zB9t<%g5Eb+4VHB~F>CJSYjY7W!G;ff1T<2+fP5XId2SlP3F^*FxNaD}Kxt+Qr_-@U zu~WxPLF>uv{jo8B-f-XoPl0{(!=|*r-gmOtb+CA=+Vb@qNfgC{I90Z-0dNC58*PRN z#4f0u+HX$oMel0s$_B~8SSB$V4iX-|!LO2q_HJ~j-ltaKRC8-u4NV{`?^H}uVyF+e z=w*r-1Lb)(0#SC~ue_pe(SF(L*S#EHFAeuO-X_dQ<>j7NX|d;rfaBd_b8F(^$a(AZ zs9?iP{5x)OVw*hM&FK7{53ZrdyO75^CL#Dd0L9>c zGPhn8)qp25YE_%g^q>-5_eM| zBkL+KbY|a6SH4-i!-oCiUa>W0P}TRiE!U%mUsTPosCu6jR;buEw1&lrLuY7WeK2Cyca7Y9;LRF|QDb5`v|klDaK(wDYt)2KFLcDtjBqZJYIdGlj>-0ffe4?`dv-+C>Yf z`Ryxg&FvKX$wyb@KM%cAkTt8TcD?#>SIIt~RP}Tyx~PBEXkw~N&p{1?B)z*UBS4_Y z(!OCM%Ohm(?F$5rz^VyQ;zs;ob-s%@;twmF>GM7+uB2U zoNYa?wA;TfGWdI6KLpcm7H(e^S@H+wTKw7X4&=r|}bO43vc z)eUdMT!%D2 zzjcS!2BbomM#b6o@=%e~RjfRXdaAvjR{n4&zmLgi@v6~~O{Lvl;_*m9ysFY+BVDzF zvj>(KU-O1$bWJBK>%I+rUu2&2aE44*@S<(j$ZjO3p8=@JvfpYa%hInOb!+&Ush#@g z#72)*Wnc$7etie(jBeuI9_YWOB+~C7F1DNedd=RaKI~X#ZwC_*oTMcA<6V?b*0?fcX=s=ZaVHIy z$=v*j6NItSj4Rp_-C{ug^exIi+l+}Io5Bs~s7MP+%l-O&HcB5xbuvw1_|nAnB_9>6 zb<=>Zl?$(dXhqVaqZ!Td!ONm$(^ZSQ9xaoxaxYYj^S+MV-p49;iZ9w*)nF}cr0n+W zL*EmW`i0|OkJ_09kESi`tbVyqR-kOmi$n8mD)qw457)ir*?nc^N4pgcyOP;@jlkP= zA#vgm&&>o(-VCMY%f?6b>|qi6N#v=y_pqBX;KO?AuSBqBI{=7#LHud7-A5MoB_8#U z@3v(>lG!b7t`lsGW>+p$Kex6S{b^w+|BP~n_@hn2G0tB*-{eEhLa~D?)jV}M>n2nS ze#DK@HmbECaB3|+`CFU6b**#;TVQCodhhh?8QlZ8VA_W|_;yj<)W*K;7p7YQZXAqm zzFs&j?_YS^Mh3j!*MU8pu+{?i>%U=MQFS=8$PZ`yfp;7^B8Max*at%x7re2o*LHIS zu}D$v^S7C;raLHc`i+5HR5|eM`7>yDjgdTNx;5$Z9gYiZ{ru1}(>X6m={lI0drdL4 z$jP;&D>F`m>T(*bN3BXt`c8ub;w&#z!39MGNc4{VDVn@E4jNu|Fmbk}dNtP-+K}#P zRXeVxtKIS5YPavvH(ESaYI=MoWA+75S*rfDdpuz7&TIE;bR>T4OCQ_3^~jI7JBQ2p zFAhX*7-5F)ITD`k^$T|_MlBAARJPwrvC+1Bh@G&+w5&I->90%O6m?$(kJ>n9$#1yB zvoGG7<;=Z=L5#$b3nyU%rbfsla+aFu6iGZ9Y;H1?+k0#ia9(q9VHi1YHKHbGB&xSh zn#uWbKPG&4%b96uw`=X8g*9w|v_FFFy?0b7utK zoQ_>1Bfe#xd(oQolCi626}oZ`)6{#|-sS4)jG3buj$QTL_bwiGO6+>di+6TrZ_Pca z%Nclfv@rADU4kHiQpLWm_2g_OxMqi5H;d`T$2U32+#zLUsL%g)b7DOy^o?nyC6xSc z+h4;30XV;Ly^c&IH36J$p?3(GmBKhx#C!b+=h~{mulG9J*R4leW!B=39Z7g97ilNq zEaNf5{osy*Ya=NW4gI{A9St3&t`A+&#_k`!*~yf~g&Tg+Yhs$PZ(#7O%F|}ff~nIK z>-$31oA}b4$16<9B+hDvu?s(2Ei*a0KK&>pb1o)@RE?hd4EJ3Hx4G7%Lq!TVyV_c} z)`h&smg=MBjK=8L;6PNJrnx|I(eL1}?=#d4R1Q5wjo>cUsfJL#F2Sz^rPSw-j&mZy& z{z7o%+02Pn(wYO+Uao`Usx1+qjg_-V#v15dB`}^!+rew zl~17HLaKrSy97~J#rI@Zna$dvF+;dneMLnmCT%u|v)k?Ka5gaGZF-;jGDO?d9I;s3 zI^CEfI%vn)6k$n)uVc)KX%fxD!7xw$Y{sKLrq}^)^R#W-Ux+y(9I>C)fb1HiPwIrE z$Z;S3=TvyV;%%=%RN~uBL5pC}p=$Bk;BJjG@4_bVLYKbc9lktYwuI7;`GkBZ_af1r z!t9ODi#)Z0 zmpVH6=NgDqcJ(MdV|c$#c^Athb-D%xAW;|XruJjM!@OOa);`yF>fG$%&~UZ#>AqFn z%g^8UVY;R}ehdZqFxkQ=?%!_!8#L3$*?f>>rEq#Lg`~tO`0^$*$A*ly?9vId8q2W;Sn4?2> z-GzdB=>Ep-J0P#>`?5@Y6Xv|P>yuT)hoe>rW#qt+HV?4w@#}-E6>_(7)t8olVF}a7 zj*M_zyrJ?%%Of<1&j?xUMi8wx^`!(PSPp}36#i8l@c=jVp>Tl?^$X@t$ z-VJWcpLaTDUpqNK*VH$`!qJ5CoaP71vVkMg94$$k2BNUT?&F3%7?8(4&Y|WiWq1Rr z-UeFZC~@rPP|{fvCL_^@1H5!ua(K z$a%KhY@H1EDNTh|WJ-A@J5i`6AtOD*GOe4;{%WL7BJKDq6Wj5RvV>-V%HB zZQzRqH@;i-kq0T)!4XsnP3>55-9-T(FLUo>C|wg8jDazqma_vcK3|@)E>dp57T669 zW7rV8vdKnGlfpinAN%xVUK0;1kCwX%R~17Xs3AA7Fn9(=ffc9|AgekVQDiGf5bFzg zfD-bcT3kO0F>TL&E281Vo3l6NSR5v=hXHLyN)(tqhHwC(pTeNJk^2d&Kp-3pC%od`Dfi zN$Vu0O(363P5h9F(9@8aMETg4he7K1p$K3%7!&twM`R?jPxdrS*w(zTETwcKDS_cF zhF}jzEhM&6dQYUbtMnvp)YOqj*7O2Afsrbptu^_3O`oaki3F=5RKSg|T%dU_sClt; z@G0gU{g*O3HUU#j=(eSg=W;&Mt7JO;r_43m6`_FXu)Q@xF2Nctf<|Z5Y(ML~{&5(> zT3CY#Xw-7lFWWCe=v*q_Ym!D+;_H6L88aDDdFzx3x z<0kmfk#ZaV5mC;fqr$s5j_sJg#gO&Ju_)|XiMkKzX)Ix0~Jq>X!xCGe|^_dBus1I<8FSn!>oH$Iw7=)r z2y-hKDPG6KB*qLZ;(g+J0s*gvGH%(E9R4YAgKK?*(0i<#^bzk*L z?U#?8cNf?@sNS8d!aoJWehcUj6pvK;ev|aYw`X$+rBYARB;RqI;jowtu>sj-BlQt| zCibvM)6I9~bEn%p;~k)2x%;Z)gr^b5tq97e_0RY3z%%$dDhmfLc=MXbs5@7Riian7 zN)O#)5ULW??ayf3-dEhT_V%!Fsf%powag}t(}2r3*qta5U9}fvb1wR*^5%In)Mi1U zY!BPyenV`mr~vUsqs!Fc6#9snvUSz6rIbqi%CSglW(!D6ZecZO76jxd0=k`YA%VH( ztW**wSNZemaH>^XkKL)>JI#m_G>@54)@EX=&;-ppU-~_hIf6e$3=}!ov?J=cb z9>7DA#HDNN{QZVU_o07;{e#W1t`C(X1}b)EuOhOaEb`^*Xxv**Al9)$JRTh@NS}d7 z^A`_9;^jAP^Y=Z5K!BB|;&jZJ7LMr{yIzJIuZQ!^B;PD%LyTc0s$!V${EbTffk%bl z%{5*v+?k%zCLLiRcR}O({-2E2d?cA(yL;3P0B1b zopmG1HY_4f)HL8WW(6l)RIdq!rW+}wkxEqKb8~>W)MrvzQzsA>SOGpB-P{ zJCMZh;~CTZu*jL4=@L}S_TFu~}08iiJ^xD%WZ+h@yINo4uUh0#ZlxN-FEK)=%q zlnc`b!z$7L`8}#T-|BNJiB~Ov=gWZjoaN-KRwSvsp{pC`3~*(E#SxO>=caT!<34;4 zgJ1!9E2}K@r$KzN47y&k1sbo@Le(=)ZHKUAV!iZ#uZ4JVUSjg{{?4m)8u_2L4WCgA z-qVhRI|GVfd2#WlEv>Bq!NEU2lSJRSdpD}3MLy?#;EWX=yEORl7l_4ND! zlDpp;8h)^CuSg*=D7r9f>uk^(#1$4|G)P@n*n4-lg@D}BAQ7vuO#;%;Nk~e#IW{&{ zOvWy2n7;uf#r+2l#?O+_vk^c3_h+EbLf?m-8zEi*F?6V~F1w{r>ysja2(~fZFU66m+Zb z^Y-uG{}aSR4<0>=g1i29W5clsQYDm&9rIF2#2o2i#Q;lo9VA4MjaA@8E_M$kCfbl1 zK@=6bfOBoY**pYo>CyobFS`G86+ohix}v&WtpD4$==cyXyUa_b(jdvNp2TJo(7 zmM2@KK%=pUegr-bJ&R+dA_NjyPRYMdn}dKZfMll+TKV93Zv)NLz5Dma&XPpStEwi! zJMskXD*8e%U%u>JPY9nPq31_;4=~JVC|MI~Yh~bW1wh3z1zVxw)vIpkYI}QCK>(!; z48-z(e|?5D<5f_3G{flad&q6OL9GU`PD|)mL9jh)VC zx9H2gd`XovHU=w+_+a5rkJGuVJOd6ScBUt19sWFw#JaPCV$VHw^$7Im!K_BI}ZV zk>$wVPlRLoza&46Gs_$G-*+>~gcm{u1c9!)O%XHbt#PCwB^f-P+<9I&LplGVO1^eT zCc*Vme)y%5&r3>YC!b!~5`!yI@HV9*DV^xF;4W?IKh|f>U9Yj_(sI+_qrtD6c|kG? zS8ni!amBVRQo#Ndb`mX}Y^gaQGCzY<0d7vhaZb+9u%F4u$h5o{Zt;@;WDwXUBsDt~ zW%SXe;D(&8bh5wQK5}vG30vr=(8e_h`kfYLY}k;o=t>#gyO5AiNl8gDzo5ze1jI;G zPQU$4@M#FDmVlNtAT)I9SCFdtw;_AbO8$T$vIGni%NCa%irsclB&Ma^0S}VdfapCJ zAhP-l@&FR16Rm>rG#?NY)zMmDGgq;kqE?U}dkq#)b=!HVu0Qr^XJ!=5g{L`1NGSK-0+kVfk>i~1vlX2YI~U3ELr#EcoX(k+T{XGM zKR-@-g1cvz7!5kS1Zv_2nmW%F-8rda^fpn{-~WlD`RA(%6k1VDt1Z{g$By49CL!Sw zhh2P-H_5Dj#aw^-ivGIu~c7C|0A#VNY_!hlalp3WIR=fGVfH+4?O+Rr{t#^plbm2+=q>$i{3 z_gFfUJPO9xrLQed#X|$osz|~vg0_S(cb^GqIUQ+SzKq<*n>zR9=dQQVS$w>!)3WA7 zT)?faXaNU(KX)TPzMvHAy#U8;_aYs>xAg`s_)iPyyzstJRIIcdL4mYv}qDV@gUxP zg$};R&1q~t^eXr6-W~G2QY3TprWJ~4kBluW>{VQ_>dG^k5S)u48TLZkSh@Rd$lD2q z|Db!JH8lhJ4x`PVQlg6iZ(GNw<=RIgBL}GmvZ_6>!0NVW_Istu-RGX;YQB|GReV}9u zl82&H)*0K@#hEOiOl29>Ed4@He23!<9iZJ1g}lD?qH`0RwW&ZiABlMM9cJa}V6p2Q zvh{Io17M!>oa=x$otF8c1QcC3DMu}EiR6Q9e-9h*H(W)4(QFk|CnhGgK>lSLv{k~u z2UTNONd|jf!%`qA&W3Y_F%hLctsP`(0w}xpl#`_7^TsPv=QIMq#1RK;%m7@0-32zO zsgf1C3>#A#+by6BpDj0qGoyf#+kQze`C&#Co7JWDVh_CnrAJ4*pB5X5c0-O0|Jgwt zSuy!KOp22D^yw2s(1jy28$rOs!(**yV9Q$IjY?Whbv`H~GOeZ_5W*0Cpkl4V%Z{HL znDY^;RIh-{s>@*1>w|}~ww&sc3~BToE{r53@D{Qdq%DOGY*gLWA*Vl2?S`gy9==-j z4TWT1fH~v*wMH=u)!IXC`mxr2IWzR4!Z6`R><-z)9V>Y~a@^4EFC9)qk78*s1Wem9PRcxw}aluNC% zB=r^yg)#MYIpx^n;fwU`9!~3hMjZ1X3%G~Gx)z;g;FUJxSVR+TP!3xCz%vi~bsK$A z&&%64WuhHM6c>D5Hm;#Y9*JQ8mU~?}CXwqT`Y~5YqIF_o`OFQ6XqppKQmkVTPP7=H z-9?FiQNF48h?f-hTiDUrK7r4r_zYtk{Od&6de>^>rwN~vH*=_I503g4Qa)nbb?#oO zS^++nQE8^!qjD><;3Kg8LO=-<`hfm~`I_upoT&75KCTnLK z#MMKZ*Xwe&{78>=XoWg%cWtMG95^{X(z(0g_|N_#A%z7}5>5$JIB#2lRKt3xGcG*R zE4frAfp#PzYIsuZia>w!9^fb!An8J}r}JM!|w z?QK2#*P)2h5Dwftd}Z;NM{=_Us6mD%H?p^iq2x5~BlxA3#m#JQOo%GNo_1edefD!C z-?>b+U2(TUqTzg<2sU055VZDD(f$hO6LEDNL8VOjq0Wblc8B}2&rhEFp!~K7{A_vp z>+N@DC8DMttW={&}Wk2a$Tv;>xT+VEq>frTs=clxdZjb zhLu(AuhRSXdPO9sW;cINZCRly<&O*>!Hd{G<{~HYqW-UPydC<&(`U|@-+m7j=IGW= z`Xf`y#ytTK-||n%>|s|&3Ha8x)A}!GpI{}a-2Jzg=Q+=YD)E0c^+T+b^$R=%1bgeb&EPmgITY(oW?;clVt-j~}1n;b{f{A*!%YH8wW(35)~i znPL?yOj0Xo51-K2*MHKR`z4i34D(OR-n#e)hxmIj4A4$_vk1zA;p7J_5J%_^%`Gf0 zgI6YJ?6~X7x5mbHFjfQv1x@_!j@h}vW^Z4RA)3SfvD;eh!>!d6*ztRwAoyY zj*iZs%S2!OPe%`(OZ5X=F-^FxIH&~@V046xtStUM$z7$aCjnGcR1lKsaM`54SCO>x zIyAztE5D0~NI^;`MN)Rwe>yh(RrEul3q{B8?;9hgiMmVFe*zN^_xlV~5glOeu|ahV zy8nwf++|RULh@(%?@~`pb8EH91r;sbMGiU8g}rndWaBpuGsq=pcb+Eehni;z1oVIQ zCiFS~dDyD2tLYZEY1v6YXQco~eNPPk(W7PX5Qd4OKEYn4sdQgw*IowXUOMW0TMbR*eh?bj-E+nO zpfPm!&zw2a%V%qyvI8MUZlyG=7$vU4`KNGC;3r3?YnG91&f1h%kg|zw)Q9rRq0#T@ z>FNLX;)g=_q_D6W6d!k>4M0$ayn@0HP{01uK4UmIu1$p7KsPSt2#quGUb|_J{%;r# z-9A8l0>Z1ojVT01U)HWG#XMO=^Gb XfA5Yu{%y5@2uQ1^tDnm{r-UW|#EKwr diff --git a/FLOAT/Images/sd_CS_ESPB_stale.png b/FLOAT/Images/sd_CS_ESPB_stale.png deleted file mode 100644 index bb7193c22944e8ea274c59a481f4b0453148a561..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58708 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 diff --git a/FLOAT/Images/sd_CS_fresh.png b/FLOAT/Images/sd_CS_fresh.png deleted file mode 100644 index 4c39489d55e91b45c846dfd5ab680cd3db3c378c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 71572 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 | -| LISTENING | 2 | Requests data from last profile. If connection drops during sending, data is lost | Ack is data itself | status to 2 after first package arrival | -| BALANCE | 3 | Moves the syriniges all the way down: usefull after pressure test, during which external pressure push syringes up | CMD3_RECVD | status to 2 | -| CLEAR_SD | 4 | Clears data file on microSD | CMD4_RECVD | status to 2 | -| SWITCH_AUTO_MODE | 5 | Toggles FLOAT Auto Mode
| SWITCH_AM_RECVD | status to 2 , AM activation state toggled | -| SEND_PACKAGE | 6 | Requests a single test package to print on the GUI
| Ack is the package itself | status to 2 | -| TRY_UPLOAD | 7 | Requests to activate the Elegant OTA server on the ESPA for OTA firmware uploading. After the upload FLAOT restarts | TRY_UPLOAD_RECVD | status to 2
| -| STATUS | - | Requests stale status to ESPB. It will respond with a status string containing FLOAT state, WiFi connection state and AM current activation state | - | - | - -Once a command is completed, ESPA acknowledgement can be: - -| ESPA ack string | ESPA ack effects on ESPB state | ESPA state | -| ----------------- | --------------------------------------- | ------------------------------------------- | -| FLOAT_IDLE | status to 0 (idle) | Idle with no data to be sent | -| FLOAT_IDLE_W_DATA | status to 1 (idle with data to be sent) | Idle with data from last profile to be sent | - - -##### STATUS COMMAND: ESPB RESPONSE - -ESPB response to **STATUS** command is composed by three parts of information: ESPA state (stale), activation of the AM on the FLOAT and WiFi connection state. The WiFi connection state is detected with the sending of a test package, while the other states are kept consistent with the ones on the FLOAT by updating them after acknowledgements reception. - -- **ESPA state**: - -| ESPB state string | ESPB state number | State description | -| :---------------: | :---------------: | --------------------------------------------------------------------------------------------------------------------- | -| CONNECTED | 0 | The FLOAT is listening for new command. Previous command succeeded | -| CONNECTED_W_DATA | 1 | The FLOAT is listening for new command and has some new data from last profile to be sent. Previous command succeeded | -| EXECUTING_CMD | 2 | FLOAT is executing a command | -| STATUS_ERROR | - | Internal error in reading the state number | - -> ==**WARNING:**== -> If committing a profile automatically, the relative acknowledgement will likely fail due to connection loss. The profile is committed anyway as it is generated from connection loss in the first place, but the GUI may not have mean to detect it. So it will likely read an **inconsistent** **idle** **status** (CONNECTED or CONNECTED_W_DATA) until FLOAT is at water level with a stable WiFi connection. In the meantime the command commits will fail, for connection loss or because the FLOAT is underwater. Anyway WiFi connection state can be detected by the STATUS command, hence giving feedback on status consistency. -> ![alt text](Images/sd_AM_inconsistency.png "Figure 4: Sequence diagram of an autonomously committed profile") - -- **AM state**: - -| ESPB state string | State description | -| :---------------: | ------------------------------------------------------------------------- | -| AUTO_MODE_YES | AM on FLOAT is activated | -| AUTO_MODE_NO | AM on FLOAT is not activated: connection losses will not trigger profiles | - -- **WiFi connection state**: - -| ESPB state string | State description | -| :---------------: | ------------------------------------------------------------ | -| CONN_OK | WiFi connection is ok | -| CONN_LOST | WiFi connection is currently down. ESPB state could be wrong | - -Example of ESPB state response: **CONNECTED_W_DATA | AUTO_MODE_NO | CONN_OK** - - --------------------------------------------------------------------------- - -### UTILITIES AND RESOURCES - -Links to Arduino library repositories: -- ESPAsyncWebServer: https://github.com/dvarrel/ESPAsyncWebSrv -- AsyncElegantOTA: https://github.com/ayushsharma82/AsyncElegantOTA diff --git a/FLOAT/espA/espA.ino b/FLOAT/espA/espA.ino deleted file mode 100644 index 90bf089..0000000 --- a/FLOAT/espA/espA.ino +++ /dev/null @@ -1,559 +0,0 @@ -/* -********************************************************************************************************* -* Code of the ESP32 on the FLOAT board (ESPA) -* -* Filename: EspA.ino -* Version: 8.1.1 -* Developers: Fachechi Gino Marco, Gullotta Salvatore -* Company: Team PoliTOcean @ Politecnico di Torino -* Arduino board package: esp32 by Espressif Systems, v2.0.17 -* -* Description: -* The code has a switch in the main loop driven by a state -* called status. The status is mainly modified by the packages -* sended by the ESPB over the MAC layer. -* The zero state is the idle one, in which -* the FLOAT communicates to CS that it is listening and -* waits for the next command to execute. The idle acknowledgement -* is sended every CONN_CHECK_PERIOD milliseconds. -* In case the microSD has some data to send, the acknowledgement -* informs the CS of that, too. -* If the ack fails to be delivered, the FLOAT can enter in Auto Mode -* (hereinafter shortened to as AM), that commits automatically a profile. -* The other states correspond to specific command routines, called when -* their relative command arrives. -* After a command completion, the FLOAT returns to idle phase. -* The FLOAT should guarantee to send a command acknowledgement only when -* the command success is sure. In the same way, if the acknowledgement sending -* fails, the command is ignored to keep consistency with the ESPB. -********************************************************************************************************* -*/ - -/** INCLUDES **/ -// Description | Version -// | -#include // Library needed if you are compiling on VSC PlatformIO plugin | / -#include // Library for pressure sensor (Bar02) control over I2C | v1.1.1 -#include // Esp_now library for WiFi connections establishing and management | / -#include // Layer for proper initialization and setting of ESP32 WiFi module | / -#include // Library for I2C connection protocol interface, used by MS5837.h and RTClib.h | / -#include // Library for SPI connection protocol interface, used by SD.h | / -#include // An SDcard control interface | v1.2.4 -#include // Library for TCP connection protocol interface, used by ESPAsyncWebServer.h | v1.1.4 -#include // Library for creation of a web server running on ESP32 , used by AsyncElegantOTA.h | v2.10.8 -#include // Library for creation of the OTA web page for new firmware uploading | v2.2.8 - -/** DEFINES **/ -#ifndef ESPA_INO - #define ESPA_INO -#endif - -#define OUTPUT_LEN 250 // Length of the output on the MAC layer -#define FILE_NAME "/FLOAT_data.txt" // Name of the file containing FLOAT measurements -// List of messages for the ESPA acknoledgements: CS has to be aware of these -#define IDLE_ACK "FLOAT_IDLE" -#define IDLE_W_DATA_ACK "FLOAT_IDLE_W_DATA" -#define CMD1_ACK "GO_RECVD" -#define CMD3_ACK "CMD3_RECVD" -#define CMD4_ACK "CMD4_RECVD" -#define CMD5_ACK "SWITCH_AM_RECVD" -#define CMD7_ACK "TRY_UPLOAD_RECVD" - -/** I/O STRUCTS - Structs containing message and command for communication over MAC. - Must match the receiver (ESPB) structures. - Necessary for esp_now library compliance. -**/ -typedef struct output_message { - char message[OUTPUT_LEN]; -} output_message; - -typedef struct input_message { - uint8_t command = 0; -} input_message; - -output_message output; -input_message input; - -/** LIBRARY VARIABLES **/ -MS5837 sensor; // Object for Bar02 interfacing -File myFile; // File object pointing to the microSD file currently modified -esp_now_peer_info_t peerInfo; // Object containing info about the MAC peer we want to connect with -AsyncWebServer server(80); -// Esp_now constant for peer MAC address value. Replace with the MAC address of your receiver (ESPB) -uint8_t broadcastAddress[] = {0xE4, 0x65, 0xB8, 0xA7E, 0x27, 0xAC}; - -/** PROGRAM GLOBAL CONSTANTS **/ -const char* SSID = "Mi10"; // Name of the net the ESPA has to connect to for OTA firmware upload -const char* PASSWORD = "ciao1234"; // Password for the net the ESPA has to connect to for OTA firmware upload -const uint8_t DIR = 12; // Pin for motor direction driving -const uint8_t STEP = 14; // Pin for motor tension driving (used as PWM) -const uint8_t EN = 27; // Active-low pin for motor enabling -const uint8_t MAX_PROFILES = 2; // Number of profiles to complete in order to gain maximum points -const uint16_t ROT_TIME = 6300; // Motor rotation time necessary to empty/fullfill the syringes, expressed in ms -const uint16_t STEP_FREQ = 300; // Frequency of the 50% duty cycle PWM used to drive the motor (STEP pin), expressed in Hz -const uint16_t MEAS_PERIOD = 100; // Period between two consecutive measurements during immersion phase, expressed in ms -const uint16_t WRITE_PERIOD = 5000; // Period between two consecutive writes to microSD during immersion phase, expressed in ms -const uint16_t CONN_CHECK_PERIOD = 500; // Period between two consecutive acknoledgements during idle phase, expressed in ms -const float FLOAT_LENGTH = 0.51; // Length of the FLOAT, measured form the very bottom to the pressure sensor top, expressed in m -const float EPSILON = 0.01; // Error span in which two consecutive measures are considered equal, expressed in m - -/** PROGRAM GLOBAL VARIABLES **/ -uint8_t meas_cnt = 0; // Number of measurements occurred since the last write to microSD, must be reset before each profile -uint8_t profile_count = 0; // Number of profiles committed since startup -uint8_t auto_mode_active = 0; // 1 if AM is active, 0 otherwise -uint8_t float_stopped = 0; // Set to 1 when the FLOAT is sensed to be stationary during immersion phase, must be reset before each profile -uint8_t motor_stopped = 0; // Set to 1 after the motor finishes its rotation during immersion phase, must be reset before each profile -uint8_t idle = 0; // 1 if in idle phase, 0 otherwise -uint8_t auto_committed = 0; // During immersion phase, 1 if immersion has been triggered by AM, 0 otherwise -int8_t send_result = -1; // Flag for sending-over-MAC logic, needed to handle sending failure -int8_t status = 0; // Status of the FLOAT, drives the main switch and keeps track of the current phase -uint16_t new_data = 0; // During idle phase, 1 if ready-to-send data is in microSD, 0 otherwise -uint16_t file_read_ptr = 0; // Pointer to the location of the last read byte in the microSD data file -uint16_t file_write_ptr = 0; // Pointer to the location of the last written byte in the microSD data file -uint64_t time_ref = 0; // Time reference for writing on the microSD during immersion phase, updated at each profile start -float atm_pressure = 0; // Stores the initial atmosphere pressure, needed for correct depth calculation -float depth = 0; // Depth measured during immersion phase, writed in microSD and used to sense FLOAT stationarity, expressed in Pa -float prevDepth = 0; // Depth of previous measurement, used during immersion phase to sense FLOAT stationarity, expressed in Pa. -// Must be reset before each profile - -/** PROGRAM LOCAL FUNCTIONS **/ -/* -********************************************************************************************************* -* OnDataRecv() -* -* Description : Callback for data arrival on the MAC layer: receives a command during idle phase. -* If the command in the input data struct is 0, the callback updates it with the -* incoming command. The value in the struct will be reset to 0 after -* the completion of the routine relative to the received command. -* Meanwhile no other incoming command will be accepted. -* -* Argument(s) : mac : MAC address of the peer from which the data was received. -* -* incomingData : Struct containing incoming data. Data maximum length is 250 bytes. -* -* len : Length of the received data. -* -* Return(s) : none -********************************************************************************************************* -*/ -void OnDataRecv (const uint8_t * mac, const uint8_t * incomingData, int len) { - - if (input.command == 0) memcpy(&input, incomingData, sizeof(input)); - -} - -/* -********************************************************************************************************* -* OnDataSent() -* -* Description : Callback for data sending on the MAC layer: it updates send_result flag to -* inform other logics whether the sending of the last package went well or not. -* The flag has to be cleared to -1 before each sending. -* -* Argument(s) : mac : MAC address of the peer to which the data was sended. -* -* status : Status of the sending. It evaluates to ESP_NOW_SEND_SUCCESS if it succeeded. -* -* Return(s) : none -********************************************************************************************************* -*/ -void OnDataSent (const uint8_t * mac, esp_now_send_status_t status) { - - if (status == ESP_NOW_SEND_SUCCESS) send_result = 1; // If sending succeeds sets the flag to 1 - else send_result = 0; // Otherwise sets it to 0 - -} - -/* -********************************************************************************************************* -* send_message() -* -* Description : Function for message sending over the MAC layer: target peer is set during setup and -* should be the CS (ESPB). In case of sending failure, signalled by the send_result flag, -* the message is continously sended until it succeeds or -* the max_conn_time milliseconds elapse. -* -* Argument(s) : message_str : Char array containing the message string. -* -* max_conn_time : Time that has to elapse before stopping to try the sending. -* Expressed in milliseconds. -* -* Return(s) : 1 if sending succeeded, 0 if given time elapsed. -********************************************************************************************************* -*/ -uint8_t send_message (char * message_str, uint16_t max_conn_time) { - memcpy(&output.message, message_str, sizeof(output.message)); // Message is copied in the output data struct - uint64_t prec_time = millis(); // A time reference (ms elapsed from startup) is stored in prec_time - while (true) { // [* sending sequence start] - send_result = -1; // send_result flat is cleared - esp_now_send(broadcastAddress, (uint8_t *) &output, sizeof(output)); // Tries to send the message over MAC layer - while (send_result == -1); // Waits for OnDataSent callback to set send_result flag - if(send_result) return 1; // If sending succeeds, function returns 1 - else if (millis() - prec_time > max_conn_time) return 0; // If sending failed and max_conn_time milliseconds elapsed from - }// prec_time set, the function returns 0. Otherwise it starts again -// the sending sequence from [* sending sequence start] -} - -/* -********************************************************************************************************* -* f_depth() -* -* Description : Utility function that uses Stevino rule to calculate a depth value starting from -* the pressure measured at setup and the last pressure value given by -* the pressure sensor. It also adjusts the depth value by adding the FLOAT -* length to it, in order to mock the position of the pressure sensor, which is -* at the top of the robot. -* -* Argument(s) : none -* -* Return(s) : The depth value calculated, expressed in meters. -********************************************************************************************************* -*/ -float f_depth () { - depth = (sensor.pressure(MS5837::Pa)-atm_pressure)/(997*9.80665); // Stevino rule to calculate depth. -// Density: 997Kg/m^3 for fresh water, 1029Kg/m^3 for sea water - return depth + FLOAT_LENGTH; // Adds the FLOAT length to the result -} - -/* -********************************************************************************************************* -* write_SD() -* -* Description : Writes to the microSD mounted on the board. In particular it writes a single line -* containing all the data needed by the CS, wrapped in a JSON format and terminated -* by a new line. The write starts after the last written byte in the file. The -* function finally updates the file_write_ptr pointer with the position -* following the last written byte in the file (the new line). The data is mostly -* provided by the sensor object which has to be updated before calling this -* function, by calling sensor.read function. -* -* Argument(s) : none -* -* Return(s) : none -********************************************************************************************************* -*/ -void write_SD () { - if (myFile) { // Checks if the file is open and the File pointer is valid - myFile.seek(file_write_ptr); // Puts the file cursor on the position stored in file_write_ptr. -// The following writes will start from that position - // Writes company number, - myFile.print("{\"company_number\":\"EX16\",\"pressure\":\""); - // pressure as measured from the bottom of the FLOAT: the multiplication is for m to Pa conversion in water, - myFile.print(sensor.pressure(MS5837::Pa) + (FLOAT_LENGTH*10000)); - myFile.print("\",\"depth\":\""); - // depth value as calculated from f_depth function, in m, - myFile.print(depth); - myFile.print("\",\"temperature\":\""); - // temperature in Celsius, - myFile.print(sensor.temperature()); - myFile.print("\",\"mseconds\":\""); - // milliseconds elapsed from the profile start - myFile.print((millis() - time_ref)); - myFile.println("\"}"); - myFile.flush(); // Commits the writes - file_write_ptr = myFile.position(); // Stores file cursor for next writes - new_data = file_write_ptr - file_read_ptr; // Updates the new_data variable with the delta in bytes between -// already-read data and the still-to-read one - } //else Serial.println("write_SD(): error in opening file!"); -} - -/* -********************************************************************************************************* -* measure() -* -* Description : The function is called every MEAS_PERIOD ms during immersion phase. It's in charge -* of stationarity detection and microSD writing. The write is performed by calling -* the write_SD function every n times measure itself is called, where n is -* the ratio between the period of the writes, WRITE_PERIOD, and the period with -* which measure is called, MEAS_PERIOD, that is usually smaller. This works better -* if the first is a multiple of the latter. The FLOAT is signalled as stationary -* when two depth measurements in a row are equal within an EPSILON of error. -* -* Argument(s) : none -* -* Return(s) : none -********************************************************************************************************* -*/ -void measure () { - sensor.read(); // Reads measurements of the Bar02 pressure sensor, updating the sensor object - f_depth(); // Calculates depth value - meas_cnt++; - if (meas_cnt >= (WRITE_PERIOD / MEAS_PERIOD)) { // Checks if enough measurements occurred since the last write on microSD, - write_SD(); // before writing again on it - meas_cnt = 0; - } - //Serial.print("The just read depth is: "); - //Serial.println(depth); - if (motor_stopped) { // The logic activates only after the motor has stopped to be sure that the FLOAT is already moving - if (prevDepth < depth + EPSILON && prevDepth > depth - EPSILON) - float_stopped = 1; // If a measurement is equal to the previous in a range of double EPSILON, -// it signals that the FLOAT is stationary by setting float_stopped flag - } - prevDepth = depth; // Updates previous depth measurement with the last one -} - -/** SETUP **/ -void setup () { - Serial.begin(115200); // Inits Serial Monitor - - pinMode(STEP, OUTPUT); // Pin assignment - pinMode(DIR, OUTPUT); - pinMode(EN, OUTPUT); - digitalWrite(EN, HIGH); // Disables the motor until needed - - while (!SD.begin()) Serial.println("Failed to initialize SD card!"); // Inits microSD - if (SD.exists(FILE_NAME)) SD.remove(FILE_NAME); // Clears data file - - WiFi.mode(WIFI_STA); // Sets device as a Wi-Fi Station - - if (esp_now_init() != ESP_OK) { // Inits esp_now - Serial.println("Error initializing ESP-NOW"); - return; - } - - esp_now_register_recv_cb(OnDataRecv); // Registers esp_now arrival callback - esp_now_register_send_cb(OnDataSent); // Registers esp_now sending callback - - memcpy(peerInfo.peer_addr, broadcastAddress, 6); // Registers peer by passing peer object pointer - peerInfo.channel = 0; // Channel selection - peerInfo.encrypt = false; - - if (esp_now_add_peer(&peerInfo) != ESP_OK){ // Adds peer - Serial.println("Failed to add peer"); - return; - } - - sensor.setModel(1); // Inits Bar02 by specifing model, - while (!sensor.init()) { - Serial.println("Init failed!"); - Serial.println("Are SDA/SCL connected correctly?"); - Serial.println("Blue Robotics Bar02: White=SDA, Green=SCL"); - delay(5000); - } - sensor.setFluidDensity(997); // and operative density in Kg/m^3 (freshwater, 1029 for seawater) - sensor.read(); - atm_pressure = sensor.pressure(MS5837::Pa); // Stores pressure value at water level for depth calculation, in Pa -} - -/** MAIN SWITCH **/ -void loop () { - switch (status) { - case 0: // Idle - { - uint8_t result; - - auto_committed = 0; - - if (!idle) input.command = 0; // If not already waiting for a command (1st idle loop), resets the command. -// This check is necessary as the new command can arrive -// right after the CONN_CHECK_PERIOD timer triggers. Reset -// is necessary for the new command detection - if (new_data != 0) result = send_message(IDLE_W_DATA_ACK, 5000); // If there are data to be sent to CS, sends an acknowledgement -// with that information to the ESPB - else result = send_message(IDLE_ACK, 5000); // Otherwise signals only that is waiting for the next command - - if (result) { // Checks for acknowledgement success - idle = 1; // Sets the idle flag: while is set the FLOAT is considered -// waiting for a new command by all the logic. Like for commands -// routines, the FLOAT is set in idle only if the ack arrives - uint64_t prec_time = millis(); // Stores a time reference for the CONN_CHECK_PERIOD timer - - while ((millis() - prec_time < CONN_CHECK_PERIOD) && input.command == 0); // Waits for a new command to arrive or for CONN_CHECK_PERIOD -// milliseconds to elapse - status = input.command; // Copies the input struct command into the status driving the -// main switch. If the time elapsed, the command may be 0 - } else if (profile_count < MAX_PROFILES && auto_mode_active) { // If the acknowledgement failed, AM is active and the FLOAT -// committed less then MAX_PROFILES profiles, immersion is -// committed automatically - auto_committed = 1; // Signals to other logics that the next profile has been -// committed automatically. Flag has to be cleared after -// each command completion - status = 1; // Sets immersion status, committing a profile - } - if (status != 0) idle = 0; // If a command has been committed, signals to other logics -// that the FLOAT exited idle phase. - }// Otherwise, the case 0 repeats remaining in idle - break; - case 1: // Profile commit and measuring - { - myFile = SD.open(FILE_NAME, FILE_WRITE); // Opens file in write mode, or creates it if non existing. -// File pointer is now at 0 - if (!myFile) /*Serial.println("idle: error in opening file!")*/; - else { - uint8_t result; - - result = send_message(CMD1_ACK, 1000); // If file succeeds to open, tries to send an acknowledgement to CS - if (result || auto_committed) { // If ack arrived or AM committed the profile, starts immersion phase - uint64_t prec_time_rot = millis(); // Stores time reference for motor rotation timer - uint64_t prec_time_meas = millis(); // Stores time reference for measurement period timer - - prevDepth = 0; - meas_cnt = 0; - time_ref = millis(); // Stores time reference for the entire profile. Used in microSD writing - profile_count++; // Increases the global counter of committed profiles - file_read_ptr = file_write_ptr; // If old profile data is written on microSD, discards it - - for (int i=0; i<2; i++) { // Logic repeats two times: one for descending phase and the other for ascending phase - float_stopped = 0; - motor_stopped = 0; - digitalWrite(DIR, i); // Sets DIR pin with the needed rotation direction. In this case is 0 and then 1 - analogWriteFrequency(STEP_FREQ); // Sets analog PWM generator frequency to STEP_FREQ - analogWrite(STEP, 127); // Sets the duty cycle of the generated PWM to 50% - digitalWrite(EN, LOW); // Enables motor - while(!float_stopped || !motor_stopped) { // Waits for the motor and the FLOAT to stop - if (millis() - prec_time_meas > MEAS_PERIOD) { // Every MEAS_PERIOD ms reads from the sensor and tries to detect if FLOAT -// stopped. It also writes to microSD every WRITE_PERIOD ms - prec_time_meas = millis(); // Resets the MEAS_PERIOD timer for next measurement - measure(); // measure function will set the float_stopped flag when detects stationarity - } - if (millis() - prec_time_rot > ROT_TIME) { // When ROT_TIME milliseconds elapse from prec_time_rot set, - analogWrite(STEP, 0); // stops the motor (duty cycle at 0%), - analogWriteFrequency(1000); // resets the PWM generator frequency, - digitalWrite(EN, HIGH); // and disables the motor - motor_stopped = 1; // Sets motor stop flag - } - } - prec_time_rot = millis(); // Resets ROT_TIME timer for the ascending phase - } - - myFile.println("STOP_DATA"); // Adds a profile-data terminator to the file - myFile.flush(); // Commits the write - file_write_ptr = myFile.position(); // Stores file cursor for next writes - new_data = file_write_ptr - file_read_ptr; // Updates the new_data variable with the delta in bytes between -// already-read data and the still-to-read one - myFile.close(); // Closes file - } - } - status = 0; // Returns to idle - } - break; - case 2: // Data sending // The command doesn't need an acknowledgement as - {// the sended data already works as ack - myFile = SD.open(FILE_NAME, FILE_READ); // Opens file in read mode, or creates it if non existing - if (!myFile) /*Serial.println("sending data: error in opening file!")*/; - else { - uint8_t result = 1; - int line_len = 0; - - myFile.seek(file_read_ptr); // Starts to read after the last read byte - while (myFile.available()) { // Tries to read until it reaches end of file - delay(50); // Slowing down sending rate to match CS reading speed -// (USB buffer is small in ESPB-CS connection) - char line[OUTPUT_LEN]; - - line_len = myFile.readBytesUntil('\n', line, OUTPUT_LEN); // Reads from microSD until encounters a new line, while copying -// into char array line. New line character is not copied - for(int i=line_len; isend(200, "text/plain", "Hi! I am ESP32."); - }); - AsyncElegantOTA.begin(&server); // Starts the ElegantOTA server on the ESPA - server.begin(); - Serial.println("HTTP server started"); - } - status = 0; - } - break; - //case 8: // New command routine - // { - // uint8_t result; - // - // result = send_message(CMD8_ACK, 1000); - // if (result) { - // // Insert here your code - // } - // status = 0; // Returns to idle - // } - // break; - default: // Default case - Serial.println("No command recognized, returning to idle..."); - status = 0; - break; - } -} \ No newline at end of file diff --git a/FLOAT/espB/espB.ino b/FLOAT/espB/espB.ino deleted file mode 100644 index b691765..0000000 --- a/FLOAT/espB/espB.ino +++ /dev/null @@ -1,272 +0,0 @@ -/* -********************************************************************************************************* -* Code of the ESP32 attached to CS (ESPB) -* -* Filename: EspB.ino -* Version: 8.1.1 -* Developers: Fachechi Gino Marco, Gullotta Salvatore -* Company: Team PoliTOcean @ Politecnico di Torino -* Arduino board package: esp32 by Espressif Systems, v2.0.17 -* -* Description: -* The ESPB main loop is a broker driven by two buffers, USB and WiFi one, filled by two callbacks. -* When a command arrives from the CS, the code sends it to the FLOAT or -* feedbacks the CS with the system state (that may be stale). -* While doing the latter, the ESPB tries to send a dummy package: -* if sending fails, it also reports the loss of connection to the CS. Part of the feedback -* to the CS is also the current activation state of the Auto Mode (AM), as it is on the FLOAT. -* When data arrives from the FLOAT, the ESPB updates the system state accordingly -* and forwards the data to the CS, as a real time feedback. -********************************************************************************************************* -*/ - -/** INCLUDES **/ -// Description | Version -// | -#include // Library needed if you are compiling on VSC PlatformIO plugin | / -#include // Esp_now library for WiFi connections establishing and management | / -#include // Layer for proper initialization and setting of ESP32 WiFi module | / -#include // Library for I2C connection protocol interface, used by MS5837.h and RTClib.h | / - -/** DEFINES **/ -#ifndef ESPB_INO - #define ESPB_INO -#endif - -#define INPUT_LEN 250 // Length of the input on the MAC layer -#define BUFFER_SIZE 20 // Chosen size in bytes of the Serial software buffer: -// longer command and status strings are strongly discouraged -// and the GUI running on the CS should be aware of this limit - -/** I/O STRUCTS - Structs containing message and command for communication over MAC. - Must match the receiver (ESPA) structures. - Necessary for esp_now library compliance. -**/ -typedef struct input_message { - char message[INPUT_LEN]; -} input_message; - -typedef struct output_message { - uint8_t command = 0; -} output_message; - -output_message output; -input_message input; - -/** LIBRARY VARIABLES **/ -esp_now_peer_info_t peerInfo; // Object containing info about the MAC peer we want to connect with -// Esp_now constant for peer MAC address value. Replace with the MAC address of your receiver (ESPA) -uint8_t broadcastAddress[] = {0x24, 0xDC, 0xC3, 0xA0, 0x3B, 0x38}; - -/** PROGRAM GLOBAL CONSTANTS **/ -const uint16_t MAX_CONN_TIME = 100; // Time in ms that has to elapse before send_message function stops to try a sending - -/** PROGRAM GLOBAL VARIABLES **/ -uint8_t auto_mode_active = 0; // 1 if AM is active, 0 otherwise -uint8_t serial_rdy = 0; // Flag for signaling that the Serial software buffer serialInput is full and ready to be consumed -uint8_t message_rdy = 0; // Flag for signaling that a new message arrived on the MAC layer and is ready to be read -int8_t send_result = -1; // Flag for sending-over-MAC logic, needed to handle sending failure -int8_t status = 0; // State variable that is updated according to arriving messages and is used to feedback the CS when requested -char serialInput[BUFFER_SIZE]; // Serial software buffer used to empty the hardware one as soon as a new command arrives - -/** PROGRAM LOCAL FUNCTIONS **/ -/* -********************************************************************************************************* -* OnDataRecv() -* -* Description : Callback for data arrival on the MAC layer: receives and manages the messages. -* If the message_rdy flag is 0, the callback updates the message in the input data struct -* with the incoming message and sets the flag. The flag will be reset to 0 after -* the message has been consumed. Meanwhile no other incoming message will be accepted. -* -* Argument(s) : mac : MAC address of the peer from which the data was received. -* -* incomingData : Struct containing incoming data. Data maximum length is 250 bytes. -* -* len : Length of the received data. -* -* Return(s) : none -********************************************************************************************************* -*/ -void OnDataRecv (const uint8_t * mac, const uint8_t * incomingData, int len) { - - if (!message_rdy) { - message_rdy = 1; - memcpy(&input, incomingData, sizeof(input)); - } - -} - -/* -********************************************************************************************************* -* OnDataSent() -* -* Description : Callback for data sending on the MAC layer: it updates send_result flag to -* inform other logics whether the sending of the last package went well or not. -* The flag has to be cleared to -1 before each sending. -* -* Argument(s) : mac : MAC address of the peer to which the data was sended. -* -* status : Status of the sending. It evaluates to ESP_NOW_SEND_SUCCESS if it succeeded. -* -* Return(s) : none -********************************************************************************************************* -*/ -void OnDataSent (const uint8_t * mac, esp_now_send_status_t status) { - - if (status == ESP_NOW_SEND_SUCCESS) send_result = 1; // If sending succeeds sets the flag to 1 - else send_result = 0; // Otherwise sets it to 0 - -} - -/* -********************************************************************************************************* -* send_command() -* -* Description : Function for command sending over the MAC layer: target peer is set during setup and -* should be the FLOAT (ESPA). In case of sending failure, signalled by the send_result flag, -* the message is continously sended until it succeeds or -* the max_conn_time milliseconds elapse. -* -* Argument(s) : message_str : Char array containing the command code. -* -* max_conn_time : Time that has to elapse before stopping to try the sending. -* Expressed in milliseconds. -* -* Return(s) : 1 if sending succeeded, 0 if given time elapsed. -********************************************************************************************************* -*/ -uint8_t send_command (uint8_t cmd_code, uint16_t max_conn_time) { - output.command = cmd_code; // Command code is copied in the output data struct - uint64_t prec_time = millis(); // A time reference (ms elapsed from startup) is stored in prec_time - while (true) { // [* sending sequence start] - send_result = -1; // send_result flat is cleared - esp_now_send(broadcastAddress, (uint8_t *) &output, sizeof(output)); // Tries to send the code over MAC layer - while(send_result == -1); // Waits for OnDataSent callback to set send_result flag - if (send_result) return 1; // If sending succeeds, function returns 1 - else if (millis() - prec_time > max_conn_time) return 0; // If sending failed and max_conn_time milliseconds elapsed from time - }// reference set, the function returns 0. Otherwise it starts -// again the sending sequence from [* sending sequence start] -} - -/* -********************************************************************************************************* -* serial_handler() -* -* Description : Callback function for Serial buffer management. If serialInput has already -* been consumed, when new data arrives on the Serial channel, the function -* takes up to 20 bytes from the hardware buffer, stopping at the new line -* character, copies them into the serialInput char array and fills the rest with -* string terminators. It also signals that the serialInput buffer is now ready to be -* read by setting the serial_rdy flag, that will be cleared only after serialInput -* consumption. Meanwhile all new data arrivals on Serial channel will be ignored. -* The function should grant a certain level of reliability in case of multiple, -* chained data arrivals, but remember that if the hardware buffer is full the new -* data arrival will be lost on the channel. Moreover, a too high arrival rate -* can lead to command losses even on the software side. -* -* Argument(s) : none -* -* Return(s) : none -********************************************************************************************************* -*/ -void serial_handler() { - if (!serial_rdy) { // Checks if the flag is clear, hence serialInput is ready to be filled - serial_rdy = 1; // Sets the serial_rdy flag, creating a lock on the serialInput array - - uint8_t buffer_index = 0; - char c = Serial.read(); - - while (c != '\n' && Serial.available()) { // While bytes are available on the channel and its not a new line - serialInput[buffer_index++] = c; // Empties the harware buffer into the serialInput buffer - c = Serial.read(); - } - for(int i=buffer_index; i 1000: # Check for >1KB size - capture_success = True - break # Success - else: - # ffmpeg might return 0 but fail to produce a valid file in some edge cases - print(f"ffmpeg command succeeded (port {port}, attempt {attempt + 1}) but output file '{file_path}' is invalid or too small.") - # Continue to retry if attempts are left - - if "bind failed: Address already in use" in last_capture_result.stderr: - if attempt < max_retries - 1: - current_delay = initial_retry_delay + (attempt * retry_delay_increment) - print(f"Port {port} in use (ffmpeg stderr: {last_capture_result.stderr.strip()}), retrying in {current_delay:.2f}s...") - time.sleep(current_delay) - continue - else: - break - else: # Different error, fail immediately (no retry for other errors) - break - - if not capture_success: - if last_capture_result is None: - raise RuntimeError(f"ffmpeg direct snapshot command for port {port} did not produce a result.") - - error_description = "ffmpeg error" - if "bind failed: Address already in last_capture_result.stderr": - error_description = "Address already in use" - - attempts_info = "" - if error_description == "Address already in use" and attempt == max_retries - 1 and max_retries > 1: - attempts_info = f" after {max_retries} attempts" - - # Add info if file was not created or too small even if ffmpeg returned 0 - file_issue_info = "" - if last_capture_result.returncode == 0 and (not os.path.exists(file_path) or os.path.getsize(file_path) <= 1000): - file_issue_info = " Output file was not created or is too small." - - - detailed_error = (f"ffmpeg direct snapshot for port {port} failed{attempts_info} due to '{error_description}' " - f"(code {last_capture_result.returncode}):{file_issue_info}\n" - f"STDOUT: {last_capture_result.stdout}\nSTDERR: {last_capture_result.stderr}") - raise RuntimeError(detailed_error) - - except subprocess.TimeoutExpired as e: - raise RuntimeError(f"ffmpeg timed out for port {port}: {str(e)}.") - except Exception as e: - if isinstance(e, RuntimeError): # Re-raise our specific RuntimeErrors - raise - else: - raise RuntimeError(f"Unexpected snapshot error for port {port}: {str(e)}") - finally: - if sdp_path_for_cleanup and os.path.exists(sdp_path_for_cleanup): - try: - os.remove(sdp_path_for_cleanup) - except OSError as e_remove: - print(f"Warning: Could not remove sdp file {sdp_path_for_cleanup}: {e_remove}") - - if not silent: - print(f"Snapshot saved to {file_path}") - return file_path - - def stop_all_streams(self): - """Stop all active RTP streams.""" - for port in self.stream_ports: - self.stop_stream(port) diff --git a/helper/sdp_files/stream_5001.sdp b/helper/sdp_files/stream_5001.sdp deleted file mode 100644 index 7a55745..0000000 --- a/helper/sdp_files/stream_5001.sdp +++ /dev/null @@ -1,10 +0,0 @@ -v=0 -o=- 0 0 IN IP4 0.0.0.0 -s=RTP Stream on port 5001 -c=IN IP4 0.0.0.0 -t=0 0 -a=tool:libavformat 61.7.100 -m=video 5001 RTP/AVP 96 -a=rtpmap:96 H264/90000 -a=fmtp:96 packetization-mode=1; profile-level-id=42e01f -a=framerate:30 diff --git a/helper/sdp_files/stream_5002.sdp b/helper/sdp_files/stream_5002.sdp deleted file mode 100644 index f995825..0000000 --- a/helper/sdp_files/stream_5002.sdp +++ /dev/null @@ -1,10 +0,0 @@ -v=0 -o=- 0 0 IN IP4 0.0.0.0 -s=RTP Stream on port 5002 -c=IN IP4 0.0.0.0 -t=0 0 -a=tool:libavformat 61.7.100 -m=video 5002 RTP/AVP 96 -a=rtpmap:96 H264/90000 -a=fmtp:96 packetization-mode=1; profile-level-id=42e01f -a=framerate:30 diff --git a/helper/sdp_files/stream_5003.sdp b/helper/sdp_files/stream_5003.sdp deleted file mode 100644 index 449c1f4..0000000 --- a/helper/sdp_files/stream_5003.sdp +++ /dev/null @@ -1,10 +0,0 @@ -v=0 -o=- 0 0 IN IP4 0.0.0.0 -s=RTP Stream on port 5003 -c=IN IP4 0.0.0.0 -t=0 0 -a=tool:libavformat 61.7.100 -m=video 5003 RTP/AVP 96 -a=rtpmap:96 H264/90000 -a=fmtp:96 packetization-mode=1; profile-level-id=42e01f -a=framerate:30 diff --git a/helper/sdp_files/stream_5004.sdp b/helper/sdp_files/stream_5004.sdp deleted file mode 100644 index 2f660d8..0000000 --- a/helper/sdp_files/stream_5004.sdp +++ /dev/null @@ -1,10 +0,0 @@ -v=0 -o=- 0 0 IN IP4 0.0.0.0 -s=RTP Stream on port 5004 -c=IN IP4 0.0.0.0 -t=0 0 -a=tool:libavformat 61.7.100 -m=video 5004 RTP/AVP 96 -a=rtpmap:96 H264/90000 -a=fmtp:96 packetization-mode=1; profile-level-id=42e01f -a=framerate:30 diff --git a/helper/sdp_files/stream_5005.sdp b/helper/sdp_files/stream_5005.sdp deleted file mode 100644 index 1b9d695..0000000 --- a/helper/sdp_files/stream_5005.sdp +++ /dev/null @@ -1,10 +0,0 @@ -v=0 -o=- 0 0 IN IP4 0.0.0.0 -s=RTP Stream on port 5005 -c=IN IP4 0.0.0.0 -t=0 0 -a=tool:libavformat 61.7.100 -m=video 5005 RTP/AVP 96 -a=rtpmap:96 H264/90000 -a=fmtp:96 packetization-mode=1; profile-level-id=42e01f -a=framerate:30 diff --git a/helper/send_test_mqtt_page.py b/helper/send_test_mqtt_page.py index 78d4882..f2765e6 100644 --- a/helper/send_test_mqtt_page.py +++ b/helper/send_test_mqtt_page.py @@ -36,6 +36,7 @@ def __init__(self, parent, controller): ttk.Button(controller_toggle_frame, text="Pitch", command=self.send_toggle_pitch_status, width=6).pack(side=tk.LEFT, padx=2) ttk.Button(rov_frame, text="WORK MODE", command=self.send_work_mode, width=20).pack(pady=5) + ttk.Button(rov_frame, text="VERTICAL MODE", command=self.send_vertical_mode, width=20).pack(pady=5) # Quick Movement Panel movement_frame = ttk.LabelFrame(control_row, text="Quick Movement", padding=10) @@ -164,6 +165,9 @@ def send_toggle_pitch_status(self): def send_work_mode(self): self.send_message(MQTT_TOPIC_COMMANDS, {"WORK_MODE": 1}) + def send_vertical_mode(self): + self.send_message(MQTT_TOPIC_COMMANDS, {"VERTICAL_MODE_TOGGLE": 1}) + def update_depth_reference(self): try: depth_value = float(self.depth_entry.get()) diff --git a/helper/webrtc_handler.py b/helper/webrtc_handler.py deleted file mode 100644 index dc4c8f6..0000000 --- a/helper/webrtc_handler.py +++ /dev/null @@ -1,386 +0,0 @@ -import asyncio -import json -import ssl -import websockets -import threading -import base64 -from datetime import datetime -import os - -class JanusWebRTCHandler: - def __init__(self): - self.server_url = None - self.janus_session_id = None - self.janus_handles = {} - self.streams_info = {} - self.connection_status = "Disconnected" - self.status_callback = None - self.websocket = None - self.connected = False - self.transaction_callbacks = {} - self.next_transaction_id = 1 - self.ws_thread = None - self.loop = None - - def set_status_callback(self, callback): - """Set callback for status updates""" - self.status_callback = callback - - def update_status(self, status): - """Update connection status and notify callback""" - self.connection_status = status - if self.status_callback: - self.status_callback(status) - - def connect(self, server_ip, port=8188, use_ssl=True, on_success=None, on_error=None): - """Connect to Janus WebRTC Gateway - - Args: - server_ip: IP address of Janus server - port: Port number (default: 8188) - use_ssl: Whether to use secure WebSocket (default: True) - on_success: Callback for successful connection - on_error: Callback for connection errors - """ - protocol = "wss" if use_ssl else "ws" - self.server_url = f"{protocol}://{server_ip}:{port}/janus" - - # Start connection in a separate thread to avoid blocking UI - def connect_thread(): - self.loop = asyncio.new_event_loop() - asyncio.set_event_loop(self.loop) - - try: - self.update_status("Connecting...") - self.loop.run_until_complete(self._connect_async(use_ssl, on_success, on_error)) - except Exception as e: - error_msg = str(e) - if "WRONG_VERSION_NUMBER" in error_msg: - # This typically happens when trying to use wss:// for a non-SSL server - error_msg = "SSL Error: The server might not support SSL. Try connecting without SSL." - - # Auto-retry with non-SSL if we were using SSL - if use_ssl: - self.update_status("Retrying without SSL...") - try: - protocol = "ws" - self.server_url = f"{protocol}://{server_ip}:{port}/janus" - self.loop.run_until_complete(self._connect_async(False, on_success, on_error)) - return - except Exception as retry_e: - error_msg = f"Failed again without SSL: {str(retry_e)}" - - self.update_status(f"Error: {error_msg}") - if on_error: - self.loop.call_soon_threadsafe(lambda: on_error(error_msg)) - - self.ws_thread = threading.Thread(target=connect_thread) - self.ws_thread.daemon = True - self.ws_thread.start() - - async def _connect_async(self, use_ssl, on_success, on_error): - """Async implementation of the connection logic""" - # SSL context that accepts self-signed certificates - ssl_context = None - if use_ssl: - ssl_context = ssl.create_default_context() - ssl_context.check_hostname = False - ssl_context.verify_mode = ssl.CERT_NONE - - try: - self.websocket = await websockets.connect( - self.server_url, - ssl=ssl_context - ) - self.connected = True - - # Start message handling loop - asyncio.create_task(self._message_loop()) - - # Create a session - await self._create_session() - - # Discover available streams - await self._discover_streams() - - # Call success callback in the main thread - if on_success: - # Using a local variable to capture the streams_info - streams = self.streams_info - self.loop.call_soon_threadsafe(lambda: on_success(streams)) - - self.update_status("Connected") - - except Exception as e: - self.connected = False - self.update_status(f"Connection failed: {str(e)}") - if on_error: - # Fix the variable capture issue by using a default parameter - error_msg = str(e) - self.loop.call_soon_threadsafe(lambda error=error_msg: on_error(error)) - raise - - async def _message_loop(self): - """Handle incoming WebSocket messages""" - while self.connected: - try: - message = await self.websocket.recv() - data = json.loads(message) - - # Handle transaction callbacks - transaction = data.get("transaction") - if transaction and transaction in self.transaction_callbacks: - callback_func = self.transaction_callbacks[transaction] - callback_func(data) - del self.transaction_callbacks[transaction] - - # Handle events - if data.get("janus") == "event": - # Handle plugin events - pass - - except websockets.exceptions.ConnectionClosed: - self.connected = False - self.update_status("Disconnected") - break - except Exception as e: - print(f"Error in message loop: {str(e)}") - - async def _create_session(self): - """Create a Janus session""" - transaction = str(self.next_transaction_id) - self.next_transaction_id += 1 - - message = { - "janus": "create", - "transaction": transaction - } - - response = await self._send_request(message) - if response.get("janus") == "success": - self.janus_session_id = response.get("data", {}).get("id") - self.update_status("Session created") - else: - raise Exception("Failed to create Janus session") - - async def _discover_streams(self): - """Discover available camera streams""" - # Attach to streaming plugin - streaming_handle = await self._attach_plugin("janus.plugin.streaming") - - # List available streams - transaction = str(self.next_transaction_id) - self.next_transaction_id += 1 - - message = { - "janus": "message", - "body": { - "request": "list" - }, - "transaction": transaction, - "session_id": self.janus_session_id, - "handle_id": streaming_handle - } - - response = await self._send_request(message) - if response.get("janus") == "success": - streams_list = response.get("plugindata", {}).get("data", {}).get("list", []) - - # Store stream information - for stream in streams_list: - stream_id = stream.get("id") - stream_name = stream.get("description", f"Camera {stream_id}") - self.streams_info[stream_id] = { - "id": stream_id, - "name": stream_name, - "handle_id": None - } - - self.update_status(f"Discovered {len(self.streams_info)} streams") - else: - raise Exception("Failed to discover streams") - - async def _attach_plugin(self, plugin): - """Attach to a Janus plugin""" - transaction = str(self.next_transaction_id) - self.next_transaction_id += 1 - - message = { - "janus": "attach", - "plugin": plugin, - "transaction": transaction, - "session_id": self.janus_session_id - } - - response = await self._send_request(message) - if response.get("janus") == "success": - handle_id = response.get("data", {}).get("id") - return handle_id - else: - raise Exception(f"Failed to attach to plugin {plugin}") - - async def _send_request(self, message): - """Send a request and wait for a response""" - transaction = message.get("transaction") - - # Create a future to receive the response - future = self.loop.create_future() - - # Set up callback - def callback(response): - if not future.done(): - future.set_result(response) - - self.transaction_callbacks[transaction] = callback - - # Send the message - await self.websocket.send(json.dumps(message)) - - # Wait for response with timeout - try: - response = await asyncio.wait_for(future, timeout=10.0) - return response - except asyncio.TimeoutError: - del self.transaction_callbacks[transaction] - raise Exception("Request timed out") - - def take_snapshot(self, stream_ids, on_success=None, on_error=None): - """Take snapshots from the specified streams""" - if not self.connected: - if on_error: - on_error("Not connected to Janus server") - return - - # Ensure stream_ids is a list - if not isinstance(stream_ids, list): - stream_ids = [stream_ids] - - # Start snapshot capture in a thread - def snapshot_thread(): - asyncio.set_event_loop(self.loop) - future = asyncio.run_coroutine_threadsafe( - self._take_snapshot_async(stream_ids), - self.loop - ) - - try: - result = future.result(timeout=15.0) # Wait up to 15 seconds - if on_success: - on_success(result) - except Exception as e: - if on_error: - on_error(str(e)) - - threading.Thread(target=snapshot_thread).start() - - async def _take_snapshot_async(self, stream_ids): - """Async implementation of snapshot capture""" - snapshots = {} - - for stream_id in stream_ids: - # Check if we have this stream - if stream_id not in self.streams_info: - continue - - # Attach to the stream if not already attached - if not self.streams_info[stream_id].get("handle_id"): - handle_id = await self._attach_plugin("janus.plugin.streaming") - self.streams_info[stream_id]["handle_id"] = handle_id - - handle_id = self.streams_info[stream_id]["handle_id"] - - # Request a snapshot - transaction = str(self.next_transaction_id) - self.next_transaction_id += 1 - - message = { - "janus": "message", - "body": { - "request": "watch", - "id": stream_id, - "snapshot": True - }, - "transaction": transaction, - "session_id": self.janus_session_id, - "handle_id": handle_id - } - - response = await self._send_request(message) - - # Process the response to extract the snapshot - if response.get("janus") == "success": - # The actual snapshot should be in a subsequent event message - # For this simplified implementation, we're assuming it works - # In a real implementation, you would wait for the snapshot event - - # Simulate saving a snapshot - snapshots[stream_id] = { - "stream_id": stream_id, - "name": self.streams_info[stream_id]["name"], - "timestamp": datetime.now().strftime("%Y%m%d_%H%M%S") - } - - # Save the snapshot - self._save_snapshot(stream_id, snapshots[stream_id]) - - return snapshots - - def _save_snapshot(self, stream_id, snapshot_info): - """Save a snapshot to file""" - # In a real implementation, this would save actual image data - # For this example, we just create a placeholder file - folder_path = os.path.join("photos", str(stream_id)) - os.makedirs(folder_path, exist_ok=True) - - timestamp = snapshot_info["timestamp"] - file_path = os.path.join(folder_path, f"{timestamp}.jpg") - - with open(file_path, "w") as file: - file.write(f"Placeholder for snapshot from {snapshot_info['name']}") - - print(f"Snapshot saved to {file_path}") - - def disconnect(self): - """Disconnect from Janus server""" - if not self.connected: - return - - def disconnect_thread(): - asyncio.set_event_loop(self.loop) - future = asyncio.run_coroutine_threadsafe( - self._disconnect_async(), - self.loop - ) - try: - future.result(timeout=5.0) - except Exception as e: - print(f"Error disconnecting: {str(e)}") - - threading.Thread(target=disconnect_thread).start() - - async def _disconnect_async(self): - """Async implementation of disconnect logic""" - if self.janus_session_id: - # Destroy session - transaction = str(self.next_transaction_id) - self.next_transaction_id += 1 - - message = { - "janus": "destroy", - "transaction": transaction, - "session_id": self.janus_session_id - } - - try: - await self.websocket.send(json.dumps(message)) - except: - pass # Ignore errors during disconnect - - # Close websocket - if self.websocket: - await self.websocket.close() - - self.connected = False - self.janus_session_id = None - self.janus_handles = {} - self.update_status("Disconnected")