Unifi Protect - Recording Mode schalten (mit Loxberry)

Einklappen
X
 
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge
  • MarkusCosi
    LoxBus Spammer
    • 28.09.2023
    • 369

    #1

    Unifi Protect - Recording Mode schalten (mit Loxberry)

    Hallo zusammen,

    Ziel: Aufzeichnungsmodus in Unifi Protect für Kameras abhängig von Anwesenheit / Abwesenheit ändern. D.h., Video-Aufzeichnungen z.B. nur bei Abwesenheit.
    Benötigt: Loxberry mit dem AnyPlugin, ggf. noch das python requests package installieren (https://requests.readthedocs.io/en/latest/user/install/)

    Leider erlaubt die aktuelle offizielle API zu Protect (UniFi Protect API (7.1.76), siehe https://<<IP_UDM>>/unifi-api/protect unter "Patch camera settings") noch nicht den Recording Modus einzelner Kameras oder übergreifend zu ändern. Dort sind bisher nur folgende Endpunkte dokumentiert: name, osdSettings, ledSettings, lcdMessage, lcdMessage, micVolume, videoMode, hdrType, smartDetectSettings.

    Die interne, inoffizielle API erlaubt dennoch ein Anpassen des Rec-Modes. Der Ansatz gestaltet sich analog zu dem PoE-Schalten eines Unifi Switches (hier). Hierzu ein Benutzer-Konto mit "Full Management"-Rechten hinsichtlich Protect im Web-Interface links unten unter People nutzen (die Login-Credentials im Code unten im .py -file anpassen, ggf. einen dedizierten Nutzer mit "local access only" einrichten).
    Klicke auf die Grafik für eine vergrößerte Ansicht  Name: protect3.jpg Ansichten: 0 Größe: 38,5 KB ID: 485838

    Dafür einfach ein .py-File (z.B. "UnifiRecMode.py") mit folgendem Inhalt anlegen und über den File manager unter /opt/loxberry/webfrontend/html/XL/user/ ablegen (und im Loxberry-Terminal "chmod +x UnifiRecMode.py"):

    Code:
    import requests
    import argparse
    import urllib3
    
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    
    UDM_HOST = "https://<<IP_UDM>>"
    USERNAME = "yourUserName"
    PASSWORD = "yourPW"
    
    session = requests.Session()
    session.verify = False
    
    
    csrf_token = None
    
    def login():
        global csrf_token
    
        r = session.post(
            f"{UDM_HOST}/api/auth/login",
            json={
                "username": USERNAME,
                "password": PASSWORD
            },
        )
        r.raise_for_status()
    
        csrf_token = (
            r.headers.get("x-updated-csrf-token")
            or r.headers.get("x-csrf-token")
        )
    
        print("CSRF:", csrf_token)
    
    
    def get_cameras():
        r = session.get(f"{UDM_HOST}/proxy/protect/api/cameras")
        r.raise_for_status()
        return r.json()
    
    def set_mode(cam_id, mode):
        headers = {
            "X-CSRF-Token": csrf_token,
            "X-Requested-With": "XMLHttpRequest",
            "Content-Type": "application/json",
        }
    
        r = session.patch(
            f"{UDM_HOST}/proxy/protect/api/cameras/{cam_id}",
            json={
                "recordingSettings": {
                    "mode": mode
                }
            },
            headers=headers,
        )
    
        print(r.status_code, r.text[:500])
    
        r.raise_for_status()
    
    
    def main():
        parser = argparse.ArgumentParser()
        parser.add_argument("-m", "--mode", required=True, help="always | detections | never")
        parser.add_argument("-f", "--filter", default="", help="camera name filter substring")
        args = parser.parse_args()
    
        login()
    
        cams = get_cameras()
    
        for cam in cams:
            name = cam.get("name", "")
            cam_id = cam.get("id")
    
            if args.filter and args.filter not in name:
                continue
    
            print(f"{name} -> {args.mode}")
    
            try:
                set_mode(cam_id, args.mode)
                print("  OK")
            except Exception as e:
                print(f"  FAIL: {e}")
    
    
    if __name__ == "__main__":
        main()
    ...in der Loxone Config kann das Skript dann über einen virtuellen Ausgang und das AnyPlugin des Loxberry benutzt werden, d.h. die folgenden Befehle setzt das AnyPlugin dann ab (die kann man auch zunächst im Loxberry Terminal testen):

    Code:
    python3 UnifiRecMode.py -m never
    python3 UnifiRecMode.py -m detections
    oder
    Code:
    python3 UnifiRecMode.py -m detections -f "Kamera Name"
    Hierzu einen virt. Ausgang anlegen zum AnyPlugin (Adresse: tcp://<<IPLoxberry>>:9095, Verbindung nach Senden schließen), darin einen virt. Befehl (Methode: GET, digital) mit folgenden Befehlen bei EIN und AUS:
    UnifiCamRecOn off command python3 /opt/loxberry/webfrontend/html/XL/user/UnifiRecMode.py -m detections
    UnifiCamRecOff off command python3 /opt/loxberry/webfrontend/html/XL/user/UnifiRecMode.py -m never

    Zum Check: Die Änderungen sieht man instantan in der Weboberfläche unter Devices...
    Klicke auf die Grafik für eine vergrößerte Ansicht  Name: protect.jpg Ansichten: 0 Größe: 139,4 KB ID: 485786
    In der Loxone Config kann das dann so aussehen (Schaltuhr nutzt den Modus "Abwesend" ganztägig):
    Klicke auf die Grafik für eine vergrößerte Ansicht  Name: protect2.jpg Ansichten: 0 Größe: 21,2 KB ID: 485836

    Sobald die offizielle API den Endpoint exponiert sollte das Ganze aber auch ohne Loxberry möglich sein...
    Zuletzt geändert von MarkusCosi; vor 28 Minuten.
  • bazzman
    Extension Master
    • 24.09.2019
    • 189

    #2
    Coole Sache! Ich hatte das mit einem Alpha-Status-Loxberry Plugin realisiert (mit etwas Perl Code), aber damit wäre es deutlich einfacher ;-)

    Kommentar

    • GeoPod
      MS Profi
      • 20.01.2021
      • 552

      #3
      Vielen Dank MarkusCosi und bazzman . Wirklich sehr spannend. Wenn ich mal Zeit habe, versuche ich dies mal umzusetzen.
      Bin sehr froh, dass ich beim Hausbau neben Loxone auf Unifi gesetzt habe. Ich nutze aber nur einen Bruchteil davon aus.

      Kommentar

      Lädt...