Skip to content

Commit

Permalink
add homekit support for battery temperature
Browse files Browse the repository at this point in the history
  • Loading branch information
tillsteinbach committed Oct 27, 2023
1 parent 9080c2c commit 95cae17
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 4 deletions.
9 changes: 5 additions & 4 deletions vwsfriend/vwsfriend/agents/battery_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@ def __init__(self, session, vehicle):
if self.vehicle.weConnectVehicle is not None:
if self.vehicle.weConnectVehicle.statusExists('charging', 'batteryStatus') \
and self.vehicle.weConnectVehicle.domains['charging']['batteryStatus'].enabled:
self.vehicle.weConnectVehicle.domains['charging']['batteryStatus'].carCapturedTimestamp.addObserver(self.__onCarCapturedTimestampChange,
AddressableLeaf.ObserverEvent.VALUE_CHANGED,
onUpdateComplete=True)
self.vehicle.weConnectVehicle.domains['charging']['batteryStatus'].carCapturedTimestamp.addObserver(
self.__onBatteryStatusCarCapturedTimestampChange,
AddressableLeaf.ObserverEvent.VALUE_CHANGED,
onUpdateComplete=True)
self.__onBatteryStatusCarCapturedTimestampChange(self.vehicle.weConnectVehicle.domains['charging']['batteryStatus'].carCapturedTimestamp, None)

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,
self.__onBatteryTemperatureStatusCarCapturedTimestampChange,
AddressableLeaf.ObserverEvent.VALUE_CHANGED,
onUpdateComplete=True)
self.__onBatteryTemperatureStatusCarCapturedTimestampChange(
Expand Down
96 changes: 96 additions & 0 deletions vwsfriend/vwsfriend/homekit/battery_temperature.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import logging

import pyhap

from weconnect.elements.charging_status import ChargingStatus
from weconnect.addressable import AddressableLeaf
from weconnect.util import kelvinToCelsius

from vwsfriend.homekit.genericAccessory import GenericAccessory

LOG = logging.getLogger("VWsFriend")


class BatteryTemperature(GenericAccessory):
"""BatteryTemperature Accessory"""

category = pyhap.const.CATEGORY_OTHER

def __init__(self, driver, bridge, aid, id, vin, displayName, batteryStatus, batteryTemperatureStatus, chargingStatus=None):
super().__init__(driver=driver, bridge=bridge, displayName=displayName, aid=aid, vin=vin, id=id)

self.service = self.add_preload_service('TemperatureSensor', ['Name', 'ConfiguredName', 'BatteryLevel', 'StatusLowBattery', 'ChargingState',
'CurrentTemperature'])

if batteryStatus.currentSOC_pct.enabled:
batteryStatus.currentSOC_pct.addObserver(self.onCurrentSOCChange, AddressableLeaf.ObserverEvent.VALUE_CHANGED)
self.charBatteryLevel = self.service.configure_char('BatteryLevel')
self.charBatteryLevel.set_value(batteryStatus.currentSOC_pct.value)
self.charStatusLowBattery = self.service.configure_char('StatusLowBattery')
self.setStatusLowBattery(batteryStatus.currentSOC_pct)

if chargingStatus is not None and chargingStatus.chargingState.enabled:
chargingStatus.chargingState.addObserver(self.onChargingState, AddressableLeaf.ObserverEvent.VALUE_CHANGED)
self.charChargingState = self.service.configure_char('ChargingState')
self.setChargingState(chargingStatus.chargingState)

if batteryTemperatureStatus is not None and batteryTemperatureStatus.temperatureHvBatteryMin_K.enabled \
and batteryTemperatureStatus.temperatureHvBatteryMax_K.enabled:
batteryTemperatureStatus.addObserver(self.onBatteryTemperatureChange, AddressableLeaf.ObserverEvent.VALUE_CHANGED)
self.charTemperature = self.service.configure_char('CurrentTemperature')
if batteryTemperatureStatus.temperatureHvBatteryMin_K.enabled and batteryTemperatureStatus.temperatureHvBatteryMax_K.enabled:
self.setBatteryTemperature(batteryTemperatureStatus.temperatureHvBatteryMin_K.value, batteryTemperatureStatus.temperatureHvBatteryMax_K.value)

self.addNameCharacteristics()

def setStatusLowBattery(self, currentSOC_pct):
if self.charStatusLowBattery is not None:
if currentSOC_pct.value > 10:
self.charStatusLowBattery.set_value(0)
else:
self.charStatusLowBattery.set_value(1)

def setChargingState(self, chargingState):
if self.charChargingState is not None:
if chargingState.value in (ChargingStatus.ChargingState.OFF,
ChargingStatus.ChargingState.READY_FOR_CHARGING,
ChargingStatus.ChargingState.CHARGE_PURPOSE_REACHED_NOT_CONSERVATION_CHARGING,
ChargingStatus.ChargingState.NOT_READY_FOR_CHARGING):
self.charChargingState.set_value(0)
elif chargingState.value in (ChargingStatus.ChargingState.CHARGING,
ChargingStatus.ChargingState.CHARGE_PURPOSE_REACHED_CONSERVATION,
ChargingStatus.ChargingState.CONSERVATION):
self.charChargingState.set_value(1)
elif chargingState.value in (ChargingStatus.ChargingState.ERROR,
ChargingStatus.ChargingState.UNSUPPORTED):
self.charChargingState.set_value(2)
else:
self.charChargingState.set_value(2)
LOG.warn('unsupported chargingState: %s', chargingState.value.value)

def setBatteryTemperature(self, temperatureHvBatteryMin_K, temperatureHvBatteryMax_K):
if self.charTemperature is not None:
temperature = (kelvinToCelsius(temperatureHvBatteryMin_K) + kelvinToCelsius(temperatureHvBatteryMax_K)) / 2
self.charTemperature.set_value(temperature)

def onCurrentSOCChange(self, element, flags):
if flags & AddressableLeaf.ObserverEvent.VALUE_CHANGED:
self.charBatteryLevel.set_value(element.value)
self.setStatusLowBattery(element)
LOG.debug('Battery SoC Changed: %d %%', element.value)
else:
LOG.debug('Unsupported event %s', flags)

def onChargingState(self, element, flags):
if flags & AddressableLeaf.ObserverEvent.VALUE_CHANGED:
self.setChargingState(element)
LOG.debug('Charging State Changed: %s', element.value.value)
else:
LOG.debug('Unsupported event %s', flags)

def onBatteryTemperatureChange(self, element, flags):
if flags & AddressableLeaf.ObserverEvent.VALUE_CHANGED and element.temperatureHvBatteryMin_K.enabled and element.temperatureHvBatteryMax_K.enabled:
self.setChargingState(element.temperatureHvBatteryMin_K.value, element.temperatureHvBatteryMax_K.value)
LOG.debug('Battery temperature Changed: %f to %f °C', element.temperatureHvBatteryMin_K.value, element.temperatureHvBatteryMax_K.value)
else:
LOG.debug('Unsupported event %s', flags)
28 changes: 28 additions & 0 deletions vwsfriend/vwsfriend/homekit/bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from .plug import Plug
from .locking_system import LockingSystem
from .flashing import Flashing
from .battery_temperature import BatteryTemperature

from vwsfriend.__version import __version__

Expand Down Expand Up @@ -182,6 +183,33 @@ def update(self): # noqa: C901
self.accessories[flashingAccessory.aid] = flashingAccessory
configChanged = True

if vehicle.statusExists('measurements', 'temperatureBatteryStatus') \
and vehicle.domains['measurements']['temperatureBatteryStatus'].carCapturedTimestamp.enabled:
temperatureBatteryStatus = vehicle.domains['measurements']['temperatureBatteryStatus']

if vehicle.statusExists('charging', 'batteryStatus'):
batteryStatus = vehicle.domains['charging']['batteryStatus']

if vehicle.statusExists('charging', 'chargingStatus'):
chargingStatus = vehicle.domains['charging']['chargingStatus']
else:
chargingStatus = None

batteryTemperatureAccessory = BatteryTemperature(driver=self.driver, bridge=self, aid=self.selectAID('BatteryTemperature', vin),
id='BatteryTemperature', vin=vin, displayName=f'{nickname} Battery Temperature',
batteryStatus=batteryStatus, batteryTemperatureStatus=temperatureBatteryStatus,
chargingStatus=chargingStatus)

batteryTemperatureAccessory.set_info_service(manufacturer=manufacturer, model=model, serial_number=f'{vin}-battery_termperature')
self.setConfigItem(batteryTemperatureAccessory.id, batteryTemperatureAccessory.vin, 'category', batteryTemperatureAccessory.category)
self.setConfigItem(batteryTemperatureAccessory.id, batteryTemperatureAccessory.vin, 'services',
[service.display_name for service in batteryTemperatureAccessory.services])
if batteryTemperatureAccessory.aid not in self.accessories:
self.add_accessory(batteryTemperatureAccessory)
else:
self.accessories[batteryTemperatureAccessory.aid] = batteryTemperatureAccessory
configChanged = True

if configChanged:
self.driver.config_changed()
self.persistConfig()
Expand Down

0 comments on commit 95cae17

Please sign in to comment.