Willkommen im Loxone Community Forum. Um alle Funktionen nutzen und sehen zu können, registriere dich bitte zuerst. Dies gilt auch für das herunterladen von Dateien.
Ich hoffe es kann mir jemand helfen. Bin hier ziemlich neu, also Entschuldigung, falls ich das Thema hier falsch Poste. Ich habe das Blink System gefunden (https://www.blinkforhome.de), und wollte fragen, ob jemand so eine Kamera schon mit Loxone in Verwendung hat bzw ob man sie zum Loxone System hinzufügen kann. Der Preis ist momentan recht gut und ich überlege mir diese zu kaufen.
Ich habe
- einen virtuellen Ausgang gesetzt mit der Adresse: https://rest-e003.immedia-semi.com
- einen virtuellen Ausgangsbefehl gesetzt mit:
. Befehl bei EIN: /api/v1/accounts/1234/networks/1234/state/arm
. HTTP-Erweiterung bei EIN: token-auth: {Auth_Token}
. HTTP_Methode bei EIN: POST
. Äquivalent bei AUS mit "disarm"
Ist das nur ne Cloudlösung ? In USA betreiben die ja recht dystopische Ansätze die Besitzer zu überreden prophylaktisch der Polizei Zugriff zu geben. Und die Polizei ist Werbepartner und bekommt Prämien wenn besonders viele Kameras in ihren Bezirken verkauft wurden.
Das fand ich mega abschreckend.
Zuletzt geändert von Miep Miep; 29.07.2021, 19:40.
äähm, jo dann kommt diese schon mal nicht für mich in Frage. Ich finde den Ansatz, dass sich ein Sicherheitsdienst oder die Polizei auf die Kameras im Alarmfalle aufschalten gar nicht so verkehrt, aber nur solange ich das steuern kann und nicht eine andere Firma, die nach USA Rechten arbeitet
ich weiß schon älter und ich habe auch schon mal gefragt aber ich liebäugle immer noch mit den cams (aufgrund des Preises und da man keine Kabel verlegen muss).
Disclaimer: Für die Umsetzung braucht es schon gefestigte Kenntnisse in der Loxone Config, sowie Erfahrung mit den verschiedenen Komponenten. Ich werde wenn möglich auf Rückfragen antworten, aber ich übernehme keine Verantwortung für Fehler, Sicherheitslücken oder sonst Irgendwas.
Da die Installation aller 3 gut beschrieben ist, gehe ich darauf jetzt nicht im Detail ein. Einzig wichtig ist, dass ihr für die Python Themen pip3 und python3 bei den Befehlen verwendet, damit unter LoxBerry/DietPi auch die richtigen Python Versionen verwendet werden.
Anmerkung: Die Blink API ist nicht offiziell dokumentiert. Noch dazu ist die API sehr "sensibel". Heißt übersetzt, dass man sehr vorsichtig mit den Requests umgehen muss, weil man sonst sehr schnell in Service protection limits reinkommt, was ein Timeout von unbestimmter Zeit bedeutet. Die Blink App ist davon aber nicht betroffen und funktioniert weiterhin.
Python Scripts
Insgesamt habe ich 7 Python Scripte im Einsatz. Die Scripte sind alle quick and dirty und ich schere mich nicht um das Error Handling. Ich bin auch kein Python Profi, daher kann es gut sein, dass das Ganze schöner geht, aber für mich ist nur wichtig, dass es geht.
PHP-Code:
# blink_start.py
# Authentifizierung gegenüber der Blink API, sowie Speicherung der Zugangsdaten und des Tokens in der blink_credentials.json
import asyncio
import sys
from aiohttp import ClientSession
from blinkpy.blinkpy import Blink
from blinkpy.auth import Auth
async def start(session: ClientSession):
blink = Blink(session=session)
blink.auth = Auth({"username": "<BlinkUsername>", "password": "<BlinkPasswort>"}, no_prompt=True, session=session)
await blink.start()
return blink
async def main():
session = ClientSession()
blink = await start(session)
await blink.save("blink_credentials.json")
await session.close()
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Sobald ihr das Script ausgeführt habt, bekommt ihr euren MFA Code aufs Handy oder per Email. Diesen müsst ihr wiederum an Blink übergeben:
PHP-Code:
# blink_verify.py
# Übergabe des Codes an Blink
# Erwartet als Parameter den Code
import sys
import asyncio
from aiohttp import ClientSession
from blinkpy.blinkpy import Blink
from blinkpy.auth import Auth
from blinkpy.helpers.util import json_load
pin = sys.argv[1]
async def start(session: ClientSession):
blink = Blink(session=session)
blink.auth = Auth(await json_load("blink_credentials.json"), no_prompt = True)
await blink.start()
return blink
async def verify(blink, pin):
await blink.auth.send_auth_key(blink, pin)
await blink.setup_post_verify()
return pin
async def main(pin):
session = ClientSession()
blink = await start(session) # Könnte man sicherlich aus dem letzten Script übergeben, aber ich hol mir das Objekt immer neu
pin = await verify(blink, pin)
await session.close()
return pin
if __name__ == "__main__":
loop = asyncio.get_event_loop()
print(loop.run_until_complete(main(pin)))
Das nächste Script fragt den Onlinestatus der eigenen Blink Umgebung ab:
PHP-Code:
# blink_online.py
# Abfrage des Onlinestatus
import sys
import asyncio
from aiohttp import ClientSession
from blinkpy.blinkpy import Blink
from blinkpy.auth import Auth
from blinkpy.helpers.util import json_load
async def start(session: ClientSession):
blink = Blink(session=session)
blink.auth = Auth(await json_load("blink_credentials.json"), no_prompt = True)
try:
await blink.start()
return blink
except ValueError:
return None
async def main():
session = ClientSession()
blink = await start(session)
if blink is None:
return 0
await session.close()
if blink.available == True:
return 1
else:
return 0
if __name__ == "__main__":
loop = asyncio.get_event_loop()
print(loop.run_until_complete(main()))
Als nächstes die Abfrage des Armstates, also ob eure Bewegungserkennung aktiviert ist oder nicht:
PHP-Code:
# blink_armstate.py
# Abfrage des Armstatus eures Systems
import sys
import asyncio
from aiohttp import ClientSession
from blinkpy.blinkpy import Blink
from blinkpy.auth import Auth
from blinkpy.helpers.util import json_load
async def start(session: ClientSession):
blink = Blink(session=session)
blink.auth = Auth(await json_load("blink_credentials.json"))
await blink.start()
return blink
async def main():
session = ClientSession()
blink = await start(session)
sync = blink.sync["<NameEurersSystems>"]
await session.close()
if sync.arm == True:
return 1
else:
return 0
if __name__ == "__main__":
loop = asyncio.get_event_loop()
print(loop.run_until_complete(main()))
Als nächstes das Script zum setzen des Armstate
PHP-Code:
# blink_arm.py # Setzt den Armstate des Systems
# Erwartet "arm" oder "disarm" als Parameter
import sys
import asyncio
from aiohttp import ClientSession
from blinkpy.blinkpy import Blink
from blinkpy.auth import Auth
from blinkpy.helpers.util import json_load
command = sys.argv[1]
async def start(session: ClientSession):
blink = Blink(session=session)
blink.auth = Auth(await json_load("blink_credentials.json"))
await blink.start()
return blink
async def main(command):
session = ClientSession()
blink = await start(session)
sync = blink.sync["<NameEurersSystems>"]
if command == "arm":
await sync.async_arm(True)
elif command == "disarm":
await sync.async_arm(False)
await blink.refresh()
await session.close()
if sync.arm == True:
return 1
else:
return 0
if __name__ == "__main__":
loop = asyncio.get_event_loop()
print(loop.run_until_complete(main(command)))
Das nächste Script kümmert sich um die Kommunikation mit den einzelnen Kameras:
PHP-Code:
# blink_camera.py
# Set und Get der Kamera Daten
# Erwartet als ersten Parameter den Namen der Kamera
# Erwartet als zweiten Parameter, was gemacht werden soll:
# "armstate" - Status der Bewegungserkennung der Kamera
# "temp" - Aktuelle Temparatur an der Kamera
# "battery" - Batteriestatus
# "arm" - Aktivieren der Bewegungserkennung
# "disarm" - Deaktivieren der Bewegungserkennung
import sys
import asyncio
from aiohttp import ClientSession
from blinkpy.blinkpy import Blink
from blinkpy.auth import Auth
from blinkpy.helpers.util import json_load
cameraname = sys.argv[1]
command = sys.argv[2]
async def start(session: ClientSession):
blink = Blink(session=session)
blink.auth = Auth(await json_load("blink_credentials.json"))
await blink.start()
return blink
async def arm(camera, blink, armbool):
await camera.async_arm(armbool)
await blink.refresh()
if camera.arm == True:
return 1
else:
return 0
async def main(cameraname, command):
session = ClientSession()
blink = await start(session)
sync = blink.sync["<NameEurersSystems>"]
camera = sync.cameras[cameraname]
if command == "armstate":
if camera.arm == True:
returnvalue = 1
else:
returnvalue = 0
elif command == "temp":
returnvalue = camera.temperature_c
elif command == "battery":
returnvalue = camera.battery
elif command == "arm":
returnvalue = await arm(camera, blink, True)
elif command == "disarm":
returnvalue = await arm(camera, blink, False)
await session.close()
return returnvalue
if __name__ == "__main__":
loop = asyncio.get_event_loop()
print(loop.run_until_complete(main(cameraname, command)))
Zu guter Letzt das Script für das Aktualisieren und Abspeichern des Vorschaubildes:
PHP-Code:
# blink_camera_refresh_image.py
# Erwartet als Parameter den Kameranamen
import sys
import asyncio
from aiohttp import ClientSession
from blinkpy.blinkpy import Blink
from blinkpy.auth import Auth
from blinkpy.helpers.util import json_load
from PIL import Image, ImageDraw, ImageFont
from datetime import datetime
async def start(session: ClientSession):
blink = Blink(session=session)
blink.auth = Auth(await json_load("blink_credentials.json"))
await blink.start()
return blink
async def main(cameraname):
session = ClientSession()
blink = await start(session)
sync = blink.sync["<NameEurersSystems>"]
camera = sync.cameras[cameraname]
await camera.snap_picture()
picture = await camera.image_to_file('/opt/loxberry/blink/Images/' + cameraname + '.jpg') # Hier den Pfad für die Bilder anpassen
await session.close()
image_path = '/opt/loxberry/blink/Images/' + cameraname + '.jpg' # Hier den Pfad für die Bilder anpassen
image = Image.open(image_path)
draw = ImageDraw.Draw(image)
font_path = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"
font_size = 24
font = ImageFont.truetype(font_path, font_size)
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
text_position = (10, 10)
text_color = "white"
draw.text(text_position, timestamp, font=font, fill=text_color) # Hier wird ein Zeitstempel in das Bild mit eingefügt
output_image_path = '/opt/loxberry/blink/Images/' + cameraname + '.jpg'
image.save(output_image_path)
return
if __name__ == "__main__":
loop = asyncio.get_event_loop()
print(loop.run_until_complete(main(sys.argv[1])))
Damit man die Bilder in weiterer Folge in der Loxone Config verwenden kann, starte ich noch einen einfachen http Server. Dafür habe ich ein Shell Script erstellt, welches auch beim Start vom Raspberry losläuft.
Code:
#!/bin/bash
cd /opt/loxberry/blink/Images # Pfad zu den Bildern (der Gleiche wie oben)
python3 -m http.server
Loxone Config
Soweit waren das einmal die Scripts. Wenn ihr noch bei mir seit, dann geht es jetzt mit der Loxone Konfiguration weiter Dafür müsst ihr wie oben erwähnt Any Plugin auf eurem Loxberry installieren. Die Einstellungen sollten so aussehen:
Jetzt geht es ENDLICH in die Loxone Config
Hier die ganzen Logiken in der Übersicht:
Allgemeine Hinweise:
Zum Aufrufen der Scripte nutze ich Virtuelle Ausgänge. Ein Beispiel (hier für den Login):
Virtueller Ausgang:
Virtueller Ausgang Befehl:
Die Struktur des Befehls ist beim Any Plugin beschrieben. Die Rückgabe erfolgt über UDP und entsprechend gibt es mehrere Virtuelle UDB Eingänge und Virtuelle UDB Eingangs Befehle. Siehe dazu ebenfalls die Any Plugin Doku.
Beschreibung:
Login (Grüne Blöcke links oben)
Taster in der App, welche den Virtuellen Ausgang mit dem korrekten Befehl aufruft. Hier z.B. blink_output_login rcudp command sudo python3 /opt/loxberry/blink/blink_start.py
Virtueller Texteingang, wo man dann den MFA Code eingibt
Übergabe des Texteingangs an den Verify Ausgang
Regelmäßiger Aufruf der Scripte für die einzelnen Informationen (Blassgrüne Blöcke)
Ich habe hier einen Schalter "Synchronisierung". Dieser aktiviert in weiterer Folge den Aufruf der Scripte. Als Quelle nutze ich hier einen virtuellen Eingang Online Status, welcher einen Virtuellen Status zur Anzeige in der App setzt.
Zusätzlich hat der Online Eingang einen Error Output, wenn keine Daten geliefert werden (weil die Blink API mal wieder zickt). Sollte die API keine Daten schicken, dann gibt es nach 1h ein einmaliges Retry. Dafür gibt es einen UND Block (Synchronisieren war auf Ja und Error ist Ja), sowie 2 Verzögerungen (die eine, damit der Schalter noch 1 Sekunde auf On bleibt, damit ich den Ausgang in dem UND verwenden kann und die Andere für die 1h).
Danach geht es weiter mit einem Impulsgeber, welcher alle 30 Minuten einen Impuls abgibt, wenn Synchronisieren auf ein ist. Hiermit steuert man den Sync Intervall.
Danach kommt eigentlich 3x (genauer gesagt 4x) das Gleiche: Flankengesteuertes Wischrelay, mit Don 1s und Doff 30s, sowie jeweils die notwendigen Cycles wie der folgende Sequenzer braucht (Sequenzer 3 Ausgänge = 3 Cycles). Dies ist dafür da, damit die API nicht zu stark belastet wird.
Der Sequenzer called dann die einzelnen Virtuellen Ausgangs Befehle für die Scripte. Da es nur max. 8 Ausgänge gibt, sind mehrere Sequenzer in Reihe geschalten. Ab Screenshot oben sieht man 3 und der 4. ist im Screenshot unten ersichtlich.
Arm/Disarm des Systems (Blassrot)
Virtueller Eingang mit dem aktuellen Status wird über eine Verzögerung (weil der Eingang manchmal kurz den falschen Wert ausgibt) und einen Flankenerkennung an einen Schalter für die UI übergeben.
Der Schalter ruft wiederum über eine Flankenerkennung die Scripte auf.
Arm/Disarm der einzelnen Kameras (Blassblau)
Ist grundsätzlich gleich wie Punkt 3, allerdings mit einer zwischengeschalteten Ablaufsteuerung als Loadbalancer (wiedereinmal für die lahme API)
Die Ablaufsteuerung läuft ständig mit einigen Sleeps (welche die CPU quasi nicht belasten) vom Start des Miniservers weg (daher Startimpuls).
In der Steuerung werden die Eingänge abgefragt und wenn eine Wertänderung ansteht, dann wird diese an den Ausgang übergeben und danach 5 Sekunden gewartet.
Code:
if AI1 = AQ1
sleep 1
endif
if AI1 != AQ1
set AQ1 = AI1
sleep 5
endif
if AI2 = AQ2
sleep 1
endif
if AI2 != AQ2
set AQ2 = AI2
sleep 5
endif
if AI3 = AQ3
sleep 1
endif
if AI3 != AQ3
set AQ3 = AI3
sleep 5
endif
if AI4 = AQ4
sleep 1
endif
if AI4 != AQ4
set AQ4 = AI4
sleep 5
endif
if AI5 = AQ5
sleep 1
endif
if AI5 != AQ5
set AQ5 = AI5
sleep 5
endif
if AI6 = AQ6
sleep 1
endif
if AI6 != AQ6
set AQ6 = AI6
sleep 5
endif
if AI7 = AQ7
sleep 1
endif
if AI7 != AQ7
set AQ7 = AI7
sleep 5
endif
if AI8 = AQ8
sleep 1
endif
if AI8 != AQ8
set AQ8 = AI8
sleep 5
endif
goto 1
end
Das wars eigentlich auch schon mit der Datenlogik. Schaut auf den ersten Blick unglaublich kompliziert aus, ist aber eigentlich immer wieder das Gleiche.
Hier die Einbindung der Bilder als Intercoms:
Beschreibung:
Wieder eine Sequenzer Logik (das ist der Ausgang O4 des letzten Sequenzers im oberen Bild)
Der Sequenzer ruft die Aktualisierung der Bilder auf (siehe blink_camera_refresh_image.py oben)
Ein Intercom pro Kamera, welche als Videostream URL den http Server auf dem Loxberry hat, den wir bei den Scripten eingerichtet haben. z.B.: http://192.168.1.19:8000/Haustür.jpg --> Der Dateiname ist immer <Kameraname>.jpg
Zusätzlich gibt es bei den Intercoms noch einen Button (O1) zum manuellen Aktualisieren
Wir verarbeiten personenbezogene Daten über Nutzer unserer Website mithilfe von Cookies und anderen Technologien, um unsere Dienste bereitzustellen, Werbung zu personalisieren und Websiteaktivitäten zu analysieren. Wir können bestimmte Informationen über unsere Nutzer mit unseren Werbe- und Analysepartnern teilen. Weitere Einzelheiten finden Sie in unserer Datenschutzrichtlinie.
Wenn Sie unten auf "Einverstanden" klicken, stimmen Sie unserer Datenschutzrichtlinie und unseren Datenverarbeitungs- und Cookie-Praktiken wie dort beschrieben zu. Sie erkennen außerdem an, dass dieses Forum möglicherweise außerhalb Ihres Landes gehostet wird und Sie der Erhebung, Speicherung und Verarbeitung Ihrer Daten in dem Land, in dem dieses Forum gehostet wird, zustimmen.
Kommentar