def __init__(self): building_zone_names_stub = xsg.get_building_zone_names_stub() self.supported_buildings = xsg.get_buildings(building_zone_names_stub) self.supported_zones = {} for bldg in self.supported_buildings: self.supported_zones[bldg] = xsg.get_zones( building_zone_names_stub, bldg)
def __init__(self): self.temperature_bands_stub = xsg.get_temperature_band_stub(TEMPERATURE_BANDS_HOST_ADDRESS) self.occupancy_stub = xsg.get_occupancy_stub(OCCUPANCY_HOST_ADDRESS) building_zone_names_stub = xsg.get_building_zone_names_stub(BUILDING_ZONE_NAMES_HOST_ADDRESS) self.supported_buildings = xsg.get_buildings(building_zone_names_stub) self.supported_zones = {} for bldg in self.supported_buildings: self.supported_zones[bldg] = xsg.get_zones(building_zone_names_stub, bldg)
def get_parameters(self, request): """ Storing and error checking request parameters. Parameters ---------- request : gRPC request Contains parameters to fetch data. Returns ------- str Error message. """ # Retrieve parameters from gRPC request object self.building_name = request.building self.end_time = datetime.datetime.utcfromtimestamp(float(request.end/1e9)).replace(tzinfo=pytz.utc) if request.window[-1] != 'm': return "invalid request, window can be only in min. correct format: \'15m\', \'5m\'..." self.window = int(request.window[:-1]) for dic in request.map_zone_state: self.map_zone_state[dic.zone] = dic.state if any(not elem for elem in [self.building_name, self.window, self.map_zone_state]): return "invalid request, empty param(s)" if request.building not in self.supported_buildings: return "invalid request, building not found, supported buildings:" + str(self.supported_buildings) self.zones = xbos_services_getter.get_zones(self.building_zone_names_stub, self.building_name) if set(self.map_zone_state.keys()) != set(self.zones): return "invalid request, specify all zones and their states in the building." # Add error checking for window if request.end < time.time(): return "invalid request, end time has to be in the future" with open(self.model_folder + self.building_name + '-model.json') as json_file: self.model_info = json.load(json_file) if self.end_time > self.round_minutes(UTC_TZ.localize(datetime.datetime.today()), 'down', self.window) + \ datetime.timedelta(minutes=self.model_info['num_future_minutes']): return "invalid request, end date is further than what model can predict" # # Other error checkings # duration = utils.get_window_in_sec(request.window) # if duration <= 0: # return None, "invalid request, duration is negative or zero" # if request.start + (duration * 1e9) > request.end: # return None, "invalid request, start date + window is greater than end date" return
def get_parameters(self, request): """ Storing and error checking request parameters. Parameters ---------- request : gRPC request Contains parameters to fetch data. Returns ------- str Error message. """ # CHECK: Move all error first and then do retrieve paramters from request obj. # Retrieve parameters from gRPC request object self.building_name = request.building self.window = request.window self.start_time = datetime.utcfromtimestamp(float(request.start/1e9)).replace(tzinfo=pytz.utc) self.end_time = datetime.utcfromtimestamp(float(request.end/1e9)).replace(tzinfo=pytz.utc) for dic in request.map_zone_state: self.map_zone_state[dic.zone] = dic.state # List of zones in building building_zone_names_stub = xbos_services_getter.get_building_zone_names_stub() self.zones = xbos_services_getter.get_zones(building_zone_names_stub, self.building_name) if set(self.map_zone_state.keys()) != set(self.zones): return "invalid request, specify all zones and their states of the building." if any(not elem for elem in [self.building_name, self.window, self.start_time, self.end_time]): return "invalid request, empty param(s)" # Add error checking for window if request.end > int((time.time() + _ONE_DAY_IN_SECONDS * 6) * 1e9): return "invalid request, end date is too far in the future, max is 6 days from now" if request.start < int(time.time() * 1e9): return "invalid request, start date is in the past." if request.start >= request.end: return "invalid request, start date is equal or after end date." if request.building not in self.supported_buildings: return "invalid request, building not found, supported buildings:" + str(self.supported_buildings)
def __init__(self, building, zones, start, end, window, non_controllable_data={}): """Exposes: - self.comfortband - self.do_not_exceed - self.occupancy - self.outdoor_temperature - self.discomfort_stub - self.hvac_consumption - self.price - self.all_zone_temperatures: pd.df with columns being zone names and values being F temperatures - self.start - self.unix_start - self.end - self.unix_end - self.window - self.building - self.zones :param building: :param zones: :param start: :param end: :param window: :param non_controllable_data: possible keys: ["comfortband", "do_not_exceed", "occupancy", "outdoor_temperature"] for each key the value needs to be a dictionary with {zone: data} for all zones in self.zones. Outdoor temperature is just data since it is data for the whole building. """ self.start = start self.unix_start = start.timestamp() * 1e9 self.end = end self.unix_end = end.timestamp() * 1e9 self.window = window # timedelta string self.building = building self.zones = zones if non_controllable_data is None: non_controllable_data = {} # TODO add error checking. check that the right zones are given in non_controllable_data and that the start/end/window are right. # Documentation: All data here is in timeseries starting exactly at start and every step corresponds to one # interval. The end is not inclusive. # temperature band temperature_band_stub = xsg.get_temperature_band_stub() if "comfortband" not in non_controllable_data: self.comfortband = { iter_zone: xsg.get_comfortband(temperature_band_stub, self.building, iter_zone, self.start, self.end, self.window) for iter_zone in self.zones} else: self.comfortband = non_controllable_data["comfortband"] err = check_data_zones(self.zones, self.comfortband, start, end, window) if err is not None: raise Exception("Bad comfortband given. " + err) if "do_not_exceed" not in non_controllable_data: self.do_not_exceed = { iter_zone: xsg.get_do_not_exceed(temperature_band_stub, self.building, iter_zone, self.start, self.end, self.window) for iter_zone in self.zones} else: self.do_not_exceed = non_controllable_data["do_not_exceed"] err = check_data_zones(self.zones, self.do_not_exceed, start, end, window) if err is not None: raise Exception("Bad DoNotExceed given. " + err) # occupancy if "occupancy" not in non_controllable_data: occupancy_stub = xsg.get_occupancy_stub() self.occupancy = { iter_zone: xsg.get_occupancy(occupancy_stub, self.building, iter_zone, self.start, self.end, self.window)["occupancy"] for iter_zone in self.zones} else: self.occupancy = non_controllable_data["occupancy"] err = check_data_zones(self.zones, self.occupancy, start, end, window) if err is not None: raise Exception("Bad occupancy given. " + err) # outdoor temperatures if "outdoor_temperature" not in non_controllable_data: outdoor_historic_stub = xsg.get_outdoor_temperature_historic_stub() self.outdoor_temperature = xsg.get_preprocessed_outdoor_temperature(outdoor_historic_stub, self.building, self.start, self.end, self.window)["temperature"] else: self.outdoor_temperature = non_controllable_data["outdoor_temperature"] err = xsg.check_data(self.outdoor_temperature, start, end, window, check_nan=True) if err is not None: raise Exception("Bad outdoor temperature given. " + err) # outdoor_prediction_channel = grpc.insecure_channel(OUTSIDE_PREDICTION) # outdoor_prediction_stub = outdoor_temperature_prediction_pb2_grpc.OutdoorTemperatureStub(outdoor_prediction_channel) # self.outdoor_temperatures = get_outside_temperature( # outdoor_historic_stub, outdoor_prediction_stub, self.building, self.start, self.end, self.window) # discomfort channel # self.discomfort_stub = xsg.get_discomfort_stub(secure=False) # HVAC Consumption TODO ERROR CHECK? hvac_consumption_stub = xsg.get_hvac_consumption_stub() self.hvac_consumption = {iter_zone: xsg.get_hvac_consumption(hvac_consumption_stub, building, iter_zone) for iter_zone in self.zones} if "energy_price" not in non_controllable_data: price_stub = xsg.get_price_stub() self.energy_price = xsg.get_price(price_stub, building, "ENERGY", start, end, window) else: self.energy_price = non_controllable_data["energy_price"] err = xsg.check_data(self.energy_price, start, end, window, check_nan=True) if err is not None: raise Exception("Bad energy prices given. " + err) self.indoor_temperature_prediction_stub = xsg.get_indoor_temperature_prediction_stub() indoor_historic_stub = xsg.get_indoor_historic_stub() # TEMPORARY -------- self.indoor_temperature_prediction = ThermalModel() # ------------ # +++++++++++++ TODO other zone temps uncomment when wanting to use real thermal model and delete uncommented section # # # get indoor temperature for other zones. # if "all_zone_temperature_data" not in non_controllable_data: # building_zone_names_stub = xsg.get_building_zone_names_stub() # all_zones = xsg.get_zones(building_zone_names_stub, building) # self.all_zone_temperature_data = {} # for iter_zone in all_zones: # # TODO there is an error with the indoor historic service where it doesn't return the full lenght of data. # zone_temperature = xsg.get_indoor_temperature_historic(indoor_historic_stub, building, iter_zone, start, end + datetime.timedelta(seconds=xsg.get_window_in_sec(window)), # window) # assert zone_temperature['unit'].values[0] == "F" # zone_temperature = zone_temperature["temperature"].squeeze() # self.all_zone_temperature_data[iter_zone] = zone_temperature.interpolate("time") # self.all_zone_temperature_data = pd.DataFrame(self.all_zone_temperature_data) # else: # self.all_zone_temperature_data = non_controllable_data["all_zone_temperature_data"] # err = check_data_zones(zones, self.all_zone_temperature_data, start, end, window, check_nan=True) # if err is not None: # if "Is missing zone" in err: # raise Exception("Bad indoor temperature data given. " + err) # else: # for iter_zone in zones: # err = xsg.check_data(self.all_zone_temperature_data[iter_zone], start, end, window, True) # if "Nan values in data." in err: # self.all_zone_temperature_data[iter_zone][:] = 70 # TODO only doing this if interpolation above does not work because everything is nan # else: # raise Exception("Bad indoor temperature data given. " + err) building_zone_names_stub = xsg.get_building_zone_names_stub() all_zones = xsg.get_zones(building_zone_names_stub, building) temp_pd = pd.Series(data=0, index = pd.date_range(start, end, freq=str(xsg.get_window_in_sec(window)) + "S")) self.all_zone_temperature_data = {iter_zone: temp_pd for iter_zone in all_zones} err = check_data_zones(zones, self.all_zone_temperature_data, start, end, window, check_nan=True) if err is not None: raise Exception("Bad indoor temperature data given. " + err) self.all_zone_temperature_data = pd.DataFrame(self.all_zone_temperature_data)
def get_preprocessed_data(building, zone, start, end, window, raw_data_granularity="1m"): """Get training data to use for indoor temperature prediction. :param building: (str) building name :param zone: (str) zone name :param start: (datetime timezone aware) :param end: (datetime timezone aware) :param window: (str) the intervals in which to split data. :param raw_data_granularity: (str) the intervals in which to get raw indoor data. :return: pd.df index= start (inclusive) to end (not inclusive) with frequency given by window. col=["t_in", "action", "t_out", "t_next", "occ", "action_duration", "action_prev", "temperature_zone_...", "dt"]. TODO explain meaning of each feature somewhere. """ # get indoor temperature and action for current zone indoor_historic_stub = xsg.get_indoor_historic_stub() indoor_temperatures = _get_indoor_temperature_historic(indoor_historic_stub, building, zone, start, end, raw_data_granularity) assert indoor_temperatures['unit'].values[0] == "F" indoor_temperatures = indoor_temperatures["temperature"].squeeze() indoor_actions = _get_action_historic(indoor_historic_stub, building, zone, start, end, raw_data_granularity) indoor_actions = indoor_actions["action"].squeeze() # get indoor temperature for other zones. building_zone_names_stub = xsg.get_building_zone_names_stub() all_zones = xsg.get_zones(building_zone_names_stub, building) all_other_zone_temperature_data = {} for iter_zone in all_zones: if iter_zone != zone: other_zone_temperature = _get_indoor_temperature_historic(indoor_historic_stub, building, iter_zone, start, end, window) assert other_zone_temperature['unit'].values[0] == "F" other_zone_temperature = other_zone_temperature["temperature"].squeeze() all_other_zone_temperature_data[iter_zone] = other_zone_temperature # Preprocessing indoor data putting temperature and action data together. indoor_data = pd.concat([indoor_temperatures.to_frame(name="t_in"), indoor_actions.to_frame(name="action")], axis=1) preprocessed_data = preprocess_indoor_data(indoor_data, xsg.get_window_in_sec(window)) if preprocessed_data is None: return None, "No data left after preprocessing." # get historic outdoor temperatures outdoor_historic_stub = xsg.get_outdoor_temperature_historic_stub() outdoor_historic_temperatures = xsg.get_outdoor_temperature_historic(outdoor_historic_stub, building, start, end, window) # getting occupancy # get occupancy occupancy_stub = xsg.get_occupancy_stub() occupancy = xsg.get_occupancy(occupancy_stub, building, zone, start, end, window) # add outdoor and occupancy and other zone temperatures preprocessed_data["t_out"] = [outdoor_historic_temperatures.loc[ idx: idx + datetime.timedelta(seconds=xsg.get_window_in_sec(window))].mean() for idx in preprocessed_data.index] preprocessed_data["occ"] = [occupancy.loc[ idx: idx + datetime.timedelta(seconds=xsg.get_window_in_sec(window))].mean() for idx in preprocessed_data.index] for iter_zone, iter_data in all_other_zone_temperature_data.items(): preprocessed_data["temperature_zone_" + iter_zone] = [ iter_data.loc[idx: idx + datetime.timedelta(seconds=xsg.get_window_in_sec(window))].mean() for idx in preprocessed_data.index] # TODO check if we should drop nan values... or at least where they are coming from preprocessed_data = preprocessed_data.dropna(axis=0) return preprocessed_data, None