diff --git a/bundles/org.openhab.binding.kvv/README.md b/bundles/org.openhab.binding.kvv/README.md index 4084761a56d..612d0528573 100644 --- a/bundles/org.openhab.binding.kvv/README.md +++ b/bundles/org.openhab.binding.kvv/README.md @@ -13,14 +13,38 @@ This includes the name of the train, the final destination and the estimated tim Since every stop is represented by a KVV-provided id, this id has to be figured out via an API call. -### Example Call for Stop 'Karlsruhe Volkswohnung' +### Example Call for Stop 'Gottesauer Platz/BGV' ```bash -# Request -curl https://live.kvv.de/webapp/stops/byname/Volkswohnung\?key\=[APIKEY] +export QUERY="gottesauer" +curl https://www.kvv.de/tunnelEfaDirect.php?action=XSLT_STOPFINDER_REQUEST&name_sf=${QUERY}&outputFormat=JSON&type_sf=any +``` -# Response -{"stops":[{"id":"de:8212:72","name":"Karlsruhe Volkswohnung","lat":49.00381654,"lon":8.40393026}]} +The exact `id` may be extracted from the JSON-encoded reponse. E.g. + +```json +"points": [ +{ + "usage": "sf", + "type": "any", + "name": "Karlsruhe, Gottesauer Platz/BGV", + "stateless": "7000006", + "anyType": "stop", + "sort": "2", + "quality": "949", + "best": "0", + "object": "Gottesauer Platz/BGV", + "mainLoc": "Karlsruhe", + "modes": "1,4,5", + "ref": { + "id": "7000006", + "gid": "de:08212:6", + "omc": "8212000", + "placeID": "15", + "place": "Karlsruhe", + "coords": "937855.00000,5723868.00000" + } +} ``` ## Channel Configuration @@ -40,8 +64,8 @@ Each set consists of the following three channels: ### Things ```things -Bridge kvv:bridge:1 "Bridge" @ "Wohnzimmer" [ maxTrains="3", updateInterval="10", apiKey="" ] { - stop gottesauerplatz "Gottesauer Platz/BGV" [ stopId="de:8212:6" ] +Bridge kvv:bridge:1 "Bridge" @ "Wohnzimmer" [ maxTrains="3", updateInterval="10" ] { + stop gottesauerplatz "Gottesauer Platz/BGV" [ stopId="7000006" ] } ``` diff --git a/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/DepartureResult.java b/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/DepartureResult.java index ddaab780cc3..75243d854b7 100644 --- a/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/DepartureResult.java +++ b/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/DepartureResult.java @@ -17,8 +17,10 @@ import java.util.List; import org.eclipse.jdt.annotation.NonNullByDefault; +import com.google.gson.annotations.SerializedName; + /** - * Represents the result of a call to the KVV api to fetch the next departures at a specific stop. + * Represents the result of a call to the KVV API to fetch the next departures at a specific stop. * * @author Maximilian Hess - Initial contribution * @@ -26,18 +28,12 @@ import org.eclipse.jdt.annotation.NonNullByDefault; @NonNullByDefault public class DepartureResult { - public String stopName; - - public List departures; - - public DepartureResult() { - this.stopName = ""; - this.departures = new ArrayList(); - } + @SerializedName(value = "departureList") + public List departures = new ArrayList(); @Override public String toString() { - return "DepartureResult [stopName=" + stopName + ", departures=" + departures + "]"; + return "DepartureResult [departures=" + departures + "]"; } /** @@ -49,28 +45,29 @@ public class DepartureResult { @NonNullByDefault public static class Departure { - public String route = ""; + @SerializedName(value = "servingLine") + public Route route = new Route(); - public String destination = ""; - - public String direction = ""; - - public String time = ""; - - public String vehicleType = ""; - - public boolean lowfloor; - - public boolean realtime; - - public int traction; - - public String stopPosition = ""; + @SerializedName(value = "countdown") + public String eta = ""; @Override public String toString() { - final String timePrefix = (this.time.endsWith("min")) ? " in " : " at "; - return "Route " + this.route + timePrefix + this.time + " heading to " + this.destination; + return "Departure [" + route + ", eta=" + eta + "]"; + } + } + + @NonNullByDefault + public static class Route { + + @SerializedName(value = "number") + public String name = ""; + + public String direction = ""; + + @Override + public String toString() { + return "name=" + name + ", direction=" + direction; } } } diff --git a/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/KVVBindingConstants.java b/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/KVVBindingConstants.java index ad7885c773c..b20f27b4741 100644 --- a/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/KVVBindingConstants.java +++ b/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/KVVBindingConstants.java @@ -39,7 +39,7 @@ public class KVVBindingConstants { public static final List SUPPORTED_THING_TYPES = Arrays.asList(THING_TYPE_BRIDGE, THING_TYPE_STOP); /** URL of the KVV API */ - public static final String API_URL = "https://live.kvv.de/webapp"; + public static final String API_FORMAT = "https://projekte.kvv-efa.de/sl3-alone/XSLT_DM_REQUEST?outputFormat=JSON&coordOutputFormat=WGS84%%5Bdd.ddddd%%5D&depType=stopEvents&locationServerActive=1&mode=direct&name_dm=%s&type_dm=stop&useOnlyStops=1&useRealtime=1&limit=%d"; /** timeout for API calls in seconds */ public static final int TIMEOUT_IN_SECONDS = 10; diff --git a/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/KVVBridgeConfig.java b/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/KVVBridgeConfig.java index 4afb93f2491..3bed729c65a 100644 --- a/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/KVVBridgeConfig.java +++ b/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/KVVBridgeConfig.java @@ -23,18 +23,14 @@ import org.eclipse.jdt.annotation.NonNullByDefault; @NonNullByDefault public class KVVBridgeConfig { - /** maximum number of traines being queried */ + /** maximum number of trains being queried */ public int maxTrains; /** the update interval in seconds */ public int updateInterval; - /** API key of the KVV API */ - public String apiKey; - public KVVBridgeConfig() { - this.maxTrains = 0; + this.maxTrains = 1; this.updateInterval = 10; - this.apiKey = ""; } } diff --git a/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/KVVBridgeHandler.java b/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/KVVBridgeHandler.java index 84e572b45db..878478acdd1 100644 --- a/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/KVVBridgeHandler.java +++ b/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/KVVBridgeHandler.java @@ -61,15 +61,7 @@ public class KVVBridgeHandler extends BaseBridgeHandler { @Override public void initialize() { - updateStatus(ThingStatus.UNKNOWN); - this.config = getConfigAs(KVVBridgeConfig.class); - if (this.config.apiKey.isEmpty()) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Failed to get bridge configuration"); - return; - } - updateStatus(ThingStatus.ONLINE); } @@ -91,8 +83,7 @@ public class KVVBridgeHandler extends BaseBridgeHandler { return cr; } - final String url = KVVBindingConstants.API_URL + "/departures/bystop/" + stopConfig.stopId + "?key=" - + config.apiKey + "&maxInfos=" + config.maxTrains; + final String url = String.format(KVVBindingConstants.API_FORMAT, stopConfig.stopId, config.maxTrains); String data; try { diff --git a/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/KVVStopHandler.java b/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/KVVStopHandler.java index d86e488bc71..4eb1a5f50cb 100644 --- a/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/KVVStopHandler.java +++ b/bundles/org.openhab.binding.kvv/src/main/java/org/openhab/binding/kvv/internal/KVVStopHandler.java @@ -32,6 +32,8 @@ import org.openhab.core.thing.binding.builder.ChannelBuilder; import org.openhab.core.thing.type.ChannelTypeUID; import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * KVVStopHandler represents a stop and holds information about the trains @@ -42,6 +44,8 @@ import org.openhab.core.types.RefreshType; @NonNullByDefault public class KVVStopHandler extends BaseThingHandler { + private final Logger logger = LoggerFactory.getLogger(KVVStopHandler.class); + @Nullable private ScheduledFuture pollingJob; @@ -91,18 +95,25 @@ public class KVVStopHandler extends BaseThingHandler { final ChannelTypeUID destType = new ChannelTypeUID(this.thing.getBridgeUID().getBindingId(), "destination"); final ChannelTypeUID etaType = new ChannelTypeUID(this.thing.getBridgeUID().getBindingId(), "eta"); + if (bridgeHandler.getBridgeConfig().maxTrains == 0) { + logger.warn("maxTrains is '0', not creating any channels"); + } + final List channels = new ArrayList(); for (int i = 0; i < bridgeHandler.getBridgeConfig().maxTrains; i++) { - channels.add(ChannelBuilder.create(new ChannelUID(this.thing.getUID(), "train" + i + "-name"), "String") - .withType(nameType).build()); - channels.add(ChannelBuilder - .create(new ChannelUID(this.thing.getUID(), "train" + i + "-destination"), "String") - .withType(destType).build()); - channels.add(ChannelBuilder.create(new ChannelUID(this.thing.getUID(), "train" + i + "-eta"), "String") - .withType(etaType).build()); + ChannelUID c = new ChannelUID(this.thing.getUID(), "train" + i + "-name"); + channels.add(ChannelBuilder.create(c, "String").withType(nameType).build()); + logger.debug("Created channel {}", c); + + c = new ChannelUID(this.thing.getUID(), "train" + i + "-destination"); + channels.add(ChannelBuilder.create(c, "String").withType(destType).build()); + logger.debug("Created channel {}", c); + + c = new ChannelUID(this.thing.getUID(), "train" + i + "-eta"); + channels.add(ChannelBuilder.create(c, "String").withType(etaType).build()); + logger.debug("Created channel {}", c); } this.updateThing(this.editThing().withChannels(channels).build()); - } this.pollingJob = this.scheduler.scheduleWithFixedDelay(new UpdateTask(bridgeHandler, this.config), 0, @@ -126,16 +137,19 @@ public class KVVStopHandler extends BaseThingHandler { private synchronized void setDepartures(final DepartureResult departures, final int maxTrains) { int i = 0; for (; i < departures.departures.size(); i++) { + final DepartureResult.Departure departure = departures.departures.get(i); + this.updateState(new ChannelUID(this.thing.getUID(), "train" + i + "-name"), - new StringType(departures.departures.get(i).route)); + new StringType(departure.route.name)); this.updateState(new ChannelUID(this.thing.getUID(), "train" + i + "-destination"), - new StringType(departures.departures.get(i).destination)); - String eta = departures.departures.get(i).time; - if (eta.equals("0")) { + new StringType(departure.route.direction)); + String eta = departure.eta; + if ("0".equals(eta)) { eta += " min"; } this.updateState(new ChannelUID(this.thing.getUID(), "train" + i + "-eta"), new StringType(eta)); } + for (; i < maxTrains; i++) { this.updateState(new ChannelUID(this.thing.getUID(), "train" + i + "-name"), StringType.EMPTY); this.updateState(new ChannelUID(this.thing.getUID(), "train" + i + "-destination"), StringType.EMPTY); diff --git a/bundles/org.openhab.binding.kvv/src/main/resources/OH-INF/i18n/kvv.properties b/bundles/org.openhab.binding.kvv/src/main/resources/OH-INF/i18n/kvv.properties index 524ec04d876..9f49f6060e9 100644 --- a/bundles/org.openhab.binding.kvv/src/main/resources/OH-INF/i18n/kvv.properties +++ b/bundles/org.openhab.binding.kvv/src/main/resources/OH-INF/i18n/kvv.properties @@ -12,9 +12,7 @@ thing-type.kvv.stop.description = Train stop for KVV Binding. # thing types config -thing-type.config.kvv.bridge.apiKey.label = API key -thing-type.config.kvv.bridge.apiKey.description = API key of the KVV API -thing-type.config.kvv.bridge.maxTrains.label = Maximum Trains Listed +thing-type.config.kvv.bridge.maxTrains.label = Maximum Trains listed thing-type.config.kvv.bridge.maxTrains.description = Maximum number of trains listed. thing-type.config.kvv.bridge.updateInterval.label = Update Interval thing-type.config.kvv.bridge.updateInterval.description = Update interval in seconds. diff --git a/bundles/org.openhab.binding.kvv/src/main/resources/OH-INF/thing/bridge.xml b/bundles/org.openhab.binding.kvv/src/main/resources/OH-INF/thing/bridge.xml index 371ccf0bd96..ea0abae9cea 100644 --- a/bundles/org.openhab.binding.kvv/src/main/resources/OH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.kvv/src/main/resources/OH-INF/thing/bridge.xml @@ -8,17 +8,15 @@ The KVV bridge connects to the KVV API. - + Maximum number of trains listed. + 1 - + Update interval in seconds. - - - - API key of the KVV API + 10