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.

@@ -22,6 +22,7 @@ if TYPE_CHECKING:
22
22
 
23
23
  from carconnectivity.attributes import EnumAttribute, FloatAttribute
24
24
 
25
+ from carconnectivity_plugins.database.plugin import Plugin
25
26
  from carconnectivity_plugins.database.model.vehicle import Vehicle
26
27
 
27
28
  LOG: logging.Logger = logging.getLogger("carconnectivity.plugins.database.agents.trip_agent")
@@ -40,7 +41,7 @@ class TripAgent(BaseAgent):
40
41
  of the vehicle to detect state transitions.
41
42
  trip (Optional[Trip]): The currently active trip, if any.
42
43
  Raises:
43
- ValueError: If vehicle or vehicle.carconnectivity_vehicle is None during initialization.
44
+ ValueError: If vehicle or self.carconnectivity_vehicle is None during initialization.
44
45
  Notes:
45
46
  - A new trip is started when the vehicle transitions to IGNITION_ON or DRIVING state.
46
47
  - A trip is ended when the vehicle transitions from IGNITION_ON/DRIVING to another state.
@@ -49,11 +50,14 @@ class TripAgent(BaseAgent):
49
50
  - Trip records include start/end dates and odometer readings when available.
50
51
  """
51
52
 
52
- def __init__(self, session_factory: scoped_session[Session], vehicle: Vehicle) -> None:
53
- if vehicle is None or vehicle.carconnectivity_vehicle is None:
53
+ def __init__(self, database_plugin: Plugin, session_factory: scoped_session[Session], vehicle: Vehicle, carconnectivity_vehicle: GenericVehicle) -> None:
54
+ if vehicle is None or carconnectivity_vehicle is None:
54
55
  raise ValueError("Vehicle or its carconnectivity_vehicle attribute is None")
56
+ self.database_plugin: Plugin = database_plugin
55
57
  self.session_factory: scoped_session[Session] = session_factory
56
58
  self.vehicle: Vehicle = vehicle
59
+ self.carconnectivity_vehicle: GenericVehicle = carconnectivity_vehicle
60
+
57
61
  self.last_carconnectivity_state: Optional[GenericVehicle.State] = None
58
62
  self.last_parked_position_latitude: Optional[float] = None
59
63
  self.last_parked_position_longitude: Optional[float] = None
@@ -67,19 +71,19 @@ class TripAgent(BaseAgent):
67
71
  LOG.info("Last trip for vehicle %s is still open during startup, closing it now", vehicle.vin)
68
72
  self.session_factory.remove()
69
73
 
70
- vehicle.carconnectivity_vehicle.state.add_observer(self.__on_state_change, Observable.ObserverEvent.UPDATED)
71
- self.__on_state_change(vehicle.carconnectivity_vehicle.state, Observable.ObserverEvent.UPDATED)
74
+ self.carconnectivity_vehicle.state.add_observer(self.__on_state_change, Observable.ObserverEvent.UPDATED)
75
+ self.__on_state_change(self.carconnectivity_vehicle.state, Observable.ObserverEvent.UPDATED)
72
76
 
73
- vehicle.carconnectivity_vehicle.position.latitude.add_observer(self._on_position_latitude_change, Observable.ObserverEvent.UPDATED)
74
- self._on_position_latitude_change(vehicle.carconnectivity_vehicle.position.latitude, Observable.ObserverEvent.UPDATED)
77
+ self.carconnectivity_vehicle.position.latitude.add_observer(self._on_position_latitude_change, Observable.ObserverEvent.UPDATED)
78
+ self._on_position_latitude_change(self.carconnectivity_vehicle.position.latitude, Observable.ObserverEvent.UPDATED)
75
79
 
76
- vehicle.carconnectivity_vehicle.position.longitude.add_observer(self._on_position_longitude_change, Observable.ObserverEvent.UPDATED)
77
- self._on_position_longitude_change(vehicle.carconnectivity_vehicle.position.longitude, Observable.ObserverEvent.UPDATED)
80
+ self.carconnectivity_vehicle.position.longitude.add_observer(self._on_position_longitude_change, Observable.ObserverEvent.UPDATED)
81
+ self._on_position_longitude_change(self.carconnectivity_vehicle.position.longitude, Observable.ObserverEvent.UPDATED)
78
82
 
79
83
  def __on_state_change(self, element: EnumAttribute[GenericVehicle.State], flags: Observable.ObserverEvent) -> None:
80
84
  del flags
81
85
  if element.enabled:
82
- if self.vehicle.carconnectivity_vehicle is None:
86
+ if self.carconnectivity_vehicle is None:
83
87
  raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
84
88
  if element.enabled and element.value is not None:
85
89
  if self.last_carconnectivity_state is not None:
@@ -97,9 +101,9 @@ class TripAgent(BaseAgent):
97
101
  LOG.info("Starting new trip for vehicle %s", self.vehicle.vin)
98
102
  start_date: datetime = element.last_updated if element.last_updated is not None else datetime.now(tz=timezone.utc)
99
103
  new_trip: Trip = Trip(vin=self.vehicle.vin, start_date=start_date)
100
- if self.vehicle.carconnectivity_vehicle.odometer.enabled and \
101
- self.vehicle.carconnectivity_vehicle.odometer.value is not None:
102
- new_trip.start_odometer = self.vehicle.carconnectivity_vehicle.odometer.value
104
+ if self.carconnectivity_vehicle.odometer.enabled and \
105
+ self.carconnectivity_vehicle.odometer.value is not None:
106
+ new_trip.start_odometer = self.carconnectivity_vehicle.odometer.value
103
107
  if not self._update_trip_position(session=session, trip=new_trip, start=True):
104
108
  # if now no position is available try the last known position that is not older than 5min
105
109
  if self.last_parked_position_latitude is not None and self.last_parked_position_longitude is not None \
@@ -116,15 +120,16 @@ class TripAgent(BaseAgent):
116
120
  except DatabaseError as err:
117
121
  session.rollback()
118
122
  LOG.error('DatabaseError while adding trip for vehicle %s to database: %s', self.vehicle.vin, err)
123
+ self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
119
124
  elif self.last_carconnectivity_state in (GenericVehicle.State.IGNITION_ON, GenericVehicle.State.DRIVING) \
120
125
  and element.value not in (GenericVehicle.State.IGNITION_ON, GenericVehicle.State.DRIVING):
121
126
  if self.trip is not None and not self.trip.is_completed():
122
127
  LOG.info("Ending trip for vehicle %s", self.vehicle.vin)
123
128
  try:
124
129
  self.trip.destination_date = element.last_updated if element.last_updated is not None else datetime.now(tz=timezone.utc)
125
- if self.vehicle.carconnectivity_vehicle.odometer.enabled and \
126
- self.vehicle.carconnectivity_vehicle.odometer.value is not None:
127
- self.trip.destination_odometer = self.vehicle.carconnectivity_vehicle.odometer.value
130
+ if self.carconnectivity_vehicle.odometer.enabled and \
131
+ self.carconnectivity_vehicle.odometer.value is not None:
132
+ self.trip.destination_odometer = self.carconnectivity_vehicle.odometer.value
128
133
  LOG.debug('Set destination odometer %.2f for trip of vehicle %s', self.trip.destination_odometer, self.vehicle.vin)
129
134
  if self._update_trip_position(session=session, trip=self.trip, start=False):
130
135
  self.trip = None
@@ -132,6 +137,7 @@ class TripAgent(BaseAgent):
132
137
  except DatabaseError as err:
133
138
  session.rollback()
134
139
  LOG.error('DatabaseError while ending trip for vehicle %s in database: %s', self.vehicle.vin, err)
140
+ self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
135
141
  self.session_factory.remove()
136
142
  self.last_carconnectivity_state = element.value
137
143
 
@@ -151,41 +157,43 @@ class TripAgent(BaseAgent):
151
157
 
152
158
  def _on_position_change(self) -> None:
153
159
  # Check if there is a finished trip that lacks destination position. We allow 5min after destination_date to set the position.
154
- if self.trip is not None and self.trip.destination_date is not None and self.trip.destination_position_latitude is None \
155
- and self.last_parked_position_time is not None \
156
- and self.last_parked_position_time < (self.trip.destination_date + timedelta(minutes=5)):
160
+ if self.trip is not None:
157
161
  with self.session_factory() as session:
158
162
  with self.trip_lock:
159
163
  self.trip = session.merge(self.trip)
160
164
  session.refresh(self.trip)
161
- self._update_trip_position(session, self.trip, start=False,
162
- latitude=self.last_parked_position_latitude,
163
- longitude=self.last_parked_position_longitude)
165
+ if self.trip.destination_date is not None and self.trip.destination_position_latitude is None \
166
+ and self.last_parked_position_time is not None \
167
+ and self.last_parked_position_time < (self.trip.destination_date + timedelta(minutes=5)):
168
+ self._update_trip_position(session, self.trip, start=False,
169
+ latitude=self.last_parked_position_latitude,
170
+ longitude=self.last_parked_position_longitude)
164
171
  self.session_factory.remove()
165
172
 
166
173
  def _update_trip_position(self, session: Session, trip: Trip, start: bool,
167
174
  latitude: Optional[float] = None, longitude: Optional[float] = None) -> bool:
168
- if self.vehicle.carconnectivity_vehicle is None:
175
+ if self.carconnectivity_vehicle is None:
169
176
  raise ValueError("Vehicle's carconnectivity_vehicle attribute is None")
170
177
  if latitude or longitude is None:
171
- if self.vehicle.carconnectivity_vehicle.position.enabled and self.vehicle.carconnectivity_vehicle.position.latitude.enabled \
172
- and self.vehicle.carconnectivity_vehicle.position.longitude.enabled \
173
- and self.vehicle.carconnectivity_vehicle.position.latitude.value is not None \
174
- and self.vehicle.carconnectivity_vehicle.position.longitude.value is not None:
175
- latitude = self.vehicle.carconnectivity_vehicle.position.latitude.value
176
- longitude = self.vehicle.carconnectivity_vehicle.position.longitude.value
178
+ if self.carconnectivity_vehicle.position.enabled and self.carconnectivity_vehicle.position.latitude.enabled \
179
+ and self.carconnectivity_vehicle.position.longitude.enabled \
180
+ and self.carconnectivity_vehicle.position.latitude.value is not None \
181
+ and self.carconnectivity_vehicle.position.longitude.value is not None:
182
+ latitude = self.carconnectivity_vehicle.position.latitude.value
183
+ longitude = self.carconnectivity_vehicle.position.longitude.value
177
184
  if latitude is not None and longitude is not None:
178
185
  if start:
179
186
  if trip.start_position_latitude is None and trip.start_position_longitude is None:
180
187
  try:
181
- trip.start_position_latitude = self.vehicle.carconnectivity_vehicle.position.latitude.value
182
- trip.start_position_longitude = self.vehicle.carconnectivity_vehicle.position.longitude.value
188
+ trip.start_position_latitude = self.carconnectivity_vehicle.position.latitude.value
189
+ trip.start_position_longitude = self.carconnectivity_vehicle.position.longitude.value
183
190
  session.commit()
184
191
  except DatabaseError as err:
185
192
  session.rollback()
186
193
  LOG.error('DatabaseError while updating position for trip of vehicle %s in database: %s', self.vehicle.vin, err)
187
- if trip.start_location is None and self.vehicle.carconnectivity_vehicle.position.location.enabled:
188
- location: Location = Location.from_carconnectivity_location(location=self.vehicle.carconnectivity_vehicle.position.location)
194
+ self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
195
+ if trip.start_location is None and self.carconnectivity_vehicle.position.location.enabled:
196
+ location: Location = Location.from_carconnectivity_location(location=self.carconnectivity_vehicle.position.location)
189
197
  try:
190
198
  location = session.merge(location)
191
199
  trip.start_location = location
@@ -193,18 +201,20 @@ class TripAgent(BaseAgent):
193
201
  except DatabaseError as err:
194
202
  session.rollback()
195
203
  LOG.error('DatabaseError while merging location for trip of vehicle %s in database: %s', self.vehicle.vin, err)
204
+ self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
196
205
  return True
197
206
  else:
198
207
  if trip.destination_position_latitude is None and trip.destination_position_longitude is None:
199
208
  try:
200
- trip.destination_position_latitude = self.vehicle.carconnectivity_vehicle.position.latitude.value
201
- trip.destination_position_longitude = self.vehicle.carconnectivity_vehicle.position.longitude.value
209
+ trip.destination_position_latitude = self.carconnectivity_vehicle.position.latitude.value
210
+ trip.destination_position_longitude = self.carconnectivity_vehicle.position.longitude.value
202
211
  session.commit()
203
212
  except DatabaseError as err:
204
213
  session.rollback()
205
214
  LOG.error('DatabaseError while updating position for trip of vehicle %s in database: %s', self.vehicle.vin, err)
206
- if trip.destination_location is None and self.vehicle.carconnectivity_vehicle.position.location.enabled:
207
- location: Location = Location.from_carconnectivity_location(location=self.vehicle.carconnectivity_vehicle.position.location)
215
+ self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
216
+ if trip.destination_location is None and self.carconnectivity_vehicle.position.location.enabled:
217
+ location: Location = Location.from_carconnectivity_location(location=self.carconnectivity_vehicle.position.location)
208
218
  try:
209
219
  location = session.merge(location)
210
220
  trip.destination_location = location
@@ -212,5 +222,6 @@ class TripAgent(BaseAgent):
212
222
  except DatabaseError as err:
213
223
  session.rollback()
214
224
  LOG.error('DatabaseError while merging location for trip of vehicle %s in database: %s', self.vehicle.vin, err)
225
+ self.database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
215
226
  return True
216
227
  return False
@@ -77,13 +77,13 @@ class ChargingSession(Base): # pylint: disable=too-few-public-methods
77
77
  location: Mapped[Optional["Location"]] = relationship("Location")
78
78
  charging_station_uid: Mapped[Optional[str]] = mapped_column(ForeignKey("charging_stations.uid"))
79
79
  charging_station: Mapped[Optional["ChargingStation"]] = relationship("ChargingStation")
80
- meter_start_kwh = Mapped[Optional[float]]
81
- meter_end_kwh = Mapped[Optional[float]]
82
- price_per_kwh = Mapped[Optional[float]]
83
- price_per_min = Mapped[Optional[float]]
84
- price_per_session = Mapped[Optional[float]]
85
- real_charged = Mapped[Optional[float]]
86
- real_cost = Mapped[Optional[float]]
80
+ meter_start_kwh: Mapped[Optional[float]]
81
+ meter_end_kwh: Mapped[Optional[float]]
82
+ price_per_kwh: Mapped[Optional[float]]
83
+ price_per_min: Mapped[Optional[float]]
84
+ price_per_session: Mapped[Optional[float]]
85
+ real_charged: Mapped[Optional[float]]
86
+ real_cost: Mapped[Optional[float]]
87
87
  tags: Mapped[list["Tag"]] = relationship("Tag", secondary=charging_tag_association_table, backref=backref("charging_sessions"))
88
88
 
89
89
  # pylint: disable-next=too-many-arguments, too-many-positional-arguments
@@ -18,6 +18,8 @@ if TYPE_CHECKING:
18
18
  from sqlalchemy.orm.session import Session
19
19
  from sqlalchemy import Constraint
20
20
 
21
+ from carconnectivity_plugins.database.plugin import Plugin
22
+
21
23
  LOG: logging.Logger = logging.getLogger("carconnectivity.plugins.database.model.drive")
22
24
 
23
25
 
@@ -56,14 +58,13 @@ class Drive(Base):
56
58
  capacity_total: Mapped[Optional[float]]
57
59
  wltp_range: Mapped[Optional[float]]
58
60
 
59
- carconnectivity_drive: Optional[GenericDrive] = None
60
61
  agents: list[BaseAgent] = []
61
62
 
62
63
  def __init__(self, vin, drive_id: Optional[str] = None) -> None:
63
64
  self.vin = vin
64
65
  self.drive_id = drive_id
65
66
 
66
- def connect(self, session_factory: scoped_session[Session], carconnectivity_drive: GenericDrive) -> None:
67
+ def connect(self, database_plugin: Plugin, session_factory: scoped_session[Session], carconnectivity_drive: GenericDrive) -> None:
67
68
  """
68
69
  Connect a CarConnectivity drive object to this database model instance.
69
70
  This method establishes a connection between the database drive model and a CarConnectivity drive object,
@@ -78,9 +79,8 @@ class Drive(Base):
78
79
  - Automatically syncs the drive type if enabled and has a value
79
80
  - Creates and registers a DriveStateAgent for managing drive state
80
81
  """
81
- if self.carconnectivity_drive is not None:
82
+ if self.agents:
82
83
  raise ValueError("Can only connect once! Drive already connected with database model")
83
- self.carconnectivity_drive = carconnectivity_drive
84
- drive_state_agent: DriveStateAgent = DriveStateAgent(session_factory, self) # type: ignore[assignment]
85
- self.agents.append(drive_state_agent)
86
84
  LOG.debug("Adding DriveStateAgent to drive %s of vehicle %s", self.drive_id, self.vin)
85
+ drive_state_agent: DriveStateAgent = DriveStateAgent(database_plugin, session_factory, self, carconnectivity_drive) # type: ignore[assignment]
86
+ self.agents.append(drive_state_agent)
@@ -23,6 +23,8 @@ if TYPE_CHECKING:
23
23
  from sqlalchemy.orm import scoped_session
24
24
  from sqlalchemy.orm.session import Session
25
25
 
26
+ from carconnectivity_plugins.database.plugin import Plugin
27
+
26
28
  LOG: logging.Logger = logging.getLogger("carconnectivity.plugins.database.model.vehicle")
27
29
 
28
30
 
@@ -66,13 +68,12 @@ class Vehicle(Base):
66
68
  type: Mapped[Optional[GenericVehicle.Type]]
67
69
  license_plate: Mapped[Optional[str]]
68
70
 
69
- carconnectivity_vehicle: Optional[GenericVehicle] = None
70
71
  agents: list[BaseAgent] = []
71
72
 
72
73
  def __init__(self, vin) -> None:
73
74
  self.vin = vin
74
75
 
75
- def connect(self, session_factory: scoped_session[Session], carconnectivity_vehicle: GenericVehicle) -> None:
76
+ def connect(self, database_plugin: Plugin, session_factory: scoped_session[Session], carconnectivity_vehicle: GenericVehicle) -> None:
76
77
  """
77
78
  Connect a CarConnectivity vehicle instance to this database vehicle model and set up observers.
78
79
  This method establishes a connection between a CarConnectivity vehicle object and this database vehicle model.
@@ -88,34 +89,33 @@ class Vehicle(Base):
88
89
  - Only enabled attributes are synchronized
89
90
  - The type attribute is only synchronized if it's not None
90
91
  """
91
- if self.carconnectivity_vehicle is not None:
92
+ if self.agents:
92
93
  raise ValueError("Can only connect once! Vehicle already connected with database model")
93
- self.carconnectivity_vehicle = carconnectivity_vehicle
94
- self.carconnectivity_vehicle.name.add_observer(self.__on_name_change, Observable.ObserverEvent.VALUE_CHANGED, on_transaction_end=True)
95
- if self.carconnectivity_vehicle.name.enabled and self.name != self.carconnectivity_vehicle.name.value:
96
- self.name = self.carconnectivity_vehicle.name.value
97
- self.carconnectivity_vehicle.manufacturer.add_observer(self.__on_manufacturer_change, Observable.ObserverEvent.VALUE_CHANGED,
98
- on_transaction_end=True)
99
- if self.carconnectivity_vehicle.manufacturer.enabled and self.manufacturer != self.carconnectivity_vehicle.manufacturer.value:
100
- self.manufacturer = self.carconnectivity_vehicle.manufacturer.value
101
- self.carconnectivity_vehicle.model.add_observer(self.__on_model_change, Observable.ObserverEvent.VALUE_CHANGED, on_transaction_end=True)
102
- if self.carconnectivity_vehicle.model.enabled and self.model != self.carconnectivity_vehicle.model.value:
103
- self.model = self.carconnectivity_vehicle.model.value
104
- self.carconnectivity_vehicle.model_year.add_observer(self.__on_model_year_change, Observable.ObserverEvent.VALUE_CHANGED,
105
- on_transaction_end=True)
106
- if self.carconnectivity_vehicle.model_year.enabled and self.model_year != self.carconnectivity_vehicle.model_year.value:
107
- self.model_year = self.carconnectivity_vehicle.model_year.value
108
- self.carconnectivity_vehicle.type.add_observer(self.__on_type_change, Observable.ObserverEvent.VALUE_CHANGED, on_transaction_end=True)
109
- if self.carconnectivity_vehicle.type.enabled and self.carconnectivity_vehicle.type.value is not None \
110
- and self.type != self.carconnectivity_vehicle.type.value:
111
- self.type = self.carconnectivity_vehicle.type.value
112
- self.carconnectivity_vehicle.license_plate.add_observer(self.__on_license_plate_change, Observable.ObserverEvent.VALUE_CHANGED,
113
- on_transaction_end=True)
114
- if self.carconnectivity_vehicle.license_plate.enabled and self.license_plate != self.carconnectivity_vehicle.license_plate.value:
115
- self.license_plate = self.carconnectivity_vehicle.license_plate.value
94
+ carconnectivity_vehicle.name.add_observer(self.__on_name_change, Observable.ObserverEvent.VALUE_CHANGED, on_transaction_end=True)
95
+ if carconnectivity_vehicle.name.enabled and self.name != carconnectivity_vehicle.name.value:
96
+ self.name = carconnectivity_vehicle.name.value
97
+ carconnectivity_vehicle.manufacturer.add_observer(self.__on_manufacturer_change, Observable.ObserverEvent.VALUE_CHANGED,
98
+ on_transaction_end=True)
99
+ if carconnectivity_vehicle.manufacturer.enabled and self.manufacturer != carconnectivity_vehicle.manufacturer.value:
100
+ self.manufacturer = carconnectivity_vehicle.manufacturer.value
101
+ carconnectivity_vehicle.model.add_observer(self.__on_model_change, Observable.ObserverEvent.VALUE_CHANGED, on_transaction_end=True)
102
+ if carconnectivity_vehicle.model.enabled and self.model != carconnectivity_vehicle.model.value:
103
+ self.model = carconnectivity_vehicle.model.value
104
+ carconnectivity_vehicle.model_year.add_observer(self.__on_model_year_change, Observable.ObserverEvent.VALUE_CHANGED,
105
+ on_transaction_end=True)
106
+ if carconnectivity_vehicle.model_year.enabled and self.model_year != carconnectivity_vehicle.model_year.value:
107
+ self.model_year = carconnectivity_vehicle.model_year.value
108
+ carconnectivity_vehicle.type.add_observer(self.__on_type_change, Observable.ObserverEvent.VALUE_CHANGED, on_transaction_end=True)
109
+ if carconnectivity_vehicle.type.enabled and carconnectivity_vehicle.type.value is not None \
110
+ and self.type != carconnectivity_vehicle.type.value:
111
+ self.type = carconnectivity_vehicle.type.value
112
+ carconnectivity_vehicle.license_plate.add_observer(self.__on_license_plate_change, Observable.ObserverEvent.VALUE_CHANGED,
113
+ on_transaction_end=True)
114
+ if carconnectivity_vehicle.license_plate.enabled and self.license_plate != carconnectivity_vehicle.license_plate.value:
115
+ self.license_plate = carconnectivity_vehicle.license_plate.value
116
116
 
117
117
  with session_factory() as session:
118
- for drive_id, drive in self.carconnectivity_vehicle.drives.drives.items():
118
+ for drive_id, drive in carconnectivity_vehicle.drives.drives.items():
119
119
  drive_db: Optional[Drive] = session.query(Drive).filter(Drive.vin == self.vin, Drive.drive_id == drive_id).first()
120
120
  if drive_db is None:
121
121
  drive_db = Drive(vin=self.vin, drive_id=drive_id)
@@ -123,30 +123,32 @@ class Vehicle(Base):
123
123
  session.add(drive_db)
124
124
  session.commit()
125
125
  LOG.debug('Added new drive %s for vehicle %s to database', drive_id, self.vin)
126
- drive_db.connect(session_factory, drive)
126
+ drive_db.connect(database_plugin, session_factory, drive)
127
127
  except IntegrityError as err:
128
128
  session.rollback()
129
129
  LOG.error('IntegrityError while adding drive %s for vehicle %s to database, likely due to concurrent addition: %s', drive_id, self.vin,
130
130
  err)
131
+ database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
131
132
  except DatabaseError as err:
132
133
  session.rollback()
133
134
  LOG.error('DatabaseError while adding drive %s for vehicle %s to database: %s', drive_id, self.vin, err)
135
+ database_plugin.healthy._set_value(value=False) # pylint: disable=protected-access
134
136
  else:
135
- drive_db.connect(session_factory, drive)
137
+ drive_db.connect(database_plugin, session_factory, drive)
136
138
  LOG.debug('Connecting drive %s for vehicle %s', drive_id, self.vin)
137
139
 
138
- state_agent: StateAgent = StateAgent(session_factory, self)
140
+ state_agent: StateAgent = StateAgent(database_plugin, session_factory, self, carconnectivity_vehicle)
139
141
  self.agents.append(state_agent)
140
142
  LOG.debug("Adding StateAgent to vehicle %s", self.vin)
141
- climazination_agent: ClimatizationAgent = ClimatizationAgent(session_factory, self)
143
+ climazination_agent: ClimatizationAgent = ClimatizationAgent(database_plugin, session_factory, self, carconnectivity_vehicle)
142
144
  self.agents.append(climazination_agent)
143
145
  LOG.debug("Adding ClimatizationAgent to vehicle %s", self.vin)
144
- trip_agent: TripAgent = TripAgent(session_factory, self)
146
+ trip_agent: TripAgent = TripAgent(database_plugin, session_factory, self, carconnectivity_vehicle)
145
147
  self.agents.append(trip_agent)
146
148
  LOG.debug("Adding TripAgent to vehicle %s", self.vin)
147
149
 
148
- if isinstance(self.carconnectivity_vehicle, ElectricVehicle):
149
- charging_agent: ChargingAgent = ChargingAgent(session_factory, self)
150
+ if isinstance(carconnectivity_vehicle, ElectricVehicle):
151
+ charging_agent: ChargingAgent = ChargingAgent(database_plugin, session_factory, self, carconnectivity_vehicle)
150
152
  self.agents.append(charging_agent)
151
153
  LOG.debug("Adding ChargingAgent to vehicle %s", self.vin)
152
154
  session_factory.remove()
@@ -93,11 +93,6 @@ class Plugin(BasePlugin): # pylint: disable=too-many-instance-attributes
93
93
  session.commit()
94
94
  self.car_connectivity.garage.add_observer(self.__on_add_vehicle, flag=Observable.ObserverEvent.ENABLED, on_transaction_end=True)
95
95
  with self.vehicles_lock:
96
- self.vehicles = {vehicle.vin: vehicle for vehicle in session.query(Vehicle).all()}
97
- for vehicle in self.vehicles.values():
98
- car_connectivity_vehicle: Optional[GenericVehicle] = self.car_connectivity.garage.get_vehicle(vehicle.vin)
99
- if car_connectivity_vehicle is not None:
100
- vehicle.connect(self.scoped_session_factory, car_connectivity_vehicle)
101
96
  for garage_vehicle in self.car_connectivity.garage.list_vehicles():
102
97
  if garage_vehicle.vin.value is not None and garage_vehicle.vin.value not in self.vehicles:
103
98
  LOG.debug('New vehicle found in garage during startup: %s', garage_vehicle.vin.value)
@@ -108,15 +103,15 @@ class Plugin(BasePlugin): # pylint: disable=too-many-instance-attributes
108
103
  session.add(new_vehicle)
109
104
  session.commit()
110
105
  LOG.debug('Added new vehicle %s to database', garage_vehicle.vin.value)
111
- new_vehicle.connect(self.scoped_session_factory, garage_vehicle)
106
+ new_vehicle.connect(self, self.scoped_session_factory, garage_vehicle)
112
107
  self.vehicles[garage_vehicle.vin.value] = new_vehicle
113
108
  except DatabaseError as err:
114
109
  session.rollback()
115
110
  LOG.error('DatabaseError while adding vehicle %s to database: %s', garage_vehicle.vin.value, err)
111
+ self.healthy._set_value(value=False) # pylint: disable=protected-access
116
112
  else:
117
- new_vehicle.connect(self.scoped_session_factory, garage_vehicle)
113
+ new_vehicle.connect(self, self.scoped_session_factory, garage_vehicle)
118
114
  self.vehicles[garage_vehicle.vin.value] = new_vehicle
119
-
120
115
  except OperationalError as err:
121
116
  LOG.error('Could not establish a connection to database, will try again after 10 seconds: %s', err)
122
117
  self.healthy._set_value(value=False) # pylint: disable=protected-access
@@ -141,13 +136,13 @@ class Plugin(BasePlugin): # pylint: disable=too-many-instance-attributes
141
136
  def __on_add_vehicle(self, element, flags) -> None:
142
137
  del flags
143
138
  with self.vehicles_lock:
144
- if isinstance(element, GenericVehicle) and element.vin not in self.vehicles:
139
+ if isinstance(element, GenericVehicle) and element.vin.value not in self.vehicles:
145
140
  LOG.debug('New vehicle added to garage: %s', element.vin)
146
141
  if element.vin.value is not None:
147
142
  with self.scoped_session_factory() as session:
148
143
  if element.vin.value in self.vehicles:
149
144
  vehicle: Vehicle = self.vehicles[element.vin.value]
150
- vehicle.connect(self.scoped_session_factory, element)
145
+ vehicle.connect(self, self.scoped_session_factory, element)
151
146
  else:
152
147
  vehicle: Vehicle = session.get(Vehicle, element.vin.value)
153
148
  if vehicle is None:
@@ -155,11 +150,12 @@ class Plugin(BasePlugin): # pylint: disable=too-many-instance-attributes
155
150
  try:
156
151
  session.add(vehicle)
157
152
  session.commit()
158
- vehicle.connect(self.scoped_session_factory, element)
153
+ vehicle.connect(self, self.scoped_session_factory, element)
159
154
  except DatabaseError as err:
160
155
  session.rollback()
161
156
  LOG.error('DatabaseError while adding vehicle %s to database: %s', element.vin.value, err)
157
+ self.healthy._set_value(value=False) # pylint: disable=protected-access
162
158
  else:
163
- vehicle.connect(self.scoped_session_factory, element)
159
+ vehicle.connect(self, self.scoped_session_factory, element)
164
160
  self.vehicles[element.vin.value] = vehicle
165
161
  self.scoped_session_factory.remove()