267 lines
8.2 KiB
Python
Raw Normal View History

2024-09-20 17:44:22 +01:00
import os
2024-09-19 11:00:07 +01:00
import paho.mqtt.client as mqtt
import json
2024-09-20 17:44:22 +01:00
from dotenv import load_dotenv
2024-09-19 11:00:07 +01:00
2024-09-20 17:44:22 +01:00
# Load the .env file
load_dotenv()
2024-09-20 14:13:21 +01:00
2024-09-20 17:44:22 +01:00
# Define the MQTT server details
broker = os.environ.get("broker")
port = int(os.environ.get("port"))
# MQTT username and password
username = os.environ.get("username")
password = os.environ.get("password")
2024-09-19 11:00:07 +01:00
2024-09-20 17:44:22 +01:00
def create_client() -> mqtt.Client:
"""Create an MQTT client and connect it to the broker
2024-09-19 11:00:07 +01:00
Returns:
2024-09-20 11:13:04 +01:00
mqtt.Client: Connected MQTT client instance
2024-09-20 14:13:21 +01:00
"""
2024-09-19 11:00:07 +01:00
# Create a new MQTT client instance
client = mqtt.Client()
# Set username and password
client.username_pw_set(username, password)
# Connect to the MQTT broker
client.connect(broker, port, 60)
2024-09-20 14:13:21 +01:00
2024-09-19 11:00:07 +01:00
return client
2024-09-20 14:13:21 +01:00
2024-09-20 11:13:04 +01:00
def create_config(client: mqtt.Client) -> None:
2024-09-19 11:00:07 +01:00
"""Create Home Assistant discovery topics
Args:
2024-09-20 11:13:04 +01:00
client (mqtt.Client): MQTT Client
2024-09-20 14:13:21 +01:00
"""
2024-09-19 11:00:07 +01:00
# Device-specific information for multiple sensors
node_id = "floppy_player" # Unique device ID
# Define discovery and state topics for each sensor
discovery_topic_disc = f"homeassistant/sensor/floppy_player/current_disc/config"
2024-09-20 14:13:21 +01:00
discovery_topic_disc_type = (
f"homeassistant/sensor/floppy_player/current_disc_type/config"
)
discovery_topic_disc_id = (
f"homeassistant/sensor/floppy_player/current_disc_id/config"
)
current_disc_state_topic_disc = (
f"homeassistant/sensor/floppy_player/current_disc/state"
)
current_disc_type_state_topic_disc = (
f"homeassistant/sensor/floppy_player/current_disc_type/state"
)
current_disc_id_state_topic_disc = (
f"homeassistant/sensor/floppy_player/current_disc_id/state"
)
2024-09-19 11:00:07 +01:00
discovery_topic_status = f"homeassistant/sensor/floppy_player/status/config"
state_topic_status = f"homeassistant/sensor/floppy_player/status/state"
# Sensor 1: current_disc (a text-based sensor)
2024-09-20 12:42:06 +01:00
current_disc_config = {
2024-09-19 11:00:07 +01:00
"name": "Current Disc",
2024-09-20 12:42:06 +01:00
"state_topic": current_disc_state_topic_disc,
2024-09-19 11:00:07 +01:00
"value_template": "{{ value }}", # Textual value
"unique_id": f"{node_id}_current_disc",
"device": {
"identifiers": [node_id],
"name": "Floppy Player",
"model": "v1",
2024-09-20 14:13:21 +01:00
"manufacturer": "Karl",
},
}
current_disc_type_state_config = {
"name": "Current Disc Type",
"state_topic": current_disc_type_state_topic_disc,
"value_template": "{{ value }}", # Textual value
"unique_id": f"{node_id}_current_disc_type",
"device": {
"identifiers": [node_id],
"name": "Floppy Player",
"model": "v1",
"manufacturer": "Karl",
},
}
current_disc_id_state_config = {
"name": "Current Disc Id",
"state_topic": current_disc_id_state_topic_disc,
"value_template": "{{ value }}", # Textual value
"unique_id": f"{node_id}_current_disc_id",
"device": {
"identifiers": [node_id],
"name": "Floppy Player",
"model": "v1",
"manufacturer": "Karl",
},
2024-09-19 11:00:07 +01:00
}
# Sensor 2: status (another text-based sensor)
status_config = {
"name": "Device Status",
"state_topic": state_topic_status,
"value_template": "{{ value }}", # Textual value
"unique_id": f"{node_id}_status",
"device": {
"identifiers": [node_id],
"name": "Floppy Player",
"model": "v1",
2024-09-20 14:13:21 +01:00
"manufacturer": "Karl",
},
2024-09-19 11:00:07 +01:00
}
2024-09-20 12:42:06 +01:00
client.publish(discovery_topic_disc, json.dumps(current_disc_config), retain=True)
2024-09-20 14:13:21 +01:00
client.publish(
discovery_topic_disc_type,
json.dumps(current_disc_type_state_config),
retain=True,
)
client.publish(
discovery_topic_disc_id, json.dumps(current_disc_id_state_config), retain=True
)
2024-09-19 11:00:07 +01:00
client.publish(discovery_topic_status, json.dumps(status_config), retain=True)
2024-09-20 11:13:04 +01:00
2024-09-20 14:13:21 +01:00
def check_current_disc(client: mqtt.Client) -> dict:
"""Check the current loaded disc, disc type, and disc ID by subscribing to the retained messages on the state topics.
2024-09-20 11:13:04 +01:00
Args:
client (mqtt.Client): MQTT Client
Returns:
2024-09-20 14:13:21 +01:00
dict: A dictionary containing the current disc, disc type, and disc ID.
"""
2024-09-20 11:13:04 +01:00
def on_message(client, userdata, message):
"""Callback function to handle received MQTT messages."""
2024-09-20 14:13:21 +01:00
topic = message.topic
userdata[topic] = message.payload.decode()
# Create a dictionary to store the messages
userdata = {
"homeassistant/sensor/floppy_player/current_disc/state": None,
"homeassistant/sensor/floppy_player/current_disc_type/state": None,
"homeassistant/sensor/floppy_player/current_disc_id/state": None,
}
2024-09-20 11:13:04 +01:00
# Set the user data and the on_message callback
client.user_data_set(userdata)
client.on_message = on_message
2024-09-20 14:13:21 +01:00
# Subscribe to the topics
current_disc_state_topic_disc = (
"homeassistant/sensor/floppy_player/current_disc/state"
)
current_disc_type_state_topic_disc = (
"homeassistant/sensor/floppy_player/current_disc_type/state"
)
current_disc_id_state_topic_disc = (
"homeassistant/sensor/floppy_player/current_disc_id/state"
)
topics = [
current_disc_state_topic_disc,
current_disc_type_state_topic_disc,
current_disc_id_state_topic_disc,
]
for topic in topics:
client.subscribe(topic)
# Run the loop manually until we receive all messages or timeout
2024-09-20 11:13:04 +01:00
timeout = 5 # Timeout after 5 seconds
2024-09-20 14:13:21 +01:00
while any(value is None for value in userdata.values()) and timeout > 0:
2024-09-20 11:13:04 +01:00
client.loop(timeout=0.1) # Process network events for a short time
timeout -= 0.1
2024-09-20 14:13:21 +01:00
# Check if we received all messages
if any(value is None for value in userdata.values()):
raise TimeoutError("Some retained messages were not found.")
2024-09-20 11:13:04 +01:00
2024-09-20 14:13:21 +01:00
# Return the relevant messages
return {
"name": userdata[current_disc_state_topic_disc],
"type": userdata[current_disc_type_state_topic_disc],
"id": userdata[current_disc_id_state_topic_disc],
}
2024-09-20 11:13:04 +01:00
2024-09-20 20:46:33 +01:00
def check_current_status(client: mqtt.Client) -> str:
"""Check the current player status by subscribing to the retained message on the state topic.
Args:
client (mqtt.Client): MQTT Client
Returns:
str: Current object at current_disc/state
"""
def on_message(client, userdata, message):
"""Callback function to handle received MQTT messages."""
userdata['message'] = message.payload.decode()
# Create a dictionary to store the message
userdata = {'message': None}
# Set the user data and the on_message callback
client.user_data_set(userdata)
client.on_message = on_message
# Subscribe to the topic
client.subscribe("homeassistant/sensor/floppy_player/status/state")
# Run the loop manually until we receive a message
timeout = 5 # Timeout after 5 seconds
while userdata['message'] is None and timeout > 0:
client.loop(timeout=0.1) # Process network events for a short time
timeout -= 0.1
# Check if we received the message
if userdata['message'] is None:
raise TimeoutError("No retained message was found.")
return userdata['message']
2024-09-20 11:13:04 +01:00
def update_disc(client: mqtt.Client, disc_message: dict) -> None:
2024-09-19 11:00:07 +01:00
"""Update current disc.
Args:
2024-09-20 11:13:04 +01:00
client (mqtt.Client): MQTT Client
2024-09-19 11:00:07 +01:00
disc_message (dict): Current disc information
"""
2024-09-20 14:13:21 +01:00
client.publish(
"homeassistant/sensor/floppy_player/current_disc/state",
disc_message[1],
retain=True,
)
client.publish(
"homeassistant/sensor/floppy_player/current_disc_type/state",
disc_message[2],
retain=True,
)
client.publish(
"homeassistant/sensor/floppy_player/current_disc_id/state",
disc_message[3],
retain=True,
)
2024-09-19 11:00:07 +01:00
print(f"Published current disc: {disc_message}")
2024-09-20 14:13:21 +01:00
2024-09-20 11:13:04 +01:00
def control_player(client: mqtt.Client, state: str) -> None:
2024-09-19 11:00:07 +01:00
"""Control the player
Args:
2024-09-20 11:13:04 +01:00
client (mqtt.Client): MQTT Client
2024-09-19 11:00:07 +01:00
state (str): Player State
2024-09-20 14:13:21 +01:00
"""
client.publish(
"homeassistant/sensor/floppy_player/status/state", state, retain=True
)
2024-09-19 11:00:07 +01:00
print(f"Published status: {state}")