mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[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:
parent
d1803dc723
commit
74ee8e76cf
@ -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");
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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 = "";
|
||||
}
|
@ -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 = "";
|
||||
}
|
@ -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;
|
||||
}
|
@ -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) {
|
||||
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");
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
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);
|
||||
|
||||
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);
|
||||
String message = "Quota Exceeded, going OFFLINE for today, will retry at : "
|
||||
+ tomorrowMidnight.toString();
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, message);
|
||||
|
||||
logger.warn("Quota Exceeded, going OFFLINE for today, will retry at : {} ", tomorrowMidnight);
|
||||
scheduler.schedule(this::initiateConnexion,
|
||||
Duration.between(LocalDateTime.now(), tomorrowMidnight).toMinutes(), TimeUnit.MINUTES);
|
||||
|
||||
} 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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
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")
|
||||
|
Loading…
Reference in New Issue
Block a user