[volvooncall] Extend battery channels (#10991)

* [volvooncall] Extend battery channels

Add some convenience channels for charging status and handle the battery level carefully because the API can be misleading.

Signed-off-by: James Hewitt-Thomas <james.hewitt@gmail.com>
This commit is contained in:
James Hewitt
2021-07-18 19:15:59 +01:00
committed by GitHub
parent 5d7993843a
commit fcc23f0ab3
8 changed files with 176 additions and 14 deletions

View File

@@ -78,8 +78,12 @@ public class VolvoOnCallBindingConstants {
public static final String AVERAGE_SPEED = "averageSpeed";
public static final String SERVICE_WARNING = "serviceWarningStatus";
public static final String BATTERY_LEVEL = "batteryLevel";
public static final String BATTERY_LEVEL_RAW = "batteryLevelRaw";
public static final String BATTERY_DISTANCE_TO_EMPTY = "batteryDistanceToEmpty";
public static final String CHARGE_STATUS = "chargeStatus";
public static final String CHARGE_STATUS_CABLE = "chargeStatusCable";
public static final String CHARGE_STATUS_CHARGING = "chargeStatusCharging";
public static final String CHARGE_STATUS_FULLY_CHARGED = "chargeStatusFullyCharged";
public static final String TIME_TO_BATTERY_FULLY_CHARGED = "timeToHVBatteryFullyCharged";
public static final String CHARGING_END = "chargingEnd";
public static final String BULB_FAILURE = "bulbFailure";

View File

@@ -27,8 +27,17 @@ import org.openhab.core.library.types.StringType;
public class HvBattery {
public int hvBatteryLevel = UNDEFINED;
public int distanceToHVBatteryEmpty = UNDEFINED;
/**
* Observed values:
* - CableNotPluggedInCar
* - CablePluggedInCar_ChargingPaused
* - CablePluggedInCar_Charging
* - CablePluggedInCar_ChargingInterrupted
* - CablePluggedInCar_FullyCharged
*/
public @NonNullByDefault({}) StringType hvBatteryChargeStatusDerived;
public int timeToHVBatteryFullyCharged = UNDEFINED;
/*
* Currently unused in the binding, maybe interesting in the future
* private ZonedDateTime timestamp;

View File

@@ -25,7 +25,7 @@ import com.google.gson.annotations.SerializedName;
/**
* The {@link Status} is responsible for storing
* Door Status informations returned by vehicule status rest answer
* Status information returned by vehicle status rest answer
*
* @author Gaël L'hopital - Initial contribution
*/

View File

@@ -373,6 +373,22 @@ public class VehicleHandler extends BaseThingHandler {
private State getBatteryValue(String channelId, HvBattery hvBattery) {
switch (channelId) {
case BATTERY_LEVEL:
/*
* If the car is charging the battery level can be reported as 100% by the API regardless of actual
* charge level, but isn't always. So, if we see that the car is Charging, ChargingPaused, or
* ChargingInterrupted and the reported battery level is 100%, then instead produce UNDEF.
*
* If we see FullyCharged, then we can rely on the value being 100% anyway.
*/
if (hvBattery.hvBatteryChargeStatusDerived != null
&& hvBattery.hvBatteryChargeStatusDerived.toString().startsWith("CablePluggedInCar_Charging")
&& hvBattery.hvBatteryLevel != UNDEFINED && hvBattery.hvBatteryLevel == 100) {
return UnDefType.UNDEF;
} else {
return hvBattery.hvBatteryLevel != UNDEFINED ? new QuantityType<>(hvBattery.hvBatteryLevel, PERCENT)
: UnDefType.UNDEF;
}
case BATTERY_LEVEL_RAW:
return hvBattery.hvBatteryLevel != UNDEFINED ? new QuantityType<>(hvBattery.hvBatteryLevel, PERCENT)
: UnDefType.UNDEF;
case BATTERY_DISTANCE_TO_EMPTY:
@@ -382,6 +398,27 @@ public class VehicleHandler extends BaseThingHandler {
case CHARGE_STATUS:
return hvBattery.hvBatteryChargeStatusDerived != null ? hvBattery.hvBatteryChargeStatusDerived
: UnDefType.UNDEF;
case CHARGE_STATUS_CABLE:
return hvBattery.hvBatteryChargeStatusDerived != null
? OnOffType.from(
hvBattery.hvBatteryChargeStatusDerived.toString().startsWith("CablePluggedInCar_"))
: UnDefType.UNDEF;
case CHARGE_STATUS_CHARGING:
return hvBattery.hvBatteryChargeStatusDerived != null
? OnOffType.from(hvBattery.hvBatteryChargeStatusDerived.toString().endsWith("_Charging"))
: UnDefType.UNDEF;
case CHARGE_STATUS_FULLY_CHARGED:
/*
* If the car is charging the battery level can be reported incorrectly by the API, so use the charging
* status instead of checking the level when the car is plugged in.
*/
if (hvBattery.hvBatteryChargeStatusDerived != null
&& hvBattery.hvBatteryChargeStatusDerived.toString().startsWith("CablePluggedInCar_")) {
return OnOffType.from(hvBattery.hvBatteryChargeStatusDerived.toString().endsWith("_FullyCharged"));
} else {
return hvBattery.hvBatteryLevel != UNDEFINED ? OnOffType.from(hvBattery.hvBatteryLevel == 100)
: UnDefType.UNDEF;
}
case TIME_TO_BATTERY_FULLY_CHARGED:
return hvBattery.timeToHVBatteryFullyCharged != UNDEFINED
? new QuantityType<>(hvBattery.timeToHVBatteryFullyCharged, MINUTE)

View File

@@ -210,13 +210,17 @@
<label>Plugin Hybrid / Twin Engine info</label>
<channels>
<channel id="batteryLevel" typeId="batteryLevel"/>
<channel id="batteryLevelRaw" typeId="batteryLevelRaw"/>
<channel id="batteryDistanceToEmpty" typeId="odometer">
<label>Distance to battery empty</label>
<label>Distance Left (Battery)</label>
</channel>
<channel id="chargeStatus" typeId="chargeStatus"/>
<channel id="chargeStatusCable" typeId="chargeStatusCable"/>
<channel id="chargeStatusCharging" typeId="chargeStatusCharging"/>
<channel id="chargeStatusFullyCharged" typeId="chargeStatusFullyCharged"/>
<channel id="timeToHVBatteryFullyCharged" typeId="timeToHVBatteryFullyCharged"/>
<channel id="chargingEnd" typeId="timestamp">
<label>Charging end</label>
<label>Charging End</label>
</channel>
</channels>
</channel-group-type>
@@ -237,7 +241,7 @@
<channel-type id="window">
<item-type>Contact</item-type>
<label>Window Status</label>
<label>Window</label>
<description>Indicates if the window is opened</description>
<state readOnly="true"></state>
</channel-type>
@@ -251,7 +255,7 @@
<channel-type id="averageSpeed">
<item-type>Number:Speed</item-type>
<label>Average speed</label>
<label>Average Speed</label>
<description>Average speed of the vehicle</description>
<state pattern="%.2f %unit%" readOnly="true"></state>
</channel-type>
@@ -316,7 +320,7 @@
<channel-type id="carLocked">
<item-type>Switch</item-type>
<label>Locked</label>
<description>Car locking status</description>
<description>Lock status</description>
<category>lock</category>
</channel-type>
@@ -343,7 +347,7 @@
<channel-type id="bulbFailure">
<item-type>Switch</item-type>
<label>Bulb Failure</label>
<description>At least on bulb is reported as dead</description>
<description>At least one bulb is reported as dead</description>
<category>alarm</category>
<state readOnly="true"></state>
</channel-type>
@@ -364,7 +368,7 @@
<channel-type id="tyrePressure">
<item-type>Number</item-type>
<label>Tyre pressure</label>
<label>Tyre Pressure</label>
<category>alarm</category>
<state readOnly="true">
<options>
@@ -377,7 +381,7 @@
<channel-type id="serviceWarningStatus">
<item-type>String</item-type>
<label>Service Warning</label>
<description>Is car service needed ?</description>
<description>Is a car service needed?</description>
<category>alarm</category>
<state readOnly="true"></state>
</channel-type>
@@ -385,21 +389,52 @@
<channel-type id="batteryLevel">
<item-type>Number:Dimensionless</item-type>
<label>Battery Level</label>
<description>Indicates the level of power in the battery (in case of PHEV / Twin Engine)</description>
<description>Indicates the level of power in the battery, or unknown in situations the API is misleading (in case of
PHEV / Twin Engine)</description>
<category>batterylevel</category>
<state pattern="%d %unit%" readOnly="true"></state>
</channel-type>
<channel-type id="batteryLevelRaw">
<item-type>Number:Dimensionless</item-type>
<label>Battery Level (Raw)</label>
<description>Indicates the level of power in the battery taken straight from the API, which can be misleading (in case
of PHEV / Twin Engine)</description>
<category>batterylevel</category>
<state pattern="%d %unit%" readOnly="true"></state>
</channel-type>
<channel-type id="chargeStatus">
<item-type>String</item-type>
<label>Charging status</label>
<label>Charging Status</label>
<description>Status of charging (in case of PHEV / Twin Engine)</description>
<state readOnly="true"></state>
</channel-type>
<channel-type id="chargeStatusCable">
<item-type>Switch</item-type>
<label>Plugged In</label>
<description>Indicates if the charging cable is connected</description>
<state readOnly="true"></state>
</channel-type>
<channel-type id="chargeStatusCharging">
<item-type>Switch</item-type>
<label>Charging</label>
<description>Indicates if the car is currently charging</description>
<state readOnly="true"></state>
</channel-type>
<channel-type id="chargeStatusFullyCharged">
<item-type>Switch</item-type>
<label>Fully Charged</label>
<description>Indicates if the car is fully charged</description>
<state readOnly="true"></state>
</channel-type>
<channel-type id="timeToHVBatteryFullyCharged">
<item-type>Number:Time</item-type>
<label>Time to battery fully charged</label>
<label>Remaining Charging Time</label>
<description>Time in seconds until the battery is fully charged (in case of PHEV / Twin Engine)</description>
<state pattern="%d %unit%" readOnly="true"></state>
</channel-type>