Esempio n. 1
0
    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']
Esempio n. 2
0
    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
Esempio n. 3
0
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
Esempio n. 4
0
    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]
Esempio n. 5
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
Esempio n. 6
0
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)
Esempio n. 8
0
    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)
Esempio n. 9
0
    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)