Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mybmw] Improve data refresh handling #16418

Merged
merged 12 commits into from
Feb 25, 2024
248 changes: 134 additions & 114 deletions bundles/org.openhab.binding.mybmw/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public interface MyBMWConstants {

static final int DEFAULT_IMAGE_SIZE_PX = 1024;

static final int DEFAULT_REFRESH_INTERVAL_MINUTES = 5;
static final int DEFAULT_REFRESH_INTERVAL_MINUTES = 60;
lsiepel marked this conversation as resolved.
Show resolved Hide resolved

// See constants from bimmer-connected
// https://github.com/bimmerconnected/bimmer_connected/blob/master/bimmer_connected/vehicle.py
Expand Down Expand Up @@ -107,6 +107,7 @@ enum ChargingPreference {
THING_TYPE_PHEV, THING_TYPE_BEV_REX, THING_TYPE_BEV);

// Thing Group definitions
static final String CHANNEL_GROUP_UPDATE = "update";
static final String CHANNEL_GROUP_STATUS = "status";
static final String CHANNEL_GROUP_SERVICE = "service";
static final String CHANNEL_GROUP_CHECK_CONTROL = "check";
Expand All @@ -120,6 +121,11 @@ enum ChargingPreference {
static final String CHANNEL_GROUP_TIRES = "tires";
static final String CHANNEL_GROUP_VEHICLE_IMAGE = "image";

// types of updates
static final String STATE_UPDATE = "state-update";
static final String CHARGING_UPDATE = "charging-update";
static final String IMAGE_UPDATE = "image-update";

// Charge Statistics & Sessions
static final String SESSIONS = "sessions";
static final String ENERGY = "energy";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ private void getState() {
ExecutionState.TIMEOUT.name().toLowerCase());
reset();
// immediately refresh data
handler.getData();
handler.updateData();
} else {
counter++;
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import static org.openhab.binding.mybmw.internal.MyBMWConstants.CHANNEL_GROUP_SERVICE;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.CHANNEL_GROUP_STATUS;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.CHANNEL_GROUP_TIRES;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.CHANNEL_GROUP_UPDATE;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.CHANNEL_GROUP_VEHICLE_IMAGE;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.CHARGE_ENABLED;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.CHARGE_PROFILE_CLIMATE;
Expand All @@ -34,6 +35,7 @@
import static org.openhab.binding.mybmw.internal.MyBMWConstants.CHARGE_PROFILE_TARGET;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.CHARGE_REMAINING;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.CHARGE_STATUS;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.CHARGING_UPDATE;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.CHECK_CONTROL;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.DATE;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.DETAILS;
Expand All @@ -54,6 +56,7 @@
import static org.openhab.binding.mybmw.internal.MyBMWConstants.HOME_DISTANCE;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.HOOD;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.IMAGE_FORMAT;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.IMAGE_UPDATE;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.IMAGE_VIEWPORT;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.ISSUE;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.LAST_FETCHED;
Expand Down Expand Up @@ -81,6 +84,7 @@
import static org.openhab.binding.mybmw.internal.MyBMWConstants.SESSIONS;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.SEVERITY;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.SOC;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.STATE_UPDATE;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.STATUS;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.SUBTITLE;
import static org.openhab.binding.mybmw.internal.MyBMWConstants.SUNROOF;
Expand Down Expand Up @@ -207,6 +211,8 @@ public class VehicleHandler extends BaseThingHandler {

private ImageProperties imageProperties = new ImageProperties();

private ThingStatus currentStatus = ThingStatus.UNKNOWN;

public VehicleHandler(Thing thing, MyBMWCommandOptionProvider commandOptionProvider,
LocationProvider locationProvider, TimeZoneProvider timeZoneProvider, String driveTrain) {
super(thing);
Expand Down Expand Up @@ -237,7 +243,8 @@ private void setOptions(final String group, final String id, List<CommandOption>
@Override
public void initialize() {
logger.trace("VehicleHandler.initialize");
updateStatus(ThingStatus.UNKNOWN);
currentStatus = ThingStatus.UNKNOWN;
updateStatus(currentStatus);
vehicleConfiguration = Optional.of(getConfigAs(MyBMWVehicleConfiguration.class));

Bridge bridge = getBridge();
Expand All @@ -257,20 +264,26 @@ public void initialize() {
updateChannel(CHANNEL_GROUP_VEHICLE_IMAGE, IMAGE_VIEWPORT, Converter.toTitleCase(imageProperties.viewport),
null);

// start update schedule
startSchedule(vehicleConfiguration.get().getRefreshInterval());
}

private void startSchedule(int interval) {
logger.trace("VehicleHandler.startSchedule");
refreshJob.ifPresentOrElse(job -> {
if (job.isCancelled()) {
// start update schedule only if the refreshInterval is not 0
if (interval > 0) {
logger.info("VehicleHandler.startSchedule with interval {}min", interval);
refreshJob.ifPresentOrElse(job -> {
if (job.isCancelled()) {
refreshJob = Optional
.of(scheduler.scheduleWithFixedDelay(this::updateData, 0, interval, TimeUnit.MINUTES));
} // else - scheduler is already running!
}, () -> {
refreshJob = Optional
.of(scheduler.scheduleWithFixedDelay(this::getData, 0, interval, TimeUnit.MINUTES));
} // else - scheduler is already running!
}, () -> {
refreshJob = Optional.of(scheduler.scheduleWithFixedDelay(this::getData, 0, interval, TimeUnit.MINUTES));
});
.of(scheduler.scheduleWithFixedDelay(this::updateData, 0, interval, TimeUnit.MINUTES));
});
} else {
logger.info("VehicleHandler initialize: don't start schedule as interval is 0");
updateData();
}
}

@Override
Expand All @@ -281,25 +294,44 @@ public void dispose() {
remote.ifPresent(RemoteServiceExecutor::cancel);
}

public void getData() {
logger.trace("VehicleHandler.getData");
/**
* update all data
*/
void updateData() {
logger.trace("VehicleHandler.updateData");
updateVehicleStatus();
if (isElectric) {
updateCharging();
}
updateImage();
}

private void updateVehicleStatus() {
proxy.ifPresentOrElse(prox -> {
vehicleConfiguration.ifPresentOrElse(config -> {

boolean stateError = false;
try {
VehicleStateContainer vehicleState = prox.requestVehicleState(config.getVin(),
config.getVehicleBrand());
triggerVehicleStatusUpdate(vehicleState, null);
stateError = false;
currentStatus = ThingStatus.ONLINE;
updateStatus(currentStatus);
} catch (NetworkException e) {
logger.debug("{}", e.toString());
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
"Vehicle State Update failed");
stateError = true;
currentStatus = ThingStatus.OFFLINE;
updateStatus(currentStatus, ThingStatusDetail.COMMUNICATION_ERROR, "Vehicle State Update failed");
}
}, () -> {
logger.warn("MyBMW Vehicle Configuration isn't present");
});
}, () -> {
logger.warn("MyBMWProxy isn't present");
});
}

if (!stateError && isElectric) {
private void updateCharging() {
proxy.ifPresentOrElse(prox -> {
vehicleConfiguration.ifPresentOrElse(config -> {
if (isElectric && ThingStatus.ONLINE.equals(currentStatus)) {
try {
updateChargingStatistics(
prox.requestChargeStatistics(config.getVin(), config.getVehicleBrand()), null);
Expand All @@ -309,7 +341,19 @@ public void getData() {
logger.debug("{}", e.toString());
}
}
if (!stateError && !imageCache.isPresent() && !imageProperties.failLimitReached()) {
}, () -> {
logger.warn("MyBMW Vehicle Configuration isn't present");
});
}, () -> {
logger.warn("MyBMWProxy isn't present");
});
}

private void updateImage() {
proxy.ifPresentOrElse(prox -> {
vehicleConfiguration.ifPresentOrElse(config -> {
if (!imageCache.isPresent() && !imageProperties.failLimitReached()
&& ThingStatus.ONLINE.equals(currentStatus)) {
try {
updateImage(prox.requestImage(config.getVin(), config.getVehicleBrand(), imageProperties));
} catch (NetworkException e) {
Expand All @@ -334,8 +378,6 @@ private void triggerVehicleStatusUpdate(VehicleStateContainer vehicleState, @Nul
if (isElectric) {
updateChargingProfile(vehicleState.getState().getChargingProfile(), channelToBeUpdated);
}

updateStatus(ThingStatus.ONLINE);
} else {
logger.debug("configuration not present");
}
Expand Down Expand Up @@ -951,6 +993,25 @@ public void handleCommand(ChannelUID channelUID, Command command) {
logger.debug("Cannot handle command {}, channel {} in group {} not a command channel",
command.toFullString(), channelUID.getAsString(), group);
}
} else if (command instanceof OnOffType) {
if (CHANNEL_GROUP_UPDATE.equals(group) && OnOffType.ON.equals(command)) {
// triggering the update of the respective channel
switch (channelUID.getIdWithoutGroup()) {
case STATE_UPDATE:
updateVehicleStatus();
break;
case CHARGING_UPDATE:
updateCharging();
break;
case IMAGE_UPDATE:
updateImage();
break;
default:
break;
}
// immediately set the switch back to off
updateChannel(group, channelUID.getIdWithoutGroup(), OnOffType.OFF, null);
mherwege marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<label>Vehicle Identification Number (VIN)</label>
<description>Unique VIN given by BMW</description>
</parameter>
<parameter name="refreshInterval" type="integer" min="1" unit="min" required="true">
<parameter name="refreshInterval" type="integer" min="0" unit="min" required="true">
<label>Refresh Interval</label>
<description>Data refresh rate for your vehicle data</description>
<default>5</default>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ thing-type.config.mybmw.bridge.region.option.ROW = Rest of the World
thing-type.config.mybmw.bridge.userName.description = MyBMW Username
thing-type.config.mybmw.bridge.userName.label = Username

thing-type.config.mybmw.vehicle.refreshInterval.description = Data refresh rate for your vehicle data
thing-type.config.mybmw.vehicle.refreshInterval.description = Data refresh rate for your vehicle data. If set to 0 no refresh will be triggered automatically.
thing-type.config.mybmw.vehicle.refreshInterval.label = Refresh Interval
thing-type.config.mybmw.vehicle.vehicleBrand.description = Vehicle brand like BMW or Mini
thing-type.config.mybmw.vehicle.vehicleBrand.label = Brand of the Vehicle
Expand Down Expand Up @@ -46,6 +46,8 @@ channel-group-type.mybmw.ev-range-values.description = Provides Mileage, remaini
channel-group-type.mybmw.ev-range-values.label = Range and Charge Data
channel-group-type.mybmw.ev-vehicle-status.description = Overall vehicle status
channel-group-type.mybmw.ev-vehicle-status.label = Vehicle Status
channel-group-type.mybmw.ev-vehicle-update.description = Force the update of the vehicle data
channel-group-type.mybmw.ev-vehicle-update.label = Force Vehicle Update
channel-group-type.mybmw.hybrid-range-values.description = Provides mileage, remaining fuel and range data for hybrid vehicles
channel-group-type.mybmw.hybrid-range-values.label = Range, Charge / Fuel Data
channel-group-type.mybmw.image-values.description = Provides an image of your vehicle
Expand All @@ -65,12 +67,16 @@ channel-group-type.mybmw.tire-pressures.description = Current and wanted pressur
channel-group-type.mybmw.tire-pressures.label = Tire Pressure
channel-group-type.mybmw.vehicle-status.description = Overall vehicle status
channel-group-type.mybmw.vehicle-status.label = Vehicle Status
channel-group-type.mybmw.vehicle-update.description = Force the update of the vehicle data
channel-group-type.mybmw.vehicle-update.label = Force Vehicle Update


# channel types
channel-type.mybmw.address-channel.label = Address
channel-type.mybmw.charging-info-channel.label = Charging Information
channel-type.mybmw.charging-remaining-channel.label = Remaining Charging Time
channel-type.mybmw.charging-status-channel.label = Charging Status
channel-type.mybmw.charging-update-channel.label = Force update of the charging data
channel-type.mybmw.check-control-channel.label = Check Control
channel-type.mybmw.checkcontrol-details-channel.label = CheckControl Details
channel-type.mybmw.checkcontrol-name-channel.label = CheckControl Description
Expand All @@ -91,6 +97,7 @@ channel-type.mybmw.home-distance-channel.description = Computed distance between
channel-type.mybmw.home-distance-channel.label = Distance From Home
channel-type.mybmw.hood-channel.label = Hood

channel-type.mybmw.image-update-channel.label = Force update of the image
channel-type.mybmw.image-view-channel.command.option.FrontLeft = Left Side View
channel-type.mybmw.image-view-channel.command.option.FrontRight = Right Side View
channel-type.mybmw.image-view-channel.command.option.FrontView = Front View
Expand Down Expand Up @@ -161,6 +168,7 @@ channel-type.mybmw.session-subtitle-channel.label = Session Details
channel-type.mybmw.session-title-channel.label = Session Title
channel-type.mybmw.soc-channel.label = Battery Charge Level

channel-type.mybmw.state-update-channel.label = Force update of the vehicle state data
channel-type.mybmw.statistic-energy-channel.description = Total energy charged in current month
channel-type.mybmw.statistic-energy-channel.label = Energy Charged
channel-type.mybmw.statistic-sessions-channel.description = Number of charging sessions this month
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="mybmw"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<channel-group-type id="ev-vehicle-update">
<label>Vehicle Update</label>
<description>Triggering the vehicle update</description>
<channels>
<channel id="state-update" typeId="state-update-channel"/>
<channel id="charging-update" typeId="charging-update-channel"/>
<channel id="image-update" typeId="image-update-channel"/>
</channels>
</channel-group-type>
</thing:thing-descriptions>
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<description>Battery Electric Vehicle (BEV)</description>

<channel-groups>
<channel-group id="update" typeId="ev-vehicle-update"/>
<channel-group id="status" typeId="ev-vehicle-status"/>
<channel-group id="doors" typeId="door-values"/>
<channel-group id="range" typeId="ev-range-values"/>
Expand All @@ -28,7 +29,7 @@
</channel-groups>

<properties>
<property name="thingTypeVersion">1</property>
<property name="thingTypeVersion">2</property>
</properties>

<representation-property>vin</representation-property>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<description>Battery Electric Vehicle with Range Extender (BEV_REX)</description>

<channel-groups>
<channel-group id="update" typeId="ev-vehicle-update"/>
<channel-group id="status" typeId="ev-vehicle-status"/>
<channel-group id="doors" typeId="door-values"/>
<channel-group id="range" typeId="hybrid-range-values"/>
Expand All @@ -28,7 +29,7 @@
</channel-groups>

<properties>
<property name="thingTypeVersion">1</property>
<property name="thingTypeVersion">2</property>
</properties>

<representation-property>vin</representation-property>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<description>Conventional Fuel Vehicle (CONV)</description>

<channel-groups>
<channel-group id="update" typeId="vehicle-update"/>
<channel-group id="status" typeId="vehicle-status"/>
<channel-group id="doors" typeId="door-values"/>
<channel-group id="range" typeId="conv-range-values"/>
Expand All @@ -25,7 +26,7 @@
</channel-groups>

<properties>
<property name="thingTypeVersion">1</property>
<property name="thingTypeVersion">2</property>
</properties>

<representation-property>vin</representation-property>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<description>Conventional Fuel Vehicle with supporting Electric Engine (PHEV)</description>

<channel-groups>
<channel-group id="update" typeId="ev-vehicle-update"/>
<channel-group id="status" typeId="ev-vehicle-status"/>
<channel-group id="doors" typeId="door-values"/>
<channel-group id="range" typeId="hybrid-range-values"/>
Expand All @@ -28,7 +29,7 @@
</channel-groups>

<properties>
<property name="thingTypeVersion">1</property>
<property name="thingTypeVersion">2</property>
</properties>

<representation-property>vin</representation-property>
Expand Down