blink-mqtt-bridge

Begonnen von juppzupp, 15 Februar 2026, 19:56:05

Vorheriges Thema - Nächstes Thema

juppzupp

ich habe ein wenig mit mit blinkpy https://github.com/fronzbot/blinkpy gespielt.
die neue authentisierungsmethode von blink klappt damit.
da ich keine ahnung habe wie man das in richtung perl übersetzt, habe ich eine blink-mqtt-bridge gebastelt.
status ist "proof of concept", es klappt aber ist ein security-albtraum, da die credentials im klartext in einer json datei gespeichert werden.
man kann einzelne kameras armen/disarmen, das system armen/disarmen, und bekommt ein motion_detected reading pro camera.
keine verarbeitung von snapshots oder videos.
mir reicht das erstmal, da ich hauptsächlich automatisiert nachts die aussenkameras an haben möchte, und wenn keiner zu hause ist auch die im innenbereich.

wer mag, kann es von hier weiter "treiben", ich bin dazu zeitlich nicht in der lage.

das fhem device :

define blink MQTT2_DEVICE blink-bridge
attr blink DbLogExclude .*_timestamp$
attr blink event-on-change-reading .*
attr blink readingList blink/sync/[^/]+/status:.*    { my $t=$TOPIC;; $t=~s#^blink/sync/##;; $t=~s#/status$##;;json2nameValue($EVENT, $t."_");; }\
blink/cameras/[^/]+/status:.* { my $t=$TOPIC;; $t=~s#^blink/cameras/##;; $t=~s#/status$##;;json2nameValue($EVENT, $t."_");; }\

attr blink setList System:arm,disarm blink/sync/[SYSTEM NAME]/cmd $EVTPART1\
terasse:arm,disarm blink/cameras/[CAMERA NAME]/cmd $EVTPART1\
flur_unten:arm,disarm blink/cameras/[CAMERA NAME]/cmd $EVTPART1\
flur_oben:arm,disarm blink/cameras/[CAMERA NAME]/cmd $EVTPART1\
Küche:arm,disarm blink/cameras/[CAMERA NAME]/cmd $EVTPART1\

automatisch generierte installationsanleitung (mileage may vary) :

# Blink MQTT Bridge — clean install (Debian/Ubuntu)

## 1) System packages
sudo apt-get update
sudo apt-get install -y python3 python3-venv python3-pip

## 2) Create folder + venv
sudo mkdir -p /opt/blink-bridge
sudo chown $USER:$USER /opt/blink-bridge
cd /opt/blink-bridge

python3 -m venv .venv
source .venv/bin/activate

## 3) Install Python deps
pip install --upgrade pip
pip install blinkpy aiohttp aiomqtt

## 4) Copy files
cp /path/to/blink_bridge.py /opt/blink-bridge/
# Use test_blink_auth.py to create blink_credentials.json

## 5) Set env vars (optional)
export MQTT_ENABLED=true
export MQTT_HOST=127.0.0.1
export MQTT_PORT=1883
export MQTT_USER=youruser
export MQTT_PASS=yourpass
export MQTT_BASE_TOPIC=blink
export MQTT_STATUS_INTERVAL=60

## 6) Test run
python3 blink_bridge.py

# Optional: systemd service
# Create /etc/systemd/system/blink-bridge.service with:
#
# [Unit]
# Description=Blink MQTT Bridge
# After=network-online.target
# Wants=network-online.target
#
# [Service]
# Type=simple
# WorkingDirectory=/opt/blink-bridge
# Environment=MQTT_ENABLED=true
# Environment=MQTT_HOST=127.0.0.1
# Environment=MQTT_PORT=1883
# Environment=MQTT_USER=youruser
# Environment=MQTT_PASS=yourpass
# Environment=MQTT_BASE_TOPIC=blink
# Environment=MQTT_STATUS_INTERVAL=60
# ExecStart=/opt/blink-bridge/.venv/bin/python /opt/blink-bridge/blink_bridge.py
# Restart=always
# RestartSec=5
#
# [Install]
# WantedBy=multi-user.target
#
# Then:
# sudo systemctl daemon-reload
# sudo systemctl enable --now blink-bridge




JWRu

Ich werde wohl das mal ausprobieren: https://github.com/weirdtangent/blink2mqtt (beruht auf blinkpy).
Den Docker-Container kann ich auf meinem Synology NAS laufen lassen.
Ich hoffe, dass ich in den nächsten Wochen mal dazu komme und werde dann hier berichten.

Vielleicht ist es besser, wenn du den Thread nach Systeme->MQTT verschiebst. Da würde er aus meiner Sicht besser passen.
ZBox; RasPi 3B; RasPi Zero W; Homematic; Z-Wave; EnOcean, Shelly; DuoFern; Oregon- und Bresser-Sensoren; Steuerung Viessmann-Heizung; ESP32 für Strom-, Wasser-, Gaszähler, Arduino für Rauchmelder und FI-Schutzschalter

rabehd

Zitat von: juppzupp am 15 Februar 2026, 19:56:05attr blink readingList blink/sync/[^/]+/status:.*    { my $t=$TOPIC;; $t=~s#^blink/sync/##;; $t=~s#/status$##;;json2nameValue($EVENT, $t."_");; }\
blink/cameras/[^/]+/status:.* { my $t=$TOPIC;; $t=~s#^blink/cameras/##;; $t=~s#/status$##;;json2nameValue($EVENT, $t."_");; }\

Also das Attribut möchte mein FHEM nicht übernehmen.
Da ich es auch nicht verstehe....

Zitatblink: bad reading name { my $t=$TOPIC;; $t=~s#^blink/sync/##;; $t=~s#/status$##;;json2nameValue($EVENT, $t."_");; }\ (contains not A-Za-z/\d_\.- or is too long)
Auch funktionierende Lösungen kann man hinterfragen.

rabehd

Ich habe FHEM in einem Docker-Container auf einem Pi5.

Schon python3 blink_bridge.py meldet Probleme.
SUCCESS: 2FA verification completed!

============================================================
TESTING BASIC FUNCTIONALITY
============================================================

[4/5] Refreshing camera data...

📹 Cameras found:
  - Th: Armed=False, Battery=ok%
  - Ter : Armed=False, Battery=ok%
  - Zu: Armed=False, Battery=ok%
  - Wo: Armed=True, Battery=None%
  - Ka : Armed=True, Battery=None%
  - Tk : Armed=False, Battery=ok%

🔌 Sync modules found:
  - Systename: Armed=True

[5/5] Saving credentials to blink_credentials.json...
Credentials saved!

============================================================
ALL TESTS PASSED!
============================================================
blinkpy is working correctly with your Blink account.
You can now use this for FHEM integration.

SUCCESS! You can proceed with blinkpy integration.
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x7ffed169cfa0>
Unclosed connector
connections: ['deque([(<aiohttp.client_proto.ResponseHandler object at 0x7ffed16be8e0>, 946914.738256688), (<aiohttp.client_proto.ResponseHandler object at 0x7ffed16a0e20>, 946915.000574291)])', 'deque([(<aiohttp.client_proto.ResponseHandler object at 0x7ffed0e284c0>, 946915.165886772)])', 'deque([(<aiohttp.client_proto.ResponseHandler object at 0x7ffed0e28ee0>, 946920.742729671)])']
connector: <aiohttp.connector.TCPConnector object at 0x7ffed169cfd0>
Fatal error on SSL transport
protocol: <asyncio.sslproto.SSLProtocol object at 0x7ffed169cc70>
transport: <_SelectorSocketTransport closing fd=6>
Traceback (most recent call last):
  File "/usr/lib/python3.9/asyncio/selector_events.py", line 918, in write
    n = self._sock.send(data)
OSError: [Errno 9] Bad file descriptor

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.9/asyncio/sslproto.py", line 684, in _process_write_backlog
    self._transport.write(chunk)
  File "/usr/lib/python3.9/asyncio/selector_events.py", line 924, in write
    self._fatal_error(exc, 'Fatal write error on socket transport')
  File "/usr/lib/python3.9/asyncio/selector_events.py", line 719, in _fatal_error
    self._force_close(exc)
  File "/usr/lib/python3.9/asyncio/selector_events.py", line 731, in _force_close
    self._loop.call_soon(self._call_connection_lost, exc)
  File "/usr/lib/python3.9/asyncio/base_events.py", line 746, in call_soon
    self._check_closed()
  File "/usr/lib/python3.9/asyncio/base_events.py", line 510, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Fatal error on SSL transport
protocol: <asyncio.sslproto.SSLProtocol object at 0x7ffed16b6370>
transport: <_SelectorSocketTransport closing fd=7>
Traceback (most recent call last):
  File "/usr/lib/python3.9/asyncio/selector_events.py", line 918, in write
    n = self._sock.send(data)
OSError: [Errno 9] Bad file descriptor

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.9/asyncio/sslproto.py", line 684, in _process_write_backlog
    self._transport.write(chunk)
  File "/usr/lib/python3.9/asyncio/selector_events.py", line 924, in write
    self._fatal_error(exc, 'Fatal write error on socket transport')
  File "/usr/lib/python3.9/asyncio/selector_events.py", line 719, in _fatal_error
    self._force_close(exc)
  File "/usr/lib/python3.9/asyncio/selector_events.py", line 731, in _force_close
    self._loop.call_soon(self._call_connection_lost, exc)
  File "/usr/lib/python3.9/asyncio/base_events.py", line 746, in call_soon
    self._check_closed()
  File "/usr/lib/python3.9/asyncio/base_events.py", line 510, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Fatal error on SSL transport
protocol: <asyncio.sslproto.SSLProtocol object at 0x7ffed0e16700>
transport: <_SelectorSocketTransport closing fd=8>
Traceback (most recent call last):
  File "/usr/lib/python3.9/asyncio/selector_events.py", line 918, in write
    n = self._sock.send(data)
OSError: [Errno 9] Bad file descriptor

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.9/asyncio/sslproto.py", line 684, in _process_write_backlog
    self._transport.write(chunk)
  File "/usr/lib/python3.9/asyncio/selector_events.py", line 924, in write
    self._fatal_error(exc, 'Fatal write error on socket transport')
  File "/usr/lib/python3.9/asyncio/selector_events.py", line 719, in _fatal_error
    self._force_close(exc)
  File "/usr/lib/python3.9/asyncio/selector_events.py", line 731, in _force_close
    self._loop.call_soon(self._call_connection_lost, exc)
  File "/usr/lib/python3.9/asyncio/base_events.py", line 746, in call_soon
    self._check_closed()
  File "/usr/lib/python3.9/asyncio/base_events.py", line 510, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Fatal error on SSL transport
protocol: <asyncio.sslproto.SSLProtocol object at 0x7ffed0e167f0>
transport: <_SelectorSocketTransport closing fd=9>
Traceback (most recent call last):
  File "/usr/lib/python3.9/asyncio/selector_events.py", line 918, in write
    n = self._sock.send(data)
OSError: [Errno 9] Bad file descriptor

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.9/asyncio/sslproto.py", line 684, in _process_write_backlog
    self._transport.write(chunk)
  File "/usr/lib/python3.9/asyncio/selector_events.py", line 924, in write
    self._fatal_error(exc, 'Fatal write error on socket transport')
  File "/usr/lib/python3.9/asyncio/selector_events.py", line 719, in _fatal_error
    self._force_close(exc)
  File "/usr/lib/python3.9/asyncio/selector_events.py", line 731, in _force_close
    self._loop.call_soon(self._call_connection_lost, exc)
  File "/usr/lib/python3.9/asyncio/base_events.py", line 746, in call_soon
    self._check_closed()
  File "/usr/lib/python3.9/asyncio/base_events.py", line 510, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Auch funktionierende Lösungen kann man hinterfragen.