[OpenUV] Correcting representation property (#8761)

* [OpenUV] Correcting representation property
Removing org.apache.commons.stringutils usage
* Corrected
* While on it, reviewed completely the binding.
* spotless applied
* Code review
* Code review enhancement

Signed-off-by: clinique <gael@lhopital.org>
This commit is contained in:
Gaël L'hopital 2020-10-29 22:49:16 +01:00 committed by GitHub
parent d1803dc723
commit 74ee8e76cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 236 additions and 233 deletions

View File

@ -28,13 +28,9 @@ import org.openhab.core.thing.ThingTypeUID;
*/
@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");

View File

@ -0,0 +1,39 @@
/**
* 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);
}
}

View File

@ -14,15 +14,15 @@ package org.openhab.binding.openuv.internal;
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;
@ -33,6 +33,11 @@ import org.osgi.service.component.annotations.Activate;
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.
@ -44,10 +49,21 @@ import org.osgi.service.component.annotations.Reference;
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
@ -59,20 +75,8 @@ public class OpenUVHandlerFactory extends BaseThingHandlerFactory {
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;
}
}

View File

@ -1,49 +0,0 @@
/**
* 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;
}
}
}

View File

@ -0,0 +1,26 @@
/**
* 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 = "";
}

View File

@ -0,0 +1,29 @@
/**
* 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 = "";
}

View File

@ -10,7 +10,9 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openuv.internal;
package org.openhab.binding.openuv.internal.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link SafeExposureConfiguration} is the class used to match the
@ -18,6 +20,7 @@ package org.openhab.binding.openuv.internal;
*
* @author Gaël L"hopital - Initial contribution
*/
@NonNullByDefault
public class SafeExposureConfiguration {
public int index = -1;
}

View File

@ -14,21 +14,16 @@ package org.openhab.binding.openuv.internal.discovery;
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;
@ -38,83 +33,54 @@ 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;
public OpenUVDiscoveryService() {
super(SUPPORTED_THING_TYPES_UIDS, DISCOVER_TIMEOUT_SECONDS);
}
@Override
protected void activate(@Nullable Map<String, @Nullable Object> configProperties) {
super.activate(configProperties);
public void setThingHandler(ThingHandler handler) {
if (handler instanceof OpenUVBridgeHandler) {
this.bridgeHandler = (OpenUVBridgeHandler) handler;
}
}
@Override
@Modified
protected void modified(@Nullable Map<String, @Nullable Object> configProperties) {
super.modified(configProperties);
public @Nullable ThingHandler getThingHandler() {
return bridgeHandler;
}
@Override
public void deactivate() {
super.deactivate();
}
@Override
protected void startScan() {
logger.debug("Starting OpenUV discovery scan");
PointType location = locationProvider.getLocation();
if (location == null) {
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");
return;
}
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 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());
}
@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");
}
} else {
logger.debug("OpenUV Bridge Handler is not set -> Will not provide any discovery results");
}
}
}

View File

@ -12,43 +12,38 @@
*/
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
@ -60,41 +55,45 @@ import com.google.gson.JsonDeserializer;
@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;
public OpenUVBridgeHandler(Bridge bridge) {
private final LocationProvider locationProvider;
private @Nullable ScheduledFuture<?> reconnectJob;
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) {
@ -106,62 +105,49 @@ public class OpenUVBridgeHandler extends BaseBridgeHandler {
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();
}
if (errorMessage.startsWith(ERROR_QUOTA_EXCEEDED)) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, errorMessage);
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);
logger.warn("Quota Exceeded, going OFFLINE for today, will retry at : {} ", tomorrowMidnight);
scheduler.schedule(this::initiateConnexion,
Duration.between(LocalDateTime.now(), tomorrowMidnight).toMinutes(), TimeUnit.MINUTES);
String message = "Quota Exceeded, going OFFLINE for today, will retry at : "
+ tomorrowMidnight.toString();
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, message);
} else if (errorMessage.startsWith(ERROR_WRONG_KEY)) {
logger.error("Error occured during API query : {}", errorMessage);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, errorMessage);
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;
}
@Override
public Collection<Class<? extends ThingHandlerService>> getServices() {
return Collections.singleton(OpenUVDiscoveryService.class);
}
public @Nullable PointType getLocation() {
return locationProvider.getLocation();
}
}

View File

@ -23,11 +23,13 @@ import java.util.concurrent.TimeUnit;
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;
@ -54,13 +56,11 @@ import org.slf4j.LoggerFactory;
*/
@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) {
@ -73,7 +73,7 @@ public class OpenUVReportHandler extends BaseThingHandler {
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 {
@ -94,7 +94,8 @@ public class OpenUVReportHandler extends BaseThingHandler {
* @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();
@ -114,22 +115,23 @@ public class OpenUVReportHandler extends BaseThingHandler {
* 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 -> {
@ -146,16 +148,17 @@ public class OpenUVReportHandler extends BaseThingHandler {
@Override
public void dispose() {
logger.debug("Disposing the OpenUV handler.");
if (refreshJob != null && !refreshJob.isCancelled()) {
refreshJob.cancel(true);
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")