Welcome to ecoControl’s documentation!¶
NOTE: The documentation is work in progress.
Contents:
Getting Started¶
ecoControl is based on open-source tools and frameworks such as Django and PostgreSQL which makes it easy to deploy. In order to be able to start ecoControl, all requirements need to be installed and a server needs to be configured.
Install Requirements¶
To automatically install all dependencies on a Linux machine, make sure that pip and bower are installed and run the following commands:
pip install -r requirements.txt bower install
How to Run ecoControl Locally¶
This section is still in process.
How to Deploy ecoControl¶
This section is still in process.
REST API Documentation¶
The ecoControl server communicates through a REST-API only.
List of All API End Points¶
API End Point | Description |
---|---|
General | |
api/ | Starting point |
api/export/ | CSV-Export function |
api/login/ | Login end point |
api/logout/ | Logout end point |
api/notifications/ | Get notifications list |
api/sensors/ | Get sensors list |
api/settings/ | Get settings list |
api/status/ | Get system status |
Technician | |
api/configure/ | Set configurations |
api/data/(monthly|yearly)/ | Get sensor data |
api/forecast/ | Get forecast |
api/forward/ | forward |
api/live/ | Get live data |
api/settings/tunable/ | Get tunable settings |
api/snippets/ | Manage snippets |
api/code/ | Manage code |
api/start/ | Start system |
api/statistics/(monthly/) | Get statistics |
api/thresholds/ | Manage thresholds |
api/automoptimize/ | Manage auto optimization |
Manager | |
api/avgs/ | Get sensor averages |
api/balance/total/(latest/) | Get balances |
api/history/ | Get history |
api/loads/ | Get loads |
api/sensor/ | Get sensor details |
api/sums/ | Get sensor sums |
General¶
Bla
CSV-Export function¶
/api/export
POST¶
Reflects post data and starts a CSV file download.
Param | Description |
---|---|
name | Name of the service |
description | Description of service |
POST /api/export
curl
Login end point¶
Logout end point¶
Get notifications list¶
Get sensors list¶
Get settings list¶
Get system status¶
Models¶
- class Configuration(*args, **kwargs)[source]¶
Configuration(id, key, value, value_type, unit, internal)
- BOOL = 4¶
- DATE = 3¶
- exception DoesNotExist¶
- Configuration.FLOAT = 2¶
- Configuration.INT = 1¶
- exception Configuration.MultipleObjectsReturned¶
- Configuration.STR = 0¶
- Configuration.TYPES = ((0, 'str'), (1, 'int'), (2, 'float'), (3, 'date'), (4, 'bool'))¶
- Configuration.get_value_type_display(*moreargs, **morekwargs)¶
- Configuration.objects = <django.db.models.manager.Manager object at 0x7ffec804db50>¶
- class Device(*args, **kwargs)[source]¶
Device(id, name, device_type)
- CU = 2¶
- DEVICE_TYPES = ((0, 'HeatStorage'), (1, 'PowerMeter'), (2, 'CogenerationUnit'), (3, 'PeakLoadBoiler'), (4, 'ThermalConsumer'), (5, 'ElectricalConsumer'))¶
- exception DoesNotExist¶
- Device.EC = 5¶
- Device.HS = 0¶
- exception Device.MultipleObjectsReturned¶
- Device.PLB = 3¶
- Device.PM = 1¶
- Device.TC = 4¶
- Device.deviceconfiguration_set¶
- Device.get_device_type_display(*moreargs, **morekwargs)¶
- Device.objects = <django.db.models.manager.Manager object at 0x7ffec804d6d0>¶
- Device.sensor_set¶
- class DeviceConfiguration(*args, **kwargs)[source]¶
Does not inherit from Configuration because of bulk creation
- BOOL = 4¶
- DATE = 3¶
- exception DoesNotExist¶
- DeviceConfiguration.FLOAT = 2¶
- DeviceConfiguration.INT = 1¶
- exception DeviceConfiguration.MultipleObjectsReturned¶
- DeviceConfiguration.STR = 0¶
- DeviceConfiguration.TYPES = ((0, 'str'), (1, 'int'), (2, 'float'), (3, 'date'), (4, 'bool'))¶
- DeviceConfiguration.device¶
- DeviceConfiguration.get_value_type_display(*moreargs, **morekwargs)¶
- DeviceConfiguration.objects = <django.db.models.manager.Manager object at 0x7ffec8060150>¶
- class Notification(*args, **kwargs)[source]¶
Notification(id, threshold_id, sensor_value_id, target, read)
- exception DoesNotExist¶
- exception Notification.MultipleObjectsReturned¶
- Notification.objects = <django.db.models.manager.Manager object at 0x7ffec7ffaf90>¶
- Notification.sensor_value¶
- Notification.threshold¶
- class RealWeatherValue(*args, **kwargs)[source]¶
RealWeatherValue(id, temperature, timestamp)
- exception DoesNotExist¶
- exception RealWeatherValue.MultipleObjectsReturned¶
- RealWeatherValue.get_next_by_timestamp(*moreargs, **morekwargs)¶
- RealWeatherValue.get_previous_by_timestamp(*moreargs, **morekwargs)¶
- RealWeatherValue.objects = <django.db.models.manager.Manager object at 0x7ffec806b310>¶
- class Sensor(*args, **kwargs)[source]¶
Sensor(id, device_id, name, key, setter, unit, in_diagram, aggregate_sum, aggregate_avg)
- exception DoesNotExist¶
- exception Sensor.MultipleObjectsReturned¶
- Sensor.device¶
- Sensor.objects = <django.db.models.manager.Manager object at 0x7ffec8060790>¶
- Sensor.sensorvalue_set¶
- Sensor.sensorvaluedaily_set¶
- Sensor.sensorvaluehourly_set¶
- Sensor.sensorvaluemonthlyavg_set¶
- Sensor.sensorvaluemonthlysum_set¶
- Sensor.threshold_set¶
- class SensorValue(*args, **kwargs)[source]¶
SensorValue(id, sensor_id, value, timestamp)
- exception DoesNotExist¶
- exception SensorValue.MultipleObjectsReturned¶
- SensorValue.get_next_by_timestamp(*moreargs, **morekwargs)¶
- SensorValue.get_previous_by_timestamp(*moreargs, **morekwargs)¶
- SensorValue.notification_set¶
- SensorValue.objects = <django.db.models.manager.Manager object at 0x7ffec8060c10>¶
- SensorValue.sensor¶
- class SensorValueDaily(*args, **kwargs)[source]¶
SensorValueDaily(id, sensor_id, timestamp, value)
- exception DoesNotExist¶
- exception SensorValueDaily.MultipleObjectsReturned¶
- SensorValueDaily.get_next_by_timestamp(*moreargs, **morekwargs)¶
- SensorValueDaily.get_previous_by_timestamp(*moreargs, **morekwargs)¶
- SensorValueDaily.objects = <django.db.models.manager.Manager object at 0x7ffec806bbd0>¶
- SensorValueDaily.sensor¶
- class SensorValueHourly(*args, **kwargs)[source]¶
SensorValueHourly(id, sensor_id, timestamp, value)
- exception DoesNotExist¶
- exception SensorValueHourly.MultipleObjectsReturned¶
- SensorValueHourly.get_next_by_timestamp(*moreargs, **morekwargs)¶
- SensorValueHourly.get_previous_by_timestamp(*moreargs, **morekwargs)¶
- SensorValueHourly.objects = <django.db.models.manager.Manager object at 0x7ffec806b790>¶
- SensorValueHourly.sensor¶
- class SensorValueMonthlyAvg(*args, **kwargs)[source]¶
SensorValueMonthlyAvg(id, sensor_id, timestamp, avg)
- exception DoesNotExist¶
- exception SensorValueMonthlyAvg.MultipleObjectsReturned¶
- SensorValueMonthlyAvg.get_next_by_timestamp(*moreargs, **morekwargs)¶
- SensorValueMonthlyAvg.get_previous_by_timestamp(*moreargs, **morekwargs)¶
- SensorValueMonthlyAvg.objects = <django.db.models.manager.Manager object at 0x7ffec7ffa510>¶
- SensorValueMonthlyAvg.sensor¶
- class SensorValueMonthlySum(*args, **kwargs)[source]¶
SensorValueMonthlySum(id, sensor_id, timestamp, sum)
- exception DoesNotExist¶
- exception SensorValueMonthlySum.MultipleObjectsReturned¶
- SensorValueMonthlySum.get_next_by_timestamp(*moreargs, **morekwargs)¶
- SensorValueMonthlySum.get_previous_by_timestamp(*moreargs, **morekwargs)¶
- SensorValueMonthlySum.objects = <django.db.models.manager.Manager object at 0x7ffec7ffa090>¶
- SensorValueMonthlySum.sensor¶
- class Threshold(*args, **kwargs)[source]¶
Threshold(id, sensor_id, name, category, show_manager, min_value, max_value)
- Danger = 5¶
- Default = 0¶
- exception DoesNotExist¶
- Threshold.Info = 3¶
- exception Threshold.MultipleObjectsReturned¶
- Threshold.Primary = 1¶
- Threshold.Success = 2¶
- Threshold.TYPES = ((0, 'Default'), (1, 'Primary'), (2, 'Success'), (3, 'Info'), (4, 'Warning'), (5, 'Danger'))¶
- Threshold.Warning = 4¶
- Threshold.get_category_display(*moreargs, **morekwargs)¶
- Threshold.notification_set¶
- Threshold.objects = <django.db.models.manager.Manager object at 0x7ffec7ffaa50>¶
- Threshold.sensor¶
- class WeatherValue(*args, **kwargs)[source]¶
WeatherValue(id, temperature, timestamp, target_time)
- exception DoesNotExist¶
- exception WeatherValue.MultipleObjectsReturned¶
- WeatherValue.get_next_by_target_time(*moreargs, **morekwargs)¶
- WeatherValue.get_next_by_timestamp(*moreargs, **morekwargs)¶
- WeatherValue.get_previous_by_target_time(*moreargs, **morekwargs)¶
- WeatherValue.get_previous_by_timestamp(*moreargs, **morekwargs)¶
- WeatherValue.objects = <django.db.models.manager.Manager object at 0x7ffec8060fd0>¶
Devices¶
This module represents the energy systems.
The hardware interface should orient at the base classes of the devices. The simulation in server.forecasting.systems is also based on these classes.
- class BaseEnvironment(initial_time=None, step_size=120, demomode=False, forecast=False)[source]¶
This class manages the environment of the devices holds the simulated time as well as the mode, the devices are running in. All connected devices share one BaseEnvironment
- demo_mode = None¶
↓ forecast | demo_mode → True False True forecast of simulated devices forecast of real devices False demo simulation real device (env not defined)
- forecast = None¶
see demo_mode
- initial_date = None¶
a unix timestamp representing the start of simulation if initial_time is None the current time is used
- step_size = None¶
int value of seconds how often the simulated devices calculate their state
- class CogenerationUnit(device_id, env)[source]¶
Represents a basic interface to a cogeneration unit. The configuration is read from the database and can be set from the frontend. The following parameters are available:
Parameters: - max_gas_input (float) – in kW
- thermal_efficiency (float) – in percent between 0 and 1 calculated by the maximal thermal power and gas input
- electrical_efficiency (float) – in percent between 0 and 1 calculated by the maximal electrical power and gas input
- minimal_workload (float) – in percent between 0 and 1 used for modulation
- minimal_off_time (float) – minimal time between to power-ons in seconds
- purchase_price (float) – in Euro
- purchase_date (date) – to calculate armotization
- maintenance_interval_hours (int) – operating hours until maintenance is necessary
- maintenance_interval_powerons (int) – maximal power-ons until maintenance is necessary
- current_electrical_production = None¶
kW
- current_gas_consumption = None¶
kW
- current_thermal_production = None¶
kWh
- gas_costs = None¶
default 0.0655 Euro per kWh
- get_operating_costs()[source]¶
Calculated by the consumed gas and maintenance costs (0.05 Euro per electric produced kWh).
- total_electrical_production = None¶
kWh
- total_gas_consumption = None¶
kWh
- total_thermal_production = None¶
kWh
- class PeakLoadBoiler(device_id, env)[source]¶
Represents a basic interface to a cogeneration unit. The configuration is read from the database and can be set from the frontend. The following parameters are available:
Parameters: - max_gas_input (float) – in kW
- thermal_efficiency (float) – in percent between 0 and 1 calculated by the maximal thermal power and gas input
- current_gas_consumption = None¶
kW
- current_thermal_production = None¶
kWh
- gas_costs = None¶
default 0.0655 Euro
- total_gas_consumption = None¶
kWh
- total_thermal_production = None¶
kWh
- class CogenerationUnit(device_id, env)[source]
Represents a basic interface to a cogeneration unit. The configuration is read from the database and can be set from the frontend. The following parameters are available:
Parameters: - max_gas_input (float) – in kW
- thermal_efficiency (float) – in percent between 0 and 1 calculated by the maximal thermal power and gas input
- electrical_efficiency (float) – in percent between 0 and 1 calculated by the maximal electrical power and gas input
- minimal_workload (float) – in percent between 0 and 1 used for modulation
- minimal_off_time (float) – minimal time between to power-ons in seconds
- purchase_price (float) – in Euro
- purchase_date (date) – to calculate armotization
- maintenance_interval_hours (int) – operating hours until maintenance is necessary
- maintenance_interval_powerons (int) – maximal power-ons until maintenance is necessary
- connected()[source]
The device needs a PowerMeter and a HeatStorage to operate properly.
- current_electrical_production = None
kW
- current_gas_consumption = None
kW
- current_thermal_production = None
kWh
- gas_costs = None
default 0.0655 Euro per kWh
- get_operating_costs()[source]
Calculated by the consumed gas and maintenance costs (0.05 Euro per electric produced kWh).
- total_electrical_production = None
kWh
- total_gas_consumption = None
kWh
- total_thermal_production = None
kWh
- workload(workload=None)[source]
Getter and setter for the workload.
Parameters: workload (float) – between 0-100, if None nothing is set Returns: current workload in percent [0,100]
- class PeakLoadBoiler(device_id, env)[source]
Represents a basic interface to a cogeneration unit. The configuration is read from the database and can be set from the frontend. The following parameters are available:
Parameters: - max_gas_input (float) – in kW
- thermal_efficiency (float) – in percent between 0 and 1 calculated by the maximal thermal power and gas input
- connected()[source]
The device needs a HeatStorage to operate properly.
- current_gas_consumption = None
kW
- current_thermal_production = None
kWh
- gas_costs = None
default 0.0655 Euro
- get_operating_costs()[source]
Calculated by the consumed gas.
- total_gas_consumption = None
kWh
- total_thermal_production = None
kWh
- workload_percent(workload=None)[source]
Getter and setter for the workload.
Parameters: workload (float) – between 0-100, if None nothing is set Returns: current workload in [0,100]
- class ThermalConsumer(device_id, env)[source]¶
This class represents the thermal consume of the house. The demand is calculated by the necessary heating power and the required warm water. The house parameters are read from the database and can be set from the frontend. The following parameters are available:
Parameters: - apartments (int) – number of apartments in the house
- avg_rooms_per_apartment (int) – average number of rooms
- avg_windows_per_room (int) – average number of windows
- type_of_windows (int) – isolation value between MISSING
- total_living_area (int) – in square meters
- type_of_housing (int) – isolation value between MISSING
- residents (int) –
- type_of_residents (int) – used to classify thermal demand MISSING RANGE
- target_temperature (int) – requested temperature of the rooms in degree Celsius
- avg_thermal_consumption (int) – in kWh
- daily_demand = None¶
list of 24 values representing target_temperature per hour
- room_height = None¶
constant room height
- temperature_warmwater = None¶
temperature of warm water 40 degrees Celsius by default
- class ElectricalConsumer(device_id, env)[source]¶
This class represents the electrical consume of the house. The demand is calculated by the forecasting in :mod:server.forecasting.forecasting The house parameters are read from the database and can be set from the frontend. The following parameters are available:
Parameters: - apartments (int) – number of apartments in the house
- residents (int) –
- type_of_residents (int) – used to classify thermal demand MISSING RANGE
- avg_electrical_consumption (int) – in kWh
- class HeatStorage(device_id, env)[source]¶
Represents a heat storage necessary to supply heating and warm water demand. The temperatures of the storage are as average and measured in degree Celsius. The configuration is read from the database and can be set from the frontend. The following parameters are available:
Parameters: - capacity (int) – in liters
- min_temperature (float) – below this temperature the PeakLoadBoiler will turn on
- target_temperature (float) – the HS schould always have this temperature
- critical_temperature (float) – above this temperature all production devices are turned off
- base_temperature = None¶
assume no lower temperature
- specific_heat_capacity = None¶
specific heat capacity of water 4.19 J/(g*K)
- class PowerMeter(device_id, env)[source]¶
Represents the power meter of the whole building. Measures the purchased and fed in electricity in kWh
- consume_energy(energy)[source]¶
This counts up the consumed energy.
Parameters: energy (float) – in kWh
- electrical_costs = None¶
costs in Euro to purchase 1 kW/h from external supplier (default 0.283)
- energy_consumed = None¶
set by consumer devices with consume_energy
- energy_produced = None¶
set by producer devices with add_energy
- fed_in_electricity = None¶
since last step
- feed_in_reward = None¶
reward in Euro for feed in 1 kW/h to public grid (default 0.0917)
- get_costs()[source]¶
Calculated by overall purchased electricity and default costs of 0.283 Euro per kWh
- get_reward()[source]¶
Calculated by overall fed in electricity and the default reward of 0.0917 Euro per kWh. Sale to tenants is not considered here.
- purchased = None¶
since last step
- get_initialized_scenario()[source]¶
The function returns a list of energy systems based on the configuration in the database
Returns: list of objects from server.forecasting.systems
- get_user_function(devices, code=None)[source]¶
Builds a method with the users code from the programming-interface.
Parameters: - systems – list of devices from :func:get_initialized_scenario:
- code – string with the user-code
Returns: callable user-function expecting a pointer to a systems list as argument
Forecasting¶
This package contains the simulation and methods for creating forecasts. They are split into statistical forecasts and weather forecast.
Simulation¶
- class SimulatedCogenerationUnit(device_id, env)[source]¶
The simulation of a cogeneration unit
- get_efficiency_loss_factor()[source]¶
Computes efficiency loss on modulation and returns left efficiency in percent [0,1]
- get_electrical_energy_production()[source]¶
Returns produced electrical energy in kWh during current time-step
- get_thermal_energy_production()[source]¶
Returns produced thermal energy in kWh during current time-step
- off_time = None¶
Saves the last powered off time to ensure minimal_off_time
- overwrite_workload = None¶
Efficiency is reached only on maximum workload at minumum workload the efficiency is decreased by 15 %
- class SimulatedPeakLoadBoiler(device_id, env)[source]¶
The simulation of a peak load boiler
- calculate_workload()[source]¶
Switches on when the heat storage is undersupplied and off if target temperature is reached. Also detects power-ons and tracks operating time.
- get_thermal_energy_production()[source]¶
Returns produced thermal energy in kWh during current time-step
- off_time = None¶
Saves the last power off time to ensure 3 min off-time
- overwrite_workload = None¶
Device can have fixed workload without internal control. Be aware of overheating!
- class SimulatedThermalConsumer(device_id, env)[source]¶
The simulation of the thermal consume (heating and warm water) of a house
Usied formulas from http://www.model.in.tum.de/um/research/groups/ai/fki-berichte/postscript/fki-227-98.pdf and http://www.inference.phy.cam.ac.uk/is/papers/DanThermalModellingBuildings.pdf
- calculate()[source]¶
Update the heating parameters when a house parameter is changed. Therefore some assumptions are made
- get_consumption_energy()[source]¶
Returns consumed thermal energy for heating in kWh during current time-step
- get_outside_temperature()[source]¶
The thermal energy demand depends on the outside temperature. For the current simulated time (self.env.now) the outside temperature is returned.
- get_warmwater_consumption_energy()[source]¶
Returns needed thermal energy for warm water in kWh during current time-step
- get_warmwater_consumption_power()[source]¶
The energy needed for warm water is calculated by the amount of needed liters in average. For the time step the power is calculated which could heat the needed water of all residents to the given temperature (40 degrees Celsius default).
- heat_apartments()[source]¶
Increases the rooms temperature. With the current heating power an amount of energy for the current time-step is produced. This energy and the specific heat capacity of air (1000 J/(m^3 * K)) is needed for the temperature calculation.
- heat_loss_power()[source]¶
Returns the power in kW by with the house loses thermal energy at outer walls and windows. The outside temperature is needed for the temperature difference.
- class SimulatedElectricalConsumer(device_id, env)[source]¶
The simulation of the electrical consume of a house based on forecasting.
- class SimulatedHeatStorage(device_id, env)[source]¶
The simulation of a heat storage
- empty_count = None¶
count the steps when mimium temperature is undershot
- get_target_energy()[source]¶
Returns the overall energy needed for reaching the target temperature when the water is cold (base temperature)
- set_temperature(temperature)[source]¶
When the simulation is initialized to a real system the temperature of the real heat storage must be set
- temperature_loss = None¶
temperature loss per day by default 3 degress Celsius
- class SimulatedPowerMeter(device_id, env)[source]¶
The simulation of a power meter
- add_energy(energy)[source]¶
Devices should use this method to supply electrical energy.
Parameters: energy (float) – in kWh
Statistical Forecasting¶
This module contains the statistical forecasting initiation and management.
The base class for all forecastings is StatisticalForecast , to generate forecasts one of the following subclasses has to be used
StatisticalForecast(env, input_data[, ...]) | This is the abstract class for statistical forecasting. |
DSHWForecast(env, input_data[, ...]) | This forecast uses the double seasonal exponential smoothing method. |
DayTypeForecast(env, input_data[, ...]) | This forecast splits the demands into 7 weekdays and minimizes and forecasts each with the holt-winters multiplicative method. |
- class StatisticalForecast(env, input_data, samples_per_hour=1, start=None, try_cache=True, **kwargs)[source]¶
This is the abstract class for statistical forecasting. Statistical forecasts use exponential smoothing methods to forecast timeseries into the future. These methods rely on the right parameters to make a realistic forecast. The parameters can be passed to the function, if they are omitted they are found by minimizing the MSE.
Forecastings are calculated after contruction of class and then whenever needed, which is set by forecast_update_interval.
Parameters: - input_data (list) – list of consecutive values sampled in samples_per_hour
- start (datetime) – start date of input data
- samples_per_hour (int) – Number of samples per hour in input_data
- try_cache (boolean) – Read and Save forecasts to a cache on the file device to avoid unneccesary recomputation, is True by default.
- **kwargs – Any instance variable can be overwritten with a keyword from here, f.e. input_weeks = 14. Will be set before any data is processed. Only use, if you know what your doing.
Variables: - forecast_update_interval (int) – The time in seconds for how long forecasts stay valid. When this interval is passed, a new forecast is calculated.
- input_weeks (int) – only forecast with this many weeks of data, default are 12 weeks.
- output_weeks (int) – the forecast will cover this many weeks of future data,default are 8 weeks.
- demands ([[],]) – the processed demands, depending on subclass this contains one or more series
- get_forecast_at(timestamp)[source]¶
Return the forecast at the (unix) timestamp.
Raise a IndexError if there is no forecast for the timestamp.
- process_inputdata(data, samples_per_hour, start)[source]¶
Preprocess and return the input demands. Needed for the division into weekdays in DayTypeForecast.
Parameters: start (datetime) – the time of the first datapoint. Only the day is of interest.
- forecast_demands()[source]¶
Forecast and return the demands. The forecasting method depends on the subclass.
- append_values(data, start_date=None)[source]¶
Pushes in new values and cuts off values at the beginning to keep input length. Will update the forecasts if needed.
- classmethod make_hourly(data, samples_per_hour)[source]¶
aggregates data series to 1hourly data.
Parameters: - data (list) – the series
- samples_per_hour (int) – number of samples per hour contained in data
Returns: list of 1hourly data
- classmethod MASE(training_series, testing_series, prediction_series)[source]¶
Computes the MEAN-ABSOLUTE SCALED ERROR forecast error for univariate time series prediction.
See “Another look at measures of forecast accuracy”, Rob J Hyndman
Parameters: - training_series (list) – the series used to train the model
- testing_series (list) – the test series to predict
- prediction_series (list) – the prediction of testing_series (same size as testing_series)
- update_if_needed()[source]¶
Internal Method Update the forecasts, if env.now is more than forecast_update_interval seconds ahead from last demand measurement
- read_from_cache()[source]¶
Internal Method Return a cached result. If try_cache = True, this will try to read from cache/cached_forecasts.cache. The results are only returned, if the timestamp of the forecast creation is not older than 24h. Else or if no cached file is available, None is returned.
Returns: list or None
Double-Seasonal Forecast¶
- class DSHWForecast(env, input_data, samples_per_hour=1, start=None, try_cache=True, **kwargs)[source]¶
Bases: server.forecasting.statistical.StatisticalForecast
This forecast uses the double seasonal exponential smoothing method. It often delivers better results than the DayTypeForecast.
- process_inputdata(data, samples_per_hour, start)[source]¶
See StatisticalForecast.process_inputdata() Dummy Method, returns array of data.
Day-Type Forecast¶
- class DayTypeForecast(env, input_data, samples_per_hour=1, start=None, try_cache=True, **kwargs)[source]¶
Bases: server.forecasting.statistical.StatisticalForecast
This forecast splits the demands into 7 weekdays and minimizes and forecasts each with the holt-winters multiplicative method.
- forecast_demands()[source]¶
See StatisticalForecast.forecast_demands(). This method uses processes, to speed up the calculation. This drives the cpu to full load for a short time.
- process_inputdata(data, samples_per_hour, start)[source]¶
See StatisticalForecast.process_inputdata() Splits the data into 7 arrays, one for each weekday.
Holt-Winters Methods¶
This module contains four exponential smoothing algorithms.
They are Holt’s linear trend method and Holt-Winters seasonal methods (additive and multiplicative). The fourth method is the double seasonal exponential smoothing method with AR(1) autocorrelation and no trend.
- References:
Hyndman, R. J.; Athanasopoulos, G. (2013) Forecasting: principles and practice. http://otexts.com/fpp/
Byrd, R. H.; Lu, P.; Nocedal, J. A Limited Memory Algorithm for Bound Constrained Optimization, (1995), SIAM Journal on Scientific and Statistical Computing, 16, 5, pp. 1190-1208.
Taylor, W James, (2003); Short-Term Electricity Demand Forecasting Using Double Seasonal Exponential Smoothing, Journal of the Operational Research Society
- linear(x, forecast, alpha=None, beta=None)[source]¶
Returns a forecast calculated with linear exponential smoothing. If alpha or beta are None, the method will optimize the MSE() and find the most suitable parameters. The method returns these optimized parameters and also the one-step-forecasts, for each value of x.
Parameters: - x (list) – the series to be forecasted
- forecast (int) – the timeperiod of the forecast. F.e. forecast=24*7 for one week (assuming hourly data)
- alpha (float) – the level component
- beta (float) – the trend component
Returns: (forecast, parameters, one-step-forecasts)
- additive(x, m, forecast, alpha=None, beta=None, gamma=None, initial_values_optimization=[0.002, 0.0, 0.0002], optimization_type='MSE')[source]¶
Returns a forecast calculated with the seasonal exponential smoothing method (additive Holt-Winters). This method will consider seasonality and can be configured by setting the length of the seasonality m. If alpha or beta or gamma are None, the method will optimize the MSE() and find the most suitable parameters. The method returns these optimized parameters and also the one-step-forecasts, for each value of x.
If optimization is used, a list of starting parameters can be supplied by initial_values_optimization. The algorithm will start searching in the neighbourhood of these values. It can’t be guaranteed, that all values in the boundaries (0,1) are considered.
Parameters: - x (list) – the series to be forecasted
- m (int) – the seasonality, f.e. m=24 for daily seasonality (a daily cycle in data is expected)
- forecast (int) – the timeperiod of the forecast. F.e. forecast=24*7 for one week (assuming hourly data)
- alpha (float) – the level component
- beta (float) – the trend component
- gamma (float) – the seasonal component component
- initial_values_optimization (list) – a first guess of the parameters to use when optimizing.
- optimization_criterion (string) –
type of minimization measure, if minimization is used
Returns: (forecast, parameters, one-step-forecasts)
- multiplicative(x, m, forecast, alpha=None, beta=None, gamma=None, initial_values_optimization=[0.002, 0.0, 0.0002], optimization_type='MSE')[source]¶
This method uses the multiplicative Holt-Winters method. It often delivers better results for our use-case than the additive method. For parameters, see additive() .
- double_seasonal(x, m, m2, forecast, alpha=None, beta=None, gamma=None, delta=None, autocorrelation=None, initial_values_optimization=[0.1, 0.0, 0.2, 0.2, 0.9], optimization_type='MSE')[source]¶
Returns a forecast calculated with the double seasonal holt-winters method ( Taylor 2003 ). This method considers two seasonalies. This is great for electrical demand forecasting, as demands have daily and weekly seasonalities. The method also uses autocorrelation, to forecast patterns in residuals. The trend component is ignored for this method, as electrical demands mostly dont have a trend.
For all parameters, see additive().
Parameters: - m (int) – intraday seasonality (m = 24, for hourly data)
- m2 (int) – intraweek seasonality (m = 24*7, for hourly data)
Returns: (forecast, parameters, one-step-forecasts)
- MSE(params, *args)[source]¶
Internal Method. Calculates the Mean Square Error of one run of holt-winters with the supplied arguments. The MSE is actually computed from the MSE of the one-step-forecast error and the error between the forecast and a testseries.
Parameters: - params (list) – (alpha, ...) the parameters
- *args (list) – (input_series, hw type, m), with hwtype in [0:3] depicting hw method
- MASE(params, *args)[source]¶
Calculates the Mean-Absolute Scaled Error (see server.forecasting.forecasting.StatisticalForecast.MASE()). For parameters see MSE().
Choltwinters — Holt-Winters Extensions¶
This module contains an optimized version of the Holt-Winters double-seasonal method and the multiplicative method.
The functions in this module should deliver the same results as the unoptimized version in holt_winters. Just import the double_seasonal() from this module instead of the one in holt_winters.py. This module has to be compiled with Cython, it introduces statically typed variables and optimizes array usage and can therefore get speedups up to 100x. Note that the optimizing function differs from the normal version, as it first searches the global boundaries and then does a extremely accurate local search. This leads to results very close to the absolute optimum.
To build this module, use the build_holtwinters_extension() function. If it suceeds, a .pyd extension is built, which can be used like a normal python module. An example for importing and building the extension can be seen in server.forecasting.forecasting (source).
Weather¶
This module handles crawling, storing and retrieving of weather values.
It is split into two Classes.
DemoWeather([env]) | Gets Weathervalues from the database. |
CurrentWeatherForecast([env, city]) | Gets the current Weatherforecast from an online service. |
- get_temperature(env, date)[source]¶
General function to retrieve forecasts. Will decide upon the env parameter, if DemoWeather or CurrentWeatherForecast should be used.
Parameters: - env (BaseEnvironment) – the current environment
- date (datetime) – the time of which to retrieve the weather(forecast)
- class DemoWeather(env=None)[source]¶
Gets Weathervalues from the database. The demo_mode operates on stored data from the past. For maximum realism, the past data should contain the real weather values as well as stored weather forecasts.
The data is stored in the database, with server.models.RealWeatherValue for history weather and server.models.WeatherValue for stored forecasts.
- get_temperature(date)[source]¶
Retrieve a temperature at a certain time. The class will cache the values after the first query to speed up subsequent requests.
Parameters: date (datetime) – The time Raises an Exception if there are no values in the database for the current time.
- get_temperature_estimate(target_date)[source]¶
Retrieve a forecasted temperature at a certain time. The target_date must be between 0 and 10 days away from the creation_date, as weather forecasts only cover 10 days.
The class will cache the values after the first query to speed up subsequent requests.
Parameters: date (datetime) – The timepoint
- class CurrentWeatherForecast(env=None, city='Berlin')[source]¶
Gets the current Weatherforecast from an online service. This is http://api.openweathermap.org/ at the moment, but may change in future versions.
- get_temperature_estimate(date)[source]¶
Get the most accurate forecast for given date that can be derived from 5 days forecast, 14 days forecast or from history data. This is the public getter for forecasts and should be used
Parameters: date (datetime) – the timepoint for which to get the forecast Returns: temperature (float)
- get_forecast_temperature_daily(date)[source]¶
get the forecast for given date. This only has day accuracy, but the forecast span is longer
- find_city(name)[source]¶
returns a dictionary with city id, names and country based on the given search name the first search result is returned as ‘default’ too.
Parameters: name (string) – f.e. “Berlin”
- get_weather_forecast(hourly=True)[source]¶
retrieves an entire forecast. Tries to get forecast from internal list or filesystem cache. If that fails or data is too old, the online service will be queried
- get_openweathermapdata()[source]¶
read from openweathermap. If this fails, use get_average_outside_temperature()
Helping functions for Forecasting¶
helpers¶
helper methods for forecasting
- approximate_index(dataset, findvalue)[source]¶
Return index value in dataset, with optimized find procedure. This assumes a dataset with continuous, increasing values. Typically, these are timestamps.
Parameters: - dataset (list) – a continuous list of values (f.e. timestamps)
- findvalue (int) – the value, of which to find the index.
- cached_data(name, data_function=None, max_age=0)[source]¶
store and retrieve data from a cache on the filesystem. The function will try to retrieve the cached data. If there is None or the data is too old, data_function will be called and the result is stored in the cache.
Parameters: - name (string) – name of cache file
- data_function (function) – A function, which outputs the data to be stored. If the function is None and the cache is invalid, the funtion will return None.
- max_age (int) – The maximum age (real time) in seconds, the cache is allowed to have before turning invalid.
Returns: data or None
dataloader¶
- class DataLoader[source]¶
This class reads data from CSV formatted in a specific way. The files are cached in memory to enable fast, re-reads
- classmethod load_from_file(filepath, column_name, delim='t', date_name='Datum', sampling_interval=600)[source]¶
load a time series from a csv file. This assumes, that the csv is formatted in the following way:
Date header Row Header1 Row Header2 Row Header N Timestamp0 Row1Value0 Row2Value0 RowNValue0 Timestamp1 ... ... ... If the values in the file isn’t sampled evenly, because it contains skips, blackouts, etc.. the data will be sampled evenly by copying certain data (see evenly_sampled()).
Parameters: - column_name (string) – The name of the column (in the csv) to retrieve
- delim (string) – The delimiter between values of a row. Default is Tab.
- date_name (string) – The name of the Date header of the date row
- sampling_interval (int) – The interval the data in the file is sampled.
- classmethod evenly_sampled(data, date_name='Datum', sampling_interval=600)[source]¶
Will return a version of data, in which every value has a corresponding timestamp, which is roughly sampling_interval seconds away from the last value. This is a maximum interval, if the data contains closer values together than sampling_interval, no actions will be taken.
The data which is used to fill up gaps is tried to gather intelligently. It is specifically designed for electrical data and takes values from one week ago, if present, else one day or the last value if everything else fails.
Parameters: - data (dict) – dictionary with column names as keys and column data as values
- date_name (string) – name of the date row
- sampling_interval (int) – the number of seconds between each consecutive sample
Forecasts¶
- class Forecast(initial_time, configurations=None, code=None, forward=None, forecast=True)[source]¶
Bases: threading.Thread
Setup a Forecast Object. A new BaseEnvironment and new Devices will be created. Forecasting can either be ran synchronous or asynchronous (threaded):
foocast = Forecast(time.time(), forward=10*24*3600) barcast = Forecast(time.time(), forward=2*24*3600) #run threaded barcast.start() #wait until foocast is finished, then get result resultfoo = foocast.run().get() # wait until barcast is finished while resultbar == None: resultbar = barcast.get()
Parameters: - initial_time (int) – timestamp of the time, at which the forecast starts
- configurations – cached configurations, if None, retrieve from database
- code – code to be executed
- forward (int) – Time to forecast. Uses DEFAULT_FORECAST_INTERVAL if None
- forecast (boolean) – Passed to BaseEnvironment forecast.
- get()[source]¶
return the result of the forecast. If the mainloop is still forecasting, None is returned.
outputs a dict with:
result = {start: datetime, step: stepsize, end: datetime, sensors: list with values per sensor (see MeasurementStorage)}
- class DemoSimulation(initial_time, configurations=None)[source]¶
Bases: server.forecasting.Forecast
A Forecast, which writes the values to the database. It replaces the real devices and is used to develop and show the capabilities of ecoControl. It uses real electrical and weather values instead of forecasts, the device simulation on the other hand is the same as in Forecast.
After calling start(), the simulation will currently run at 30 steps per second (or 30x speed). This is controlled by the step_size in BaseEnvironment.
The simulation can be forwarded to a certain point by setting the forward variable in seconds > 0. It will then run at maximum speed. The simulation runs until the variable running is set to False.
Note
DemoSimulations should generally be started with start_or_get()
- run()[source]¶
run while running is true, call the parent step() method. This method must be called by start(), otherwise it immediately returns
- classmethod start_or_get(print_visible=False)[source]¶
This method starts a new demo simulation if necessary and it makes sure that only one demo simulation can run at once. This is the preferred way to start the demo simulation.
Returns: DemoSimulation or None if system not in demo mode.
- class ForecastQueue[source]¶
A container, holding the running forecasts. Each forecast gets an id.
Usage:
q = ForecastQueue() f_id = q.schedule_new(initial_time=time.time()) #... do other stuff, then retrieve forecast result = q.get_by_id(f_id)
- get_initialized_scenario(env, configurations)[source]¶
this function returns an initialized scenario. It creates new simulated devices and connects the right devices.
The devices are restored to the latest state of the SensorValue‘s in the db, if there are no Values, a warning will be logged and the standard values are used.
Parameters: - env – BaseEnvironment for all Devices
- configurations (list) – the device configurations, which to set in the devices. These are typically DeviceConfiguration objects.
Returns: a namedtuple of devices, with the acronym (f.e plb), as key
Auto-Optimization¶
This module contains the algorithm for optimizing the costs of energy systems.
- DEFAULT_FORECAST_INTERVAL = 3600.0¶
The interval for how long one auto_optimize will forecast and for how long one specific workload is set. Note, that this constant also represents a compromise: Shorter intervals can adjust to quick changes, f.e. electricity demands changes, while longer intervals can incorporate more forecasts, but wont be able to adjust quickly. The interval of one hour lead to good results in our tests.
- auto_optimize(forecast)[source]¶
Tries to optimize the cost and sets the cu.overwrite_workload
The method forecasts from env.now with different cu workloads and finds the one with the lowest cost. The length of the forecast is DEFAULT_FORECAST_INTERVAL.
Parameters: forecast – the forecast to be optimized
- find_optimal_config(initial_time, forecast)[source]¶
Internal Method Main method, which optimizes the costs by running a global approximation for the best configuration and then running a local minimization method on this approximation
- estimate_cost(params, *args)[source]¶
Internal Method copies the devices and environment, forwards it and returns the costs.
Parameters: - params (list) – parameter to be optimized (CU.workload for now)
- args – (initial_time, forecast, prices, rewards)
- simplified_forecast(env, initial_time, devices)[source]¶
runs the forward loop only executing the step function
- total_costs(devices, prices, rewards)[source]¶
Internal Method Returns the cost of a forecast run. The function uses the prices which are stored in the db deviceconfiguration. It is also constrained by boundaries, f.e. the heatstorage should never go below min temperature.
Parameters: - devices – The devices after the forecast
- prices, rewards (dict) – Cached prices and rewards
Front End¶
The front end has been developed independently from the ecoControl server and communicates exclusively through the REST-API. It is based on jQuery and Twitter’s Bootstrap which provides an easy to use grid system and enables a responsive design. For all diagrams, the front end is using Highcharts and Highstock. The programming interface is based on Ace.
Structure¶
The front end can be found within the /static folder.
Folder | Description |
---|---|
css/ | Custom style sheets |
img/ | All images |
js/ | ecoControl specific Javascript code |
js/libs/ | Custom libraries |
js/mgmt/ | All Javascript code for the management views |
js/tech/ | All Javascript code for the technician views |
libs/ | Third party libraries |
templates/ | Mustache templates |
index.html | This is the starting point |
Multi-language Support¶
The front end is available in English and in German. The language files can be found in /static/js/ and are called lang.en.js and lang.de.js.