carconnectivity-plugin-database 0.1__py3-none-any.whl → 0.1a16__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of carconnectivity-plugin-database might be problematic. Click here for more details.

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