carconnectivity-plugin-database 0.1a16__py3-none-any.whl → 0.1a21__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.1a16.dist-info → carconnectivity_plugin_database-0.1a21.dist-info}/METADATA +1 -1
- {carconnectivity_plugin_database-0.1a16.dist-info → carconnectivity_plugin_database-0.1a21.dist-info}/RECORD +16 -16
- carconnectivity_plugins/database/_version.py +2 -2
- carconnectivity_plugins/database/agents/charging_agent.py +189 -88
- carconnectivity_plugins/database/agents/climatization_agent.py +13 -6
- carconnectivity_plugins/database/agents/drive_state_agent.py +148 -96
- carconnectivity_plugins/database/agents/state_agent.py +26 -14
- carconnectivity_plugins/database/agents/trip_agent.py +48 -37
- carconnectivity_plugins/database/model/charging_session.py +7 -7
- carconnectivity_plugins/database/model/drive.py +6 -6
- carconnectivity_plugins/database/model/vehicle.py +36 -34
- carconnectivity_plugins/database/plugin.py +8 -12
- {carconnectivity_plugin_database-0.1a16.dist-info → carconnectivity_plugin_database-0.1a21.dist-info}/WHEEL +0 -0
- {carconnectivity_plugin_database-0.1a16.dist-info → carconnectivity_plugin_database-0.1a21.dist-info}/entry_points.txt +0 -0
- {carconnectivity_plugin_database-0.1a16.dist-info → carconnectivity_plugin_database-0.1a21.dist-info}/licenses/LICENSE +0 -0
- {carconnectivity_plugin_database-0.1a16.dist-info → carconnectivity_plugin_database-0.1a21.dist-info}/top_level.txt +0 -0
|
@@ -18,9 +18,11 @@ if TYPE_CHECKING:
|
|
|
18
18
|
from sqlalchemy.orm.session import Session
|
|
19
19
|
|
|
20
20
|
from carconnectivity.attributes import EnumAttribute
|
|
21
|
+
from carconnectivity.vehicle import GenericVehicle
|
|
21
22
|
|
|
22
23
|
from carconnectivity.climatization import Climatization
|
|
23
24
|
|
|
25
|
+
from carconnectivity_plugins.database.plugin import Plugin
|
|
24
26
|
from carconnectivity_plugins.database.model.vehicle import Vehicle
|
|
25
27
|
|
|
26
28
|
|
|
@@ -28,19 +30,21 @@ LOG: logging.Logger = logging.getLogger("carconnectivity.plugins.database.agents
|
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
class ClimatizationAgent(BaseAgent):
|
|
31
|
-
def __init__(self, session_factory: scoped_session[Session], vehicle: Vehicle) -> None:
|
|
32
|
-
if vehicle is None or
|
|
33
|
+
def __init__(self, database_plugin: Plugin, session_factory: scoped_session[Session], vehicle: Vehicle, carconnectivity_vehicle: GenericVehicle) -> None:
|
|
34
|
+
if vehicle is None or carconnectivity_vehicle is None:
|
|
33
35
|
raise ValueError("Vehicle or its carconnectivity_vehicle attribute is None")
|
|
36
|
+
self.database_plugin: Plugin = database_plugin
|
|
34
37
|
self.session_factory: scoped_session[Session] = session_factory
|
|
35
38
|
self.vehicle: Vehicle = vehicle
|
|
39
|
+
self.carconnectivity_vehicle: GenericVehicle = carconnectivity_vehicle
|
|
36
40
|
|
|
37
41
|
with self.session_factory() as session:
|
|
38
42
|
self.last_state: Optional[ClimatizationState] = session.query(ClimatizationState).filter(ClimatizationState.vehicle == vehicle)\
|
|
39
43
|
.order_by(ClimatizationState.first_date.desc()).first()
|
|
40
44
|
self.last_state_lock: threading.RLock = threading.RLock()
|
|
41
45
|
|
|
42
|
-
|
|
43
|
-
self.__on_state_change(
|
|
46
|
+
self.carconnectivity_vehicle.climatization.state.add_observer(self.__on_state_change, Observable.ObserverEvent.UPDATED)
|
|
47
|
+
self.__on_state_change(self.carconnectivity_vehicle.climatization.state, Observable.ObserverEvent.UPDATED)
|
|
44
48
|
self.session_factory.remove()
|
|
45
49
|
|
|
46
50
|
def __on_state_change(self, element: EnumAttribute[Climatization.ClimatizationState], flags: Observable.ObserverEvent) -> None:
|
|
@@ -51,8 +55,9 @@ class ClimatizationAgent(BaseAgent):
|
|
|
51
55
|
if self.last_state is not None:
|
|
52
56
|
self.last_state = session.merge(self.last_state)
|
|
53
57
|
session.refresh(self.last_state)
|
|
54
|
-
if
|
|
55
|
-
and
|
|
58
|
+
if element.last_updated is not None \
|
|
59
|
+
and (self.last_state is None or (self.last_state.state != element.value
|
|
60
|
+
and element.last_updated > self.last_state.last_date)):
|
|
56
61
|
new_state: ClimatizationState = ClimatizationState(vin=self.vehicle.vin, first_date=element.last_updated,
|
|
57
62
|
last_date=element.last_updated, state=element.value)
|
|
58
63
|
try:
|
|
@@ -63,6 +68,7 @@ class ClimatizationAgent(BaseAgent):
|
|
|
63
68
|
except DatabaseError as err:
|
|
64
69
|
session.rollback()
|
|
65
70
|
LOG.error('DatabaseError while adding climatizationstate for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
71
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
66
72
|
|
|
67
73
|
elif self.last_state is not None and self.last_state.state == element.value and element.last_updated is not None:
|
|
68
74
|
if self.last_state.last_date is None or element.last_updated > self.last_state.last_date:
|
|
@@ -73,4 +79,5 @@ class ClimatizationAgent(BaseAgent):
|
|
|
73
79
|
except DatabaseError as err:
|
|
74
80
|
session.rollback()
|
|
75
81
|
LOG.error('DatabaseError while updating climatizationstate for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
82
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
76
83
|
self.session_factory.remove()
|
|
@@ -8,7 +8,7 @@ import logging
|
|
|
8
8
|
from sqlalchemy.exc import DatabaseError
|
|
9
9
|
|
|
10
10
|
from carconnectivity.observable import Observable
|
|
11
|
-
from carconnectivity.drive import
|
|
11
|
+
from carconnectivity.drive import ElectricDrive, CombustionDrive
|
|
12
12
|
|
|
13
13
|
from carconnectivity_plugins.database.agents.base_agent import BaseAgent
|
|
14
14
|
from carconnectivity_plugins.database.model.drive_level import DriveLevel
|
|
@@ -23,7 +23,9 @@ if TYPE_CHECKING:
|
|
|
23
23
|
|
|
24
24
|
from carconnectivity.attributes import LevelAttribute, RangeAttribute, EnumAttribute, EnergyAttribute, VolumeAttribute, EnergyConsumptionAttribute, \
|
|
25
25
|
FuelConsumptionAttribute
|
|
26
|
+
from carconnectivity.drive import GenericDrive
|
|
26
27
|
|
|
28
|
+
from carconnectivity_plugins.database.plugin import Plugin
|
|
27
29
|
from carconnectivity_plugins.database.model.drive import Drive
|
|
28
30
|
|
|
29
31
|
|
|
@@ -31,87 +33,98 @@ LOG: logging.Logger = logging.getLogger("carconnectivity.plugins.database.agents
|
|
|
31
33
|
|
|
32
34
|
|
|
33
35
|
class DriveStateAgent(BaseAgent):
|
|
34
|
-
def __init__(self, session_factory: scoped_session[Session], drive: Drive) -> None:
|
|
35
|
-
|
|
36
|
-
raise ValueError("Drive or its carconnectivity_drive attribute is None")
|
|
36
|
+
def __init__(self, database_plugin: Plugin, session_factory: scoped_session[Session], drive: Drive, carconnectivity_drive: GenericDrive) -> None:
|
|
37
|
+
self.database_plugin: Plugin = database_plugin
|
|
37
38
|
self.session_factory: scoped_session[Session] = session_factory
|
|
38
39
|
self.drive: Drive = drive
|
|
40
|
+
self.drive_lock: threading.RLock = threading.RLock()
|
|
41
|
+
self.carconnectivity_drive: GenericDrive = carconnectivity_drive
|
|
42
|
+
with self.drive_lock:
|
|
43
|
+
with self.session_factory() as session:
|
|
44
|
+
self.drive = session.merge(self.drive)
|
|
45
|
+
session.refresh(self.drive)
|
|
39
46
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
self.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
self.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
.filter(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
self.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
47
|
+
if self.drive is None or self.carconnectivity_drive is None:
|
|
48
|
+
raise ValueError("Drive or its carconnectivity_drive attribute is None")
|
|
49
|
+
|
|
50
|
+
self.carconnectivity_drive.type.add_observer(self.__on_type_change, Observable.ObserverEvent.VALUE_CHANGED, on_transaction_end=True)
|
|
51
|
+
self.type_lock: threading.RLock = threading.RLock()
|
|
52
|
+
self.__on_type_change(self.carconnectivity_drive.type, Observable.ObserverEvent.VALUE_CHANGED)
|
|
53
|
+
|
|
54
|
+
self.carconnectivity_drive.range_wltp.add_observer(self.__on_range_wltp_change, Observable.ObserverEvent.VALUE_CHANGED,
|
|
55
|
+
on_transaction_end=True)
|
|
56
|
+
self.range_wltp_lock: threading.RLock = threading.RLock()
|
|
57
|
+
self.__on_range_wltp_change(self.carconnectivity_drive.range_wltp, Observable.ObserverEvent.VALUE_CHANGED)
|
|
58
|
+
|
|
59
|
+
if isinstance(self.carconnectivity_drive, ElectricDrive):
|
|
60
|
+
self.carconnectivity_drive.battery.total_capacity.add_observer(self.__on_electric_total_capacity_change,
|
|
61
|
+
Observable.ObserverEvent.VALUE_CHANGED, on_transaction_end=True)
|
|
62
|
+
self.total_capacity_lock: threading.RLock = threading.RLock()
|
|
63
|
+
self.__on_electric_total_capacity_change(self.carconnectivity_drive.battery.total_capacity, Observable.ObserverEvent.VALUE_CHANGED)
|
|
64
|
+
|
|
65
|
+
self.carconnectivity_drive.battery.available_capacity.add_observer(self.__on_electric_available_capacity_change,
|
|
66
|
+
Observable.ObserverEvent.VALUE_CHANGED, on_transaction_end=True)
|
|
67
|
+
self.available_capacity_lock: threading.RLock = threading.RLock()
|
|
68
|
+
self.__on_electric_available_capacity_change(self.carconnectivity_drive.battery.available_capacity,
|
|
69
|
+
Observable.ObserverEvent.VALUE_CHANGED)
|
|
70
|
+
|
|
71
|
+
self.last_electric_consumption: Optional[DriveConsumption] = session.query(DriveConsumption) \
|
|
72
|
+
.filter(DriveConsumption.drive_id == self.drive.id).order_by(DriveConsumption.first_date.desc()).first()
|
|
73
|
+
self.last_electric_consumption_lock: threading.RLock = threading.RLock()
|
|
74
|
+
self.carconnectivity_drive.consumption.add_observer(self.__on_electric_consumption_change,
|
|
75
|
+
Observable.ObserverEvent.VALUE_CHANGED)
|
|
76
|
+
self.__on_electric_consumption_change(self.carconnectivity_drive.consumption, Observable.ObserverEvent.UPDATED)
|
|
77
|
+
|
|
78
|
+
elif isinstance(self.carconnectivity_drive, CombustionDrive):
|
|
79
|
+
self.carconnectivity_drive.fuel_tank.available_capacity.add_observer(self.__on_fuel_available_capacity_change,
|
|
80
|
+
Observable.ObserverEvent.VALUE_CHANGED, on_transaction_end=True)
|
|
81
|
+
self.fuel_available_capacity_lock: threading.RLock = threading.RLock()
|
|
82
|
+
self.__on_fuel_available_capacity_change(self.carconnectivity_drive.fuel_tank.available_capacity, Observable.ObserverEvent.VALUE_CHANGED)
|
|
83
|
+
|
|
84
|
+
self.last_fuel_consumption: Optional[DriveConsumption] = session.query(DriveConsumption) \
|
|
85
|
+
.filter(DriveConsumption.drive_id == self.drive.id).order_by(DriveConsumption.first_date.desc()).first()
|
|
86
|
+
self.last_fuel_consumption_lock: threading.RLock = threading.RLock()
|
|
87
|
+
self.carconnectivity_drive.consumption.add_observer(self.__on_fuel_consumption_change,
|
|
88
|
+
Observable.ObserverEvent.VALUE_CHANGED)
|
|
89
|
+
self.__on_fuel_consumption_change(self.carconnectivity_drive.consumption, Observable.ObserverEvent.UPDATED)
|
|
90
|
+
|
|
91
|
+
self.last_level: Optional[DriveLevel] = session.query(DriveLevel).filter(DriveLevel.drive_id == self.drive.id) \
|
|
92
|
+
.order_by(DriveLevel.first_date.desc()).first()
|
|
93
|
+
self.last_level_lock: threading.RLock = threading.RLock()
|
|
94
|
+
self.last_range: Optional[DriveRange] = session.query(DriveRange).filter(DriveRange.drive_id == self.drive.id) \
|
|
95
|
+
.order_by(DriveRange.first_date.desc()).first()
|
|
96
|
+
self.last_range_lock: threading.RLock = threading.RLock()
|
|
97
|
+
self.last_range_estimated_full: Optional[DriveRangeEstimatedFull] = session.query(DriveRangeEstimatedFull) \
|
|
98
|
+
.filter(DriveRangeEstimatedFull.drive_id == self.drive.id).order_by(DriveRangeEstimatedFull.first_date.desc()).first()
|
|
99
|
+
self.last_range_estimated_full_lock: threading.RLock = threading.RLock()
|
|
100
|
+
|
|
101
|
+
if self.carconnectivity_drive is not None:
|
|
102
|
+
self.carconnectivity_drive.level.add_observer(self.__on_level_change, Observable.ObserverEvent.UPDATED)
|
|
103
|
+
if self.carconnectivity_drive.level.enabled:
|
|
104
|
+
self.__on_level_change(self.carconnectivity_drive.level, Observable.ObserverEvent.UPDATED)
|
|
105
|
+
|
|
106
|
+
self.carconnectivity_drive.range.add_observer(self.__on_range_change, Observable.ObserverEvent.UPDATED)
|
|
107
|
+
if self.carconnectivity_drive.range.enabled:
|
|
108
|
+
self.__on_range_change(self.carconnectivity_drive.range, Observable.ObserverEvent.UPDATED)
|
|
109
|
+
|
|
110
|
+
self.carconnectivity_drive.range_estimated_full.add_observer(self.__on_range_estimated_full_change, Observable.ObserverEvent.UPDATED)
|
|
111
|
+
if self.carconnectivity_drive.range_estimated_full.enabled:
|
|
112
|
+
self.__on_range_estimated_full_change(self.carconnectivity_drive.range_estimated_full, Observable.ObserverEvent.UPDATED)
|
|
113
|
+
session_factory.remove()
|
|
102
114
|
|
|
103
115
|
def __on_level_change(self, element: LevelAttribute, flags: Observable.ObserverEvent) -> None:
|
|
104
116
|
del flags
|
|
105
117
|
if element.enabled:
|
|
106
|
-
with self.last_level_lock:
|
|
118
|
+
with self.last_level_lock, self.drive_lock:
|
|
107
119
|
with self.session_factory() as session:
|
|
108
120
|
self.drive = session.merge(self.drive)
|
|
109
121
|
session.refresh(self.drive)
|
|
110
122
|
if self.last_level is not None:
|
|
111
123
|
self.last_level = session.merge(self.last_level)
|
|
112
124
|
session.refresh(self.last_level)
|
|
113
|
-
if
|
|
114
|
-
and
|
|
125
|
+
if element.last_updated is not None \
|
|
126
|
+
and (self.last_level is None or (self.last_level.level != element.value
|
|
127
|
+
and element.last_updated > self.last_level.last_date)):
|
|
115
128
|
new_level: DriveLevel = DriveLevel(drive_id=self.drive.id, first_date=element.last_updated, last_date=element.last_updated,
|
|
116
129
|
level=element.value)
|
|
117
130
|
try:
|
|
@@ -122,6 +135,7 @@ class DriveStateAgent(BaseAgent):
|
|
|
122
135
|
except DatabaseError as err:
|
|
123
136
|
session.rollback()
|
|
124
137
|
LOG.error('DatabaseError while adding level for drive %s to database: %s', self.drive.id, err)
|
|
138
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
125
139
|
elif self.last_level is not None and self.last_level.level == element.value \
|
|
126
140
|
and element.last_updated is not None:
|
|
127
141
|
if self.last_level.last_date is None or element.last_updated > self.last_level.last_date:
|
|
@@ -132,20 +146,22 @@ class DriveStateAgent(BaseAgent):
|
|
|
132
146
|
except DatabaseError as err:
|
|
133
147
|
session.rollback()
|
|
134
148
|
LOG.error('DatabaseError while updating level for drive %s in database: %s', self.drive.id, err)
|
|
149
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
135
150
|
self.session_factory.remove()
|
|
136
151
|
|
|
137
152
|
def __on_range_change(self, element: RangeAttribute, flags: Observable.ObserverEvent) -> None:
|
|
138
153
|
del flags
|
|
139
154
|
if element.enabled:
|
|
140
|
-
with self.last_range_lock:
|
|
155
|
+
with self.last_range_lock, self.drive_lock:
|
|
141
156
|
with self.session_factory() as session:
|
|
142
157
|
self.drive = session.merge(self.drive)
|
|
143
158
|
session.refresh(self.drive)
|
|
144
159
|
if self.last_range is not None:
|
|
145
160
|
self.last_range = session.merge(self.last_range)
|
|
146
161
|
session.refresh(self.last_range)
|
|
147
|
-
if
|
|
148
|
-
and
|
|
162
|
+
if element.last_updated is not None \
|
|
163
|
+
and (self.last_range is None or (self.last_range.range != element.value
|
|
164
|
+
and element.last_updated > self.last_range.last_date)):
|
|
149
165
|
new_range: DriveRange = DriveRange(drive_id=self.drive.id, first_date=element.last_updated, last_date=element.last_updated,
|
|
150
166
|
range=element.value)
|
|
151
167
|
try:
|
|
@@ -156,6 +172,7 @@ class DriveStateAgent(BaseAgent):
|
|
|
156
172
|
except DatabaseError as err:
|
|
157
173
|
session.rollback()
|
|
158
174
|
LOG.error('DatabaseError while adding range for drive %s to database: %s', self.drive.id, err)
|
|
175
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
159
176
|
elif self.last_range is not None and self.last_range.range == element.value \
|
|
160
177
|
and element.last_updated is not None:
|
|
161
178
|
if self.last_range.last_date is None or element.last_updated > self.last_range.last_date:
|
|
@@ -166,20 +183,22 @@ class DriveStateAgent(BaseAgent):
|
|
|
166
183
|
except DatabaseError as err:
|
|
167
184
|
session.rollback()
|
|
168
185
|
LOG.error('DatabaseError while updating range for drive %s in database: %s', self.drive.id, err)
|
|
186
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
169
187
|
self.session_factory.remove()
|
|
170
188
|
|
|
171
189
|
def __on_range_estimated_full_change(self, element: RangeAttribute, flags: Observable.ObserverEvent) -> None:
|
|
172
190
|
del flags
|
|
173
191
|
if element.enabled:
|
|
174
|
-
with self.last_range_estimated_full_lock:
|
|
192
|
+
with self.last_range_estimated_full_lock, self.drive_lock:
|
|
175
193
|
with self.session_factory() as session:
|
|
176
194
|
self.drive = session.merge(self.drive)
|
|
177
195
|
session.refresh(self.drive)
|
|
178
196
|
if self.last_range_estimated_full is not None:
|
|
179
197
|
self.last_range_estimated_full = session.merge(self.last_range_estimated_full)
|
|
180
198
|
session.refresh(self.last_range_estimated_full)
|
|
181
|
-
if
|
|
182
|
-
and
|
|
199
|
+
if element.last_updated is not None \
|
|
200
|
+
and (self.last_range_estimated_full is None or (self.last_range_estimated_full.range_estimated_full != element.value
|
|
201
|
+
and element.last_updated > self.last_range_estimated_full.last_date)):
|
|
183
202
|
new_range: DriveRangeEstimatedFull = DriveRangeEstimatedFull(drive_id=self.drive.id, first_date=element.last_updated,
|
|
184
203
|
last_date=element.last_updated, range_estimated_full=element.value)
|
|
185
204
|
try:
|
|
@@ -190,6 +209,7 @@ class DriveStateAgent(BaseAgent):
|
|
|
190
209
|
except DatabaseError as err:
|
|
191
210
|
session.rollback()
|
|
192
211
|
LOG.error('DatabaseError while adding range_estimated_full for drive %s to database: %s', self.drive.id, err)
|
|
212
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
193
213
|
elif self.last_range_estimated_full is not None and self.last_range_estimated_full.range_estimated_full == element.value \
|
|
194
214
|
and element.last_updated is not None:
|
|
195
215
|
if self.last_range_estimated_full.last_date is None or element.last_updated > self.last_range_estimated_full.last_date:
|
|
@@ -200,75 +220,102 @@ class DriveStateAgent(BaseAgent):
|
|
|
200
220
|
except DatabaseError as err:
|
|
201
221
|
session.rollback()
|
|
202
222
|
LOG.error('DatabaseError while updating range_estimated_full for drive %s in database: %s', self.drive.id, err)
|
|
223
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
203
224
|
self.session_factory.remove()
|
|
204
225
|
|
|
205
226
|
def __on_type_change(self, element: EnumAttribute[GenericDrive.Type], flags: Observable.ObserverEvent) -> None:
|
|
206
227
|
del flags
|
|
207
|
-
with self.type_lock:
|
|
228
|
+
with self.type_lock, self.drive_lock:
|
|
208
229
|
with self.session_factory() as session:
|
|
209
230
|
self.drive = session.merge(self.drive)
|
|
210
231
|
session.refresh(self.drive)
|
|
211
232
|
if element.enabled and element.value is not None and self.drive.type != element.value:
|
|
212
|
-
|
|
213
|
-
|
|
233
|
+
try:
|
|
234
|
+
self.drive.type = element.value
|
|
235
|
+
session.commit()
|
|
236
|
+
except DatabaseError as err:
|
|
237
|
+
session.rollback()
|
|
238
|
+
LOG.error('DatabaseError while updating type for drive %s to database: %s', self.drive.id, err)
|
|
239
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
214
240
|
self.session_factory.remove()
|
|
215
241
|
|
|
216
242
|
def __on_electric_total_capacity_change(self, element: EnergyAttribute, flags: Observable.ObserverEvent) -> None:
|
|
217
243
|
del flags
|
|
218
|
-
with self.total_capacity_lock:
|
|
244
|
+
with self.total_capacity_lock, self.drive_lock:
|
|
219
245
|
with self.session_factory() as session:
|
|
220
246
|
self.drive = session.merge(self.drive)
|
|
221
247
|
session.refresh(self.drive)
|
|
222
248
|
if element.enabled and element.value is not None and self.drive.capacity_total != element.value:
|
|
223
|
-
|
|
224
|
-
|
|
249
|
+
try:
|
|
250
|
+
self.drive.capacity_total = element.value
|
|
251
|
+
session.commit()
|
|
252
|
+
except DatabaseError as err:
|
|
253
|
+
session.rollback()
|
|
254
|
+
LOG.error('DatabaseError while updating total capacity for drive %s to database: %s', self.drive.id, err)
|
|
255
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
225
256
|
self.session_factory.remove()
|
|
226
257
|
|
|
227
258
|
def __on_electric_available_capacity_change(self, element: EnergyAttribute, flags: Observable.ObserverEvent) -> None:
|
|
228
259
|
del flags
|
|
229
|
-
with self.available_capacity_lock:
|
|
260
|
+
with self.available_capacity_lock, self.drive_lock:
|
|
230
261
|
with self.session_factory() as session:
|
|
231
262
|
self.drive = session.merge(self.drive)
|
|
232
263
|
session.refresh(self.drive)
|
|
233
264
|
if element.enabled and element.value is not None and self.drive.capacity != element.value:
|
|
234
|
-
|
|
235
|
-
|
|
265
|
+
try:
|
|
266
|
+
self.drive.capacity = element.value
|
|
267
|
+
session.commit()
|
|
268
|
+
except DatabaseError as err:
|
|
269
|
+
session.rollback()
|
|
270
|
+
LOG.error('DatabaseError while updating available capacity for drive %s to database: %s', self.drive.id, err)
|
|
271
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
236
272
|
self.session_factory.remove()
|
|
237
273
|
|
|
238
274
|
def __on_range_wltp_change(self, element: RangeAttribute, flags: Observable.ObserverEvent) -> None:
|
|
239
275
|
del flags
|
|
240
|
-
with self.range_wltp_lock:
|
|
276
|
+
with self.range_wltp_lock, self.drive_lock:
|
|
241
277
|
with self.session_factory() as session:
|
|
242
278
|
self.drive = session.merge(self.drive)
|
|
243
279
|
session.refresh(self.drive)
|
|
244
280
|
if element.enabled and element.value is not None and self.drive.wltp_range != element.value:
|
|
245
|
-
|
|
246
|
-
|
|
281
|
+
try:
|
|
282
|
+
self.drive.wltp_range = element.value
|
|
283
|
+
session.commit()
|
|
284
|
+
except DatabaseError as err:
|
|
285
|
+
session.rollback()
|
|
286
|
+
LOG.error('DatabaseError while updating WLTP range for drive %s to database: %s', self.drive.id, err)
|
|
287
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
247
288
|
self.session_factory.remove()
|
|
248
289
|
|
|
249
290
|
def __on_fuel_available_capacity_change(self, element: VolumeAttribute, flags: Observable.ObserverEvent) -> None:
|
|
250
291
|
del flags
|
|
251
|
-
with self.fuel_available_capacity_lock:
|
|
292
|
+
with self.fuel_available_capacity_lock, self.drive_lock:
|
|
252
293
|
with self.session_factory() as session:
|
|
253
294
|
self.drive = session.merge(self.drive)
|
|
254
295
|
session.refresh(self.drive)
|
|
255
296
|
if element.enabled and element.value is not None and self.drive.capacity != element.value:
|
|
256
|
-
|
|
257
|
-
|
|
297
|
+
try:
|
|
298
|
+
self.drive.capacity = element.value
|
|
299
|
+
session.commit()
|
|
300
|
+
except DatabaseError as err:
|
|
301
|
+
session.rollback()
|
|
302
|
+
LOG.error('DatabaseError while updating available capacity for drive %s to database: %s', self.drive.id, err)
|
|
303
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
258
304
|
self.session_factory.remove()
|
|
259
305
|
|
|
260
306
|
def __on_electric_consumption_change(self, element: EnergyConsumptionAttribute, flags: Observable.ObserverEvent) -> None:
|
|
261
307
|
del flags
|
|
262
308
|
if element.enabled:
|
|
263
|
-
with self.last_electric_consumption_lock:
|
|
309
|
+
with self.last_electric_consumption_lock, self.drive_lock:
|
|
264
310
|
with self.session_factory() as session:
|
|
265
311
|
self.drive = session.merge(self.drive)
|
|
266
312
|
session.refresh(self.drive)
|
|
267
313
|
if self.last_electric_consumption is not None:
|
|
268
314
|
self.last_electric_consumption = session.merge(self.last_electric_consumption)
|
|
269
315
|
session.refresh(self.last_electric_consumption)
|
|
270
|
-
if
|
|
271
|
-
and
|
|
316
|
+
if element.last_updated is not None \
|
|
317
|
+
and (self.last_electric_consumption is None or (self.last_electric_consumption.consumption != element.value
|
|
318
|
+
and element.last_updated > self.last_electric_consumption.last_date)):
|
|
272
319
|
new_level: DriveConsumption = DriveConsumption(drive_id=self.drive.id, first_date=element.last_updated, last_date=element.last_updated,
|
|
273
320
|
consumption=element.value)
|
|
274
321
|
try:
|
|
@@ -279,6 +326,7 @@ class DriveStateAgent(BaseAgent):
|
|
|
279
326
|
except DatabaseError as err:
|
|
280
327
|
session.rollback()
|
|
281
328
|
LOG.error('DatabaseError while adding consumption for drive %s to database: %s', self.drive.id, err)
|
|
329
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
282
330
|
elif self.last_electric_consumption is not None and self.last_electric_consumption.consumption == element.value \
|
|
283
331
|
and element.last_updated is not None:
|
|
284
332
|
if self.last_electric_consumption.last_date is None or element.last_updated > self.last_electric_consumption.last_date:
|
|
@@ -289,20 +337,22 @@ class DriveStateAgent(BaseAgent):
|
|
|
289
337
|
except DatabaseError as err:
|
|
290
338
|
session.rollback()
|
|
291
339
|
LOG.error('DatabaseError while updating consumption for drive %s in database: %s', self.drive.id, err)
|
|
340
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
292
341
|
self.session_factory.remove()
|
|
293
342
|
|
|
294
343
|
def __on_fuel_consumption_change(self, element: FuelConsumptionAttribute, flags: Observable.ObserverEvent) -> None:
|
|
295
344
|
del flags
|
|
296
345
|
if element.enabled:
|
|
297
|
-
with self.last_fuel_consumption_lock:
|
|
346
|
+
with self.last_fuel_consumption_lock, self.drive_lock:
|
|
298
347
|
with self.session_factory() as session:
|
|
299
348
|
self.drive = session.merge(self.drive)
|
|
300
349
|
session.refresh(self.drive)
|
|
301
350
|
if self.last_fuel_consumption is not None:
|
|
302
351
|
self.last_fuel_consumption = session.merge(self.last_fuel_consumption)
|
|
303
352
|
session.refresh(self.last_fuel_consumption)
|
|
304
|
-
if
|
|
305
|
-
and
|
|
353
|
+
if element.last_updated is not None \
|
|
354
|
+
and (self.last_fuel_consumption is None or (self.last_fuel_consumption.consumption != element.value
|
|
355
|
+
and element.last_updated > self.last_fuel_consumption.last_date)):
|
|
306
356
|
new_level: DriveConsumption = DriveConsumption(drive_id=self.drive.id, first_date=element.last_updated, last_date=element.last_updated,
|
|
307
357
|
consumption=element.value)
|
|
308
358
|
try:
|
|
@@ -313,6 +363,7 @@ class DriveStateAgent(BaseAgent):
|
|
|
313
363
|
except DatabaseError as err:
|
|
314
364
|
session.rollback()
|
|
315
365
|
LOG.error('DatabaseError while adding consumption for drive %s to database: %s', self.drive.id, err)
|
|
366
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
316
367
|
elif self.last_fuel_consumption is not None and self.last_fuel_consumption.consumption == element.value \
|
|
317
368
|
and element.last_updated is not None:
|
|
318
369
|
if self.last_fuel_consumption.last_date is None or element.last_updated > self.last_fuel_consumption.last_date:
|
|
@@ -323,4 +374,5 @@ class DriveStateAgent(BaseAgent):
|
|
|
323
374
|
except DatabaseError as err:
|
|
324
375
|
session.rollback()
|
|
325
376
|
LOG.error('DatabaseError while updating consumption for drive %s in database: %s', self.drive.id, err)
|
|
377
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
326
378
|
self.session_factory.remove()
|
|
@@ -23,6 +23,7 @@ if TYPE_CHECKING:
|
|
|
23
23
|
|
|
24
24
|
from carconnectivity.vehicle import GenericVehicle
|
|
25
25
|
|
|
26
|
+
from carconnectivity_plugins.database.plugin import Plugin
|
|
26
27
|
from carconnectivity_plugins.database.model.vehicle import Vehicle
|
|
27
28
|
|
|
28
29
|
|
|
@@ -30,11 +31,13 @@ LOG: logging.Logger = logging.getLogger("carconnectivity.plugins.database.agents
|
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
class StateAgent(BaseAgent):
|
|
33
|
-
def __init__(self, session_factory: scoped_session[Session], vehicle: Vehicle) -> None:
|
|
34
|
-
if vehicle is None or
|
|
34
|
+
def __init__(self, database_plugin: Plugin, session_factory: scoped_session[Session], vehicle: Vehicle, carconnectivity_vehicle: GenericVehicle) -> None:
|
|
35
|
+
if vehicle is None or carconnectivity_vehicle is None:
|
|
35
36
|
raise ValueError("Vehicle or its carconnectivity_vehicle attribute is None")
|
|
37
|
+
self.database_plugin: Plugin = database_plugin
|
|
36
38
|
self.session_factory: scoped_session[Session] = session_factory
|
|
37
39
|
self.vehicle: Vehicle = vehicle
|
|
40
|
+
self.carconnectivity_vehicle: GenericVehicle = carconnectivity_vehicle
|
|
38
41
|
|
|
39
42
|
with self.session_factory() as session:
|
|
40
43
|
self.last_state: Optional[State] = session.query(State).filter(State.vehicle == vehicle).order_by(State.first_date.desc()).first()
|
|
@@ -48,14 +51,14 @@ class StateAgent(BaseAgent):
|
|
|
48
51
|
.order_by(OutsideTemperature.first_date.desc()).first()
|
|
49
52
|
self.last_outside_temperature_lock: threading.RLock = threading.RLock()
|
|
50
53
|
|
|
51
|
-
|
|
52
|
-
self.__on_state_change(
|
|
54
|
+
self.carconnectivity_vehicle.state.add_observer(self.__on_state_change, Observable.ObserverEvent.UPDATED)
|
|
55
|
+
self.__on_state_change(self.carconnectivity_vehicle.state, Observable.ObserverEvent.UPDATED)
|
|
53
56
|
|
|
54
|
-
|
|
55
|
-
self.__on_connection_state_change(
|
|
57
|
+
self.carconnectivity_vehicle.connection_state.add_observer(self.__on_connection_state_change, Observable.ObserverEvent.UPDATED)
|
|
58
|
+
self.__on_connection_state_change(self.carconnectivity_vehicle.connection_state, Observable.ObserverEvent.UPDATED)
|
|
56
59
|
|
|
57
|
-
|
|
58
|
-
self.__on_outside_temperature_change(
|
|
60
|
+
self.carconnectivity_vehicle.outside_temperature.add_observer(self.__on_outside_temperature_change, Observable.ObserverEvent.UPDATED)
|
|
61
|
+
self.__on_outside_temperature_change(self.carconnectivity_vehicle.outside_temperature, Observable.ObserverEvent.UPDATED)
|
|
59
62
|
self.session_factory.remove()
|
|
60
63
|
|
|
61
64
|
def __on_state_change(self, element: EnumAttribute[GenericVehicle.State], flags: Observable.ObserverEvent) -> None:
|
|
@@ -66,8 +69,9 @@ class StateAgent(BaseAgent):
|
|
|
66
69
|
if self.last_state is not None:
|
|
67
70
|
self.last_state = session.merge(self.last_state)
|
|
68
71
|
session.refresh(self.last_state)
|
|
69
|
-
if
|
|
70
|
-
and
|
|
72
|
+
if element.last_updated is not None \
|
|
73
|
+
and (self.last_state is None or (self.last_state.state != element.value
|
|
74
|
+
and element.last_updated > self.last_state.last_date)):
|
|
71
75
|
new_state: State = State(vin=self.vehicle.vin, first_date=element.last_updated, last_date=element.last_updated, state=element.value)
|
|
72
76
|
try:
|
|
73
77
|
session.add(new_state)
|
|
@@ -77,6 +81,7 @@ class StateAgent(BaseAgent):
|
|
|
77
81
|
except DatabaseError as err:
|
|
78
82
|
session.rollback()
|
|
79
83
|
LOG.error('DatabaseError while adding state for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
84
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
80
85
|
|
|
81
86
|
elif self.last_state is not None and self.last_state.state == element.value and element.last_updated is not None:
|
|
82
87
|
if self.last_state.last_date is None or element.last_updated > self.last_state.last_date:
|
|
@@ -87,6 +92,7 @@ class StateAgent(BaseAgent):
|
|
|
87
92
|
except DatabaseError as err:
|
|
88
93
|
session.rollback()
|
|
89
94
|
LOG.error('DatabaseError while updating state for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
95
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
90
96
|
self.session_factory.remove()
|
|
91
97
|
|
|
92
98
|
def __on_connection_state_change(self, element: EnumAttribute[GenericVehicle.ConnectionState], flags: Observable.ObserverEvent) -> None:
|
|
@@ -97,8 +103,9 @@ class StateAgent(BaseAgent):
|
|
|
97
103
|
if self.last_connection_state is not None:
|
|
98
104
|
self.last_connection_state = session.merge(self.last_connection_state)
|
|
99
105
|
session.refresh(self.last_connection_state)
|
|
100
|
-
if
|
|
101
|
-
and
|
|
106
|
+
if element.last_updated is not None \
|
|
107
|
+
and (self.last_connection_state is None or (self.last_connection_state.connection_state != element.value
|
|
108
|
+
and element.last_updated > self.last_connection_state.last_date)):
|
|
102
109
|
new_connection_state: ConnectionState = ConnectionState(vin=self.vehicle.vin, first_date=element.last_updated,
|
|
103
110
|
last_date=element.last_updated, connection_state=element.value)
|
|
104
111
|
try:
|
|
@@ -109,6 +116,7 @@ class StateAgent(BaseAgent):
|
|
|
109
116
|
except DatabaseError as err:
|
|
110
117
|
session.rollback()
|
|
111
118
|
LOG.error('DatabaseError while adding connection state for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
119
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
112
120
|
elif self.last_connection_state is not None and self.last_connection_state.connection_state == element.value \
|
|
113
121
|
and element.last_updated is not None:
|
|
114
122
|
if self.last_connection_state.last_date is None or element.last_updated > self.last_connection_state.last_date:
|
|
@@ -119,6 +127,7 @@ class StateAgent(BaseAgent):
|
|
|
119
127
|
except DatabaseError as err:
|
|
120
128
|
session.rollback()
|
|
121
129
|
LOG.error('DatabaseError while updating connection state for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
130
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
122
131
|
self.session_factory.remove()
|
|
123
132
|
|
|
124
133
|
def __on_outside_temperature_change(self, element: TemperatureAttribute, flags: Observable.ObserverEvent) -> None:
|
|
@@ -129,8 +138,9 @@ class StateAgent(BaseAgent):
|
|
|
129
138
|
if self.last_outside_temperature is not None:
|
|
130
139
|
self.last_outside_temperature = session.merge(self.last_outside_temperature)
|
|
131
140
|
session.refresh(self.last_outside_temperature)
|
|
132
|
-
if
|
|
133
|
-
and
|
|
141
|
+
if element.last_updated is not None \
|
|
142
|
+
and (self.last_outside_temperature is None or (self.last_outside_temperature.outside_temperature != element.value
|
|
143
|
+
and element.last_updated > self.last_outside_temperature.last_date)):
|
|
134
144
|
new_outside_temperature: OutsideTemperature = OutsideTemperature(vin=self.vehicle.vin, first_date=element.last_updated,
|
|
135
145
|
last_date=element.last_updated, outside_temperature=element.value)
|
|
136
146
|
try:
|
|
@@ -141,6 +151,7 @@ class StateAgent(BaseAgent):
|
|
|
141
151
|
except DatabaseError as err:
|
|
142
152
|
session.rollback()
|
|
143
153
|
LOG.error('DatabaseError while adding outside temperature for vehicle %s to database: %s', self.vehicle.vin, err)
|
|
154
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
144
155
|
elif self.last_outside_temperature is not None and self.last_outside_temperature.outside_temperature == element.value \
|
|
145
156
|
and element.last_updated is not None:
|
|
146
157
|
if self.last_outside_temperature.last_date is None or element.last_updated > self.last_outside_temperature.last_date:
|
|
@@ -151,4 +162,5 @@ class StateAgent(BaseAgent):
|
|
|
151
162
|
except DatabaseError as err:
|
|
152
163
|
session.rollback()
|
|
153
164
|
LOG.error('DatabaseError while updating outside temperature for vehicle %s in database: %s', self.vehicle.vin, err)
|
|
165
|
+
self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
|
|
154
166
|
self.session_factory.remove()
|