diff --git a/.fpm b/.fpm index 67bc598..af9b5f9 100644 --- a/.fpm +++ b/.fpm @@ -5,11 +5,13 @@ --log warn --python-bin python3 --python-package-name-prefix python3 +--python-disable-dependency paho-mqtt --python-disable-dependency PyYAML ---depends python3-yaml --python-disable-dependency pytz +--depends python3-yaml --depends python3-tz --depends libcap-dev ---deb-systemd service/sentinel_mrhat_cam.service +--before-install script/sentinel-mrhat-cam.preinst +--deb-systemd service/sentinel-mrhat-cam.service --deb-systemd-enable --deb-systemd-auto-start diff --git a/scripts/sentinel_mrhat_cam.sh b/bin/sentinel_mrhat_cam.sh similarity index 100% rename from scripts/sentinel_mrhat_cam.sh rename to bin/sentinel_mrhat_cam.sh diff --git a/scripts/sentinel_mrhat_cam_main.py b/bin/sentinel_mrhat_cam_main.py similarity index 92% rename from scripts/sentinel_mrhat_cam_main.py rename to bin/sentinel_mrhat_cam_main.py index a06e577..11e3c41 100644 --- a/scripts/sentinel_mrhat_cam_main.py +++ b/bin/sentinel_mrhat_cam_main.py @@ -1,105 +1,104 @@ -#!/usr/bin/env python3 - -import shutil -from os import makedirs -from os.path import dirname, exists, isdir, join -from pathlib import Path - -from sentinel_mrhat_cam.app import App -from sentinel_mrhat_cam.logger import Logger -from sentinel_mrhat_cam.static_config import LOG_CONFIG_PATH, CONFIG_PATH, CONFIG_DIR -import logging -import sys - - -def main(): - """ - Main entry point for the application. - - This function initializes the logger, creates an instance of the App class, - and runs the application based on the configured mode. - - The application can run in three modes: - 1. "always-on": Continuously takes pictures and sends them. - 2. "periodic": Sends images periodically based on the configured schedule. - 3. "single-shot": Takes one picture, sends it, and then exits the script. - - The function handles the initialization of logging, creates the App instance - with the provided configuration, and manages the main execution loop based - on the selected mode. - In case of a SystemExit exception, it logs the exit reason, disconnects - from MQTT, and exits the application with the provided exit code. - - Raises - ------ - SystemExit - If the application needs to exit due to an error or completion of its task. - - Notes - ----- - This function is the entry point of the application when run as a script. - It sets up all necessary components and manages the main execution flow. - """ - - # Setting up the configuration directory and copying the default configuration files if necessary - _set_up_configuration() - - # Configuring and starting the logging - logger = Logger(LOG_CONFIG_PATH) - logger.start_logging() - - # Instantiating the Camera and MQTT objects with the provided configuration file - app = App(CONFIG_PATH, logger) - app.start() - - try: - # The app is taking pictures nonstop - if app.config.data['mode'] == "always-on": - app.run_always() - # The app is sending the images periodically - elif app.config.data['mode'] == "periodic": - app.run_periodically() - # The app takes one picture then exit - elif app.config.data['mode'] == "single-shot": - app.run() - - except SystemExit as e: - logging.info(f"Exit code in main: {e.code}\n Exiting the application because: {e}") - sys.exit(e.code) - finally: - app.mqtt.disconnect() - logger.disconnect_mqtt() - - -def _set_up_configuration(): - """ - Set up the configuration directory and copy the default configuration files if necessary. - - This function creates the configuration directory if it does not exist and copies the default - configuration files to the configuration directory if they do not exist. Will not overwrite existing files. - - Notes - ----- - This function is called before the main function to ensure that the configuration files are - available before the application starts. - """ - - # Setting the default configuration path - default_config_dir = str(Path(dirname(__file__)).parent.absolute().joinpath('config')) - - # Ensuring configuration directory exists - if not isdir(CONFIG_DIR): - makedirs(CONFIG_DIR, exist_ok=True) - - # Copying the default configuration files to the config directory, if they do not exist - if not exists(LOG_CONFIG_PATH): - default_log_config = join(default_config_dir, 'log_config.yaml') - shutil.copy(default_log_config, LOG_CONFIG_PATH) - - if not exists(CONFIG_PATH): - default_config = join(default_config_dir, 'config.json') - shutil.copy(default_config, CONFIG_PATH) - - -if __name__ == "__main__": - main() +#!/usr/bin/env python3 + +import logging +import shutil +import sys +from os import makedirs +from os.path import dirname, exists, isdir, join, basename +from pathlib import Path + +from sentinel_mrhat_cam.app import App +from sentinel_mrhat_cam.logger import Logger +from sentinel_mrhat_cam.static_config import LOG_CONFIG_PATH, CONFIG_PATH, CONFIG_DIR + + +def main(): + """ + Main entry point for the application. + + This function initializes the logger, creates an instance of the App class, + and runs the application based on the configured mode. + + The application can run in three modes: + 1. "always-on": Continuously takes pictures and sends them. + 2. "periodic": Sends images periodically based on the configured schedule. + 3. "single-shot": Takes one picture, sends it, and then exits the script. + + The function handles the initialization of logging, creates the App instance + with the provided configuration, and manages the main execution loop based + on the selected mode. + In case of a SystemExit exception, it logs the exit reason, disconnects + from MQTT, and exits the application with the provided exit code. + + Raises + ------ + SystemExit + If the application needs to exit due to an error or completion of its task. + + Notes + ----- + This function is the entry point of the application when run as a script. + It sets up all necessary components and manages the main execution flow. + """ + + # Setting up the configuration directory and copying the default configuration files if necessary + _set_up_configuration() + + # Configuring and starting the logging + logger = Logger(LOG_CONFIG_PATH) + logger.start_logging() + + # Instantiating the Camera and MQTT objects with the provided configuration file + app = App(CONFIG_PATH, logger) + app.start() + + try: + # The app is taking pictures nonstop + if app.config.data['mode'] == "always-on": + app.run_always() + # The app is sending the images periodically + elif app.config.data['mode'] == "periodic": + app.run_periodically() + # The app takes one picture then exit + elif app.config.data['mode'] == "single-shot": + app.run() + + except SystemExit as e: + logging.info(f"Exit code in main: {e.code}\n Exiting the application because: {e}") + sys.exit(e.code) + finally: + app.mqtt.disconnect() + logger.disconnect_mqtt() + + +def _set_up_configuration(): + """ + Set up the configuration directory and copy the default configuration files if necessary. + + This function creates the configuration directory if it does not exist and copies the default + configuration files to the configuration directory if they do not exist. Will not overwrite existing files. + + Notes + ----- + This function is called before the main function to ensure that the configuration files are + available before the application starts. + """ + + # Setting the default configuration path + default_config_dir = str(Path(dirname(__file__)).parent.absolute().joinpath('config')) + + # Ensuring configuration directory exists + if not isdir(CONFIG_DIR): + makedirs(CONFIG_DIR, exist_ok=True) + + # Copying the default configuration files to the config directory, if they do not exist + if not exists(LOG_CONFIG_PATH): + default_log_config = join(default_config_dir, basename(LOG_CONFIG_PATH)) + shutil.copy(default_log_config, LOG_CONFIG_PATH) + if not exists(CONFIG_PATH): + default_config = join(default_config_dir, basename(CONFIG_PATH)) + shutil.copy(default_config, CONFIG_PATH) + + +if __name__ == "__main__": + main() diff --git a/config/config.json b/config/sentinel_app_config.json similarity index 100% rename from config/config.json rename to config/sentinel_app_config.json diff --git a/config/log_config.yaml b/config/sentinel_log_config.yaml similarity index 100% rename from config/log_config.yaml rename to config/sentinel_log_config.yaml diff --git a/script/sentinel-mrhat-cam.preinst b/script/sentinel-mrhat-cam.preinst new file mode 100644 index 0000000..dda9713 --- /dev/null +++ b/script/sentinel-mrhat-cam.preinst @@ -0,0 +1 @@ +pip3 install --upgrade paho-mqtt diff --git a/scripts/sentinel_mrhat_cam_daemon.sh b/scripts/sentinel_mrhat_cam_daemon.sh deleted file mode 100644 index b78d027..0000000 --- a/scripts/sentinel_mrhat_cam_daemon.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -# Define the service file path -SERVICE_FILE="/etc/systemd/system/sentinel_mrhat_cam.service" - -# Create the service file with the necessary content -sudo bash -c "cat > $SERVICE_FILE < None: def load(self) -> None: """ - Load the configuration from the `config.json` file. + Load the configuration from the `sentinel_app_config.json` file. If the file is successfully opened and read, the configuration data is validated and stored in the `data` attribute of the Config instance. diff --git a/sentinel_mrhat_cam/logger.py b/sentinel_mrhat_cam/logger.py index 458f843..1b64fc3 100644 --- a/sentinel_mrhat_cam/logger.py +++ b/sentinel_mrhat_cam/logger.py @@ -61,7 +61,7 @@ def start_logging(self) -> None: """ Start the logging process. - This method loads the logging configuration from the `log_config.yaml` file, + This method loads the logging configuration from the `sentinel_log_config.yaml` file, sets up the logging system, and adds the MQTT handler to the root logger. Raises diff --git a/sentinel_mrhat_cam/static_config.py b/sentinel_mrhat_cam/static_config.py index b5d1f5b..b73144d 100644 --- a/sentinel_mrhat_cam/static_config.py +++ b/sentinel_mrhat_cam/static_config.py @@ -2,9 +2,9 @@ import logging # Configuration file paths -CONFIG_DIR = '/etc/sentinel_mrhat_cam' -LOG_CONFIG_PATH = os.path.join(CONFIG_DIR, 'log_config.yaml') -CONFIG_PATH = os.path.join(CONFIG_DIR, 'config.json') +CONFIG_DIR = '/etc/sentinel-mrhat-cam' +LOG_CONFIG_PATH = os.path.join(CONFIG_DIR, 'sentinel_log_config.yaml') +CONFIG_PATH = os.path.join(CONFIG_DIR, 'sentinel_app_config.json') TEMP_CONFIG_PATH = os.path.join(CONFIG_DIR, 'temp_config.json') STATE_FILE_PATH = os.path.join(CONFIG_DIR, 'state_file.json') diff --git a/service/sentinel_mrhat_cam.service b/service/sentinel-mrhat-cam.service similarity index 100% rename from service/sentinel_mrhat_cam.service rename to service/sentinel-mrhat-cam.service diff --git a/setup.py b/setup.py index 63d2187..d83c3a3 100644 --- a/setup.py +++ b/setup.py @@ -1,13 +1,13 @@ from setuptools import setup, find_packages setup( - name='sentinel_mrhat_cam', + name='sentinel-mrhat-cam', version='1.1.6', description='Testing python code for Starling detection project', author='Ferenc Nandor Janky, Attila Gombos, Nyiri Levente, Nyitrai Bence', author_email='info@effective-range.com', packages=find_packages(), - scripts=['scripts/sentinel_mrhat_cam.sh', 'scripts/sentinel_mrhat_cam_main.py'], - data_files=[('config', ['config/config.json', 'config/log_config.yaml'])], - install_requires=['picamera2', 'PyYAML>=6.0', 'pillow', 'pytz', 'paho-mqtt', 'numpy'], + scripts=['bin/sentinel_mrhat_cam.sh', 'bin/sentinel_mrhat_cam_main.py'], + data_files=[('config', ['config/sentinel_app_config.json', 'config/sentinel_log_config.yaml'])], + install_requires=['picamera2', 'PyYAML', 'pillow', 'pytz', 'paho-mqtt', 'numpy'], )