Skip to content

Commit

Permalink
new database schema to add battery temperature logging
Browse files Browse the repository at this point in the history
  • Loading branch information
tillsteinbach committed Oct 27, 2023
1 parent 8209552 commit 9080c2c
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 2 deletions.
49 changes: 47 additions & 2 deletions vwsfriend/vwsfriend/agents/battery_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from sqlalchemy.orm.exc import ObjectDeletedError

from vwsfriend.model.battery import Battery
from vwsfriend.model.battery_temperature import BatteryTemperature

from weconnect.addressable import AddressableLeaf

Expand All @@ -16,6 +17,9 @@ def __init__(self, session, vehicle):
self.vehicle = session.merge(vehicle)
self.battery = session.query(Battery).filter(and_(Battery.vehicle == vehicle,
Battery.carCapturedTimestamp.isnot(None))).order_by(Battery.carCapturedTimestamp.desc()).first()
self.batteryTemperature = session.query(BatteryTemperature).filter(and_(BatteryTemperature.vehicle == vehicle,
BatteryTemperature.carCapturedTimestamp.isnot(None))) \
.order_by(BatteryTemperature.carCapturedTimestamp.desc()).first()

# register for updates:
if self.vehicle.weConnectVehicle is not None:
Expand All @@ -24,9 +28,18 @@ def __init__(self, session, vehicle):
self.vehicle.weConnectVehicle.domains['charging']['batteryStatus'].carCapturedTimestamp.addObserver(self.__onCarCapturedTimestampChange,
AddressableLeaf.ObserverEvent.VALUE_CHANGED,
onUpdateComplete=True)
self.__onCarCapturedTimestampChange(self.vehicle.weConnectVehicle.domains['charging']['batteryStatus'].carCapturedTimestamp, None)
self.__onBatteryStatusCarCapturedTimestampChange(self.vehicle.weConnectVehicle.domains['charging']['batteryStatus'].carCapturedTimestamp, None)

def __onCarCapturedTimestampChange(self, element, flags):
if self.vehicle.weConnectVehicle.statusExists('measurements', 'temperatureBatteryStatus') \
and self.vehicle.weConnectVehicle.domains['measurements']['temperatureBatteryStatus'].enabled:
self.vehicle.weConnectVehicle.domains['measurements']['temperatureBatteryStatus'].carCapturedTimestamp.addObserver(
self.__onCarCapturedTimestampChange,
AddressableLeaf.ObserverEvent.VALUE_CHANGED,
onUpdateComplete=True)
self.__onBatteryTemperatureStatusCarCapturedTimestampChange(
self.vehicle.weConnectVehicle.domains['measurements']['temperatureBatteryStatus'].carCapturedTimestamp, None)

def __onBatteryStatusCarCapturedTimestampChange(self, element, flags):
if element is not None and element.value is not None:
batteryStatus = self.vehicle.weConnectVehicle.domains['charging']['batteryStatus']
current_currentSOC_pct = batteryStatus.currentSOC_pct.value
Expand Down Expand Up @@ -57,5 +70,37 @@ def __onCarCapturedTimestampChange(self, element, flags):
LOG.warning('Could not add battery entry to the database, this is usually due to an error in the WeConnect API (%s)', err)
self.session.commit()

def __onBatteryTemperatureStatusCarCapturedTimestampChange(self, element, flags):
if element is not None and element.value is not None:
batteryTemperatureStatus = self.vehicle.weConnectVehicle.domains['measurements']['temperatureBatteryStatus']
current_temperatureHvBatteryMin_K = batteryTemperatureStatus.temperatureHvBatteryMin_K.value
current_temperatureHvBatteryMax_K = batteryTemperatureStatus.temperatureHvBatteryMax_K.value

if self.batteryTemperature is not None:
try:
self.session.refresh(self.batteryTemperature)
except ObjectDeletedError:
LOG.warning('Last battery entry was deleted')
self.batteryTemperature = self.session.query(BatteryTemperature).filter(and_(BatteryTemperature.vehicle == self.vehicle,
BatteryTemperature.carCapturedTimestamp.isnot(None)))\
.order_by(BatteryTemperature.carCapturedTimestamp.desc()).first()

if self.batteryTemperature is None or (self.batteryTemperature.carCapturedTimestamp != batteryTemperatureStatus.carCapturedTimestamp.value and (
self.batteryTemperature.temperatureHvBatteryMin_K != current_temperatureHvBatteryMin_K
or self.batteryTemperature.temperatureHvBatteryMax_K != current_temperatureHvBatteryMax_K)):

if self.batteryTemperature is not None and self.batteryTemperature.carCapturedTimestamp > element.value:
LOG.warning('carCapturedTimestamp (%s) provided by batteryTemperatureStatus is older than previously recorded carCapturedTimestamp (%s)',
element.value, self.batteryTemperature.carCapturedTimestamp)

self.batteryTemperature = BatteryTemperature(self.vehicle, batteryTemperatureStatus.carCapturedTimestamp.value,
current_temperatureHvBatteryMin_K, current_temperatureHvBatteryMax_K)
with self.session.begin_nested():
try:
self.session.add(self.batteryTemperature)
except IntegrityError as err:
LOG.warning('Could not add batteryTemperature entry to the database, this is usually due to an error in the WeConnect API (%s)', err)
self.session.commit()

def commit(self):
self.session.commit()
1 change: 1 addition & 0 deletions vwsfriend/vwsfriend/model/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .battery import Battery
from .battery_temperature import BatteryTemperature
from .charge import Charge
from .charging_session import ChargingSession
from .climatization import Climatization
Expand Down
24 changes: 24 additions & 0 deletions vwsfriend/vwsfriend/model/battery_temperature.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from sqlalchemy import Column, Integer, Float, String, ForeignKey, UniqueConstraint
from sqlalchemy.orm import relationship

from vwsfriend.model.base import Base
from vwsfriend.model.datetime_decorator import DatetimeDecorator


class BatteryTemperature(Base):
__tablename__ = 'battery_temperature'
__table_args__ = (
UniqueConstraint('vehicle_vin', 'carCapturedTimestamp'),
)
id = Column(Integer, primary_key=True)
vehicle_vin = Column(String, ForeignKey('vehicles.vin'))
carCapturedTimestamp = Column(DatetimeDecorator(timezone=True), nullable=False)
vehicle = relationship("Vehicle")
temperatureHvBatteryMin_K = Column(Float)
temperatureHvBatteryMax_K = Column(Float)

def __init__(self, vehicle, carCapturedTimestamp, temperatureHvBatteryMin_K, temperatureHvBatteryMax_K):
self.vehicle = vehicle
self.carCapturedTimestamp = carCapturedTimestamp
self.temperatureHvBatteryMin_K = temperatureHvBatteryMin_K
self.temperatureHvBatteryMax_K = temperatureHvBatteryMax_K
Binary file modified vwsfriend/vwsfriend/model/vwsfriend-schema/reference.db
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""Added battery temperature table
Revision ID: 6c4cdc5006ba
Revises: f3a66cd08ebe
Create Date: 2023-10-27 12:12:09.450271
"""
from alembic import op
import sqlalchemy as sa

from vwsfriend.model.datetime_decorator import DatetimeDecorator

# revision identifiers, used by Alembic.
revision = '6c4cdc5006ba'
down_revision = 'f3a66cd08ebe'
branch_labels = None
depends_on = None


def upgrade():
op.create_table('battery_temperature',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('vehicle_vin', sa.String(), nullable=True),
sa.Column('carCapturedTimestamp', DatetimeDecorator(timezone=True), nullable=False),
sa.Column('temperatureHvBatteryMin_K', sa.Float(), nullable=True),
sa.Column('temperatureHvBatteryMax_K', sa.Float(), nullable=True),
sa.ForeignKeyConstraint(['vehicle_vin'], ['vehicles.vin'], ),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('vehicle_vin', 'carCapturedTimestamp')
)


def downgrade():
op.drop_table('battery_temperature')

0 comments on commit 9080c2c

Please sign in to comment.