*/
@NonNullByDefault
public class OpenUVBindingConstants {
- public static final String BASE_URL = "https://api.openuv.io/api/v1/uv";
public static final String BINDING_ID = "openuv";
public static final String LOCAL = "local";
- public static final String LOCATION = "location";
- public static final String APIKEY = "apikey";
-
// List of Bridge Type UIDs
public static final ThingTypeUID APIBRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, "openuvapi");
--- /dev/null
+/**
+ * Copyright (c) 2010-2020 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.openuv.internal;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * Will be thrown for cloud errors
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public class OpenUVException extends Exception {
+ private static final long serialVersionUID = -1411477662081482350L;
+ private static final String ERROR_QUOTA_EXCEEDED = "Daily API quota exceeded";
+ private static final String ERROR_WRONG_KEY = "User with API Key not found";
+
+ public OpenUVException(String message) {
+ super(message);
+ }
+
+ public boolean isApiKeyError() {
+ return this.getMessage().startsWith(ERROR_WRONG_KEY);
+ }
+
+ public boolean isQuotaError() {
+ return this.getMessage().startsWith(ERROR_QUOTA_EXCEEDED);
+ }
+}
import static org.openhab.binding.openuv.internal.OpenUVBindingConstants.*;
-import java.util.Hashtable;
+import java.time.ZonedDateTime;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.openuv.internal.discovery.OpenUVDiscoveryService;
import org.openhab.binding.openuv.internal.handler.OpenUVBridgeHandler;
import org.openhab.binding.openuv.internal.handler.OpenUVReportHandler;
-import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.i18n.LocationProvider;
+import org.openhab.core.i18n.TimeZoneProvider;
+import org.openhab.core.library.types.DecimalType;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonDeserializer;
+
/**
* The {@link OpenUVHandlerFactory} is responsible for creating things and thing
* handlers.
public class OpenUVHandlerFactory extends BaseThingHandlerFactory {
private final LocationProvider locationProvider;
+ private final Gson gson;
@Activate
- public OpenUVHandlerFactory(@Reference LocationProvider locationProvider) {
+ public OpenUVHandlerFactory(@Reference TimeZoneProvider timeZoneProvider,
+ @Reference LocationProvider locationProvider) {
this.locationProvider = locationProvider;
+ this.gson = new GsonBuilder()
+ .registerTypeAdapter(DecimalType.class,
+ (JsonDeserializer<DecimalType>) (json, type, jsonDeserializationContext) -> DecimalType
+ .valueOf(json.getAsJsonPrimitive().getAsString()))
+ .registerTypeAdapter(ZonedDateTime.class,
+ (JsonDeserializer<ZonedDateTime>) (json, type, jsonDeserializationContext) -> ZonedDateTime
+ .parse(json.getAsJsonPrimitive().getAsString())
+ .withZoneSameInstant(timeZoneProvider.getTimeZone()))
+ .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
}
@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
- if (APIBRIDGE_THING_TYPE.equals(thingTypeUID)) {
- OpenUVBridgeHandler handler = new OpenUVBridgeHandler((Bridge) thing);
- registerOpenUVDiscoveryService(handler);
- return handler;
- } else if (LOCATION_REPORT_THING_TYPE.equals(thingTypeUID)) {
- return new OpenUVReportHandler(thing);
- }
-
- return null;
- }
-
- private void registerOpenUVDiscoveryService(OpenUVBridgeHandler bridgeHandler) {
- OpenUVDiscoveryService discoveryService = new OpenUVDiscoveryService(bridgeHandler, locationProvider);
- bridgeHandler.getDiscoveryServiceRegs().put(bridgeHandler.getThing().getUID(),
- bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>()));
+ return APIBRIDGE_THING_TYPE.equals(thingTypeUID)
+ ? new OpenUVBridgeHandler((Bridge) thing, locationProvider, gson)
+ : LOCATION_REPORT_THING_TYPE.equals(thingTypeUID) ? new OpenUVReportHandler(thing) : null;
}
}
+++ /dev/null
-/**
- * Copyright (c) 2010-2020 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.openuv.internal;
-
-/**
- * The {@link ReportConfiguration} is the class used to match the
- * thing configuration.
- *
- * @author Gaël L"hopital - Initial contribution
- */
-public class ReportConfiguration {
- String[] elements = null;
-
- private String location;
- public Integer refresh;
-
- public String getLatitude() {
- return getElement(0);
- }
-
- public String getLongitude() {
- return getElement(1);
- }
-
- public String getAltitude() {
- return getElement(2);
- }
-
- private String getElement(int index) {
- if (elements == null) {
- elements = location.split(",");
- }
- if (index < elements.length) {
- return elements[index].trim();
- } else {
- return null;
- }
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2010-2020 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.openuv.internal;
-
-/**
- * The {@link SafeExposureConfiguration} is the class used to match the
- * SafeExposure channel configuration.
- *
- * @author Gaël L"hopital - Initial contribution
- */
-public class SafeExposureConfiguration {
- public int index = -1;
-}
--- /dev/null
+/**
+ * Copyright (c) 2010-2020 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.openuv.internal.config;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link BridgeConfiguration} is the class used to match the
+ * bridge configuration.
+ *
+ * @author Gaël L"hopital - Initial contribution
+ */
+@NonNullByDefault
+public class BridgeConfiguration {
+ public String apikey = "";
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2020 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.openuv.internal.config;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link ReportConfiguration} is the class used to match the
+ * thing configuration.
+ *
+ * @author Gaël L"hopital - Initial contribution
+ */
+@NonNullByDefault
+public class ReportConfiguration {
+ public static final String LOCATION = "location";
+
+ public int refresh = 10;
+ public String location = "";
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2020 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.openuv.internal.config;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link SafeExposureConfiguration} is the class used to match the
+ * SafeExposure channel configuration.
+ *
+ * @author Gaël L"hopital - Initial contribution
+ */
+@NonNullByDefault
+public class SafeExposureConfiguration {
+ public int index = -1;
+}
import static org.openhab.binding.openuv.internal.OpenUVBindingConstants.*;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.openuv.internal.config.ReportConfiguration;
import org.openhab.binding.openuv.internal.handler.OpenUVBridgeHandler;
import org.openhab.core.config.discovery.AbstractDiscoveryService;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
-import org.openhab.core.i18n.LocationProvider;
import org.openhab.core.library.types.PointType;
import org.openhab.core.thing.ThingUID;
-import org.osgi.service.component.annotations.Modified;
+import org.openhab.core.thing.binding.ThingHandler;
+import org.openhab.core.thing.binding.ThingHandlerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* @author Gaël L'hopital - Initial Contribution
*/
@NonNullByDefault
-public class OpenUVDiscoveryService extends AbstractDiscoveryService {
+public class OpenUVDiscoveryService extends AbstractDiscoveryService implements ThingHandlerService {
private final Logger logger = LoggerFactory.getLogger(OpenUVDiscoveryService.class);
- private static final int DISCOVER_TIMEOUT_SECONDS = 10;
- private static final int LOCATION_CHANGED_CHECK_INTERVAL = 60;
+ private static final int DISCOVER_TIMEOUT_SECONDS = 2;
- private final LocationProvider locationProvider;
- private final OpenUVBridgeHandler bridgeHandler;
- private @Nullable ScheduledFuture<?> discoveryJob;
- private @Nullable PointType previousLocation;
+ private @Nullable OpenUVBridgeHandler bridgeHandler;
/**
* Creates a OpenUVDiscoveryService with enabled autostart.
*/
- public OpenUVDiscoveryService(OpenUVBridgeHandler bridgeHandler, LocationProvider locationProvider) {
- super(SUPPORTED_THING_TYPES_UIDS, DISCOVER_TIMEOUT_SECONDS, true);
- this.locationProvider = locationProvider;
- this.bridgeHandler = bridgeHandler;
- }
-
- @Override
- protected void activate(@Nullable Map<String, @Nullable Object> configProperties) {
- super.activate(configProperties);
- }
-
- @Override
- @Modified
- protected void modified(@Nullable Map<String, @Nullable Object> configProperties) {
- super.modified(configProperties);
+ public OpenUVDiscoveryService() {
+ super(SUPPORTED_THING_TYPES_UIDS, DISCOVER_TIMEOUT_SECONDS);
}
@Override
- protected void startScan() {
- logger.debug("Starting OpenUV discovery scan");
- PointType location = locationProvider.getLocation();
- if (location == null) {
- logger.debug("LocationProvider.getLocation() is not set -> Will not provide any discovery results");
- return;
+ public void setThingHandler(ThingHandler handler) {
+ if (handler instanceof OpenUVBridgeHandler) {
+ this.bridgeHandler = (OpenUVBridgeHandler) handler;
}
- createResults(location);
}
@Override
- protected void startBackgroundDiscovery() {
- if (discoveryJob == null) {
- discoveryJob = scheduler.scheduleWithFixedDelay(() -> {
- PointType currentLocation = locationProvider.getLocation();
- if (currentLocation != null && !Objects.equals(currentLocation, previousLocation)) {
- logger.debug("Location has been changed from {} to {}: Creating new discovery results",
- previousLocation, currentLocation);
- createResults(currentLocation);
- previousLocation = currentLocation;
- }
- }, 0, LOCATION_CHANGED_CHECK_INTERVAL, TimeUnit.SECONDS);
- logger.debug("Scheduled OpenUV-changed job every {} seconds", LOCATION_CHANGED_CHECK_INTERVAL);
- }
+ public @Nullable ThingHandler getThingHandler() {
+ return bridgeHandler;
}
- public void createResults(PointType location) {
- ThingUID bridgeUID = bridgeHandler.getThing().getUID();
- ThingUID localOpenUVThing = new ThingUID(LOCATION_REPORT_THING_TYPE, bridgeUID, LOCAL);
- Map<String, Object> properties = new HashMap<>();
- properties.put(LOCATION, location.toString());
- thingDiscovered(DiscoveryResultBuilder.create(localOpenUVThing).withLabel("Local UV Information")
- .withProperties(properties).withRepresentationProperty(location.toString()).withBridge(bridgeUID)
- .build());
+ @Override
+ public void deactivate() {
+ super.deactivate();
}
- @SuppressWarnings("null")
@Override
- protected void stopBackgroundDiscovery() {
- logger.debug("Stopping OpenUV background discovery");
- if (discoveryJob != null && !discoveryJob.isCancelled()) {
- if (discoveryJob.cancel(true)) {
- discoveryJob = null;
- logger.debug("Stopped OpenUV background discovery");
+ protected void startScan() {
+ logger.debug("Starting OpenUV discovery scan");
+ OpenUVBridgeHandler bridge = bridgeHandler;
+ if (bridge != null) {
+ PointType location = bridge.getLocation();
+ if (location != null) {
+ ThingUID bridgeUID = bridge.getThing().getUID();
+ thingDiscovered(DiscoveryResultBuilder
+ .create(new ThingUID(LOCATION_REPORT_THING_TYPE, bridgeUID, LOCAL)).withLabel("Local UV Report")
+ .withProperty(ReportConfiguration.LOCATION, location.toString())
+ .withRepresentationProperty(ReportConfiguration.LOCATION).withBridge(bridgeUID).build());
+ } else {
+ logger.debug("LocationProvider.getLocation() is not set -> Will not provide any discovery results");
}
+ } else {
+ logger.debug("OpenUV Bridge Handler is not set -> Will not provide any discovery results");
}
}
}
*/
package org.openhab.binding.openuv.internal.handler;
-import static org.openhab.binding.openuv.internal.OpenUVBindingConstants.BASE_URL;
-
import java.io.IOException;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
-import java.time.ZonedDateTime;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Properties;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
-import org.apache.commons.lang.StringUtils;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.openuv.internal.OpenUVBindingConstants;
+import org.openhab.binding.openuv.internal.OpenUVException;
+import org.openhab.binding.openuv.internal.config.BridgeConfiguration;
+import org.openhab.binding.openuv.internal.discovery.OpenUVDiscoveryService;
import org.openhab.binding.openuv.internal.json.OpenUVResponse;
import org.openhab.binding.openuv.internal.json.OpenUVResult;
-import org.openhab.core.config.core.Configuration;
+import org.openhab.core.i18n.LocationProvider;
import org.openhab.core.io.net.http.HttpUtil;
-import org.openhab.core.library.types.DecimalType;
+import org.openhab.core.library.types.PointType;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
-import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.BaseBridgeHandler;
+import org.openhab.core.thing.binding.ThingHandlerService;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
-import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonDeserializer;
/**
* {@link OpenUVBridgeHandler} is the handler for OpenUV API and connects it
@NonNullByDefault
public class OpenUVBridgeHandler extends BaseBridgeHandler {
private final Logger logger = LoggerFactory.getLogger(OpenUVBridgeHandler.class);
- private static final String ERROR_QUOTA_EXCEEDED = "Daily API quota exceeded";
- private static final String ERROR_WRONG_KEY = "User with API Key not found";
- private static final int REQUEST_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(30);
+ private static final String QUERY_URL = "https://api.openuv.io/api/v1/uv?lat=%s&lng=%s&alt=%s";
- private final Gson gson = new GsonBuilder()
- .registerTypeAdapter(DecimalType.class,
- (JsonDeserializer<DecimalType>) (json, type, jsonDeserializationContext) -> DecimalType
- .valueOf(json.getAsJsonPrimitive().getAsString()))
- .registerTypeAdapter(ZonedDateTime.class,
- (JsonDeserializer<ZonedDateTime>) (json, type, jsonDeserializationContext) -> ZonedDateTime
- .parse(json.getAsJsonPrimitive().getAsString()))
- .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
+ private static final int REQUEST_TIMEOUT_MS = (int) TimeUnit.SECONDS.toMillis(30);
- private Map<ThingUID, @Nullable ServiceRegistration<?>> discoveryServiceRegs = new HashMap<>();
private final Properties header = new Properties();
+ private final Gson gson;
+
+ private final LocationProvider locationProvider;
+ private @Nullable ScheduledFuture<?> reconnectJob;
- public OpenUVBridgeHandler(Bridge bridge) {
+ public OpenUVBridgeHandler(Bridge bridge, LocationProvider locationProvider, Gson gson) {
super(bridge);
+ this.gson = gson;
+ this.locationProvider = locationProvider;
}
@Override
public void initialize() {
logger.debug("Initializing OpenUV API bridge handler.");
- Configuration config = getThing().getConfiguration();
- String apiKey = (String) config.get(OpenUVBindingConstants.APIKEY);
- if (StringUtils.trimToNull(apiKey) == null) {
+ BridgeConfiguration config = getConfigAs(BridgeConfiguration.class);
+ if (config.apikey.isEmpty()) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"Parameter 'apikey' must be configured.");
} else {
- header.put("x-access-token", apiKey);
+ header.put("x-access-token", config.apikey);
initiateConnexion();
}
}
+ @Override
+ public void dispose() {
+ ScheduledFuture<?> job = this.reconnectJob;
+ if (job != null && !job.isCancelled()) {
+ job.cancel(true);
+ }
+ reconnectJob = null;
+ }
+
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (command instanceof RefreshType) {
private void initiateConnexion() {
// Check if the provided api key is valid for use with the OpenUV service
- getUVData("0", "0", null);
+ getUVData("0", "0", "0");
}
- public Map<ThingUID, @Nullable ServiceRegistration<?>> getDiscoveryServiceRegs() {
- return discoveryServiceRegs;
- }
-
- public void setDiscoveryServiceRegs(Map<ThingUID, @Nullable ServiceRegistration<?>> discoveryServiceRegs) {
- this.discoveryServiceRegs = discoveryServiceRegs;
- }
-
- @Override
- public void handleRemoval() {
- // removes the old registration service associated to the bridge, if existing
- ServiceRegistration<?> dis = getDiscoveryServiceRegs().get(getThing().getUID());
- if (dis != null) {
- dis.unregister();
- }
- super.handleRemoval();
- }
-
- public @Nullable OpenUVResult getUVData(String latitude, String longitude, @Nullable String altitude) {
- StringBuilder urlBuilder = new StringBuilder(BASE_URL).append("?lat=").append(latitude).append("&lng=")
- .append(longitude);
-
- if (altitude != null) {
- urlBuilder.append("&alt=").append(altitude);
- }
- String errorMessage = null;
+ public @Nullable OpenUVResult getUVData(String latitude, String longitude, String altitude) {
try {
- String jsonData = HttpUtil.executeUrl("GET", urlBuilder.toString(), header, null, null, REQUEST_TIMEOUT);
+ String jsonData = HttpUtil.executeUrl("GET", String.format(QUERY_URL, latitude, longitude, altitude),
+ header, null, null, REQUEST_TIMEOUT_MS);
OpenUVResponse uvResponse = gson.fromJson(jsonData, OpenUVResponse.class);
if (uvResponse.getError() == null) {
updateStatus(ThingStatus.ONLINE);
return uvResponse.getResult();
} else {
- errorMessage = uvResponse.getError();
+ throw new OpenUVException(uvResponse.getError());
}
} catch (IOException e) {
- errorMessage = e.getMessage();
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
+ } catch (OpenUVException e) {
+ if (e.isQuotaError()) {
+ LocalDate today = LocalDate.now();
+ LocalDate tomorrow = today.plusDays(1);
+ LocalDateTime tomorrowMidnight = tomorrow.atStartOfDay().plusMinutes(2);
+
+ String message = "Quota Exceeded, going OFFLINE for today, will retry at : "
+ + tomorrowMidnight.toString();
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, message);
+
+ reconnectJob = scheduler.schedule(this::initiateConnexion,
+ Duration.between(LocalDateTime.now(), tomorrowMidnight).toMinutes(), TimeUnit.MINUTES);
+ } else if (e.isApiKeyError()) {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
+ } else {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, e.getMessage());
+ }
}
+ return null;
+ }
- if (errorMessage.startsWith(ERROR_QUOTA_EXCEEDED)) {
- updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, errorMessage);
- LocalDate today = LocalDate.now();
- LocalDate tomorrow = today.plusDays(1);
- LocalDateTime tomorrowMidnight = tomorrow.atStartOfDay().plusMinutes(2);
-
- logger.warn("Quota Exceeded, going OFFLINE for today, will retry at : {} ", tomorrowMidnight);
- scheduler.schedule(this::initiateConnexion,
- Duration.between(LocalDateTime.now(), tomorrowMidnight).toMinutes(), TimeUnit.MINUTES);
+ @Override
+ public Collection<Class<? extends ThingHandlerService>> getServices() {
+ return Collections.singleton(OpenUVDiscoveryService.class);
+ }
- } else if (errorMessage.startsWith(ERROR_WRONG_KEY)) {
- logger.error("Error occured during API query : {}", errorMessage);
- updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, errorMessage);
- }
- return null;
+ public @Nullable PointType getLocation() {
+ return locationProvider.getLocation();
}
}
import javax.measure.quantity.Angle;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.openuv.internal.ReportConfiguration;
-import org.openhab.binding.openuv.internal.SafeExposureConfiguration;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.openuv.internal.config.ReportConfiguration;
+import org.openhab.binding.openuv.internal.config.SafeExposureConfiguration;
import org.openhab.binding.openuv.internal.json.OpenUVResult;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.HSBType;
+import org.openhab.core.library.types.PointType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.SmartHomeUnits;
import org.openhab.core.thing.Bridge;
*/
@NonNullByDefault
public class OpenUVReportHandler extends BaseThingHandler {
- private static final int DEFAULT_REFRESH_PERIOD = 30;
-
private final Logger logger = LoggerFactory.getLogger(OpenUVReportHandler.class);
private @NonNullByDefault({}) OpenUVBridgeHandler bridgeHandler;
- private @NonNullByDefault({}) ScheduledFuture<?> refreshJob;
- private @NonNullByDefault({}) ScheduledFuture<?> uvMaxJob;
+ private @Nullable ScheduledFuture<?> refreshJob;
+ private @Nullable ScheduledFuture<?> uvMaxJob;
private boolean suspendUpdates = false;
public OpenUVReportHandler(Thing thing) {
ReportConfiguration config = getConfigAs(ReportConfiguration.class);
- if (config.refresh != null && config.refresh < 3) {
+ if (config.refresh < 3) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"Parameter 'refresh' must be higher than 3 minutes to stay in free API plan");
} else {
* @param openUVData
*/
private void scheduleUVMaxEvent(OpenUVResult openUVData) {
- if ((uvMaxJob == null || uvMaxJob.isCancelled())) {
+ ScheduledFuture<?> job = this.uvMaxJob;
+ if ((job == null || job.isCancelled())) {
State uvMaxTime = openUVData.getUVMaxTime();
if (uvMaxTime != UnDefType.NULL) {
ZonedDateTime uvMaxZdt = ((DateTimeType) uvMaxTime).getZonedDateTime();
* Start the job refreshing the data
*/
private void startAutomaticRefresh() {
- if (refreshJob == null || refreshJob.isCancelled()) {
+ ScheduledFuture<?> job = this.refreshJob;
+ if (job == null || job.isCancelled()) {
ReportConfiguration config = getConfigAs(ReportConfiguration.class);
- int delay = (config.refresh != null) ? config.refresh.intValue() : DEFAULT_REFRESH_PERIOD;
refreshJob = scheduler.scheduleWithFixedDelay(() -> {
if (!suspendUpdates) {
updateChannels(config);
}
- }, 0, delay, TimeUnit.MINUTES);
+ }, 0, config.refresh, TimeUnit.MINUTES);
}
}
private void updateChannels(ReportConfiguration config) {
ThingStatusInfo bridgeStatusInfo = bridgeHandler.getThing().getStatusInfo();
if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
- OpenUVResult openUVData = bridgeHandler.getUVData(config.getLatitude(), config.getLongitude(),
- config.getAltitude());
+ PointType location = new PointType(config.location);
+ OpenUVResult openUVData = bridgeHandler.getUVData(location.getLatitude().toString(),
+ location.getLongitude().toString(), location.getAltitude().toString());
if (openUVData != null) {
scheduleUVMaxEvent(openUVData);
getThing().getChannels().forEach(channel -> {
@Override
public void dispose() {
logger.debug("Disposing the OpenUV handler.");
-
- if (refreshJob != null && !refreshJob.isCancelled()) {
- refreshJob.cancel(true);
- refreshJob = null;
+ ScheduledFuture<?> refresh = this.refreshJob;
+ if (refresh != null && !refresh.isCancelled()) {
+ refresh.cancel(true);
}
+ refreshJob = null;
- if (uvMaxJob != null && !uvMaxJob.isCancelled()) {
- uvMaxJob.cancel(true);
- uvMaxJob = null;
+ ScheduledFuture<?> uxMax = this.uvMaxJob;
+ if (uxMax != null && !uxMax.isCancelled()) {
+ uxMax.cancel(true);
}
+ uvMaxJob = null;
}
@SuppressWarnings("unchecked")