emhass 0.5.1__py3-none-any.whl → 0.6.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
emhass/command_line.py CHANGED
@@ -488,7 +488,7 @@ def publish_data(input_data_dict: dict, logger: logging.Logger,
488
488
  custom_deferrable_forecast_id = params['passed_data']['custom_deferrable_forecast_id']
489
489
  for k in range(input_data_dict['opt'].optim_conf['num_def_loads']):
490
490
  if "P_deferrable{}".format(k) not in opt_res_latest.columns:
491
- logger.error("P_deferrable{}".format(k)+" was not found in results DataFrame. Optimization task may need to be relaunched or it did not converged to a solution.")
491
+ logger.error("P_deferrable{}".format(k)+" was not found in results DataFrame. Optimization task may need to be relaunched or it did not converge to a solution.")
492
492
  else:
493
493
  input_data_dict['rh'].post_data(opt_res_latest["P_deferrable{}".format(k)], idx_closest,
494
494
  custom_deferrable_forecast_id[k]["entity_id"],
@@ -500,7 +500,7 @@ def publish_data(input_data_dict: dict, logger: logging.Logger,
500
500
  # Publish battery power
501
501
  if input_data_dict['opt'].optim_conf['set_use_battery']:
502
502
  if 'P_batt' not in opt_res_latest.columns:
503
- logger.error("P_batt was not found in results DataFrame. Optimization task may need to be relaunched or it did not converged to a solution.")
503
+ logger.error("P_batt was not found in results DataFrame. Optimization task may need to be relaunched or it did not converge to a solution.")
504
504
  else:
505
505
  custom_batt_forecast_id = params['passed_data']['custom_batt_forecast_id']
506
506
  input_data_dict['rh'].post_data(opt_res_latest['P_batt'], idx_closest,
@@ -536,15 +536,15 @@ def publish_data(input_data_dict: dict, logger: logging.Logger,
536
536
  custom_cost_fun_id["friendly_name"],
537
537
  type_var = 'cost_fun',
538
538
  publish_prefix = publish_prefix)
539
- # Publish the optimization status (A work in progress, will be available on future release)
540
- '''
539
+ # Publish the optimization status
541
540
  custom_cost_fun_id = params['passed_data']['custom_optim_status_id']
542
- input_data_dict['rh'].post_data(input_data_dict['opt'].optim_status, idx_closest,
541
+ input_data_dict['rh'].post_data(opt_res_latest['optim_status'], idx_closest,
543
542
  custom_cost_fun_id["entity_id"],
544
543
  custom_cost_fun_id["unit_of_measurement"],
545
544
  custom_cost_fun_id["friendly_name"],
546
545
  type_var = 'optim_status',
547
- publish_prefix = publish_prefix)'''
546
+ publish_prefix = publish_prefix)
547
+ cols_published = cols_published+["optim_status"]
548
548
  # Publish unit_load_cost
549
549
  custom_unit_load_cost_id = params['passed_data']['custom_unit_load_cost_id']
550
550
  input_data_dict['rh'].post_data(opt_res_latest['unit_load_cost'], idx_closest,
emhass/forecast.py CHANGED
@@ -315,7 +315,8 @@ class forecast(object):
315
315
  # Define index
316
316
  data.set_index('ts', inplace=True)
317
317
  else:
318
- self.logger.error("Passed method is not valid")
318
+ self.logger.error("Method %r is not valid", method)
319
+ data = None
319
320
  return data
320
321
 
321
322
  def cloud_cover_to_irradiance(self, cloud_cover: pd.Series,
emhass/optimization.py CHANGED
@@ -204,10 +204,10 @@ class optimization:
204
204
  for i in set_I)
205
205
  elif self.costfun == 'cost':
206
206
  if self.optim_conf['set_total_pv_sell']:
207
- objective = plp.lpSum(-0.001*self.timeStep*unit_load_cost[i]*P_grid_pos[i]
207
+ objective = plp.lpSum(-0.001*self.timeStep*unit_load_cost[i]*(P_load[i] + P_def_sum[i])
208
208
  for i in set_I)
209
209
  else:
210
- objective = plp.lpSum(-0.001*self.timeStep*unit_load_cost[i]*(P_load[i] + P_def_sum[i])
210
+ objective = plp.lpSum(-0.001*self.timeStep*unit_load_cost[i]*P_grid_pos[i]
211
211
  for i in set_I)
212
212
  elif self.costfun == 'self-consumption':
213
213
  if type_self_conso == 'bigm':
@@ -387,25 +387,24 @@ class optimization:
387
387
 
388
388
  ## Finally, we call the solver to solve our optimization model:
389
389
  # solving with default solver CBC
390
- try:
391
- if self.lp_solver == 'PULP_CBC_CMD':
392
- opt_model.solve(PULP_CBC_CMD(msg=0))
393
- elif self.lp_solver == 'GLPK_CMD':
394
- opt_model.solve(GLPK_CMD(msg=0))
395
- elif self.lp_solver == 'COIN_CMD':
396
- opt_model.solve(COIN_CMD(msg=0, path=self.lp_solver_path))
397
- else:
398
- self.logger.error("Invalid solver name passed")
399
- except Exception:
400
- self.logger.error("It was not possible to find a valid solver for Pulp package")
390
+ if self.lp_solver == 'PULP_CBC_CMD':
391
+ opt_model.solve(PULP_CBC_CMD(msg=0))
392
+ elif self.lp_solver == 'GLPK_CMD':
393
+ opt_model.solve(GLPK_CMD(msg=0))
394
+ elif self.lp_solver == 'COIN_CMD':
395
+ opt_model.solve(COIN_CMD(msg=0, path=self.lp_solver_path))
396
+ else:
397
+ self.logger.warning("Solver %s unknown, using default", self.lp_solver)
398
+ opt_model.solve()
401
399
 
402
400
  # The status of the solution is printed to the screen
403
401
  self.optim_status = plp.LpStatus[opt_model.status]
404
402
  self.logger.info("Status: " + self.optim_status)
405
403
  if plp.value(opt_model.objective) is None:
406
- self.logger.warning("Cost function cannot be evaluated, probably None")
404
+ self.logger.warning("Cost function cannot be evaluated")
405
+ return
407
406
  else:
408
- self.logger.info("Total value of the Cost function = " + str(round(plp.value(opt_model.objective),2)))
407
+ self.logger.info("Total value of the Cost function = %.02f", plp.value(opt_model.objective))
409
408
 
410
409
  # Build results Dataframe
411
410
  opt_tp = pd.DataFrame()
@@ -450,7 +449,10 @@ class optimization:
450
449
  opt_tp["cost_fun_profit"] = [-0.001*self.timeStep*(unit_load_cost[i]*P_grid_pos[i].varValue + \
451
450
  unit_prod_price[i]*P_grid_neg[i].varValue) for i in set_I]
452
451
  elif self.costfun == 'cost':
453
- opt_tp["cost_fun_cost"] = [-0.001*self.timeStep*unit_load_cost[i]*(P_load[i] + P_def_sum_tp[i]) for i in set_I]
452
+ if self.optim_conf['set_total_pv_sell']:
453
+ opt_tp["cost_fun_cost"] = [-0.001*self.timeStep*unit_load_cost[i]*(P_load[i] + P_def_sum_tp[i]) for i in set_I]
454
+ else:
455
+ opt_tp["cost_fun_cost"] = [-0.001*self.timeStep*unit_load_cost[i]*P_grid_pos[i].varValue for i in set_I]
454
456
  elif self.costfun == 'self-consumption':
455
457
  if type_self_conso == 'maxmin':
456
458
  opt_tp["cost_fun_selfcons"] = [-0.001*self.timeStep*unit_load_cost[i]*SC[i].varValue for i in set_I]
@@ -459,6 +461,9 @@ class optimization:
459
461
  unit_prod_price[i]*P_grid_neg[i].varValue) for i in set_I]
460
462
  else:
461
463
  self.logger.error("The cost function specified type is not valid")
464
+
465
+ # Add the optimization status
466
+ opt_tp["optim_status"] = self.optim_status
462
467
 
463
468
  return opt_tp
464
469
 
emhass/retrieve_hass.py CHANGED
@@ -116,6 +116,9 @@ class retrieve_hass:
116
116
  response = get(url, headers=headers)
117
117
  except Exception:
118
118
  return "Request Get Error"
119
+ else:
120
+ if response.status_code > 299:
121
+ return f"Request Get Error: {response.status_code}"
119
122
  '''import bz2 # Uncomment to save a serialized data for tests
120
123
  import _pickle as cPickle
121
124
  with bz2.BZ2File("data/test_response_get_data_get_method.pbz2", "w") as f:
@@ -131,8 +134,8 @@ class retrieve_hass:
131
134
  self.logger.error("Retrieved empty Dataframe, check that correct day or variable names are passed")
132
135
  self.logger.error("Either the names of the passed variables are not correct or days_to_retrieve is larger than the recorded history of your sensor (check your recorder settings)")
133
136
  if i == 0: # Defining the DataFrame container
134
- from_date = pd.to_datetime(df_raw['last_changed']).min()
135
- to_date = pd.to_datetime(df_raw['last_changed']).max()
137
+ from_date = pd.to_datetime(df_raw['last_changed'], format="ISO8601").min()
138
+ to_date = pd.to_datetime(df_raw['last_changed'], format="ISO8601").max()
136
139
  ts = pd.to_datetime(pd.date_range(start=from_date, end=to_date, freq=self.freq),
137
140
  format='%Y-%d-%m %H:%M').round(self.freq)
138
141
  df_day = pd.DataFrame(index = ts)
@@ -140,7 +143,7 @@ class retrieve_hass:
140
143
  df_tp = df_raw.copy()[['state']].replace(
141
144
  ['unknown', 'unavailable', ''], np.nan).astype(float).rename(columns={'state': var})
142
145
  # Setting index, resampling and concatenation
143
- df_tp.set_index(pd.to_datetime(df_raw['last_changed']), inplace=True)
146
+ df_tp.set_index(pd.to_datetime(df_raw['last_changed'], format="ISO8601"), inplace=True)
144
147
  df_tp = df_tp.resample(self.freq).mean()
145
148
  df_day = pd.concat([df_day, df_tp], axis=1)
146
149
 
@@ -174,17 +177,14 @@ class retrieve_hass:
174
177
  :rtype: pandas.DataFrame
175
178
 
176
179
  """
177
- if load_negative: # Apply the correct sign to load power
178
- try:
180
+ try:
181
+ if load_negative: # Apply the correct sign to load power
179
182
  self.df_final[var_load+'_positive'] = -self.df_final[var_load]
180
- except KeyError:
181
- self.logger.error("Variable "+var_load+" was not found. This is typically because no data could be retrieved from Home Assistant")
182
- else:
183
- try:
183
+ else:
184
184
  self.df_final[var_load+'_positive'] = self.df_final[var_load]
185
- except KeyError:
186
- self.logger.error("Variable "+var_load+" was not found. This is typically because no data could be retrieved from Home Assistant")
187
- self.df_final.drop([var_load], inplace=True, axis=1)
185
+ self.df_final.drop([var_load], inplace=True, axis=1)
186
+ except KeyError:
187
+ self.logger.error("Variable "+var_load+" was not found. This is typically because no data could be retrieved from Home Assistant")
188
188
  if set_zero_min: # Apply minimum values
189
189
  self.df_final.clip(lower=0.0, inplace=True, axis=1)
190
190
  self.df_final.replace(to_replace=0.0, value=np.nan, inplace=True)
@@ -282,6 +282,8 @@ class retrieve_hass:
282
282
  state = np.round(data_df.sum()[0],2)
283
283
  elif type_var == 'unit_load_cost' or type_var == 'unit_prod_price':
284
284
  state = np.round(data_df.loc[data_df.index[idx]],4)
285
+ elif type_var == 'optim_status':
286
+ state = data_df.loc[data_df.index[idx]]
285
287
  else:
286
288
  state = np.round(data_df.loc[data_df.index[idx]],2)
287
289
  if type_var == 'power':
@@ -305,6 +307,14 @@ class retrieve_hass:
305
307
  elif type_var == 'mlforecaster':
306
308
  data = retrieve_hass.get_attr_data_dict(data_df, idx, entity_id, unit_of_measurement,
307
309
  friendly_name, "scheduled_forecast", state)
310
+ elif type_var == 'optim_status':
311
+ data = {
312
+ "state": state,
313
+ "attributes": {
314
+ "unit_of_measurement": unit_of_measurement,
315
+ "friendly_name": friendly_name
316
+ }
317
+ }
308
318
  else:
309
319
  data = {
310
320
  "state": "{:.2f}".format(state),
emhass/utils.py CHANGED
@@ -136,6 +136,7 @@ def treat_runtimeparams(runtimeparams: str, params: str, retrieve_hass_conf: dic
136
136
  'custom_batt_soc_forecast_id': {"entity_id": "sensor.soc_batt_forecast", "unit_of_measurement": "%", "friendly_name": "Battery SOC Forecast"},
137
137
  'custom_grid_forecast_id': {"entity_id": "sensor.p_grid_forecast", "unit_of_measurement": "W", "friendly_name": "Grid Power Forecast"},
138
138
  'custom_cost_fun_id': {"entity_id": "sensor.total_cost_fun_value", "unit_of_measurement": "", "friendly_name": "Total cost function value"},
139
+ 'custom_optim_status_id': {"entity_id": "sensor.optim_status", "unit_of_measurement": "", "friendly_name": "EMHASS optimization status"},
139
140
  'custom_unit_load_cost_id': {"entity_id": "sensor.unit_load_cost", "unit_of_measurement": "€/kWh", "friendly_name": "Unit Load Cost"},
140
141
  'custom_unit_prod_price_id': {"entity_id": "sensor.unit_prod_price", "unit_of_measurement": "€/kWh", "friendly_name": "Unit Prod Price"},
141
142
  'custom_deferrable_forecast_id': custom_deferrable_forecast_id,
@@ -339,6 +340,8 @@ def treat_runtimeparams(runtimeparams: str, params: str, retrieve_hass_conf: dic
339
340
  params['passed_data']['custom_grid_forecast_id'] = runtimeparams['custom_grid_forecast_id']
340
341
  if 'custom_cost_fun_id' in runtimeparams.keys():
341
342
  params['passed_data']['custom_cost_fun_id'] = runtimeparams['custom_cost_fun_id']
343
+ if 'custom_optim_status_id' in runtimeparams.keys():
344
+ params['passed_data']['custom_optim_status_id'] = runtimeparams['custom_optim_status_id']
342
345
  if 'custom_unit_load_cost_id' in runtimeparams.keys():
343
346
  params['passed_data']['custom_unit_load_cost_id'] = runtimeparams['custom_unit_load_cost_id']
344
347
  if 'custom_unit_prod_price_id' in runtimeparams.keys():
emhass/web_server.py CHANGED
@@ -5,7 +5,7 @@ from flask import Flask, request, make_response, render_template
5
5
  from jinja2 import Environment, PackageLoader
6
6
  from requests import get
7
7
  from waitress import serve
8
- from importlib.metadata import version
8
+ from importlib.metadata import version, PackageNotFoundError
9
9
  from pathlib import Path
10
10
  import os, json, argparse, pickle, yaml, logging
11
11
  from distutils.util import strtobool
@@ -265,9 +265,9 @@ if __name__ == "__main__":
265
265
  app.logger.error("options.json does not exists")
266
266
  DATA_PATH = "/share/" #"/data/"
267
267
  else:
268
- CONFIG_PATH = "/app/config_emhass.yaml"
268
+ CONFIG_PATH = os.getenv("CONFIG_PATH", default="/app/config_emhass.yaml")
269
269
  options = None
270
- DATA_PATH = "/app/data/"
270
+ DATA_PATH = os.getenv("DATA_PATH", default="/app/data/")
271
271
  config_path = Path(CONFIG_PATH)
272
272
  data_path = Path(DATA_PATH)
273
273
 
@@ -328,7 +328,7 @@ if __name__ == "__main__":
328
328
  else:
329
329
  costfun = os.getenv('LOCAL_COSTFUN', default='profit')
330
330
  logging_level = os.getenv('LOGGING_LEVEL', default='INFO')
331
- with open('/app/secrets_emhass.yaml', 'r') as file:
331
+ with open(os.getenv('SECRETS_PATH', default='/app/secrets_emhass.yaml'), 'r') as file:
332
332
  params_secrets = yaml.load(file, Loader=yaml.FullLoader)
333
333
  hass_url = params_secrets['hass_url']
334
334
 
@@ -364,5 +364,8 @@ if __name__ == "__main__":
364
364
  app.logger.info("Launching the emhass webserver at: http://"+web_ui_url+":"+str(port))
365
365
  app.logger.info("Home Assistant data fetch will be performed using url: "+hass_url)
366
366
  app.logger.info("The data path is: "+str(data_path))
367
- app.logger.info("Using core emhass version: "+version('emhass'))
367
+ try:
368
+ app.logger.info("Using core emhass version: "+version('emhass'))
369
+ except PackageNotFoundError:
370
+ app.logger.info("Using development emhass version")
368
371
  serve(app, host=web_ui_url, port=port, threads=8)
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021-2022 David HERNANDEZ
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,25 +1,24 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: emhass
3
- Version: 0.5.1
3
+ Version: 0.6.1
4
4
  Summary: An Energy Management System for Home Assistant
5
5
  Home-page: https://github.com/davidusb-geek/emhass
6
6
  Author: David HERNANDEZ
7
7
  Author-email: davidusb@gmail.com
8
- License: UNKNOWN
9
8
  Keywords: energy,management,optimization,hass
10
- Platform: UNKNOWN
11
9
  Classifier: Development Status :: 5 - Production/Stable
12
10
  Classifier: Intended Audience :: Developers
13
11
  Classifier: Topic :: Software Development :: Build Tools
14
12
  Classifier: License :: OSI Approved :: MIT License
15
13
  Classifier: Programming Language :: Python :: 3.10
16
14
  Classifier: Operating System :: OS Independent
17
- Requires-Python: >=3.9, <=3.10
15
+ Requires-Python: >=3.9, <3.12
18
16
  Description-Content-Type: text/markdown
17
+ License-File: LICENSE
19
18
  Requires-Dist: wheel
20
- Requires-Dist: numpy ==1.22.2
21
- Requires-Dist: scipy <1.9.0
22
- Requires-Dist: pandas ==1.4.1
19
+ Requires-Dist: numpy ==1.26
20
+ Requires-Dist: scipy ==1.11.3
21
+ Requires-Dist: pandas ==2.0.3
23
22
  Requires-Dist: pvlib >=0.10.1
24
23
  Requires-Dist: protobuf >=3.0.0
25
24
  Requires-Dist: pytz >=2021.1
@@ -27,8 +26,8 @@ Requires-Dist: requests >=2.25.1
27
26
  Requires-Dist: beautifulsoup4 >=4.9.3
28
27
  Requires-Dist: pulp >=2.4
29
28
  Requires-Dist: pyyaml >=5.4.1
30
- Requires-Dist: tables ==3.7.0
31
- Requires-Dist: skforecast ==0.10.1
29
+ Requires-Dist: tables ==3.9.1
30
+ Requires-Dist: skforecast ==0.11.0
32
31
 
33
32
  <div align="center">
34
33
  <br>
@@ -324,6 +323,26 @@ shell_command:
324
323
  ```
325
324
  And you should be careful that the list of dictionaries has the correct length, which is the number of defined deferrable loads.
326
325
 
326
+ ### Computed variables and published data
327
+
328
+ Below you can find a list of the variables resulting from EMHASS computation, showed in the charts, and then published to Home Assistant through the ```publish_data``` command:
329
+
330
+ | EMHASS variable | Definition | Home Assistant published sensor |
331
+ | --------------- | ---------- | --------------------------------|
332
+ | P_PV | Forecasted power generation from your solar panels (Watts). This helps you predict how much solar energy you will produce during the forecast period. | sensor.p_pv_forecast |
333
+ | P_Load | Forecasted household power consumption (Watts). This gives you an idea of how much energy your appliances are expected to use. | sensor.p_load_forecast |
334
+ | P_deferrableX [X = 0, 1, 2, ...] | Forecasted power consumption of deferrable loads (Watts). Deferable loads are appliances that can be managed by EMHASS. EMHASS helps you optimise energy usage by prioritising solar self-consumption and minimizing reliance on the grid or by taking advantage or supply and feed-in tariff volatility. You can have multiple deferable loads and you use this sensor in HA to control these loads via smart switch or other IoT means at your disposal. | sensor.p_deferrableX |
335
+ | P_grid_pos | Forecasted power imported from the grid (Watts). This indicates the amount of energy you are expected to draw from the grid when your solar production is insufficient to meet your needs or it is advantagous to consume from the grid. | - |
336
+ | P_grid_neg | Forecasted power exported to the grid (Watts). This indicates the amount of excess solar energy you are expected to send back to the grid during the forecast period. | - |
337
+ | P_batt | Forecasted (dis)charge power load (Watt) for the battery (if installed). If negative it indicates the battery is charging, if positive that the battery is discharging. | sensor.p_batt_forecast |
338
+ | P_grid | Forecasted net power flow between your home and the grid (Watts). This is calculated as P_grid_pos - P_grid_neg. A positive value indicates net export, while a negative value indicates net import. | sensor.p_grid_forecast |
339
+ | SOC_opt | Forecasted battery optimized Status Of Charge (SOC) percentage level | sensor.soc_batt_forecast |
340
+ | unit_load_cost | Forecasted cost per unit of energy you pay to the grid (typically "Currency"/kWh). This helps you understand the expected energy cost during the forecast period. | sensor.unit_load_cost |
341
+ | unit_prod_price | Forecasted price you receive for selling excess solar energy back to the grid (typically "Currency"/kWh). This helps you understand the potential income from your solar production. | sensor.unit_prod_price |
342
+ | cost_profit | Forecasted profit or loss from your energy usage for the forecast period. This is calculated as unit_load_cost * P_Load - unit_prod_price * P_grid_pos. A positive value indicates a profit, while a negative value indicates a loss. | sensor.total_cost_profit_value |
343
+ | cost_fun_cost | Forecasted cost associated with deferring loads to maximize solar self-consumption. This helps you evaluate the trade-off between managing the load and not managing and potential cost savings. | sensor.total_cost_fun_value |
344
+
345
+
327
346
  ## Passing your own data
328
347
 
329
348
  In EMHASS we have basically 4 forecasts to deal with:
@@ -448,5 +467,3 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
448
467
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
449
468
 
450
469
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
451
-
452
-
@@ -0,0 +1,16 @@
1
+ emhass/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ emhass/command_line.py,sha256=GCFwCVZ1sZkjGfLMJW8Ub_r1RIXnsLzjJ1l2IifYze4,36634
3
+ emhass/forecast.py,sha256=WTlsoan_IgzRKqm5Ri1mHOC2sLdlTv4kauNY03n8EPQ,43088
4
+ emhass/machine_learning_forecaster.py,sha256=Zhs8zcTn9E5yBNjdyYDPXjd2x6iQuqtL-QgaE74ODco,15633
5
+ emhass/optimization.py,sha256=Bj7m9UJr0kFqbMFsGAALw41ly1I7x8Jl_er4IYH5xfg,31481
6
+ emhass/retrieve_hass.py,sha256=4RqpwJDTyqTlyg6mez5yu3rx7sm2od5lrkCMzb8Db4k,17345
7
+ emhass/utils.py,sha256=SCDRHRG3JNcfSzm2S23DBJEzOuzaYGUhwKzzgqGtIYE,24057
8
+ emhass/web_server.py,sha256=jhNKo4Mi62g9-aNPzCQtGXbcPjDxC_Is_rvwJ97f1yg,20190
9
+ emhass/static/style.css,sha256=5qGJl0MZGSaSvr0HUcGQ9UgMtDKP2CiyE-1H-jbsLuU,6760
10
+ emhass/templates/index.html,sha256=6zXvh8KGZC3wUmyW5RrkMn1PsQkWDI2wtrbLv7VUPmc,3224
11
+ emhass-0.6.1.dist-info/LICENSE,sha256=1X3-S1yvOCBDBeox1aK3dq00m7dA8NDtcPrpKPISzbE,1077
12
+ emhass-0.6.1.dist-info/METADATA,sha256=ryVijY824OZ-rYzENbfwxqUtw1yA-R6OyVf-weluEC4,32059
13
+ emhass-0.6.1.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
14
+ emhass-0.6.1.dist-info/entry_points.txt,sha256=6Bp1NFOGNv_fSTxYl1ke3K3h3aqAcBxI-bgq5yq-i1M,52
15
+ emhass-0.6.1.dist-info/top_level.txt,sha256=L7fIX4awfmxQbAePtSdVg2e6x_HhghfReHfsKSpKr9I,7
16
+ emhass-0.6.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.2)
2
+ Generator: bdist_wheel (0.42.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,3 +1,2 @@
1
1
  [console_scripts]
2
2
  emhass = emhass.command_line:main
3
-
@@ -1,15 +0,0 @@
1
- emhass/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- emhass/command_line.py,sha256=59vdgjJ4sPDEnWlD2cehaLSrBU6E3qtvaVfmBvcisS0,36657
3
- emhass/forecast.py,sha256=3zqFIKwfu5cjGGLDGUZ-j1eMu8sWlSAc679oGmIwPeo,43060
4
- emhass/machine_learning_forecaster.py,sha256=Zhs8zcTn9E5yBNjdyYDPXjd2x6iQuqtL-QgaE74ODco,15633
5
- emhass/optimization.py,sha256=FURVCVt0lWSIX2DYF8GEGu8FuwqL4kp42hS7uVO8ekQ,31299
6
- emhass/retrieve_hass.py,sha256=TRECIc_ZohY1MOVC5t7UjB0t9Ke3gNIn6x8ZrnBMGUo,16969
7
- emhass/utils.py,sha256=F8b_8SHAjQDCDgk0w1WS6b3oQKdEUXkhiNSe2_9ufGs,23729
8
- emhass/web_server.py,sha256=KFrsvHLeM3ShCUpnZx_InysJ194My3HHGoVc5cS1zo4,19961
9
- emhass/static/style.css,sha256=5qGJl0MZGSaSvr0HUcGQ9UgMtDKP2CiyE-1H-jbsLuU,6760
10
- emhass/templates/index.html,sha256=6zXvh8KGZC3wUmyW5RrkMn1PsQkWDI2wtrbLv7VUPmc,3224
11
- emhass-0.5.1.dist-info/METADATA,sha256=eoUSC-ioYEfxP01Lbq9fOXScDIegvDrLLc0sTrz6gEw,28913
12
- emhass-0.5.1.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
13
- emhass-0.5.1.dist-info/entry_points.txt,sha256=tJULCm7mHGYb_IxyzPN_4KFYvhxv209_jq68jPiByy0,53
14
- emhass-0.5.1.dist-info/top_level.txt,sha256=L7fIX4awfmxQbAePtSdVg2e6x_HhghfReHfsKSpKr9I,7
15
- emhass-0.5.1.dist-info/RECORD,,