carconnectivity-plugin-database 0.1a19__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.
- carconnectivity_database/__init__.py +0 -0
- carconnectivity_database/carconnectivity_database_base.py +26 -0
- carconnectivity_plugin_database-0.1a19.dist-info/METADATA +74 -0
- carconnectivity_plugin_database-0.1a19.dist-info/RECORD +48 -0
- carconnectivity_plugin_database-0.1a19.dist-info/WHEEL +5 -0
- carconnectivity_plugin_database-0.1a19.dist-info/entry_points.txt +2 -0
- carconnectivity_plugin_database-0.1a19.dist-info/licenses/LICENSE +21 -0
- carconnectivity_plugin_database-0.1a19.dist-info/top_level.txt +2 -0
- carconnectivity_plugins/database/__init__.py +0 -0
- carconnectivity_plugins/database/_version.py +34 -0
- carconnectivity_plugins/database/agents/base_agent.py +2 -0
- carconnectivity_plugins/database/agents/charging_agent.py +523 -0
- carconnectivity_plugins/database/agents/climatization_agent.py +80 -0
- carconnectivity_plugins/database/agents/drive_state_agent.py +368 -0
- carconnectivity_plugins/database/agents/state_agent.py +162 -0
- carconnectivity_plugins/database/agents/trip_agent.py +225 -0
- carconnectivity_plugins/database/model/__init__.py +19 -0
- carconnectivity_plugins/database/model/alembic.ini +100 -0
- carconnectivity_plugins/database/model/base.py +4 -0
- carconnectivity_plugins/database/model/carconnectivity_schema/README +1 -0
- carconnectivity_plugins/database/model/carconnectivity_schema/__init__.py +0 -0
- carconnectivity_plugins/database/model/carconnectivity_schema/env.py +78 -0
- carconnectivity_plugins/database/model/carconnectivity_schema/script.py.mako +24 -0
- carconnectivity_plugins/database/model/carconnectivity_schema/versions/__init__.py +0 -0
- carconnectivity_plugins/database/model/charging_power.py +52 -0
- carconnectivity_plugins/database/model/charging_rate.py +52 -0
- carconnectivity_plugins/database/model/charging_session.py +144 -0
- carconnectivity_plugins/database/model/charging_state.py +57 -0
- carconnectivity_plugins/database/model/charging_station.py +66 -0
- carconnectivity_plugins/database/model/climatization_state.py +57 -0
- carconnectivity_plugins/database/model/connection_state.py +57 -0
- carconnectivity_plugins/database/model/datetime_decorator.py +44 -0
- carconnectivity_plugins/database/model/drive.py +89 -0
- carconnectivity_plugins/database/model/drive_consumption.py +48 -0
- carconnectivity_plugins/database/model/drive_level.py +50 -0
- carconnectivity_plugins/database/model/drive_range.py +53 -0
- carconnectivity_plugins/database/model/drive_range_full.py +53 -0
- carconnectivity_plugins/database/model/location.py +85 -0
- carconnectivity_plugins/database/model/migrations.py +24 -0
- carconnectivity_plugins/database/model/outside_temperature.py +52 -0
- carconnectivity_plugins/database/model/state.py +56 -0
- carconnectivity_plugins/database/model/tag.py +31 -0
- carconnectivity_plugins/database/model/timedelta_decorator.py +33 -0
- carconnectivity_plugins/database/model/trip.py +85 -0
- carconnectivity_plugins/database/model/vehicle.py +186 -0
- carconnectivity_plugins/database/plugin.py +167 -0
- carconnectivity_plugins/database/ui/plugin_ui.py +48 -0
- carconnectivity_plugins/database/ui/templates/database/status.html +8 -0
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
|
+
|
|
4
|
+
import threading
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
from datetime import timedelta
|
|
8
|
+
|
|
9
|
+
from sqlalchemy.exc import DatabaseError
|
|
10
|
+
|
|
11
|
+
from carconnectivity.observable import Observable
|
|
12
|
+
from carconnectivity.vehicle import ElectricVehicle
|
|
13
|
+
from carconnectivity.charging import Charging
|
|
14
|
+
from carconnectivity.charging_connector import ChargingConnector
|
|
15
|
+
|
|
16
|
+
from carconnectivity_plugins.database.agents.base_agent import BaseAgent
|
|
17
|
+
|
|
18
|
+
from carconnectivity_plugins.database.model.charging_state import ChargingState
|
|
19
|
+
from carconnectivity_plugins.database.model.charging_rate import ChargingRate
|
|
20
|
+
from carconnectivity_plugins.database.model.charging_power import ChargingPower
|
|
21
|
+
from carconnectivity_plugins.database.model.charging_session import ChargingSession
|
|
22
|
+
from carconnectivity_plugins.database.model.location import Location
|
|
23
|
+
from carconnectivity_plugins.database.model.charging_station import ChargingStation
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from typing import Optional
|
|
27
|
+
from sqlalchemy.orm import scoped_session
|
|
28
|
+
from sqlalchemy.orm.session import Session
|
|
29
|
+
|
|
30
|
+
from carconnectivity.attributes import EnumAttribute, SpeedAttribute, PowerAttribute
|
|
31
|
+
|
|
32
|
+
from carconnectivity_plugins.database.plugin import Plugin
|
|
33
|
+
from carconnectivity_plugins.database.model.vehicle import Vehicle
|
|
34
|
+
from carconnectivity.drive import ElectricDrive
|
|
35
|
+
|
|
36
|
+
LOG: logging.Logger = logging.getLogger("carconnectivity.plugins.database.agents.charging_agent")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ChargingAgent(BaseAgent):
|
|
40
|
+
|
|
41
|
+
def __init__(self, database_plugin: Plugin, session_factory: scoped_session[Session], vehicle: Vehicle) -> None:
|
|
42
|
+
if vehicle is None or vehicle.carconnectivity_vehicle is None:
|
|
43
|
+
raise ValueError("Vehicle or its carconnectivity_vehicle attribute is None")
|
|
44
|
+
if not isinstance(vehicle.carconnectivity_vehicle, ElectricVehicle):
|
|
45
|
+
raise ValueError("Vehicle's carconnectivity_vehicle attribute is not an ElectricVehicle")
|
|
46
|
+
self.database_plugin: Plugin = database_plugin
|
|
47
|
+
self.session_factory: scoped_session[Session] = session_factory
|
|
48
|
+
self.vehicle: Vehicle = vehicle
|
|
49
|
+
|
|
50
|
+
with self.session_factory() as session:
|
|
51
|
+
self.last_charging_session: Optional[ChargingSession] = session.query(ChargingSession).filter(ChargingSession.vehicle == vehicle) \
|
|
52
|
+
.order_by(ChargingSession.session_start_date.desc().nulls_first(),
|
|
53
|
+
ChargingSession.plug_locked_date.desc().nulls_first(),
|
|
54
|
+
ChargingSession.plug_connected_date.desc().nulls_first()).first()
|
|
55
|
+
|
|
56
|
+
self.last_charging_session_lock: threading.RLock = threading.RLock()
|
|
57
|
+
self.carconnectivity_last_charging_state: Optional[Charging.ChargingState] = vehicle.carconnectivity_vehicle.charging.state.value
|
|
58
|
+
self.carconnectivity_last_connector_state: Optional[ChargingConnector.ChargingConnectorConnectionState] = vehicle.carconnectivity_vehicle.charging\
|
|
59
|
+
.connector.connection_state.value
|
|
60
|
+
self.carconnectivity_last_connector_lock_state: Optional[ChargingConnector.ChargingConnectorLockState] = vehicle.carconnectivity_vehicle.charging\
|
|
61
|
+
.connector.lock_state.value
|
|
62
|
+
if self.last_charging_session is not None and not self.last_charging_session.is_closed():
|
|
63
|
+
if vehicle.carconnectivity_vehicle.charging.state.value in (Charging.ChargingState.CHARGING, Charging.ChargingState.CONSERVATION) \
|
|
64
|
+
or (vehicle.carconnectivity_vehicle.charging.connector.connection_state.enabled
|
|
65
|
+
and vehicle.carconnectivity_vehicle.charging.connector.connection_state.value ==
|
|
66
|
+
ChargingConnector.ChargingConnectorConnectionState.CONNECTED) \
|
|
67
|
+
or (vehicle.carconnectivity_vehicle.charging.connector.lock_state.enabled
|
|
68
|
+
and vehicle.carconnectivity_vehicle.charging.connector.lock_state.value == ChargingConnector.ChargingConnectorLockState.LOCKED):
|
|
69
|
+
LOG.info("Last charging session for vehicle %s is still open during startup, will continue this session", vehicle.vin)
|
|
70
|
+
else:
|
|
71
|
+
LOG.info("Last charging session for vehicle %s is still open during startup, but we are not charging, ignoring it", vehicle.vin)
|
|
72
|
+
self.last_charging_session = None
|
|
73
|
+
else:
|
|
74
|
+
self.last_charging_session = None
|
|
75
|
+
|
|
76
|
+
self.last_charging_state: Optional[ChargingState] = session.query(ChargingState).filter(ChargingState.vehicle == vehicle)\
|
|
77
|
+
.order_by(ChargingState.first_date.desc()).first()
|
|
78
|
+
self.last_charging_state_lock: threading.RLock = threading.RLock()
|
|
79
|
+
|
|
80
|
+
self.last_charging_rate: Optional[ChargingRate] = session.query(ChargingRate).filter(ChargingRate.vehicle == vehicle)\
|
|
81
|
+
.order_by(ChargingRate.first_date.desc()).first()
|
|
82
|
+
self.last_charging_rate_lock: threading.RLock = threading.RLock()
|
|
83
|
+
|
|
84
|
+
self.last_charging_power: Optional[ChargingPower] = session.query(ChargingPower).filter(ChargingPower.vehicle == vehicle)\
|
|
85
|
+
.order_by(ChargingPower.first_date.desc()).first()
|
|
86
|
+
self.last_charging_power_lock: threading.RLock = threading.RLock()
|
|
87
|
+
|
|
88
|
+
vehicle.carconnectivity_vehicle.charging.connector.connection_state.add_observer(self.__on_connector_state_change, Observable.ObserverEvent.UPDATED)
|
|
89
|
+
if vehicle.carconnectivity_vehicle.charging.connector.connection_state.enabled:
|
|
90
|
+
self.__on_connector_state_change(vehicle.carconnectivity_vehicle.charging.connector.connection_state, Observable.ObserverEvent.UPDATED)
|
|
91
|
+
|
|
92
|
+
vehicle.carconnectivity_vehicle.charging.connector.lock_state.add_observer(self.__on_connector_lock_state_change, Observable.ObserverEvent.UPDATED)
|
|
93
|
+
if vehicle.carconnectivity_vehicle.charging.connector.lock_state.enabled:
|
|
94
|
+
self.__on_connector_lock_state_change(vehicle.carconnectivity_vehicle.charging.connector.lock_state, Observable.ObserverEvent.UPDATED)
|
|
95
|
+
|
|
96
|
+
vehicle.carconnectivity_vehicle.charging.state.add_observer(self.__on_charging_state_change, Observable.ObserverEvent.UPDATED)
|
|
97
|
+
if vehicle.carconnectivity_vehicle.charging.state.enabled:
|
|
98
|
+
self.__on_charging_state_change(vehicle.carconnectivity_vehicle.charging.state, Observable.ObserverEvent.UPDATED)
|
|
99
|
+
|
|
100
|
+
vehicle.carconnectivity_vehicle.charging.rate.add_observer(self.__on_charging_rate_change, Observable.ObserverEvent.UPDATED)
|
|
101
|
+
if vehicle.carconnectivity_vehicle.charging.rate.enabled:
|
|
102
|
+
self.__on_charging_rate_change(vehicle.carconnectivity_vehicle.charging.rate, Observable.ObserverEvent.UPDATED)
|
|
103
|
+
|
|
104
|
+
vehicle.carconnectivity_vehicle.charging.power.add_observer(self.__on_charging_power_change, Observable.ObserverEvent.UPDATED)
|
|
105
|
+
if vehicle.carconnectivity_vehicle.charging.power.enabled:
|
|
106
|
+
self.__on_charging_power_change(vehicle.carconnectivity_vehicle.charging.power, Observable.ObserverEvent.UPDATED)
|
|
107
|
+
self.session_factory.remove()
|
|
108
|
+
|
|
109
|
+
def __on_charging_state_change(self, element: EnumAttribute[Charging.ChargingState], flags: Observable.ObserverEvent) -> None:
|
|
110
|
+
del flags
|
|
111
|
+
if self.vehicle.carconnectivity_vehicle is None:
|
|
112
|
+
raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
|
|
113
|
+
|
|
114
|
+
if element.enabled:
|
|
115
|
+
with self.session_factory() as session:
|
|
116
|
+
with self.last_charging_state_lock:
|
|
117
|
+
if self.last_charging_state is not None:
|
|
118
|
+
self.last_charging_state = session.merge(self.last_charging_state)
|
|
119
|
+
session.refresh(self.last_charging_state)
|
|
120
|
+
if (self.last_charging_state is None or self.last_charging_state.state != element.value) \
|
|
121
|
+
and element.last_updated is not None:
|
|
122
|
+
new_charging_state: ChargingState = ChargingState(vin=self.vehicle.vin, first_date=element.last_updated,
|
|
123
|
+
last_date=element.last_updated, state=element.value)
|
|
124
|
+
try:
|
|
125
|
+
session.add(new_charging_state)
|
|
126
|
+
session.commit()
|
|
127
|
+
LOG.debug('Added new charging state %s for vehicle %s to database', element.value, self.vehicle.vin)
|
|
128
|
+
self.last_charging_state = new_charging_state
|
|
129
|
+
except DatabaseError as err:
|
|
130
|
+
session.rollback()
|
|
131
|
+
LOG.error('DatabaseError while adding charging state for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
132
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
133
|
+
|
|
134
|
+
elif self.last_charging_state is not None and self.last_charging_state.state == element.value and element.last_updated is not None:
|
|
135
|
+
if self.last_charging_state.last_date is None or element.last_updated > self.last_charging_state.last_date:
|
|
136
|
+
try:
|
|
137
|
+
self.last_charging_state.last_date = element.last_updated
|
|
138
|
+
session.commit()
|
|
139
|
+
LOG.debug('Updated charging state %s for vehicle %s in database', element.value, self.vehicle.vin)
|
|
140
|
+
except DatabaseError as err:
|
|
141
|
+
session.rollback()
|
|
142
|
+
LOG.error('DatabaseError while updating charging state for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
143
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
144
|
+
|
|
145
|
+
with self.last_charging_session_lock:
|
|
146
|
+
if self.last_charging_session is not None:
|
|
147
|
+
self.last_charging_session = session.merge(self.last_charging_session)
|
|
148
|
+
session.refresh(self.last_charging_session)
|
|
149
|
+
|
|
150
|
+
if element.value in (Charging.ChargingState.CHARGING, Charging.ChargingState.CONSERVATION) \
|
|
151
|
+
and self.carconnectivity_last_charging_state not in (Charging.ChargingState.CHARGING, Charging.ChargingState.CONSERVATION):
|
|
152
|
+
if self.last_charging_session is None or self.last_charging_session.is_closed():
|
|
153
|
+
# check that we are not resuming an old session
|
|
154
|
+
allowed_interrupt: timedelta = timedelta(hours=24)
|
|
155
|
+
# we allow longer CONSERVATION within the session
|
|
156
|
+
if element.value == Charging.ChargingState.CONSERVATION:
|
|
157
|
+
allowed_interrupt = timedelta(hours=300)
|
|
158
|
+
# We can reuse the session if the vehicle was connected and not disconnected in the meantime
|
|
159
|
+
# And the session end date was not set or is within the allowed interrupt time
|
|
160
|
+
if self.last_charging_session is not None \
|
|
161
|
+
and self.last_charging_session.was_connected() and not self.last_charging_session.was_disconnected() \
|
|
162
|
+
and (self.last_charging_session.session_end_date is None or element.last_changed is None
|
|
163
|
+
or self.last_charging_session.session_end_date > (element.last_changed - allowed_interrupt)):
|
|
164
|
+
LOG.debug("Continuing existing charging session for vehicle %s", self.vehicle.vin)
|
|
165
|
+
try:
|
|
166
|
+
self.last_charging_session.session_end_date = None
|
|
167
|
+
self.last_charging_session.end_level = None
|
|
168
|
+
session.commit()
|
|
169
|
+
except DatabaseError as err:
|
|
170
|
+
session.rollback()
|
|
171
|
+
LOG.error('DatabaseError while updating charging session for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
172
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
173
|
+
else:
|
|
174
|
+
LOG.info("Starting new charging session for vehicle %s", self.vehicle.vin)
|
|
175
|
+
new_session: ChargingSession = ChargingSession(vin=self.vehicle.vin, session_start_date=element.last_changed)
|
|
176
|
+
try:
|
|
177
|
+
session.add(new_session)
|
|
178
|
+
LOG.debug('Added new charging session for vehicle %s to database', self.vehicle.vin)
|
|
179
|
+
self._update_session_odometer(session, new_session)
|
|
180
|
+
self._update_session_position(session, new_session)
|
|
181
|
+
self._update_session_charging_type(session, new_session)
|
|
182
|
+
self.last_charging_session = new_session
|
|
183
|
+
session.commit()
|
|
184
|
+
except DatabaseError as err:
|
|
185
|
+
session.rollback()
|
|
186
|
+
LOG.error('DatabaseError while adding charging session for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
187
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
188
|
+
else:
|
|
189
|
+
if self.last_charging_session.was_started():
|
|
190
|
+
LOG.debug("Continuing existing charging session for vehicle %s", self.vehicle.vin)
|
|
191
|
+
else:
|
|
192
|
+
LOG.debug("Starting charging in existing charging session for vehicle %s", self.vehicle.vin)
|
|
193
|
+
try:
|
|
194
|
+
self.last_charging_session.session_start_date = element.last_changed
|
|
195
|
+
self._update_session_odometer(session, self.last_charging_session)
|
|
196
|
+
self._update_session_position(session, self.last_charging_session)
|
|
197
|
+
self._update_session_charging_type(session, self.last_charging_session)
|
|
198
|
+
session.commit()
|
|
199
|
+
except DatabaseError as err:
|
|
200
|
+
session.rollback()
|
|
201
|
+
LOG.error('DatabaseError while starting charging session for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
202
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
203
|
+
# Update startlevel at beginning of charging
|
|
204
|
+
if self.last_charging_session is not None and isinstance(self.vehicle.carconnectivity_vehicle, ElectricVehicle):
|
|
205
|
+
electric_drive: Optional[ElectricDrive] = self.vehicle.carconnectivity_vehicle.get_electric_drive()
|
|
206
|
+
if electric_drive is not None and electric_drive.level.enabled and electric_drive.level.value is not None:
|
|
207
|
+
try:
|
|
208
|
+
self.last_charging_session.start_level = electric_drive.level.value
|
|
209
|
+
session.commit()
|
|
210
|
+
except DatabaseError as err:
|
|
211
|
+
session.rollback()
|
|
212
|
+
LOG.error('DatabaseError while setting start level for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
213
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
214
|
+
elif element.value not in (Charging.ChargingState.CHARGING, Charging.ChargingState.CONSERVATION) \
|
|
215
|
+
and self.carconnectivity_last_charging_state in (Charging.ChargingState.CHARGING, Charging.ChargingState.CONSERVATION):
|
|
216
|
+
if self.last_charging_session is not None and not self.last_charging_session.was_ended():
|
|
217
|
+
LOG.info("Ending charging session for vehicle %s", self.vehicle.vin)
|
|
218
|
+
try:
|
|
219
|
+
self.last_charging_session.session_end_date = element.last_changed
|
|
220
|
+
session.commit()
|
|
221
|
+
except DatabaseError as err:
|
|
222
|
+
session.rollback()
|
|
223
|
+
LOG.error('DatabaseError while ending charging session for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
224
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
225
|
+
if isinstance(self.vehicle.carconnectivity_vehicle, ElectricVehicle):
|
|
226
|
+
electric_drive: Optional[ElectricDrive] = self.vehicle.carconnectivity_vehicle.get_electric_drive()
|
|
227
|
+
if electric_drive is not None and electric_drive.level.enabled and electric_drive.level.value is not None:
|
|
228
|
+
try:
|
|
229
|
+
self.last_charging_session.end_level = electric_drive.level.value
|
|
230
|
+
session.commit()
|
|
231
|
+
except DatabaseError as err:
|
|
232
|
+
session.rollback()
|
|
233
|
+
LOG.error('DatabaseError while setting start level for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
234
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
235
|
+
self.carconnectivity_last_charging_state = element.value
|
|
236
|
+
self.session_factory.remove()
|
|
237
|
+
|
|
238
|
+
def __on_charging_rate_change(self, element: SpeedAttribute, flags: Observable.ObserverEvent) -> None:
|
|
239
|
+
del flags
|
|
240
|
+
if self.vehicle.carconnectivity_vehicle is None:
|
|
241
|
+
raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
|
|
242
|
+
if element.enabled:
|
|
243
|
+
with self.last_charging_rate_lock:
|
|
244
|
+
with self.session_factory() as session:
|
|
245
|
+
if self.last_charging_rate is not None:
|
|
246
|
+
self.last_charging_rate = session.merge(self.last_charging_rate)
|
|
247
|
+
session.refresh(self.last_charging_rate)
|
|
248
|
+
if (self.last_charging_rate is None or self.last_charging_rate.rate != element.value) \
|
|
249
|
+
and element.last_updated is not None:
|
|
250
|
+
new_charging_rate: ChargingRate = ChargingRate(vin=self.vehicle.vin, first_date=element.last_updated,
|
|
251
|
+
last_date=element.last_updated, rate=element.value)
|
|
252
|
+
try:
|
|
253
|
+
session.add(new_charging_rate)
|
|
254
|
+
session.commit()
|
|
255
|
+
LOG.debug('Added new charging rate %s for vehicle %s to database', element.value, self.vehicle.vin)
|
|
256
|
+
self.last_charging_rate = new_charging_rate
|
|
257
|
+
except DatabaseError as err:
|
|
258
|
+
session.rollback()
|
|
259
|
+
LOG.error('DatabaseError while adding charging rate for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
260
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
261
|
+
elif self.last_charging_rate is not None and self.last_charging_rate.rate == element.value and element.last_updated is not None:
|
|
262
|
+
if self.last_charging_rate.last_date is None or element.last_updated > self.last_charging_rate.last_date:
|
|
263
|
+
try:
|
|
264
|
+
self.last_charging_rate.last_date = element.last_updated
|
|
265
|
+
session.commit()
|
|
266
|
+
LOG.debug('Updated charging rate %s for vehicle %s in database', element.value, self.vehicle.vin)
|
|
267
|
+
except DatabaseError as err:
|
|
268
|
+
session.rollback()
|
|
269
|
+
LOG.error('DatabaseError while updating charging rate for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
270
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
271
|
+
self.session_factory.remove()
|
|
272
|
+
|
|
273
|
+
def __on_charging_power_change(self, element: PowerAttribute, flags: Observable.ObserverEvent) -> None:
|
|
274
|
+
del flags
|
|
275
|
+
if self.vehicle.carconnectivity_vehicle is None:
|
|
276
|
+
raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
|
|
277
|
+
if element.enabled:
|
|
278
|
+
with self.last_charging_power_lock:
|
|
279
|
+
with self.session_factory() as session:
|
|
280
|
+
if self.last_charging_power is not None:
|
|
281
|
+
self.last_charging_power = session.merge(self.last_charging_power)
|
|
282
|
+
session.refresh(self.last_charging_power)
|
|
283
|
+
if (self.last_charging_power is None or self.last_charging_power.power != element.value) \
|
|
284
|
+
and element.last_updated is not None:
|
|
285
|
+
new_charging_power: ChargingPower = ChargingPower(vin=self.vehicle.vin, first_date=element.last_updated,
|
|
286
|
+
last_date=element.last_updated, power=element.value)
|
|
287
|
+
try:
|
|
288
|
+
session.add(new_charging_power)
|
|
289
|
+
session.commit()
|
|
290
|
+
LOG.debug('Added new charging power %s for vehicle %s to database', element.value, self.vehicle.vin)
|
|
291
|
+
self.last_charging_power = new_charging_power
|
|
292
|
+
except DatabaseError as err:
|
|
293
|
+
session.rollback()
|
|
294
|
+
LOG.error('DatabaseError while adding charging power for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
295
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
296
|
+
elif self.last_charging_power is not None and self.last_charging_power.power == element.value and element.last_updated is not None:
|
|
297
|
+
if self.last_charging_power.last_date is None or element.last_updated > self.last_charging_power.last_date:
|
|
298
|
+
try:
|
|
299
|
+
self.last_charging_power.last_date = element.last_updated
|
|
300
|
+
LOG.debug('Updated charging power %s for vehicle %s in database', element.value, self.vehicle.vin)
|
|
301
|
+
except DatabaseError as err:
|
|
302
|
+
session.rollback()
|
|
303
|
+
LOG.error('DatabaseError while updating charging power for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
304
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
305
|
+
self.session_factory.remove()
|
|
306
|
+
|
|
307
|
+
def __on_connector_state_change(self, element: EnumAttribute[ChargingConnector.ChargingConnectorConnectionState], flags: Observable.ObserverEvent) -> None:
|
|
308
|
+
del flags
|
|
309
|
+
if self.vehicle.carconnectivity_vehicle is None:
|
|
310
|
+
raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
|
|
311
|
+
|
|
312
|
+
with self.session_factory() as session:
|
|
313
|
+
with self.last_charging_session_lock:
|
|
314
|
+
if self.last_charging_session is not None:
|
|
315
|
+
self.last_charging_session = session.merge(self.last_charging_session)
|
|
316
|
+
session.refresh(self.last_charging_session)
|
|
317
|
+
|
|
318
|
+
if element.value == ChargingConnector.ChargingConnectorConnectionState.CONNECTED \
|
|
319
|
+
and self.carconnectivity_last_connector_state != ChargingConnector.ChargingConnectorConnectionState.CONNECTED:
|
|
320
|
+
if self.last_charging_session is None or self.last_charging_session.is_closed():
|
|
321
|
+
LOG.info("Starting new charging session for vehicle %s due to connector connected state", self.vehicle.vin)
|
|
322
|
+
new_session: ChargingSession = ChargingSession(vin=self.vehicle.vin, plug_connected_date=element.last_changed)
|
|
323
|
+
try:
|
|
324
|
+
session.add(new_session)
|
|
325
|
+
self._update_session_odometer(session, new_session)
|
|
326
|
+
self._update_session_position(session, new_session)
|
|
327
|
+
session.commit()
|
|
328
|
+
LOG.debug('Added new charging session for vehicle %s to database', self.vehicle.vin)
|
|
329
|
+
self.last_charging_session = new_session
|
|
330
|
+
except DatabaseError as err:
|
|
331
|
+
session.rollback()
|
|
332
|
+
LOG.error('DatabaseError while adding charging session for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
333
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
334
|
+
elif not self.last_charging_session.was_connected():
|
|
335
|
+
LOG.debug("Continuing existing charging session for vehicle %s, writing connected date", self.vehicle.vin)
|
|
336
|
+
try:
|
|
337
|
+
self.last_charging_session.plug_connected_date = element.last_changed
|
|
338
|
+
self._update_session_odometer(session, self.last_charging_session)
|
|
339
|
+
self._update_session_position(session, self.last_charging_session)
|
|
340
|
+
session.commit()
|
|
341
|
+
except DatabaseError as err:
|
|
342
|
+
session.rollback()
|
|
343
|
+
LOG.error('DatabaseError while starting charging session for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
344
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
345
|
+
elif element.value != ChargingConnector.ChargingConnectorConnectionState.CONNECTED \
|
|
346
|
+
and self.carconnectivity_last_connector_state == ChargingConnector.ChargingConnectorConnectionState.CONNECTED:
|
|
347
|
+
if self.last_charging_session is not None and not self.last_charging_session.was_disconnected():
|
|
348
|
+
LOG.info("Writing plug disconnected date for charging session of vehicle %s", self.vehicle.vin)
|
|
349
|
+
try:
|
|
350
|
+
self.last_charging_session.plug_disconnected_date = element.last_changed
|
|
351
|
+
session.commit()
|
|
352
|
+
except DatabaseError as err:
|
|
353
|
+
session.rollback()
|
|
354
|
+
LOG.error('DatabaseError while ending 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
|
+
# Create charging session when connected at startup
|
|
357
|
+
elif element.value == ChargingConnector.ChargingConnectorConnectionState.CONNECTED \
|
|
358
|
+
and self.carconnectivity_last_connector_state == ChargingConnector.ChargingConnectorConnectionState.CONNECTED:
|
|
359
|
+
if self.last_charging_session is None or self.last_charging_session.is_closed():
|
|
360
|
+
LOG.info("Starting new charging session for vehicle %s due to connector connected state", self.vehicle.vin)
|
|
361
|
+
new_session: ChargingSession = ChargingSession(vin=self.vehicle.vin, plug_connected_date=element.last_changed)
|
|
362
|
+
try:
|
|
363
|
+
session.add(new_session)
|
|
364
|
+
self._update_session_odometer(session, new_session)
|
|
365
|
+
self._update_session_position(session, new_session)
|
|
366
|
+
session.commit()
|
|
367
|
+
LOG.debug('Added new charging session for vehicle %s to database', self.vehicle.vin)
|
|
368
|
+
self.last_charging_session = new_session
|
|
369
|
+
except DatabaseError as err:
|
|
370
|
+
session.rollback()
|
|
371
|
+
LOG.error('DatabaseError while adding charging session for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
372
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
373
|
+
elif self.last_charging_session is not None and not self.last_charging_session.was_connected():
|
|
374
|
+
try:
|
|
375
|
+
self.last_charging_session.plug_connected_date = element.last_changed
|
|
376
|
+
session.commit()
|
|
377
|
+
LOG.info("Writing plug connected date for charging session of vehicle %s", self.vehicle.vin)
|
|
378
|
+
except DatabaseError as err:
|
|
379
|
+
session.rollback()
|
|
380
|
+
LOG.error('DatabaseError while changing charging session for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
381
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
382
|
+
self.carconnectivity_last_connector_state = element.value
|
|
383
|
+
self.session_factory.remove()
|
|
384
|
+
|
|
385
|
+
def __on_connector_lock_state_change(self, element: EnumAttribute[ChargingConnector.ChargingConnectorLockState], flags: Observable.ObserverEvent) -> None:
|
|
386
|
+
del flags
|
|
387
|
+
if self.vehicle.carconnectivity_vehicle is None:
|
|
388
|
+
raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
|
|
389
|
+
|
|
390
|
+
with self.session_factory() as session:
|
|
391
|
+
with self.last_charging_session_lock:
|
|
392
|
+
if self.last_charging_session is not None:
|
|
393
|
+
self.last_charging_session = session.merge(self.last_charging_session)
|
|
394
|
+
session.refresh(self.last_charging_session)
|
|
395
|
+
|
|
396
|
+
if element.value == ChargingConnector.ChargingConnectorLockState.LOCKED \
|
|
397
|
+
and self.carconnectivity_last_connector_lock_state != ChargingConnector.ChargingConnectorLockState.LOCKED:
|
|
398
|
+
if self.last_charging_session is None or self.last_charging_session.is_closed():
|
|
399
|
+
LOG.info("Starting new charging session for vehicle %s due to connector locked state", self.vehicle.vin)
|
|
400
|
+
new_session: ChargingSession = ChargingSession(vin=self.vehicle.vin, plug_locked_date=element.last_changed)
|
|
401
|
+
try:
|
|
402
|
+
session.add(new_session)
|
|
403
|
+
self._update_session_odometer(session, new_session)
|
|
404
|
+
self._update_session_position(session, new_session)
|
|
405
|
+
session.commit()
|
|
406
|
+
LOG.debug('Added new charging session for vehicle %s to database', self.vehicle.vin)
|
|
407
|
+
self.last_charging_session = new_session
|
|
408
|
+
except DatabaseError as err:
|
|
409
|
+
session.rollback()
|
|
410
|
+
LOG.error('DatabaseError while adding charging session for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
411
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
412
|
+
elif not self.last_charging_session.was_locked():
|
|
413
|
+
LOG.debug("Continuing existing charging session for vehicle %s, writing locked date", self.vehicle.vin)
|
|
414
|
+
try:
|
|
415
|
+
self.last_charging_session.plug_locked_date = element.last_changed
|
|
416
|
+
self._update_session_odometer(session, self.last_charging_session)
|
|
417
|
+
self._update_session_position(session, self.last_charging_session)
|
|
418
|
+
session.commit()
|
|
419
|
+
except DatabaseError as err:
|
|
420
|
+
session.rollback()
|
|
421
|
+
LOG.error('DatabaseError while starting charging session for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
422
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
423
|
+
elif element.value != ChargingConnector.ChargingConnectorLockState.LOCKED \
|
|
424
|
+
and self.carconnectivity_last_connector_lock_state == ChargingConnector.ChargingConnectorLockState.LOCKED:
|
|
425
|
+
if self.last_charging_session is not None and not self.last_charging_session.was_unlocked():
|
|
426
|
+
LOG.info("Writing plug unlocked date for charging session of vehicle %s", self.vehicle.vin)
|
|
427
|
+
try:
|
|
428
|
+
self.last_charging_session.plug_unlocked_date = element.last_changed
|
|
429
|
+
session.commit()
|
|
430
|
+
except DatabaseError as err:
|
|
431
|
+
session.rollback()
|
|
432
|
+
LOG.error('DatabaseError while ending charging session for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
433
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
434
|
+
# Create charging session when locked at startup
|
|
435
|
+
elif element.value == ChargingConnector.ChargingConnectorLockState.LOCKED \
|
|
436
|
+
and self.carconnectivity_last_connector_lock_state == ChargingConnector.ChargingConnectorLockState.LOCKED:
|
|
437
|
+
if self.last_charging_session is None or self.last_charging_session.is_closed():
|
|
438
|
+
LOG.info("Starting new charging session for vehicle %s due to connector locked state", self.vehicle.vin)
|
|
439
|
+
new_session: ChargingSession = ChargingSession(vin=self.vehicle.vin, plug_locked_date=element.last_changed)
|
|
440
|
+
try:
|
|
441
|
+
session.add(new_session)
|
|
442
|
+
self._update_session_odometer(session, new_session)
|
|
443
|
+
self._update_session_position(session, new_session)
|
|
444
|
+
session.commit()
|
|
445
|
+
LOG.debug('Added new charging session for vehicle %s to database', self.vehicle.vin)
|
|
446
|
+
self.last_charging_session = new_session
|
|
447
|
+
except DatabaseError as err:
|
|
448
|
+
session.rollback()
|
|
449
|
+
LOG.error('DatabaseError while adding charging session for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
450
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
451
|
+
elif self.last_charging_session is not None and not self.last_charging_session.was_locked():
|
|
452
|
+
try:
|
|
453
|
+
self.last_charging_session.plug_locked_date = element.last_changed
|
|
454
|
+
session.commit()
|
|
455
|
+
LOG.info("Writing plug locked date for charging session of vehicle %s", self.vehicle.vin)
|
|
456
|
+
except DatabaseError as err:
|
|
457
|
+
session.rollback()
|
|
458
|
+
LOG.error('DatabaseError while changing charging session for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
459
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
460
|
+
self.carconnectivity_last_connector_lock_state = element.value
|
|
461
|
+
self.session_factory.remove()
|
|
462
|
+
|
|
463
|
+
def _update_session_odometer(self, session: Session, charging_session: ChargingSession) -> None:
|
|
464
|
+
if self.vehicle.carconnectivity_vehicle is None:
|
|
465
|
+
raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
|
|
466
|
+
if self.vehicle.carconnectivity_vehicle.odometer.enabled:
|
|
467
|
+
if charging_session.session_odometer is None:
|
|
468
|
+
try:
|
|
469
|
+
charging_session.session_odometer = self.vehicle.carconnectivity_vehicle.odometer.value
|
|
470
|
+
except DatabaseError as err:
|
|
471
|
+
session.rollback()
|
|
472
|
+
LOG.error('DatabaseError while updating odometer for charging session of vehicle %s in database: %s', self.vehicle.vin, err)
|
|
473
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
474
|
+
|
|
475
|
+
def _update_session_charging_type(self, session: Session, charging_session: ChargingSession) -> None:
|
|
476
|
+
if self.vehicle.carconnectivity_vehicle is None:
|
|
477
|
+
raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
|
|
478
|
+
if isinstance(self.vehicle.carconnectivity_vehicle, ElectricVehicle) and self.vehicle.carconnectivity_vehicle.charging.type.enabled \
|
|
479
|
+
and self.vehicle.carconnectivity_vehicle.charging.type.value is not None:
|
|
480
|
+
if charging_session.charging_type is None:
|
|
481
|
+
try:
|
|
482
|
+
charging_session.charging_type = self.vehicle.carconnectivity_vehicle.charging.type.value
|
|
483
|
+
except DatabaseError as err:
|
|
484
|
+
session.rollback()
|
|
485
|
+
LOG.error('DatabaseError while updating charging type for charging session of vehicle %s in database: %s', self.vehicle.vin, err)
|
|
486
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
487
|
+
|
|
488
|
+
def _update_session_position(self, session: Session, charging_session: ChargingSession) -> None:
|
|
489
|
+
if self.vehicle.carconnectivity_vehicle is None:
|
|
490
|
+
raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
|
|
491
|
+
if self.vehicle.carconnectivity_vehicle.position.enabled and self.vehicle.carconnectivity_vehicle.position.latitude.enabled \
|
|
492
|
+
and self.vehicle.carconnectivity_vehicle.position.longitude.enabled \
|
|
493
|
+
and self.vehicle.carconnectivity_vehicle.position.latitude.value is not None \
|
|
494
|
+
and self.vehicle.carconnectivity_vehicle.position.longitude.value is not None:
|
|
495
|
+
if charging_session.session_position_latitude is None and charging_session.session_position_longitude is None:
|
|
496
|
+
try:
|
|
497
|
+
charging_session.session_position_latitude = self.vehicle.carconnectivity_vehicle.position.latitude.value
|
|
498
|
+
charging_session.session_position_longitude = self.vehicle.carconnectivity_vehicle.position.longitude.value
|
|
499
|
+
except DatabaseError as err:
|
|
500
|
+
session.rollback()
|
|
501
|
+
LOG.error('DatabaseError while updating position for charging session of vehicle %s in database: %s', self.vehicle.vin, err)
|
|
502
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
503
|
+
if charging_session.location is None and self.vehicle.carconnectivity_vehicle.position.location.enabled:
|
|
504
|
+
location: Location = Location.from_carconnectivity_location(location=self.vehicle.carconnectivity_vehicle.position.location)
|
|
505
|
+
try:
|
|
506
|
+
location = session.merge(location)
|
|
507
|
+
charging_session.location = location
|
|
508
|
+
except DatabaseError as err:
|
|
509
|
+
session.rollback()
|
|
510
|
+
LOG.error('DatabaseError while merging location for charging session of vehicle %s in database: %s', self.vehicle.vin, err)
|
|
511
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
512
|
+
if charging_session.charging_station is None \
|
|
513
|
+
and isinstance(self.vehicle.carconnectivity_vehicle, ElectricVehicle) and self.vehicle.carconnectivity_vehicle.charging is not None \
|
|
514
|
+
and self.vehicle.carconnectivity_vehicle.charging.enabled and self.vehicle.carconnectivity_vehicle.charging.charging_station.enabled:
|
|
515
|
+
charging_station: ChargingStation = ChargingStation.from_carconnectivity_charging_station(
|
|
516
|
+
charging_station=self.vehicle.carconnectivity_vehicle.charging.charging_station)
|
|
517
|
+
try:
|
|
518
|
+
charging_station = session.merge(charging_station)
|
|
519
|
+
charging_session.charging_station = charging_station
|
|
520
|
+
except DatabaseError as err:
|
|
521
|
+
session.rollback()
|
|
522
|
+
LOG.error('DatabaseError while merging charging station for charging session of vehicle %s in database: %s', self.vehicle.vin, err)
|
|
523
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
|
+
|
|
4
|
+
import threading
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
|
|
8
|
+
from sqlalchemy.exc import DatabaseError
|
|
9
|
+
|
|
10
|
+
from carconnectivity.observable import Observable
|
|
11
|
+
|
|
12
|
+
from carconnectivity_plugins.database.agents.base_agent import BaseAgent
|
|
13
|
+
from carconnectivity_plugins.database.model.climatization_state import ClimatizationState
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from typing import Optional
|
|
17
|
+
from sqlalchemy.orm import scoped_session
|
|
18
|
+
from sqlalchemy.orm.session import Session
|
|
19
|
+
|
|
20
|
+
from carconnectivity.attributes import EnumAttribute
|
|
21
|
+
|
|
22
|
+
from carconnectivity.climatization import Climatization
|
|
23
|
+
|
|
24
|
+
from carconnectivity_plugins.database.plugin import Plugin
|
|
25
|
+
from carconnectivity_plugins.database.model.vehicle import Vehicle
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
LOG: logging.Logger = logging.getLogger("carconnectivity.plugins.database.agents.climatization_agent")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ClimatizationAgent(BaseAgent):
|
|
32
|
+
def __init__(self, database_plugin: Plugin, session_factory: scoped_session[Session], vehicle: Vehicle) -> None:
|
|
33
|
+
if vehicle is None or vehicle.carconnectivity_vehicle is None:
|
|
34
|
+
raise ValueError("Vehicle or its carconnectivity_vehicle attribute is None")
|
|
35
|
+
self.database_plugin: Plugin = database_plugin
|
|
36
|
+
self.session_factory: scoped_session[Session] = session_factory
|
|
37
|
+
self.vehicle: Vehicle = vehicle
|
|
38
|
+
|
|
39
|
+
with self.session_factory() as session:
|
|
40
|
+
self.last_state: Optional[ClimatizationState] = session.query(ClimatizationState).filter(ClimatizationState.vehicle == vehicle)\
|
|
41
|
+
.order_by(ClimatizationState.first_date.desc()).first()
|
|
42
|
+
self.last_state_lock: threading.RLock = threading.RLock()
|
|
43
|
+
|
|
44
|
+
vehicle.carconnectivity_vehicle.climatization.state.add_observer(self.__on_state_change, Observable.ObserverEvent.UPDATED)
|
|
45
|
+
self.__on_state_change(vehicle.carconnectivity_vehicle.climatization.state, Observable.ObserverEvent.UPDATED)
|
|
46
|
+
self.session_factory.remove()
|
|
47
|
+
|
|
48
|
+
def __on_state_change(self, element: EnumAttribute[Climatization.ClimatizationState], flags: Observable.ObserverEvent) -> None:
|
|
49
|
+
del flags
|
|
50
|
+
if element.enabled:
|
|
51
|
+
with self.last_state_lock:
|
|
52
|
+
with self.session_factory() as session:
|
|
53
|
+
if self.last_state is not None:
|
|
54
|
+
self.last_state = session.merge(self.last_state)
|
|
55
|
+
session.refresh(self.last_state)
|
|
56
|
+
if (self.last_state is None or self.last_state.state != element.value) \
|
|
57
|
+
and element.last_updated is not None:
|
|
58
|
+
new_state: ClimatizationState = ClimatizationState(vin=self.vehicle.vin, first_date=element.last_updated,
|
|
59
|
+
last_date=element.last_updated, state=element.value)
|
|
60
|
+
try:
|
|
61
|
+
session.add(new_state)
|
|
62
|
+
session.commit()
|
|
63
|
+
LOG.debug('Added new climatization state %s for vehicle %s to database', element.value, self.vehicle.vin)
|
|
64
|
+
self.last_state = new_state
|
|
65
|
+
except DatabaseError as err:
|
|
66
|
+
session.rollback()
|
|
67
|
+
LOG.error('DatabaseError while adding climatizationstate for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
68
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
69
|
+
|
|
70
|
+
elif self.last_state is not None and self.last_state.state == element.value and element.last_updated is not None:
|
|
71
|
+
if self.last_state.last_date is None or element.last_updated > self.last_state.last_date:
|
|
72
|
+
try:
|
|
73
|
+
self.last_state.last_date = element.last_updated
|
|
74
|
+
session.commit()
|
|
75
|
+
LOG.debug('Updated climatizationstate %s for vehicle %s in database', element.value, self.vehicle.vin)
|
|
76
|
+
except DatabaseError as err:
|
|
77
|
+
session.rollback()
|
|
78
|
+
LOG.error('DatabaseError while updating climatizationstate for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
79
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
80
|
+
self.session_factory.remove()
|