This repository has been archived by the owner on Mar 29, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstate.py
executable file
·149 lines (107 loc) · 4.24 KB
/
state.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/usr/bin/python -u
# -u to unbuffer stdout, plays nicer with supervisor
import sys
import json
import time
import os
import logging
import paho.mqtt.client as paho
import paho.mqtt.publish as publish
from subprocess import Popen, PIPE
from time import gmtime, strftime
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
datefmt='%m-%d %H:%M')
logger = logging.getLogger(os.path.basename(__file__))
logger.debug('Starting...')
""" hostname and topic of MQTT """
hostname = os.getenv('MQTT_HOST')
topic_base = os.getenv('MQTT_TOPIC')
topic_wildcard = topic_base + "#"
topic_toggle = topic_base + 'toggle'
topic_switches = topic_base + 'switches'
""" Optional username and password for MQTT """
username = os.getenv('MQTT_USERNAME', None)
password = os.getenv('MQTT_PASSWORD', None)
mqtt_options = {'hostname': hostname}
if username is not None and password is not None:
logging.debug("connected to MQTT with authentication")
mqtt_options['auth'] = {'username': username, 'password': password}
else:
logging.debug("connected to MQTT without authentication")
def on_message(client, userdata, message):
if switches is None:
logging.debug("not configured yet, ignoring request")
return False
try:
data = json.loads(message.payload)
except:
logging.debug("failed to parse json. message=%s" % message.payload)
return False
if data['action'] != "on" and data['action'] != "off":
logging.debug("action (%s) is not valid" % data['action'])
return False
name = data['switch']
action = data['action']
source = data.get('source')
if name in switches['rooms']:
logging.debug("switch=%s action=%s source=%s" %
(name, action, source))
update_state(name, action)
elif name in switches['scenes']:
logging.debug("Handling scene=%s" % name)
switch_list = switches['scenes'][name]
logger.debug("read switch list for scene=%s as: %s" % (name, switch_list))
for switch in switch_list:
logging.debug("switch=%s action=%s source=%s scene=%s" %
(switch, action, source, name))
update_state(switch, action)
else:
# if it isn't in rooms or scenes it isn't valid, so return
logging.debug("%s not found in switches or scenes" % switch_name)
return False
def on_config(client, userdata, message):
global switches
try:
logging.debug("parsing json. message=%s" % message.payload)
data = json.loads(message.payload)
except:
logging.debug("failed to parse json. message=%s" % message.payload)
return False
switches = data
logging.debug("configured correctly")
def on_connect(client, userdata, rc):
logging.debug("connected with result code=%s " % str(rc))
def update_state(switch, action):
logging.debug("Updating state with %s turned %s" % (switch, action))
switches['rooms'][switch]['state'] = action
switches['updated']['by'] = 'state.py'
time_stamp = strftime("%a %b %d %H:%M:%S %Z %Y", gmtime())
switches['updated']['at'] = time_stamp
new_config = dict()
new_config = switches
mqtt_options['retain'] = True
mqtt_options['payload'] = json.dumps(new_config)
# logger.debug("mqtt args=%s" % mqtt_options)
# logger.debug("mqtt topic=%s" % topic_switches)
publish.single(topic_switches, **mqtt_options)
if __name__ == "__main__":
# Bit hacky, making this global. But you know ;)
switches = None
mqttc = paho.Client()
mqttc.message_callback_add(topic_toggle, on_message)
mqttc.message_callback_add(topic_switches, on_config)
mqttc.on_connect = on_connect
if username is not None and password is not None:
logging.debug("connected to MQTT with authentication")
mqttc.username_pw_set(username, password)
else:
logging.debug("connected to MQTT without authentication")
try:
mqttc.connect(hostname)
except Exception as e:
logging.debug("failed to connect: %s" % e)
logging.debug("subscribing to topic: %s" % topic_wildcard)
mqttc.subscribe(topic_wildcard)
while mqttc.loop() == 0:
pass