Skip to content

Commit

Permalink
v2.3.10 (#908)
Browse files Browse the repository at this point in the history
* Update bridge status #907

* Update bridge status on HA status online #907

* Changelog
  • Loading branch information
mrlt8 authored Jul 9, 2023
1 parent 9290fd0 commit bf618b9
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 23 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ You can then use the web interface at `http://localhost:5000` where localhost is

See [basic usage](#basic-usage) for additional information or visit the [wiki page](https://github.com/mrlt8/docker-wyze-bridge/wiki/Home-Assistant) for additional information on using the bridge as a Home Assistant Add-on.

## What's Changed in v2.3.10

* FIX: KeyError when upgrading with old cache data in v2.3.9 (#905) Thanks @itsamenathan!
* You should be able to remove or set `FRESH_DATA` back to false.
* MQTT: Update bridge status (#907) Thanks @giorgi1324!

## What's Changed in v2.3.9

* NEW: ENV Options - token-based authentication (#876)
Expand Down
6 changes: 6 additions & 0 deletions app/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## What's Changed in v2.3.10

* FIX: KeyError when upgrading with old cache data in v2.3.9 (#905) Thanks @itsamenathan!
* You should be able to remove or set `FRESH_DATA` back to false.
* MQTT: Update bridge status (#907) Thanks @giorgi1324!

## What's Changed in v2.3.9

* NEW: ENV Options - token-based authentication (#876)
Expand Down
2 changes: 1 addition & 1 deletion app/wyzebridge/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
HASS_TOKEN: str = getenv("SUPERVISOR_TOKEN", "")
setup_hass(HASS_TOKEN)
MQTT_DISCOVERY = env_bool("MQTT_DTOPIC")

MQTT_TOPIC = env_bool("MQTT_TOPIC", "wyzebridge").strip("/")
ON_DEMAND = bool(env_bool("on_demand") if getenv("ON_DEMAND") else True)
CONNECT_TIMEOUT: int = env_bool("CONNECT_TIMEOUT", 20, style="int")

Expand Down
35 changes: 26 additions & 9 deletions app/wyzebridge/mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import paho.mqtt.client
import paho.mqtt.publish
from wyzebridge.bridge_utils import env_bool
from wyzebridge.config import IMG_PATH, MQTT_DISCOVERY, VERSION
from wyzebridge.config import IMG_PATH, MQTT_DISCOVERY, MQTT_TOPIC, VERSION
from wyzebridge.logging import logger
from wyzebridge.wyze_commands import GET_CMDS, GET_PAYLOAD, PARAMS, SET_CMDS
from wyzecam import WyzeCamera
Expand Down Expand Up @@ -40,7 +40,7 @@ def wrapper(*args, **kwargs):
@mqtt_enabled
def wyze_discovery(cam: WyzeCamera, cam_uri: str) -> None:
"""Add Wyze camera to MQTT if enabled."""
base = f"wyzebridge/{cam_uri or cam.name_uri}/"
base = f"{MQTT_TOPIC}/{cam_uri or cam.name_uri}/"
msgs = [(f"{base}state", "stopped")]
if MQTT_DISCOVERY:
base_payload = {
Expand All @@ -58,7 +58,7 @@ def wyze_discovery(cam: WyzeCamera, cam_uri: str) -> None:
for entity, data in get_entities(base).items():
topic = f"{MQTT_DISCOVERY}/{data['type']}/{cam.mac}/{entity}/config"
if "availability_topic" not in data["payload"]:
data["payload"]["availability_topic"] = "wyzebridge/state"
data["payload"]["availability_topic"] = f"{MQTT_TOPIC}/state"

payload = dict(
base_payload | data["payload"],
Expand All @@ -79,15 +79,32 @@ def mqtt_sub_topic(m_topics: list, callback) -> Optional[paho.mqtt.client.Client
client.username_pw_set(MQTT_USER, MQTT_PASS or None)
client.user_data_set(callback)
client.on_connect = lambda mq_client, *_: (
mq_client.publish("wyzebridge/state", "online"),
[mq_client.subscribe(f"wyzebridge/{m_topic}") for m_topic in m_topics],
mq_client.publish(f"{MQTT_TOPIC}/state", "online"),
[mq_client.subscribe(f"{MQTT_TOPIC}/{m_topic}") for m_topic in m_topics],
)
client.will_set("wyzebridge/state", payload="offline", qos=1, retain=True)
client.will_set(f"{MQTT_TOPIC}/state", payload="offline", qos=1, retain=True)
client.connect(MQTT_HOST, int(MQTT_PORT or 1883), 30)
if MQTT_DISCOVERY:
client.subscribe(f"{MQTT_DISCOVERY}/status")
client.message_callback_add(
f"{MQTT_DISCOVERY}/status",
lambda mq_client, _, msg: bridge_status(mq_client, [])
if msg.payload.decode().lower() == "online"
else None,
)
client.loop_start()
return client


def bridge_status(client: Optional[paho.mqtt.client.Client], cams: list):
"""Set bridge online if MQTT is enabled."""
if not client:
return
client.publish(f"{MQTT_TOPIC}/state", "online")
for cam in cams:
client.publish(f"{MQTT_TOPIC}/{cam}/state", "online")


@mqtt_enabled
def send_mqtt(messages: list) -> None:
"""Publish a message to the MQTT server."""
Expand All @@ -105,9 +122,8 @@ def send_mqtt(messages: list) -> None:

@mqtt_enabled
def publish_message(topic: str, message=None):
base = "wyzebridge/"
paho.mqtt.publish.single(
topic=base + topic,
topic=f"{MQTT_TOPIC}/{topic}",
payload=message,
hostname=MQTT_HOST,
port=int(MQTT_PORT or 1883),
Expand All @@ -133,14 +149,15 @@ def update_preview(cam_name: str):


@mqtt_enabled
def mqtt_cam_control(cam_names: dict, callback):
def cam_control(cam_names: dict, callback):
topics = []
for uri in cam_names:
topics += [f"{uri.lower()}/{t}/set" for t in SET_CMDS]
topics += [f"{uri.lower()}/{t}/get" for t in GET_CMDS | PARAMS]

if client := mqtt_sub_topic(topics, callback):
client.on_message = _on_message
return client


def _on_message(client, callback, msg):
Expand Down
13 changes: 8 additions & 5 deletions app/wyzebridge/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from wyzebridge.config import MQTT_DISCOVERY, SNAPSHOT_INT, SNAPSHOT_TYPE
from wyzebridge.ffmpeg import rtsp_snap_cmd
from wyzebridge.logging import logger
from wyzebridge.mqtt import mqtt_cam_control, publish_message, update_preview
from wyzebridge.mqtt import bridge_status, cam_control, publish_message, update_preview
from wyzebridge.rtsp_event import RtspEvent


Expand Down Expand Up @@ -96,15 +96,16 @@ def monitor_streams(self, mtx_health: Callable) -> None:
self.stop_flag = False
if self.thread:
self.thread.start()
mqtt = mqtt_cam_control(self.streams, self.send_cmd)
mqtt = cam_control(self.streams, self.send_cmd)
logger.info(f"🎬 {self.total} stream{'s'[:self.total^1]} enabled")
event = RtspEvent(self.streams)
while not self.stop_flag:
mtx_health()
event.read(timeout=1)
cams = self.health_check_all()
if cams and SNAPSHOT_TYPE == "rtsp":
self.snap_all(cams)
self.snap_all(cams)
if int(time.time()) % 15 == 0:
mtx_health()
bridge_status(mqtt, cams)
if mqtt:
mqtt.loop_stop()
logger.info("Stream monitoring stopped")
Expand Down Expand Up @@ -136,6 +137,8 @@ def snap_all(self, cams: list[str]):
Parameters:
- cams (list[str]): names of the streams to take a snapshot of.
"""
if SNAPSHOT_TYPE != "rtsp" or not cams:
return
if time.time() - self.last_snap < SNAPSHOT_INT:
return
self.last_snap = time.time()
Expand Down
8 changes: 4 additions & 4 deletions app/wyzebridge/wyze_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@

import requests
from wyzebridge.bridge_utils import env_bool
from wyzebridge.config import BOA_COOLDOWN, BOA_INTERVAL, IMG_PATH
from wyzebridge.config import BOA_COOLDOWN, BOA_INTERVAL, IMG_PATH, MQTT_TOPIC
from wyzebridge.logging import logger
from wyzebridge.mqtt import MQTT_ENABLED, send_mqtt
from wyzebridge.wyze_commands import CMD_VALUES, GET_CMDS, GET_PAYLOAD, PARAMS, SET_CMDS
from wyzecam import TutkError, WyzeIOTCSession, WyzeIOTCSessionState, tutk_protocol
from wyzecam import WyzeIOTCSession, WyzeIOTCSessionState, tutk_protocol


def cam_http_alive(ip: str) -> bool:
Expand Down Expand Up @@ -178,7 +178,7 @@ def camera_control(


def update_mqtt_values(topic: str, cam_name: str, resp: dict):
base = f"wyzebridge/{cam_name}"
base = f"{MQTT_TOPIC}/{cam_name}"
if msgs := [(f"{base}/{k}", resp[v]) for k, v in PARAMS.items() if v in resp]:
send_mqtt(msgs)

Expand Down Expand Up @@ -275,7 +275,7 @@ def motion_alarm(cam: dict):
logger.info(f"[MOTION] Alarm file detected at {cam['last_photo'][1]}")
cam["cooldown"] = datetime.now() + timedelta(seconds=BOA_COOLDOWN)
cam["last_alarm"] = cam["last_photo"]
send_mqtt([(f"wyzebridge/{cam['uri']}/motion", motion)])
send_mqtt([(f"{MQTT_TOPIC}/{cam['uri']}/motion", motion)])
if motion and (http := env_bool("boa_motion")):
try:
resp = requests.get(http.format(cam_name=cam["uri"]))
Expand Down
8 changes: 4 additions & 4 deletions app/wyzebridge/wyze_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from typing import Optional

from wyzebridge.bridge_utils import env_bool, env_cam
from wyzebridge.config import BRIDGE_IP, COOLDOWN
from wyzebridge.config import BRIDGE_IP, COOLDOWN, MQTT_TOPIC
from wyzebridge.ffmpeg import get_ffmpeg_cmd
from wyzebridge.logging import logger
from wyzebridge.mqtt import send_mqtt, update_mqtt_state, wyze_discovery
Expand Down Expand Up @@ -444,9 +444,9 @@ def get_cam_params(
logger.info(f"🔊 Audio Enabled - {codec_str.upper()}/{rate:,}Hz")

mqtt = [
(f"wyzebridge/{uri.lower()}/net_mode", net_mode),
(f"wyzebridge/{uri.lower()}/wifi", wifi),
(f"wyzebridge/{uri.lower()}/audio", json.dumps(audio) if audio else False),
(f"{MQTT_TOPIC}/{uri.lower()}/net_mode", net_mode),
(f"{MQTT_TOPIC}/{uri.lower()}/wifi", wifi),
(f"{MQTT_TOPIC}/{uri.lower()}/audio", json.dumps(audio) if audio else False),
]
send_mqtt(mqtt)
return v_codec, fps, audio
Expand Down

0 comments on commit bf618b9

Please sign in to comment.