juham-automation 0.1.2__tar.gz → 0.1.4__tar.gz
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.
- {juham_automation-0.1.2/juham_automation.egg-info → juham_automation-0.1.4}/PKG-INFO +11 -7
- {juham_automation-0.1.2 → juham_automation-0.1.4}/README.rst +6 -2
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/automation/energycostcalculator.py +106 -63
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/automation/heatingoptimizer.py +120 -63
- {juham_automation-0.1.2 → juham_automation-0.1.4/juham_automation.egg-info}/PKG-INFO +11 -7
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation.egg-info/requires.txt +1 -1
- {juham_automation-0.1.2 → juham_automation-0.1.4}/pyproject.toml +7 -9
- juham_automation-0.1.4/tests/automation/test_energycostcalculator.py +272 -0
- juham_automation-0.1.4/tests/automation/test_heatingoptimizer.py +333 -0
- juham_automation-0.1.2/tests/automation/test_energycostcalculator.py +0 -118
- juham_automation-0.1.2/tests/automation/test_heatingoptimizer.py +0 -134
- {juham_automation-0.1.2 → juham_automation-0.1.4}/LICENSE.rst +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/MANIFEST.in +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/examples/myapp.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/__init__.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/automation/__init__.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/automation/energybalancer.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/automation/powermeter_simulator.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/automation/spothintafi.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/automation/watercirculator.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/japp.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/py.typed +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/ts/__init__.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/ts/electricityprice_ts.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/ts/energybalancer_ts.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/ts/energycostcalculator_ts.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/ts/forecast_ts.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/ts/log_ts.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/ts/power_ts.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/ts/powermeter_ts.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation/ts/powerplan_ts.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation.egg-info/SOURCES.txt +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation.egg-info/dependency_links.txt +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation.egg-info/entry_points.txt +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/juham_automation.egg-info/top_level.txt +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/setup.cfg +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/tests/__init__.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/tests/automation/__init__.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/tests/automation/test_energybalancer.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/tests/automation/test_juham.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/tests/automation/test_spothintafi.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/tests/test_japp.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/tests/ts/__init__.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/tests/ts/test_energycostcalculator_ts.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/tests/ts/test_forecast_ts.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/tests/ts/test_log_ts.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/tests/ts/test_power_ts.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/tests/ts/test_powermeter_ts.py +0 -0
- {juham_automation-0.1.2 → juham_automation-0.1.4}/tests/ts/test_powerplan_ts.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: juham-automation
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Juha's Ultimate Home Automation Masterpiece
|
|
5
5
|
Author-email: J Meskanen <juham.api@gmail.com>
|
|
6
6
|
Maintainer-email: "J. Meskanen" <juham.api@gmail.com>
|
|
@@ -30,11 +30,11 @@ License: LICENSE
|
|
|
30
30
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
Project-URL: Homepage, https://gitlab.com/juham/juham/juham-automation
|
|
34
|
-
Project-URL: Bug Reports, https://gitlab.com/juham/juham/juham-
|
|
33
|
+
Project-URL: Homepage, https://gitlab.com/juham/juham/juham-automation
|
|
34
|
+
Project-URL: Bug Reports, https://gitlab.com/juham/juham/juham-automationt
|
|
35
35
|
Project-URL: Funding, https://meskanen.com
|
|
36
36
|
Project-URL: Say Thanks!, http://meskanen.com
|
|
37
|
-
Project-URL: Source, https://gitlab.com/juham/juham/juham-automation
|
|
37
|
+
Project-URL: Source, https://gitlab.com/juham/juham/juham-automation
|
|
38
38
|
Keywords: home,automation,juham
|
|
39
39
|
Classifier: Development Status :: 3 - Alpha
|
|
40
40
|
Classifier: Intended Audience :: Developers
|
|
@@ -44,7 +44,7 @@ Classifier: Programming Language :: Python :: 3.8
|
|
|
44
44
|
Requires-Python: >=3.8
|
|
45
45
|
Description-Content-Type: text/markdown
|
|
46
46
|
License-File: LICENSE.rst
|
|
47
|
-
Requires-Dist: juham_core>=0.1.
|
|
47
|
+
Requires-Dist: juham_core>=0.1.6
|
|
48
48
|
Provides-Extra: dev
|
|
49
49
|
Requires-Dist: check-manifest; extra == "dev"
|
|
50
50
|
Requires-Dist: coverage>=7.0; extra == "dev"
|
|
@@ -56,9 +56,11 @@ Welcome to Juham™ - Juha's Ultimate Home Automation Masterpiece
|
|
|
56
56
|
Project Description
|
|
57
57
|
-------------------
|
|
58
58
|
|
|
59
|
-
This package extends the ``juham_core`` package, providing home automation building blocks that address most common needs.
|
|
59
|
+
This package extends the ``juham_core`` package, providing home automation building blocks that address most common needs.
|
|
60
|
+
It consists of two main sub-modules:
|
|
60
61
|
|
|
61
62
|
``automation``:
|
|
63
|
+
|
|
62
64
|
- **spothintafi**: Acquires electricity prices in Finland.
|
|
63
65
|
- **watercirculator**: Automates a water circulator pump based on hot water temperature and motion detection.
|
|
64
66
|
- **heatingoptimizer**: Controls hot water radiators based on temperature sensors and electricity price data.
|
|
@@ -66,6 +68,7 @@ This package extends the ``juham_core`` package, providing home automation build
|
|
|
66
68
|
- **energybalancer**: Handles real-time energy balancing and net billing.
|
|
67
69
|
|
|
68
70
|
``ts``:
|
|
71
|
+
|
|
69
72
|
- This folder contains time series recorders that listen for Juham™ topics and store the data in a time series database for later inspection.
|
|
70
73
|
|
|
71
74
|
Project Status
|
|
@@ -73,7 +76,8 @@ Project Status
|
|
|
73
76
|
|
|
74
77
|
**Current State**: **Alpha (Status 3)**
|
|
75
78
|
|
|
76
|
-
All classes have been tested to some extent, and no known bugs have been reported. However, the code still requires
|
|
79
|
+
All classes have been tested to some extent, and no known bugs have been reported. However, the code still requires
|
|
80
|
+
work in terms of design and robustness.
|
|
77
81
|
|
|
78
82
|
|
|
79
83
|
Project Links
|
|
@@ -4,9 +4,11 @@ Welcome to Juham™ - Juha's Ultimate Home Automation Masterpiece
|
|
|
4
4
|
Project Description
|
|
5
5
|
-------------------
|
|
6
6
|
|
|
7
|
-
This package extends the ``juham_core`` package, providing home automation building blocks that address most common needs.
|
|
7
|
+
This package extends the ``juham_core`` package, providing home automation building blocks that address most common needs.
|
|
8
|
+
It consists of two main sub-modules:
|
|
8
9
|
|
|
9
10
|
``automation``:
|
|
11
|
+
|
|
10
12
|
- **spothintafi**: Acquires electricity prices in Finland.
|
|
11
13
|
- **watercirculator**: Automates a water circulator pump based on hot water temperature and motion detection.
|
|
12
14
|
- **heatingoptimizer**: Controls hot water radiators based on temperature sensors and electricity price data.
|
|
@@ -14,6 +16,7 @@ This package extends the ``juham_core`` package, providing home automation build
|
|
|
14
16
|
- **energybalancer**: Handles real-time energy balancing and net billing.
|
|
15
17
|
|
|
16
18
|
``ts``:
|
|
19
|
+
|
|
17
20
|
- This folder contains time series recorders that listen for Juham™ topics and store the data in a time series database for later inspection.
|
|
18
21
|
|
|
19
22
|
Project Status
|
|
@@ -21,7 +24,8 @@ Project Status
|
|
|
21
24
|
|
|
22
25
|
**Current State**: **Alpha (Status 3)**
|
|
23
26
|
|
|
24
|
-
All classes have been tested to some extent, and no known bugs have been reported. However, the code still requires
|
|
27
|
+
All classes have been tested to some extent, and no known bugs have been reported. However, the code still requires
|
|
28
|
+
work in terms of design and robustness.
|
|
25
29
|
|
|
26
30
|
|
|
27
31
|
Project Links
|
|
@@ -6,6 +6,7 @@ from juham_core import Juham
|
|
|
6
6
|
from juham_core.timeutils import (
|
|
7
7
|
elapsed_seconds_in_day,
|
|
8
8
|
elapsed_seconds_in_hour,
|
|
9
|
+
elapsed_seconds_in_interval,
|
|
9
10
|
quantize,
|
|
10
11
|
timestamp,
|
|
11
12
|
)
|
|
@@ -28,17 +29,20 @@ class EnergyCostCalculator(Juham):
|
|
|
28
29
|
_kwh_to_joule_coeff: float = 1000.0 * 3600
|
|
29
30
|
_joule_to_kwh_coeff: float = 1.0 / _kwh_to_joule_coeff
|
|
30
31
|
|
|
31
|
-
energy_balancing_interval:
|
|
32
|
+
energy_balancing_interval: int = 900 # in seconds (15 minutes)
|
|
32
33
|
|
|
33
34
|
def __init__(self, name: str = "ecc") -> None:
|
|
34
35
|
super().__init__(name)
|
|
35
36
|
self.current_ts: float = 0
|
|
37
|
+
self.total_balance_interval : float = 0
|
|
36
38
|
self.total_balance_hour: float = 0
|
|
37
39
|
self.total_balance_day: float = 0
|
|
40
|
+
self.net_energy_balance_cost_interval: float = 0
|
|
38
41
|
self.net_energy_balance_cost_hour: float = 0
|
|
39
42
|
self.net_energy_balance_cost_day: float = 0
|
|
40
|
-
self.
|
|
41
|
-
self.
|
|
43
|
+
self.net_energy_balance_start_interval : float = elapsed_seconds_in_interval(timestamp(), self.energy_balancing_interval)
|
|
44
|
+
self.net_energy_balance_start_hour : float = elapsed_seconds_in_hour(timestamp())
|
|
45
|
+
self.net_energy_balance_start_day : float = elapsed_seconds_in_day(timestamp())
|
|
42
46
|
self.spots: list[dict[str, float]] = []
|
|
43
47
|
self.init_topics()
|
|
44
48
|
|
|
@@ -68,10 +72,10 @@ class EnergyCostCalculator(Juham):
|
|
|
68
72
|
self.error(f"Unknown event {msg.topic}")
|
|
69
73
|
|
|
70
74
|
def on_spot(self, spot: dict[Any, Any]) -> None:
|
|
71
|
-
"""Stores the received per
|
|
75
|
+
"""Stores the received per slot electricity prices to spots list.
|
|
72
76
|
|
|
73
77
|
Args:
|
|
74
|
-
spot (list): list of
|
|
78
|
+
spot (list): list of spot prices
|
|
75
79
|
"""
|
|
76
80
|
|
|
77
81
|
for s in spot:
|
|
@@ -88,76 +92,91 @@ class EnergyCostCalculator(Juham):
|
|
|
88
92
|
"""
|
|
89
93
|
return price * self._joule_to_kwh_coeff
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
|
|
96
|
+
def get_price_at(self, ts: float) -> float:
|
|
97
|
+
"""Return the spot price applicable at the given timestamp.
|
|
94
98
|
|
|
95
99
|
Args:
|
|
96
|
-
|
|
97
|
-
|
|
100
|
+
ts (float): current time (epoch seconds)
|
|
101
|
+
|
|
98
102
|
Returns:
|
|
99
|
-
|
|
103
|
+
float: PriceWithTax for the slot that contains ts. Returns the last
|
|
104
|
+
known price if ts is equal/after the last spot timestamp.
|
|
105
|
+
Returns 0.0 and logs an error if no matching slot is found.
|
|
100
106
|
"""
|
|
101
|
-
|
|
102
|
-
|
|
107
|
+
if not self.spots:
|
|
108
|
+
self.error(f"PANIC: no spot prices available; lookup ts={ts}")
|
|
109
|
+
return 0.0
|
|
110
|
+
|
|
111
|
+
# ensure spots sorted by timestamp (defensive)
|
|
112
|
+
try:
|
|
113
|
+
# cheap check — assumes list of dicts with "Timestamp"
|
|
114
|
+
if any(self.spots[i]["Timestamp"] > self.spots[i + 1]["Timestamp"] for i in range(len(self.spots) - 1)):
|
|
115
|
+
self.spots.sort(key=lambda r: r["Timestamp"])
|
|
116
|
+
except Exception:
|
|
117
|
+
# if unexpected structure, still try safe path below and log
|
|
118
|
+
self.debug("get_price_at: spot list structure unexpected while checking sort order", "")
|
|
103
119
|
|
|
104
120
|
for i in range(0, len(self.spots) - 1):
|
|
105
121
|
r0 = self.spots[i]
|
|
106
122
|
r1 = self.spots[i + 1]
|
|
107
123
|
ts0 = r0["Timestamp"]
|
|
108
124
|
ts1 = r1["Timestamp"]
|
|
109
|
-
if
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
125
|
+
if ts >= ts0 and ts < ts1:
|
|
126
|
+
return r0["PriceWithTax"]
|
|
127
|
+
|
|
128
|
+
# If timestamp is exactly equal to the last spot timestamp or beyond
|
|
129
|
+
last = self.spots[-1]
|
|
130
|
+
if ts >= last["Timestamp"]:
|
|
131
|
+
return last["PriceWithTax"]
|
|
132
|
+
|
|
133
|
+
# If we get here, ts is before the first spot timestamp
|
|
134
|
+
first = self.spots[0]
|
|
135
|
+
self.error(
|
|
136
|
+
f"PANIC: Timestamp {ts} out of bounds for spot price lookup; "
|
|
137
|
+
f"first=(ts={first['Timestamp']}, price={first.get('PriceWithTax')}), "
|
|
138
|
+
f"last=(ts={last['Timestamp']}, price={last.get('PriceWithTax')}), "
|
|
139
|
+
f"len(spots)={len(self.spots)}"
|
|
140
|
+
)
|
|
141
|
+
return 0.0
|
|
142
|
+
|
|
143
|
+
|
|
117
144
|
|
|
118
145
|
def calculate_net_energy_cost(
|
|
119
146
|
self, ts_prev: float, ts_now: float, energy: float
|
|
120
147
|
) -> float:
|
|
121
|
-
"""
|
|
122
|
-
|
|
148
|
+
"""
|
|
149
|
+
Calculate the cost (or revenue) of energy consumed/produced over the given time interval.
|
|
150
|
+
Positive values indicate revenue, negative values indicate cost.
|
|
123
151
|
|
|
124
152
|
Args:
|
|
125
|
-
ts_prev (
|
|
126
|
-
ts_now (
|
|
127
|
-
energy (float):
|
|
153
|
+
ts_prev (float): Start timestamp of the interval
|
|
154
|
+
ts_now (float): End timestamp of the interval
|
|
155
|
+
energy (float): Energy consumed during the interval (in watts or Joules)
|
|
156
|
+
|
|
128
157
|
Returns:
|
|
129
|
-
|
|
158
|
+
float: Total cost/revenue for the interval
|
|
130
159
|
"""
|
|
131
|
-
cost
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
ts_0 = quantize(self.energy_balancing_interval, now)
|
|
149
|
-
t1 = (ts_0 - prev) / elapsed
|
|
150
|
-
t2 = (now - ts_0) / elapsed
|
|
151
|
-
cost = (
|
|
152
|
-
cost
|
|
153
|
-
+ energy
|
|
154
|
-
* ((1.0 - t1) * start_price + t2 * stop_price)
|
|
155
|
-
* elapsed_seconds
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
prev = prev + elapsed_seconds
|
|
160
|
+
cost = 0.0
|
|
161
|
+
current = ts_prev
|
|
162
|
+
interval = self.energy_balancing_interval
|
|
163
|
+
|
|
164
|
+
while current < ts_now:
|
|
165
|
+
next_ts = min(ts_now, current + interval)
|
|
166
|
+
# Get spot price at start and end of interval
|
|
167
|
+
price_start = self.map_kwh_prices_to_joules(self.get_price_at(current))
|
|
168
|
+
price_end = self.map_kwh_prices_to_joules(self.get_price_at(next_ts))
|
|
169
|
+
|
|
170
|
+
# Trapezoidal integration: average price over interval
|
|
171
|
+
avg_price = (price_start + price_end) / 2.0
|
|
172
|
+
dt = next_ts - current
|
|
173
|
+
cost += energy * avg_price * dt
|
|
174
|
+
|
|
175
|
+
current = next_ts
|
|
176
|
+
|
|
159
177
|
return cost
|
|
160
178
|
|
|
179
|
+
|
|
161
180
|
def on_powerconsumption(self, ts_now: float, m: dict[Any, Any]) -> None:
|
|
162
181
|
"""Calculate net energy cost and update the hourly consumption attribute
|
|
163
182
|
accordingly.
|
|
@@ -170,21 +189,29 @@ class EnergyCostCalculator(Juham):
|
|
|
170
189
|
if not self.spots:
|
|
171
190
|
self.info("Waiting for electricity prices...")
|
|
172
191
|
elif self.current_ts == 0:
|
|
192
|
+
self.net_energy_balance_cost_interval = 0.0
|
|
173
193
|
self.net_energy_balance_cost_hour = 0.0
|
|
174
194
|
self.net_energy_balance_cost_day = 0.0
|
|
175
195
|
self.current_ts = ts_now
|
|
176
|
-
self.
|
|
196
|
+
self.net_energy_balance_start_interval = quantize(
|
|
177
197
|
self.energy_balancing_interval, ts_now
|
|
178
198
|
)
|
|
199
|
+
self.net_energy_balance_start_hour = quantize(
|
|
200
|
+
3600, ts_now
|
|
201
|
+
)
|
|
179
202
|
else:
|
|
180
203
|
# calculate cost of energy consumed/produced
|
|
181
204
|
dp: float = self.calculate_net_energy_cost(self.current_ts, ts_now, power)
|
|
205
|
+
self.net_energy_balance_cost_interval = self.net_energy_balance_cost_interval + dp
|
|
182
206
|
self.net_energy_balance_cost_hour = self.net_energy_balance_cost_hour + dp
|
|
183
207
|
self.net_energy_balance_cost_day = self.net_energy_balance_cost_day + dp
|
|
184
208
|
|
|
185
209
|
# calculate and publish energy balance
|
|
186
210
|
dt = ts_now - self.current_ts # time elapsed since previous call
|
|
187
211
|
balance = dt * power # energy consumed/produced in this slot in Joules
|
|
212
|
+
self.total_balance_interval = (
|
|
213
|
+
self.total_balance_interval + balance * self._joule_to_kwh_coeff
|
|
214
|
+
)
|
|
188
215
|
self.total_balance_hour = (
|
|
189
216
|
self.total_balance_hour + balance * self._joule_to_kwh_coeff
|
|
190
217
|
)
|
|
@@ -195,16 +222,32 @@ class EnergyCostCalculator(Juham):
|
|
|
195
222
|
self.publish_energy_cost(
|
|
196
223
|
ts_now,
|
|
197
224
|
self.name,
|
|
225
|
+
self.net_energy_balance_cost_interval,
|
|
198
226
|
self.net_energy_balance_cost_hour,
|
|
199
227
|
self.net_energy_balance_cost_day,
|
|
200
228
|
)
|
|
201
229
|
|
|
202
230
|
# Check if the current energy balancing interval has ended
|
|
203
231
|
# If so, reset the net_energy_balance attribute for the next interval
|
|
204
|
-
if
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
232
|
+
if ts_now - self.net_energy_balance_start_interval > self.energy_balancing_interval:
|
|
233
|
+
# publish average energy cost per hour
|
|
234
|
+
if abs(self.total_balance_interval) > 0:
|
|
235
|
+
msg = {
|
|
236
|
+
"name": self.name,
|
|
237
|
+
"average_interval": self.net_energy_balance_cost_interval
|
|
238
|
+
/ self.total_balance_interval,
|
|
239
|
+
"ts": ts_now,
|
|
240
|
+
}
|
|
241
|
+
self.publish(self.topic_out_energy_cost, json.dumps(msg), 0, False)
|
|
242
|
+
|
|
243
|
+
# reset for the next hour
|
|
244
|
+
self.total_balance_interval = 0
|
|
245
|
+
self.net_energy_balance_cost_interval = 0.0
|
|
246
|
+
self.net_energy_balance_start_interval = ts_now
|
|
247
|
+
|
|
248
|
+
# Check if the current energy balancing interval has ended
|
|
249
|
+
# If so, reset the net_energy_balance attribute for the next interval
|
|
250
|
+
if ts_now - self.net_energy_balance_start_hour > 3600:
|
|
208
251
|
# publish average energy cost per hour
|
|
209
252
|
if abs(self.total_balance_hour) > 0:
|
|
210
253
|
msg = {
|
|
@@ -253,9 +296,9 @@ class EnergyCostCalculator(Juham):
|
|
|
253
296
|
self.publish(self.topic_out_net_energy_balance, json.dumps(msg), 1, True)
|
|
254
297
|
|
|
255
298
|
def publish_energy_cost(
|
|
256
|
-
self, ts_now: float, site: str, cost_hour: float, cost_day: float
|
|
299
|
+
self, ts_now: float, site: str, cost_interval : float, cost_hour: float, cost_day: float
|
|
257
300
|
) -> None:
|
|
258
|
-
"""Publish daily and
|
|
301
|
+
"""Publish daily, hourly and per interval energy cost/revenue
|
|
259
302
|
|
|
260
303
|
Args:
|
|
261
304
|
ts_now (float): timestamp
|
|
@@ -263,5 +306,5 @@ class EnergyCostCalculator(Juham):
|
|
|
263
306
|
cost_hour (float): cost or revenue per hour.
|
|
264
307
|
cost_day (float) : cost or revenue per day
|
|
265
308
|
"""
|
|
266
|
-
msg = {"name": site, "cost_hour": cost_hour, "cost_day": cost_day, "ts": ts_now}
|
|
309
|
+
msg = {"name": site, "cost_interval": cost_interval, "cost_hour": cost_hour, "cost_day": cost_day, "ts": ts_now}
|
|
267
310
|
self.publish(self.topic_out_energy_cost, json.dumps(msg), 1, True)
|