Thank you for your donation!


Cloudsmith graciously provides open-source package management and distribution for our project.


MQTT support
#11
(03-13-2020, 09:53 AM)NishaChavan Wrote: Great Information was very useful for me. Thank you for sharing this information.

I've added some more, but it's a bit rough at the moment and needs more testing.

Added ability to send alerts
Added ability to send timers (aka kitchen timer)
Added skip and ffwd commands ( > >>)


So long as all hostnames are different, added ability to listen for:
moode/hostname or
moode/all (which sends commands to every player subscribed to moode/#)

Also in current state without installing additional software to moode, timer and alert can only work with wav files

Timer function needs work and currently only accepts minutes so the example is like: timer 60 /home/pi/timer.wav

Code:
#!/usr/bin/env python

'''

Getting Started
---------------
1.edit settings section of this script using your mqtt broker settings
2.copy to /home/pi folder
3.create a systemd service to auto start at boot
4.reboot
5.test

Basic Commands
--------------
volume up 10
volume dn 10
volume 25
mute
stop
pause
toggle
status
stream http://stream.radioparadise.com/mp3-320
alert /home/pi/doorbell.wav
timer 60 /home/pi/timer.wav
reboot

Advanced Commands
-----------------
Any valid mpc command in the format of:
mpc command

'''

# settings
mqttHost = "192.168.1.5"
mqttPort = 1883
mqttKeep = 60 #keep alive seconds
mqttUser = "test"
mqttPass = "password"
topicVal = "moode"
alertVol = "75%"
fastForw = 30 #fast forward seconds


# don't change anything below unless you know what you are doing ;-)
import paho.mqtt.client as mqtt
import subprocess

ip = subprocess.check_output("hostname -I", shell=True).strip()
host = subprocess.check_output("hostname", shell=True).strip()

subTopic = topicVal + "/#"
pubTopic = topicVal + "/" + host + "/status"

def on_connect(client, userdata, flags, rc):
   print("Connected with result code "+str(rc))
   client.subscribe(subTopic)
   client.publish(pubTopic, "Online", qos=0, retain=True)
   volume = subprocess.check_output("/var/www/vol.sh", shell=True).strip()
   client.publish(pubTopic + "/ip", ip, qos=0, retain=True)
   client.publish(pubTopic + "/hostname", host, qos=0, retain=True)
   client.publish(pubTopic + "/volume", volume, qos=0, retain=True)
   #TODO add log error

def on_message(client, userdata, msg):
   topic = msg.topic.decode("utf-8")
   if (topic == topicVal + "/" + host) or (topic == topicVal + "/all"):
       action = msg.payload.decode("utf-8")
       if action.startswith("volume"):
           vol = action.replace("volume ", "")
           subprocess.check_output("/var/www/vol.sh " + vol, shell=True)
           vol = subprocess.check_output("/var/www/vol.sh", shell=True).strip()
           client.publish(pubTopic + "/volume" , vol, qos=0, retain=True)
       elif action.startswith("mpc"):
           subprocess.check_output(action, shell=True)
       elif action == "mute":
           subprocess.check_output("/var/www/vol.sh mute", shell=True)
           client.publish(pubTopic + "/volume" , "Muted", qos=0, retain=False)
       elif action == "stop":
           subprocess.check_output("mpc stop", shell=True)
       elif action == "pause" or action == "toggle":
           subprocess.check_output("mpc toggle", shell=True)
       elif action == "status":
           #import imp
           #f = open("/var/local/www/currentsong.txt")
           #global data
           #data = imp.load_source('data', '', f)
           #f.close()
           status = subprocess.check_output("mpc status", shell=True)
           #status2 = subprocess.check_output("mpc status", shell=True)
           client.publish(pubTopic + "/mpc-status" , status, qos=0, retain=True)
           #client.publish(pubTopic + "/other-status" , status2, qos=0, retain=True)
           #client.publish(pubTopic + "/more-status" , data, qos=0, retain=True)
           vol = subprocess.check_output("/var/www/vol.sh", shell=True).strip()
           client.publish(pubTopic + "/volume" , vol, qos=0, retain=True)
       elif action == "sync":
           pass
       elif action.startswith("stream"):
           url = action.replace("stream ", "")
           subprocess.check_output("mpc clear && mpc add " + url + " && mpc play", shell=True)
       elif action.startswith("alert"):
           url = action.replace("alert ", "")
           status = subprocess.check_output("mpc status", shell=True)
           if "[playing]" in status:
               subprocess.check_output("mpc toggle && amixer set Digital " + alertVol, shell=True)
               subprocess.check_output("aplay " + url, shell=True)
               subprocess.check_output("amixer set Digital 100% && mpc toggle", shell=True)
           else:
               subprocess.check_output("amixer set Digital " + alertVol, shell=True)
               subprocess.check_output("aplay " + url, shell=True)
               subprocess.check_output("amixer set Digital 100%", shell=True)
       elif action == "reboot":
           subprocess.check_output("mpc stop && sudo systemctl stop nginx && sudo reboot", shell=True)
       elif action == ">":
           subprocess.check_output("mpc seek +" + fastFwd, shell=True)
       elif action == ">>":
           subprocess.check_output("mpc next", shell=True)
       elif action.startswith("timer"):
           cmd = action.replace("timer ", "")
           out = subprocess.check_output("/home/pi/timer.py " + cmd, shell=True)
           client.publish(pubTopic + "/timer" , out, qos=0, retain=True)
       else:
           try:
               float(action)
               subprocess.check_output("/var/www/vol.sh " + action, shell=True)
               vol = subprocess.check_output("/var/www/vol.sh", shell=True).strip()
               client.publish(pubTopic + "/volume" , vol, qos=0, retain=True)
           except ValueError:
               print("Error")
           # do nothing - command in payload not defined
 #          pass
   else:
       # do nothing - the message was not for me
       pass

def on_publish(client, userdata, mid):
   print("mid: " + str(mid))

def on_subscribe(client, userdata, mid, granted_qos):
   print("Subscribed: " + str(mid) + " " + str(granted_qos))

def on_log(client, userdata, level, buf):
   print(buf)


client = mqtt.Client()
client.username_pw_set(mqttUser,mqttPass)
# last will
client.will_set(pubTopic, "Offline", qos=0, retain=True)
# event callbacks
client.on_message = on_message
client.on_connect = on_connect
client.on_publish = on_publish
client.on_subscribe = on_subscribe
# connect
client.connect(mqttHost,mqttPort,mqttKeep)
# keep listening for messages
client.loop_forever()

timer.py (also located in home/pi folder)

Code:
#!/usr/bin/env python1

import subprocess      
import time
import sys
from os.path import expanduser

timerVol = "75%"

total = len(sys.argv)

status = subprocess.check_output("mpc status", shell=True)

if (total == 2):
   wavfil = expanduser("~") + "/timer.wav"
else:
   wavfil = expanduser("~") + "/" + str(sys.argv[2])

timer  = (float(sys.argv[1]) * 60)

time.sleep(timer)

#subprocess.check_output("aplay " + wavfil, shell=True)
status = subprocess.check_output("mpc status", shell=True)


Please remember. I'm not a programmer but have a need ;-)
Reply
#12
Forgot to mention that if you send a message with a number from 0 to 100, will also change volume without needing the "volume" part of the message.
Reply
#13
Thumbs Up 
Thanks for sharing! Had to make the following adjustments to make it work:

Line 51
host = subprocess.check_output("hostname", shell=True).strip()

to
host = subprocess.check_output("hostname", shell=True).strip().decode("utf-8")

and


Line 69
action = msg.payload.decode("utf-8")
to
action = msg.payload
Reply


Forum Jump: