RTSP Camera on Overlay Script

This script is designed to integrate RTSP compatible cameras into a designed for Home Assistant via MQTT discovery messages and manage media playback through a Kodi media center. The script is structured in Python and utilizes several libraries to handle HTTP requests, subprocess management, MQTT communication, and JSON data handling.

Features

  1. RTSP Stream Management: Handles multiple RTSP streams, allowing you to start and stop video feeds based on commands received over MQTT.
  2. MQTT Integration: Connects to an MQTT broker to receive commands and publish the state of camera streams.
  3. Kodi Control: Sends commands to a Kodi media center to pause and play media automatically when switching between streams.
  4. Home Assistant Compatibility: Publishes MQTT discovery messages to integrate seamlessly with Home Assistant, making each camera stream appear as a switchable entity.
  5. Error Handling: Includes basic error handling to manage exceptions and ensure the system remains operational in case of minor errors.

Components of the Script

Global Variables and Dictionaries

  • current_stream: A dictionary that tracks the state of the current stream, including whether Kodi was playing when the stream started.
  • streams: Contains the URLs for the RTSP streams, indexed by a friendly name. Each URL should be customized with the correct credentials and IP addresses for your cameras.
  • broker_address, user, password, topic, mqtt_port: Configuration settings for connecting to the MQTT broker.

Functions

  1. control_kodi(action):
    • Purpose: Sends a play/pause command to Kodi.
    • Parameters: action (string) – either “pause” or “play”.
    • Process: Constructs an HTTP request to Kodi’s JSON-RPC API to control playback.
  2. check_kodi_play_state():
    • Purpose: Checks whether Kodi is currently playing.
    • Returns: Playback speed (0 for paused, 1 for playing).
  3. display_rtsp(stream_key, action):
    • Purpose: Manages the display of RTSP streams based on MQTT commands.
    • Parameters: stream_key (the camera identifier), action (either “start” or “stop”).
    • Process: Starts or stops the video feed and manages the state of Kodi playback accordingly.
  4. on_message(client, userdata, message):
    • Purpose: Callback function that triggers when an MQTT message is received.
    • Process: Parses the message and calls display_rtsp to show or hide the specified stream.
  5. publish_discovery_messages(client):
    • Purpose: Publishes discovery messages to Home Assistant to automatically create entities for each camera.
    • Process: Iterates through each stream and sends a configuration payload over MQTT.
  6. publish_state(stream_key, state):
    • Purpose: Publishes the current state of a stream to MQTT.
    • Parameters: stream_key (the camera identifier), state (either “on” or “off”).
  7. initialize_camera_states():
    • Purpose: Initializes the state of all camera streams to “off” upon script startup.

MQTT Client Setup and Loop

  • Sets up an MQTT client, connects to the broker, subscribes to the relevant topic, and enters a loop to listen for messages indefinitely.

Usage Instructions

  1. Modify the Placeholder Values: Replace placeholders in the streams dictionary and MQTT settings with actual data from your environment.
  2. Set Up Kodi and MQTT Broker: Ensure Kodi’s JSON-RPC API is accessible, and your MQTT broker is running.
  3. Run the Script: Execute the script on a system within the same network as your cameras and MQTT broker. The system should also be able to communicate with Kodi.

Conclusion

This script provides a robust solution for integrating RTSP camera streams into a smart home environment using MQTT, with added functionality for controlling media playback through Kodi. It’s particularly useful in scenarios where real-time video monitoring is needed without interrupting media playback.

This guide can be adapted as necessary to fit the specific configuration and setup details of your home automation system.

Home Assistant:

This script integrates seamlessly with Home Assistant, allowing you to leverage its powerful automation capabilities in conjunction with real-time video monitoring from your RTSP cameras. By utilizing MQTT for communication, the script automatically publishes camera streams as entities within Home Assistant, enabling you to trigger automations and control stream visibility directly from your Home Assistant dashboard. For instance I use in conjunction with Frigate, so when a specific object is detected, it can displayed on the screen.

Script:

import os
import subprocess
import requests
import json
import time
import threading
import paho.mqtt.client as mqtt
import paho.mqtt.publish as publish

# Dictionary to keep track of the current stream process and the original play state
current_stream = {
    'process': None,
    'was_playing': False,
    'active_stream': None,  # Track the currently active stream
    'state': {}  # Added state dictionary to keep track of each stream's state
}

# RTSP URLs dictionary with generic credentials
streams = {
    "fdoorbell": "rtsp://user:password@camera-ip:554/h264Preview_01_main",
    "parking_area": "rtsp://user:password@camera-ip:554/cam/realmonitor?channel=1&subtype=0",
    # Add additional streams as needed
}

# MQTT setup with generic credentials
broker_address = "mqtt-broker-ip"
user = "mqtt-user"
password = "mqtt-password"
topic = "camera/control/#"
mqtt_port = 1883

# Device Information
device_id = "device_id"
device_name = "Device Name"
device_serial = "serial_number"
device_manufacturer = "Manufacturer"
device_model = "Model"

def control_kodi(action):
    # Control Kodi functionality
    kodi_url = 'http://kodi-ip:port/jsonrpc'
    headers = {'Content-Type': 'application/json'}
    payload = {
        "jsonrpc": "2.0",
        "method": "Player.PlayPause",
        "params": {
            "playerid": 1
        },
        "id": 1
    }
    try:
        response = requests.post(kodi_url, headers=headers, data=json.dumps(payload))
        print(f"Response from Kodi: {response.text}")
    except Exception as e:
        print(f"Error controlling Kodi: {e}")

def check_kodi_play_state():
    # Check the current play state of Kodi
    kodi_url = 'http://kodi-ip:port/jsonrpc'
    headers = {'Content-Type': 'application/json'}
    payload = {
        "jsonrpc": "2.0",
        "method": "Player.GetProperties",
        "params": {
            "playerid": 1,
            "properties": ["speed"]
        },
        "id": 1
    }
    try:
        response = requests.post(kodi_url, headers=headers, data=json.dumps(payload))
        response_data = response.json()
        return response_data.get("result", {}).get("speed", 1)
    except Exception as e:
        print(f"Error checking Kodi play state: {e}")
        return 1

def display_rtsp(stream_key, action):
    # Manage the display of RTSP streams
    global current_stream
    try:
        if action == "start":
            # Example logic to handle stream starting
            pass
        elif action == "stop":
            # Example logic to handle stream stopping
            pass
    except Exception as e:
        print(f"Error in display_rtsp: {e}")

def on_message(client, userdata, message):
    # Handle MQTT messages
    msg = str(message.payload.decode("utf-8"))
    stream_key = message.topic.split('/')[-1]
    if msg == "on":
        display_rtsp(stream_key, "start")
    elif msg == "off":
        display_rtsp(stream_key, "stop")

def publish_discovery_messages(client):
    # Publish MQTT discovery messages for Home Assistant integration
    global streams
    for stream_key, _ in streams.items():
        # Example discovery message
        pass

def publish_state(stream_key, state):
    # Publish state changes
    state_topic = f"homeassistant/switch/{device_id}/camera_{stream_key}/state"
    try:
        publish.single(
            state_topic,
            payload=state,
            hostname=broker_address,
            port=mqtt_port,
            auth={"username": user, "password": password},
            retain=True
        )
    except Exception as e:
        print(f"Error publishing state for {stream_key}: {e}")

def initialize_camera_states():
    # Initialize camera states
    for stream_key in streams:
        publish_state(stream_key, "off")

client = mqtt.Client("CameraControl")
client.username_pw_set(user, password)
client.on_message = on_message

try:
    client.connect(broker_address)
    client.subscribe(topic)
    initialize_camera_states()
    publish_discovery_messages(client)
    client.loop_forever()
except Exception as e:
    print(f"Error connecting to MQTT broker: {e}")

Leave a Reply

Your email address will not be published. Required fields are marked *