def preprocess_occ_mdal(self): """ Returns the required dataframe for the occupancy predictions ------- Pandas DataFrame """ hod = HodClient( "xbos/hod", self.c ) # TODO MAKE THIS WORK WITH FROM AND xbos/hod, FOR SOME REASON IT DOES NOT occ_query = """SELECT ?sensor ?uuid ?zone FROM %s WHERE { ?sensor rdf:type brick:Occupancy_Sensor . ?sensor bf:isPointOf/bf:isPartOf ?zone . ?sensor bf:uuid ?uuid . ?zone rdf:type brick:HVAC_Zone }; """ % self.controller_cfg[ "Building"] # get all the occupancy sensors uuids results = hod.do_query(occ_query) # run the query uuids = [[x['?zone'], x['?uuid']] for x in results['Rows']] # unpack # only choose the sensors for the zone specified in cfg query_list = [] for i in uuids: if i[0] == self.zone: query_list.append(i[1]) # get the sensor data c = mdal.MDALClient("xbos/mdal", client=self.c) dfs = c.do_query({ 'Composition': query_list, 'Selectors': [mdal.MAX] * len(query_list), 'Time': { 'T0': (self.now - timedelta(days=25)).strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'T1': self.now.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'WindowSize': str(self.interval) + 'min', 'Aligned': True } }) dfs = pd.concat([dframe for uid, dframe in dfs.items()], axis=1) df = dfs[[query_list[0]]] df.columns.values[0] = 'occ' df.is_copy = False df.columns = ['occ'] # perform OR on the data, if one sensor is activated, the whole zone is considered occupied for i in range(1, len(query_list)): df.loc[:, 'occ'] += dfs[query_list[i]] df.loc[:, 'occ'] = 1 * (df['occ'] > 0) return df.tz_localize(None)
def thermostat_setpoints(self): uuids = [ self.cfg["Data_Manager"]["UUIDS"]['Thermostat_high'], self.cfg["Data_Manager"]["UUIDS"]['Thermostat_low'], self.cfg["Data_Manager"]["UUIDS"]['Thermostat_mode'] ] c = mdal.MDALClient("xbos/mdal", client=self.c) dfs = c.do_query({ 'Composition': uuids, 'Selectors': [mdal.MEAN, mdal.MEAN, mdal.MEAN], 'Time': { 'T0': (self.now - timedelta(minutes=10)).strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'T1': self.now.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'WindowSize': '1min', 'Aligned': True } }) df = pd.concat([dframe for uid, dframe in dfs.items()], axis=1) df = df.rename(columns={ uuids[0]: 'T_High', uuids[1]: 'T_Low', uuids[2]: 'T_Mode' }) return df['T_High'][-1], df['T_Low'][-1], df['T_Mode'][-1]
def __init__(self, start=None, end=None, timezone='US/Pacific'): """ params: start: (string, "%Y-%m-%d %H:%M:%S %Z") When should the data start. end: (string, "%Y-%m-%d %H:%M:%S %Z") when should the data end. timezone: (string) As used by pytz. Used for both start and end """ # data clients self.client = mdal.MDALClient("xbos/mdal") self.hod = HodClient("xbos/hod") self.SITE = "ciee" tz = pytz.timezone('US/Pacific') temp_end = dati.datetime.today() if end is None else datetime.strptime( end, "%Y-%m-%d %H:%M:%S %Z") temp_start = ( temp_end - dati.timedelta(10)) if start is None else datetime.strptime( start, "%Y-%m-%d %H:%M:%S %Z") self.end = tz.localize(temp_end) self.start = tz.localize(temp_start) self.zone_sensor_df = self.get_occupancy() self.building_df = self.get_building_occupancy() self.zone_df = self.get_zone_occupancy()
def preprocess_therm(self): uuids = [ self.cfg["Data_Manager"]["UUIDS"]["Thermostat_temperature"], self.cfg["Data_Manager"]["UUIDS"]["Thermostat_state"], self.cfg["Data_Manager"]["UUIDS"]["Temperature_Outside"] ] c = mdal.MDALClient("xbos/mdal", client=self.c) dfs = c.do_query({ 'Composition': uuids, 'Selectors': [mdal.MEAN, mdal.MAX, mdal.MEAN], 'Time': { 'T0': '2017-07-21 00:00:00 UTC', 'T1': self.now.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'WindowSize': '1min', 'Aligned': True } }) df = pd.concat([dframe for uid, dframe in dfs.items()], axis=1) df = df.rename(columns={ uuids[0]: 'tin', uuids[1]: 'a', uuids[2]: 't_out' }) df = df.fillna(method='pad') df['a'] = df.apply(f3, axis=1) df['tin'] = df['tin'].replace(to_replace=0, method='pad') df['t_out'] = df['t_out'].replace(to_replace=0, method='pad') df.dropna() df['change_of_action'] = (df['a'].diff(1) != 0).astype('int').cumsum() listerino = [] for j in df.change_of_action.unique(): for dfs in [ df[df['change_of_action'] == j][i:i + self.interval] for i in range(0, df[df['change_of_action'] == j].shape[0], self.interval) ]: listerino.append({ 'time': dfs.index[0], 'tin': dfs['tin'][0], 't_next': dfs['tin'][-1], 'dt': dfs.shape[0], 'tout': dfs['t_out'][0], 'action': dfs['a'][0] }) df = pd.DataFrame(listerino).set_index('time') df['a1'] = df.apply(f1, axis=1) df['a2'] = df.apply(f2, axis=1) return df.tz_localize(None)
def preprocess_occ(self): #this only works for ciee, check how it should be writen properly: hod = HodClient("ciee/hod", self.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']] query_list = [] for i in uuids: if i[0] == self.zone: query_list.append(i[1]) c = mdal.MDALClient("xbos/mdal") dfs = c.do_query({ 'Composition': query_list, 'Selectors': [mdal.MAX] * len(query_list), 'Time': { 'T0': (self.now - timedelta(days=30)).strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'T1': self.now.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'WindowSize': str(self.interval) + 'min', 'Aligned': True } }) dfs = pd.concat([dframe for uid, dframe in dfs.items()], axis=1) df = dfs[[query_list[0]]] df.columns.values[0] = 'occ' df.is_copy = False df.columns = ['occ'] for i in range(1, len(query_list)): df.loc[:, 'occ'] += dfs[query_list[i]] df.loc[:, 'occ'] = 1 * (df['occ'] > 0) return df.tz_localize(None)
def preprocess_data(UUID, c, startime, endtime): c = mdal.MDALClient("xbos/mdal", client=c) dfs = c.do_query({'Composition': [UUID], 'Selectors': [mdal.MAX], 'Time': {'T0': startime.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'T1': endtime.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'WindowSize': '1min', 'Aligned': True}}) df = [dframe for uid, dframe in dfs.items()][0] df = df.rename(columns={UUID: 'State'}) df = df.loc[df['State'] != 0.0] return df.dropna()
def _get_outside_data(self, start=None, end=None): # TODO update docstring """Get outside temperature for thermal model. :param start: (datetime) time to start. relative to datamanager instance timezone. :param end: (datetime) time to end. relative to datamanager instance timezone. :return outside temperature has freq of 15 min and pd.df columns["tin", "a"] has freq of self.window_size. """ if end is None: end = self.now if start is None: start = end - timedelta(hours=10) # Converting start and end from datamanger timezone to UTC timezone. start = start.astimezone(pytz.timezone("UTC")) end = end.astimezone(pytz.timezone("UTC")) outside_temperature_query = """SELECT ?weather_station ?uuid FROM %s WHERE { ?weather_station rdf:type brick:Weather_Temperature_Sensor. ?weather_station bf:uuid ?uuid. };""" # get outside temperature data # TODO UPDATE OUTSIDE TEMPERATURE STUFF # TODO for now taking all weather stations and preprocessing it. Should be determined based on metadata. outside_temperature_query_data = self.hod_client.do_query( outside_temperature_query % self.building)["Rows"][0] # Get data from MDAL mdal_client = mdal.MDALClient("xbos/mdal", client=self.client) outside_temperature_data = mdal_client.do_query({ 'Composition': [outside_temperature_query_data["?uuid"]], # uuid from Mr.Plotter. should use outside_temperature_query_data["?uuid"], 'Selectors': [mdal.MEAN], 'Time': { 'T0': start.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'T1': end.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'WindowSize': str(15) + 'min', # TODO document that we are getting 15 min intervals because then we get less nan values. 'Aligned': True } }) outside_temperature_data = outside_temperature_data["df"] outside_temperature_data.columns = ["t_out"] return outside_temperature_data
def _get_outside_data(self, start=None, end=None, inclusive=False): # TODO update docstring """Get outside temperature for thermal model. :param start: (datetime) time to start. in UTC time. :param end: (datetime) time to end. in UTC time. :param inclusive: (bool) whether the end time should be inclusive. which means that we get the time for the end, plus 15 min. :return ({uuid: (pd.df) (col: "t_out) outside_data}) outside temperature has freq of 15 min and pd.df columns["tin", "action"] has freq of self.window_size. """ # add an interval, to make the end inclusive, which means that we get the time for the end, plus 15 min. if inclusive: end += datetime.timedelta(minutes=15) outside_temperature_query = """SELECT ?weather_station ?uuid FROM %s WHERE { ?weather_station rdf:type brick:Weather_Temperature_Sensor. ?weather_station bf:uuid ?uuid. };""" # get outside temperature data # TODO UPDATE OUTSIDE TEMPERATURE STUFF # TODO for now taking all weather stations and preprocessing it. Should be determined based on metadata. outside_temperature_query_data = self.hod_client.do_query(outside_temperature_query % self.building)["Rows"] outside_temperature_data = {} for weather_station in outside_temperature_query_data: # Get data from MDAL mdal_client = mdal.MDALClient("xbos/mdal", client=self.client) mdal_query = { 'Composition': [weather_station["?uuid"]], # uuid from Mr.Plotter. should use outside_temperature_query_data["?uuid"], 'Selectors': [mdal.MEAN] , 'Time': {'T0': start.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'T1': end.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'WindowSize': str(15) + 'min', # TODO document that we are getting 15 min intervals because then we get fewer nan values. 'Aligned': True}} mdal_outside_data = utils.get_mdal_data(mdal_client, mdal_query) mdal_outside_data.columns = ["t_out"] outside_temperature_data[weather_station["?uuid"]] = mdal_outside_data return outside_temperature_data
""" res3=hod.do_query(type_query % SITE) byrooms_type = defaultdict(list) for item in res3['Rows']: byrooms_type[item['?room']].append(item['?label']) print byrooms_type print "Room types loaded!" Actuated = "" ################################################ Controls c = mdal.MDALClient("xbos/mdal") for room in all_rooms: Type = byrooms_type[room][0] if Type=="Hallway": for light in byrooms[room]: if ACTUATE: brightness =20 Actuated += "Lights in room"+str(room)+" was set to"+str(brightness)+"\n" light.set_brightness(min(light.brightness,brightness)) elif Type=="Toilet": for light in byrooms[room]: print "c"#print light.brightness if ACTUATE:
def _get_inside_data(self, start, end): """Get thermostat status and temperature and outside temperature for thermal model. :param start: (datetime) time to start. relative to datamanager instance timezone. :param end: (datetime) time to end. relative to datamanager instance timezone. :return outside temperature has freq of 15 min and pd.df columns["tin", "a"] has freq of self.window_size. """ # Converting start and end from datamanger timezone to UTC timezone. start = start.astimezone(pytz.timezone("UTC")) end = end.astimezone(pytz.timezone("UTC")) # following queries are for the whole building. thermostat_status_query = """SELECT ?zone ?uuid FROM %s WHERE { ?tstat rdf:type brick:Thermostat . ?tstat bf:hasLocation/bf:isPartOf ?location_zone . ?location_zone rdf:type brick:HVAC_Zone . ?tstat bf:controls ?RTU . ?RTU rdf:type brick:RTU . ?RTU bf:feeds ?zone. ?zone rdf:type brick:HVAC_Zone . ?tstat bf:hasPoint ?status_point . ?status_point rdf:type brick:Thermostat_Status . ?status_point bf:uuid ?uuid. };""" # Start of FIX for missing Brick query thermostat_status_query = """SELECT ?zone ?uuid FROM %s WHERE { ?tstat rdf:type brick:Thermostat . ?tstat bf:controls ?RTU . ?RTU rdf:type brick:RTU . ?RTU bf:feeds ?zone. ?zone rdf:type brick:HVAC_Zone . ?tstat bf:hasPoint ?status_point . ?status_point rdf:type brick:Thermostat_Status . ?status_point bf:uuid ?uuid. };""" # End of FIX - delete when Brick is fixed thermostat_temperature_query = """SELECT ?zone ?uuid FROM %s WHERE { ?tstat rdf:type brick:Thermostat . ?tstat bf:hasLocation/bf:isPartOf ?location_zone . ?location_zone rdf:type brick:HVAC_Zone . ?tstat bf:controls ?RTU . ?RTU rdf:type brick:RTU . ?RTU bf:feeds ?zone. ?zone rdf:type brick:HVAC_Zone . ?tstat bf:hasPoint ?thermostat_point . ?thermostat_point rdf:type brick:Temperature_Sensor . ?thermostat_point bf:uuid ?uuid. };""" # Start of FIX for missing Brick query thermostat_temperature_query = """SELECT ?zone ?uuid FROM %s WHERE { ?tstat rdf:type brick:Thermostat . ?tstat bf:controls ?RTU . ?RTU rdf:type brick:RTU . ?RTU bf:feeds ?zone. ?zone rdf:type brick:HVAC_Zone . ?tstat bf:hasPoint ?thermostat_point . ?thermostat_point rdf:type brick:Temperature_Sensor . ?thermostat_point bf:uuid ?uuid. };""" # End of FIX - delete when Brick is fixed temp_thermostat_query_data = { "tstat_temperature": self.hod_client.do_query(thermostat_temperature_query % self.building)["Rows"], "tstat_action": self.hod_client.do_query(thermostat_status_query % self.building)["Rows"], } # give the thermostat query data better structure for later loop. Can index by zone and then get uuids for each # thermostat attribute. thermostat_query_data = {} for tstat_attr, attr_dicts in temp_thermostat_query_data.items(): for dict in attr_dicts: if dict["?zone"] not in thermostat_query_data: thermostat_query_data[dict["?zone"]] = {} thermostat_query_data[ dict["?zone"]][tstat_attr] = dict["?uuid"] # get the data for the thermostats for each zone. mdal_client = mdal.MDALClient("xbos/mdal", client=self.client) zone_thermal_data = {} for zone, dict in thermostat_query_data.items(): # get the thermostat data dfs = mdal_client.do_query({ 'Composition': [dict["tstat_temperature"], dict["tstat_action"]], 'Selectors': [mdal.MEAN, mdal.MAX], 'Time': { 'T0': start.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'T1': end.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'WindowSize': str(self.window_size) + 'min', 'Aligned': True } }) df = pd.concat([dframe for uid, dframe in dfs.items()], axis=1) zone_thermal_data[zone] = df.rename(columns={ dict["tstat_temperature"]: 't_in', dict["tstat_action"]: 'a' }) # TODO Note: The timezone for the data relies to be converted by MDAL to the local timezone. return zone_thermal_data
import os import pytz import yaml from xbos.services import hod, mdal cfg = yaml.load(open('config.yml')) AGENT = cfg.get('agent', '127.0.0.1:28589') if AGENT.startswith('$'): AGENT = os.environ[AGENT] ENTITY = cfg.get('entity', '') if ENTITY.startswith('$'): ENTITY = os.environ[ENTITY[1:]] SITE = cfg.get('site', 'ciee') HOD = hod.HodClient(cfg.get('hod', 'xbos/hod')) MDAL = mdal.MDALClient(cfg.get('mdal', 'xbos/mdal')) TZ = pytz.timezone(cfg.get('tz', 'US/Pacific'))
def lights(building, client, actuate=False): ACTUATE = actuate SITE = building # Cahnge this according to the site # print RoomsType.RoomsType[df['column_name'] == some_value] c = client hod = HodClient("xbos/hod") skipped = "" ####### occ query occ_query = """SELECT * FROM %s WHERE { ?l rdf:type brick:Lighting_System . ?l bf:feeds ?room . ?room rdf:type brick:Room . ?l bf:uri ?luri . ?l bf:hasPoint ?p . ?p rdf:type brick:Occupancy_Sensor . ?p bf:uri ?puri . ?p bf:uuid ?puuid };""" res2 = hod.do_query(occ_query % SITE) byrooms_o = defaultdict(list) for item in res2['Rows']: byrooms_o[item['?room']].append(item['?puuid']) print "Occupancy uuids loaded!" ####### light query light_query = """ SELECT ?light ?room ?light_uri FROM %s WHERE { ?light rdf:type brick:Lighting_System . ?light bf:feeds ?room . ?room rdf:type brick:Room . ?light bf:uri ?light_uri }; """ res = hod.do_query(light_query % SITE) byrooms = defaultdict(list) all_rooms = set() for item in res['Rows']: all_rooms.add(item['?room']) try: l = Light(c, item['?light_uri']) byrooms[item['?room']].append(l) except: skipped += str(item['?light']) + "in room" + str( item['?room']) + " skipped! \n" pass print "Lighting systems loaded!" ####### room type query type_query = """SELECT * FROM %s WHERE { ?room rdf:type brick:Room. ?room rdf:label ?label }; """ res3 = hod.do_query(type_query % SITE) byrooms_type = defaultdict(list) for item in res3['Rows']: byrooms_type[item['?room']].append(item['?label']) print byrooms_type print "Room types loaded!" Actuated = "" ################################################ Controls c = mdal.MDALClient("xbos/mdal") for room in all_rooms: Type = byrooms_type[room][0] if Type == "Hallway": for light in byrooms[room]: if ACTUATE: brightness = 20 Actuated += "Lights in room" + str( room) + " was set to" + str(brightness) + "\n" light.set_brightness(min(light.brightness, brightness)) elif Type == "Toilet": for light in byrooms[room]: print "c" # print light.brightness if ACTUATE: brightness = 10 Actuated += "Lights in room" + str( room) + " was set to" + str(brightness) + "\n" light.set_brightness(min(light.brightness, brightness)) else: query_list = [] for i in byrooms_o[room]: query_list.append(i) # get the sensor data now = datetime.datetime.utcnow().replace( tzinfo=pytz.timezone("UTC")) dfs = c.do_query({ 'Composition': query_list, 'Selectors': [mdal.MAX] * len(query_list), 'Time': { 'T0': (now - timedelta(hours=0.5)).strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'T1': now.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'WindowSize': str(30) + 'min', 'Aligned': True } }) dfs = pd.concat([dframe for uid, dframe in dfs.items()], axis=1) df = dfs[[query_list[0]]] df.columns.values[0] = 'occ' df.is_copy = False df.columns = ['occ'] # perform OR on the data, if one sensor is activated, the whole room is considered occupied for i in range(1, len(query_list)): df.loc[:, 'occ'] += dfs[query_list[i]] df.loc[:, 'occ'] = 1 * (df['occ'] > 0) if df["occ"][0] != 1: for light in byrooms[room]: if ACTUATE: brightness = 0 Actuated += "Lights in room" + str( room) + " was set to " + str(brightness) + "\n" light.set_brightness(min(light.brightness, brightness)) else: for light in byrooms[room]: print light.brightness if ACTUATE: brightness = 10 Actuated += "Lights in room" + str( room) + " was set to " + str(brightness) + "\n" light.set_brightness(min(light.brightness, brightness)) print "Done!" print "================================" print "We skipped the following lights:" print skipped print "We actuated the following lights:" print Actuated
def thermostat_setpoints(self, start, end, window_size=1): """ Gets the thermostat setpoints from archiver from start to end. Does not preprocess the data. :param start: datetime in utc time. :param end: datetime in utc time. :param window_size: The frequency with which to get the data. :return: pd.df columns="t_high", "t_low" with timeseries in utc time with freq=window_size. """ cooling_setpoint_query = """SELECT ?zone ?uuid FROM %s WHERE { ?tstat rdf:type brick:Thermostat . ?tstat bf:controls ?RTU . ?RTU rdf:type brick:RTU . ?RTU bf:feeds ?zone. ?zone rdf:type brick:HVAC_Zone . ?tstat bf:hasPoint ?setpoint . ?setpoint rdf:type brick:Supply_Air_Temperature_Cooling_Setpoint . ?setpoint bf:uuid ?uuid. };""" heating_setpoint_query = """SELECT ?zone ?uuid FROM %s WHERE { ?tstat rdf:type brick:Thermostat . ?tstat bf:controls ?RTU . ?RTU rdf:type brick:RTU . ?RTU bf:feeds ?zone. ?zone rdf:type brick:HVAC_Zone . ?tstat bf:hasPoint ?setpoint . ?setpoint rdf:type brick:Supply_Air_Temperature_Heating_Setpoint . ?setpoint bf:uuid ?uuid. };""" hod_client = HodClient("xbos/hod", self.c) # get query data temp_thermostat_query_data = { "cooling_setpoint": hod_client.do_query(cooling_setpoint_query % self.controller_cfg["Building"])["Rows"], "heating_setpoint": hod_client.do_query(heating_setpoint_query % self.controller_cfg["Building"])["Rows"], } # give the thermostat query data better structure for later loop. Can index by zone and then get uuids for each # thermostat attribute. thermostat_query_data = {} for tstat_attr, attr_dicts in temp_thermostat_query_data.items(): for dict in attr_dicts: if dict["?zone"] not in thermostat_query_data: thermostat_query_data[dict["?zone"]] = {} thermostat_query_data[ dict["?zone"]][tstat_attr] = dict["?uuid"] # get the data for the thermostats for each zone. mdal_client = mdal.MDALClient("xbos/mdal", client=self.c) zone_setpoint_data = {} for zone, dict in thermostat_query_data.items(): mdal_query = { 'Composition': [dict["heating_setpoint"], dict["cooling_setpoint"]], 'Selectors': [mdal.MEAN, mdal.MEAN], 'Time': { 'T0': start.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'T1': end.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'WindowSize': str(window_size) + 'min', 'Aligned': True } } # get the thermostat data df = utils.get_mdal_data(mdal_client, mdal_query) zone_setpoint_data[zone] = df.rename( columns={ dict["heating_setpoint"]: 't_low', dict["cooling_setpoint"]: 't_high' }) return zone_setpoint_data
def data_fetch(cfg, cli, zones): # state, tin, tout, setp_high, setp_low UUIDS = { "SouthZone": [ "dfb2b403-fd08-3e9b-bf3f-18c699ce40d6", "03099008-5224-3b61-b07e-eee445e64620", "1c467b79-b314-3c1e-83e6-ea5e7048c37b", "dbbf4a91-107a-3b15-b2c0-a49b54116daa", "eeadc8ed-6255-320d-b845-84f44748fe95" ], "NorthZone": [ "5e55e5b1-007b-39fa-98b6-ae01baa6dccd", "c7e33fa6-f683-36e9-b97a-7f096e4b57d4", "1c467b79-b314-3c1e-83e6-ea5e7048c37b", "9fa56ac1-0f8a-3ad2-86e8-72e816b875ad", "e4e0db0b-1c15-330e-a864-011e558f542e" ], "CentralZone": [ "187ed9b8-ee9b-3042-875e-088a08da37ae", "c05385e5-a947-37a3-902e-f6ea45a43fe8", "1c467b79-b314-3c1e-83e6-ea5e7048c37b", "0d037818-02c2-3e5b-87e9-94570d43b418", "6cbee2ae-06e7-3fc3-a2fc-698fa3deadee" ], "EastZone": [ "7e543d07-16d1-32bb-94af-95a01f4675f9", "b47ba370-bceb-39cf-9552-d1225d910039", "1c467b79-b314-3c1e-83e6-ea5e7048c37b", "d38446d4-32cc-34bd-b293-0a3871a6759b", "e4d39723-5907-35bd-a9b2-fc57b58b3779" ] } uspac = pytz.timezone(cfg["Pytz_Timezone"]) startime = uspac.localize( datetime.datetime.strptime( cfg["Start_Date"], '%Y-%m-%d %H:%M:%S')).astimezone(tz=pytz.utc) endtime = startime + timedelta(hours=24) hod = HodClient(cfg["Building"] + "/hod", cli) 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 }; """ # get all the occupancy sensors uuids results = hod.do_query(occ_query) # run the query occ_uuids = [[x['?zone'], x['?uuid']] for x in results['Rows']] # unpack dataframes = {} for zone in zones: query_list = [] for i in occ_uuids: if i[0] == zone: query_list.append(i[1]) c = mdal.MDALClient("xbos/mdal", client=cli) dfs = c.do_query({ 'Composition': UUIDS[zone], 'Selectors': [mdal.MAX, mdal.MEAN, mdal.MEAN, mdal.MEAN, mdal.MEAN], 'Time': { 'T0': startime.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'T1': endtime.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'WindowSize': '1min', 'Aligned': True } }) df = pd.concat([dframe for uid, dframe in dfs.items()], axis=1) df_th = df.rename( columns={ UUIDS[zone][0]: 'State', UUIDS[zone][1]: 'Tin', UUIDS[zone][2]: 'Tout', UUIDS[zone][3]: "STPH", UUIDS[zone][4]: "STPL" }) df_th['change_of_action'] = (df_th['State'].diff(1) != 0).astype('int').cumsum() c = mdal.MDALClient("xbos/mdal", client=cli) dfs = c.do_query({ 'Composition': query_list, 'Selectors': [mdal.MAX] * len(query_list), 'Time': { 'T0': startime.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'T1': endtime.strftime('%Y-%m-%d %H:%M:%S') + ' UTC', 'WindowSize': '1min', 'Aligned': True } }) dfs = pd.concat([dframe for uid, dframe in dfs.items()], axis=1) df = dfs[[query_list[0]]] df.columns.values[0] = 'Occ' df.is_copy = False df.columns = ['Occ'] # perform OR on the data, if one sensor is activated, the whole zone is considered occupied for i in range(1, len(query_list)): df.loc[:, 'Occ'] += dfs[query_list[i]] df.loc[:, 'Occ'] = 1 * (df['Occ'] > 0) df_occ = df dataframes[zone] = pd.concat([df_th, df_occ], axis=1) return dataframes