carconnectivity-plugin-database 0.1__py3-none-any.whl → 0.1a16__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.
Potentially problematic release.
This version of carconnectivity-plugin-database might be problematic. Click here for more details.
- {carconnectivity_plugin_database-0.1.dist-info → carconnectivity_plugin_database-0.1a16.dist-info}/METADATA +2 -2
- {carconnectivity_plugin_database-0.1.dist-info → carconnectivity_plugin_database-0.1a16.dist-info}/RECORD +16 -16
- carconnectivity_plugins/database/_version.py +2 -2
- carconnectivity_plugins/database/agents/charging_agent.py +89 -205
- carconnectivity_plugins/database/agents/climatization_agent.py +6 -13
- carconnectivity_plugins/database/agents/drive_state_agent.py +96 -148
- carconnectivity_plugins/database/agents/state_agent.py +14 -26
- carconnectivity_plugins/database/agents/trip_agent.py +37 -48
- carconnectivity_plugins/database/model/charging_session.py +7 -7
- carconnectivity_plugins/database/model/drive.py +6 -6
- carconnectivity_plugins/database/model/vehicle.py +34 -36
- carconnectivity_plugins/database/plugin.py +14 -10
- {carconnectivity_plugin_database-0.1.dist-info → carconnectivity_plugin_database-0.1a16.dist-info}/WHEEL +0 -0
- {carconnectivity_plugin_database-0.1.dist-info → carconnectivity_plugin_database-0.1a16.dist-info}/entry_points.txt +0 -0
- {carconnectivity_plugin_database-0.1.dist-info → carconnectivity_plugin_database-0.1a16.dist-info}/licenses/LICENSE +0 -0
- {carconnectivity_plugin_database-0.1.dist-info → carconnectivity_plugin_database-0.1a16.dist-info}/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ from typing import TYPE_CHECKING
|
|
|
4
4
|
import threading
|
|
5
5
|
|
|
6
6
|
import logging
|
|
7
|
-
from datetime import timedelta
|
|
7
|
+
from datetime import timedelta
|
|
8
8
|
|
|
9
9
|
from sqlalchemy.exc import DatabaseError
|
|
10
10
|
|
|
@@ -27,9 +27,8 @@ if TYPE_CHECKING:
|
|
|
27
27
|
from sqlalchemy.orm import scoped_session
|
|
28
28
|
from sqlalchemy.orm.session import Session
|
|
29
29
|
|
|
30
|
-
from carconnectivity.attributes import EnumAttribute, SpeedAttribute, PowerAttribute
|
|
30
|
+
from carconnectivity.attributes import EnumAttribute, SpeedAttribute, PowerAttribute
|
|
31
31
|
|
|
32
|
-
from carconnectivity_plugins.database.plugin import Plugin
|
|
33
32
|
from carconnectivity_plugins.database.model.vehicle import Vehicle
|
|
34
33
|
from carconnectivity.drive import ElectricDrive
|
|
35
34
|
|
|
@@ -38,16 +37,13 @@ LOG: logging.Logger = logging.getLogger("carconnectivity.plugins.database.agents
|
|
|
38
37
|
|
|
39
38
|
class ChargingAgent(BaseAgent):
|
|
40
39
|
|
|
41
|
-
def __init__(self,
|
|
42
|
-
|
|
43
|
-
if vehicle is None or carconnectivity_vehicle is None:
|
|
40
|
+
def __init__(self, session_factory: scoped_session[Session], vehicle: Vehicle) -> None:
|
|
41
|
+
if vehicle is None or vehicle.carconnectivity_vehicle is None:
|
|
44
42
|
raise ValueError("Vehicle or its carconnectivity_vehicle attribute is None")
|
|
45
|
-
if not isinstance(carconnectivity_vehicle, ElectricVehicle):
|
|
43
|
+
if not isinstance(vehicle.carconnectivity_vehicle, ElectricVehicle):
|
|
46
44
|
raise ValueError("Vehicle's carconnectivity_vehicle attribute is not an ElectricVehicle")
|
|
47
|
-
self.database_plugin: Plugin = database_plugin
|
|
48
45
|
self.session_factory: scoped_session[Session] = session_factory
|
|
49
46
|
self.vehicle: Vehicle = vehicle
|
|
50
|
-
self.carconnectivity_vehicle: ElectricVehicle = carconnectivity_vehicle
|
|
51
47
|
|
|
52
48
|
with self.session_factory() as session:
|
|
53
49
|
self.last_charging_session: Optional[ChargingSession] = session.query(ChargingSession).filter(ChargingSession.vehicle == vehicle) \
|
|
@@ -56,22 +52,24 @@ class ChargingAgent(BaseAgent):
|
|
|
56
52
|
ChargingSession.plug_connected_date.desc().nulls_first()).first()
|
|
57
53
|
|
|
58
54
|
self.last_charging_session_lock: threading.RLock = threading.RLock()
|
|
59
|
-
self.carconnectivity_last_charging_state: Optional[Charging.ChargingState] =
|
|
60
|
-
self.carconnectivity_last_connector_state: Optional[ChargingConnector.ChargingConnectorConnectionState] =
|
|
55
|
+
self.carconnectivity_last_charging_state: Optional[Charging.ChargingState] = vehicle.carconnectivity_vehicle.charging.state.value
|
|
56
|
+
self.carconnectivity_last_connector_state: Optional[ChargingConnector.ChargingConnectorConnectionState] = vehicle.carconnectivity_vehicle.charging\
|
|
61
57
|
.connector.connection_state.value
|
|
62
|
-
self.carconnectivity_last_connector_lock_state: Optional[ChargingConnector.ChargingConnectorLockState] =
|
|
58
|
+
self.carconnectivity_last_connector_lock_state: Optional[ChargingConnector.ChargingConnectorLockState] = vehicle.carconnectivity_vehicle.charging\
|
|
63
59
|
.connector.lock_state.value
|
|
64
60
|
if self.last_charging_session is not None and not self.last_charging_session.is_closed():
|
|
65
|
-
if
|
|
66
|
-
or (
|
|
67
|
-
and
|
|
61
|
+
if vehicle.carconnectivity_vehicle.charging.state.value in (Charging.ChargingState.CHARGING, Charging.ChargingState.CONSERVATION) \
|
|
62
|
+
or (vehicle.carconnectivity_vehicle.charging.connector.connection_state.enabled
|
|
63
|
+
and vehicle.carconnectivity_vehicle.charging.connector.connection_state.value ==
|
|
68
64
|
ChargingConnector.ChargingConnectorConnectionState.CONNECTED) \
|
|
69
|
-
or (
|
|
70
|
-
and
|
|
65
|
+
or (vehicle.carconnectivity_vehicle.charging.connector.lock_state.enabled
|
|
66
|
+
and vehicle.carconnectivity_vehicle.charging.connector.lock_state.value == ChargingConnector.ChargingConnectorLockState.LOCKED):
|
|
71
67
|
LOG.info("Last charging session for vehicle %s is still open during startup, will continue this session", vehicle.vin)
|
|
72
68
|
else:
|
|
73
69
|
LOG.info("Last charging session for vehicle %s is still open during startup, but we are not charging, ignoring it", vehicle.vin)
|
|
74
70
|
self.last_charging_session = None
|
|
71
|
+
else:
|
|
72
|
+
self.last_charging_session = None
|
|
75
73
|
|
|
76
74
|
self.last_charging_state: Optional[ChargingState] = session.query(ChargingState).filter(ChargingState.vehicle == vehicle)\
|
|
77
75
|
.order_by(ChargingState.first_date.desc()).first()
|
|
@@ -85,36 +83,30 @@ class ChargingAgent(BaseAgent):
|
|
|
85
83
|
.order_by(ChargingPower.first_date.desc()).first()
|
|
86
84
|
self.last_charging_power_lock: threading.RLock = threading.RLock()
|
|
87
85
|
|
|
88
|
-
|
|
89
|
-
if
|
|
90
|
-
self.__on_connector_state_change(
|
|
86
|
+
vehicle.carconnectivity_vehicle.charging.connector.connection_state.add_observer(self.__on_connector_state_change, Observable.ObserverEvent.UPDATED)
|
|
87
|
+
if vehicle.carconnectivity_vehicle.charging.connector.connection_state.enabled:
|
|
88
|
+
self.__on_connector_state_change(vehicle.carconnectivity_vehicle.charging.connector.connection_state, Observable.ObserverEvent.UPDATED)
|
|
91
89
|
|
|
92
|
-
|
|
93
|
-
if
|
|
94
|
-
self.__on_connector_lock_state_change(
|
|
90
|
+
vehicle.carconnectivity_vehicle.charging.connector.lock_state.add_observer(self.__on_connector_lock_state_change, Observable.ObserverEvent.UPDATED)
|
|
91
|
+
if vehicle.carconnectivity_vehicle.charging.connector.lock_state.enabled:
|
|
92
|
+
self.__on_connector_lock_state_change(vehicle.carconnectivity_vehicle.charging.connector.lock_state, Observable.ObserverEvent.UPDATED)
|
|
95
93
|
|
|
96
|
-
|
|
97
|
-
if
|
|
98
|
-
self.__on_charging_state_change(
|
|
94
|
+
vehicle.carconnectivity_vehicle.charging.state.add_observer(self.__on_charging_state_change, Observable.ObserverEvent.UPDATED)
|
|
95
|
+
if vehicle.carconnectivity_vehicle.charging.state.enabled:
|
|
96
|
+
self.__on_charging_state_change(vehicle.carconnectivity_vehicle.charging.state, Observable.ObserverEvent.UPDATED)
|
|
99
97
|
|
|
100
|
-
|
|
101
|
-
if
|
|
102
|
-
self.__on_charging_rate_change(
|
|
98
|
+
vehicle.carconnectivity_vehicle.charging.rate.add_observer(self.__on_charging_rate_change, Observable.ObserverEvent.UPDATED)
|
|
99
|
+
if vehicle.carconnectivity_vehicle.charging.rate.enabled:
|
|
100
|
+
self.__on_charging_rate_change(vehicle.carconnectivity_vehicle.charging.rate, Observable.ObserverEvent.UPDATED)
|
|
103
101
|
|
|
104
|
-
|
|
105
|
-
if
|
|
106
|
-
self.__on_charging_power_change(
|
|
107
|
-
|
|
108
|
-
self.carconnectivity_vehicle.charging.type.add_observer(self._on_charging_type_change, Observable.ObserverEvent.VALUE_CHANGED)
|
|
109
|
-
|
|
110
|
-
electric_drive: Optional[ElectricDrive] = self.carconnectivity_vehicle.get_electric_drive()
|
|
111
|
-
if electric_drive is not None:
|
|
112
|
-
electric_drive.level.add_observer(self._on_battery_level_change, Observable.ObserverEvent.VALUE_CHANGED)
|
|
102
|
+
vehicle.carconnectivity_vehicle.charging.power.add_observer(self.__on_charging_power_change, Observable.ObserverEvent.UPDATED)
|
|
103
|
+
if vehicle.carconnectivity_vehicle.charging.power.enabled:
|
|
104
|
+
self.__on_charging_power_change(vehicle.carconnectivity_vehicle.charging.power, Observable.ObserverEvent.UPDATED)
|
|
113
105
|
self.session_factory.remove()
|
|
114
106
|
|
|
115
107
|
def __on_charging_state_change(self, element: EnumAttribute[Charging.ChargingState], flags: Observable.ObserverEvent) -> None:
|
|
116
108
|
del flags
|
|
117
|
-
if self.carconnectivity_vehicle is None:
|
|
109
|
+
if self.vehicle.carconnectivity_vehicle is None:
|
|
118
110
|
raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
|
|
119
111
|
|
|
120
112
|
if element.enabled:
|
|
@@ -123,9 +115,8 @@ class ChargingAgent(BaseAgent):
|
|
|
123
115
|
if self.last_charging_state is not None:
|
|
124
116
|
self.last_charging_state = session.merge(self.last_charging_state)
|
|
125
117
|
session.refresh(self.last_charging_state)
|
|
126
|
-
if
|
|
127
|
-
and
|
|
128
|
-
and element.last_updated > self.last_charging_state.last_date)):
|
|
118
|
+
if (self.last_charging_state is None or self.last_charging_state.state != element.value) \
|
|
119
|
+
and element.last_updated is not None:
|
|
129
120
|
new_charging_state: ChargingState = ChargingState(vin=self.vehicle.vin, first_date=element.last_updated,
|
|
130
121
|
last_date=element.last_updated, state=element.value)
|
|
131
122
|
try:
|
|
@@ -136,7 +127,6 @@ class ChargingAgent(BaseAgent):
|
|
|
136
127
|
except DatabaseError as err:
|
|
137
128
|
session.rollback()
|
|
138
129
|
LOG.error('DatabaseError while adding charging state for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
139
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
140
130
|
|
|
141
131
|
elif self.last_charging_state is not None and self.last_charging_state.state == element.value and element.last_updated is not None:
|
|
142
132
|
if self.last_charging_state.last_date is None or element.last_updated > self.last_charging_state.last_date:
|
|
@@ -147,7 +137,6 @@ class ChargingAgent(BaseAgent):
|
|
|
147
137
|
except DatabaseError as err:
|
|
148
138
|
session.rollback()
|
|
149
139
|
LOG.error('DatabaseError while updating charging state for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
150
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
151
140
|
|
|
152
141
|
with self.last_charging_session_lock:
|
|
153
142
|
if self.last_charging_session is not None:
|
|
@@ -172,12 +161,10 @@ class ChargingAgent(BaseAgent):
|
|
|
172
161
|
try:
|
|
173
162
|
self.last_charging_session.session_end_date = None
|
|
174
163
|
self.last_charging_session.end_level = None
|
|
175
|
-
self._update_session_charging_type(session, self.last_charging_session)
|
|
176
164
|
session.commit()
|
|
177
165
|
except DatabaseError as err:
|
|
178
166
|
session.rollback()
|
|
179
167
|
LOG.error('DatabaseError while updating charging session for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
180
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
181
168
|
else:
|
|
182
169
|
LOG.info("Starting new charging session for vehicle %s", self.vehicle.vin)
|
|
183
170
|
new_session: ChargingSession = ChargingSession(vin=self.vehicle.vin, session_start_date=element.last_changed)
|
|
@@ -192,7 +179,6 @@ class ChargingAgent(BaseAgent):
|
|
|
192
179
|
except DatabaseError as err:
|
|
193
180
|
session.rollback()
|
|
194
181
|
LOG.error('DatabaseError while adding charging session for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
195
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
196
182
|
else:
|
|
197
183
|
if self.last_charging_session.was_started():
|
|
198
184
|
LOG.debug("Continuing existing charging session for vehicle %s", self.vehicle.vin)
|
|
@@ -207,10 +193,9 @@ class ChargingAgent(BaseAgent):
|
|
|
207
193
|
except DatabaseError as err:
|
|
208
194
|
session.rollback()
|
|
209
195
|
LOG.error('DatabaseError while starting charging session for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
210
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
211
196
|
# Update startlevel at beginning of charging
|
|
212
|
-
if self.last_charging_session is not None and isinstance(self.carconnectivity_vehicle, ElectricVehicle):
|
|
213
|
-
electric_drive: Optional[ElectricDrive] = self.carconnectivity_vehicle.get_electric_drive()
|
|
197
|
+
if self.last_charging_session is not None and isinstance(self.vehicle.carconnectivity_vehicle, ElectricVehicle):
|
|
198
|
+
electric_drive: Optional[ElectricDrive] = self.vehicle.carconnectivity_vehicle.get_electric_drive()
|
|
214
199
|
if electric_drive is not None and electric_drive.level.enabled and electric_drive.level.value is not None:
|
|
215
200
|
try:
|
|
216
201
|
self.last_charging_session.start_level = electric_drive.level.value
|
|
@@ -218,7 +203,6 @@ class ChargingAgent(BaseAgent):
|
|
|
218
203
|
except DatabaseError as err:
|
|
219
204
|
session.rollback()
|
|
220
205
|
LOG.error('DatabaseError while setting start level for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
221
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
222
206
|
elif element.value not in (Charging.ChargingState.CHARGING, Charging.ChargingState.CONSERVATION) \
|
|
223
207
|
and self.carconnectivity_last_charging_state in (Charging.ChargingState.CHARGING, Charging.ChargingState.CONSERVATION):
|
|
224
208
|
if self.last_charging_session is not None and not self.last_charging_session.was_ended():
|
|
@@ -229,9 +213,8 @@ class ChargingAgent(BaseAgent):
|
|
|
229
213
|
except DatabaseError as err:
|
|
230
214
|
session.rollback()
|
|
231
215
|
LOG.error('DatabaseError while ending charging session for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
electric_drive: Optional[ElectricDrive] = self.carconnectivity_vehicle.get_electric_drive()
|
|
216
|
+
if isinstance(self.vehicle.carconnectivity_vehicle, ElectricVehicle):
|
|
217
|
+
electric_drive: Optional[ElectricDrive] = self.vehicle.carconnectivity_vehicle.get_electric_drive()
|
|
235
218
|
if electric_drive is not None and electric_drive.level.enabled and electric_drive.level.value is not None:
|
|
236
219
|
try:
|
|
237
220
|
self.last_charging_session.end_level = electric_drive.level.value
|
|
@@ -239,13 +222,12 @@ class ChargingAgent(BaseAgent):
|
|
|
239
222
|
except DatabaseError as err:
|
|
240
223
|
session.rollback()
|
|
241
224
|
LOG.error('DatabaseError while setting start level for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
242
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
243
225
|
self.carconnectivity_last_charging_state = element.value
|
|
244
226
|
self.session_factory.remove()
|
|
245
227
|
|
|
246
228
|
def __on_charging_rate_change(self, element: SpeedAttribute, flags: Observable.ObserverEvent) -> None:
|
|
247
229
|
del flags
|
|
248
|
-
if self.carconnectivity_vehicle is None:
|
|
230
|
+
if self.vehicle.carconnectivity_vehicle is None:
|
|
249
231
|
raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
|
|
250
232
|
if element.enabled:
|
|
251
233
|
with self.last_charging_rate_lock:
|
|
@@ -253,9 +235,8 @@ class ChargingAgent(BaseAgent):
|
|
|
253
235
|
if self.last_charging_rate is not None:
|
|
254
236
|
self.last_charging_rate = session.merge(self.last_charging_rate)
|
|
255
237
|
session.refresh(self.last_charging_rate)
|
|
256
|
-
if
|
|
257
|
-
and
|
|
258
|
-
and element.last_updated > self.last_charging_rate.last_date)):
|
|
238
|
+
if (self.last_charging_rate is None or self.last_charging_rate.rate != element.value) \
|
|
239
|
+
and element.last_updated is not None:
|
|
259
240
|
new_charging_rate: ChargingRate = ChargingRate(vin=self.vehicle.vin, first_date=element.last_updated,
|
|
260
241
|
last_date=element.last_updated, rate=element.value)
|
|
261
242
|
try:
|
|
@@ -266,7 +247,6 @@ class ChargingAgent(BaseAgent):
|
|
|
266
247
|
except DatabaseError as err:
|
|
267
248
|
session.rollback()
|
|
268
249
|
LOG.error('DatabaseError while adding charging rate for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
269
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
270
250
|
elif self.last_charging_rate is not None and self.last_charging_rate.rate == element.value and element.last_updated is not None:
|
|
271
251
|
if self.last_charging_rate.last_date is None or element.last_updated > self.last_charging_rate.last_date:
|
|
272
252
|
try:
|
|
@@ -276,12 +256,11 @@ class ChargingAgent(BaseAgent):
|
|
|
276
256
|
except DatabaseError as err:
|
|
277
257
|
session.rollback()
|
|
278
258
|
LOG.error('DatabaseError while updating charging rate for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
279
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
280
259
|
self.session_factory.remove()
|
|
281
260
|
|
|
282
261
|
def __on_charging_power_change(self, element: PowerAttribute, flags: Observable.ObserverEvent) -> None:
|
|
283
262
|
del flags
|
|
284
|
-
if self.carconnectivity_vehicle is None:
|
|
263
|
+
if self.vehicle.carconnectivity_vehicle is None:
|
|
285
264
|
raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
|
|
286
265
|
if element.enabled:
|
|
287
266
|
with self.last_charging_power_lock:
|
|
@@ -289,9 +268,8 @@ class ChargingAgent(BaseAgent):
|
|
|
289
268
|
if self.last_charging_power is not None:
|
|
290
269
|
self.last_charging_power = session.merge(self.last_charging_power)
|
|
291
270
|
session.refresh(self.last_charging_power)
|
|
292
|
-
if
|
|
293
|
-
and
|
|
294
|
-
and element.last_updated > self.last_charging_power.last_date)):
|
|
271
|
+
if (self.last_charging_power is None or self.last_charging_power.power != element.value) \
|
|
272
|
+
and element.last_updated is not None:
|
|
295
273
|
new_charging_power: ChargingPower = ChargingPower(vin=self.vehicle.vin, first_date=element.last_updated,
|
|
296
274
|
last_date=element.last_updated, power=element.value)
|
|
297
275
|
try:
|
|
@@ -302,7 +280,6 @@ class ChargingAgent(BaseAgent):
|
|
|
302
280
|
except DatabaseError as err:
|
|
303
281
|
session.rollback()
|
|
304
282
|
LOG.error('DatabaseError while adding charging power for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
305
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
306
283
|
elif self.last_charging_power is not None and self.last_charging_power.power == element.value and element.last_updated is not None:
|
|
307
284
|
if self.last_charging_power.last_date is None or element.last_updated > self.last_charging_power.last_date:
|
|
308
285
|
try:
|
|
@@ -311,12 +288,11 @@ class ChargingAgent(BaseAgent):
|
|
|
311
288
|
except DatabaseError as err:
|
|
312
289
|
session.rollback()
|
|
313
290
|
LOG.error('DatabaseError while updating charging power for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
314
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
315
291
|
self.session_factory.remove()
|
|
316
292
|
|
|
317
293
|
def __on_connector_state_change(self, element: EnumAttribute[ChargingConnector.ChargingConnectorConnectionState], flags: Observable.ObserverEvent) -> None:
|
|
318
294
|
del flags
|
|
319
|
-
if self.carconnectivity_vehicle is None:
|
|
295
|
+
if self.vehicle.carconnectivity_vehicle is None:
|
|
320
296
|
raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
|
|
321
297
|
|
|
322
298
|
with self.session_factory() as session:
|
|
@@ -326,7 +302,6 @@ class ChargingAgent(BaseAgent):
|
|
|
326
302
|
session.refresh(self.last_charging_session)
|
|
327
303
|
|
|
328
304
|
if element.value == ChargingConnector.ChargingConnectorConnectionState.CONNECTED \
|
|
329
|
-
and self.carconnectivity_last_connector_state is not None \
|
|
330
305
|
and self.carconnectivity_last_connector_state != ChargingConnector.ChargingConnectorConnectionState.CONNECTED:
|
|
331
306
|
if self.last_charging_session is None or self.last_charging_session.is_closed():
|
|
332
307
|
LOG.info("Starting new charging session for vehicle %s due to connector connected state", self.vehicle.vin)
|
|
@@ -341,7 +316,6 @@ class ChargingAgent(BaseAgent):
|
|
|
341
316
|
except DatabaseError as err:
|
|
342
317
|
session.rollback()
|
|
343
318
|
LOG.error('DatabaseError while adding charging session for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
344
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
345
319
|
elif not self.last_charging_session.was_connected():
|
|
346
320
|
LOG.debug("Continuing existing charging session for vehicle %s, writing connected date", self.vehicle.vin)
|
|
347
321
|
try:
|
|
@@ -352,7 +326,6 @@ class ChargingAgent(BaseAgent):
|
|
|
352
326
|
except DatabaseError as err:
|
|
353
327
|
session.rollback()
|
|
354
328
|
LOG.error('DatabaseError while starting charging session for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
355
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
356
329
|
elif element.value != ChargingConnector.ChargingConnectorConnectionState.CONNECTED \
|
|
357
330
|
and self.carconnectivity_last_connector_state == ChargingConnector.ChargingConnectorConnectionState.CONNECTED:
|
|
358
331
|
if self.last_charging_session is not None and not self.last_charging_session.was_disconnected():
|
|
@@ -363,29 +336,22 @@ class ChargingAgent(BaseAgent):
|
|
|
363
336
|
except DatabaseError as err:
|
|
364
337
|
session.rollback()
|
|
365
338
|
LOG.error('DatabaseError while ending charging session for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
366
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
367
339
|
# Create charging session when connected at startup
|
|
368
340
|
elif element.value == ChargingConnector.ChargingConnectorConnectionState.CONNECTED \
|
|
369
341
|
and self.carconnectivity_last_connector_state == ChargingConnector.ChargingConnectorConnectionState.CONNECTED:
|
|
370
342
|
if self.last_charging_session is None or self.last_charging_session.is_closed():
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
LOG.debug('Added new charging session for vehicle %s to database', self.vehicle.vin)
|
|
384
|
-
self.last_charging_session = new_session
|
|
385
|
-
except DatabaseError as err:
|
|
386
|
-
session.rollback()
|
|
387
|
-
LOG.error('DatabaseError while adding charging session for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
388
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
343
|
+
LOG.info("Starting new charging session for vehicle %s due to connector connected state", self.vehicle.vin)
|
|
344
|
+
new_session: ChargingSession = ChargingSession(vin=self.vehicle.vin, plug_connected_date=element.last_changed)
|
|
345
|
+
try:
|
|
346
|
+
session.add(new_session)
|
|
347
|
+
self._update_session_odometer(session, new_session)
|
|
348
|
+
self._update_session_position(session, new_session)
|
|
349
|
+
session.commit()
|
|
350
|
+
LOG.debug('Added new charging session for vehicle %s to database', self.vehicle.vin)
|
|
351
|
+
self.last_charging_session = new_session
|
|
352
|
+
except DatabaseError as err:
|
|
353
|
+
session.rollback()
|
|
354
|
+
LOG.error('DatabaseError while adding charging session for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
389
355
|
elif self.last_charging_session is not None and not self.last_charging_session.was_connected():
|
|
390
356
|
try:
|
|
391
357
|
self.last_charging_session.plug_connected_date = element.last_changed
|
|
@@ -394,13 +360,12 @@ class ChargingAgent(BaseAgent):
|
|
|
394
360
|
except DatabaseError as err:
|
|
395
361
|
session.rollback()
|
|
396
362
|
LOG.error('DatabaseError while changing charging session for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
397
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
398
363
|
self.carconnectivity_last_connector_state = element.value
|
|
399
364
|
self.session_factory.remove()
|
|
400
365
|
|
|
401
366
|
def __on_connector_lock_state_change(self, element: EnumAttribute[ChargingConnector.ChargingConnectorLockState], flags: Observable.ObserverEvent) -> None:
|
|
402
367
|
del flags
|
|
403
|
-
if self.carconnectivity_vehicle is None:
|
|
368
|
+
if self.vehicle.carconnectivity_vehicle is None:
|
|
404
369
|
raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
|
|
405
370
|
|
|
406
371
|
with self.session_factory() as session:
|
|
@@ -410,36 +375,20 @@ class ChargingAgent(BaseAgent):
|
|
|
410
375
|
session.refresh(self.last_charging_session)
|
|
411
376
|
|
|
412
377
|
if element.value == ChargingConnector.ChargingConnectorLockState.LOCKED \
|
|
413
|
-
and self.carconnectivity_last_connector_lock_state is not None \
|
|
414
378
|
and self.carconnectivity_last_connector_lock_state != ChargingConnector.ChargingConnectorLockState.LOCKED:
|
|
415
379
|
if self.last_charging_session is None or self.last_charging_session.is_closed():
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
429
|
-
else:
|
|
430
|
-
LOG.info("Starting new charging session for vehicle %s due to connector locked state", self.vehicle.vin)
|
|
431
|
-
new_session: ChargingSession = ChargingSession(vin=self.vehicle.vin, plug_locked_date=element.last_changed)
|
|
432
|
-
try:
|
|
433
|
-
session.add(new_session)
|
|
434
|
-
self._update_session_odometer(session, new_session)
|
|
435
|
-
self._update_session_position(session, new_session)
|
|
436
|
-
session.commit()
|
|
437
|
-
LOG.debug('Added new charging session for vehicle %s to database', self.vehicle.vin)
|
|
438
|
-
self.last_charging_session = new_session
|
|
439
|
-
except DatabaseError as err:
|
|
440
|
-
session.rollback()
|
|
441
|
-
LOG.error('DatabaseError while adding charging session for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
442
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
380
|
+
LOG.info("Starting new charging session for vehicle %s due to connector locked state", self.vehicle.vin)
|
|
381
|
+
new_session: ChargingSession = ChargingSession(vin=self.vehicle.vin, plug_locked_date=element.last_changed)
|
|
382
|
+
try:
|
|
383
|
+
session.add(new_session)
|
|
384
|
+
self._update_session_odometer(session, new_session)
|
|
385
|
+
self._update_session_position(session, new_session)
|
|
386
|
+
session.commit()
|
|
387
|
+
LOG.debug('Added new charging session for vehicle %s to database', self.vehicle.vin)
|
|
388
|
+
self.last_charging_session = new_session
|
|
389
|
+
except DatabaseError as err:
|
|
390
|
+
session.rollback()
|
|
391
|
+
LOG.error('DatabaseError while adding charging session for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
443
392
|
elif not self.last_charging_session.was_locked():
|
|
444
393
|
LOG.debug("Continuing existing charging session for vehicle %s, writing locked date", self.vehicle.vin)
|
|
445
394
|
try:
|
|
@@ -450,7 +399,6 @@ class ChargingAgent(BaseAgent):
|
|
|
450
399
|
except DatabaseError as err:
|
|
451
400
|
session.rollback()
|
|
452
401
|
LOG.error('DatabaseError while starting charging session for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
453
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
454
402
|
elif element.value != ChargingConnector.ChargingConnectorLockState.LOCKED \
|
|
455
403
|
and self.carconnectivity_last_connector_lock_state == ChargingConnector.ChargingConnectorLockState.LOCKED:
|
|
456
404
|
if self.last_charging_session is not None and not self.last_charging_session.was_unlocked():
|
|
@@ -461,26 +409,11 @@ class ChargingAgent(BaseAgent):
|
|
|
461
409
|
except DatabaseError as err:
|
|
462
410
|
session.rollback()
|
|
463
411
|
LOG.error('DatabaseError while ending charging session for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
464
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
465
412
|
# Create charging session when locked at startup
|
|
466
413
|
elif element.value == ChargingConnector.ChargingConnectorLockState.LOCKED \
|
|
467
414
|
and self.carconnectivity_last_connector_lock_state == ChargingConnector.ChargingConnectorLockState.LOCKED:
|
|
468
415
|
if self.last_charging_session is None or self.last_charging_session.is_closed():
|
|
469
|
-
|
|
470
|
-
if self.last_charging_session is not None and not self.last_charging_session.was_disconnected() \
|
|
471
|
-
and (self.last_charging_session.plug_unlocked_date is None
|
|
472
|
-
or self.last_charging_session.plug_unlocked_date > ((element.last_changed or datetime.now(timezone.utc))
|
|
473
|
-
- timedelta(hours=24))):
|
|
474
|
-
LOG.debug("found a closed charging session that was not disconneced. This could be an interrupted session we want to continue")
|
|
475
|
-
try:
|
|
476
|
-
self.last_charging_session.plug_unlocked_date = None
|
|
477
|
-
session.commit()
|
|
478
|
-
except DatabaseError as err:
|
|
479
|
-
session.rollback()
|
|
480
|
-
LOG.error('DatabaseError while changing charging session for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
481
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
482
|
-
else:
|
|
483
|
-
LOG.info("Starting new charging session for vehicle %s due to connector locked state on startup", self.vehicle.vin)
|
|
416
|
+
LOG.info("Starting new charging session for vehicle %s due to connector locked state", self.vehicle.vin)
|
|
484
417
|
new_session: ChargingSession = ChargingSession(vin=self.vehicle.vin, plug_locked_date=element.last_changed)
|
|
485
418
|
try:
|
|
486
419
|
session.add(new_session)
|
|
@@ -492,7 +425,6 @@ class ChargingAgent(BaseAgent):
|
|
|
492
425
|
except DatabaseError as err:
|
|
493
426
|
session.rollback()
|
|
494
427
|
LOG.error('DatabaseError while adding charging session for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
495
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
496
428
|
elif self.last_charging_session is not None and not self.last_charging_session.was_locked():
|
|
497
429
|
try:
|
|
498
430
|
self.last_charging_session.plug_locked_date = element.last_changed
|
|
@@ -501,110 +433,62 @@ class ChargingAgent(BaseAgent):
|
|
|
501
433
|
except DatabaseError as err:
|
|
502
434
|
session.rollback()
|
|
503
435
|
LOG.error('DatabaseError while changing charging session for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
504
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
505
436
|
self.carconnectivity_last_connector_lock_state = element.value
|
|
506
437
|
self.session_factory.remove()
|
|
507
438
|
|
|
508
439
|
def _update_session_odometer(self, session: Session, charging_session: ChargingSession) -> None:
|
|
509
|
-
if self.carconnectivity_vehicle is None:
|
|
440
|
+
if self.vehicle.carconnectivity_vehicle is None:
|
|
510
441
|
raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
|
|
511
|
-
if self.carconnectivity_vehicle.odometer.enabled:
|
|
442
|
+
if self.vehicle.carconnectivity_vehicle.odometer.enabled:
|
|
512
443
|
if charging_session.session_odometer is None:
|
|
513
444
|
try:
|
|
514
|
-
charging_session.session_odometer = self.carconnectivity_vehicle.odometer.value
|
|
445
|
+
charging_session.session_odometer = self.vehicle.carconnectivity_vehicle.odometer.value
|
|
515
446
|
except DatabaseError as err:
|
|
516
447
|
session.rollback()
|
|
517
448
|
LOG.error('DatabaseError while updating odometer for charging session of vehicle %s in database: %s', self.vehicle.vin, err)
|
|
518
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
519
449
|
|
|
520
450
|
def _update_session_charging_type(self, session: Session, charging_session: ChargingSession) -> None:
|
|
521
|
-
if self.carconnectivity_vehicle is None:
|
|
451
|
+
if self.vehicle.carconnectivity_vehicle is None:
|
|
522
452
|
raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
|
|
523
|
-
if isinstance(self.carconnectivity_vehicle, ElectricVehicle) and self.carconnectivity_vehicle.charging.type.enabled \
|
|
524
|
-
and self.carconnectivity_vehicle.charging.type.value is not None:
|
|
453
|
+
if isinstance(self.vehicle.carconnectivity_vehicle, ElectricVehicle) and self.vehicle.carconnectivity_vehicle.charging.type.enabled \
|
|
454
|
+
and self.vehicle.carconnectivity_vehicle.charging.type.value is not None:
|
|
525
455
|
if charging_session.charging_type is None:
|
|
526
456
|
try:
|
|
527
|
-
charging_session.charging_type = self.carconnectivity_vehicle.charging.type.value
|
|
457
|
+
charging_session.charging_type = self.vehicle.carconnectivity_vehicle.charging.type.value
|
|
528
458
|
except DatabaseError as err:
|
|
529
459
|
session.rollback()
|
|
530
460
|
LOG.error('DatabaseError while updating charging type for charging session of vehicle %s in database: %s', self.vehicle.vin, err)
|
|
531
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
532
461
|
|
|
533
462
|
def _update_session_position(self, session: Session, charging_session: ChargingSession) -> None:
|
|
534
|
-
if self.carconnectivity_vehicle is None:
|
|
463
|
+
if self.vehicle.carconnectivity_vehicle is None:
|
|
535
464
|
raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
|
|
536
|
-
if self.carconnectivity_vehicle.position.enabled and self.carconnectivity_vehicle.position.latitude.enabled \
|
|
537
|
-
and self.carconnectivity_vehicle.position.longitude.enabled \
|
|
538
|
-
and self.carconnectivity_vehicle.position.latitude.value is not None \
|
|
539
|
-
and self.carconnectivity_vehicle.position.longitude.value is not None:
|
|
465
|
+
if self.vehicle.carconnectivity_vehicle.position.enabled and self.vehicle.carconnectivity_vehicle.position.latitude.enabled \
|
|
466
|
+
and self.vehicle.carconnectivity_vehicle.position.longitude.enabled \
|
|
467
|
+
and self.vehicle.carconnectivity_vehicle.position.latitude.value is not None \
|
|
468
|
+
and self.vehicle.carconnectivity_vehicle.position.longitude.value is not None:
|
|
540
469
|
if charging_session.session_position_latitude is None and charging_session.session_position_longitude is None:
|
|
541
470
|
try:
|
|
542
|
-
charging_session.session_position_latitude = self.carconnectivity_vehicle.position.latitude.value
|
|
543
|
-
charging_session.session_position_longitude = self.carconnectivity_vehicle.position.longitude.value
|
|
471
|
+
charging_session.session_position_latitude = self.vehicle.carconnectivity_vehicle.position.latitude.value
|
|
472
|
+
charging_session.session_position_longitude = self.vehicle.carconnectivity_vehicle.position.longitude.value
|
|
544
473
|
except DatabaseError as err:
|
|
545
474
|
session.rollback()
|
|
546
475
|
LOG.error('DatabaseError while updating position for charging session of vehicle %s in database: %s', self.vehicle.vin, err)
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
location: Location = Location.from_carconnectivity_location(location=self.carconnectivity_vehicle.position.location)
|
|
476
|
+
if charging_session.location is None and self.vehicle.carconnectivity_vehicle.position.location.enabled:
|
|
477
|
+
location: Location = Location.from_carconnectivity_location(location=self.vehicle.carconnectivity_vehicle.position.location)
|
|
550
478
|
try:
|
|
551
479
|
location = session.merge(location)
|
|
552
480
|
charging_session.location = location
|
|
553
481
|
except DatabaseError as err:
|
|
554
482
|
session.rollback()
|
|
555
483
|
LOG.error('DatabaseError while merging location for charging session of vehicle %s in database: %s', self.vehicle.vin, err)
|
|
556
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
557
484
|
if charging_session.charging_station is None \
|
|
558
|
-
and isinstance(self.carconnectivity_vehicle, ElectricVehicle) and self.carconnectivity_vehicle.charging is not None \
|
|
559
|
-
and self.carconnectivity_vehicle.charging.enabled and self.carconnectivity_vehicle.charging.charging_station.enabled:
|
|
485
|
+
and isinstance(self.vehicle.carconnectivity_vehicle, ElectricVehicle) and self.vehicle.carconnectivity_vehicle.charging is not None \
|
|
486
|
+
and self.vehicle.carconnectivity_vehicle.charging.enabled and self.vehicle.carconnectivity_vehicle.charging.charging_station.enabled:
|
|
560
487
|
charging_station: ChargingStation = ChargingStation.from_carconnectivity_charging_station(
|
|
561
|
-
charging_station=self.carconnectivity_vehicle.charging.charging_station)
|
|
488
|
+
charging_station=self.vehicle.carconnectivity_vehicle.charging.charging_station)
|
|
562
489
|
try:
|
|
563
490
|
charging_station = session.merge(charging_station)
|
|
564
491
|
charging_session.charging_station = charging_station
|
|
565
492
|
except DatabaseError as err:
|
|
566
493
|
session.rollback()
|
|
567
494
|
LOG.error('DatabaseError while merging charging station for charging session of vehicle %s in database: %s', self.vehicle.vin, err)
|
|
568
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
569
|
-
|
|
570
|
-
def _on_charging_type_change(self, element: EnumAttribute[Charging.ChargingType], flags: Observable.ObserverEvent) -> None:
|
|
571
|
-
del flags
|
|
572
|
-
if element.enabled:
|
|
573
|
-
with self.session_factory() as session:
|
|
574
|
-
with self.last_charging_session_lock:
|
|
575
|
-
if self.last_charging_session is not None:
|
|
576
|
-
self.last_charging_session = session.merge(self.last_charging_session)
|
|
577
|
-
session.refresh(self.last_charging_session)
|
|
578
|
-
if self.last_charging_session is not None and not self.last_charging_session.is_closed() \
|
|
579
|
-
and element.value in [Charging.ChargingType.AC, Charging.ChargingType.DC]:
|
|
580
|
-
try:
|
|
581
|
-
self.last_charging_session.charging_type = element.value
|
|
582
|
-
session.commit()
|
|
583
|
-
except DatabaseError as err:
|
|
584
|
-
session.rollback()
|
|
585
|
-
LOG.error('DatabaseError while updating type of charging session for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
586
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
587
|
-
self.session_factory.remove()
|
|
588
|
-
|
|
589
|
-
def _on_battery_level_change(self, element: FloatAttribute, flags: Observable.ObserverEvent) -> None:
|
|
590
|
-
del flags
|
|
591
|
-
if element.enabled and element.value is not None:
|
|
592
|
-
# We try to see if there was a late battery level update for a finished session
|
|
593
|
-
with self.session_factory() as session:
|
|
594
|
-
with self.last_charging_session_lock:
|
|
595
|
-
if self.last_charging_session is not None:
|
|
596
|
-
self.last_charging_session = session.merge(self.last_charging_session)
|
|
597
|
-
session.refresh(self.last_charging_session)
|
|
598
|
-
if self.last_charging_session is not None and self.last_charging_session.session_end_date is not None:
|
|
599
|
-
if element.last_updated is not None and (element.last_updated <= (self.last_charging_session.session_end_date + timedelta(minutes=1))):
|
|
600
|
-
# Only update if we have no end level yet or the new level is higher than the previous one (this happens with late level updates)
|
|
601
|
-
if self.last_charging_session.end_level is None or self.last_charging_session.end_level < element.value:
|
|
602
|
-
try:
|
|
603
|
-
self.last_charging_session.end_level = element.value
|
|
604
|
-
session.commit()
|
|
605
|
-
except DatabaseError as err:
|
|
606
|
-
session.rollback()
|
|
607
|
-
LOG.error('DatabaseError while updating battery level of charging session for vehicle %s in database: %s',
|
|
608
|
-
self.vehicle.vin, err)
|
|
609
|
-
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
610
|
-
self.session_factory.remove()
|