mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +01:00
[KVV] Replace underlying API (#13186)
* [KVV] Replace underlying API The underlying API does no longer work so it is replace. An API key is no longer necessary. Users need to replace the `stopId` in there station thing configuration. See README.md for details. Signed-off-by: Maximilian Hess <mail@ne0h.de> Co-authored-by: Laurent Garnier <lg.hc@free.fr>
This commit is contained in:
parent
79309cb746
commit
8ab5f629c3
@ -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" ]
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -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<Departure> departures;
|
||||
|
||||
public DepartureResult() {
|
||||
this.stopName = "";
|
||||
this.departures = new ArrayList<Departure>();
|
||||
}
|
||||
@SerializedName(value = "departureList")
|
||||
public List<Departure> departures = new ArrayList<Departure>();
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public class KVVBindingConstants {
|
||||
public static final List<ThingTypeUID> 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;
|
||||
|
@ -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 = "";
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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<Channel> channels = new ArrayList<Channel>();
|
||||
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);
|
||||
|
@ -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.
|
||||
|
@ -8,17 +8,15 @@
|
||||
<description>The KVV bridge connects to the KVV API.</description>
|
||||
|
||||
<config-description>
|
||||
<parameter name="maxTrains" type="integer" required="true" min="0" max="127">
|
||||
<parameter name="maxTrains" type="integer" min="1" max="127">
|
||||
<label>Maximum Trains Listed</label>
|
||||
<description>Maximum number of trains listed.</description>
|
||||
<default>1</default>
|
||||
</parameter>
|
||||
<parameter name="updateInterval" type="integer" required="true" min="1">
|
||||
<parameter name="updateInterval" type="integer" min="1">
|
||||
<label>Update Interval</label>
|
||||
<description>Update interval in seconds.</description>
|
||||
</parameter>
|
||||
<parameter name="apiKey" type="text" required="true">
|
||||
<label>API key</label>
|
||||
<description>API key of the KVV API</description>
|
||||
<default>10</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
|
Loading…
Reference in New Issue
Block a user