def inside_temperature(self, cfg): if cfg['Server']: c = get_client(agent='172.17.0.1:28589', entity="thanos.ent") else: c = get_client() archiver = DataClient(c) uuids = [cfg['UUIDS']['thermostat_temperature']] temp_now = self.current_time start = '"' + temp_now.strftime('%Y-%m-%d %H:%M:%S') + ' PST"' end = '"' + (temp_now - datetime.timedelta(minutes=10) ).strftime('%Y-%m-%d %H:%M:%S') + ' PST"' dfs = make_dataframe( archiver.window_uuids(uuids, end, start, '1min', timeout=120)) for uid, df in dfs.items(): if uid == uuids[0]: if 'mean' in df.columns: df = df[['mean']] df.columns = ['tin'] dfs[uid] = df.resample('1min').mean() uid, df = dfs.items()[0] df['tin'] = df['tin'].replace(to_replace=0, method='pad') return df['tin']
def get_occupancy(self, start='"2017-09-01 00:00:00 MST"', end='"2017-09-12 00:00:00 MST"', time_steps="15T"): """Returns a dictionary {Zone: occupancy_data} where the occupancy data is a pandas dataframe, where each column represents a sensor. It is indexed as timeseries data with time_steps as given. It has all the data in the range of times start to end as given. Note, the data is given in MST time as that is how it stores. We will convert it in the function to PST. Parameters: start: When should the data start. Has to be a string of a string '"Time"'. end: when should the data end. Has to be a string of a string '"Time"'. time_steps: in what intervals (start, start+time+steps) do we want to look at data. If a sensor regiester someone in those 15minutes, then we will treat the whole 15 minute as being occupied. (Is this a valid assumption?) Returns: A dataframe. Only returns the data for whole days. Will truncate edge days if needed. IMPROVEMENT TO ME: maybe make it such that we don't have to store the data in a different cell. such that we only ever have to make a call to this function, and it will somehow store the already pulled function, such that it doesn't have to pull it over and over again. """ # define a Brick query to get the occupancy information q = """SELECT ?zone ?sensor_uuid WHERE { ?zone rdf:type brick:HVAC_Zone . ?zone bf:hasPart ?room . ?sensor bf:isLocatedIn ?room . ?sensor rdf:type/rdfs:subClassOf* brick:Occupancy_Sensor . ?sensor bf:uuid ?sensor_uuid . }; """ result = self.hod.do_query(q)['Rows'] occupancy_sensors = defaultdict(list) for sensor in result: occupancy_sensors[sensor['?zone']].append(sensor['?sensor_uuid']) zone_sensor_df = defaultdict() for zone, sensor_uuid in occupancy_sensors.items(): occupancy_data = make_dataframe(self.archiver.data_uuids(sensor_uuid, start, end, timeout=300)) occupancy_df = merge_dfs(occupancy_data, resample=time_steps, do_max=True) idx = occupancy_df.index idx = idx.tz_localize(pytz.utc).tz_convert(tz) occupancy_df.index = idx #The following will make sure that we only have whole days in the returned DF. Only because of timezones. # Need to truncate ends since we don't have more data. if occupancy_df.index[0].time() > pd.Timestamp("00:00:00").time(): temp = occupancy_df.index[0] d_temp = pd.Timestamp(temp + pd.Timedelta("1 days")) d_temp = d_temp.replace(hour=0,minute=0,second=0) occupancy_df = occupancy_df.loc[d_temp:] if occupancy_df.index[-1].time() < pd.Timestamp("23:45:00").time(): temp = occupancy_df.index[-1] d_temp = pd.Timestamp(temp + pd.Timedelta("-1 days")) d_temp = d_temp.replace(hour=23,minute=45,second=0) occupancy_df = occupancy_df.loc[:d_temp] zone_sensor_df[zone] = 1*(occupancy_df > 0) return zone_sensor_df
def _fetch_dataframe(): """ Returns a `pandas.DataFrame` with columns tin: the current temperature a: 0=noop, 1=cooling, 2=heating a1: is cooling? a2: is heating? next_temp: the temperature at the next time step """ with _silence(): # set $BW2_AGENT and $BW2_DEFAULT_ENTITY archiver = DataClient(get_client()) now = datetime.now(pytz.timezone('America/Los_Angeles')) start = (now + timedelta(minutes=15)).strftime(DATE_FMT) end = (now - timedelta(days=7)).strftime(DATE_FMT) dfs = make_dataframe(archiver.window_uuids(UUIDS, end, start, INTERVAL)) for uid, df in dfs.items(): if uid == SE_TEMP: if 'mean' in df.columns: df = df[['mean']] df.columns = ['tin'] elif uid == SE_STATE: if 'max' in df.columns: df = df[['max']] df.columns = ['a'] dfs[uid] = df.resample(INTERVAL).mean() df = pd.concat([dframe for uid, dframe in dfs.items()], axis=1) df['a1'] = df.apply(lambda row: int(row['a'] > 0 and row['a'] <= 1), axis=1) df['a2'] = df.apply(lambda row: int(row['a'] > 1), axis=1) # the following are the features used by the baseline model df['tin'] = df['tin'].replace(to_replace=0, method='pad') df['tin_a1'] = df.tin * df.a1 df['tin_a2'] = df.tin * df.a2 df['next_temp'] = df['tin'].shift(-1) # the following are necessary because rulinalg complains about ill-conditioning # note that numpy does not have this problem df.tin_a1 += np.random.randn(len(df.tin)) * 1e-8 df.tin_a2 += np.random.randn(len(df.tin)) * 1e-8 df = df.dropna() return df
def __init__(self, cfg, now=datetime.datetime.utcnow().replace( tzinfo=pytz.timezone("UTC")).astimezone( tz=pytz.timezone("America/Los_Angeles")), heat=4000, cool=4000, vent=500): # query the server to learn the energy rates of the next 8 hours self.heat = heat self.cool = cool self.vent = vent self.mode = cfg['energy_rates'] self.now = now if cfg['Server']: c = get_client(agent='172.17.0.1:28589', entity="thanos.ent") else: c = get_client() archiver = DataClient(c) uuids = [cfg['UUIDS']['energy_cost']] start = '"' + (now).strftime('%Y-%m-%d %H:%M:%S') + ' PST"' end = '"' + ( now - timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S') + ' PST"' dfs = make_dataframe( archiver.window_uuids(uuids, end, start, '15min', timeout=120)) for uid, df in dfs.items(): if uid == uuids[0]: if 'mean' in df.columns: df = df[['mean']] df.columns = ['cost'] dfs[uid] = df.resample('15min').mean() uid, self.df = dfs.items()[0]
def hvac_control(): try: # query the server to lean the current setpoints and the state of the thermostat if cfg['Server']: c = get_client(agent='172.17.0.1:28589', entity="thanos.ent") else: c = get_client() archiver = DataClient(c) uuids = [ cfg['UUIDS']['thermostat_high'], cfg['UUIDS']['thermostat_low'], cfg['UUIDS']['thermostat_mode'] ] temp_now = datetime.datetime.utcnow().replace( tzinfo=pytz.timezone("UTC")).astimezone( tz=pytz.timezone("America/Los_Angeles")) start = '"' + temp_now.strftime('%Y-%m-%d %H:%M:%S') + ' PST"' end = '"' + (temp_now - datetime.timedelta(minutes=10) ).strftime('%Y-%m-%d %H:%M:%S') + ' PST"' dfs = make_dataframe( archiver.window_uuids(uuids, end, start, '1min', timeout=120)) for uid, df in dfs.items(): if uid == uuids[0]: if 'mean' in df.columns: df = df[['mean']] df.columns = ['t_high'] elif uid == uuids[1]: if 'mean' in df.columns: df = df[['mean']] df.columns = ['t_low'] elif uid == uuids[2]: if 'mean' in df.columns: df = df[['mean']] df.columns = ['mode'] dfs[uid] = df.resample('1min').mean() df = pd.concat([dframe for uid, dframe in dfs.items()], axis=1) except: e = sys.exc_info()[0] print e return False # document the "before" state try: f = open(filename, 'a') f.write("Did read: " + str(df['t_low'][-1]) + ", " + str(df['t_high'][-1]) + ", " + str(df['mode'][-1]) + "\n") f.close() except: print "Could not document changes." # choose the apropriate setpoints according to weekday and time weekno = temp_now.weekday() if weekno < 5: now = datetime.datetime.utcnow().replace( tzinfo=pytz.timezone("UTC")).astimezone( tz=pytz.timezone("America/Los_Angeles")) now_time = now.time() if now_time >= datetime.time(18, 0) or now_time < datetime.time(7, 0): heating_setpoint = 62. cooling_setpoint = 85. else: heating_setpoint = 70. cooling_setpoint = 76. else: heating_setpoint = 62. cooling_setpoint = 85. try: adv = Advise(cfg) action, temp = adv.advise() temp = float(temp) except: e = sys.exc_info()[0] print e return False # action "0" is Do Nothing, action "1" is Cooling, action "2" is Heating if action == "0": p = { "override": True, "heating_setpoint": math.floor(temp - 0.1) - 1, "cooling_setpoint": math.ceil(temp + 0.1) + 1, "mode": 3 } print "Doing nothing" print p # document changes try: f = open(filename, 'a') f.write("Did write: " + str(math.floor(temp - 0.1) - 1) + ", " + str(math.ceil(temp + 0.1) + 1) + ", " + str(3) + "\n") f.close() except: print "Could not document changes." elif action == "1": p = { "override": True, "heating_setpoint": heating_setpoint, "cooling_setpoint": math.floor(temp - 0.1), "mode": 3 } print "Heating" print p # document changes try: f = open(filename, 'a') f.write("Did write: " + str(heating_setpoint) + ", " + str(math.floor(temp - 0.1)) + ", " + str(3) + "\n") f.close() except: print "Could not document changes." elif action == "2": p = { "override": True, "heating_setpoint": math.ceil(temp + 0.1), "cooling_setpoint": cooling_setpoint, "mode": 3 } print "Cooling" print p # document changes try: f = open(filename, 'a') f.write("Did write: " + str(math.ceil(temp + 0.1)) + ", " + str(cooling_setpoint) + ", " + str(3) + "\n") f.close() except: print "Could not document changes." else: print "Problem with action." return False # try to commit the changes to the thermostat, if it doesnt work 10 times in a row ignore and try again later for z in normal_zones: for i in range(10): try: zones[z].write(p) break except: if i == 9: e = sys.exc_info()[0] print e return False continue return True
import matplotlib.pyplot as plt c = get_client() archiver = DataClient(c) demand = "4d6e251a-48e1-3bc0-907d-7d5440c34bb9" uuids = [demand] now = datetime.datetime.utcnow().replace( tzinfo=pytz.timezone("UTC")).astimezone( tz=pytz.timezone("America/Los_Angeles")) start = '"' + now.strftime('%Y-%m-%d %H:%M:%S') + ' PST"' end = '"2017-9-21 00:00:00 PST"' dfs = make_dataframe( archiver.window_uuids(uuids, end, start, '1min', timeout=120)) for uid, df in dfs.items(): if uid == uuids[0]: if 'mean' in df.columns: df = df[['mean']] df.columns = ['House Consumption'] dfs[uid] = df.resample('1min').mean() uid, df = dfs.items()[0] df = df / (1000 * 60) print df.resample('60T').sum().describe()
uuids = [[x['?zone'], x['?uuid']] for x in results['Rows']] per_zone_occ_list = [] for zone_name in zones: query_list = [] for i in uuids: if i[0] == zone_name: query_list.append(i[1]) start = '"' + temp_now.strftime('%Y-%m-%d %H:%M:%S') + ' PST"' end = '"' + (temp_now - timedelta(days=60)).strftime('%Y-%m-%d %H:%M:%S') + ' PST"' dfs = make_dataframe( archiver.window_uuids(query_list, end, start, '15min', timeout=120)) for uid, df in dfs.items(): if 'mean' in df.columns: df = df[['mean']] df.columns = ['occ'] dfs[uid] = df.resample('15min').mean() df = dfs.values()[0] if len(dfs) > 1: for newdf in dfs.values()[1:]: df['occ'] += newdf['occ'] df['occ'] = 1 * (df['occ'] > 0) df.index = df.index.tz_localize(pytz.timezone("America/Los_Angeles")) per_zone_occ_list.append(df)
def __init__(self, cfg, now=datetime.datetime.utcnow().replace( tzinfo=pytz.timezone("UTC")).astimezone( tz=pytz.timezone("America/Los_Angeles"))): # query the server to get all the available occupancy sensors zone_name = cfg['zone'] if cfg['Server']: c = get_client(agent='172.17.0.1:28589', entity="thanos.ent") else: c = get_client() archiver = DataClient(c) hod = HodClient("ciee/hod", c) occ_query = """SELECT ?sensor ?uuid ?zone WHERE { ?sensor rdf:type brick:Occupancy_Sensor . ?sensor bf:isLocatedIn/bf:isPartOf ?zone . ?sensor bf:uuid ?uuid . ?zone rdf:type brick:HVAC_Zone }; """ results = hod.do_query(occ_query) uuids = [[x['?zone'], x['?uuid']] for x in results['Rows']] temp_now = now # select the sensors that are contained in the zone we are optimizing for query_list = [] for i in uuids: if i[0] == zone_name: query_list.append(i[1]) start = '"' + (temp_now).strftime('%Y-%m-%d %H:%M:%S') + ' PST"' end = '"' + (temp_now - timedelta(days=30) ).strftime('%Y-%m-%d %H:%M:%S') + ' PST"' dfs = make_dataframe( archiver.window_uuids(query_list, end, start, '15min', timeout=120)) for uid, df in dfs.items(): if 'mean' in df.columns: df = df[['mean']] df.columns = ['occ'] dfs[uid] = df.resample('15min').mean() df = dfs.values()[0] if len(dfs) > 1: for newdf in dfs.values()[1:]: df['occ'] += newdf['occ'] df['occ'] = 1 * (df['occ'] > 0) df.index = df.index.tz_localize(pytz.timezone("America/Los_Angeles")) observation_length_addition = 4 * 60 k = 5 prediction_time = 4 * 60 resample_time = 15 #now = df.index[-prediction_time/resample_time] now = df.index[-1] observation_length = mins_in_day(now) + observation_length_addition similar_moments = find_similar_days(df, now, observation_length, k) self.predictions = predict(df, now, similar_moments, prediction_time, resample_time)
def preprocess_thermal(self, cfg): # if state is 1 we are doing heating def f1(row): if row['a'] > 0 and row['a'] <= 1: val = 1 else: val = 0 return val # if state is 2 we are doing cooling def f2(row): if row['a'] > 1 and row['a'] <= 2: val = 1 else: val = 0 return val final_df = pd.DataFrame() flag = True heating_count = 0 cooling_count = 0 do_nothing_count = 0 max_action_count = 50 month_count = 0 while flag: # query the server for the thermostat state and temperature if cfg['Server']: c = get_client(agent='172.17.0.1:28589', entity="thanos.ent") else: c = get_client() archiver = DataClient(c) uuids = [ cfg['UUIDS']['thermostat_temperature'], cfg['UUIDS']['thermostat_state'] ] temp_now = self.current_time start = '"' + (temp_now + timedelta(minutes=15) - timedelta(days=(month_count) * 30) ).strftime('%Y-%m-%d %H:%M:%S') + ' PST"' end = '"' + (temp_now - timedelta(days=(month_count + 1) * 30) ).strftime('%Y-%m-%d %H:%M:%S') + ' PST"' dfs = make_dataframe( archiver.window_uuids(uuids, end, start, '15min', timeout=120)) for uid, df in dfs.items(): if uid == uuids[0]: if 'mean' in df.columns: df = df[['mean']] df.columns = ['tin'] elif uid == uuids[1]: if 'max' in df.columns: df = df[['max']] df.columns = ['a'] dfs[uid] = df.resample('15min').mean() df = pd.concat([dframe for uid, dframe in dfs.items()], axis=1) df['a1'] = df.apply(f1, axis=1) df['a2'] = df.apply(f2, axis=1) df['tin'] = df['tin'].replace(to_replace=0, method='pad') df['temp_next'] = df['tin'].shift(-1) df = df.dropna() for idx in reversed(df.index): if df.at[idx, 'a1'] == 1 and heating_count <= max_action_count: if df.at[idx, 'tin'] <= df.at[idx, 'temp_next']: final_df = final_df.append(df[df.index == idx]) heating_count += 1 elif df.at[idx, 'a2'] == 1 and cooling_count < max_action_count: if df.at[idx, 'tin'] >= df.at[idx, 'temp_next']: final_df = final_df.append(df[df.index == idx]) cooling_count += 1 elif df.at[idx, 'a1'] == 0 and df.at[ idx, 'a2'] == 0 and do_nothing_count < max_action_count: final_df = final_df.append(df[df.index == idx]) do_nothing_count += 1 if heating_count>=max_action_count and cooling_count>=max_action_count\ and do_nothing_count>=max_action_count: flag = False break month_count += 1 return shuffle(final_df)