-
Notifications
You must be signed in to change notification settings - Fork 3
/
driver.py
245 lines (201 loc) · 8.86 KB
/
driver.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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
##############################################################################################################
## AutoHome is a system that enables you to control any device at home using a Raspberry Pi, and AdafruitIO.##
## You can also integrate IFTTT with AdafruitIO so you can control everything using Google Assistant. ##
## You can find the project with README at github.com/rirozizo/AutoHome ##
##############################################################################################################
# Importing needed libraries
import sys, os
from Adafruit_IO import MQTTClient
import RPi.GPIO as GPIO
import paho.mqtt.client as mqtt
# Library for time and sleep, might need later
#from time import sleep
# Dummy relay pin number (GPIO number and NOT physical pins)
ac_relay_pin = 26
GPIO.setmode(GPIO.BCM)
# Set GPIO pin to OUT
GPIO.setup(ac_relay_pin, GPIO.OUT)
# Give HIGH
#GPIO.output(ac_relay_pin, 1)
# Give LOW
#GPIO.output(ac_relay_pin, 0)
# Sleep for 5 seconds
#sleep(5)
# Set to your Adafruit IO key.
# Remember, your key is a secret,
# so make sure not to publish it when you publish this code!
# I used a separate file to read the key from. This is done so that we don't expose the key in the code itself, but a separatefile
f=open("/home/pi/autohome/aiokey.txt", "r")
contents =f.read()
contents = contents.strip()
#print(contents)
ADAFRUIT_IO_KEY = contents
# Set to your Adafruit IO username.
# (go to https://accounts.adafruit.com to find your username)
ADAFRUIT_IO_USERNAME = 'rirozizo'
# Set the IDs of the feeds to subscribe to for updates.
MASTER_FEED_ID = 'master'
AC_FEED_ID = 'ac'
AC_STATUS_FEED_ID = 'ac-status'
SERVICE_STATUS_FEED_ID = 'service-status'
TASMOTA1_FEED_ID = 'tasmota1'
TASMOTA2_FEED_ID = 'tasmota2'
TASMOTA1_STATUS_FEED_ID = 'tasmota1-status'
TASMOTA2_STATUS_FEED_ID = 'tasmota2-status'
TASMOTA_LAST_WILL_ID = 'will'
# Set the statuses of global variables
# This is to keep track of the Master switch so we can disable the control of everything in one switch
MASTER_DATA = 'OFF'
# This is to keep track of the last (old) value of the Master switch, so that we can apply the current feeds' data when we switch Master back on
OLD_MASTER_DATA = 'OFF'
##########################################
## ADAFRUIT ##
##########################################
# Define callback functions which will be called when certain events happen.
def connected(client):
# Connected function will be called when the client is connected to Adafruit IO.
# This is a good place to subscribe to feed changes. The client parameter
# passed to this function is the Adafruit IO MQTT client so you can make
# calls against it easily.
print('Connected to Adafruit IO! Listening for {0} changes...'.format(AC_FEED_ID))
# Subscribe to changes on the feed.
client.subscribe(AC_FEED_ID)
client.subscribe(MASTER_FEED_ID)
client.subscribe(TASMOTA1_FEED_ID)
client.subscribe(TASMOTA2_FEED_ID)
# Get existing value from feed so we match the current user input
client.receive(MASTER_FEED_ID)
# Set the AdaFruitIO Service Status Indicator to ON
client.publish(SERVICE_STATUS_FEED_ID, "ON")
# client.publish("rirozizo/feeds/will", "in")
def disconnected(client):
# Disconnected function will be called when the client disconnects.
print('Disconnected from Adafruit IO!')
sys.exit(1)
##############################################################################################################################
def message(client, feed_id, payload):
# Message function will be called when a subscribed feed has a new value.
# The feed_id parameter identifies the feed, and the payload parameter has
# the new value.
print('Feed {0} received new value: {1}'.format(feed_id, payload))
# I'm a noob, this took a while to figure out, always add "global" before a variable if you intend on changing it
global MASTER_DATA
global OLD_MASER_DATA
global MASTER_FEED_ID
# If we modify the Master switch
if feed_id == MASTER_FEED_ID:
OLD_MASER_DATA = MASTER_DATA
MASTER_DATA = payload
# If master is On, get the latest AC Feed data
if MASTER_DATA == "ON":
client.receive(AC_FEED_ID)
client.receive(TASMOTA1_FEED_ID)
client.receive(TASMOTA2_FEED_ID)
##########################################
#Do the next action if the payload is ON:#
##########################################
# If the received feed id is the one that belongs to the AC control, and the payload is ON
if MASTER_DATA == "ON" and feed_id == AC_FEED_ID and payload == "ON":
print('Turning AC ON')
ac_control("ON")
###########################################
#Do the next action if the payload is OFF:#
###########################################
# If the received feed id is the one that belongs to the AC control, and the payload is OFF
if MASTER_DATA == "ON" and feed_id == AC_FEED_ID and payload == "OFF":
print('Turning AC OFF')
ac_control("OFF")
# Tasmota control
if MASTER_DATA == "ON" and feed_id == TASMOTA1_FEED_ID and payload == "ON":
print('Turning Tasmota Relay 1 ON')
tasmota_control(1, "ON")
if MASTER_DATA == "ON" and feed_id == TASMOTA1_FEED_ID and payload == "OFF":
print('Turning Tasmota Relay 1 OFF')
tasmota_control(1, "OFF")
if MASTER_DATA == "ON" and feed_id == TASMOTA2_FEED_ID and payload == "ON":
print('Turning Tasmota Relay 2 ON')
tasmota_control(2, "ON")
if MASTER_DATA == "ON" and feed_id == TASMOTA2_FEED_ID and payload == "OFF":
print('Turning Tasmota Relay 2 OFF')
tasmota_control(2, "OFF")
# If the Master switch is off, we don't do anything
elif MASTER_DATA == "OFF":
print('Master seems to be OFF, not doing anything')
##############################################################################################################################
def ac_control(control):
if control == "ON":
# Let AdaFruitIO know of the current status now
print('Setting AC\'s status to ON')
client.publish(AC_STATUS_FEED_ID, "ON")
# The relay that I happen to use it an "Active-Low" relay, so I used an NPN Transistor to fix its odd behaviour
GPIO.output(ac_relay_pin, 1)
if control == "OFF":
print('Setting AC\'s status to OFF')
# Let AdaFruitIO know of the current status now
client.publish(AC_STATUS_FEED_ID, "OFF")
GPIO.output(ac_relay_pin, 0)
def tasmota_control(relay, control):
if relay == 1 and control == "ON":
pass
os.popen('mosquitto_pub -t tasmota/cmnd/power1 -m ON').read()
client.publish(TASMOTA1_STATUS_FEED_ID, "ON")
if relay == 1 and control == "OFF":
pass
os.popen('mosquitto_pub -t tasmota/cmnd/power1 -m OFF').read()
client.publish(TASMOTA1_STATUS_FEED_ID, "OFF")
if relay == 2 and control == "ON":
pass
os.popen('mosquitto_pub -t tasmota/cmnd/power2 -m ON').read()
client.publish(TASMOTA2_STATUS_FEED_ID, "ON")
if relay == 2 and control == "OFF":
pass
os.popen('mosquitto_pub -t tasmota/cmnd/power2 -m OFF').read()
client.publish(TASMOTA2_STATUS_FEED_ID, "OFF")
##############################################################################################################################
# Create an MQTT client instance.
client = MQTTClient(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY)
# Setup the callback functions defined above.
client.on_connect = connected
client.on_disconnect = disconnected
client.on_message = message
# Connect to the Adafruit IO server.
#client.will("rirozizo/feeds/will", "out")
client.connect()
##########################################
## TASMOTA ##
##########################################
def on_connect(mqttclient, userdata, flags, rc):
print("Connected with result code "+str(rc))
#On Tasmota's side we set the Topic to "tasmota" and the Full Topic to "%topic%/"
#Tasmota's Last Will and Testament becomes "tasmota/LWT", this is how we monitor if the SONOFF Device is on or not
mqttclient.subscribe("tasmota/LWT")
def on_message(mqttclient, userdata, msg):
#If the SONOFF sends a signal that it's Online
if msg.payload.decode() == "Online":
print("Tasmota is Online!")
client.publish(TASMOTA_LAST_WILL_ID, "ON")
#If the SONOFF goes offline, we receive its LWT Message
if msg.payload.decode() == "Offline":
print("Tasmota is Offline!")
client.publish(TASMOTA_LAST_WILL_ID, "OFF")
mqttclient = mqtt.Client()
mqttclient.connect('localhost',1883,5)
mqttclient.on_connect = on_connect
mqttclient.on_message = on_message
mqttclient.loop_start()
# Start a message loop that blocks forever waiting for MQTT messages to be
# received. Note there are other options for running the event loop like doing
# so in a background thread--see the mqtt_client.py example to learn more.
try:
##########################################
## ADAFRUIT ##
##########################################
client.loop_blocking()
except:
# Set the AdaFruitIO Service Status Indicator to OFF
client.publish(SERVICE_STATUS_FEED_ID, "OFF")
print('\nExited Successfully \n')
# Kill MQTT Client Background Process
mqttclient.loop_stop()
# Cleanup GPIO before exiting
GPIO.cleanup()