Added webcontrol API
This commit is contained in:
parent
a13f099e14
commit
ce6b363d4e
|
@ -1,5 +1,5 @@
|
||||||
mqtt:
|
mqtt:
|
||||||
host: 192.168.0.6
|
host: mqtt
|
||||||
user: '{FRIGATE_MQTT_USERNAME}'
|
user: '{FRIGATE_MQTT_USERNAME}'
|
||||||
password: '{FRIGATE_MQTT_PASSWORD}'
|
password: '{FRIGATE_MQTT_PASSWORD}'
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,9 @@ services:
|
||||||
# networks:
|
# networks:
|
||||||
# - frigate
|
# - frigate
|
||||||
ports:
|
ports:
|
||||||
- 127.0.0.1:5000:5000
|
- 127.0.0.1:10000:5000
|
||||||
|
extra_hosts:
|
||||||
|
- mqtt:192.168.0.6
|
||||||
notify:
|
notify:
|
||||||
container_name: frigate-notify
|
container_name: frigate-notify
|
||||||
image: frigate-notify:latest
|
image: frigate-notify:latest
|
||||||
|
@ -63,6 +65,32 @@ services:
|
||||||
source: /etc/localtime
|
source: /etc/localtime
|
||||||
target: /etc/localtime
|
target: /etc/localtime
|
||||||
read_only: true
|
read_only: true
|
||||||
|
extra_hosts:
|
||||||
|
- mqtt:192.168.0.6
|
||||||
|
webcontrol:
|
||||||
|
container_name: frigate-webcontrol
|
||||||
|
image: frigate-webcontrol:latest
|
||||||
|
labels:
|
||||||
|
autoheal: 'true'
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: curl -s -f http://localhost -o /dev/null
|
||||||
|
interval: 60s
|
||||||
|
retries: 1
|
||||||
|
start_period: 30s
|
||||||
|
timeout: 30s
|
||||||
|
environment:
|
||||||
|
MQTT_USERNAME: frigate
|
||||||
|
MQTT_PASSWORD: ${MQTT_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: /etc/localtime
|
||||||
|
target: /etc/localtime
|
||||||
|
read_only: true
|
||||||
|
ports:
|
||||||
|
- 127.0.0.1:10001:80
|
||||||
|
extra_hosts:
|
||||||
|
- mqtt:192.168.0.6
|
||||||
# mqtt:
|
# mqtt:
|
||||||
# container_name: mqtt
|
# container_name: mqtt
|
||||||
# image: eclipse-mosquitto:latest
|
# image: eclipse-mosquitto:latest
|
||||||
|
|
|
@ -6,9 +6,13 @@ server {
|
||||||
ssl_certificate_key "/certs/homelab.net/homelab.net.key";
|
ssl_certificate_key "/certs/homelab.net/homelab.net.key";
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
proxy_pass "http://localhost:5000/";
|
proxy_pass "http://localhost:10000/";
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
proxy_set_header Connection "upgrade";
|
proxy_set_header Connection "upgrade";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location /webcontrol/ {
|
||||||
|
proxy_pass "http://localhost:10001/";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
30
install.yaml
30
install.yaml
|
@ -55,7 +55,7 @@
|
||||||
dest: /data/frigate-config/config.yaml
|
dest: /data/frigate-config/config.yaml
|
||||||
mode: preserve
|
mode: preserve
|
||||||
|
|
||||||
- name: Create temporary Docker build directory
|
- name: Create temporary Docker build directory for frigate-notify
|
||||||
ansible.builtin.tempfile:
|
ansible.builtin.tempfile:
|
||||||
state: directory
|
state: directory
|
||||||
register: docker_build_dir
|
register: docker_build_dir
|
||||||
|
@ -73,7 +73,30 @@
|
||||||
source: build
|
source: build
|
||||||
force_source: true
|
force_source: true
|
||||||
state: present
|
state: present
|
||||||
- name: Remove temporary Docker build directory
|
- name: Remove temporary Docker build directory for frigate-notify
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: '{{docker_build_dir.path}}'
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Create temporary Docker build directory for frigate-webcontrol
|
||||||
|
ansible.builtin.tempfile:
|
||||||
|
state: directory
|
||||||
|
register: docker_build_dir
|
||||||
|
- name: Copy Docker build directory
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: webcontrol/
|
||||||
|
dest: '{{docker_build_dir.path}}'
|
||||||
|
mode: preserve
|
||||||
|
- name: Build frigate-webcontrol Docker image
|
||||||
|
ansible.builtin.docker_image:
|
||||||
|
build:
|
||||||
|
path: '{{docker_build_dir.path}}'
|
||||||
|
name: frigate-webcontrol
|
||||||
|
tag: latest
|
||||||
|
source: build
|
||||||
|
force_source: true
|
||||||
|
state: present
|
||||||
|
- name: Remove temporary Docker build directory for frigate-webcontrol
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: '{{docker_build_dir.path}}'
|
path: '{{docker_build_dir.path}}'
|
||||||
state: absent
|
state: absent
|
||||||
|
@ -126,7 +149,8 @@
|
||||||
- '{{item.reverse_proxy}}'
|
- '{{item.reverse_proxy}}'
|
||||||
- '{{item.reverse_proxy_port}}'
|
- '{{item.reverse_proxy_port}}'
|
||||||
with_items:
|
with_items:
|
||||||
- {service: frigate, port: 5000, domain: null, reverse_proxy: nginx_barad-dur, reverse_proxy_port: 443}
|
- {service: frigate, port: 10000, domain: null, reverse_proxy: nginx_barad-dur, reverse_proxy_port: 443}
|
||||||
|
- {service: frigate, port: 10001, domain: null, reverse_proxy: nginx_barad-dur, reverse_proxy_port: 443}
|
||||||
- name: Insert into Postgres table service_data
|
- name: Insert into Postgres table service_data
|
||||||
community.postgresql.postgresql_query:
|
community.postgresql.postgresql_query:
|
||||||
login_host: '{{homelab_config.database.host}}'
|
login_host: '{{homelab_config.database.host}}'
|
||||||
|
|
|
@ -6,6 +6,6 @@ ENTRYPOINT ["python3", "mqtt.py"]
|
||||||
RUN pip3 install --upgrade pip
|
RUN pip3 install --upgrade pip
|
||||||
|
|
||||||
COPY requirements.txt .
|
COPY requirements.txt .
|
||||||
RUN pip install -r requirements.txt
|
RUN pip3 install -r requirements.txt
|
||||||
|
|
||||||
COPY src .
|
COPY src .
|
||||||
|
|
|
@ -24,12 +24,12 @@ def on_message(client, userdata, message):
|
||||||
|
|
||||||
|
|
||||||
def subscribe():
|
def subscribe():
|
||||||
client = mqtt.Client('frigate_notifications')
|
client = mqtt.Client()
|
||||||
client.username_pw_set(os.environ['MQTT_USERNAME'], password=os.environ['MQTT_PASSWORD'])
|
client.username_pw_set(os.environ['MQTT_USERNAME'], password=os.environ['MQTT_PASSWORD'])
|
||||||
client.on_connect = on_connect
|
client.on_connect = on_connect
|
||||||
client.on_message = on_message
|
client.on_message = on_message
|
||||||
|
|
||||||
client.connect(host='192.168.0.6', port=1883)
|
client.connect(host='mqtt', port=1883)
|
||||||
client.loop_forever()
|
client.loop_forever()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import json
|
import json
|
||||||
import requests
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
last_notification_time = {}
|
last_notification_time = {}
|
||||||
|
|
||||||
|
@ -30,8 +30,15 @@ def send_notification(event_id, camera, object_label, score, priority=3):
|
||||||
{
|
{
|
||||||
'action': 'http',
|
'action': 'http',
|
||||||
'label': 'Disable (30m)',
|
'label': 'Disable (30m)',
|
||||||
'url': 'https://www.google.com/',
|
'url': f'https://frigate.homelab.net/webcontrol/camera/{camera}/detect',
|
||||||
'method': 'GET',
|
'method': 'POST',
|
||||||
|
'headers': {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
'body': json.dumps({
|
||||||
|
'value': False,
|
||||||
|
'duration': 30
|
||||||
|
}),
|
||||||
'clear': True
|
'clear': True
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -49,9 +56,15 @@ def send_notification(event_id, camera, object_label, score, priority=3):
|
||||||
{
|
{
|
||||||
'action': 'http',
|
'action': 'http',
|
||||||
'label': 'DBL (30m)',
|
'label': 'DBL (30m)',
|
||||||
'url': 'https://www.google.com/',
|
'url': f'https://frigate.homelab.net/webcontrol/camera/{camera}/detect',
|
||||||
'method': 'GET',
|
'method': 'POST',
|
||||||
'clear': True
|
'headers': {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
'body': json.dumps({
|
||||||
|
'value': False,
|
||||||
|
'duration': 30
|
||||||
|
})
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
FROM python:3.11
|
||||||
|
WORKDIR /code
|
||||||
|
|
||||||
|
ENTRYPOINT ["python3", "server.py"]
|
||||||
|
|
||||||
|
RUN pip3 install --upgrade pip
|
||||||
|
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip3 install -r requirements.txt
|
||||||
|
|
||||||
|
COPY src .
|
|
@ -0,0 +1,2 @@
|
||||||
|
flask==2.3.2
|
||||||
|
paho-mqtt==1.6.1
|
|
@ -0,0 +1,37 @@
|
||||||
|
import os
|
||||||
|
from time import sleep
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
from flask import Blueprint, request, jsonify
|
||||||
|
import paho.mqtt.publish as mqtt_publish
|
||||||
|
|
||||||
|
|
||||||
|
blueprint = Blueprint('detection', __name__)
|
||||||
|
|
||||||
|
|
||||||
|
def set_camera_detection(camera: str, value: bool, delay: int = 0) -> None:
|
||||||
|
sleep(delay)
|
||||||
|
|
||||||
|
mqtt_publish.single(f'frigate/{camera}/detect/set', 'ON' if value else 'OFF', hostname='mqtt', port=1883, auth={'username': os.environ['MQTT_USERNAME'], 'password': os.environ['MQTT_PASSWORD']})
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route('/camera/<string:camera>/detect', methods=['POST'])
|
||||||
|
def camera_detect_POST(camera):
|
||||||
|
if not request.json:
|
||||||
|
return jsonify({
|
||||||
|
'status': 'failure',
|
||||||
|
'description': 'Request body needs to be in JSON format'
|
||||||
|
}), 400
|
||||||
|
|
||||||
|
value = request.json.get('value', True)
|
||||||
|
set_camera_detection(camera, value)
|
||||||
|
|
||||||
|
duration = request.json.get('duration', 0)
|
||||||
|
if duration > 0:
|
||||||
|
# Start sleeping thread to revert value after duration
|
||||||
|
thread = Thread(target=set_camera_detection, args=(camera, not value, duration * 60))
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'status': 'success'
|
||||||
|
}), 200
|
|
@ -0,0 +1,20 @@
|
||||||
|
from flask import Flask, jsonify
|
||||||
|
|
||||||
|
import detection
|
||||||
|
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.register_blueprint(detection.blueprint)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/', methods=['GET'])
|
||||||
|
def home_GET():
|
||||||
|
return jsonify({
|
||||||
|
'status': 'success',
|
||||||
|
'name': 'webcontrol',
|
||||||
|
'description': 'This is a custom webcontrol API for Frigate that allows minimal control over the NVR system through an HTTP API'
|
||||||
|
}), 200
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host='0.0.0.0', port=80, debug=False)
|
Loading…
Reference in New Issue