Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Smart Thermostat Raspberry PI - part modified remote boiler control function
def fcontroll():
"""
Main boiler controll function.
Gets current and set temperature
uses 3 run levels to controll boiler.
run level 0 = initial,
run level 1 = determine how many mintues boier shoudl be on,
run level 2 = continuesly check of boier should be on for 10 minutes
Inserts message in sendmes table.
Runs as seprate thread.
"""
runScen = 0
boilerStat = 0
setBoiler = 0
maxScen = (10*60) #maximum run for 1 hour long
scenLength = 0
cursource = '40b5af01' #divice id used for logging purposses
logging.info("time sleep 10 started")
time.sleep(10)
logging.info("time sleep 10 complete")
bvepoch = 9999999999
usettemp = -30000
prevsettemp = -30000
settemptime = -(60*60*24*5)
while True:
try:
fscurtime = time.time()
fsvepoch = int(fscurtime)
fsvsub = int(datetime.datetime.fromtimestamp(fscurtime).strftime('%f'))
fkepoch = bvepoch - fsvepoch
fsmintime = fsvepoch-5
curtemp = -30000 #lower than 0 Kelvin
settemp = -30000 #lower than 0 Kelvin
curtempepoch = -(60*60*24*5)
settempepoch = -(60*60*24*5)
outtemp = 1500 #default outside temperature
#get current actual inside temperature form sensvals table
dbd8 = dbc.cursor()
dbd8.execute("SELECT vepoch,vvalue FROM sensvals where vsource = '40b5af01' and vport='rx000A04' order by vepoch desc, vkey asc LIMIT 1")
rows = dbd8.fetchall()
for row in rows:
curtempepoch = row[0]
curtemp = row[1]
dbd8.close()
#get current set temperature form sensvals table
dbd9 = dbc.cursor()
dbd9.execute("SELECT vepoch,vvalue FROM sensvals where vsource = '40b5af01' and vport='rx000A02' order by vepoch desc, vkey asc LIMIT 1")
rows = dbd9.fetchall()
for row in rows:
settempepoch = row[0]
settemp = row[1]
dbd9.close()
#get current outside temperature form curtemp table
dbcontr1 = dbc.cursor()
dbcontr1.execute("SELECT vvalue FROM curtemp ORDER BY vkey asc LIMIT 1")
rows = dbcontr1.fetchall()
for row in rows:
outtemp = row[0]
dbcontr1.close()
#only set usettemp if settemp has not ben changed for 5 seconds
#this is prevent the temperature scenrio to be based on a slightly higher settemp instead of waiting for the final set temp
#to be set by the user
if (prevsettemp != settemp):
settemptime = fsvepoch
elif (fsvepoch - settemptime > 5 ):
usettemp = settemp
prevsettemp = settemp
#devault variables
curtemptimediff = fsvepoch-curtempepoch #check how many seconds ago last current temperature has been received
settemptimediff = fsvepoch-settempepoch #check how many seconds ago last current temperature has been received
tempdif = (usettemp*10) - curtemp
outtempdif = (usettemp*10) - outtemp
#!!include if settemp is set and the other checsk if temp is actual
if(runScen == 0): #no scenario running
runScen = frunScen(curtemp,usettemp)
elif (runScen == 1): #start scenario
usedkey = 'failed'
usedkey,runminutes = getscen(tempdif,outtempdif)
if (usedkey <> 'failed'): #only use scenarios if a valid scenario has been retrieved
scenLength = runminutes[0]
maxrun = 6
#insert used scenario and values used to determine this scenario to be uploaded to cloud server for scoring.
usscenpreky = cursource+'_'+str(fkepoch)
uscenkey = usscenpreky+'_'+ usedkey
dbdconsa5 = dbc.cursor()
dbdconsa5.execute("INSERT INTO usedscenario (vkey, vprekey, viepoch, scenariokey, vtempdif, vouttempdif, vtemp, vouttemp, vsettemp) values ('%s','%s',%i,'%s',%i,%i,%i,%i,%i)" % (uscenkey,usscenpreky,fsvepoch,usedkey,tempdif,outtempdif,curtemp,outtemp,settemp))
dbdconsa5.close()
else: #otherwise determine number of seconds boiler should be on using fscenlengh() function
scenLength = fscenLength(curtemp,usettemp)
maxrun = 1
logging.info(usedkey)
runnum = 0
startScen = int(time.time())
runScen = 2
boilerStat = 1
logging.info(str(maxrun))
logging.info(str(runnum))
logging.info(str(scenLength))
elif(runScen == 2): #run scenario
runCurtime = int(time.time())
if (boilerStat == 1 ):
boilerStat = fboilerStat(startScen,scenLength,runCurtime,curtemp,settemp)
if (boilerStat == 1 ):
setBoiler = 1 #send Arduino 1 for boilerstat
else:
setBoiler = 0 #send Arduino 0 for boilerstat
if(runCurtime - startScen > maxScen):
runScen = 3
elif(runScen == 3): #check if scenario schould go to next interval of 10 minus or complete after 60 miutes
runnum = runnum + 1
if (runnum < maxrun): #go to next iteration of 10 minutes
runScen = 2
boilerStat = 1
startScen = int(time.time())
scenLength = runminutes[runnum] #get number of minutes to be on from scenario array
logging.info(str(maxrun))
logging.info(str(runnum))
logging.info(str(scenLength))
else: #completed 60 minutes
runScen = 0
scurhour = int(datetime.datetime.fromtimestamp(fscurtime).strftime('%H'))
scurminute = int(datetime.datetime.fromtimestamp(fscurtime).strftime('%M'))
#only send message if temperature readings are current and withint normal range
if (curtemp > -30000 and curtemptimediff < 20 and settemp > -30000 and settemptimediff < 20):
vchecksum = scurhour+scurminute+setBoiler+curtemp
sendstr = str(scurhour).zfill(2) + str(scurminute).zfill(2) + str(setBoiler) + str(curtemp).zfill(4)+str(vchecksum).zfill(4)
fins(fscurtime,cursource,'rx000B01',scenLength) #for logging purposses, insert in sensvals table
fins(fscurtime,cursource,'rx000B02',boilerStat) #for logging purposses, insert in sensvals table
fins(fscurtime,cursource,'rx000B03',setBoiler) #for logging purposses, insert in sensvals table
#insert message in sendmes table
dbd10 = dbc.cursor()
dbd10.execute("INSERT INTO sendmes(vepoch, vsub, vsendmes) VALUES(?,?,?)",(fsvepoch,fsvsub,sendstr))
dbd10.close()
#delete older messages, keep messages of last 5 seconds
dbd13 = dbc.cursor()
dbd13.execute("DELETE from sendmes where vepoch < %i" % fsmintime)
dbd13.close()
except Exception:
logging.exception("fcontroll")
time.sleep(1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment