-
Notifications
You must be signed in to change notification settings - Fork 0
/
salt-GitHub.py
316 lines (288 loc) · 12.2 KB
/
salt-GitHub.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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
#!/usr/bin/python2.7
# Salt Tank Level Program
# Last Change 4/18/2020 2130
# Added MQTT QoS and Retain
import time # Sleep Function
import RPi.GPIO as GPIO # GPIO Controls
from datetime import datetime # Now Fuction
import smtplib # Email Library
from decimal import Decimal # Convert float to Decimal
import paho.mqtt.client as mqtt # Allow publishing to MQTT Server
# sudo python2.7 -m pip install paho-mqtt
''' Use BCM GPIO references instead of physical pin numbers '''
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
''' Define Variables '''
Trigger = 8 # Set Trigger to GPIO 8 *** As Needed ***
Echo = 25 # Set Echo to GPIO 25 *** As Needed ***
Wait = 2 # Set time between pulses in seconds
Pulse = 0.00001 # Set ultrasonic pulse length in seconds
PWait = 20 # Wait time for testing
PWait = 600 # Time between readings in seconds (24*60*60) *** As desired ***
Debug = True # Print to screen if True; do not comment out
Debug = False # Do not Print to screen if False; comment out to be True
Email = False # False to not send emails; do not comment out
Email = True # True to send emails; *** comment out to be False ***
MQTT_Email = Email # Variable to send Email info to MQTT since a 'Email' variable 'sometimes' as issues
MQTT_Enable = False # False to not send MQTT; do not comment out
MQTT_Enable = True # True to send MQTT *** comment out to be False ***
MQTT_Debug = Debug # Variable to send Debug info to MQTT since a 'Debug' variable 'sometimes' as issues
Samples = 11 # Number of samples to take for average
lvTop = 3 # Top of Tank from Sensor *** Depends on your tank ***
lvBag = 4 # Level of inces of Salt per 40lb bag (4" per bag leveled) *** Depends on your tank ***
lvFull = lvTop + lvBag # Full Tank level
TopLv = 33 # Tank top level from bottom (33.3") *** Depends on your tank ***
BottomLv= 11 # Top of water level from absolute bottom (lowest measureable level) *** Depends on your tank ***
lvEmpty = TopLv-BottomLv# Water level in tank is empty from Sensor, Sensor is at 35" from bottom
Broker_IP = "10.74.1.224" # MQTT Broker IP *** IP address of your MQTT Broker ***
Broker_Port = "1883" # MQTT Broker Port *** Port of your MQTT Broker 1883 is default ***
MQTT_Wait = .01 # Pause between MQTT Topic Pulishing
MailDay = 4 # Monday = 0, Tuesday = 1, Wensday = 2, Thursday = 3, Friday = 4, Saturday = 5, Sunday = 6 *** As Desired ***
''' GMail variables '''
''' Sanatize for GitHub ''' # Sanatize for GitHub
gmail_user = '[email protected]' # Gmail account *** Insert your email *** # Sanatize for GitHub '[email protected]'
gmail_password = 'YourPassword' # Gmail Password *** Insert your password *** # Sanatize for GitHub 'YourPassword'
sent_from = gmail_user # Email Sender 'Do NOT edit'
to = ['[email protected]'] # Email Recipient *** Insert your 1st Recipient *** # Sanatize for GitHub '[email protected]'
cc = ['[email protected]'] # 2nd Email Recipient *** Insert your 2nd Recipient or comment out cc below *** # Sanatize for GitHub '[email protected]'
subject = 'Salt Tank Status' # Email Subject can be updated
body = 'Body of email' # Email Body can be updated
mail_sent = False # Allow only one email on the designated day.
''' Debug print to screen colors '''
POff = '\033[0m' # Color Effects Off
PBold = '\033[1m' # Bold
PUnderline = '\033[4m' # Underline single
PBoldOff = '\033[21m' # Bold Off
PBlinkOff = '\033[25m' # Blink Off
PBlack = '\033[90m' # Black
PRed = '\033[91m' # Red
PGreen = '\033[92m' # Green
PYellow = '\033[93m' # Yellow
PBlue = '\033[94m' # Blue
PPurple = '\033[95m' # Purple
PCyan = '\033[96m' # Cyan
PWhite = '\033[97m' # White
''' Set pins as output and input '''
GPIO.setup(Trigger, GPIO.OUT) # Trigger
GPIO.setup(Echo, GPIO.IN) # Echo
''' Set trigger to False (Low) '''
GPIO.output(Trigger, False)
''' Define functions'''
def measure():
# This function measures a distance
GPIO.output(Trigger, True)
time.sleep(Pulse)
GPIO.output(Trigger, False)
start = time.time()
while GPIO.input(Echo)==0:
start = time.time()
while GPIO.input(Echo)==1:
stop = time.time()
elapsed = stop-start
distance = Decimal(elapsed * 6744.166310046,2) - lvTop
# 34300 is speed of sound in cm/sec or 13488.332620092 in/sec
# Divide by 2 to account for sound there and echo back
# Divide by 2.54 to convert to inches from cm
# Conversion = 6751.95 in/sec or 6744.166310046
# v = 331m/s + 0.6m/s/C * T speed of sound in m/s compensated for temperature or speed = 331 + 0.6 * Temp in C
# Velocity = 331.4 + 0.6*Temperature + 0.0124*Relative_Humidity ... Temperature is in Celsius Degrees ... Relative Humidity can be measured by sensors in %age ... Velocity in m/sec
return distance
def measure_average():
# This function takes measurements and returns the average.
distance = 0 # Ensure distance zeroed out
for i in range (1, Samples, 1):
time.sleep(Wait)
distance = distance + measure()
if Debug is True:
print (Samples - i),
print "\t",
print (round(distance/i,2))
distance = distance / (Samples - 1)
return distance
def Message():
# This function sends the email
# Indents affect email formating
toAll = to + cc
if Debug is True:
# Removed cc for testing
toAll = to
try:
email_text = """\
From: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(to), subject, body)
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.ehlo()
server.login(gmail_user, gmail_password)
server.sendmail(sent_from, toAll, email_text)
server.close()
if Debug is True:
print (PCyan)
print "sent_from:\t",
print (sent_from)
print "to:\t\t",
print (to)
print "subject:\t",
print (subject)
print "body:\t\t",
print (body)
print (PPurple)
print "email_text:"
print (email_text)
print (POff)
except:
#Handle email errors without crashing
if Debug is True:
print "Email send failure"
def MQTT():
# Send to the MQTT Broker
try:
mqttc = mqtt.Client("python_pub")
mqttc.connect(Broker_IP, Broker_Port)
time.sleep(MQTT_Wait)
QoS = 0
Retain = True
# mqttc.publish(Topic, Payload, QoS, Retain)
# QoS 0=Send only, 1=Confirm, 2=send until confirmed
mqttc.publish("salt/Debugy/MQTT_Finish", 'False', QoS, Retain)
if Debug is True: print 'MQTT published MQTT_All False'
time.sleep(MQTT_Wait)
mqttc.publish("salt/Debugy/Count", '17', QoS, Retain)
if Debug is True: print 'MQTT published TopicCount'
time.sleep(MQTT_Wait)
mqttc.publish("salt/Percent", PercentFull, QoS, Retain)
if Debug is True: print 'MQTT published Percent'
time.sleep(MQTT_Wait)
mqttc.publish("salt/Level", SaltLv, QoS, Retain)
if Debug is True: print 'MQTT published Level'
time.sleep(MQTT_Wait)
mqttc.publish("salt/Bags", Bags, QoS, Retain)
if Debug is True: print 'MQTT published Bags'
time.sleep(MQTT_Wait)
mqttc.publish("salt/Email/Emails", MQTT_Email, QoS, Retain)
if Debug is True: print 'MQTT published Emails'
time.sleep(MQTT_Wait)
mqttc.publish("salt/Time", ETime, QoS, Retain)
if Debug is True: print 'MQTT published Time'
time.sleep(MQTT_Wait)
mqttc.publish("salt/Debugy/DebugEnabled", MQTT_Debug, QoS, Retain)
if Debug is True: print 'MQTT published Debug'
time.sleep(MQTT_Wait)
mqttc.publish("salt/Email/MailDay", MailDay, QoS, Retain)
if Debug is True: print 'MQTT published MailDay'
time.sleep(MQTT_Wait)
mqttc.publish("salt/Email/MailDayInfo", 'Monday = 0, Tuesday = 1, Wensday = 2, Thursday = 3, Friday = 4, Saturday = 5, Sunday = 6', QoS, Retain)
if Debug is True: print 'MQTT published MailDayInfo'
time.sleep(MQTT_Wait)
mqttc.publish("salt/Constant/Samples", Samples, QoS, Retain)
if Debug is True: print 'MQTT published Samples'
time.sleep(MQTT_Wait)
mqttc.publish("salt/Constant/lvTop", lvTop, QoS, Retain)
if Debug is True: print 'MQTT published lvTop'
time.sleep(MQTT_Wait)
mqttc.publish("salt/Constant/lvBag", lvBag, QoS, Retain)
if Debug is True: print 'MQTT published lvBag'
time.sleep(MQTT_Wait)
mqttc.publish("salt/Constant/lvFull", lvFull, QoS, Retain)
if Debug is True: print 'MQTT published lvFull'
time.sleep(MQTT_Wait)
mqttc.publish("salt/Constant/TopLv", TopLv, QoS, Retain)
if Debug is True: print 'MQTT published TopLv'
time.sleep(MQTT_Wait)
mqttc.publish("salt/Constant/BottomLv", BottomLv, QoS, Retain)
if Debug is True: print 'MQTT published BottomLv'
time.sleep(MQTT_Wait)
mqttc.publish("salt/Constant/lvEmpty", lvEmpty, QoS, Retain)
if Debug is True: print 'MQTT published lvEmpty'
time.sleep(MQTT_Wait)
mqttc.publish("salt/Debugy/MQTT_Finish", 'True', QoS, Retain)
if Debug is True: print 'MQTT published MQTT_All True'
if Debug is True: print "All MQTT updated"
except:
# Prevent crashing if Broker is disconnected
if Debug is True:
print "MQTT Failed"
''' Main Script '''
''' Wrap main content in a try block so we can catch the user pressing CTRL-C and run the GPIO cleanup function. '''
''' This will also prevent the user seeing lots of unnecessary error messages. '''
try:
if Debug is True:
now = datetime.now()
current_time = "Starting Salt Tank Measurement at: " + str(now.strftime("%H:%M:%S"))
print (PRed)
print (current_time)
print ("Debug is On")
if Email is True:
print ("Email will be sent")
else:
print ("Email will NOT be sent")
Temp = (Samples*Wait)
print (str(Temp)) + " seconds per Average; ",
print (str(Samples-1)) + " Samples per Average"
print (str(PWait)) + " second(s) or " + str(PWait/60) + " minute(s) or " + str(PWait/60/60) + " hour(s); between Reading"
print "Inches to max possible salt level from sensor: " + str(lvTop)
print "Inches of salt per 40lb bag: " + str(lvBag)
print "Inches from sensor considered full of salt: " + str(lvFull)
print "Inches from sensor considered empty of salt: " + str(lvEmpty)
print (POff)
while True:
distance = measure_average()
Dist = str(round(distance,2))
Bags = str(round((distance-lvTop)/lvBag,1))
#PercentFull = str(int((TopLv - lvTop - distance)/(TopLv-lvTop)*100))
PercentFull = str(round((lvEmpty - distance + lvTop)/(lvEmpty)*100,1))
SaltLv = str(round(TopLv - distance,2))
now = datetime.now()
ETime = str(now.strftime("%H:%M:%S on %m-%d-%Y"))
if MQTT_Enable is True:
MQTT()
if Debug is True:
print (PYellow)
#now = datetime.now()
Dist_Time = "Average Distance = " + Dist + " at " + ETime
print (Dist_Time),
print " / " + Bags + " bags of salt needed. / ",
print (PercentFull),
print "% Full / Salt Level is ",
print (SaltLv),
print "inces."
print (POff)
if distance <= lvFull:
subject = 'Salt Tank is FULL'
body = "Tank Full at " + PercentFull + "%, " + SaltLv + " inches of Salt, " + Dist + " inches from top " + ETime
elif distance >= lvEmpty:
subject = 'Salt Tank is EMPTY'
body = "Tank Empty at " + PercentFull + "%, " + SaltLv + " inches of Salt, " + Dist + " inches from top, " + Bags + " Bags of Salt to Fill " + ETime
else:
subject = 'Salt Tank Status'
body = "Tank Level is " + PercentFull + "%, " + SaltLv + " inches of Salt, " + Dist + " inches from top, " + Bags + " Bags of Salt to Fill " + ETime
if Email is True:
today = datetime.today()
Weekday = today.weekday()
if Debug is True:
# Send Email during Debug regardless of day or send schedule
print "Current day of week is " + str(Weekday)
print "Monday = 0, Tuesday = 1, Wensday = 2, Thursday = 3, Friday = 4, Saturday = 5, Sunday = 6"
Message()
else:
if distance >= lvEmpty and mail_sent is False:
# Send email if empty regardless of day of week
subject = 'Salt Tank is EMPTY'
body = "Tank Empty at " + PercentFull + "%, " + SaltLv + " inches of Salt, " + Dist + " inches from top, " + Bags + " Bags of Salt to Fill " + ETime
Message()
mail_sent = True # Allow only one empty level email vice one every read cycle
else:
if Weekday == MailDay and mail_sent is False:
# Send email for tank status
subject = 'Salt Tank Status'
body = "Tank Level is " + PercentFull + "%, " + SaltLv + " inches of Salt, " + Dist + " inches from top, " + Bags + " Bags of Salt to Fill " + ETime
Message()
mail_sent = True # Allow only this email on sending day
if Weekday <> MailDay:
mail_sent = False # Reset to allow email next time
time.sleep(PWait) # Sleep between readings
except KeyboardInterrupt:
''' User pressed CTRL-C / Reset GPIO settings '''
GPIO.cleanup()