2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.mybmw.internal.handler;
15 import java.util.Collection;
16 import java.util.List;
17 import java.util.Optional;
18 import java.util.concurrent.ScheduledFuture;
19 import java.util.concurrent.TimeUnit;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.openhab.binding.mybmw.internal.MyBMWBridgeConfiguration;
23 import org.openhab.binding.mybmw.internal.discovery.VehicleDiscovery;
24 import org.openhab.binding.mybmw.internal.handler.backend.MyBMWFileProxy;
25 import org.openhab.binding.mybmw.internal.handler.backend.MyBMWHttpProxy;
26 import org.openhab.binding.mybmw.internal.handler.backend.MyBMWProxy;
27 import org.openhab.binding.mybmw.internal.utils.Constants;
28 import org.openhab.binding.mybmw.internal.utils.MyBMWConfigurationChecker;
29 import org.openhab.core.i18n.LocaleProvider;
30 import org.openhab.core.io.net.http.HttpClientFactory;
31 import org.openhab.core.thing.Bridge;
32 import org.openhab.core.thing.ChannelUID;
33 import org.openhab.core.thing.ThingStatus;
34 import org.openhab.core.thing.ThingStatusDetail;
35 import org.openhab.core.thing.binding.BaseBridgeHandler;
36 import org.openhab.core.thing.binding.ThingHandlerService;
37 import org.openhab.core.types.Command;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
42 * The {@link MyBMWBridgeHandler} is responsible for handling commands, which
44 * sent to one of the channels.
46 * @author Bernd Weymann - Initial contribution
47 * @author Martin Grassl - refactored, all discovery functionality moved to VehicleDiscovery
50 public class MyBMWBridgeHandler extends BaseBridgeHandler {
52 private static final String ENVIRONMENT = "ENVIRONMENT";
53 private static final String TEST = "test";
54 private static final String TESTUSER = "testuser";
56 private final Logger logger = LoggerFactory.getLogger(MyBMWBridgeHandler.class);
58 private HttpClientFactory httpClientFactory;
59 private Optional<MyBMWProxy> myBmwProxy = Optional.empty();
60 private Optional<ScheduledFuture<?>> initializerJob = Optional.empty();
61 private Optional<VehicleDiscovery> vehicleDiscovery = Optional.empty();
62 private LocaleProvider localeProvider;
64 public MyBMWBridgeHandler(Bridge bridge, HttpClientFactory hcf, LocaleProvider localeProvider) {
66 httpClientFactory = hcf;
67 this.localeProvider = localeProvider;
70 public void setVehicleDiscovery(VehicleDiscovery vehicleDiscovery) {
71 logger.trace("MyBMWBridgeHandler.setVehicleDiscovery");
72 this.vehicleDiscovery = Optional.of(vehicleDiscovery);
76 public void handleCommand(ChannelUID channelUID, Command command) {
77 // no commands available
78 logger.trace("MyBMWBridgeHandler.handleCommand");
82 public void initialize() {
83 logger.trace("MyBMWBridgeHandler.initialize");
84 updateStatus(ThingStatus.UNKNOWN);
85 MyBMWBridgeConfiguration config = getConfigAs(MyBMWBridgeConfiguration.class);
86 if (config.language.equals(Constants.LANGUAGE_AUTODETECT)) {
87 config.language = localeProvider.getLocale().getLanguage().toLowerCase();
89 if (!MyBMWConfigurationChecker.checkConfiguration(config)) {
90 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR);
92 // there is no risk in this functionality as several steps have to happen to get the file proxy working:
93 // 1. environment variable ENVIRONMENT has to be available
94 // 2. username of the myBMW account must be set to "testuser" which is anyhow no valid username
95 // 3. the jar file must contain the fingerprints which will only happen if it has been built with the
97 String environment = System.getenv(ENVIRONMENT);
99 if (environment == null) {
103 createMyBmwProxy(config, environment);
104 initializerJob = Optional.of(scheduler.schedule(this::discoverVehicles, 2, TimeUnit.SECONDS));
108 private synchronized void createMyBmwProxy(MyBMWBridgeConfiguration config, String environment) {
109 if (!myBmwProxy.isPresent()) {
110 if (!(TEST.equals(environment) && TESTUSER.equals(config.userName))) {
111 myBmwProxy = Optional.of(new MyBMWHttpProxy(httpClientFactory, config));
113 myBmwProxy = Optional.of(new MyBMWFileProxy(httpClientFactory, config));
115 logger.trace("MyBMWBridgeHandler proxy set");
120 public void dispose() {
121 logger.trace("MyBMWBridgeHandler.dispose");
122 initializerJob.ifPresent(job -> job.cancel(true));
125 public void vehicleDiscoveryError() {
126 logger.trace("MyBMWBridgeHandler.vehicleDiscoveryError");
127 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Request vehicles failed");
130 public void vehicleDiscoverySuccess() {
131 logger.trace("MyBMWBridgeHandler.vehicleDiscoverySuccess");
132 updateStatus(ThingStatus.ONLINE);
135 private void discoverVehicles() {
136 logger.trace("MyBMWBridgeHandler.requestVehicles");
138 MyBMWBridgeConfiguration config = getConfigAs(MyBMWBridgeConfiguration.class);
140 myBmwProxy.ifPresent(proxy -> proxy.setBridgeConfiguration(config));
142 vehicleDiscovery.ifPresent(discovery -> discovery.discoverVehicles());
146 public Collection<Class<? extends ThingHandlerService>> getServices() {
147 logger.trace("MyBMWBridgeHandler.getServices");
148 return List.of(VehicleDiscovery.class);
151 public Optional<MyBMWProxy> getMyBmwProxy() {
152 logger.trace("MyBMWBridgeHandler.getProxy");
153 createMyBmwProxy(getConfigAs(MyBMWBridgeConfiguration.class), ENVIRONMENT);