-
Notifications
You must be signed in to change notification settings - Fork 0
/
esp_check_mqtt3.py
executable file
·135 lines (107 loc) · 4.64 KB
/
esp_check_mqtt3.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!bin/python
'''
This is a python 3.x script that is usually run on a raspberry pi
and is connected to sonos so it can issue sonos commands like changing
the volume and pausing the music
This script subscribes to mqtt messages that are generated by
devices like the esp32-based m5stack and its sonos_remote_m5stack.py script
Those mqtt messages are sent to the mqtt broker running on ec2 box and this script subscribes
to that topic, which is sonos/{location}
'''
import os
from time import sleep
import json
import sys
home = os.path.split(os.getcwd())[0]
sys.path = [os.path.join(home, 'SoCo')] + sys.path
import soco
from soco import config as soco_config
import paho.mqtt.client as mqtt
from config import aws_mqtt_uri, location
soco_config.CACHE_ENABLED = False
n = 0
while 1:
n+=1
print("attempt "+str(n))
try:
sp = soco.discover(timeout=2)
speakers = {s.player_name:s for s in sp}
except TypeError as e:
print(e)
sleep(1)
else:
break
for s in sp:
print("{} -- coordinator:{}".format(s.player_name.encode('ascii', 'ignore'), s.group.coordinator.player_name.encode('ascii', 'ignore')))
master_name = input("Which speaker do you want to be master? ")
master = speakers.get(master_name)
if master:
print("Master speaker is: {}".format(master.player_name))
sp = [s for s in sp if s.group.coordinator is master]
print("Master group:")
for s in sp:
print("{} -- coordinator:{}".format(s.player_name.encode('ascii', 'ignore'), s.group.coordinator.player_name.encode('ascii', 'ignore')))
else:
print("Somehow you didn't pick a master or spell it correctly (case matters)")
sys.exit(1)
meta_format_radio = '''<DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:r="urn:schemas-rinconnetworks-com:metadata-1-0/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"><item id="-1" parentID="-1" restricted="true"><dc:title>{title}</dc:title><upnp:class>object.item.audioItem.audioBroadcast</upnp:class><desc id="cdudn" nameSpace="urn:schemas-rinconnetworks-com:metadata-1-0/">{service}</desc></item></DIDL-Lite>'''
station = ["WNYC-FM", "x-sonosapi-stream:s21606?sid=254&flags=32", "SA_RINCON65031_"]
uri = station[1]
uri = uri.replace('&', '&') # need to escape '&' in radio URIs
meta = meta_format_radio.format(title=station[0], service=station[2])
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
# Subscribing in on_connect() means that if we lose the connection and
# reconnect then subscriptions will be renewed.
# client.subscribe("$SYS/#")
client.subscribe('sonos/'+location)
# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.payload))
body = msg.payload
print("mqtt messge body =", body)
try:
task = json.loads(body)
except Exception as e:
print("error reading the mqtt message body: ", e)
return
action = task.get('action', '')
if action == 'play_pause':
try:
state = master.get_current_transport_info()['current_transport_state']
except Exception as e:
print("Encountered error in state = master.get_current_transport_info(): ", e)
state = 'ERROR'
# check if sonos is playing music
if state == 'PLAYING':
master.pause()
elif state!='ERROR':
master.play()
elif action in ('quieter','louder'):
for s in sp:
s.volume = s.volume - 10 if action=='quieter' else s.volume + 10
print("I tried to make the volume "+action)
elif action == "volume": #{"action":"volume", "level":70}
level = task.get("level", 500)
level = int(round(level/10, -1))
if level < 70:
for s in sp:
s.volume = level
print("I changed the volume to:", level)
else:
print("Volume was too high:", level)
elif action == "play_wnyc":
master.play_uri(uri, meta, station[0]) # station[0] is the title of the station
elif action == "play_queue":
queue = master.get_queue()
if len(queue) != 0:
master.stop()
master.play_from_queue(0)
else:
print("I have no idea what you said")
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(aws_mqtt_uri, 1883, 60)
client.loop_forever()
# could also call while 1: client.loop() sleep(1) so could do other things in loop. Not sure what timeout should be set to if we call loop "manually"