Files
bt-mqtt-gateway/workers/mpd.py
T
2020-07-09 21:11:52 +02:00

130 lines
5.9 KiB
Python

from mqtt import MqttMessage, MqttConfigMessage
from workers.base import BaseWorker
import logger
import subprocess
import traceback
REQUIREMENTS = []
_LOGGER = logger.get(__name__)
class MpdWorker(BaseWorker):
def mqttHomieDevice(self, name, nodes):
return [
MqttConfigMessage(self.format_topic(), "$state", payload="ready"),
MqttConfigMessage(self.format_topic(), "$homie", payload="3.0"),
MqttConfigMessage(self.format_topic(), "$name", payload=name),
MqttConfigMessage(self.format_topic(), "$nodes", payload=nodes)
]
def mqttHomieNode(self, label, name, properties):
return [
MqttConfigMessage(self.format_topic(label), "$name", payload=name),
MqttConfigMessage(self.format_topic(label), "$properties", payload=properties),
]
def mqttHomieProperty(self, node, prop, name, dtype, settable = False, retained = False, unit = None, dformat = None):
retval = [
MqttConfigMessage(self.format_topic(node, prop), "$name", payload=name),
MqttConfigMessage(self.format_topic(node, prop), "$datatype", payload=dtype),
MqttConfigMessage(self.format_topic(node, prop), "$settable", payload="true" if settable else "false"),
MqttConfigMessage(self.format_topic(node, prop), "$retained", payload="true" if retained else "false")
]
if unit is not None:
retval.append(MqttConfigMessage(self.format_topic(node, prop), "$unit", payload=unit))
if dformat is not None:
retval.append(MqttConfigMessage(self.format_topic(node, prop), "$format", payload=dformat))
return retval
def _setup(self):
if not hasattr(self, 'mpc_path'):
self.mpc_path = '/usr/bin/mpc'
def config(self):
_LOGGER.debug("Configuring")
retval = self.mqttHomieDevice("Media Player Daemon (MyRoom)", "controls")
retval += self.mqttHomieNode("controls", "Player Controls", "volume,control,play,playlist,current")
retval += self.mqttHomieProperty("controls", "volume", "Volume", "integer", True, True, "%", "0:100")
retval += self.mqttHomieProperty("controls", "control", "Media Control", "enum", True, True, dformat = "play,pause,stop")
retval += self.mqttHomieProperty("controls", "play", "Play Button", "boolean", True, True)
retval += self.mqttHomieProperty("controls", "playlist", "Playlist", "string", True, True)
retval += self.mqttHomieProperty("controls", "current", "Currently Playing", "string", False, False)
return retval
def status_update(self):
retval = []
try:
retval.append(MqttMessage(topic=self.format_topic("controls", "current"), payload=self.mpc_get_current(), retain=True))
except Exception as e:
_LOGGER.error("Caught exception in MpdWorker.on_command(): {}".format(e))
traceback.print_exc();
return retval
def on_command(self, topic, value):
retval = []
try:
value = value.decode('utf-8')
_, nodename, propname, operation = topic.split('/')
_LOGGER.debug("Command \"%s\", on %s.%s: %s", operation, nodename, propname, value)
if propname == "volume" and operation == "set":
if self.mpc_set_volume(value):
retval.append(MqttMessage(topic=self.format_topic("controls", "volume"), payload=value, retain=True))
elif propname == "control" and operation == "set":
if (value == "play" or value == "PLAY") and self.call_mpc(["play"]) == 0:
retval.append(MqttMessage(topic=self.format_topic("controls", "control"), payload=value, retain=True))
elif (value == "pause" or value == "PAUSE") and self.call_mpc(["pause"]) == 0:
retval.append(MqttMessage(topic=self.format_topic("controls", "control"), payload=value, retain=True))
elif (value == "stop" or value == "STOP") and self.call_mpc(["stop"]) == 0:
retval.append(MqttMessage(topic=self.format_topic("controls", "control"), payload=value, retain=True))
elif propname == "play" and operation == "set":
if (value == "true" or value == "on") and self.call_mpc(["play"]) == 0:
retval.append(MqttMessage(topic=self.format_topic("controls", "play"), payload="true", retain=True))
elif (value == "false" or value == "off") and self.call_mpc(["stop"]) == 0:
retval.append(MqttMessage(topic=self.format_topic("controls", "play"), payload="false", retain=True))
elif propname == "playlist" and operation == "set":
if self.mpc_set_playlist(value):
retval.append(MqttMessage(topic=self.format_topic("controls", "playlist"), payload=value, retain=True))
retval.append(MqttMessage(topic=self.format_topic("controls", "current"), payload=self.mpc_get_current(), retain=True))
except Exception as e:
_LOGGER.error("Caught exception in MpdWorker.on_command(): {}".format(e))
traceback.print_exc();
return retval
def run_mpc(self, args):
args = [self.mpc_path] + args
result = subprocess.run(args, stdout=subprocess.PIPE)
_LOGGER.debug("run_mpc: %s -> %s", str(args), str(result))
return (result.returncode, result.stdout)
def call_mpc(self, args):
args = [self.mpc_path] + args
_LOGGER.debug("call_mpc: %s", str(args))
return subprocess.call(args)
def mpc_set_volume(self, volume):
return self.call_mpc(["volume", str(volume)]) == 0
def mpc_set_playlist(self, pl):
return self.call_mpc(["load", str(pl)]) == 0
def mpc_get_current(self):
retcode, out = self.run_mpc(["current"])
if retcode == 0:
return out
else:
return ""