Skip to content

Commit a690b09

Browse files
committed
Add metric pvcontrol_car_energy_consumption_wh
- calculated on SOC value, counts only decrements
1 parent 51ebe2e commit a690b09

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

pvcontrol/car.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class CarData(BaseData):
2828
@dataclass
2929
class CarConfig(BaseConfig):
3030
cycle_time: int = 5 * 60 # [s] cycle time for reading car data, used by scheduler
31+
energy_one_percent_soc: int = 580 # [Wh]
3132

3233

3334
C = typing.TypeVar("C", bound=CarConfig) # type of configuration
@@ -39,10 +40,12 @@ class Car(BaseService[C, CarData]):
3940
_metrics_pvc_car_soc = prometheus_client.Gauge("pvcontrol_car_soc_ratio", "State of Charge")
4041
_metrics_pvc_car_range = prometheus_client.Gauge("pvcontrol_car_cruising_range_meters", "Remaining cruising range")
4142
_metrics_pvc_car_mileage = prometheus_client.Gauge("pvcontrol_car_mileage_meters", "Mileage")
43+
_metrics_pvc_car_energy_consumption = prometheus_client.Counter("pvcontrol_car_energy_consumption_wh", "Energy Consumption")
4244

4345
def __init__(self, config: C):
4446
super().__init__(config)
4547
self._set_data(CarData())
48+
self._last_soc = 0
4649

4750
def read_data(self) -> CarData:
4851
"""Read meter data and report metrics. The data is cached."""
@@ -51,6 +54,10 @@ def read_data(self) -> CarData:
5154
Car._metrics_pvc_car_soc.set(d.soc / 100)
5255
Car._metrics_pvc_car_range.set(d.cruising_range * 1000)
5356
Car._metrics_pvc_car_mileage.set(d.mileage * 1000)
57+
if d.soc < self._last_soc:
58+
# soc [0..100%], 100% = 58kWh = 58.000 Wh
59+
Car._metrics_pvc_car_energy_consumption.inc((self._last_soc - d.soc) * self.get_config().energy_one_percent_soc)
60+
self._last_soc = d.soc
5461
return d
5562

5663
def _read_data(self) -> CarData:
@@ -60,12 +67,13 @@ def _read_data(self) -> CarData:
6067
class SimulatedCar(Car[CarConfig]):
6168
def __init__(self, config: CarConfig):
6269
super().__init__(config)
70+
self.set_data(CarData(error=0, data_captured_at=datetime.now(), cruising_range=150, soc=50, mileage=10000))
6371

6472
def set_data(self, d: CarData):
6573
self._set_data(d)
6674

6775
def _read_data(self) -> CarData:
68-
return CarData(error=0, data_captured_at=datetime.now(), cruising_range=150, soc=50, mileage=10000)
76+
return self.get_data()
6977

7078

7179
# just to permanently grey out car SOC in UI

tests/test_car.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import datetime
44
import json
55
import os
6-
from pvcontrol.car import HtmlFormParser, LoginFormParser, VolkswagenIDCar, VolkswagenIDCarConfig
6+
from pvcontrol.car import Car, CarConfig, CarData, HtmlFormParser, LoginFormParser, VolkswagenIDCar, VolkswagenIDCarConfig, SimulatedCar
77

88
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s [%(levelname)s] %(name)s - %(message)s")
99
# logging.getLogger("urllib3.connectionpool").setLevel(logging.INFO)
@@ -176,3 +176,41 @@ def test_disabled(self):
176176
c = self.car.read_data()
177177
self.assertEqual(1, c.error)
178178
self.assertEqual(0, c.soc)
179+
180+
181+
class SimulatedCarTest(unittest.TestCase):
182+
def setUp(self):
183+
self.car = SimulatedCar(CarConfig())
184+
185+
def test_energy_consumption(self):
186+
c = self.car.read_data()
187+
self.assertEqual(50, c.soc)
188+
self.assertEqual(0, Car._metrics_pvc_car_energy_consumption._value.get())
189+
190+
# driving
191+
self.car.set_data(CarData(soc=49))
192+
c = self.car.read_data()
193+
self.assertEqual(49, c.soc)
194+
self.assertEqual(580, Car._metrics_pvc_car_energy_consumption._value.get())
195+
196+
self.car.set_data(CarData(soc=40))
197+
c = self.car.read_data()
198+
self.assertEqual(40, c.soc)
199+
self.assertEqual(5800, Car._metrics_pvc_car_energy_consumption._value.get())
200+
201+
# not driving
202+
c = self.car.read_data()
203+
self.assertEqual(40, c.soc)
204+
self.assertEqual(5800, Car._metrics_pvc_car_energy_consumption._value.get())
205+
206+
# charging
207+
self.car.set_data(CarData(soc=50))
208+
c = self.car.read_data()
209+
self.assertEqual(50, c.soc)
210+
self.assertEqual(5800, Car._metrics_pvc_car_energy_consumption._value.get())
211+
212+
# driving
213+
self.car.set_data(CarData(soc=40))
214+
c = self.car.read_data()
215+
self.assertEqual(40, c.soc)
216+
self.assertEqual(2 * 5800, Car._metrics_pvc_car_energy_consumption._value.get())

0 commit comments

Comments
 (0)