From f27c9823a144e7c5b45797a1e201ed895297b699 Mon Sep 17 00:00:00 2001 From: Romain Bazile Date: Mon, 16 Nov 2020 17:39:45 +0100 Subject: [PATCH] Integration of raspimjpeg The source code of the modified version of raspimjpeg used by the PlanktoScope is hosted [here](https://github.com/PlanktonPlanet/userland/tree/master/host_applications/linux/apps/raspicam). We moved away from picamera to improve the stability of the system. This commit should closes the elusive #51 and #54. After a lot of tests, it was clear that even a forked version of picamera was not going to solve our problem while also improving on our capturing speed. The modified version of RaspiMJPEG does that. RaspiMJPEG streams the image flux to /dev/shm/mjpeg/cam.jpg . This is passively reloaded by the streaming server (still written in python). RaspiMJPEG is controlled through a special file called a Pipe which is used to send it commands. The list is available [here](https://github.com/PlanktonPlanet/userland/tree/master/host_applications/linux/apps/raspicam/Config.md). The raspimjpeg binary is distributed directly in this repository, in the folder `scripts/raspimjpeg/bin/`. --- docs/expert_setup.md | 29 -- hardware.json | 13 +- scripts/planktoscope/imager.py | 548 +++++++++++++----------- scripts/planktoscope/raspimjpeg.py | 447 +++++++++++++++++++ scripts/raspimjpeg/bin/raspimjpeg | Bin 0 -> 84520 bytes scripts/raspimjpeg/bin/raspistill | Bin 0 -> 125296 bytes scripts/raspimjpeg/macros/error_hard.sh | 2 + scripts/raspimjpeg/macros/startstopX.sh | 40 ++ scripts/raspimjpeg/macros/test.sh | 2 + scripts/raspimjpeg/raspimjpeg.conf | 180 ++++++++ 10 files changed, 980 insertions(+), 281 deletions(-) create mode 100644 scripts/planktoscope/raspimjpeg.py create mode 100755 scripts/raspimjpeg/bin/raspimjpeg create mode 100755 scripts/raspimjpeg/bin/raspistill create mode 100644 scripts/raspimjpeg/macros/error_hard.sh create mode 100644 scripts/raspimjpeg/macros/startstopX.sh create mode 100644 scripts/raspimjpeg/macros/test.sh create mode 100644 scripts/raspimjpeg/raspimjpeg.conf diff --git a/docs/expert_setup.md b/docs/expert_setup.md index 2861b74..4369e5b 100644 --- a/docs/expert_setup.md +++ b/docs/expert_setup.md @@ -173,35 +173,6 @@ The device appearing at addresses 60 and 70 is our motor controller. Address `0d In case the motor controller does not appear, shutdown your Planktoscope and check the wiring. If your board is using a connector instead of a soldered pin connection (as happens with the Adafruit Bonnet Motor Controller), sometimes the pins on the male side need to be bent a little to make good contact. In any case, do not hesitate to ask for help in Slack. -### Install RPi Cam Web Interface - -You can find more information about the RPi Cam Web Interface on [eLinux' website](https://elinux.org/RPi-Cam-Web-Interface). - -To set it up, clone the code from Github and enable and run the install script with the following commands -```sh -cd ~/libraries -git clone https://github.com/silvanmelchior/RPi_Cam_Web_Interface.git -cd RPi_Cam_Web_Interface -./install.sh -``` - -Change the autostart setting to No, and then press Enter to allow default setting of the installation. Once everything is installed, press Enter to start the RPi Cam Web Interface now. - -To test the interface locally, try accessing this url from the browser in the Raspberry: http://localhost/html - -You can also try to access this page from another computer connected to the same network. - -If your computer has `avahi` or the `Bonjour` service installed and running, you can directly use this url: http://raspberrypi.local/html/ . - -If this is not the case, you first need to find the IP address of your Raspberry Pi by running the following: -```sh -sudo ip addr show | grep 'inet 1' -``` - -The web page can then be accessed at `http://[IP_ADDRESS]/html/`. - -If the interface is loading and a picture is displayed, you can now stop this interface for now by simply running `./stop.sh`. - ### Install Ultimate GPS HAT diff --git a/hardware.json b/hardware.json index 795d249..bc89ed6 100644 --- a/hardware.json +++ b/hardware.json @@ -1,9 +1,10 @@ { - "stepper_reverse" : false, + "stepper_reverse": false, "microsteps": 32, - "focus_steps_per_mm" : 40, - "pump_steps_per_ml" : 507, - "focus_max_speed" : 0.5, - "pump_max_speed" : 30, - "stepper_type" : "adafruit" + "focus_steps_per_mm": 40, + "pump_steps_per_ml": 507, + "focus_max_speed": 0.5, + "pump_max_speed": 30, + "stepper_type": "adafruit", + "camera_type": "HQ" } \ No newline at end of file diff --git a/scripts/planktoscope/imager.py b/scripts/planktoscope/imager.py index 2d9a36b..9a6edaf 100644 --- a/scripts/planktoscope/imager.py +++ b/scripts/planktoscope/imager.py @@ -12,10 +12,10 @@ import datetime import time # Libraries manipulate json format, execute bash commands -import json, shutil, os +import json, shutil -# Library to control the PiCamera -import picamera +# Library for path and filesystem manipulations +import os # Library for starting processes import multiprocessing @@ -27,36 +27,22 @@ import planktoscope.light # import planktoscope.streamer import planktoscope.imager_state_machine +# import raspimjpeg module +import planktoscope.raspimjpeg + ################################################################################ # Streaming PiCamera over server ################################################################################ -import io import socketserver import http.server import threading +import functools + ################################################################################ # Classes for the PiCamera Streaming ################################################################################ -class StreamingOutput(object): - def __init__(self): - self.frame = None - self.buffer = io.BytesIO() - self.condition = threading.Condition() - - def write(self, buf): - if buf.startswith(b"\xff\xd8"): - # New frame, copy the existing buffer's content and notify all - # clients it's available - self.buffer.truncate() - with self.condition: - self.frame = self.buffer.getvalue() - self.condition.notify_all() - self.buffer.seek(0) - return self.buffer.write(buf) - - class StreamingHandler(http.server.BaseHTTPRequestHandler): # Webpage content containing the PiCamera Streaming PAGE = """\ @@ -70,6 +56,10 @@ class StreamingHandler(http.server.BaseHTTPRequestHandler): """ + def __init__(self, delay, *args, **kwargs): + self.delay = delay + super(StreamingHandler, self).__init__(*args, **kwargs) + @logger.catch def do_GET(self): if self.path == "/": @@ -95,15 +85,23 @@ class StreamingHandler(http.server.BaseHTTPRequestHandler): self.end_headers() try: while True: - with output.condition: - output.condition.wait() - frame = output.frame - self.wfile.write(b"--FRAME\r\n") - self.send_header("Content-Type", "image/jpeg") - self.send_header("Content-Length", len(frame)) - self.end_headers() - self.wfile.write(frame) - self.wfile.write(b"\r\n") + try: + with open("/dev/shm/mjpeg/cam.jpg", "rb") as jpeg: + frame = jpeg.read() + except FileNotFoundError as e: + logger.error(f"Camera has not been started yet") + time.sleep(5) + except Exception as e: + logger.exception(f"An exception occured {e}") + else: + self.wfile.write(b"--FRAME\r\n") + self.send_header("Content-Type", "image/jpeg") + self.send_header("Content-Length", len(frame)) + self.end_headers() + self.wfile.write(frame) + self.wfile.write(b"\r\n") + time.sleep(self.delay) + except BrokenPipeError as e: logger.info(f"Removed streaming client {self.client_address}") else: @@ -116,11 +114,8 @@ class StreamingServer(socketserver.ThreadingMixIn, http.server.HTTPServer): daemon_threads = True -output = StreamingOutput() - logger.info("planktoscope.imager is loaded") - ################################################################################ # Main Imager class ################################################################################ @@ -128,20 +123,35 @@ class ImagerProcess(multiprocessing.Process): """This class contains the main definitions for the imager of the PlanktoScope""" @logger.catch - def __init__(self, event, resolution=(3280, 2464), iso=60, shutter_speed=500): + def __init__(self, stop_event, iso=100, shutter_speed=500): """Initialize the Imager class Args: - event (multiprocessing.Event): shutdown event - resolution (tuple, optional): Camera native resolution. Defaults to (3280, 2464). - iso (int, optional): ISO sensitivity. Defaults to 60. + stop_event (multiprocessing.Event): shutdown event + iso (int, optional): ISO sensitivity. Defaults to 100. shutter_speed (int, optional): Shutter speed of the camera. Defaults to 500. """ super(ImagerProcess, self).__init__(name="imager") logger.info("planktoscope.imager is initialising") - self.stop_event = event + if os.path.exists("/home/pi/PlanktonScope/hardware.json"): + # load hardware.json + with open("/home/pi/PlanktonScope/hardware.json", "r") as config_file: + configuration = json.load(config_file) + logger.debug(f"Hardware configuration loaded is {configuration}") + else: + logger.info( + "The hardware configuration file doesn't exists, using defaults" + ) + configuration = {} + + self.__camera_type = "v2.1" + + # parse the config data. If the key is absent, we are using the default value + self.__camera_type = configuration.get("camera_type", self.__camera_type) + + self.stop_event = stop_event self.__imager = planktoscope.imager_state_machine.Imager() self.__img_goal = 0 self.__img_done = 0 @@ -149,8 +159,29 @@ class ImagerProcess(multiprocessing.Process): self.__pump_volume = None self.__img_goal = None self.imager_client = None - self.__camera = None - self.__resolution = resolution + + # Initialise the camera and the process + # Also starts the streaming to the temporary file + self.__camera = planktoscope.raspimjpeg.raspimjpeg() + + try: + self.__camera.start() + except Exception as e: + logger.exception( + f"An exception has occured when starting up raspimjpeg: {e}" + ) + exit(1) + + if self.__camera.sensor_name == "IMX219": # Camera v2.1 + self.__resolution = (3280, 2464) + elif self.__camera.sensor_name == "IMX477": # Camera HQ + self.__resolution = (4056, 3040) + else: + self.__resolution = (1280, 1024) + logger.error( + f"The connected camera {self.__camera.sensor_name} is not recognized, please check your camera" + ) + self.__iso = iso self.__shutter_speed = shutter_speed self.__exposure_mode = "fixedfps" @@ -158,12 +189,43 @@ class ImagerProcess(multiprocessing.Process): self.__export_path = "" self.__global_metadata = None - logger.success("planktoscope.imager is initialised and ready to go!") + logger.info("Initialising the camera with the default settings") + try: + self.__camera.resolution = self.__resolution + except TimeoutError as e: + logger.error( + "A timeout has occured when setting the resolution, trying again" + ) + self.__camera.resolution = self.__resolution + time.sleep(0.1) - @logger.catch - def start_camera(self): - """Start the camera streaming process""" - self.__camera.start_recording(output, format="mjpeg", resize=(640, 480)) + try: + self.__camera.iso = self.__iso + except TimeoutError as e: + logger.error( + "A timeout has occured when setting the ISO number, trying again" + ) + self.__camera.iso = self.__iso + time.sleep(0.1) + + try: + self.__camera.shutter_speed = self.__shutter_speed + except TimeoutError as e: + logger.error( + "A timeout has occured when setting the shutter speed, trying again" + ) + self.__camera.shutter_speed = self.__shutter_speed + time.sleep(0.1) + + try: + self.__camera.exposure_mode = self.__exposure_mode + except TimeoutError as e: + logger.error( + "A timeout has occured when setting the exposure mode, trying again" + ) + self.__camera.exposure_mode = self.__exposure_mode + + logger.success("planktoscope.imager is initialised and ready to go!") def pump_callback(self, client, userdata, msg): """Callback for when we receive an MQTT message @@ -196,93 +258,93 @@ class ImagerProcess(multiprocessing.Process): def __message_image(self, last_message): """Actions for when we receive a message""" - if ( - "sleep" not in last_message - or "volume" not in last_message - or "nb_frame" not in last_message - ): + if ( + "sleep" not in last_message + or "volume" not in last_message + or "nb_frame" not in last_message + ): logger.error(f"The received message has the wrong argument {last_message}") - self.imager_client.client.publish("status/imager", '{"status":"Error"}') - return - # Change the state of the machine - self.__imager.change(planktoscope.imager_state_machine.Imaging) + self.imager_client.client.publish("status/imager", '{"status":"Error"}') + return + # Change the state of the machine + self.__imager.change(planktoscope.imager_state_machine.Imaging) - # Get duration to wait before an image from the different received arguments - self.__sleep_before = float(last_message["sleep"]) - # Get volume in between two images from the different received arguments - self.__pump_volume = float(last_message["volume"]) - # Get the number of frames to image from the different received arguments - self.__img_goal = int(last_message["nb_frame"]) + # Get duration to wait before an image from the different received arguments + self.__sleep_before = float(last_message["sleep"]) + # Get volume in between two images from the different received arguments + self.__pump_volume = float(last_message["volume"]) + # Get the number of frames to image from the different received arguments + self.__img_goal = int(last_message["nb_frame"]) - self.imager_client.client.publish("status/imager", '{"status":"Started"}') + self.imager_client.client.publish("status/imager", '{"status":"Started"}') def __message_stop(self, last_message): # Remove callback for "status/pump" and unsubscribe - self.imager_client.client.message_callback_remove("status/pump") - self.imager_client.client.unsubscribe("status/pump") + self.imager_client.client.message_callback_remove("status/pump") + self.imager_client.client.unsubscribe("status/pump") - # Stops the pump - self.imager_client.client.publish("actuator/pump", '{"action": "stop"}') + # Stops the pump + self.imager_client.client.publish("actuator/pump", '{"action": "stop"}') - logger.info("The imaging has been interrupted.") + logger.info("The imaging has been interrupted.") - # Publish the status "Interrupted" to via MQTT to Node-RED + # Publish the status "Interrupted" to via MQTT to Node-RED self.imager_client.client.publish("status/imager", '{"status":"Interrupted"}') - # Set the LEDs as Green - planktoscope.light.setRGB(0, 255, 0) + # Set the LEDs as Green + planktoscope.light.setRGB(0, 255, 0) - # Change state to Stop - self.__imager.change(planktoscope.imager_state_machine.Stop) + # Change state to Stop + self.__imager.change(planktoscope.imager_state_machine.Stop) def __message_update(self, last_message): if self.__imager.state.name == "stop": - if "config" not in last_message: - logger.error( - f"The received message has the wrong argument {last_message}" - ) - self.imager_client.client.publish( - "status/imager", '{"status":"Configuration message error"}' - ) - return - logger.info("Updating the configuration now with the received data") - # Updating the configuration with the passed parameter in payload["config"] - nodered_metadata = last_message["config"] - # Definition of the few important metadata - local_metadata = { - "process_datetime": datetime.datetime.now().isoformat().split(".")[0], - "acq_camera_resolution": self.__resolution, - "acq_camera_iso": self.__iso, - "acq_camera_shutter_speed": self.__shutter_speed, - } - # Concat the local metadata and the metadata from Node-RED - self.__global_metadata = {**local_metadata, **nodered_metadata} - - # Publish the status "Config updated" to via MQTT to Node-RED - self.imager_client.client.publish( - "status/imager", '{"status":"Config updated"}' + if "config" not in last_message: + logger.error( + f"The received message has the wrong argument {last_message}" ) - logger.info("Configuration has been updated") - else: - logger.error("We can't update the configuration while we are imaging.") - # Publish the status "Interrupted" to via MQTT to Node-RED - self.imager_client.client.publish("status/imager", '{"status":"Busy"}') + self.imager_client.client.publish( + "status/imager", '{"status":"Configuration message error"}' + ) + return + logger.info("Updating the configuration now with the received data") + # Updating the configuration with the passed parameter in payload["config"] + nodered_metadata = last_message["config"] + # Definition of the few important metadata + local_metadata = { + "process_datetime": datetime.datetime.now().isoformat().split(".")[0], + "acq_camera_resolution": self.__resolution, + "acq_camera_iso": self.__iso, + "acq_camera_shutter_speed": self.__shutter_speed, + } + # Concat the local metadata and the metadata from Node-RED + self.__global_metadata = {**local_metadata, **nodered_metadata} + + # Publish the status "Config updated" to via MQTT to Node-RED + self.imager_client.client.publish( + "status/imager", '{"status":"Config updated"}' + ) + logger.info("Configuration has been updated") + else: + logger.error("We can't update the configuration while we are imaging.") + # Publish the status "Interrupted" to via MQTT to Node-RED + self.imager_client.client.publish("status/imager", '{"status":"Busy"}') def __message_settings(self, last_message): if self.__imager.state.name == "stop": - if "settings" not in last_message: - logger.error( - f"The received message has the wrong argument {last_message}" - ) - self.imager_client.client.publish( - "status/imager", '{"status":"Camera settings error"}' - ) - return - logger.info("Updating the camera settings now with the received data") - # Updating the configuration with the passed parameter in payload["config"] - settings = last_message["settings"] - if "resolution" in settings: - self.__resolution = settings.get("resolution", self.__resolution) + if "settings" not in last_message: + logger.error( + f"The received message has the wrong argument {last_message}" + ) + self.imager_client.client.publish( + "status/imager", '{"status":"Camera settings error"}' + ) + return + logger.info("Updating the camera settings now with the received data") + # Updating the configuration with the passed parameter in payload["config"] + settings = last_message["settings"] + if "resolution" in settings: + self.__resolution = settings.get("resolution", self.__resolution) logger.debug(f"Updating the camera resolution to {self.__resolution}") try: self.__camera.resolution = self.__resolution @@ -298,9 +360,9 @@ class ImagerProcess(multiprocessing.Process): ) return - if "iso" in settings: - self.__iso = settings.get("iso", self.__iso) - logger.debug(f"Updating the camera iso to {self.__iso}") + if "iso" in settings: + self.__iso = settings.get("iso", self.__iso) + logger.debug(f"Updating the camera iso to {self.__iso}") try: self.__camera.iso = self.__iso except TimeoutError as e: @@ -315,13 +377,13 @@ class ImagerProcess(multiprocessing.Process): ) return - if "shutter_speed" in settings: - self.__shutter_speed = settings.get( - "shutter_speed", self.__shutter_speed - ) - logger.debug( - f"Updating the camera shutter speed to {self.__shutter_speed}" - ) + if "shutter_speed" in settings: + self.__shutter_speed = settings.get( + "shutter_speed", self.__shutter_speed + ) + logger.debug( + f"Updating the camera shutter speed to {self.__shutter_speed}" + ) try: self.__camera.shutter_speed = self.__shutter_speed except TimeoutError as e: @@ -335,15 +397,15 @@ class ImagerProcess(multiprocessing.Process): "status/imager", '{"status":"Error: Shutter speed not valid"}' ) return - # Publish the status "Config updated" to via MQTT to Node-RED - self.imager_client.client.publish( - "status/imager", '{"status":"Camera settings updated"}' - ) - logger.info("Camera settings have been updated") - else: + # Publish the status "Config updated" to via MQTT to Node-RED + self.imager_client.client.publish( + "status/imager", '{"status":"Camera settings updated"}' + ) + logger.info("Camera settings have been updated") + else: logger.error("We can't update the camera settings while we are imaging.") - # Publish the status "Interrupted" to via MQTT to Node-RED - self.imager_client.client.publish("status/imager", '{"status":"Busy"}') + # Publish the status "Interrupted" to via MQTT to Node-RED + self.imager_client.client.publish("status/imager", '{"status":"Busy"}') @logger.catch def treat_message(self): @@ -379,50 +441,123 @@ class ImagerProcess(multiprocessing.Process): # TODO we should make sure here that we are not writing to an existing folder # otherwise we might overwrite the metadata.json file + # subscribe to status/pump + self.imager_client.client.subscribe("status/pump") + self.imager_client.client.message_callback_add( + "status/pump", self.pump_callback + ) + + logger.info("Setting up the directory structure for storing the pictures") + self.__export_path = os.path.join( + self.__base_path, + # We only keep the date '2020-09-25T15:25:21.079769' + self.__global_metadata["process_datetime"].split("T")[0], + str(self.__global_metadata["sample_id"]), + str(self.__global_metadata["acq_id"]), + ) + if not os.path.exists(self.__export_path): + # create the path! + os.makedirs(self.__export_path) + + # Export the metadata to a json file + logger.info("Exporting the metadata to a metadata.json") + config_path = os.path.join(self.__export_path, "metadata.json") + with open(config_path, "w") as metadata_file: + json.dump(self.__global_metadata, metadata_file) + logger.debug( + f"Metadata dumped in {metadata_file} are {self.__global_metadata}" + ) + + # Sleep a duration before to start acquisition + time.sleep(self.__sleep_before) + + # Set the LEDs as Blue + planktoscope.light.setRGB(0, 0, 255) + self.imager_client.client.publish( + "actuator/pump", + json.dumps( + { + "action": "move", + "direction": "FORWARD", + "volume": self.__pump_volume, + "flowrate": 2, + } + ), + ) + # FIXME We should probably update the global metadata here with the current datetime/position/etc... + + # Set the LEDs as Green + planktoscope.light.setRGB(0, 255, 0) + + # Change state towards Waiting for pump + self.__imager.change(planktoscope.imager_state_machine.Waiting) + + def __state_capture(self): + # Set the LEDs as Cyan + planktoscope.light.setRGB(0, 255, 255) + + filename = f"{datetime.datetime.now().strftime('%H_%M_%S_%f')}.jpg" + + # Define the filename of the image + filename_path = os.path.join(self.__export_path, filename) + + logger.info( + f"Capturing image {self.__img_done + 1}/{self.__img_goal} to {filename_path}" + ) + + # Capture an image with the proper filename + try: + self.__camera.capture(filename_path) + except TimeoutError as e: + logger.error("A timeout happened while waiting for a capture to happen") + + # Set the LEDs as Green + planktoscope.light.setRGB(0, 255, 0) + + # Publish the name of the image to via MQTT to Node-RED + self.imager_client.client.publish( + "status/imager", + f'{{"status":"Image {self.__img_done + 1}/{self.__img_goal} has been imaged to {filename}"}}', + ) + + # Increment the counter + self.__img_done += 1 + + # If counter reach the number of frame, break + if self.__img_done >= self.__img_goal: + # Reset the counter to 0 + self.__img_done = 0 + + # Publish the status "Done" to via MQTT to Node-RED + self.imager_client.client.publish("status/imager", '{"status":"Done"}') + + # Change state towards done + self.__imager.change(planktoscope.imager_state_machine.Stop) + # Set the LEDs as Green + planktoscope.light.setRGB(0, 255, 255) + else: + # We have not reached the final stage, let's keep imaging + # Set the LEDs as Blue + planktoscope.light.setRGB(0, 0, 255) + # subscribe to status/pump self.imager_client.client.subscribe("status/pump") self.imager_client.client.message_callback_add( "status/pump", self.pump_callback ) - logger.info("Setting up the directory structure for storing the pictures") - self.__export_path = os.path.join( - self.__base_path, - # We only keep the date '2020-09-25T15:25:21.079769' - self.__global_metadata["process_datetime"].split("T")[0], - str(self.__global_metadata["sample_id"]), - str(self.__global_metadata["acq_id"]), - ) - if not os.path.exists(self.__export_path): - # create the path! - os.makedirs(self.__export_path) - - # Export the metadata to a json file - logger.info("Exporting the metadata to a metadata.json") - config_path = os.path.join(self.__export_path, "metadata.json") - with open(config_path, "w") as metadata_file: - json.dump(self.__global_metadata, metadata_file) - logger.debug( - f"Metadata dumped in {metadata_file} are {self.__global_metadata}" - ) - - # Sleep a duration before to start acquisition - time.sleep(self.__sleep_before) - - # Set the LEDs as Blue - planktoscope.light.setRGB(0, 0, 255) + # Pump during a given volume self.imager_client.client.publish( "actuator/pump", json.dumps( { "action": "move", - "direction": "FORWARD", + "direction": "BACKWARD", "volume": self.__pump_volume, "flowrate": 2, } ), ) - # FIXME We should probably update the global metadata here with the current datetime/position/etc... # Set the LEDs as Green planktoscope.light.setRGB(0, 255, 0) @@ -430,76 +565,6 @@ class ImagerProcess(multiprocessing.Process): # Change state towards Waiting for pump self.__imager.change(planktoscope.imager_state_machine.Waiting) - def __state_capture(self): - # Set the LEDs as Cyan - planktoscope.light.setRGB(0, 255, 255) - - filename = f"{datetime.datetime.now().strftime('%H_%M_%S_%f')}.jpg" - - # Define the filename of the image - filename_path = os.path.join(self.__export_path, filename) - - logger.info( - f"Capturing image {self.__img_done + 1}/{self.__img_goal} to {filename_path}" - ) - - # Capture an image with the proper filename - self.__camera.capture(filename_path) - - # Set the LEDs as Green - planktoscope.light.setRGB(0, 255, 0) - - # Publish the name of the image to via MQTT to Node-RED - self.imager_client.client.publish( - "status/imager", - f'{{"status":"Image {self.__img_done + 1}/{self.__img_goal} has been imaged to {filename}"}}', - ) - - # Increment the counter - self.__img_done += 1 - - # If counter reach the number of frame, break - if self.__img_done >= self.__img_goal: - # Reset the counter to 0 - self.__img_done = 0 - - # Publish the status "Done" to via MQTT to Node-RED - self.imager_client.client.publish("status/imager", '{"status":"Done"}') - - # Change state towards done - self.__imager.change(planktoscope.imager_state_machine.Stop) - # Set the LEDs as Green - planktoscope.light.setRGB(0, 255, 255) - else: - # We have not reached the final stage, let's keep imaging - # Set the LEDs as Blue - planktoscope.light.setRGB(0, 0, 255) - - # subscribe to status/pump - self.imager_client.client.subscribe("status/pump") - self.imager_client.client.message_callback_add( - "status/pump", self.pump_callback - ) - - # Pump during a given volume - self.imager_client.client.publish( - "actuator/pump", - json.dumps( - { - "action": "move", - "direction": "BACKWARD", - "volume": self.__pump_volume, - "flowrate": 2, - } - ), - ) - - # Set the LEDs as Green - planktoscope.light.setRGB(0, 255, 0) - - # Change state towards Waiting for pump - self.__imager.change(planktoscope.imager_state_machine.Waiting) - @logger.catch def state_machine(self): if self.__imager.state.name == "imaging": @@ -529,19 +594,12 @@ class ImagerProcess(multiprocessing.Process): self.imager_client.client.publish("status/imager", '{"status":"Starting up"}') - logger.info("Initialising the camera") - # PiCamera settings - self.__camera = picamera.PiCamera(resolution=self.__resolution) - # TODO Check camera version here - self.__camera.iso = self.__iso - self.__camera.shutter_speed = self.__shutter_speed - self.__camera.exposure_mode = self.__exposure_mode - - address = ("", 8000) - server = StreamingServer(address, StreamingHandler) - # Starts the streaming server process logger.info("Starting the streaming server thread") - self.start_camera() + address = ("", 8000) + fps = 16 + refresh_delay = 1 / fps + handler = functools.partial(StreamingHandler, refresh_delay) + server = StreamingServer(address, handler) self.streaming_thread = threading.Thread( target=server.serve_forever, daemon=True ) @@ -552,16 +610,14 @@ class ImagerProcess(multiprocessing.Process): logger.success("Camera is READY!") - # This is the loop + # This is the main loop while not self.stop_event.is_set(): self.treat_message() self.state_machine() - time.sleep(0.001) logger.info("Shutting down the imager process") self.imager_client.client.publish("status/imager", '{"status":"Dead"}') - logger.debug("Stopping the camera") - self.__camera.stop_recording() + logger.debug("Stopping the raspimjpeg process") self.__camera.close() logger.debug("Stopping the streaming thread") server.shutdown() diff --git a/scripts/planktoscope/raspimjpeg.py b/scripts/planktoscope/raspimjpeg.py new file mode 100644 index 0000000..1095a3b --- /dev/null +++ b/scripts/planktoscope/raspimjpeg.py @@ -0,0 +1,447 @@ +################################################################################ +# Practical Libraries +################################################################################ + +# Logger library compatible with multiprocessing +from loguru import logger + +# Library for path and filesystem manipulations +import os + +# Library to get date and time for folder name and filename +import datetime +import time + +# Library to control the RaspiMJPEG process +import subprocess # nosec + + +################################################################################ +# Class for the communication with RaspiMJPEG +################################################################################ +class raspimjpeg(object): + def __init__(self, *args, **kwargs): + self.__configfile = "/home/pi/PlanktonScope/scripts/raspimjpeg/raspimjpeg.conf" + self.__binary = "/home/pi/PlanktonScope/scripts/raspimjpeg/bin/raspimjpeg" + self.__statusfile = "/dev/shm/mjpeg/status_mjpeg.txt" + self.__pipe = "/home/pi/PlanktonScope/scripts/raspimjpeg/FIFO" + + # make sure the status file exists and is empty + if not os.path.exists(self.__statusfile): + logger.debug("The status file does not exists, creating now") + # create the path! + os.makedirs(os.path.dirname(self.__statusfile), exist_ok=True) + + # If the file does not exists, creates it + # otherwise make sure it's empty + with open(self.__statusfile, "w") as file: + file.write("") + + # make sure the pipe exists + if not os.path.exists(self.__pipe): + logger.debug("The pipe does not exists, creating now") + os.makedirs(os.path.dirname(self.__pipe), exist_ok=True) + os.mkfifo(self.__pipe) + + # make sure the config file exists + if not os.path.exists(self.__configfile): + logger.error("The config file does not exists!") + + def start(self): + logger.debug("Starting up raspimjpeg") + # The input to this call are perfectly controlled + # hence the nosec comment to deactivate bandit error + self.__process = subprocess.Popen( # nosec + [self.__binary, "-c", self.__configfile], + stdout=subprocess.PIPE, + bufsize=1, # means line buffered + text=True, + ) + # self.__process.stdout can be read as a file + + # This will set the reads on stdout to be non-blocking + os.set_blocking(self.__process.stdout.fileno(), False) + + try: + name_string = self.__parse_output_for("Camera Name") + self.__sensor_name = name_string.rsplit(" ", 1)[1].upper().rstrip() + except TimeoutError as e: + logger.exception( + f"A timeout happened while waiting for RaspiMJPEG to start: {e}" + ) + + try: + width_string = self.__parse_output_for("Camera Max Width:") + self.__width = width_string.rsplit(" ", 1)[1] + except TimeoutError as e: + logger.exception( + f"A timeout happened while waiting for RaspiMJPEG to start: {e}" + ) + try: + height_string = self.__parse_output_for("Camera Max Height") + self.__height = height_string.rsplit(" ", 1)[1] + except TimeoutError as e: + logger.exception( + f"A timeout happened while waiting for RaspiMJPEG to start: {e}" + ) + + try: + self.__wait_for_output("Starting command loop") + except TimeoutError as e: + logger.exception( + f"A timeout happened while waiting for RaspiMJPEG to start: {e}" + ) + + def status(self): + return self.__get_status() + + def __parse_output_for(self, text, timeout=5): + """Blocking, waiting for specific output from process + + Continously poll the process stdout file object. + + Args: + text (string): String to wait for + timeout (int, optional): Timeout duration in seconds. Defaults to 5. + + Raises: + TimeoutError: A timeout happened before the required output showed up + """ + logger.debug(f"Parsing the output for {text} for {timeout}s") + wait_until = datetime.datetime.now() + datetime.timedelta(seconds=timeout) + + break_loop = False + while True: + for nextline in self.__process.stdout: + logger.trace(f"last read line is {nextline}") + if nextline.startswith(text): + return nextline + + if wait_until < datetime.datetime.now(): + # The timeout has been reached! + logger.error("A timeout has occured waiting for a RaspiMJPEG answer") + raise TimeoutError + + time.sleep(0.1) + + def __wait_for_output(self, output, timeout=5): + """Blocking, waiting for specific output from process + + Continously poll the process stdout file object. + + Args: + output (string): String to wait for + timeout (int, optional): Timeout duration in seconds. Defaults to 5. + + Raises: + TimeoutError: A timeout happened before the required output showed up + """ + logger.debug(f"Waiting for {output} for {timeout}s") + wait_until = datetime.datetime.now() + datetime.timedelta(seconds=timeout) + + break_loop = False + while True: + for nextline in self.__process.stdout: + logger.trace(f"last read line is {nextline}") + if nextline.startswith("Error:"): + logger.error(f"RaspiMJPEG error: {nextline}") + elif nextline.startswith(output): + return + + if wait_until < datetime.datetime.now(): + # The timeout has been reached! + logger.error("A timeout has occured waiting for a RaspiMJPEG answer") + raise TimeoutError + + time.sleep(0.1) + + def __get_status(self): + """Open and return the status file content + + Returns: + string: status of the process + """ + logger.trace("Getting the status file") + try: + with open(self.__statusfile, "r") as status: + status = status.read() + logger.trace(f"Read {status} from {self.__statusfile}") + return status + except FileNotFoundError as e: + logger.error( + f"The status file was not found, make sure the filesystem has not been corrupted" + ) + return "" + + def __wait_for_status(self, status, timeout=5): + """Wait for a specific status. Blocking, obviously. + + Args: + status (string): The status to wait for + """ + logger.debug(f"Waiting for {status} for {timeout}s") + wait_until = datetime.datetime.now() + datetime.timedelta(seconds=timeout) + + message = self.__get_status() + + while True: + if message.startswith(status): + return + + if wait_until < datetime.datetime.now(): + # The timeout has been reached! + logger.error("A timeout has occured waiting for a RaspiMJPEG answer") + raise TimeoutError + + time.sleep(0.1) + logger.debug(f"not {status} yet") + message = self.__get_status() + + def __send_command(self, command): + """Sends a command to the RaspiMJPEG process + + Args: + command (string): the command string to send + """ + # TODO add check to make sure the pipe is open on the other side, otherwise this is blocking. + # Maybe just check that self.__process is still alive? :-) + logger.debug(f"Sending the command [{command}] to raspimjpeg") + with open(self.__pipe, "w") as pipe: + pipe.write(f"{command}\n") + + @property + def sensor_name(self): + """Sensor name of the connected camera + + Returns: + string: Sensor name. One of OV5647 (cam v1), IMX219 (cam v2.1), IMX477(ca HQ) + """ + return self.__sensor_name + + @property + def width(self): + return self.__width + + @property + def height(self): + return self.__height + + @property + def resolution(self): + return self.__resolution + + @resolution.setter + def resolution(self, resolution): + """Change the camera image resolution + + For a full FOV, allowable resolutions are: + - (3280,2464), (1640,1232), (1640,922) for Camera V2.1 + - (2028,1520), (4056,3040) for HQ Camera + + + Args: + resolution (tuple of int): resolution to set the camera to + """ + logger.debug(f"Setting the resolution to {resolution}") + if resolution in [ + (3280, 2464), + (1640, 1232), + (1640, 922), + (2028, 1520), + (4056, 3040), + ]: + self.__resolution = resolution + self.__send_command( + f"px 1640 1232 15 15 {self.__resolution[0]} {self.__resolution[1]} 01" + ) + else: + logger.error(f"The resolution specified ({resolution}) is not valid") + raise ValueError + + @property + def iso(self): + return self.__iso + + @iso.setter + def iso(self, iso): + """Change the camera iso number + + Iso number will be rounded to the closest one of + 0, 100, 200, 320, 400, 500, 640, 800. + If 0, Iso number will be chosen automatically by the camera + + Args: + iso (int): Iso number + """ + logger.debug(f"Setting the iso number to {iso}") + + if 0 <= iso <= 800: + self.__iso = iso + self.__send_command(f"is {self.__iso}") + self.__wait_for_output("Change: iso") + else: + logger.error(f"The ISO number specified ({iso}) is not valid") + raise ValueError + + @property + def shutter_speed(self): + return self.__shutter_speed + + @shutter_speed.setter + def shutter_speed(self, shutter_speed): + """Change the camera shutter speed + + Args: + shutter_speed (int): shutter speed in µs + """ + logger.debug(f"Setting the shutter speed to {shutter_speed}") + if 0 < shutter_speed < 5000: + self.__shutter_speed = shutter_speed + self.__send_command(f"ss {self.__shutter_speed}") + self.__wait_for_output("Change: shutter_speed") + else: + logger.error(f"The shutter speed specified ({shutter_speed}) is not valid") + raise ValueError + + @property + def exposure_mode(self): + return self.__exposure_mode + + @exposure_mode.setter + def exposure_mode(self, mode): + """Change the camera exposure mode + + Is one of off, auto, night, nightpreview, backlight, spotlight, + sports, snow, beach, verylong, fixedfps, antishake, fireworks + + Args: + mode (string): exposure mode to use + """ + logger.debug(f"Setting the exposure mode to {mode}") + if mode in [ + "off", + "auto", + "night", + "nightpreview", + "backlight", + "spotlight", + "sports", + "snow", + "beach", + "verylong", + "fixedfps", + "antishake", + "fireworks", + ]: + self.__exposure_mode = mode + self.__send_command(f"em {self.__exposure_mode}") + else: + logger.error(f"The exposure mode specified ({mode}) is not valid") + raise ValueError + + @property + def white_balance(self): + return self.__white_balance + + @white_balance.setter + def white_balance(self, mode): + """Change the camera white balance mode + + Is one of off, auto, sun, cloudy, shade, tungsten, + fluorescent, incandescent, flash, horizon + + Args: + mode (string): white balance mode to use + """ + logger.debug(f"Setting the white balance mode to {mode}") + if mode in [ + "off", + "auto", + "sun", + "cloudy", + "shade", + "tungsten", + "fluorescent", + "incandescent", + "flash", + "horizon", + ]: + self.__white_balance = mode + self.__send_command(f"wb {self.__white_balance}") + else: + logger.error( + f"The camera white balance mode specified ({mode}) is not valid" + ) + raise ValueError + + @property + def image_quality(self): + return self.__image_quality + + @image_quality.setter + def image_quality(self, image_quality): + """Change the output image quality + + Args: + image_quality (int): image quality [0,100] + """ + logger.debug(f"Setting image quality to {image_quality}") + if 0 <= image_quality <= 100: + self.__image_quality = image_quality + self.__send_command(f"ss {self.__image_quality}") + else: + logger.error( + f"The output image quality specified ({image_quality}) is not valid" + ) + raise ValueError + + @property + def preview_quality(self): + return self.__preview_quality + + @preview_quality.setter + def preview_quality(self, preview_quality): + """Change the preview image quality + + Args: + preview_quality (int): image quality [0,100] + """ + logger.debug(f"Setting preview quality to {preview_quality}") + if 0 <= preview_quality <= 100: + self.__preview_quality = preview_quality + self.__send_command(f"pv {self.__preview_quality} 512 01") + else: + logger.error( + f"The preview image quality specified ({preview_quality}) is not valid" + ) + raise ValueError + + def capture(self, path="", timeout=5): + """Capture an image. Blocks for timeout seconds(5 by default) until the image is captured. + + Args: + path (str, optional): Path to image file. Defaults to "". + timeout (int, optional): Timeout duration in seconds. Defaults to 5. + + Raises: + TimeoutError: A timeout happened before the required output showed up + """ + logger.debug(f"Capturing an image to {path}") + if path == "": + self.__send_command(f"im") + else: + self.__send_command(f"im {path}") + + self.__wait_for_output("Capturing image", timeout / 2) + self.__wait_for_status("ready", timeout / 2) + + def stop(self): + """Halt and release the camera. """ + logger.debug("Releasing the camera now") + self.__send_command(f"ru 0") + + def close(self): + """Kill the process.""" + logger.debug("Killing raspimjpeg in a nice way") + self.__process.terminate() + self.__process.wait() diff --git a/scripts/raspimjpeg/bin/raspimjpeg b/scripts/raspimjpeg/bin/raspimjpeg new file mode 100755 index 0000000000000000000000000000000000000000..24d3f8cf0fffe30860353ce29b64a96a0cd06172 GIT binary patch literal 84520 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 literal 0 HcmV?d00001 diff --git a/scripts/raspimjpeg/bin/raspistill b/scripts/raspimjpeg/bin/raspistill new file mode 100755 index 0000000000000000000000000000000000000000..509bd2faaf21df152d88e606dbc63c9019cb17c6 GIT binary patch literal 125296 zcmd?Se|%KM_4s`^*+2+E76>)QNLGwCYLEq^qDEaL2-c`8M5Q$!laK@w$uEUt}0rz=jApw-J|Rc#R>HU0|Fq z_F2hdo)RW{^X%JA_+Q~};Np^WGWqIW7bQXC@QqE&D0s8-v=}S_a`NUN-2L@CZ<+AT zY13{m+qmzN?`NkSTDR_Yp(FhWEvX}aQeVa;e?_F%NnTO{>5`zeM{6>6ZeC$@k@Hco3Kh)#D9CxZ zN9P(1jeg-}4@v&sB)x57hOrO$JJNpAJEQ}o_eg&v$=^ZJpGfbM4w2;V&!i7YAyR~N zm?VEu(h(Cgj80$|>8Q#J=qCM5%l9h$AHWl&&qyappOfV83k#V4_VKSh1!56;94VeO zgp@!^B%MJTNg72;BH4dm13y#c&r&cIIEFM<<j_#RKSe#u(aP4fd{lksS;fO%9`fwIYoA#5`lUy<-I{pS<3q3fV*JHF zJbrP`%)4Ii9kJ<(D>JhHXT+};U3bgHS3i94iW#9F9{TWt&sP?&T6x_|J} z%O7uA^snK!w=Bp^d+uld_~^N}?^tqq`?&91c+0}3n?A}Ka{bhIkDa;bUll)pG+O`k zOOGG9c-udJb@1%VE?)mm&TZfP+vAH8lfqBF-}JM#_xDAf{Oqr9p8Va)w>I3p^9Qe9 zF)y^jyLj2XD_;vfcIoU7x_7;H_3=yZExv5)O_BCd&!3ok@ZMReXWg=D?HS*Wzij-y z(fVH;t(=#iw!ifJ;rEp9dbD)?Zz8LgJa*l#p}%_Lnmhi!sQS$xTvuE1!q%HhD>>H*^yV?|8U-jEB`cQ*U(J|-u%%$y$3(JyKCdP#aCTrTo^i5 zo7(!+&UxQmzohVtf*H@f^VUsc+;!f+ZMf>k!9QK|{CO3hKiM_;=_hVJYxYD>#`mh% zU;mxo9=`JAU%xS~vi9T7+ruY*yXmoC?Ec~J&cEpBpsP3Db>?#qtypK7YoIMWy|PDB0SI*s69JBN*fzGXWaaLK>usK3f`#AYKYe?}aZ`jh+!I|G#b z6^`~-JL*Rq^qR%dsy}Hz$kF}}b|Fy8>$Q0x`JY-tHfu@V(8eRYwP@vI$?tIV|9h=m z+W%?@|ENF7r`Z{xm-L9E|A!szs~zp1aP*h!7~fOk?A4$2*XE#?*#;B!+z2o{5;^u|Md);nl--n9PO`g@b{5J-YpJ#5!kjZVAi6@0D76(cef1|I@W{sULLk^J9nn?sT-z zbBuqaqkg7?--(Zt!KNB?Iy>eoB+We)m(a+HsC$ZNc#{2WLAZ(9GN zk0FlshwZ@wW&BGV`5uS8bU5rI?BKWA(SEPiztAsr$UnzH|3yc6uS4J0I>z^@gZ@7p z^8baSe7A$&MGk$Nn^iRi;diTJyx(>3yUCHi(?Rb!hrFjc_#5gN?^%xWXEb?w!C%ty z!rv}O|K$#U_Mv0^eg{AAI^=tiqy0%o`vOOPlOun^p`U4v@@0FyX4G+jk-m|AE3%XPv%@&o_$hl+mA}eEOpOt@sQk^N z3}f#q!`P|vKcw8=k9gUSWJAxr!a5%idM^==wJ&CW3?Gue@oR<=AYY@}`$prFAii1U z4<{N%a&(~oN8mRRC1)~jY5y0LoV?yJQWgKt!_Tpw8%Bd_{~GzcPV2l%>NnBf!j%K# zb1}Zc21}_PBiYENeu%??-Ku?ryc`VVs(d2tGlIxK{spUk=LYGIO9_M-$_0X`5#dEcd1{$iE|N^f1mQbzp>6egkC26 z#J_DA6^dRmVJ- zH4W(J4C=4Y^!Enz7k)q;MejZIuggD^`dc`NajWu8*xOF6{ZaaxPI;j!zkv1&e?c83 z-v;uBe#9J5<%8jWVVbL7o@=qsjOGFP{+|A}_99c&z6t)^=-;o}|Ah8(-YS10zbol~ z&+Y+zHPb$@%`i5o_BT+zUGYD{7;fB7KIuK`sP;beF(BV$BOQH|Y#89@4*K_R#YR;9 zG}^o0V16ihm(kw|!@GxykX2z`TH4P@@i}XKO+40QC`vk4b}cGhrHL4pT+zP zsrGx&-%jk4VVmv$i2W^Oek7A0!M|_7PwQ*UUsawBKbtv-t5@UyCga)ulY#NN;b%Ae zg;f7L$!9$>U~ew!Z(A5+>U#wKW*;5zcwwObpF)3K(|~*)!XA3H@sEVRgU|~qex8Ni z^zRwQag|S|za7sFwEqtLhp@kpDlcUG2bVD(#sA&Z-%S6IF~{EqKMfw288?VLFQyM^z)xU<|_Xa_?g6b zeJXzr`a8H{fS*Co*XK(&`A~3Re$IoxB<6$YOZwjeecPXVkgps79mn2m`nzbK`6%;Q z)!$5h(qECk(${a{KYP`H{N8808+r!jOA`9X(&$}Iz65)BD|z0`c-s#R_|N+&-_2mB ztMa`=!EeS#WLo_G82)mYe|G;p%$IiL-JtkurabVh_0B-XHxK$d|Bk;?{9a4__~Xco z=Td$p@+=E82G!qi^1I)GhRU}xzV)%0t#H!kQ!1*f zO7n_lSCkrNvzqGK`huG3Y6#Sp7S)$p?aQmm>y3hfxs}yb1$FgBR4EuBY!kDd)R)n& zq~M#_es|Fqn)YG5NoCCnBLY;GRwBvb zc~(~zOLI%>HNn-DR+SW3jjX2wWcAT}ne6;3C*hLPy87B`H7rXjMYTnhrD(07&hB)8 z{3+E%-Nh(xZgs6rpkFwZm8jE{;;Ed}mR6J&)%9BfMsNyQYs3|$Rdeghv_aSO^L45) zP7%1(wq|~Pzk$xLFRu^-HTfv6uBs|6t}n;FPU%v6t_$$X@+g>JUR8hT#M82cxC&~E zgm_WKS5}yf&6gHceP#KV$jco0DqfWh*>iD0aY1oKIYwwr$hyh`b3!dB2D3C@P*Yzk zl9^pwTsbXw>dXZbrRv;@siuieF&odUm-%QvyQ8$WzI5T_`uf`P*^_H)ixyEbg%Q*O z^|Fa`cyN1FxhQ{vj+gU%W|_{e>xFi1dDXl? zZS`DiklY>RrT2*vKyP3yb!8wqSWkUvUg^U6`L(4&;rjBbk{iTk)r_!Nr)V;|USQXi zs%E!2MfF8O$eOA8C{7vSl#gzLST(0Qw|Xv* zrc(xh=PA|IwIu^}rlszq5M?%eXZW%Y9w zfFWH?8X}+>_?1BU!qN)KqAXtQPsi%L|-WjMo~!#E7-tusZde0sGz#0RF<}Zg84Ni zjK*3RPg^j5HV(I-ZV{$YD%Mt8SzaY`nT(~5I}uv-eKY6R&M9Id@;Jxx{@N1;Hnp}E zyQdT!ixg%|5@prZb){3PtLBu?mHdq?*5ySN<@cMEZZ4WvI%R%sEh923n}&U3WzpQy zo2Ji@Co}IWsF$y6C6^nO z)g^O`x_fKu=g7knasHP~G)gK=d6rZZS1<~)b&D$bmq3BBQcs+ur6HW9ERw8j#bu?Y z{)#IL%Bt&>R~^uYttg8knwnc$Ra|K*)4~d>=2y;U9j&RQ?^@j3Y(>fP%Vw`-<@XkF z{X@Do^VM|2)?=w`UpmIK<>0b`)r*-9XD~sypIclk3$_#~MMAoFMBeU)q%O#PMJ)1mvBjT?GGNOrWL&i(yh|n+wMFF!p9jT~zuZ8J z#m1aD74z}z#39ARSEUP~2aYIfhy}~*s*A6@vY@W6xTtE5QB_n`T~|?BT4O+5mRYkR ztqNpXh| zR$RZRrnF$TC_yNp5$U=LjTm$8t1V}S&XHhNq#Q>|8qDo>gB2j`J<^Re`D{4-qTw7Yg;?@7G-&W1;iBZ`$psf1xs=0LqM2mGq@|7hh zy!1@n3bsM&RO{hJiKsx>Vveg;N_ z_6o2M;mL}u>juUkoRpN#DVkq_O_>dAYD*Uo_7s%NudLCV*m7Bbic9nYyK__evuo!T z71UQ3)XtqTsP;8YQyByrgV6AOH&Wpz$PdCdTqxGHUH zXQ^eto@HoraT;|*A*_~l_u>Rft$5{hRn5&L3|SNHbTx|ZoBeMJtE$W>SC$RYyv)?o z4xx@1&f0$&i{>w|_$eq5d$s22X&cSB^+xf#1w}PA2o{HH@@JVCwoAA~ph|gVd2ua) z1BP2theJKxC|H5&#qpr+lG3>{2~mVmUs_aCU2k!NEki(dpwdAJ2Nbtbhb5|Dew{u& zPO*8S5LN&l$tePBH_MvYyESb&B%wFce-N=$mev-@Vh@*Z7%xO(5W@QN{(6<*0TTTXXw=VVeYv_Ec5F`9I^|tYg)XR zQKG}33z$z9w-T)w}$ zS|XkT6G|Xp_N1{VGlJ<{Tl3|)Zp8=Ma$#7~{x>V2P%CEhIluOXS%z&eqWFOcs=GCN zojqmvCDryqY!{o$x@qSnrS*hJrzf_k-$&L}&n~S{vs#YYWbT=hsk(~IL+*{&PYcW} zxZ%d!sr~k6#bgC#MO6}5pH@gYGp3yO`ByA~UkU{rGM`gjjA`kfkOL6&1aQDC9Zkg7 zSk6nP;OQ4^Q9!xuU6B7NmL>)LtcqJ8XsWBO9e8FL20Tcige1tKp#01BEQD&st;t5% zRvZ)9oSOvVnnRM9=ieAh@uFhfLOmO~(+U>9UObOINYR37q6Rb6v3NYyotr+R$fjX0 zC(3nb611EVwaw*QV_&Ny+{>vi)648ng-&zW+lz-KbS{@&mt|U}nCC1sYZed?vYcqE zmxF45$R-DpNdBw)zj5ZRN*s=8!Vy%NvM`6MHZANhub)yd@scdV#;)kcCR|~RFRQLB z9bY@U=zc~sJ_qxYJ$&7G7V+_cilVA{_0?4ZOY8fyxcr(@x$j?FR9jwJH{R^B@}8Q~ zx#RKrwNx${KU)F+;8I0seS7ZT?v~{i&41_Scef>xorg{vBu=%Ui9u{wGp5 zhEls+pmw>z#PzaRgI9R{f6{J{+1}>KE|NA@k~%sCsUbA%QpsC?18pR4jYpovn>`GS z!K$t2E&2ofST(GtmYi(bc3XjVx&2JqTe7n#S>*%Lknc$T|NY;i@zy&~FCt4SFXt`b zVB=4`TarJK%(GuAA9PB2C-2pGb!2!+R(rQr9&22~y%j02h#~Tso%d^KHeGFB^ z8Qm&xwU5=>yNrS%R$Zzq`Z4|G^6d|A8jTVK%M`3paG`ECurwEL5;W!FmOkDA=fAlY*@ZZcuQu zf?E~buHa4ucPqG8!2=2&Qt+^X#}quS;7JADymS}&Br2GspjW|k1v3=PQgD)j*$Pfq zFjv8Vg82#-Dp;amje_+GE>y5l!4(QNDY#C-4GIPo+^XO<1-C2MuHbG3_b7Nk!Gj7O zQm|9OV+!^vcv3-QzOo|)Jqji%n5_Q1VhR zUcn>~!Q%>^RM35&ns*8&DVVBYx`LSsW+|AhV2*;h3g#)8 zuV9IS6$;iXxJ1E51)CIXRd9oXn-$!q;C2OfD7ag}Jqqqs@SuW+6bvbNOu=3Sk1J?! zZ^!h{3dSp#q+qgwsS0K&n5m#o!E6Qn3g##nP%uxySqhdYSf*fwf(sQ~qF{r9O$xRs z*s5Sq!OaS8QBdw9$+-3^xL?5o3WgLstYD{t#}z!G;7JAJ7b$yD(4%0gf?fsF74#{X zrQjq5a}=DeV6K9*6wFt!P{9fXYZRG8!L15zQ*ft(?F#Nz zaKC~F6g;TlVFf!CJf`3Y1y3qy+^^)Nphv+Z1-%NUE102RmV%QM%vNx^g1HI?6wFt! zP{9%fD-^6zuwKE13T{_$+hU8)?F#Nt@PvXV6+FJgs&_)clL{K&ww`AzIO#houb^MS z1_g7!Yn2BS%u}#c!Fb|=(cCXe6v#a#k3bALN#I4?GZJ_McfSNya3@OOx4CO1@GF2^_=SS%G{QxKN;%`&k0dv;j^{q4Kp*!I1y10;n!t(NI}>;* z_qzmgp=^)9%kVn_FX!H=z$>^*EN~Kc+5}$7{Z@f&SVID@=Ki6;Z0;BfyoS4c0RAn6R&1>S`I z1#)pMUEs~=U*Ik1U*N6iUtj?J3%m{e3!H)e1D z;5X5~z;B^{fp?*Qfn1C$5%@poU*O&7Utj_H7g&h?1s0)yfwR%Sz+&_-umt@JEJgnU z=b(RqbJ4%RGW0L79Q_Nt2mK42hyDdJk2VXeME?S-(7(WH^e?am{R_Mo{R^x`{{rjK zzrcF*FK|Bk7q|fZ3%n2g3*_S90fCFqzrg#^zre-lU*Hn-FYr6)U*LDqzrY6cFYp2M zFYrP1FK{XP7ubmY*=K!i8TuEv9Q_M?2>lCOf&K+PjQ#~ag8l`rME?St(7(WD^e^yx z=wIL}^e?al{R?~){R>=;{spc<{{malzreNVU*O~DU*J0QFYpQUFK|8j7x;bjFK`3; z7q}7q3w#p&3v5IG0)yyZ;3o7h@G0~!@M-ifa5MTB_ze0N_$>Mt_#FBdxCQ+S`~mtG z_(SwB@JHxh;8yf6@W<$1;7`!Mz@MUjf!ol(z@MRifzP9Vf!oo)z!%WJz+a$$fxkrm z0(YQ)fxklk0)LJE1^x#83*3qR1@1!s0$)V`0$)P^0^8BQz?ad#z*o?}z*o_~z}@Iy z;A`mFKklP@hZ#rX8+LWNL*t_EP+Rnj(5g^;?~Boao~7ZL8lJAHU0 ze7lBk)$q+4zCpuVHM~i~8#R21hSzI&g@%`Cc)o_`X?U)N=V*AghG%JbriQ0$c&dgc zX?UWByEXjer<(jV{FsIx*6>3ben7+bYWQvq->Ko-HGHdvZ`SY)8s4hmO&Z>);Y&2U zUc)OiyhOwEH9Swlb2U6i!?QI!OT#lYJYB<6H9Sef6E)ne;U_=Qh^{A2EDuqK7VTjvBsTB-Ln+{_~5zqm9&Qbhkxg8(NPT2Jw<7*fFNB?`XZW zHG+{?U+a-ro~8Smqgm87-oJN%HQA&Cz&LBFRHaA|;bjNnTPq z>2~M@sOtxo0DZtR;Ca9b;Ag;k;I>QKqT$7D-G(<5aruLhg*=;jZF4xbCfMP*YFN*R zYnsC`i(|X5AHFht{@u;t+;f|wg_Duf_07>4XBtQ2;QO{SjH82rC&n5_Q+*qwo^K85 zaT_x`9*i;G&x3xfZ&j$}s`#E+zUHt8=sx$cBd$PWm|t&;#L6{#&2jnQITJQU1EZVc^3HFL zGmLLVvf~){Xr7S%9atvu7h_C}o_=VI_Wiu(e0hu>oC!Bj6%^KT=PA$7MZPF_?xe+_PG*p~mq_~lB z)nA&iVfbCS>sarqU7en*l6yvZf{~Vl+7=n^3d0hsMAh*g*1^gnej)%PA{MCTN-|kI!{q2 z2U$!W(;W6P=iQzMu&p)GR8Mns%P4F>WEKc^NLi|9W7JLAQ|ftKVMEA%9?$a)JRjt1 z3B4`)_KLn|M3(mTtzSa_dfz+f_uKUANjRsc?Ofw%rSO2=J)a^!n};rZ!BNvEG>N;cNJ+8m;YbTH%o5-Uw_$uEFm+nzg_MtCKhE>sv>2lVc$g1={lMho z?1OvRW0H2hXMOW5_+HX}(j=bk2FkPezp?i>Tt+YW-X8YLq!Ms%i1LH%cS(oOj4{$b z1pblzI%)bb_W9In>4x_2*&CDg@~oE;T>-8A;BL~kkKmhUZc-*mM!dI+y)`L|v5cnf zjad_YE#y~lrn316`*hkgG~Z?TuODvQ8o2F_q!ZNVS!X9_48Y^SEsSvo_$=^5(pk{S z2L^z9KY>r^Oagk5Lk@h(?+^4c8xsG@`Gzko>h*4n#`^L5Mr-r~{FwOPzkSU(nrF`Y zR&(A2&fOU0xFsbpAez2YFy1xq1y?MTg|?oFvl@@{L1h@8H3ad_4Or4KNky+El)&;z~Apg zXOx|wEHo3F@&_YvfmI<+g1TJ(#_%8`FY+;EvbHt4)*cC}vHY{IFQswvvXC3Qk$xps zc$2g#)}inTWO+y_H0{Bg`kT}YY57yG3tntJM(bbe6*Z3L@@0%1~KcHTKah1T+ zLw$Yki)~e8Axr3sZDquPvxcO2tvT0;OiG|DG1+3pyTo~mzyqU2cGlQ48T$&=M++Vt9k^l=AbK37*G}h<|ahj%Rq$ zalEyrW}pv_UK5O(#*i1DJVr~@j~q9DEiIY>E%7OLYU}pe&->Qz6ka_8bNj8&`i`!G z*ZuG#zEX5)@(Zu^LZdJk5!=oWtPCeGcihI>!(vzR%;lXDjxp|#pO;F=G_V0rYjnO{ zR=7MIOPM@lp8Yy=Fh1HRam)byeCYp#@#at_e%tQ%4wLuR=myI2r5*g9LAl89R#hgx z{SnF+s`BBge43-YRh17_<=1KD4Yc2;%0*8?{|c>q0p)usPf}$*t*nwVxA%$YDYBL&WgutfQ#N>^r#W218sG=d@-#>5 z!DSC~;{1Ib=sqI0eBy$A9kJ5C;9s|%%Y5$5*w?ZD+_yV=zrJroFLh*%k@Y1D81I`B zmOWd`RcG`(L;s$XvwCEmSTe#m8ltZTct{GgMjPVOqQPYB0iS%_c&%fm%Xn)YWs?8# zAmgq0S2jiyeQV)2KXNrXcA0WuPd9=!%DXh0g{_@5UhPN%Ps28c6Pu@bUXBd+z7k0` zmaB=;7|0uREd#o7N zT9XEIQp#lxNSUm|7bRI`SE(|IMeXw6pJSEPf6y`D`cpToQ_ zLS{FiUzZV#WRKh!^^ZlijN^3UjBj5WO(Z3g?6IaAOQWyQhrOo$k};lejPcn2_8t8h zV-#PV#NK%+ed6~!T9u5xImk%K^gR~MyvWoC`|#kJOyBagqQ9iT-^7m9T>XrFU#p|9tEdyv>JW>q-|nb0 zfjaL~N9LLAH}bMN`I%ACur0;bSQzn$agX}j35r@kDMd%#A zVBgEg{nbKW^K0yHUaJ63$9`K<#`K6^or&y4rsYZpY)Sk1ep=)*?o=HdKhbxTSgfn% ztuZ}YyVJ~fk;9D_;bkj)JV|Qm6xt$_Y-m0$>j}6I+sH)smx+7=f$)|%BSCCAH?P^` zQ+Ue8?iZlf?DUPCi805RAITo2H=CBo=U?Q-Pl!%r?p%Y9vuR2BKUBH+Dtj#V!oPj?HV@n| z?uZQX2VKM-39?VQ^k02uOmXnKwCKU%$cR0>_$rCd&J=%zFB-;}Y zs{%dWIH#upe4W@lXP|?;!Hz-r7D__r>RchykiXuZ%t zPHWr`hQ^*3?3hKYygnu-6yuu`dLlM9B;$}hRz7^pVGMD`ogMhMUwiIP?wJkWvOa8Q z+<9^y&i+PZIZWhj>V8#d8*Tna-Ea{`(q1XW)d|JI#)Ef&uiSIIl#EUJ>(LcZ4*8P{2ZQURKrmZ{l zqqgpj@3(ckg2=xmNLF7NW7kkOuEqdXX9mD!N_es2=D|ASF?`-4$G?PR`6eK&q5(FhRV|31WC?wL&Q z#urA8uio_3*x;sg`b@-k55niha3+h-@4B5dpHxhmN^+4#aOTMs8P*&2eej&Be9xUR zMv7PA0q{x6f8$56S?er)9M28T;YEj{J0rLzx&rywHg+E8Hc5(x7hKNJ#fK*#N3q`( zDn7JmT4ye@wib?MjM#xW2N>&j{@G`q|4TcG9py|-;+*O9n=a?;tP$c@WbVI6T^Wn1 z1MT?^^<4ClPFwN4?9)>+z=sryyr+conJ2qg6J#%#AU1_>Or?G%`K)&O0vFn1?=1;q zdQNzAJAMY;pJ5xH4VS$=b&z`_{4W{V7G3koz?^7NbK+6vgtQeJGAB0CUeSAgcK>-3EV~q6I29hfMtfuy<2A>@-d*^Td67z+%*oglK1SX}CAJguz)w8u8+L_l z)y7uF${E~@&>5kp^4{r$cX!9V_^wIFdOPRShOf|!?`{3bSj1k3F;4dMU2^s< zKAwGz*m*2+jbr~b8kw9C^ZnR!kjp6WG04{SE!s$XTMl>9e&8JYn|{^}{zBL7+be&G zelu&No3P>4H(d>X=REnZ+8v*!L$8GXhYiobaH{YhdBSH&m>?hjrd=+m|kd=D@vv`NV%Ise|W58eVi=iQZ?xp^J_lDQfYd<8m8RQNJ*b6>1m4e_wcCi@FJK*(xzfVfdpfo(erP{u z)BR@~Y8@FvUvj=BKIrf4M-And#^aY#@y$h5@XlFpB4;Q=@xNlTUidaz@agdNJndy| z72ng&xqc>Ry@Jcx=}z)8r}x6Qz(N^kJH9HkfxXIxs3*jJ7d&6+gU5px^UgCKJP|xG zuq^Bb_q1<_F1U7S*d=jvJ9{|#7d{g4LlWbyhHmLC&EcTX@i&I!6rT-BzK>8Yafa~q zI6TSOwX@CxTAlAv=dh|HG^8)l!9uOhGV0iI6F+~OB4<$II}LyE)med+^1lUn-|cxJ zD(Aa0uW!Z&OaJ%LPU?C&^W~lGh)+19eVaXw^&VtqgjYW)lZf#`tWgr{mvPQK3;Erv z_N&e{q0w-mSHNo%S8rrpPMR$Q$uP;-lxuxBNP-NA?;b@1HQP<0CEK zIg&nNj1iF-pskyg=q8bIN?hh)Uc`gHIG%UO;BN4EpaFCPPhJWg;0YkVo7z7Io9F|- z9PwbohdH1Ah49b#k#C&aKP85DCH?U#GFk7wj5CDu)0lId5h+>N`-w+IcD^8cqm9uO z^p!zfGe%%OGM_sdpk=PJ$lAH4kH>aI{(lu3EzCc)Pg^N+CXU7Bq`WD*WY2|dMgEBo zuzdn@H2p!4GxK$vEn6`q@e=x%_3`JlJ1DXx{*eBCo{iBHyq_~#0^wJYp-ty5`Zz#) zi7mvAt`b=U1L4;{AJFBiobAfl;|a!Qc#-Q@$l@0G-obe<9y0POxZDHzA$jo?FOe5G z6Taje-{WnGCVE<;t1lfJVjbshNK3Tk8)JIbj665wrfki*V?zed){HzaB(VwS%U!Zp z61~ZOX$j}hGS+GEdmiJI=c3ORo?ox@$+>mE9?!uZw>ZwH$HLQ@VvmfildPa6`&vSWNw39xZ^1g#{l~YINy2%T?RZuStUcSNe1oV6*bRJZ6W~bz1&< z@|(5%wdA*H`K!q9)bf{;-=pOxl0Ts3FCib&@)wbhS^Pw|fAI_ESpeq~{dQfBZ5qBO zu=i1s$>3gaxd*cT3*He~=f{ytdEY;gm`eBMamdZh921$1g#HHFi9cDyU5ZZ5(&bF% zan7I%p<%BhvJU(co!IT%w3EI)^qs`KO&ki3L${ke#u>&v?L)Wqc$xpQMy0E>;;pQ! zo_|v>Mb%p=`vPctp?xN_z3>zRPxSMC60(@K*y_haKhx)J>q(e5xaal7pZ6qkw%c;m znLWa*&G%ax&wqq|Cg;tzt-K@s(T|^gMvL#!Xydc*8M^rEJv#l8)6oC9Mql=#jT-&m zDEbZ1zYM)4YxKFdW%8b=c;BJXmi1Qn|Gq|h3$zYuv^SIY;sb5pbmixkk88ZrnkR;T zO>`OU@wXj`De}$_pX#;VJul$-IDCZcw~n({5`S)RrpwuP*KcI4_0vYy1uuIt{E4g^ zvd-A+hO8%FwRZ6B|553y=y=~zc{d||Ao;4aXj6hcf4Os}`HNlDTLv#u&riK=TD@^v zz2~X7i!)}~FU!7SFLhf+Ee)M_Dd!9DxSBoGVb0)Veg2T(2J#ahD*LIMY3nAYi09lU z#p+T%~xtx#N z>zWa0Huo_f`~&*zl|D;@H`b2|>O7W}9;)GtJC!=Eu>*X{UN6?46I$&)mB(~=%%-jI z8AEI*W7sNvVaxHHDY`uH?Rk)OV0HA>>o&pngVAL87XK-0s_aE&%(DNKaeJWm2aniy zFd{OOG0D5_SfeHMYTBmI33fN}w72c&2k2jPup6Gei37Sa?{TPjc?LAwXd`ip?2pCQ zeEM16`drS6&3!rj3%`#ekKWH%%euz&lM-vJ*UynLL-aGGE2+g~pGyw!fzBIyDcx*AUMR z8<4F>v+sYw`%3DGJ{NMfF7J@JT}xclOrM3C3^^xXzXRTETa|kh z!kdqNa-rF&e10=)#UbkH{C`{H{}K3agfBZ*CH`6;&v~&;S7@FM&Cn;7zP-P-^zHi! zeG9L%q0hNG@8!4)0WI6#39Y-ezUR?*sn+)!^u5s0_sPHa9etU;n|SWj;Y}K?SOZYGo}A)wKg}=CZGO8r=gvt)tgMcM2&Xh_yO88p?!;@{dKKP z7HzJEwwzl|;(U3MoG<$xJu(6PyRaoYo|=zrA7*?v0Of9P2jeYFlXvl}LS@{A^&7#+ zVJX{2n-DhW*?5?PtI@R5+Wy^XoJ{)oGM9Ph;1=x_azB%_V> ze*KYWp&@qL$t6n;DGWa;kCa5cB+hWmc;36_h{OhC`o_C{^N+r+J=FD4CleZ()RVJr zsYfi);Wg>63Q65$+T(X=JJW1Cs&9OUdk{MnQY$n((3k{`Ngj)ajLq;&4rS7A6X#2l zM=TAAZeI3m<4!d6OxkjvZh&5UT#T`kG#z?n(95MxF6}M8q33%C{>=I#CQ;_$J2i<* z<(cf6GK8klc4R5?eTzHNspMrYn&a`l8ujo!TMhIRp`Qr-Stl4f`TfM727j|WZP6NN zCYk!9KYy@;|3Bf;oB(v#pU9o3nucA;(s!(}_K56L#MdG1M+|gGS*I6%-QtJPzl?V( zyx3*Q^ta-;%e+X}WZa9*|opaf953Z3huZd=}{+a6o zV-z1)KNwvEhy~CU{4Yu6;wHKZw|8%epO8Kg4OcSsMCR+2W6o+JH`#BjPe!s>$Y zF0Nm8@xQn*&!FYr?v12e(yb)9_bc~>my%YKhEf+^BbzU1i?&|QxR9BtQ{o(1OXV(e zD{-;-mmKaf_abA)5s77d?Gu(qd(mCR*V>|kkb|rTVs|;rgBWOjL|GnX_H(y)dH5Pt z7N#s)D~qS>a>@?zJVSe)$aC?xLhoJ5JX)EDvI|w&Zz;3+O7bm_Vt-woqX+s)zgD_KCMojnB-VIbv$5csI3{_J_eiFXRQC1bk7e(St-)Wa zu{^pJ+6~Yis?k2G1tHsWhQMe zJXAwF2yMIn68e9Y{-y6S%51%q!H3+Lw(}L_x$D;DW8RbqZ_Kj{a5=ZIX?e*fdz-^Q zg`S(a!acW?zw`aWpm`g+-bZRFho!81ygwZ4z23ZcN4-(C(8;I%ab)81z8kG# zo#eh3qoI zeUo=Kq+@${k3!l(Y9ehTwuqpyFrM47}oi`jAu5V+Z)=V+i4fy zz+St?;`88nzqI(o#xA06S= zfxVmg-UM8}M?82Ndd5FX%$Z6&_+r|!u*3_g>?wD1XZi9myjvn~pp!zQHTn|I&NydT zSk`@m@u&0b*E|z{C-JP&BJp5r^aY-M3N5p3FxcVc**2b4{H!fnF@d;Y8}V1*`$y!Q zr4ZeTKiSW_V2L|zUHlQ-N}^oy;$II@el314i~3gF&-aBM?%d&{($%xKXp<`Rg3Zw( zzF&WsDi#P89Cz=skB|huFu#xjg^+ zZZpR0<@s9brtT*u<-58<)n0s!>?4F1`OYHXvv}q%U)OYnORU(!hjE)fa+&X06VZF; z)4Xd1P9n`BtstKb%mq#&`N1XM`4sPgN&88=Nf#3r zz*$=Z@1GiY@7chf`}h<6aGp7exHi@>f}_|kb~GV7IpY-lk71pb-z6#WJ`mo+8lA}eIDCfUKwC40M=ijQU8< zaGpZXX1&nH!`BU!`!zw?19!NOSiXK8dKhou$N$Sb{^CF2agoL&zpd5JW8q)beiI%u z|3Bcd`9I(>pz+w9Fu>zZcG0qCHf}PEaqzf8lcT(wG3_gqhQ{A(8h^=( zzmq}3xCH*h4hO-P%r6&yNNmJ|y*x=@9{;XR{-4|Z^7m0c5!;e6)Py)+Xt#b#C$as> zBW2iQlDXF>7UzyYVmt90^VGC^V!3!_kBBB=7=B#(Y5ZH?(I<(qeY8zSPWpa1QSF!E zFeORZ{14#Cf7ps&M#0N*sDBmzKE^NnFW2}#=iiKX2E0i9`?dPR{>$T?P9L-XgYi}} z-T-5icx@!SxWWIM@=u4KYySg&ZiJuqu*FY2{M3X0H~BH(C*?oj=Y06_DSqPM=P+*o zeAsb1cIXZ?hvV9V9ec5@y~?)sgk=3%eMEl$NzS6=-L$MN^39y{4z}3s5Ny?-V7=$` zCw$UFOdd=9QE~^GeHmKeEDE14^=jy+#9_no?q1G(crTcejt%=*FV49C!|tyqczd2p zAX1tXjI<~0>)7CLg zu?ZhBw-5Zkse?B9`xX8D-_FV1@U%5#@iPb=6oS{FgJg6ttdM&VA--KfHm&U>O+NNJ z7|{b~eU=`$*G`<;VZWC#xR+%558wBqB4fEDD0iJb_!Bp{#OWU5nndw0(5Qj;M-=aJ zeyaNuIXe_xh(Ae27jnM27T!HP*~%V8xLB3+w;)^A&5MP|hdpq414`WQyzpI@y-H_ZLTGJVeJr6b-JCWaLM8KW%{74MX zB>y#J?qv_=M$R&ZWRp)TFT5vddEwbZ{vzb>M{aVitjpi_=W)uP%UqDVoygnl>oE2` z0ex)$3wsUrh@y{la2ewY&Qn)hZqaMJ!>2j@I?F*32<&Jax(S8w{9zV?&nz&{g}@@YZx1L&!eGB2kfDkx(CQ_pzc@o>(lz>eTQia z()T2X{c@(;)da18gBEtsKZbOTmKRzRO*>f{y~RQ6YG`qe4EYWeSq!Bg^Ndx^hjXLjcXB3a?%92hMoVHWn=tijJcxgIAS&m)+u={z@ecW@@Y+P1 zCTLsp)|!iABiMP@LTF0eMbyPNL@KCTahkf!JH}zr;e?}(JcG79u zcFS2G_3ic#QJ+{K;-S9hH1#`FeS7SSsn0qX={&bB+BxCN<9OHP&605;-(c^djxEPM zl$ap7pX0nQ~I|?Bq!9byD{bYm+Sl z7zwHNaUw zKQII60rqy1_z|N9U;{82m<&92gv5^qwFAG-S;^p`-k!l{pW8F|;;}u0uRgCw_Ha#% zS@!vs?emQ~YpSe8_B+~SAMxqXT|Fm)oKtbS&$YyjMP0)E3Q9{HCk*U(UDUYk22XNQ~1Uv0+PeF#aLN zAM98LUt4a&9(@5bZn)Hpb!J7*6MHjeMQ#Dc0Pp0vE1vnA%$n}n*CFja+;fmvT;kL} z!tcj}xW~l4`4Z~7@Bef6k$F3M1_5urtF8OU;vGG4^DgL#Sx0{rS z?WZyZTizlQ`94PCQr=UiWFV8?2X=KP6C1jQ%!r(C7+1|1cYRpCM>&gkJFZEy!*kA= z9De$`rJ=Jtlf$q2f*tbPO}x{K9>8Di7hBcdm03(qAyb9q;Xe$v-> zk?ixM+$Y_R9aLin|F`?3`{Aka9cyeC z!OJA@uj1c@tqT8lYW!bLo3E<>3A{-Co3#4L)bE|fnGUwUnRP6N`4D7Hk@Ydg`{I{`HD`EZBBE_xr@QS5W`S53%isB<2rBE=CrH(ablR+!X+Kw={=`go4E0 z%-dj)-@3ED&9-5zkrWxsciNMJ&BV#y>zu+|P2}0t!1Li(?)rUb(hNi{=UM-md@6h! z&EY4c%omKzov@F4Y)KIpdk%cuXurb!;0+4T0rx6=I=Cy*s-FuUqws({A8I|%17F8D z=hp0t%D0ik2_vRt1V_+ctn@R-yKnRc?oe(Y^*Wz1)M!judJV5 zWMj$#`J_>{Rr~-x;C9-T1)EvZgB>e{hL?93(3O0jcXrs1PTkPs`;M=q$2TY`vK9!v z$wE(bNc;OVdXg7O)>jU>U^Be9> ztb?Q-q+a%e@(#&9TM+vedzHQVigpq{$@Z_ZR!oxblvva3Gluw@N29h~$-c+n-JZeu zg2&f7+O%o($z9yhaq!N*ay0A7=x@PaeVjGd|J}KQ`Tm4`?ROc+*5A2|>5p6c*j#Yg z$HvI-a&qP)X9{xWB(bpUvCn$s!|n{ugybw}7-KP5Q}ghpavqdutnDm(WLwX6k*nqJ zQZf?C%rhf{b0VKs??=>;^MV+DA5qQ>ro~zQum2gm$@$SYk?ps{Kk#m@oq5}?&0ASF zv*0h$^JrAoQITCHe9HXU&v%`MhxdvtmVfw!yj$`?E1$ym@d?3)xfeW8=USe5B=5KC z%qBmi<&luP<>640_PmMb$r>&By%V?p;ZTCVF_fx3U(fSG$s?yh2C+Z+gkWPRPVN(G z&+~YmF8OU%y#wUq0*{0)NI2Mie!{x$p@C%~yX<4iGNi5=*G2q($RZ1bj2}xQlS~KI9>NEatpF;)Zf zMt<8Oo;i_CUH$$PE@6G9_zQfR%_*=_w7`)L|AvG_;~ z$rvMBN3x4 zcf)cPZtH0W&m`8Acgp%0j`Msw&!yjYpp&Du`4MIEUU?kjT=BN0*L3ul1>X4(?~F~=i-hrcw*aqUe8u}}gd1kzY9d(J%iTAWdZxFtj13XWV-`_~$PK(If^k0-;tIFjY zR=LNL@Zh3f;+FT}G2&j9CoBueH_4wuQ_j=%afl3I`hD?1G0+e@k-K?u zjK$slsC8~>@pGbYdCUpUv{_f;ha2CE_fnSkKwDhiy`%@)MgvF7Je9HXK055FG57S( zcp93YNk-Qp^y2pIr@vswZergI#-s12@vrNX#V_~<{9^kRsn^A>*0;+XW{e`kdlX%{r|I0Ma~FL5I_m0t+^y!qCZ3GW1qs`d$b8?ecz;L$+rZ1!8h=O)Dn}|18csAp9SUuhcaj; zs}W0zA&H;pBwn9RY9b|)T8P;__+pW%-1m|>?rGQ+|2%ZXwp01ujeMuzoF$m|eEQnK z&*lt17u|Ee$L(qODA~^)olpaItKHx6G+=w&<)OXA*CMANUr9b*LeUxXd zc|U>gH?i5)sQgZ~JQrEZGdatUb}n>O=CSt40qjBif&2!W{O+3Ep%OnT^G5E8$sHTN zsymgs_B$S-FR_YEpYQ1tyo$cO$KCp> z-X&|5=|`Cp66cA$I08w)mv!VbpJL2$THjFc?k-F$6M3At4UMs%=G~RDL)xitC-R6H ztZydv)R^7d$D7QU0j91NHT3@4<&0|61c39<{DkN^sw-i$g^&-LHH6mKrfaw%3ZiD z4qBt-yM|$uhhDL4zmPa17rbyC|8J@W&Z8c&>^iHxjo;QB(35<7qkAbcIO^ptb)E>)f~`%$CD&aq*6z0Rr)55Px*v$n`SyR<$EIG z^9yufGz7wb#IG5?cTHR1`3U@lc^-FC%83u~s|kMrcXg>|!je<6Uy!)s}A(WBi-&ME&Pz&%5icef%>2PY<&m((VfLSNemI z=cyxoiySyZ?~?s!HgsZrj~_ATCh^)H>d5{x7PtZXlQnV$unhY z*6$G2ui$r^m=`k7Wp2oOdYR`kpTstYF;>yxO8EId)V&RSRmHjQzxGZ7VK>DcKuamD z3neAm1UD~QMAYyqSk%pniXK`LvUgrEB-_035;<)`f*^$&3$>PNiKn);y`1w&DOxV2 zHi%a1(H5=VVvntR@3;#WNe;K=oO*gZ<$iy&*4kM_+I!Fce(vXU|LDrhnt5jCndf=t znP;AvHM^`A`;B%r$C!P3TlZ@__um*CklpXlw)ig{FdjIi!!zcl&6(5SR`*K4>S9bR z=UK^9%%k}wK%1s+PfwIHUq*$;!_uSBbGdBSkmxoY+wv09xP$uLi})tf3O}3)A(vX~ zoXbGp!%&mHpP5U&<@lSCDUG3S>P$k3QH z)_}Zs<`t-{zO%&6e8L?=vyiKO(C|#hk5A@PM-aWDawBM4V?<-^tat{`cQeNFyYO{} z`OO#mm6T*jxCN<0w(;LmM(f>2fYUs!vVv9FcU)LwUz4u8@L4SFG3&MPR%Civ-;CC%H_0rx&k)LL?7vp@>IY^)5*nV2;dHwoj z-??{LbDz2$Ty1zKxqa~g^f1rsKXUe4x(Oe_FlZxfyv4bHAv%hgokNWKPUg z8sDjE-SGtPk}dH*2YjSIE&47Q`W|gcCrG9=56e!_JaQ5ol+Ic?r1$Uhp3P^kj(P)O zqx+q2YeVli{loC-6D}s7HjC9i-+5`e#QJ%#&kxi7W@Prq)c@Rnb^7=g>sRgR8~(v> zudbD>n*xzCaFv{NWky1Gom+tfr#A8=c&d3m$8$T+VxGA?tYJ<~;VI@pXBqv@cxL@) zVd^+OfqRkF0C;G;$~OOZcyq=lb9Lb9&;JAYulw?2L-OAx|DZ2_<&b=IU>*QXF5+l&&&5SYw|4Tv3ZVf;T}7l#pKQ4VVv}t zv)Htw^^0_t&czx17T$?&7+fn%18=PX76W_qBJOFs{Ae<__p!{}obsgh>U%HkPCXh- zC1uY|bnEi;q-WzZcC%-(7f|1Urybp)`}=f{Uk&ftQ+NV?>f0{i(>>eKx5oY~d(hzI z_#My>*LJ4QTrIn9Szna8^-b4?C4B!}&bQ_}unW4e?|Piy=Q!E6Eq(bWeV1#UGWwsf zAGo$7TfU6)(t%^U~la}~>1?vZBce3cq_#x&dbq1|~{0RO9-F3t|#Q3RRhsUGtdziDkU(HB& z=ko1l!F^kK-TWjXl*gY<%{bbTSpkgJ zL-HZNOBf=%r7x zl}dn#xG&m%XmukFwrDCShw@Y=a!2vEtfe(eKczgwUcn> zz&q*7*fL~^G~xJJ>J^Uf1RPvHL-;adK=jZUSZ4TjXP@i^!JQyqc~|o;eWkQA`f0wM zWXy?2^O29-h?#ed4Rabk?V}x)3usSzQD^Y%)tz|@sl!`0=$uxp5Zbiy+jL>Rx14}% zT90JH;Hx%p2b=P&d&ZRo_GT{5(vLkN_@1DC51;Yw_{xJ{V}Z4Yz{b^Q(zT{@c;M8r zigfv&kBi6P@h9Gs@K*D$`W2kXngLwG)6f@D_M)&Mr(tvShJm5KI!`U!Mb|WC$6B3f zwuB7+&!yD=WZ$#Yul!!#r7yP`UO#+dLKYWijX8_*f`1zLg}}xB0^C&Kpebh)SZ^$n zF6+$PXl&=C))uE8!O!#Fe0*a2`OcO&zf*8d@)AZ?ih0KH*gWzpBsTN?Y&+`*Lg~=M z=7~@dvs^|7nQ?!f@F)Jo9)K@(j1Welo}U_Q@Xmr<^C>L;PFBpC|rR;!m9Xdtfa4xlAMBp%-3B?f=;; zsddEf=h@ElC7#E49_RTM&v$uxc#^C&JpY|^?AYkeV727lr>}2D#&m98`uZm0D`!s! z*y-gvgX0rBgN&O{0r1}aY^0$htTmdStowHMkA*Jco#rX&=dcf!It=V4AFOn`VDFNA z(5~)-(|XOuXQKPyP-NT(H`pHY%bGG@`7x{yRDO|LUiZ8)k8sc1V3~Z%T*vo}!#F>t zwTN)kyd`{9cBWfacettS*db+Q3weDDyX}=yhPnHc`mcU*KJwi#bAJzGN8f3UAwHZj zly5tFsw}+oq{b5KoXnk+l`kpAI8ght3C2>d)=vkR6Xk=z$1(2kF=tL0c3+pd>k57u zeLRf&uAXPS$?niNwds%MG}ZM3(zi2CrV)DgBOmN>YzmEs`l~9evu&(Rc)ECEJY_s% zc$WVI-NY!@lzs^h3Uwe9Q5HJxcy*@-KJm;NF;VJ-+f4%*bXBL`bJsp z`e8cVwx5^o17_a^VD58awD;Q#%#I7dG`cX@?(R3o;_0r;5%AMKve%~OrfMHvvRj4I zFDQ55@A1{<;8#UPp5W=?*~C-Bvz$kISo_4<&peGE{>)bFZJsB2I(b&`$VVety1WEg zLY~xC7pjx!b>OrBvMKz2|sKAsnO^4W7Rdx7YrG0?HVzX!qIDEeaD*hE`8xTY;V z9G)EGX6`dnA2xHDWNSoPxzdslL^Sh7Mn z-Cd~ud$1Uorq2c+a8nuj6bjzmmL6N)mVOaDq(@KFzVI-134NAbsZpmv^Vewn3ZLPQDAVPU(9-#DV=r{kG2NzT8L-=bNo@!d1HJ z^wh6rah0x9U4METI-q-pS!KyQ&VJ}VRBXsYsw>~Ci+V=i*pT|>RP?u1Y0g_nW?9p| z`!@U&oxMF@(OWdr8L{_~F`e)5^sOzwS=kcSAcNm5mNM7$e(0$I`qHO1E&67a_hu&X z^QgL?iE_2En(kF0k*?E7gKgeA`dF1K7 zLY@8AJ*LgzBj2dx&qAN;PSXHq)P&!|lo!vm)|IW~;jH<=`~DGqGR|gx(77~EzJ5>t zpMr*#{6P7(#_Rf>eJaDYlvLeLA&l%->Gkh=OpWj6>{(JfyDC`Xu?HdsyQaKcV2H>vOI9)4Jng+S}TP;v5C(?6-yj zz)p~ykfyOXhWWh!nSWaNwqa|MKbyGrO>(RiDem72ot5tK-*MIE?71ePi^iVl@-M&T z`wQNMR{$J^8@@SX+e`O)xFL(k*b2!;KIgGd33d#)l*smFPTM8i!kllQU*gGG>eV>H z=O3yYf(J6Wr`(6b>%g)fd1~GeIBb>e>emZCJk&n@?USt9zB-Ol#~(<0@jI;jU~WE$ zyo_V)NuCIg8T;@i*6Y{}W)HLM(Gx2z*#NsUi)`2Sw;oJZK*xn)XD-uu4$V=&Cr$V7 z3D*C+gLjZVk#zm$v+Ugt?q`+{`YgY%JpS8`4|*Z(x4BOjHiB@`I!yO#XxxjRk65go z%DD5}&`oR0ow`@U?4@2$zUc6ev?ZEq4@2)qc>egF)_#O#@mnbDQNBRFc&4?NaR1S7(c_Av`*QKK8rqdXpK{8u z=Z)+TVguNO(eBhAD9_zpIzMwr`-K{NmhIdtb6RbKV}Ly2?2I+ZJ9|;|qnrLB+eXiB z+Q6JAeN%?7w!AyF;Ry7m{^o$Y*I+$*Lf=tq-$r+VOXq1^yruTRN$ncmneoW|^VnXp z8_bR_JB+6i=rsfUwC=x@eBDROIXHY5JJa|E4Zc^2##0zSWh&>`^Niy?8)<8X z8L!+o9$_t_{`G=`?Tjh)(eX_^XwENvoc@iGZR++n#=Egq-S=|dpP+0PvVS2xHJ)*& z@3hari@VhpeIM?&DPN!ZthKc_o^?LRqRyW(7KF=~Fu$c}%0-R8!b>~srePP2d!27e zM!WAvcz=zuP1I5Mgro0f5NbT_Td#Xl@V^l1pWzjALk-{X)$r||@Q+nOGwgAlhqe++ z(()N-j_}Spi=UT6+nOnkoj|prg0MT6;dAHM(zv=Qjy@FcB$xjDe;_~cSMqm|-~3nd zA0mH6U{L;g==X|yw`69yWwgJkHaGBYYyoi6T%oj0zBIvYVojUC#`p8h`=(p%h}JrP ztvN>go9DKH4{h9HH{M5l`E22{-0bVI4|=MXy!-`@<_U8$p2 zb*H{DE1l&0Lmp=r^0@OW#8~J{q!_o>vSc9qY?AM(Q-S1LN$iX70hf`V)au>B89~0m zi}G8~j3tdp`OLdohYy_CesEwr_jb?a`>=~YH2d_6+kZGP{GKfX!|vP0{Qtv&7g~Qf zFt!5S4BnEhVbDXeul3~|`uH{I=gfPm+qpkl=%W>b_^-gsy>j`b%8P;qf8@ZRtzb_Z_n@1I#&Cy>W3exfAVv{PBcu5gvPhhwxFt zg@pPJ=PbN9J3-?WdT{1YW7EPXJb9boj)#~pO?qnIL#(gb zc^*f;y11VS-fDl;?s^~{>W1Fbsr97uJFUAi_akSr889r2ulmGW(r?kef0Z18hvb4e zeUE$qqK#xV7ajg0aQ)Eb2<3IxLbK|j+@Baro!}&V4X)Ioe(+5WRKRYQ9_4!<*=Ip) zY~d%IhSR?4S?$*I9`$HE(x;GMr+GD0Pa?s!uc=0WY;y_Vy%mnNQ*GcJ)QNPyLZSaVPdf0p(3um)1(J{tb5; z4k@2cd6iZEBFaT*Q+>!~4pF;{=m+|f-|RX+eJ<%|NKZcM^eY1XGk9d97d-3uVr28> zZx-zyJ>i{QlYDA^^3Jb)3j8ek_D+ED$av7XHTaj3Z6_H#!C3<=qCTsxcBgyJINHZ}!G4cw?LBVJjh*Qoh1hA>4zr2BZ?hIAF4+pqa(qB_ zjCbs*zECN5bKPLhftj;l*1eqN_hQ-#KbRaTnTSNwoG%H<_u{4J8(D$R_~vu0?!d|^oq5na^bWl8V9x!M zGY%$E_LwjI-`w;Z$_6>Vrm{MdBfp+k_KXX|yp@IFY<;N92Xn%O!LH51V5@}WBln-P zpp9KWK}W2VJRqy$k!bJ}%9Gcp{U^zz;^2~zk7pMBD@IOq#$XI#1UvoZm}SlTI^Q~X zFdlf$Y-SAb^zxJ=M;a?J;$iI5zjVHCtj#=xEJ;?Pv=K&zb-qqGDQ(kP_7c8^Bv99T z?X-a{r7`w0e0v%G89nTsd6BJ(9C~_~y~6F%Bj^S*wjR@*fQ-o3>)EwIqvw)F&&ke~ zpIG*xN0U}V)4_a=v&&sxUx|#U9{tX5F>6cHZrK)o-?fu_J^4*vcU&HF`BGqQ$#AY9 zwBCIW^Da5^z6;TsX-2d&Wz-`d+3WE4b$BUS=q#)9Jsnnt zep>{b&PREDX8&Z*lfe7?S!Qrb>JE@oI%6qcF*0Cut?Cl&r-9LL*XlQHIiHoS?;og7 zYg2!HC2oCB`rw`bZq^XE%Url`0JjZ3OJ;V!XMQu|+&049lBYJl9jqsfP|rRd$-v4b z=+?6Clz6lpd5~=uMF-{R`wL_Tyi=9p75ML-!g>T*U_O!UKU!n0>Y`5c$d*hwFw#$# zNiKj{LpuCV-R-7dOZrO6d-tB8!_Apm)R4Gvq1Xv(*Bw zoJq!d;8zcHF!K@co~)I_tKa@wGMY4NyDhGqNe)>5o3+WWxSQXrTkC(dSN7q-G<+B) z?T;4?rZE?qv>*E5@K>0$rM~)pNm`BDCNdI|Y;EEPd&HA%(EJ@e_*^xfpQI0xAv6AL z>>&7{GjJLM7y{enXAz!^uh2E(aYW~+@G<(*?^0W&>rCu6=qtMdI)&6H*&;hGkS3n( zq?~vpU9tVGbEo7lMpvce+b}eR-_mCZ=(!zw{uBMkf7t1V{Kuznv&%3l@8=pbE(~U=nZ&RGT?H#nI{rw2?GWIJ0YaTpU$TOZNmuCjgSe}VI zi+N7kU3^a=TZ8YK&;$4(3&p20XrjJ(XR5@XJoqF1uD#Wh&|c$1wEWFKojWxKcu#j+ z2kp*6yXM^v?aJ|sN2v1v?HurUuk-oTFF7}7L#Q7caQh>`=>AfTC*foEEXvroq)ju2 z_D0hM%#)ywj&s&C$o(#j6R+PZsY7#=;VJy}#);PJo$z+FJ61gS>A+9-;OUd*PRW5_ z^MPd?ohoqq(o4rC(x1aTr#GQ<2;aHIv3<1OTH(ztZC?NQ&DiMR+=5QPKIZJbb^GXm zY?nlL4t5yxf%Dt4xRZCy1V;AcblR3od;9cN4V`J}%HO}~=pASKbdy&M@Apb z%3h${;Y~1M&i-zn=<1GY$(PmLca>;{J}M4$X4WbVnt@~Lgpr|W-&E502G`h?qLJud z9Kc^}?@T}G!f5W6zM2Tl3h)sr{|Yy+gnCz#ul-lm?d3neQz}s{&HZoF7aSr2lgy7bQT#J3Og29>2VMCXTTl<_SgkrKMbr{f4aCo1MEIv z_gw%s2rM>owqATLd$s|)?E`7S7olXmr;9s+ z&@u1b%#HxzJmkHYa5v$5$bT8(%Y?C3B!MtW*sO6uxR9`!u$b^YeBueliRYVf`0nW_ zXa2=5-EKv@`)<9IwGpzv8yTC$7?;d#CZ6|kCw@svbn{W@ha{(GJI&{>A%(kYyo*V&?%fgKxmet%B7MRUrTcHJ)s z4m{3xHqZp#OaqsB=t2EvCO&Y+kh537nti)$*rYEFKhvIOcg(0x;c_|UWnXyZ*!MDL zZB0IH3uc`9OI@!3H+1bV+RghZdAo_X?R3Umn`DHz#@)&t0qZS%?}vE~@~q^MUF7!( z1&7$L!@z$G@+p3WWy3>H$xA3So@OXgSgt%+_)Io4wvst59>v?qTQ(;=-E@o&4604~KoJhX2-&y_K3x^asoWAx)n@o9U&dK5m$mk{5H zPJ4iTVSKAv-=6H^p`PhWy0Y@RkbcWI8t&CNyS?wZ1mm^Z0*=4`x5k>`#1={zk!7 zcD#Q~dHo$ue;2C1_)SZI(>R)a;{$2IRv{l+x1A*1N57w2=g?suami~w;flGA9eS{L zZ{}dqwRL)3{~N#It-j{!&ea6t2sy|p=UcHheh*XQF8r`L4{1wwbk_*q$Wg6XQ{^ZP zIo7xKRylKh1Y3}P%HB~wWe@%m{uEezgUz@WkFD^w%uh(unDqQ%I$tXvK{0*P{DU2D z{0*b{J#qE1l)k-1AD`If^hrD}X<@C>Y_Wi#E$*zl?H6rntrr5cUmS4mDwq9m>x~_0 z>=);5d+wFnANkq{ugsFaP$uvCjx_UbwoI?D%(A~wW-0A_%U9-zugvX#q0Ghf?-5^_ zXH|yrsWTs5sCXdKmds&qm-vK0WOh2=ZsRQfQG8IG7m9QwbHh>Oh9_K>$+dY%7rcDv zDzEwdG&DX9{|$Y6cby29!ynyqR3=`rPKNKf><8vgfOgQ4Gm_i&+nzZAbPV!l@eSRx z|ILwG3qRAxk%4aN><;U^nDgy(KJ!K{bBKIK7G=;oseE|-d-!K`A9Cz{3#@axxwd47 zGo{p{@29hCGw3hAdvfsiv}@)h>eiae$Q*kG7T+GKpGZOIpM{%b5#25y%saq6dA}ns z0Va_Ak0LWo{JumZV}WzDnj25EXL{P*GnH-p4*RBae#@Bv`fsu4D4jQcx})rA^v0z=hmY59(c;>w`>HB3HoVhxQ(-h*F%efuA9=^@LN1Z zd<1#T+?T5N9NuM{t3KQcp>pcGm3ng9IKxgo;)C{Kc2Li!fZaivC)_$B)S>s^LkF)8 zOu*2My_tF4o#{}5yI6ae z3;2#Ah;M2HcX8+r4BTj;-0%;LUbu(2>R3!2@_+5aj@n^urEh$@7-3%z9j^Te=CeJz z=j}tZn`1d+U3)asz+KUVkL->dWsbBb;BQT&}NO z^+)XMlKFoljxgMe;Lt2WsXwD7H&Rx^xGb_G4Wn>FJnRHG{n~s=a$4* zHc#N|LBm(hycxbeMW4mj*BP%ntZf67>>o%VIY1L%1_ot`2e z-FeDSch3KsJ-Sig;=$%k*?mHE`Y!P6hroXxc(Z?d0r!T&FG${p zeR;Q%r!v?P=zi=!U*1i=ykX=?hP^t=e0A#V;CsG2{8!mJL*)GrUmm`YY#z2i`jjv4 zQ@*^By{dDi;LwrS7v{XgtFQAt60)HCfYo+0ZL{t?wHSsTN}Kj>gi_8 zmhmw53m!s`xAUNbv8PUrqHf`m%N%{D+Cj!8qmuD?%EQ(e!Mo~%520Z$yza^RjNl`{ z0~@sPk=vYyQyO@KS6_j>JF^j7k7-Sfj?A%cPfcfiM!VmOP(EPYt9unfvhPEz(KcCo zFXqX+OfpQqNjLP^ovE>yGr-|B=$SJFFYL2%e|Bl2z7+ZJVoor4%^_d=Pr|K$y2cBJ zJgsjwv~eO5gJBppTk6Bkdai{u*=)I-b30zlZ&J=6AM^V{eRuX7A@iZ-Y}b{T6eh&X8#=-bPwpq%GY>zr-KtvZr}0c0<{`wC*>= zhBLCIaUBv(x}s?+4=oprFE2-V=-}_?IKJKEv@so=C;D)f{jq79V}D$qXN@~{C@aX`7I3KPM7V>BnjWK`8F>y7khG9>NGg)Z~JBPwCajH_C`~lfe)=Ve-Y00sEeUiL_@E6m=dOOqGlG~C6y&cJssrKYHX!mqvC1)1f z`JL3c=?>ON0jncz1;DrUSiiv=Imv6C%{RCK=Gd;xFzyx!6Ay4!4*PVR#!&!yIs=}& zeu<3?ZLRQEGxyTRGvJ-zcSrKWo0CeH9UCa@PQ418WLjy}z!kK872kvS+?f{cLAyi0 z`Sa^Q@3yplD`rRUX6{4B!QQLW6JM{-pS=bEZ0TQ=mKEEa4fT&Gs~N5BDsx z7T|7(Iv2NmaJ!i{kMkQG+rULQ36Fg~oHXt{oN^ia!b!5jQ2RAE$s_x1$u^7oLTzv& z|LMr`l)@|x!yV}y?xxci3lwhQUeO>n&O_kEqqE1oLE=I7I5z8dWce*a_zRwavJTE! zZ%w}g-?z1GOWx?>oD0q$2PfgG-wqMJ`QZKqAI=w(pA5ri`>PqrY0z#@N_LLJgM9FK zopaQzUsDl#Yi4?4>$A1|j<51QL|w-sn=`f4CE2eg9FNX9%x{9^k!R-Tvd1!ip#FXQ zhKKy7@F^+z?B;!ZH|reUPx8K-cg5B2BF5A=zQA`98drS(qj^C(I=`zk)6?}_>UH7H zJo2lcBcCfNdj^@7O(A-Ougo7lyv748MOc+Kg%VGCVpjsX0yKOK_Hbl)k~s@GmnTmL9j3j1HD{j0)ICF9tR& zJVnodRmR%(S0_{-a+YI7UKqY%)NeBDC}Xqkj}syjd#dm?gn`i=7wFDYf8ZI<^AR3w ztW)UDQ^1{Kt&qL5NblHKr$+LizE2_V=J(I9<19Xl^HZ8fK7`&3QFl}1pMUpJ)lZv} zlNqeX!_!9L>)@Uw=o=1=9oTr;Z!*7nO@6^UQp3s@9Lp9^Z<7}&sbc?g zD`#NE*Y3V1!vn?;--GN!9zyi{475IpT)fu}&CBPaXV7)LhZ3Jj2E%ic;>Ar9(6^DY ztI?@xLnM*;z8ogZn>lN{&cBOQM8FZ=WF-qk5VKxMv5p&U|)Y z_{~QLzO&|ja9jqCqx%D`%lcDm)(up)etO^?VDDd3#qS|Z8o0l;dLTgkx%^&E0sS4e zW^R98YfgV|>)d|y#-V)phP?fH=AO6vgXMguHG8ia`_fgx?aTXf_KfL&GQ_WJY#-A< zA~a$kKa@Y<{T^Foj&*Zy>-Pt?w*G7&z?s)P>#kG*V`b8wD+a!^y=Gw2_TqtIdvg2p zw$JO&-JaXeA)7;zC(V6l;FzN>qWc$n}k;TXdA3C9w?Ls*B*X-+I)eXVbRa?qP6 zN!R=mM22F%e9fiG*Ssk`rnulX)8^g4P2i3)%ls=V;|rA=llM96iGnqj)rn8Lg!l1; zuixz0Mekr6?PHPl=xw7oBl-zz{Ob{`qy}3vZdur?!6!+xEAWArvu<6*J|Rz-=ebEd zf5WnrH_V(?Pz!qZ)k zWy-^sqTe4#j{sgU(xI0D7X&Up@<0%smNy32Gr(>GmNfJXzl96D%6Vlj_Ufh#x-oA! zWmfOq$?vja_e@}pU<@s=A4umC?{9e+>5Kj=FN%~mgb;O64 z?o5v-UPJsE(rw}~;tjx0BwkK@D(S_{xNV3bNBuR`q#`ei}Z!0e-gMd;`4~#L-~2c%ZOh_`a&qVeS-8T zaeaedOZsx+5#r-WUqQS?aoSo*yqNeUq?Z$)NW2>O7;&5UDAH?)k0)M5dL427*2YNE z6U4_5kCWa^JWM=9`Uc_!#6L>?n~3KVpEc^z%rNrWc+cg%k}^Sf*U7uZyLc#miucly ze}@d`!TMS73B|+l zgf)aVVT^DhVL4$jp?Fq8D1Jo<#jELr;?oR5@n;s{Lc%h_d4%%_%Lo?|iU*4cMgJ(F zXuq6LbYDRzny(}*CM+kMNEjou32O*N<2pjoH$f=cHWP}j8wf?yO@#S`ZG@szF7Zy{ z7NO|3+($RdrCZPF|2?|>pVG=t_rHa|$G~X~Jb#(+Qe@#p!YbaMBfO9NUc%M9A0}+& z{UG7zct1e6k@p_LyLsP7_zB8CNq7hEPY|vrzngF=?~f9$Qsf1DpE2<&^#rH~fBQJy376mXHRg%C`i}g^xtC;@^iX$B zjA?Y(TJY7H)tbU@PZlEQ;Gz7B!RsQhxa-FU^dhjOx1a{d0$MN&9cSkMG`+u7022fYVut=$xd=1j|_0LZhx>gLL~W zcyyAs&E}gX;NQZ2(!Bcs@IMG|PH8?jwo_L}rWLpmQFKu`4|R=5@ZCp`qnqCE!XD$1 z9esx95ny|%Lv~aL^dHrGbGn1|SBKK*e^2C1qti4__b1;>Jso~Cm3uG0nb7rSDvx?| zqu2zr@qX`PnNgAL>BC)fQwPI5U9Y7MgGhM{Fha4MVduBIr&CdnI zw-J|&TEq`P*Zt7>aPOPo@Mfx~@TF9M->y1?EFKEHlzQKKEOYS4OR2-8?>_<$Xlp;| z2Lf;616kU4V9HCWr&BMbo&lyO2+XLLQZO`hn7GOwdX_xW4pR0oWe<>kh_c#mdU`79 zY04d?Tn=@Pekt`DWuGCgvWH3U8Kb&sa};fp-V=oPls!0&dip5$9OZJs0l1@-?a6b> zK12Hci^+TT&D2549uy2^hf(&>bo%oSdC!vu{6WD{cK4pR0oWe<>kh_d)b`kuay^mi%uGUW=WbNoxG zyD9q&al>EIdp=Hi%I?3Iwn^{FdlUB}{GCNTrz!Ue08jP(w5Ye!^z za$@(~^eFWA@wT0rpZtmQi@#ugLwC2aCiB)~d&s|zbot2TOXi%ytLAQwC_dbB^fG!! zx>tMc%Ey;5&iEFI7ZUgO-SI(;^L*Oclb25$zyEQs9KLw=F`2v2{j-=~OdW|%Q>T3W zO3&xcysODmo%wDa-vCq2IiEOLd8B*oc)oMaKOfQ_gZVu**1_^WZ~Qqr6aUXnXgnjh zH>18=ZQZFGCwBLhH15s(WIF5R1b5W|KemkD3}!Uf40HQkDV#XR z(-YX6nGHVqwDYk~boXfw`ccxpY4X|ICVnmX1zo!H;x2tV_v=4jEuT8)dm=i|aTj}T z+cKl*oBX3Szz^%aDg8j?fu!bB**;-=Tl!$+Rn7ppzSmS+a%6<>7gOKh`)>I%m!$IP zPZ&JqKOFRB-k-h}Jo3RapL#z69uMFP6t24Sr7gK4 zwJWpY2)~aph2KtQ-$ed|vB_Nacypn3ZbrUN$x&|j{&YTl$fXbSXy zhoJn#H@Wn-dH;?2Y#|?n_=ozAai(P$@7fD#V~roVV{qNS;&zLFZ9jQpxwH3dfw%5R z4Z}xo&oaM)^BSCAnOz`S4E|=P&ac?CF{2QlH0|z#epc(l{ZqLUM&EM}yYJKH+iok$ z9gSu9LtF3f*V#XvcW9*C>x2!IIglhT%KYBDGp*khe?76=oCVZ5&hyU$euJ}tJ5J`o z`yf1Pvz>2YzeinG=;8iHsP7N2uuo^>y9^`y(C<~=)y_O%WPdCtTueEA2jKNjdndE7 ziFI}($k-R0elt{O0Ve^!=WF`+-5ZascKj%1|21IF1fHx5STEk`>?@tA2$(aQ|MD;3 zg0AH}jEY z1@9>3$_kykqNY$LC-j^Cno!TcabUkqp6D*UD7rUM_d*x;lP>H+7xwEzU~7Ply09Mu zc46qufCt+(1opGQ&TwJFF06;cmLaf9-TpmK2u`Ut+)%%r;oaRJ|Cr=oqu?<7?CoR+ zgHY!IwO=?7Inh}+(Pa9Rw#?s(zpPcXk6RMO?;myUf&BcxDxI|ywD=M2$cMR`cqcfi z?F6#)GUINgD+8)CTFy5s)S+{l8cV8cVVNVBu?l2h34Aa6@`)KqzI~Y8kr|o%@`*?< zzYCq}V61%kL@{!cI5H?F%@aB@YNrbsDMnUSta9XJC9?89f^8G3U3V_*+eF*C3qb8k zMoPh3_P@r&tK z*Bb7w2)#GZb@%XriHxfgp@Re6(9I6LIADdg4Lkze%ajofUnhPYWu$wgyZ6vnE6hCx z&};)R`W{33+!1J06LI+bCNLL`+uOfz+?j#d$o*`_$R1$*_~wA8&Xr5&Q+J=C1$tr= zWqY;fZDbf({hV_)vH32(wOhm8y4)WtdQK-UA8*e`*!^39pu?yCtPZL}wxokNXMC;` z**dsI5R-!-8l zdHHnsG_^9Rrz0{uDIFJR-O;ae&pKPmF8$nDKL}XQ|KRT)60VZj8HKwzAI5!5(6<8m zd;*%a(NVBmc z36;Mv!X73t*x7xL(+)DzC;8QQz5y8FD!G-u5ZxuWz1+Fl?al+uZI-o;M`sSg;C<~` z=>_)9(HA4ZPdu!E$KqkdxSoLu@C}SRivI4%jHkU}p}qYrw4?F3i13pR4ymxO%>vpJ zT~z;!UVc+O$rI)&8=Obv1Jc|g8fZS*fS%Y?*ufmPJ3FVS&KSJxL|^n07W|E)FI2Dh z{m=)-9b=BZZ13V+u54)P$S<+3={ke6P3lDf2$5_0!)N-uilf z?wZ~G*CNmNv$ym+_Ot{$thKZMcdhGP_$1jeP3O1HKgaVbuLQx9;Js&-GUg zsh_sLF@pL-z+X0`{(S1MYCZE045#mnZ{6E}liTi1t!F6nT>rP|^G8B&_m3F2yT2US znLY0N1Iy|ADCB8aXm`KlXe9YtNc%8p!G`B2?r7NNhrT~BK$+vnY7gN@km2owH?m%nj(IMzH}f3h_Bry+cjpnlqfI=RJjmD>&)I72 z4Qh@OKDNzoGV$p5n2u@AV!V|A^F7uHJAn6}1?K4CF5P3WfpIn*J)t>S^gim{V>Aad{7XPNt(aep#e51Y-nWr?`k04X?dRar1@g#ZZ^Sr2|n`G~6 z?vTFHSxL>KvDxS=be3%3PNTDQSAt^)N6=Yg-amJ42lG&ru=C%shwpIhVZOK9jqL9B z$*yc*tyy$tS$b#_dAi@r=(R5FiE{Y^zNYgYefX8O?}D$p;N8m2j-J+d(Ooi6iC%oG zvM?xl?(Un$d*C|O|8uAd*%FT=E8jsrq;sXO-h|#->wFs6v6S1%yXrK|0PjFA@L!QMXu^}%7<|Huvs-M0quD+i|7Cakrs@r#OZLyMi1osO<;rX^39;eJB zj0L}LF=yIY*Kx+g{GNoqAv^$#&Wl4!bFRwB0<TQI86O0aK8 zKKGfO(tS^y*WJZ8#O8ZJ!3k%T5$q+vk#Bx8?yDyL1#~QD!I4vaPj>cpXO64c$Eg|S zs$-RdHn3;^cK;Vn?1ty$zpOPU@f4Hp*yWrZUt(G19E53(a?b*f{6tY?P~i@D@*Amh^`M=+09`Ko zxRd%l`}h|4GXJ8j=^M$jy0DYVxwoyG@l?j|G6lYx*$Axmo}MH=M?561`Qy(&Lmt9= z-r0v7Q~(ol)9(XjEPjqhNdFq~PnK|2nC~OD@xBl^y|*F98+f0`yF#t4ze7CmkMNRu zijj-h1k$_MACBNV>Ajz|(*2nQ)TcYiuBM;i$iwhZN>) zdgV9zlJb#T&Mu^E zl1+ad_0*yB#NOR>US199s%w+#;@_BMj+{Puad<;F?S+x9{DKWmnC;t z)*C#M-5snswbpo#4+6qGJv^sx;hjgeTuqcU5Pg(>(7hy*74J?K?1Symu(KZ4e4sur z1U6RK>D)`gogaZmf%mc=U18rpIieBDWT@IbDrZ4Z(kLIY;2b=k#7{X}H@*=oA zLSs5N){YDWdTrLT6>|dil5~Q1E7Ai_<#TioPXlMxf>vSbUeZTj)sQN@r~zJ-B`>ub z)0^$hVc`?}9}g-_wO_Q1wM%!h{l>X=z>Nopw~utwZy?=`2Z*Zu-@vyYT?=_FOl8I_YjaK)gN2O`k@(8xIg~54!17Nq6G` z;_U%9eG2JrJV3l1z8E@3NO$A-SZ%y3=;iV`&KhzSFkZZS+RGPp2RN6Oqr5`+c&WWQ zE%<3c zQ^6^hr)A@`Bg-98*#Xm2K`Vk%-(48&{Yv3;FP$lTo`>(kLQmY>o%+_@%}Fa7-#-lh zvVK=SXxqu0$b_V2U4|WWdG`Gpz9Yuo*%k~G_606McmA}yZ^9)z(4okvl}KCRR5}_kCUCrX!bDq%SQTSdxYUoHe(TExcQYM*SRHHm?g=e>^>UWLI+8#oteY!znvD zADAzp$Cmbu1}50M5TJ=7zhi-c9uNjA=74Yzg0DSTlo!l%M%{xF=O^ z^`z>0!4cb{^Gd?J#y)J2D}#ZReciqM(1O*I&K>tSW3)Xb8*WE0W6bKIzmF#aWy{ml zc{zUjD=lk^*4n^#=M-|ExgF^Ueu#Z-+g`?5FY9{+_Ls3u`0b0{&FKPoSXj`Vnleg0 zN6wA12VnQEeyx!A$oTeG!@=%XbIO({bH}xJ)9&N6`($oeGIc5Kp~AjbP_|oic}c&u zZQHSQB)2~&a;z!(-iqzB?$NxDed48_6ma9(pl2Wq z{R`VK7hGWeZrW&{N_>WR@`W*5`YyVp9eKz0B46!MZz1(c)^skk(Bj_Mz=Ez+&K+M4 z&`u!uk#@Cl(n3IJQ)3|@xea`#yKgEqzRH?bH+C-dPVH z;UT&7rv;Z3BA>{iEB7AG6aKL$b+^W--QBnE2(+^|kIIGU8)hyb=#{;4QKd zWX#=S`Y1bYX%2G5(a=_=y zo_IGm$$1>?rUL87C+P!nok+Kbk1(Dc81`S!gURMIRy!g`jV`g=_=LXzYwC4jkg4^}4i_@BzLqe;O8?Jqle#QHM&>G8Dm34P@}67ATpCb_=@z0&2tkZ0B~ zU0+K^kk`WDZG4;ht>lz^WaAU~)NUYcfbis(Qjrs1O67Fjl^hv;9z5>oJ7fK{&|MRx zw2m;}VI}YxmSdk{*LXgB&XXqtZS=FNJN0irJ@@W{iXQE~+h*=SYL0~uC1t!+f^H8+C@zk z|Gf10hD1YCOJm$#+YpPpnOP96KWU*wrZb6(#tPGf zUD>d9ZAE>oDHP&B|E&$pabolR9kUw}&9x2nP4>(X-7nz@g%*6EcjrUVPH6U>a}4t5 z=Y(7Y=2un4E1NF>ARI%tc)h;`%AQ|=$)C5ezG7`{rM5=%4VA0Oe$)cRAP%dzE_7UE>Q%b zf*zG;8yU(%n>x>@kW=T}hPsB9M%%4retpI2x_Atkwb$1+*Vwn)*E?M>p(7ZSjJEn_DFg6WwKl%iu1>U=xC3ZeO)Uvw9M_nRAwriX0 z`i5pZ?((R%-fpfTZFNg+U2L+wym6!5*iv7w@qbxUORT|0P!qMKbhN6r`ZAmGN>QVF znrkYW?aQ22FSBbZs3RV)_bLuqx7F9dx7aOqLzQqexYCeQ6T0jFOKbGEp>gA?rbJzB zv(sjULrgVN6tf!|?dryO1qv)Qq`w{|Cfm`vctum(uB?ey-UD?T<5ewnVA@Al78c zyS#A4hYITIR#$+IUAZ=PePlyXWX6WUvCB+ggruUrqOPIZuC9P*MJ-oJZeq37wIJwA zvn-A8rPsRvbDW6A1+oMJ6*k?7*RG>WRgDd6k*oTqhQ`VETtg1<5QFOJsT6Ms1gNZQ ziAfqnpJhnKM!TUN#VE1K5^QxtMWe*cTI$u^QqL4+M9-tn2l{FRxx{vRYgwgD-hf4h zYtVy?7H9s;X4u80Qz8)!C4wtxPjYEgDe+3_*=!jv;{!#k(!qglt#0&}8O*SY2U{r} zR5Dgmg&%$}V`wX-Xl>C$_*7OTP*QPQNu}$Mr`7BmGJu!2G}eob>x^PodRDPprSWwZ z|C{pj?|>yf)m~~hHOCW8lK3fCUBgR50(f`cbldb^omsB9DIT}Y1Z!x9l9hoV{D_)1 z+$5jPV4qj06r(}#3e>0U40|3F{HR^Kp$ffK%b!7B#GM&;C~RdzonR|nSY9=Uc)+*M zyyFV1)H6nCd+l0>9$wM~`_|}AEWi`>;oxP!+0toOUkf2h&Ah{YMwL@KyjpWMY^kkB0mYf$i#L>PELmR?vr&%q z4UJ4DwM|BsG&C}%qz&x9iA;`^PMI9}tXQKl(9%p{#Z{;KYBwd~lw;gudNejP#gXoq z<^b_U`ap3-y>jA@Nw-S}d9}6$lvXo#tLPDBV~xgEQ=qnF%Pp2IcRuUEiMg5v7BnzQ=uFmcB^xJpfWsgSgSsSRz} z9N*9^ctpH0-e65bt1OGxp-3e3q%>7FB(T2F&}ObLjm0a`5vE?E*20RqDr}BebInyX zaoJU3hf~tgC8~Q`tZ98kg1Sv$E#t*gQt$=KS!&zgoDcu_2CIUWg*=!xR(M?y=d&h4 zlU=NS*iE&q@eYd_qw~c|s{-z- zUFlu_R8U-1*8mGp(TN5m&nf3l45lD`j`_--H)mX+aA}ikYEW)zyt%O!negc2Wf?nQ zePeBN+}JhEv4$40%_^;GsBD4bRqNRkY^+#sSHO+>7!#N=1ckbRuopDk;!WJnOkyp$)Zl321EU#HRGRSaqyw0-L zBW8^bAFZm|Ia9wu)C9{+Xav8x1yiuu!LO>Wr2%bIiCJhdU1OoSFTgXdG?iMe zZnH3sHm+}ItW#ZAM`~ILtZUq`UgL##6SAsVR~v_m9*vzm(Y?-vBi<;z(1d+r;NlgA zZm?)$T|>RmMOC#M;<2iP(E%0p=!u$&d(=maqBwZmql|f0z#6LxhWr~&`j{bU7m-%r zrrmsj{2cOd&|CA#3lNrSRl%PTTAyNht*e||kF~d|skZ(eRdc(sf+fS1#%#2e%ebw_ zGDOWGO^!@ZuCcamvYDz^HO3)v;|I&SH1n6l=BlknTQW4E6|&!g{fw&cSKgAvfzf4q zm8igZ8l|X(kv)j7W50XgS6u*ayVw-5q7Ey~0&9Wk9(~177eTx{caX9;_5KgtmZ+$# zZI%TO-Mmz?`7wL9!mPeicf6H6G}? zj;b$haIjIGm^(x3b#pbhPrdqT=u}$Yki}wNgIVyzYFRZ@Y(yiuIj&}69weu}#f;|| zBYvI>2%FZ|)K=C=I=sSCVCNUNiv&PzT^Xwl zvqV;Z+_k{1tUU}*?$q=J*-Pw&&J?C73I~q65Xb={$^_ypSCsFV@s3FZ$F#_}DZ0!? zElc`fH9nTPaEVSW^H!2Rt}XDYm)R_P!Y(Reg@mhy)ng-LXf?HH*;rI$7Fk97!?a-K z(8zSPo;lwvd(GOWv?g8$i!2V?TFbSx)H}m~Srs+SL`iz7nWNFE#KFh4^G%{XOVj2J zz&JCwFW;TgU4T-jbJlH6AF~vi<;8Ab8g8(M%u*$G3yZ%=r44rJq$?)di>gewu&*j> zt7_v=vcAC(TdTh&rkfacV7!r8!pt9-mbzv;qB5>wvla#I*jqlvPPQZ0Yf_jD3*&aI0gFqPN&`aKXgJ@5 z{f@IilBK$;6HT%BhFTeWM6KD01j}61TwQ5%Es`Yp@Nq?A?utusd~)?+|)36>NJTtda6{?s%gerJ?-jvymCr>+O_c+ zdJkPz)O4BcN-PaECs&~BBm*0_;PsSdF^ zcSeFTO6+^$@r1WxjXA`1DCN}zZL>ZZSMU33_ABSvt5L(ov}$aq#&0PBN8V&rIth9{~)~-#|#RcK?o4KQ@ z1@$9wmT4S=)RoP+KWNj-i!n>1Z^*5P#lS%G>7uJ{v*V484Khp?;k&42$-)BA%y;wT z05DFN#>SRJvpt-}2GcTHVZovmx6Geu@QB{FY|#qn>rH?v;8A+xUoG;%GUyZhM)LOj z)q+vYb~IB_Cw6Xx1;z(KDRjM?hn~$Q(=}{Uhu|34%+!t8c!)QXsW${1XI6zwV7pGX z8)fDoD;}jhf4CMfE%?=3l390F)Ebs+Y-x-LBL-M=jgd4)3018%t2ca1bqz)nYp8ih zLro*ZgL5_ZdCZvYj1$#J0J`GiT-Vnk|4IX1GHNMf9L&_*j3P1#o;wb7>f_C_njBm) zX;4?jtoZ=W8sL)EJ1ZLH%A09AVn)3fnI)0Y*K_HY>F@_S8?xq$D2{EUQE&kWY=gUI z7OiCq!7f@jv*?zYMayWnX!136(mS*3nroX|V)5&XCQq%>`d#Z-^Kwr@cIk2^n0w4S zWt!~8coY?2Ju3A6AFRi&zX}h`;6GE}&_u7^3#Ci(4XIypSb{xtYTT z>u-$Xn5xGj8f-!aj#raRP_@y5Ip8W-jR|+Ith6Ohni-I7ta{B8fH}S{_=u5g*H$rl z?rp&p5_fEpmL^tjvc>JcarbsUYsQMR32|YAvZ(3vjFXnSn5%@08Kg1qXvXFS)ps2a zxDLYA$%e=6;u!;jKpW#tj4k>l$M!P$D~t_dhQQj24fee)sAde`>*Zu*gqZy?XN%18 z_6l6niIFT{sM)2$+-CLyhb3-#jn1Vkfi*&x*I*IWGwFElaZ+VBd6u4Q*{F!uys^8N zOI~Af*{#acYh6VG1IFZ9)?)P%$&h}-xl^UBwQLjMV$)d`KsOj9^j_a!#=KbvXvV5* zG1}j=X@%=tmxuV-Y8qnpOq+7c82!vbE_*fiI(%m0kQ5l40Q0Bc6W>U!%t*+O>=e8R zjsEBh0OrCN z@7(_a2GMrbz2~*%pls;ovz@%jJ-a3nQB=Qu(_%)x5JzxCBZrQIb;np*Yiu>mw0-qy zCd&GnvcQzTAe<+(K0sF%j5BGKqsM&u)V1|)j?TX+tKMKP*&M#wHbjSMz^B6zPc!RLQkzy=HUwK!C&Tnk6Gqm*qy1H7v#<6D- z4TzptbpcFK7h0=26H2yHmK^18&bHN%Qr?tQ+SL__@RQ|4I z*<)tZW$g2s^@gK;$pU4Ma|~H8S#?CE5$*Y6r=VPYT4Jw|d021HzjgWirOII0)+~hm zw&=1&H{HH$=@ezx)?=bNL&cqMnQWy_YU^9fYQTY=>TAQy(_XcMc7t1~+REAzZegX# zUUn2SJ#x1VOS4)u6+P z7e%IX3I@x}{IRn!^Gd$voyjbo;+lcyY10)S1%|9DJumMz4iT_6sB^L$9K3RF8bfzg!7Za~9Y#vLiNbDKY-h*Rrn;eNOXF49vNEo- zfL>WI%>WLT&zkSPI=wW1osL;QSkAl;smn3-2Vu;+2Qxcn_LxD(O!&@Nb=MWXwg+hj z<%<@|n!ZJUmR&U^+vhg zHp>?Yi(8+UrtbUk8RX3%?%6aC*sa6k!}Ud4M-1ZQr3+liUYib&Twt$XT8;^jZ-+cM zcS&XzC+DRJZaHvEXWwbFuQ6!ZJKn*ntV_k2ntZy!*kR7brn8gj_(3)7Jw5H4CdK^0 zd6H8uEKpoeQ_Nebpk&SI1v81Uz|hH`!7}*FSmt}MQm5`z=4%CWJ$8jPI7hiE#I>u> zpC_2Bn1ns!cLCa0yE@JOQ`T{02UFiU ziQ&$sO>#iHH7e6HevMLRy9YCJBPuautw~f{tJfy1YP^04EU!djt<_vzVU=dB48H55 z&1Fz^O(I^MU2V+r&O6|bXWtGGi!sUJpY`_Yij8r+Px2hm3sZ`vL4^{mQcZ!Za?Lu# ziDx_EI&~@IO$zp)YnJ+r7ZQ%BEe%?`So_;eS76#=mawsinr^b$?KP(-w9M3QIHVAz zidkC9mEkT%MHERHja}V@x2?2U3ofUhCTiAR+4Utpx(zco&UA^wp*>tHX6KOoKe$R!+$sdU4zA4%NpmgD<+&>Fj9w*Q{Q|EpyV9{ z<$spl<)0UeVI0F~ZKA}6btN35tu{VG&UG07t+(z`d5#(BxKh@7pfj%V$)KFXvg>+t zylj%MTMn(=Ra!HPEYaIpNNQm;8F#B_&DMxZZ7tR|+OwK(SlcvN#?JNEyJn2zwYG~n zCpOc@iC(+5dX*;6$#g(;*Ite%==8gajR4Wozi-lFJZ4I9mLo2~WHNcn(c-l%c<~vw z;M;U-v)M(2rrA}cWyzr_`v`eyUat);w<5>aTj3Z}7dEXpU*N1Z|5|y^-hx%0Ic0QC z1#%~kd!n%cZ*LQR_Bv;;+rt#rX!~Dhesq2eb6cX~blY#rnvvpcF;a)8Uaaa$t(P3T zPE^9GF(zcGYrp&IRJJREX34|ZCU%|~QLFJm&3E<{Cz&LVIA&owi9IjIZ8Jgu4P(GB zjk7lZS;Dn zYk$){tC6y1rM1+lEW4Uw>(1SJfjtp3CZz>5@NQuDSbNfWJbbueecKJabnpEHdCK?F zzvIGr>1%O5lf=IZ?{S|$XE-MW?WH%(VLjkVkmIYkAlzM(Y`BI4>VE_F_78$yu+BTq zudHYqep`D%bQwJmyjdI-C49EGnQI6AhuAHGb8Pz<(}$FvVHmqsoK(|7X|k2wzcv0C zwwhS(m<%_P9rW^c<2EvNw#FM9O4$XiW_Q$W@cJ9<`L}tvDc{Rr>m{a5uqIS|BO!y( zoETYK>v;J$wyd+78dmFA2X=#V)?Ozlv;!+{g&1_%*+S!VaC;kEvSjel!Cj9VBsim_ zQ6YHrRw$wChsP$suWZ)TDnwlloqg%9E#zDK ze{e}nIph0W&S570iC>QKrZMKQNJ__3<8D~$=fz#9X? z-1b~$mu(mQXUMPoYB)gi4m%tMmN@(?aoAS^_eu=+O4e02tzG3ZnL3a*%45Ay{;wT5 zu*{)mhRrI8C~dlZT;=uAdv|p_djj&5$78GDnFJ(T9?j+KZ>`D}5tp<1TB-ZtU1N=; zK^RBH4Zde*0*5!OggGk6VJ5drDtrFem5n@~E@Kwzh=ZFSudZ8U`~-CpB9FsPS@P!A zG+=kmHTY+9Rj=}lBkoRfa%)*jW0j_cYz61RP+r={%RL`24iD6>lK==gC?!azeI=N& zKY0At^oa$S_dimkILCuGm_NR;CZB=VS$wk2P#>D_D${JXFW>c5us3h^V_gv8zILrR ztdsZ-o<*?@j6z4Aqs|sE(?=B!cMf8sDh9`a*>5n%vy5e+&0^{p%omTG(Tie``NtI7 zSj({rqjF|vUzCN0F+QfhTAo={W}mQ-4s%}4FFjOF%o%^IXtSS*Xgf%HvdT_C-Ky%k zRnm4kq%kxdi$GmsCbO(_itz6|7>BH@9ARDMjK85UuKW)Ln#f8uAK1&?@G>`?;D$wn zVe-oe)&2~^M||=BO!-`2`Jfv=uOHAr!*B1+C!**7=(ce9+Ae0Fz_NjbB*GXFwnK!E4rqxmN>%|81W{N)1W`Z-1Sr7}WpQ%6 z!4Lr^7^1LZBRJZu0{i*aqi=Po1vp{%4>onWy6RiMU%jh-Rkv>4Dy2uUii*;ij?&t4 z=It@|w9u5jmi}yYcse&yN@i%cuJ+%YE4jnj#qaEL3H?>M6OZv{n9>1ZYq586mM3sT z%qypEWv7TH(Z&&%-cdHGztVo&$TamKx?b3JWA^%Ns|_T3LzXWL zu6w0;5N=)USut;YZ&sikj)^aE+7`}tjBjRP>ZJ%cUS?`@(7KJe+i%&FW7N*MS8I^Q zSmx%nrCXYt>c^up4}n9)v0EGm{*`1M85Hc6(*kV=8)%2pd6ZrYh|3aM=yBpc=RiW0P>ZBfUf8*f^C zoh>RCtabtfo_IrcOnrUe~fUehr(?$83T%IxX&0epyc%Ej!jXs}W?2Lo7m>HdDi|X%wb0q<@w6 zlYR448V7+Uwn!P1OhYwI*tKWh-i>)tw~Ms*$e9O{+)%NPrc%2j)NT>JzD!xEA5rtB z&`gdhnW@nke0;`(eE#3=7tbeKzo3?VuBmF(kt;dX%rBZBXH9GSReI#dV${X7gtt6`!86jnI5lwQEtN6qsPso$DY!n>j0%C*#)Jga$Vq@m&tiSX}N6%CQSnu_+4WBE`x7z z==a7dztIR$zJF}Ib>R8|JZ!yws~a6cp0+&kAS#V8L5BE7C3#|2U(8d|^OG%Kd2-`t z(XVz|_85mWZ}(<}S7}I9)p*0)%j1-TXZxg`w>0frd)v!ny?h+VQd+Jw=qz@5soffS z9&2NLT)xxice96AFH6`oqwl7*lfkbm>Z#d39s9Vg8T#k*?z`4(y45dH>QUXUJg~l? zur`kJRc;}xC9RaeG6BnHA}3m(Fza1G&M?Rkx1p?|+` z_xQA*am)IzR;_=KQ-k=5?o3z4ykj_vx%$?w>^aPJd_Hj=v+K5X+2nPYUAJZ%FuT{S z$|@aR{{f2-vi}b65o8{9=5?1?{B9OT z)O8%726gwmBq3_?|q= z`y6Jh3g4nn;eHgo|5^Iv7t?;y^+CRY{J!Gn=xl%Zo!m18^D~6IgTm0vIA3c zPhmfeKI7b!=D7#n2o7)oOJnn8dLc@g{g3#!wlm+=IF;A{X|4R;^;>mogk9&o2VDs$PP?}ExjN6 z@jEifAxtTg2kcLwpGM17@t(uJo5NfiUSau^w-)RR(H&^(N*wTPNAEyO>3^sqqq2;P_J%s%T`lxeL8K1}A zbTjpdmfFACn#_BulxR(_Lyn=F(c+Tsz&?FtCRu?grFz^sm8qoqvy!Tt>Tlyg&?)_Lb=u0z&gN~wJpus=-r1I|ry=>Yb_=p)Wea_J2AbLjKV zO>(LEPWn8$6)h#XG=P2m67Dx}Zjwt!v7bOci592i(mCu6cTq2B>zjDrK)mQ9Xt_zB z#(oxk&bb}zq3n8TzsT@=(EnCd_;>jIx5oMZ#-HAGnCIfiOk>|m-n;v38K$n!-=;D= zPdL9G%9NWgGrzteT+^+iADM+#JKT8Rzr758z1rdPFT-C|JN)%%gN!w_sgB`aP2c== zDU)?;*1RIyy6(0+uj6CkHWo{hRg1}6zQ|#INv0KRmOolLo;DRXINYTcZM%QJH` zS7heZH)pQOyrAyt%r%)#^-#?%HBQ@6m^l`kxHy8LqBIY#ORnW#qjaj~W35Yi__yw@ ztVOkew6>%1S8F?=4;#OT0HE{|Wbo%#X28|075CnffP4bvDfUC!p2+^*nuR)u2LaY`BDj(v!xf z#y3N0Y-;#E#uO!6`jVunp%?Q~ZIGP$GW{8w{viF9`G1)I#!S-}@Hp*J{xb7t-GS4z znS`5ZGxq79kb5qp$8Z&BX77xr@EqiLalfOz%cNhMuz<^5vPXx(E1w zUEL)AchpgX$z1tUf|4t~$-i`F*$h_~Zv!=CPV%pI{bF*N)^z5wWcHNHGIKKZGk;^| z%Vu7#d1L0X47O=FN^LtlAnbDT1Nl|z+*}786X5G9$T}{?!g@HS_+0!VW zIaB22GRRH7WE^?UJ0Hrxz*F%f5Ak@_{O;A1*IXQv%QB1bbA=MO;;NCEKC+r+cNebp z$pZfCGXHz#j3k2+Bfqw`_VPB)2P&1@^V-*EHlem{vNPVsI(6v!uO^xHMeU0gEoyIH z*uIco`{MdJZFN%#=cOj(7uE_n(Sm(jFC^yN==#J+sb7?UUOpC1`oskY=MiUf@fCwgFQ(jfz;^xBl}5e#->c;mGDe~IIFFZjZh8sQ`#HZ=7gDPe2L7rSlHf}HLeR9 zuat==$3)ndK2bl_X0hve73WA=oRZ`9?KTjSFL7SK%)#jds)tRQ+4h;!XCzs$lowH} zXJ#L6dfO#$pYo2zoel4-f28hRcKty-Ua(cSrgq<$+6P95i|u1Q`8RQfQ9DO8aOiUT zw*0nQb-?!R!5;f|&e(VXx@1v%Z+RkNc+IZb#2%d`9SpF!4Yza53LjJD*f3cz#5Ic+ zx#2gvVA#A!UqH3q%<*LfIg}=D-r85fHa=A5u(!Mpd$^gp$Az|F{(A>*#=3Rs4dUz1 zF1UShmLo_D;v(z?eVEH{qD9bdia-wk?k_H2+r7>oCbJyKjVs@Vjp!pUg5?v11$_{D z@8dK)PPW&%O$0cmgKh8*eF58_IhAEW-^i#ASPdC*R7%au#+%g&NirXTalC0%%&yA} zDOB^P;WKA9uja?b@*I?{Z)OsGMUWd$iX&S~Vav|tRN^^`IL9FqgNe?2OY&oUeg8Bi zLXxq?SYOY7m9iYKOF1@IkpY(Dj+EmKo4W3n|_eC-Eh-Ga^}8X%0S*FQ2< zoE>N`HTrR+SWo$&(C*!~U0a>=7ap&JC$q!j1wl|_BsU>qHpe1a)@_eG{J&b6Y z`u#lRmUW2R@|7IBcBD$}u3(di&@E_9C$A)Rqx({lz3lbvF3Ax zzr$mu9D%AgZ;4Zfdb4sKVy&8|s@^=+gjmysRMne#Wr$y#0&Mk3Ho`B7@HMVQSm%c1 zM?X`i^6fz(RN6Q0qJI!mQyZ&hB;s$Ty@uGAzg7+Z+%^$I_Tl^b(%W?T_vNSg@P}PU zGJJggxkzu@&*ScK9a#Q5gZPy`^&P9GnePsLdtq*wTxy$!A^Y&vmqPxuzs*eUiTD-Y zVYkMt^eevX3Fn>k48kwWb(Qoko4&(;kXOykq(*YKJ@7o;N)&J807X9cus_6|oQ!M(C04x5d11$QEcc%QN zJ_0Oy%OlnFjsS~(BETm60E<5GXtn>z0E@mq!18|}z@oRRGaF^gXL*1{F9cZr2Ldem z?f{FvC%~dN{|24OMpf13b6cl2Uzr`ef$~a>UW=m)R*Wd11$fi0xbH# z@AGGr^*H`!h0{~_|`hJP9nS?{0unj_&*6g z57vBN^v{61A4usZ{;isqsJw*>IH)`> zv5yFb?8lRb*&AS$9Zwqm*g@A`R|Z(|cLrGTp9-+(W^yCb``2X0DAyhXEdR$o?#PaR zHsillHvPi;a8UYRSR?(DZtsAf&z+9K+x%Z$aIU`$1z7PP4Y1OGJiww)exlm{{s4=9 zIKc9MB*3B{53uMb0xbH_C;2nVmd|8>ML&JSkzM*bK9ynB7x-r|oG!b z;{ONmUa$}EN8p12UFjL9?0s!c&O;Y&F#em9saQ(jCWpn}`KGjeYJ3rHHS~GOJb84= zk1yM=PxGttTM?AUweSnK60dJhP2ch%*!H5mx>ni#y!qQHHtiw6O5gTptLfU`YnAoi z^xYK8e{+E4zvUmQ>B|Ew`uy)z)7J-B^y$x4)3sOFDjR=SfEB;?5r_1L11!4sF^BXc z0Tx|*m_z#M0E@1D&LMrp4^nL653thT^~02I%EP=6l^f6d)Kd#sD`jd`YHusRS2(Qp zwgr5R!)nhDgJ0^f+I#C8?e`Y)|7o=!uvWf=Z>BvIz%OuE?R5v(ho|(Ud$pUB_3(S; z=XZOf^zS?4Ic)iBzo1oizH>05ANijt|7|tGKN`@Lo-_ZP@(V8?st&*DY&HGa^C?#O zZ~500%m4Z5-oHz4-s4%x>q*aautcEB>mKm4;4Kd4!JR#+eCPug!0R3TKCoB5yqahD z@Mk3B(1le*zCSLUnbMWs%>jN0e&H6}J^y4t7ytGED}P5KtbK!4+2@a;Vm00s$ftJ^ zpD+gbx6d0xfjoLI1mU>^p;r2bVsy&q_e2o?N1zKA;P>gDKHJA{<5Z zlL1}%-4S5r_f&+n$ImL8-zIJAFltuvS;7~d4_5uk|BeUiESdbgxY6Q;hHlr#4h8hT z#lNu6|F^(i`TU;`((`@j!UtgT`FTvQ-Ho#CFP7i?1Nu+!FRXP|@BieS)W6Du-4!-C z<|oR}iU@D6?9rQ*sJ{zOgHQR-klzA0ERW;c)AD!$bm6c(b_ea{TIj+m2H#%J2L9Wj z3;Xi=9M~&gUK@k-u7EDQ1ty>0eF0thJs9AV@C$3o>iIhrnNhZV4Fvc*@C)A)@E-~2 z3jcV3Ri4wYNW&A}6_jTe;R*Zx{|4~WU|U|ceeDU#s{mctm)8h*Z-B?aUa5Q(UsELS zvO#*@48O3Jz|EYj3{$~UHKKO<82=2q5J})f~@n0R_kHIh8 zMHBM;O;=U(4+U8HI~L(BL4MU7dPjiw59}eg@fR6-N@h=bJUj|)RT}1N#HtiyiOYVd2{id9zL?hEh-A!yHvryq~}SBI}wkSdkePvH0YQUAH*68gW(pYS~J#+O-n zBm7cuH|6Ks>vK)?Zx??ZPd)RYcR@eo+Vf4|R&bVR<$nYC0O4(M_)c&OxYgl2Smig{ z;Zd-!FZq8ncsKmxj{XQZeLpiN`8}|I-=p?&0Ic?qb?NyNaG1VNgTwevfW!1W1@`Zo zGnCgiz+wFV2v&Wn$tiv3z~TF!X_SwD|D*KG1N-;Y3U2|}w^#Xp1vo6b(#EiS)z zM)>g;GQM^~H1ugn5A?9UO5m`()m{pYpOMCl-{S!meKNq?6`xacF!zG>{L+Da4(a`L zME_ERzX|qxs>J_8@cyaPAN3*puMz*OOObDHMN^)l&j)*@_?Jd_ZG`pBxL4x;G7mB* zjx&eEuJDQxeGIJcNtF!I-yYH51J?QjK^XdnBKn_!yADwJjM6dSMukS@IOP>^Y=>Z3V${eKi~dmGrxZkSnEC8ef@&tF9GxC2P ztoMNn@h|#|w6Nxs(lJKzBR({jPU!xTJP6;4f+35u-5DJh%0rKtrFXMkfM1NI)W$g;E{0~I4fVF?Y)4v|k{}HVB=TEuz*2H+? zl~^waFaI3hh&%d=!KZi9W}vD3UKR1bCc<||cre0SBm5{>>o?n7_`AV=e4EYqc0Aak zr}X`P+RuPUFzNfNi2khzpNVi|B!8}n@X`psCc-^ny?>-xoA^h;dY^XA;fEsr zM3vw23-8)!eza8dPclbx^bKIWe>&yx=7|4Zu=aZlxbk`gtg}qK zJlqf7P5S3M{~wS1pN#N#B76qC{s1z?`JZC9%z{*3$jbmr6t#l&Ji5iu**^!K&G@py z;f-LuFYI#tyEpK!@P0eO?~U+BBK+qOemcUZBm7ga-nSoh@n1$k>%5m04!?)zvv53J zqKa@z>01@y?g-x-;rG$s{r+3E?+2l4f8Bf+-|t2I9|CK?NDFa^|7b-2e1x9?>#Ukn zj{nCI{gSI7IHmMo1=jvH-{0PUwWr$pTov(mMR+*EZ;$YMz+w440oH!5t6hFS8}WZF z!rzYYS@5oRrt*J|UKG*3)&EpJFB5i3?Qa=4oj*1wYXZ9Re<%19n~INPm;b(qz8$Rn zvpeZ9qQ51gKOW&f0Bb*;m;avyYrn@v7yefw{_jQj$6&oL>~Q>-{RZ)Wk2d1)La_F? z>~MHB*em7d?g-xx*84>t-tUUedbCf^`@qML2Rm?9{yqxU{sWcgWsG;90_%Ju&wo<> zol<;%AK`zBaJU6t{LNAOx*@_Vz}m033tpwC8?61MPdR))So@#6ynGbwmBN2tgg+YL z&w{m|&$ste5&cIIp2K>H_J8^KTEJc@zK#g5j_~bZ?ayS0Gx-^g=nqDCCV^^w{~pKx zF6i1%;_Gh@So=AB`5c!2gX#0M}ID&n~#Q}Nhv+^Ucz|EeBbl8gS8* ziuwC;eIvi>@JA?!J1Y0N^YO8}@lm(A^cBZ)io1u8EE8RxH`vQ{I-?^w4uLJ@xM56p z(kJ;sA*ajsa@!kmA4l@BV=mV>G18mMwJlEkQK>mypw_l18R1Oj zoVnvF$8~uNliuNiz7sVUsc<<>*(Qb$Lvxd3#lBxU>l9m0k;`N^k+)oqi%0s0Mtkx@ zxdPvkmUH=u$;8H4m>3@3W^>Oq+iSRHhfBpNg3A3>IeR@JDXTbC;r>QW)z^fxT)y#il~mY}`OvjJ1n9 z;JMJ;!!_of8E&G~g;r(nx}HiYj#Z#8D(y}BOJ$CR)wMOcH^tn#7dV-lC~0VN(lNco zF&|iWaT2S)+{Iq@g{T02tfO{sNxYF(CEm!{T*uC}H1aC9S2r3o(5ou2TSFN9T8_xBOv{af3XB=?UK-2Efe zwY@7#T;|R*f3&Vc=8Il?f`5hAT}_j4y%yg1_kLtG9%SKqC|b5|y~^2>;>(8BUTb3y zhQ_x&Ale=08=Mwxtu?~nqP9Ygv)TD-IkEPhQ5T92+T7*luir6wH+K&V(jLs=)aF`; za*`hzAdYiLwemzy zq0c(#u!GzX9AwXM7>9|#rLc9lkQ*AA6m`Nf76v;&!GQ?B?9hPx;@f8{z083)IUf_f z!aBH^E4XiQLH0s{6jvOTg9;e5i2|GN{0oDHzLaKtS8~Z&0WO}xSQy5{kYQ8}QAqks zUf*aVV#}jBcNZAIlq0UT{3<~y0SeeeUpCQqzTvi2w{BSD9d!tRNmW{akb>CkNBOy2 z_pNJkx7^m5%O$yW8*g8|ic413uHAG?cdmQY>W#PH>Qb*LE1*E>q%qk9IKGKNlP_~^ zOQGCX=v!Rzr5u;+?R>dm?i|zg2HZw=-^!KiHf~tGCbzh)qar4a)N%b_qH@g@UACJG zz_{CdyqItuq7eck9BiPG)E+iYY?TuO?12IkJ;j`^Sm9^{PA1SGJlcCflw4qnJkg*< zp_>cr%*dSd4{aRm9~kf3ifxr{k}D!1&6QhQdq*Yd`?-v!G(@@w%f&F%{-Jfnk=174 zFIVTv$)oU88)h&-Ie&0KpBRT%}Be>x$!D_J*zv^vjK-{g%nzjmFJ2X3WYl zo|YNs?RcMXe;2tO91qiCO3GZy=nKiX=qkvZuFiB56pmjR>m4p#;8U4owo>dL9ot6n z_D<$?R6|}j`h~pxL!I1XxJqrgob==g7_kyEC}|AwRY}Wj=)N__V96XqBR8#)!ySs< zc^&OwN+hTla?I?=PZAjYIS2xIt*fOU7~>v#V{@&--C6DP>kHR3D|ba44Nw(XCQChK z#FQ^?9BCaqkGa-6L6A6xtcyPy&6{&Uo%wX zypOaw>Pk@x(e{A8v0{_}+o8AzI3N3Qy+5umm?ALMRoB1z#tfMMQNUhp_a=(!}0c zeLzcW&nPS@zTUMOcQh^i&gU13KI!c zCrTm#)-$H@WJGs%SLLPVy^LYQ>dOxfT~O#g4X*WTc%1C=t$Hvi4AJ_k$0gUSf?j4? z;U;q*Cqq0^e6TF>Ye%P5=1x!})FG|rGS)yURp+4gt(yHq_6l&)V(wZEv*2lKh6alx z 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 literal 0 HcmV?d00001 diff --git a/scripts/raspimjpeg/macros/error_hard.sh b/scripts/raspimjpeg/macros/error_hard.sh new file mode 100644 index 0000000..83ffe8d --- /dev/null +++ b/scripts/raspimjpeg/macros/error_hard.sh @@ -0,0 +1,2 @@ +#!/bin/bash +sudo shutdown -r now diff --git a/scripts/raspimjpeg/macros/startstopX.sh b/scripts/raspimjpeg/macros/startstopX.sh new file mode 100644 index 0000000..25454b7 --- /dev/null +++ b/scripts/raspimjpeg/macros/startstopX.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# example start up script which converts any existing .h264 files into MP4 + +MACRODIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +BASEDIR="$( cd "$( dirname "${MACRODIR}" )" >/dev/null 2>&1 && pwd )" +mypidfile=${MACRODIR}/startstop.sh.pid +mylogfile=${BASEDIR}/scheduleLog.txt + +#Check if script already running +NOW=`date +"-%Y/%m/%d %H:%M:%S-"` +if [ -f $mypidfile ]; then + echo "${NOW} Script already running..." >> ${mylogfile} + exit +fi +#Remove PID file when exiting +trap "rm -f -- '$mypidfile'" EXIT + +echo $$ > "$mypidfile" + +#Do conversion +if [ "$1" == "start" ]; then + cd ${MACRODIR} + cd ../media + shopt -s nullglob + for f in *.h264 + do + f1=${f%.*}.mp4 + NOW=`date +"-%Y/%m/%d %H:%M:%S-"` + echo "${NOW} Converting $f" >> ${mylogfile} + #set -e;MP4Box -fps 25 -add $f $f1 > /dev/null 2>&1;rm $f; + if MP4Box -fps 25 -add $f $f1; then + NOW=`date +"-%Y/%m/%d %H:%M:%S-"` + echo "${NOW} Conversion complete, removing $f" >> ${mylogfile} + rm $f + else + NOW=`date +"-%Y/%m/%d %H:%M:%S-"` + echo "${NOW} Error with $f" >> ${mylogfile} + fi + done +fi diff --git a/scripts/raspimjpeg/macros/test.sh b/scripts/raspimjpeg/macros/test.sh new file mode 100644 index 0000000..5c3012d --- /dev/null +++ b/scripts/raspimjpeg/macros/test.sh @@ -0,0 +1,2 @@ +#!/bin/bash +date >/var/www/testmacro.txt diff --git a/scripts/raspimjpeg/raspimjpeg.conf b/scripts/raspimjpeg/raspimjpeg.conf new file mode 100644 index 0000000..5e8673c --- /dev/null +++ b/scripts/raspimjpeg/raspimjpeg.conf @@ -0,0 +1,180 @@ +################################ +# Config File for raspimjpeg # +################################ +# Syntax: "Command Param", no spaces before/after line allowed + +# +# Camera Options +# +# annotation max length: 31 characters +annotation +anno_background false +anno3_custom_background_colour 0 +anno3_custom_background_Y 0 +anno3_custom_background_U 128 +anno3_custom_background_V 128 +anno3_custom_text_colour 0 +anno3_custom_text_Y 255 +anno3_custom_text_U 128 +anno3_custom_text_V 128 +anno_text_size 50 + +sharpness 0 +contrast 0 +brightness 50 +saturation 0 +iso 0 +metering_mode average +video_stabilisation false +exposure_compensation 0 +exposure_mode auto +white_balance auto +autowbgain_r 150 +autowbgain_b 150 +image_effect none +colour_effect_en false +colour_effect_u 128 +colour_effect_v 128 +rotation 0 +hflip false +vflip false +sensor_region_x 0 +sensor_region_y 0 +sensor_region_w 65536 +sensor_region_h 65536 +shutter_speed 0 +raw_layer false +stat_pass 0 + +# camera_num 0 - no selection. 1/2 selects first or second camera on compute module +camera_num 0 + +#MMAL settings +minimise_frag 0 +initial_quant 25 +encode_qp 31 +#mmal_logfile used for debugging callbacks (set to /dev/shm/mjpeg/mmallogfile for short periods only) +mmal_logfile +#sleep after stopping uSec +stop_pause 100000 + +# +# Preview Options +# +# fps_preview = video_fps (below) / divider +# +width 800 +quality 10 +divider 1 + +# +# Video Options +# +video_width 1640 +video_height 1232 +video_fps 15 +video_bitrate 17000000 +video_buffer 0 +#h264_buffer_size 0 sets to default (65536) Higher gives smoother set of callbacks +h264_buffer_size 131072 +h264_buffers 0 +video_split 0 + +#MP4Box Off=leave as raw h264, background=box in background +MP4Box background +MP4Box_fps 25 +MP4Box_cmd (set -e;MP4Box -fps %i -add %s %s > /dev/null 2>&1;rm "%s";) & +# +# Image Options +# +image_width 3280 +image_height 2464 +image_quality 25 + +#time lapse interval 0.1 sec units +tl_interval 30 + +# +# Motion Detection +# +motion_external true +vector_preview false +vector_mode ? +motion_noise 1010 +motion_threshold 250 +motion_clip 0 +motion_image +motion_initframes 0 +motion_startframes 3 +motion_stopframes 150 +motion_pipe +motion_file 0 + +# +# File Locations +# +# preview path: add %d for number +# image+video path: add %d for number, year, month, day, hour, minute, second +# macros_path can be used to store macros executed by sy command +# boxing_path if set is where h264 files will be temporarily stored when boxing used +# image, video and lapse may be configured relative to media_path if first / left out +base_path /home/pi/PlanktonScope/scripts/raspimjpeg/ +preview_path /dev/shm/mjpeg/cam.jpg +image_path /home/pi/data/%Y%M%D/im_%i_%h%m%s.jpg +lapse_path /home/pi/media/tl_%i_%t_%Y%M%D_%h%m%s.jpg +video_path /home/pi/media/vi_%v_%Y%M%D_%h%m%s.mp4 +status_file /dev/shm/mjpeg/status_mjpeg.txt +control_file /home/pi/PlanktonScope/scripts/raspimjpeg/FIFO +media_path /home/pi/data/ +macros_path /home/pi/PlanktonScope/scripts/raspimjpeg/macros +user_annotate /dev/shm/mjpeg/user_annotate.txt +boxing_path +subdir_char @ +count_format %04d + +#Job macros - prefix with & to make it run asynchronously +error_soft error_soft.sh +error_hard error_hard.sh +start_img start_img.sh +end_img &end_img.sh +start_vid &start_vid.sh +end_vid end_vid.sh +end_box &end_box.sh +do_cmd &do_cmd.sh +motion_event motion_event.sh +startstop startstop.sh + +# thumb generator control +# Set v, i, or t in string to enable thumbs for images, videos, or lapse +thumb_gen vt + +# +# Autostart +# +# autostart: standard/idle +# motion detection can only be true if autostart is standard +# +autostart standard +motion_detection false + +# Watchdog +# Interval in 0.1 secs +# Errors is Number of times cam.jpg doesn't change before exit +watchdog_interval 30 +watchdog_errors 3 +# Set callback_timeout to 0 to disable it +callback_timeout 30 +#optional user_config file to overwrite (persist) changes +user_config /home/pi/PlanktonScope/scripts/raspimjpeg/uconfig + +#logfile for raspimjpeg, default to merge with scheduler log +log_file /home/pi/PlanktonScope/scripts/raspimjpeg/raspimjpeg.log +log_size 10000 +motion_logfile /home/pi/PlanktonScope/scripts/raspimjpeg/motion.log + +#enforce_lf set to 1 to only process FIFO commands when terminated with LF +enforce_lf 1 + +#FIFO poll interval microseconds 1000000 minimum +fifo_interval 100000 +