Reputation: 356
I am working on a thermostat that can be programmed to be off according to the time of day.
This is my thermostat function:
def thermostat(ac_on, acPower, temp_inside, Temp_desired):
if temp_inside > Temp_desired:
ac_on = True
if temp_inside < Temp_desired:
ac_on = False
ac_heatflow = acPower if ac_on == True else 0
return ac_heatflow, ac_on
Temp_desired
is a set integer value, and temp_inside
is the changing indoor temperature value that gets compared to Temp_desired
(right now every couple of seconds) to see if the air conditioner (A/C) will be “on,” or “off.” ac_heatflow
is the power usage when the A/C is on, and acPower
is the A/C power value assigned outside of the function.
My issue now is that I want to now add a time component to my thermostat, where the the A/C can be programmed to be off. For example, the A/C will work normally throughout the day, but from 8:00am to 10:00am it must be off, and from 3:00pm to 5:45pm it must be off, so during these intervals ac_on = False
, but outside these intervals the thermostat will revert back to the original method where it determines if the air conditioner is on/off based on the room temperature.
The aforementioned time intervals will be in seconds when used in the function, so 8:00am would be 28800, 10:00am --> 36000, 3:00pm --> 54000, 5:45pm --> 63900.
This is what I have been trying:
def thermostat(ac_on, acPower, temp_inside, Temp_desired, start, end, t):
while t >= start or t <= end:
ac_on = False
else:
if temp_inside > Temp_desired + 2:
ac_on = True
if temp_inside < Temp_desired:
ac_on = False
ac_heatflow = 400 if ac_on == True else 0
return ac_heatflow, ac_on
start
is a start time of the interval, end
is the interval end time and t
right now is in seconds. There is a calculation of temperature every couple of seconds over a 24 hour period, a full day is 86400 seconds, so start
and end
can be any value between 0 and 86400, for example, start = 1000
and end = 3000
. The issue with the above code is that there is no output, it seems as though Python is “hung” up on that initial while statement, so I have to stop the script. I also tried:
if t >= start or t <= end:
ac_on = False
else:
if temp_inside > Temp_desired + 2:
ac_on = True
if temp_inside < Temp_desired:
ac_on = False
ac_heatflow = 400 if ac_on == True else 0
return ac_heatflow, ac_on
But this sets all the values for ac_heatflow
to 0.
I am unsure how to code the function so that it can be programmed to also take into account the time of day. Maybe this is a nested loop issue, or perhaps it requires a separate function that focuses on defining the time intervals and feeds those assignments into the thermostat function.
Upvotes: 0
Views: 2568
Reputation: 2076
The key is to use pythons datetime
library. Some pointers:
ac_on
in you function so there is no need to pass it in.datetime
lib Since you are accustomed to pythons conditional assignment, we can be moe concise and pythonic with a little refactoring.
import datetime
def ithermostat(temp, ac_power, desired_temp,\
off_times={'morning':(datetime.time(8, 0), datetime.time(10, 0)),\
'afternoon':(datetime.time(15, 0), datetime.time(17, 45))}):
"""(num, num, num, dict) -> (num, bool)
Return the tuple (ac_power_usage per unit time, ac_on status) of the thermostat
The ac is turned on only when the current time is not in off times AND
the tempreture is higher than the desired tempreture
"""
off_period = False # this flag will be set when the system is in the off period
current_time = datetime.datetime.now().time()
for k, v in off_times.items():
print(v)
if v[0] <= current_time <= v[1]:
print("system in mandatory off period")
off_period = True
break
ac_on = False if off_period else temp > desired_temp
ac_power_usage = ac_power if ac_on else 0
return ac_power_usage, ac_on
A more concise more readable and more pythonic version of the same function is as follows:
def ithermostat2(temp, ac_power, desired_temp,\
off_times = {'morning':(datetime.time(8, 0), datetime.time(10, 0)),\
'afternoon':(datetime.time(15, 0), datetime.time(17, 45))}):
"""(num, num, num, dict) -> (num, bool)
Return the tuple (ac_power_usage per unit time, ac_on status) of the thermostat
The ac is turned on only when the current time is not in off times AND
the tempreture is higher than the desired tempreture
"""
current_time = datetime.datetime.now().time()
off_period = any(v[0] <= current_time <= v[1] for k, v in off_times.items()) #check if the current time is in off_times
ac_on = False if off_period else temp > desired_temp
ac_power_usage = ac_power if ac_on else 0
return ac_power_usage, ac_on
Both functions have been tested and work well.
Upvotes: 0
Reputation: 6815
The problem is with the expression t >= start or t <= end
. Firstly what are start an end? You describe in the situation two time periods, but you are only passing into the function arguments for one potential time period?
Lets assume start=100
and end =700
. If t
is before the start, say t=5
. Well t
is still less than 700, so this statement will be true. Or if t
is after the end, say t=705
, then t
is still larger than 100, so again this expression will evaluate to true (which is why ac_on
is always False). Basically no matter what the value of t
this statement will always be true. I think what you want is t >= start and t <= end
.
Although I am still slightly confused by the two time periods you have described, maybe pass in 4 arguments, start1, end1, start2 and end2, then use:
if (t >= start1 and t <= end1) or (t >= start2 and t <= end2):
Upvotes: 1