commit 2e26cdf0b30bf91d5356b43c92e7413a20cb7db9 Author: Antonio J. Delgado Date: Tue Oct 11 10:19:01 2022 +0300 Initial commit with previous code diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..711a2b1 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,3 @@ +--- +# Default values for variables of the role +# variable_name: value diff --git a/files/process_motion_event.sh b/files/process_motion_event.sh new file mode 100644 index 0000000..1f70377 --- /dev/null +++ b/files/process_motion_event.sh @@ -0,0 +1,173 @@ +#!/usr/bin/env bash + +#shellcheck disable=SC1091 +test -e /var/lib/from_repos/scripts/shared_functions.sh && source /var/lib/from_repos/scripts/shared_functions.sh + +data="\"date\": \"$(date +%s)\"" +while [ $# -gt 0 ] +do + case "$1" in + "--event-type"|"-e") + shift + event_type="$1" + data="${data}, \"event_type\": \"${event_type}\"" + shift + ;; + "--camera-id"|"-t") + shift + camera_id="$1" + data="${data}, \"camera_id\": \"${camera_id}\"" + shift + ;; + "--image-width"|"-w") + shift + image_width="${1}" + data="${data}, \"image_width\": \"${image_width}\"" + shift + ;; + "--height-motion"|"-J") + shift + height_motion="$1" + data="${data}, \"height_motion\": \"${height_motion}\"" + shift + ;; + "--width-motion"|"-i") + shift + width_motion="$1" + data="${data}, \"width_motion\": \"${width_motion}\"" + shift + ;; + "--text-event"|"-C") + shift + text_event="${1}" + data="${data}, \"text_event\": \"${text_event}\"" + shift + ;; + "--threshold"|"-o") + shift + threshold="${1}" + data="${data}, \"threshold\": \"${threshold}\"" + shift + ;; + "--camera-name"|"-c") + shift + camera_name="${1}" + data="${data}, \"camera_name\": \"${camera_name}\"" + shift + ;; + "--event"|"-v") + shift + event="${1}" + data="${data}, \"event\": \"${event}\"" + shift + ;; + "--changed-pixels"|"-D") + shift + changed_pixels="${1}" + data="${data}, \"changed_pixels\": \"${changed_pixels}\"" + shift + ;; + "--image-height"|"-h") + shift + image_height="${1}" + data="${data}, \"image_height\": \"${image_height}\"" + shift + ;; + "--motion-center-x"|"-K") + shift + motion_center_x="${1}" + data="${data}, \"motion_center_x\": \"${motion_center_x}\"" + shift + ;; + "--motion-center-y"|"-L") + shift + motion_center_y="${1}" + data="${data}, \"motion_center_y\": \"${motion_center_y}\"" + shift + ;; + "--file"|"-f") + shift + file="${1}" + data="${data}, \"file\": \"${file}\"" + shift + ;; + "--despeckle-labels"|"-Q") + shift + despeckle_labels="${1}" + data="${data}, \"despeckle_labels\": \"${despeckle_labels}\"" + shift + ;; + "--frames-per-second"|"-F") + shift + fps="${1}" + data="${data}, \"fps\": \"${fps}\"" + shift + ;; + "--frame-number"|"-q") + shift + frame_number="${1}" + data="${data}, \"frame_number\": \"${frame_number}\"" + shift + ;; + "--noise-level"|"-N") + shift + noise_level="${1}" + data="${data}, \"noise_level\": \"${noise_level}\"" + shift + ;; + "--filetype-number"|"-n") + shift + filetype_number="${1}" + data="${data}, \"filetype_number\": \"${filetype_number}\"" + shift + ;; + "--host"|"-h") + shift + motion_host="${1}" + data="${data}, \"motion_host\": \"${motion_host}\"" + shift + ;; + "--signal-destination"|"-s") + shift + signal_destination="${1}" + shift + ;; + "--home-assistant-token"|"-T") + shift + ha_token="${1}" + shift + ;; + "--home-assistant-url"|"-U") + shift + ha_url="${1}" + shift + ;; + "--email-destination"|"-E") + shift + email_destination="${1}" + shift + ;; + *) + ;; + esac +done + +if [ -n "${file}" ]; then + file_uri=$(echo "${file}" | sed 's|/srv/expendable_data|https://ficheros.koti.site|g') + data="${data}, \"file_uri\": \"${file_uri}\"" +fi + +data="{${data}}" +if [ "${event_type}" == "on_movie_end" ]; then + message "Sending to Signal destination '${signal_destination}'..." + /var/lib/from_repos/signal_scripts/send_msg.sh --destination "${signal_destination}" \ + --message "Clip termino en camara '${camera_name}' (${motion_host}). Evento: #${event}. File: ${file_uri}" + + message "Sending email to '${email_destination}'..." + echo "${data}" | mail -s "Motion event '${event_type}' on '${host}'" "${email_destination}" +fi + +message "Sending Home Assistant event ..." +result=$(curl -X POST -H "Authorization: Bearer ${ha_token}" -H "Content-Type: application/json" "${ha_url}/api/events/motion_event" -d "${data}") +return_code=$? +message "Return code: ${return_code}. Result: ${result}" \ No newline at end of file diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..6197089 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart motion service + service: + name: motion + state: restarted diff --git a/tasks/configure.yml b/tasks/configure.yml new file mode 100644 index 0000000..c1e62d9 --- /dev/null +++ b/tasks/configure.yml @@ -0,0 +1,115 @@ +--- + # - name: Ensure motion mount folder exists + # file: + # path: "{{ target_dir }}" + # state: directory + # owner: motion + # group: motion + # mode: 0755 + # - name: Ensure motion shared folder is mounted + # ansible.posix.mount: + # path: "{{ target_dir }}" + # src: 192.168.1.7:/motion + # fstype: nfs4 + # opts: _netdev + # state: present + # - name: Ensure mail notification script is deployed + # copy: + # src: ../scripts/mail_notification.sh + # dest: /usr/local/bin/mail_notification.sh + # owner: root + # group: root + # mode: 0755 + - name: Ensure motion group exists + group: + name: motion + + - name: Ensure motion members are configured + user: + name: "{{ item }}" + append: true + groups: + - motion + loop: "{{ motion_members }}" + + - name: Ensure motion's log folder exists + file: + path: "{{ motion_config['log_file'] | dirname }}" + state: directory + owner: motion + when: "'log_file' in motion_config" + + - name: Ensure motion can write to log folder + file: + path: "{{ motion_config['log_file'] }}" + state: touch + owner: motion + when: "'log_file' in motion_config" + + - name: Ensure camera configurations folder exists + file: + path: "{{ motion_config['camera_dir'] | default('/etc/motion/conf.g') }}" + state: directory + owner: motion + + - name: Configure motion + template: + src: templates/motion.conf.j2 + dest: /etc/motion/motion.conf + backup: yes + notify: Restart motion service + + - name: Configure cameras + template: + src: templates/camera.conf.j2 + dest: "{{ motion_config['camera_dir'] }}/{{ item.camera_name }}.conf" + backup: yes + loop: "{{ motion_config['cameras'] }}" + notify: Restart motion service + + - name: Ensure target directories are writable by motion + file: + path: "{{ item.target_dir }}" + owner: motion + state: directory + loop: "{{ motion_config['cameras'] }}" + when: item.target_dir is defined + + - name: Check if there is a default file for initd + stat: + path: /etc/default/motion + register: motion_default_file + + - name: Ensure motion daemon is enabled + lineinfile: + path: /etc/default/motion + regexp: '^start_motion_daemon' + line: 'start_motion_daemon=yes' + when: motion_default_file.stat.exists + + - name: Ensure motion service is running and enabled + service: + name: motion + state: started + enabled: true + + - name: Enable motion web stream in ufw + ufw: + rule: allow + port: "{{ item.stream_port }}" + loop: "{{ motion_config['cameras'] | selectattr('stream_port', 'defined') }}" + + - name: Enable motion web control in ufw + ufw: + rule: allow + port: "{{ motion_config['webcontrol_port'] }}" + + - name: Ensure motion can read signal configuration + ansible.posix.acl: + path: /etc/signal_configuration + entity: motion + etype: user + permissions: 'rx' + recursive: true + state: present + default: true diff --git a/tasks/install.yml b/tasks/install.yml new file mode 100644 index 0000000..60c87bb --- /dev/null +++ b/tasks/install.yml @@ -0,0 +1,14 @@ +--- + - name: Install required software + apt: + name: + - motion + - mutt + + - name: Deploy script to process events + copy: + src: files/process_motion_event.sh + dest: /usr/local/bin/process_motion_event.sh + owner: motion + group: motion + mode: 0750 \ No newline at end of file diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..044be5c --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,5 @@ +--- +- name: Ensure installation of Motion + include_tasks: install.yml +- name: Ensure configuration of Motion + include_tasks: configure.yml \ No newline at end of file diff --git a/templates/camera.conf.j2 b/templates/camera.conf.j2 new file mode 100644 index 0000000..41060a7 --- /dev/null +++ b/templates/camera.conf.j2 @@ -0,0 +1,7 @@ +{% for key, value in item.items() %} +{% if value != "" %} +{{ key }} {{ value }} +{% else %} +# {{ key }} +{% endif %} +{% endfor %} \ No newline at end of file diff --git a/templates/motion.conf.j2 b/templates/motion.conf.j2 new file mode 100644 index 0000000..b69b785 --- /dev/null +++ b/templates/motion.conf.j2 @@ -0,0 +1,20 @@ +{% if motion_config %}{% for key, value in motion_config.items() %} +{% if key != 'cameras' and key != "camera" %}{{ key }} {{ value }}{% endif %} + +{% endfor %}{% endif %} + +{% if motion_config['cameras']|length < 2 %} +# Only camera +{% for key, value in motion_config['cameras'][0].items() %} +{% if value != "" %} +{{ key }} {{ value }} +{% else %} +# {{ key }} +{% endif %} +{% endfor %} +# End of only camera +{% else %} +{% for camera in motion_config['cameras'] %} +camera {{ motion_config['camera_dir'] }}/{{ camera['camera_name'] }}.conf +{% endfor %} +{% endif %} \ No newline at end of file