mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +01:00
[deutschebahn] DB API Marketplace adjustments (#12786)
* Changes API URL and authentication Headers for DB API Marketplace. * Fixed some typos and code style findings. Signed-off-by: Sönke Küper <soenkekueper@gmx.de>
This commit is contained in:
parent
a30bb59400
commit
76001902a3
@ -14,14 +14,18 @@ The information are requested from the timetable api of Deutsche Bahn developer
|
||||
|
||||
To configure a timetable you first need to register at Deutsche Bahn developer portal and register for timetable API to get an access key.
|
||||
|
||||
1. Go to [Deutsche Bahn Developer](https://developer.deutschebahn.com)
|
||||
1. Go to [DB API Marketplace](https://developers.deutschebahn.com/)
|
||||
2. Register new account or login with an existing one
|
||||
3. If no application is configured yet (check Tab "Meine Anwendungen") create a new application. Only the name is required, any other fields can be left blank.
|
||||
4. Go to APIs - Timetables v1 (may be displayed on second page)
|
||||
5. Choose your previously created application and hit "Abonnieren"
|
||||
6. In confirmation-dialog choose "Wechsel zu meine Abonnements"
|
||||
7. Create an access key for the production environment by hitting "Schlüssel Erstellen"
|
||||
8. Copy the "Zugangstoken". This is required to access the api from openHAB.
|
||||
3. If no application is configured yet (check Tab "Anwendungen" at top) create a new application. Only the name is required, for example openHAB, any other fields can be left blank.
|
||||
4. Remember the shown **Client ID** and **Client Secret**.
|
||||
5. Go to **Katalog** and search for **Timetables** api.
|
||||
6. Within **Zugehörige APIs** select the Timetables api.
|
||||
7. Select **Abonnieren** at top left of the page.
|
||||
8. Select the Nutzungsplan **Free** by clicking **Abonnieren**.
|
||||
9. Select the previously created application.
|
||||
10. Click **Next**.
|
||||
11. Click **Fertig**.
|
||||
12. Now you have successfully registered the api within an application. The **Client ID** and **Client Secret** can now be used during bridge configuration.
|
||||
|
||||
### Determine the EVA-No of your station
|
||||
|
||||
@ -31,13 +35,14 @@ You can look up the number within the csv file available at [Haltestellendaten](
|
||||
### Configure timetable bridge
|
||||
|
||||
With access key for developer portal and eva no. of your station you're ready to configure a timetable (bridge) for this station.
|
||||
In addition you can configure if only arrivals, only departures or all trains should be contained within the timetable.
|
||||
In addition, you can configure if only arrivals, only departures or all trains should be contained within the timetable.
|
||||
|
||||
**timetable** parameters:
|
||||
|
||||
| Property | Default | Required | Description |
|
||||
|-|-|-|-|
|
||||
| `accessToken` | | Yes | The access token for the timetable api within the developer portal of Deutsche Bahn. |
|
||||
| `clientId` | | Yes | The Client ID for the application with registered timetable api within the DB API Marketplace. |
|
||||
| `clientSecret` | | Yes | The Client Secret (API Key) for the application with registered timetable api within the DB API Marketplace. |
|
||||
| `evaNo` | | Yes | The eva nr. of the train station for which the timetable will be requested.|
|
||||
| `trainFilter` | | Yes | Selects the trains that will be displayed in the timetable. Either only arrivals, only departures or all trains can be displayed. |
|
||||
| `additionalFilter` | | No | Specifies additional filters for trains, that should be displayed within the timetable. |
|
||||
@ -48,7 +53,7 @@ and only trains that matches the given filter will be contained within the timet
|
||||
|
||||
To specify an advanced filter you can
|
||||
|
||||
- specify a filter for the value of a given channel. Therefore you must specify the channel name (with channel group) and specify a compare value like this:
|
||||
- specify a filter for the value of a given channel. Therefore, you must specify the channel name (with channel group) and specify a compare value like this:
|
||||
`departure#line="RE60"` this will select all trains with line RE60
|
||||
- use regular expressions for expected channel values, for example: `departure#line="RE.*"`, this will match all lines starting with "RE".
|
||||
- combine multiple statements as "and" conjunction by using `&`. If used, both parts must match, for example: `departure#line="RE60" & trip#category="WFB"`
|
||||
@ -82,10 +87,10 @@ train things, the channels of these trains will be undefined.
|
||||
## Channels
|
||||
|
||||
Each train has a set of channels, that provides access to any information served by the timetable API. A detailed description of the values and their meaning can be found within
|
||||
the [Timetables V1 API Description](https://developer.deutschebahn.com/store/apis/info?name=Timetables&version=v1&provider=DBOpenData&).
|
||||
the [Timetables V1 API Description](https://developers.deutschebahn.com/db-api-marketplace/apis/product/timetables).
|
||||
The information are grouped into three channel-groups:
|
||||
The first channel group (trip) contains all information for the trip of the train, for example the category (like ICE, RE, S).
|
||||
The second and third channel group contains information about the the arrival and the departure of the train at the given station.
|
||||
The second and third channel group contains information about the arrival and the departure of the train at the given station.
|
||||
Both of the groups may provide an 'UNDEF' channel value, when the train does not arrive / depart at this station
|
||||
(due it starts or ends at the given station). If you have configured your timetable to contain only departures (with property trainFilter) the departure channel values will always be defined
|
||||
and if you have selected only arrivals the arrival channel values will always be defined.
|
||||
|
@ -32,9 +32,14 @@ import org.openhab.binding.deutschebahn.internal.filter.TimetableStopPredicate;
|
||||
public class DeutscheBahnTimetableConfiguration {
|
||||
|
||||
/**
|
||||
* Access-Token.
|
||||
* Client-ID for DB-API Application
|
||||
*/
|
||||
public String accessToken = "";
|
||||
public String clientId = "";
|
||||
|
||||
/**
|
||||
* Client-Secret for DB-API Application
|
||||
*/
|
||||
public String clientSecret = "";
|
||||
|
||||
/**
|
||||
* evaNo of the station to be queried.
|
||||
|
@ -13,7 +13,6 @@
|
||||
package org.openhab.binding.deutschebahn.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
@ -53,7 +52,6 @@ import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* The {@link DeutscheBahnTimetableHandler} is responsible for handling commands, which are
|
||||
@ -116,7 +114,7 @@ public class DeutscheBahnTimetableHandler extends BaseBridgeHandler {
|
||||
private final ScheduledExecutorService executorService;
|
||||
|
||||
/**
|
||||
* Creates an new {@link DeutscheBahnTimetableHandler}.
|
||||
* Creates a new {@link DeutscheBahnTimetableHandler}.
|
||||
*/
|
||||
public DeutscheBahnTimetableHandler( //
|
||||
final Bridge bridge, //
|
||||
@ -152,7 +150,11 @@ public class DeutscheBahnTimetableHandler extends BaseBridgeHandler {
|
||||
final DeutscheBahnTimetableConfiguration config = this.getConfigAs(DeutscheBahnTimetableConfiguration.class);
|
||||
|
||||
try {
|
||||
final TimetablesV1Api api = this.timetablesV1ApiFactory.create(config.accessToken, HttpUtil::executeUrl);
|
||||
final TimetablesV1Api api = this.timetablesV1ApiFactory.create( //
|
||||
config.clientId, //
|
||||
config.clientSecret, //
|
||||
HttpUtil::executeUrl //
|
||||
);
|
||||
|
||||
final TimetableStopFilter stopFilter = config.getTrainFilterFilter();
|
||||
final TimetableStopPredicate additionalFilter = config.getAdditionalFilter();
|
||||
@ -183,7 +185,7 @@ public class DeutscheBahnTimetableHandler extends BaseBridgeHandler {
|
||||
});
|
||||
} catch (FilterScannerException | FilterParserException e) {
|
||||
this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
|
||||
} catch (JAXBException | SAXException | URISyntaxException e) {
|
||||
} catch (JAXBException e) {
|
||||
this.logger.error("Error initializing api", e);
|
||||
this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
@ -195,7 +197,7 @@ public class DeutscheBahnTimetableHandler extends BaseBridgeHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules an job that updates the timetable every 30 seconds.
|
||||
* Schedules a job that updates the timetable every 30 seconds.
|
||||
*/
|
||||
private void restartJob() {
|
||||
this.logger.debug("Restarting jobs for bridge {}", this.getThing().getUID());
|
||||
@ -298,7 +300,7 @@ public class DeutscheBahnTimetableHandler extends BaseBridgeHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an map containing the things grouped by timetable stop position.
|
||||
* Returns a map containing the things grouped by timetable stop position.
|
||||
*/
|
||||
private GroupedThings groupThingsPerPosition() {
|
||||
final GroupedThings groupedThings = new GroupedThings();
|
||||
|
@ -52,7 +52,6 @@ public class DeutscheBahnTrainHandler extends BaseThingHandler {
|
||||
* Creates an new ChannelWithConfig.
|
||||
*
|
||||
* @param channelUid The UID of the channel
|
||||
* @param configuration Configuration for the given channel.
|
||||
* @param attributeSelection The attribute that provides the state that will be displayed.
|
||||
*/
|
||||
public ChannelWithConfig( //
|
||||
@ -166,8 +165,7 @@ public class DeutscheBahnTrainHandler extends BaseThingHandler {
|
||||
final String channelId = channelUid.getId();
|
||||
int hashIndex = channelId.indexOf("#");
|
||||
assert hashIndex > 0;
|
||||
final String attributeName = channelId.substring(hashIndex + 1);
|
||||
return attributeName;
|
||||
return channelId.substring(hashIndex + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,7 +41,7 @@ import org.openhab.core.types.State;
|
||||
*
|
||||
* chapter "1.2.11 Event" in Technical Interface Description for external Developers
|
||||
*
|
||||
* @see https://developer.deutschebahn.com/store/apis/info?name=Timetables&version=v1&provider=DBOpenData&#tab1
|
||||
* @see <a href="https://developers.deutschebahn.com/db-api-marketplace/apis/product/timetables">DB API Marketplace</a>
|
||||
*
|
||||
* @author Sönke Küper - initial contribution
|
||||
*
|
||||
@ -370,7 +370,9 @@ public final class EventAttribute<VALUE_TYPE, STATE_TYPE extends State>
|
||||
if (value == null) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
return Collections.singletonList(DATETIME_FORMAT.format(value));
|
||||
synchronized (DATETIME_FORMAT) {
|
||||
return Collections.singletonList(DATETIME_FORMAT.format(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,99 +22,99 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
*
|
||||
* chapter "2 List of all codes" in Technical Interface Description for external Developers
|
||||
*
|
||||
* @see https://developer.deutschebahn.com/store/apis/info?name=Timetables&version=v1&provider=DBOpenData&#tab1
|
||||
* @see <a href="https://developers.deutschebahn.com/db-api-marketplace/apis/product/timetables">DB API Marketplace</a>
|
||||
*
|
||||
* @author Sönke Küper - initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class MessageCodes {
|
||||
|
||||
private static Map<Integer, String> codes = new HashMap<>();
|
||||
private static final Map<Integer, String> CODES = new HashMap<>();
|
||||
static {
|
||||
codes.put(0, "keine Verspätungsbegründung");
|
||||
codes.put(2, "Polizeiliche Ermittlung");
|
||||
codes.put(3, "Feuerwehreinsatz an der Strecke");
|
||||
codes.put(4, "kurzfristiger Personalausfall");
|
||||
codes.put(5, "ärztliche Versorgung eines Fahrgastes");
|
||||
codes.put(6, "Betätigen der Notbremse");
|
||||
codes.put(7, "Personen im Gleis");
|
||||
codes.put(8, "Notarzteinsatz am Gleis");
|
||||
codes.put(9, "Streikauswirkungen");
|
||||
codes.put(10, "Tiere im Gleis");
|
||||
codes.put(11, "Unwetter");
|
||||
codes.put(12, "Warten auf ein verspätetes Schiff");
|
||||
codes.put(13, "Pass- und Zollkontrolle");
|
||||
codes.put(14, "Technische Störung am Bahnhof");
|
||||
codes.put(15, "Beeinträchtigung durch Vandalismus");
|
||||
codes.put(16, "Entschärfung einer Fliegerbombe");
|
||||
codes.put(17, "Beschädigung einer Brücke");
|
||||
codes.put(18, "umgestürzter Baum im Gleis");
|
||||
codes.put(19, "Unfall an einem Bahnübergang");
|
||||
codes.put(20, "Tiere im Gleis");
|
||||
codes.put(21, "Warten auf Fahrgäste aus einem anderen Zug");
|
||||
codes.put(22, "Witterungsbedingte Störung");
|
||||
codes.put(23, "Feuerwehreinsatz auf Bahngelände");
|
||||
codes.put(24, "Verspätung im Ausland");
|
||||
codes.put(25, "Warten auf weitere Wagen");
|
||||
codes.put(28, "Gegenstände im Gleis");
|
||||
codes.put(29, "Ersatzverkehr mit Bus ist eingerichtet");
|
||||
codes.put(31, "Bauarbeiten");
|
||||
codes.put(32, "Verzögerung beim Ein-/Ausstieg");
|
||||
codes.put(33, "Oberleitungsstörung");
|
||||
codes.put(34, "Signalstörung");
|
||||
codes.put(35, "Streckensperrung");
|
||||
codes.put(36, "technische Störung am Zug");
|
||||
codes.put(38, "technische Störung an der Strecke");
|
||||
codes.put(39, "Anhängen von zusätzlichen Wagen");
|
||||
codes.put(40, "Stellwerksstörung /-ausfall");
|
||||
codes.put(41, "Störung an einem Bahnübergang");
|
||||
codes.put(42, "außerplanmäßige Geschwindigkeitsbeschränkung");
|
||||
codes.put(43, "Verspätung eines vorausfahrenden Zuges");
|
||||
codes.put(44, "Warten auf einen entgegenkommenden Zug");
|
||||
codes.put(45, "Überholung");
|
||||
codes.put(46, "Warten auf freie Einfahrt");
|
||||
codes.put(47, "verspätete Bereitstellung des Zuges");
|
||||
codes.put(48, "Verspätung aus vorheriger Fahrt");
|
||||
codes.put(55, "technische Störung an einem anderen Zug");
|
||||
codes.put(56, "Warten auf Fahrgäste aus einem Bus");
|
||||
codes.put(57, "Zusätzlicher Halt zum Ein-/Ausstieg für Reisende");
|
||||
codes.put(58, "Umleitung des Zuges");
|
||||
codes.put(59, "Schnee und Eis");
|
||||
codes.put(60, "Reduzierte Geschwindigkeit wegen Sturm");
|
||||
codes.put(61, "Türstörung");
|
||||
codes.put(62, "behobene technische Störung am Zug");
|
||||
codes.put(63, "technische Untersuchung am Zug");
|
||||
codes.put(64, "Weichenstörung");
|
||||
codes.put(65, "Erdrutsch");
|
||||
codes.put(66, "Hochwasser");
|
||||
codes.put(70, "WLAN im gesamten Zug nicht verfügbar");
|
||||
codes.put(71, "WLAN in einem/mehreren Wagen nicht verfügbar");
|
||||
codes.put(72, "Info-/Entertainment nicht verfügbar");
|
||||
codes.put(73, "Heute: Mehrzweckabteil vorne");
|
||||
codes.put(74, "Heute: Mehrzweckabteil hinten");
|
||||
codes.put(75, "Heute: 1. Klasse vorne");
|
||||
codes.put(76, "Heute: 1. Klasse hinten");
|
||||
codes.put(77, "ohne 1. Klasse");
|
||||
codes.put(79, "ohne Mehrzweckabteil");
|
||||
codes.put(80, "andere Reihenfolge der Wagen");
|
||||
codes.put(82, "mehrere Wagen fehlen");
|
||||
codes.put(83, "Störung fahrzeuggebundene Einstiegshilfe");
|
||||
codes.put(84, "Zug verkehrt richtig gereiht");
|
||||
codes.put(85, "ein Wagen fehlt");
|
||||
codes.put(86, "gesamter Zug ohne Reservierung");
|
||||
codes.put(87, "einzelne Wagen ohne Reservierung");
|
||||
codes.put(88, "keine Qualitätsmängel");
|
||||
codes.put(89, "Reservierungen sind wieder vorhanden");
|
||||
codes.put(90, "kein gastronomisches Angebot");
|
||||
codes.put(91, "fehlende Fahrradbeförderung");
|
||||
codes.put(92, "Eingeschränkte Fahrradbeförderung");
|
||||
codes.put(93, "keine behindertengerechte Einrichtung");
|
||||
codes.put(94, "Ersatzbewirtschaftung");
|
||||
codes.put(95, "Ohne behindertengerechtes WC");
|
||||
codes.put(96, "Überbesetzung mit Kulanzleistungen");
|
||||
codes.put(97, "Überbesetzung ohne Kulanzleistungen");
|
||||
codes.put(98, "sonstige Qualitätsmängel");
|
||||
codes.put(99, "Verzögerungen im Betriebsablauf");
|
||||
CODES.put(0, "keine Verspätungsbegründung");
|
||||
CODES.put(2, "Polizeiliche Ermittlung");
|
||||
CODES.put(3, "Feuerwehreinsatz an der Strecke");
|
||||
CODES.put(4, "kurzfristiger Personalausfall");
|
||||
CODES.put(5, "ärztliche Versorgung eines Fahrgastes");
|
||||
CODES.put(6, "Betätigen der Notbremse");
|
||||
CODES.put(7, "Personen im Gleis");
|
||||
CODES.put(8, "Notarzteinsatz am Gleis");
|
||||
CODES.put(9, "Streikauswirkungen");
|
||||
CODES.put(10, "Tiere im Gleis");
|
||||
CODES.put(11, "Unwetter");
|
||||
CODES.put(12, "Warten auf ein verspätetes Schiff");
|
||||
CODES.put(13, "Pass- und Zollkontrolle");
|
||||
CODES.put(14, "Technische Störung am Bahnhof");
|
||||
CODES.put(15, "Beeinträchtigung durch Vandalismus");
|
||||
CODES.put(16, "Entschärfung einer Fliegerbombe");
|
||||
CODES.put(17, "Beschädigung einer Brücke");
|
||||
CODES.put(18, "umgestürzter Baum im Gleis");
|
||||
CODES.put(19, "Unfall an einem Bahnübergang");
|
||||
CODES.put(20, "Tiere im Gleis");
|
||||
CODES.put(21, "Warten auf Fahrgäste aus einem anderen Zug");
|
||||
CODES.put(22, "Witterungsbedingte Störung");
|
||||
CODES.put(23, "Feuerwehreinsatz auf Bahngelände");
|
||||
CODES.put(24, "Verspätung im Ausland");
|
||||
CODES.put(25, "Warten auf weitere Wagen");
|
||||
CODES.put(28, "Gegenstände im Gleis");
|
||||
CODES.put(29, "Ersatzverkehr mit Bus ist eingerichtet");
|
||||
CODES.put(31, "Bauarbeiten");
|
||||
CODES.put(32, "Verzögerung beim Ein-/Ausstieg");
|
||||
CODES.put(33, "Oberleitungsstörung");
|
||||
CODES.put(34, "Signalstörung");
|
||||
CODES.put(35, "Streckensperrung");
|
||||
CODES.put(36, "technische Störung am Zug");
|
||||
CODES.put(38, "technische Störung an der Strecke");
|
||||
CODES.put(39, "Anhängen von zusätzlichen Wagen");
|
||||
CODES.put(40, "Stellwerksstörung /-ausfall");
|
||||
CODES.put(41, "Störung an einem Bahnübergang");
|
||||
CODES.put(42, "außerplanmäßige Geschwindigkeitsbeschränkung");
|
||||
CODES.put(43, "Verspätung eines vorausfahrenden Zuges");
|
||||
CODES.put(44, "Warten auf einen entgegenkommenden Zug");
|
||||
CODES.put(45, "Überholung");
|
||||
CODES.put(46, "Warten auf freie Einfahrt");
|
||||
CODES.put(47, "verspätete Bereitstellung des Zuges");
|
||||
CODES.put(48, "Verspätung aus vorheriger Fahrt");
|
||||
CODES.put(55, "technische Störung an einem anderen Zug");
|
||||
CODES.put(56, "Warten auf Fahrgäste aus einem Bus");
|
||||
CODES.put(57, "Zusätzlicher Halt zum Ein-/Ausstieg für Reisende");
|
||||
CODES.put(58, "Umleitung des Zuges");
|
||||
CODES.put(59, "Schnee und Eis");
|
||||
CODES.put(60, "Reduzierte Geschwindigkeit wegen Sturm");
|
||||
CODES.put(61, "Türstörung");
|
||||
CODES.put(62, "behobene technische Störung am Zug");
|
||||
CODES.put(63, "technische Untersuchung am Zug");
|
||||
CODES.put(64, "Weichenstörung");
|
||||
CODES.put(65, "Erdrutsch");
|
||||
CODES.put(66, "Hochwasser");
|
||||
CODES.put(70, "WLAN im gesamten Zug nicht verfügbar");
|
||||
CODES.put(71, "WLAN in einem/mehreren Wagen nicht verfügbar");
|
||||
CODES.put(72, "Info-/Entertainment nicht verfügbar");
|
||||
CODES.put(73, "Heute: Mehrzweckabteil vorne");
|
||||
CODES.put(74, "Heute: Mehrzweckabteil hinten");
|
||||
CODES.put(75, "Heute: 1. Klasse vorne");
|
||||
CODES.put(76, "Heute: 1. Klasse hinten");
|
||||
CODES.put(77, "ohne 1. Klasse");
|
||||
CODES.put(79, "ohne Mehrzweckabteil");
|
||||
CODES.put(80, "andere Reihenfolge der Wagen");
|
||||
CODES.put(82, "mehrere Wagen fehlen");
|
||||
CODES.put(83, "Störung fahrzeuggebundene Einstiegshilfe");
|
||||
CODES.put(84, "Zug verkehrt richtig gereiht");
|
||||
CODES.put(85, "ein Wagen fehlt");
|
||||
CODES.put(86, "gesamter Zug ohne Reservierung");
|
||||
CODES.put(87, "einzelne Wagen ohne Reservierung");
|
||||
CODES.put(88, "keine Qualitätsmängel");
|
||||
CODES.put(89, "Reservierungen sind wieder vorhanden");
|
||||
CODES.put(90, "kein gastronomisches Angebot");
|
||||
CODES.put(91, "fehlende Fahrradbeförderung");
|
||||
CODES.put(92, "Eingeschränkte Fahrradbeförderung");
|
||||
CODES.put(93, "keine behindertengerechte Einrichtung");
|
||||
CODES.put(94, "Ersatzbewirtschaftung");
|
||||
CODES.put(95, "Ohne behindertengerechtes WC");
|
||||
CODES.put(96, "Überbesetzung mit Kulanzleistungen");
|
||||
CODES.put(97, "Überbesetzung ohne Kulanzleistungen");
|
||||
CODES.put(98, "sonstige Qualitätsmängel");
|
||||
CODES.put(99, "Verzögerungen im Betriebsablauf");
|
||||
}
|
||||
|
||||
private MessageCodes() {
|
||||
@ -124,7 +124,7 @@ public final class MessageCodes {
|
||||
* Returns the message for the given code or emtpy string if not present.
|
||||
*/
|
||||
public static String getMessage(final int code) {
|
||||
final String message = codes.get(code);
|
||||
final String message = CODES.get(code);
|
||||
if (message == null) {
|
||||
return "";
|
||||
} else {
|
||||
|
@ -52,5 +52,5 @@ public enum TimetableStopFilter implements TimetableStopPredicate {
|
||||
public boolean test(TimetableStop t) {
|
||||
return t.getAr() != null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,8 @@ import org.openhab.core.types.UnDefType;
|
||||
*
|
||||
* chapter "1.2.7 TripLabel" in Technical Interface Description for external Developers
|
||||
*
|
||||
* @see https://developer.deutschebahn.com/store/apis/info?name=Timetables&version=v1&provider=DBOpenData&#tab1
|
||||
* @see @see <a href="https://developers.deutschebahn.com/db-api-marketplace/apis/product/timetables">DB API
|
||||
* Marketplace</a>
|
||||
*
|
||||
* @author Sönke Küper - Initial contribution.
|
||||
*
|
||||
|
@ -31,7 +31,7 @@ public final class ChannelNameEquals extends FilterToken {
|
||||
|
||||
private final String channelName;
|
||||
private final Pattern filterValue;
|
||||
private String channelGroup;
|
||||
private final String channelGroup;
|
||||
|
||||
/**
|
||||
* Creates an new {@link ChannelNameEquals}.
|
||||
@ -66,7 +66,7 @@ public final class ChannelNameEquals extends FilterToken {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.channelGroup + "#" + channelName + "=\"" + this.filterValue.toString() + "\"";
|
||||
return this.channelGroup + "#" + channelName + "=\"" + this.filterValue + "\"";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -31,7 +31,7 @@ public final class FilterParser {
|
||||
private abstract static class State implements FilterTokenVisitor<State> {
|
||||
|
||||
@Nullable
|
||||
private State previousState;
|
||||
private final State previousState;
|
||||
|
||||
public State(@Nullable State previousState) {
|
||||
this.previousState = previousState;
|
||||
@ -110,7 +110,7 @@ public final class FilterParser {
|
||||
|
||||
@Override
|
||||
public State handle(BracketCloseToken token) throws FilterParserException {
|
||||
throw new FilterParserException("Unexpected token " + token.toString() + " at " + token.getPosition());
|
||||
throw new FilterParserException("Unexpected token " + token + " at " + token.getPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -147,14 +147,14 @@ public final class FilterParser {
|
||||
|
||||
@Override
|
||||
public State handle(OrOperator operator) throws FilterParserException {
|
||||
throw new FilterParserException("Invalid second argument for '&' operator " + operator.toString() + " at "
|
||||
+ operator.getPosition());
|
||||
throw new FilterParserException(
|
||||
"Invalid second argument for '&' operator " + operator + " at " + operator.getPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public State handle(AndOperator operator) throws FilterParserException {
|
||||
throw new FilterParserException("Invalid second argument for '&' operator " + operator.toString() + " at "
|
||||
+ operator.getPosition());
|
||||
throw new FilterParserException(
|
||||
"Invalid second argument for '&' operator " + operator + " at " + operator.getPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -165,7 +165,7 @@ public final class FilterParser {
|
||||
@Override
|
||||
public State handle(BracketCloseToken token) throws FilterParserException {
|
||||
throw new FilterParserException(
|
||||
"Invalid second argument for '&' operator " + token.toString() + " at " + token.getPosition());
|
||||
"Invalid second argument for '&' operator " + token + " at " + token.getPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -193,14 +193,14 @@ public final class FilterParser {
|
||||
|
||||
@Override
|
||||
public State handle(OrOperator operator) throws FilterParserException {
|
||||
throw new FilterParserException("Invalid second argument for '|' operator " + operator.toString() + " at "
|
||||
+ operator.getPosition());
|
||||
throw new FilterParserException(
|
||||
"Invalid second argument for '|' operator " + operator + " at " + operator.getPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public State handle(AndOperator operator) throws FilterParserException {
|
||||
throw new FilterParserException("Invalid second argument for '|' operator " + operator.toString() + " at "
|
||||
+ operator.getPosition());
|
||||
throw new FilterParserException(
|
||||
"Invalid second argument for '|' operator " + operator + " at " + operator.getPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -211,7 +211,7 @@ public final class FilterParser {
|
||||
@Override
|
||||
public State handle(BracketCloseToken token) throws FilterParserException {
|
||||
throw new FilterParserException(
|
||||
"Invalid second argument for '|' operator " + token.toString() + " at " + token.getPosition());
|
||||
"Invalid second argument for '|' operator " + token + " at " + token.getPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -146,7 +146,7 @@ public final class FilterScanner {
|
||||
|
||||
private final int startPosition;
|
||||
private final String channelName;
|
||||
private String channelGroup;
|
||||
private final String channelGroup;
|
||||
|
||||
/**
|
||||
* Creates an new {@link ExpectQuotesState}.
|
||||
|
@ -21,7 +21,7 @@ import org.openhab.binding.deutschebahn.internal.timetable.dto.Timetable;
|
||||
/**
|
||||
* Interface for timetables API in V1.
|
||||
*
|
||||
* @see https://developer.deutschebahn.com/store/apis/info?name=Timetables&version=v1&provider=DBOpenData
|
||||
* @see <a href="https://developers.deutschebahn.com/db-api-marketplace/apis/product/timetables">DB API Marketplace</a>
|
||||
*
|
||||
* @author Sönke Küper - initial contribution
|
||||
*/
|
||||
@ -33,7 +33,7 @@ public interface TimetablesV1Api {
|
||||
* Calls the "/plan" endpoint of the rest-service.
|
||||
*
|
||||
* REST-endpoint documentation: (from
|
||||
* {@see https://developer.deutschebahn.com/store/apis/info?name=Timetables&version=v1&provider=DBOpenData}).
|
||||
* {@see https://developers.deutschebahn.com/db-api-marketplace/apis/product/timetables}).
|
||||
* Returns a Timetable object (see Timetable) that contains planned data for the specified station (evaNo)
|
||||
* within the hourly time slice given by date (format YYMMDD) and hour (format HH). The data includes stops
|
||||
* for all trips that arrive or depart within that slice. There is a small overlap between slices since some
|
||||
@ -58,7 +58,7 @@ public interface TimetablesV1Api {
|
||||
* Calls the "/fchg" endpoint of the rest-service.
|
||||
*
|
||||
* REST-endpoint documentation: (from
|
||||
* {@see https://developer.deutschebahn.com/store/apis/info?name=Timetables&version=v1&provider=DBOpenData}).
|
||||
* {@see https://developers.deutschebahn.com/db-api-marketplace/apis/product/timetables}).
|
||||
* Returns a Timetable object (see Timetable) that contains all known changes for the station given by evaNo.
|
||||
*
|
||||
* The data includes all known changes from now on until undefinitely into the future. Once changes become obsolete
|
||||
@ -82,7 +82,7 @@ public interface TimetablesV1Api {
|
||||
* Calls the "/plan" endpoint of the rest-service.
|
||||
*
|
||||
* REST-endpoint documentation: (from
|
||||
* {@see https://developer.deutschebahn.com/store/apis/info?name=Timetables&version=v1&provider=DBOpenData}).
|
||||
* {@see https://developers.deutschebahn.com/db-api-marketplace/apis/product/timetables}).
|
||||
* Returns a Timetable object (see Timetable) that contains all recent changes for the station given by evaNo.
|
||||
* Recent changes are always a subset of the full changes. They may equal full changes but are typically much
|
||||
* smaller.
|
||||
|
@ -12,13 +12,10 @@
|
||||
*/
|
||||
package org.openhab.binding.deutschebahn.internal.timetable;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.deutschebahn.internal.timetable.TimetablesV1Impl.HttpCallable;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Factory for {@link TimetablesV1Api}.
|
||||
@ -31,6 +28,6 @@ public interface TimetablesV1ApiFactory {
|
||||
/**
|
||||
* Creates an new instance of the {@link TimetablesV1Api}.
|
||||
*/
|
||||
public abstract TimetablesV1Api create(final String authToken, final HttpCallable httpCallable)
|
||||
throws JAXBException, SAXException, URISyntaxException;
|
||||
public abstract TimetablesV1Api create(final String clientId, final String clientSecret,
|
||||
final HttpCallable httpCallable) throws JAXBException;
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ package org.openhab.binding.deutschebahn.internal.timetable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
import java.net.URISyntaxException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Properties;
|
||||
@ -50,7 +49,7 @@ public final class TimetablesV1Impl implements TimetablesV1Api {
|
||||
|
||||
/**
|
||||
* Executes the given <code>url</code> with the given <code>httpMethod</code>.
|
||||
* Furthermore the <code>http.proxyXXX</code> System variables are read and
|
||||
* Furthermore, the <code>http.proxyXXX</code> System variables are read and
|
||||
* set into the {@link org.eclipse.jetty.client.HttpClient}.
|
||||
*
|
||||
* @param httpMethod the HTTP method to use
|
||||
@ -61,35 +60,43 @@ public final class TimetablesV1Impl implements TimetablesV1Api {
|
||||
* @param contentType the content type of the given <code>content</code>
|
||||
* @param timeout the socket timeout in milliseconds to wait for data
|
||||
* @return the response body or <code>NULL</code> when the request went wrong
|
||||
* @throws IOException when the request execution failed, timed out or it was interrupted
|
||||
* @throws IOException when the request execution failed, timed out, or it was interrupted
|
||||
*/
|
||||
public abstract String executeUrl(String httpMethod, String url, Properties httpHeaders,
|
||||
@Nullable InputStream content, @Nullable String contentType, int timeout) throws IOException;
|
||||
}
|
||||
|
||||
private static final String PLAN_URL = "https://api.deutschebahn.com/timetables/v1/plan/%evaNo%/%date%/%hour%";
|
||||
private static final String FCHG_URL = "https://api.deutschebahn.com/timetables/v1/fchg/%evaNo%";
|
||||
private static final String RCHG_URL = "https://api.deutschebahn.com/timetables/v1/rchg/%evaNo%";
|
||||
private static final String BASE_URL = "https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1";
|
||||
private static final String PLAN_URL = BASE_URL + "/plan/%evaNo%/%date%/%hour%";
|
||||
private static final String FCHG_URL = BASE_URL + "/fchg/%evaNo%";
|
||||
private static final String RCHG_URL = BASE_URL + "/rchg/%evaNo%";
|
||||
|
||||
private static final String DB_CLIENT_ID_HEADER_NAME = "DB-Client-Id";
|
||||
private static final String DB_CLIENT_SECRET_HEADER_NAME = "DB-Api-Key";
|
||||
|
||||
private static final int REQUEST_TIMEOUT_MS = (int) TimeUnit.SECONDS.toMillis(30);
|
||||
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyMMdd");
|
||||
private static final SimpleDateFormat HOUR_FORMAT = new SimpleDateFormat("HH");
|
||||
|
||||
private final String authToken;
|
||||
private final String clientId;
|
||||
private final String clientSecret;
|
||||
private final HttpCallable httpCallable;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(TimetablesV1Impl.class);
|
||||
private JAXBContext jaxbContext;
|
||||
private final JAXBContext jaxbContext;
|
||||
// private Schema schema;
|
||||
|
||||
/**
|
||||
* Creates an new {@link TimetablesV1Impl}.
|
||||
* Creates a new {@link TimetablesV1Impl}.
|
||||
*
|
||||
* @param authToken The authentication token for timetable api on developer.deutschebahn.com.
|
||||
* @param clientSecret The client secret for application with linked timetable api on developers.deutschebahn.com.
|
||||
*/
|
||||
public TimetablesV1Impl(final String authToken, final HttpCallable httpCallable)
|
||||
throws JAXBException, SAXException, URISyntaxException {
|
||||
this.authToken = authToken;
|
||||
public TimetablesV1Impl( //
|
||||
final String clientId, //
|
||||
final String clientSecret, //
|
||||
final HttpCallable httpCallable) throws JAXBException {
|
||||
this.clientId = clientId;
|
||||
this.clientSecret = clientSecret;
|
||||
this.httpCallable = httpCallable;
|
||||
|
||||
// The results from webservice does not conform to the schema provided. The triplabel-Element (tl) is expected
|
||||
@ -149,7 +156,7 @@ public final class TimetablesV1Impl implements TimetablesV1Api {
|
||||
}
|
||||
|
||||
try {
|
||||
return unmarshal(response, Timetable.class);
|
||||
return unmarshal(response);
|
||||
} catch (JAXBException | SAXException e) {
|
||||
this.logger.error("Error parsing response from timetable api.", e);
|
||||
throw new IOException(e);
|
||||
@ -162,22 +169,21 @@ public final class TimetablesV1Impl implements TimetablesV1Api {
|
||||
private Properties createHeaders() {
|
||||
final Properties headers = new Properties();
|
||||
headers.put(HttpHeader.ACCEPT.asString(), "application/xml");
|
||||
headers.put(HttpHeader.AUTHORIZATION.asString(), "Bearer " + this.authToken);
|
||||
headers.put(DB_CLIENT_ID_HEADER_NAME, this.clientId);
|
||||
headers.put(DB_CLIENT_SECRET_HEADER_NAME, this.clientSecret);
|
||||
return headers;
|
||||
}
|
||||
|
||||
private <T> T unmarshal(final String xmlContent, final Class<T> clazz) throws JAXBException, SAXException {
|
||||
private <T> T unmarshal(final String xmlContent) throws JAXBException, SAXException {
|
||||
return unmarshal( //
|
||||
jaxbContext, //
|
||||
null, // Provide no schema, due webservice results are not schema-valid.
|
||||
xmlContent, //
|
||||
clazz //
|
||||
);
|
||||
xmlContent);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T unmarshal(final JAXBContext jaxbContext, @Nullable final Schema schema,
|
||||
final String xmlContent, final Class<T> clss) throws JAXBException {
|
||||
final String xmlContent) throws JAXBException {
|
||||
final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
|
||||
unmarshaller.setSchema(schema);
|
||||
final JAXBElement<T> resultObject = (JAXBElement<T>) unmarshaller.unmarshal(new StringReader(xmlContent));
|
||||
|
@ -8,22 +8,24 @@ binding.deutschebahn.description = This binding provides timetable information f
|
||||
thing-type.deutschebahn.timetable.label = Deutsche Bahn Timetable
|
||||
thing-type.deutschebahn.timetable.description = Connection to the timetable API of Deutsche Bahn. Provides timetable data that can be displayed using the train things.
|
||||
thing-type.deutschebahn.train.label = Train
|
||||
thing-type.deutschebahn.train.description = Displays informations about an train within the given timetable at one station.
|
||||
thing-type.deutschebahn.train.description = Displays information about a train within the given timetable at one station.
|
||||
thing-type.deutschebahn.train.group.arrival.label = Arrival
|
||||
thing-type.deutschebahn.train.group.arrival.description = Contains all informations about the arrival of the train at the station. Channels may be empty, if the trains starts at this station.
|
||||
thing-type.deutschebahn.train.group.arrival.description = Contains all information about the arrival of the train at the station. Channels may be empty, if the trains starts at this station.
|
||||
thing-type.deutschebahn.train.group.departure.label = Departure
|
||||
thing-type.deutschebahn.train.group.departure.description = Contains all informations about the departure of the train at the station. Channels may be empty, if the trains ends at this station.
|
||||
thing-type.deutschebahn.train.group.departure.description = Contains all information about the departure of the train at the station. Channels may be empty, if the trains ends at this station.
|
||||
thing-type.deutschebahn.train.group.trip.label = Trip
|
||||
thing-type.deutschebahn.train.group.trip.description = Contains all informations about the trip of the train.
|
||||
thing-type.deutschebahn.train.group.trip.description = Contains all information about the trip of the train.
|
||||
|
||||
# thing types config
|
||||
|
||||
thing-type.config.deutschebahn.timetable.accessToken.label = Access Token
|
||||
thing-type.config.deutschebahn.timetable.accessToken.description = Access Token from Deutsche Bahn developer portal for accessing the webservice api.
|
||||
thing-type.config.deutschebahn.timetable.clientId.label = Client Id
|
||||
thing-type.config.deutschebahn.timetable.clientId.description = Client ID from Application within DB API Marketplace for accessing the timetables webservice api.
|
||||
thing-type.config.deutschebahn.timetable.clientSecret.label = Client Secret (API Key)
|
||||
thing-type.config.deutschebahn.timetable.clientSecret.description = Client Secret (API Key) from Application within DB API Marketplace for accessing the timetables webservice api.
|
||||
thing-type.config.deutschebahn.timetable.evaNo.label = EvaNo of Station
|
||||
thing-type.config.deutschebahn.timetable.evaNo.description = evaNo of the station, for which the timetable should be requested. see https://data.deutschebahn.com/dataset.tags.EVA-Nr..html
|
||||
thing-type.config.deutschebahn.timetable.trainFilter.label = Train Filter
|
||||
thing-type.config.deutschebahn.timetable.trainFilter.description = Selects the trains that will be be displayed in this timetable. If not set only departures will be provided.
|
||||
thing-type.config.deutschebahn.timetable.trainFilter.description = Selects the trains that will be displayed in this timetable. If not set only departures will be provided.
|
||||
thing-type.config.deutschebahn.timetable.trainFilter.option.all = All
|
||||
thing-type.config.deutschebahn.timetable.trainFilter.option.arrivals = Arrivals
|
||||
thing-type.config.deutschebahn.timetable.trainFilter.option.departures = Departures
|
||||
@ -33,9 +35,9 @@ thing-type.config.deutschebahn.train.position.description = Selects the position
|
||||
# channel group types
|
||||
|
||||
channel-group-type.deutschebahn.eventAttributes.label = Event Attributes
|
||||
channel-group-type.deutschebahn.eventAttributes.description = Contains all attributes for an event (arrival / departure) of an train at the station.
|
||||
channel-group-type.deutschebahn.eventAttributes.description = Contains all attributes for an event (arrival / departure) of a train at the station.
|
||||
channel-group-type.deutschebahn.tripAttributes.label = Trip Attributes
|
||||
channel-group-type.deutschebahn.tripAttributes.description = Contains all informations about the trip of the train.
|
||||
channel-group-type.deutschebahn.tripAttributes.description = Contains all information about the trip of the train.
|
||||
|
||||
# channel types
|
||||
|
||||
@ -51,7 +53,7 @@ channel-type.deutschebahn.changed-final-station.description = Changed final stat
|
||||
channel-type.deutschebahn.changed-intermediate-stations.label = Changed Intermediate Stations
|
||||
channel-type.deutschebahn.changed-intermediate-stations.description = Returns the changed stations this train came from (for arrivals) or the stations this train will go to (for departures). Stations will be separated by single dash.
|
||||
channel-type.deutschebahn.changed-path.label = Changed Path
|
||||
channel-type.deutschebahn.changed-path.description = Provides the planned path of a train. For arrival, the path indicates the stations that come before the current station. The first element then is the trip’s start station. For departure, the path indicates the stations that come after the current station. The last ele-ment in the path then is the trip’s destination station. Note that the current station is never included in the path (neither for arrival nor for departure).
|
||||
channel-type.deutschebahn.changed-path.description = Provides the planned path of a train. For arrival, the path indicates the stations that come before the current station. The first element then is the trip’s start station. For departure, the path indicates the stations that come after the current station. The last element in the path then is the trip’s destination station. Note that the current station is never included in the path (neither for arrival nor for departure).
|
||||
channel-type.deutschebahn.changed-platform.label = Changed Platform
|
||||
channel-type.deutschebahn.changed-platform.description = Provides the changed platform of a train.
|
||||
channel-type.deutschebahn.changed-status.label = Changed Status
|
||||
@ -71,7 +73,7 @@ channel-type.deutschebahn.hidden.description = On if the event should not be sho
|
||||
channel-type.deutschebahn.line.label = Line
|
||||
channel-type.deutschebahn.line.description = The line indicator.
|
||||
channel-type.deutschebahn.messages.label = Messages
|
||||
channel-type.deutschebahn.messages.description = Messages for this train. Contains all translated codes from the messages of the selected train stop. Multiple messages will be separated with an single dash.
|
||||
channel-type.deutschebahn.messages.description = Messages for this train. Contains all translated codes from the messages of the selected train stop. Multiple messages will be separated with a single dash.
|
||||
channel-type.deutschebahn.number.label = Number
|
||||
channel-type.deutschebahn.number.description = Provides the trip/train number, e.g. "4523".
|
||||
channel-type.deutschebahn.owner.label = Owner
|
||||
@ -83,7 +85,7 @@ channel-type.deutschebahn.planned-final-station.description = Planned final stat
|
||||
channel-type.deutschebahn.planned-intermediate-stations.label = Planned Intermediate Stations
|
||||
channel-type.deutschebahn.planned-intermediate-stations.description = Returns the planned stations this train came from (for arrivals) or the stations this train will go to (for departures). Stations will be separated by single dash.
|
||||
channel-type.deutschebahn.planned-path.label = Planned Path
|
||||
channel-type.deutschebahn.planned-path.description = Provides the planned path of a train. For arrival, the path indicates the stations that come before the current station. The first element then is the trip’s start station. For departure, the path indicates the stations that come after the current station. The last ele-ment in the path then is the trip’s destination station. Note that the current station is never included in the path (neither for arrival nor for departure).
|
||||
channel-type.deutschebahn.planned-path.description = Provides the planned path of a train. For arrival, the path indicates the stations that come before the current station. The first element then is the trip’s start station. For departure, the path indicates the stations that come after the current station. The last element in the path then is the trip’s destination station. Note that the current station is never included in the path (neither for arrival nor for departure).
|
||||
channel-type.deutschebahn.planned-platform.label = Planned Platform
|
||||
channel-type.deutschebahn.planned-platform.description = Provides the planned platform of a train.
|
||||
channel-type.deutschebahn.planned-status.label = Planned Status
|
||||
|
@ -11,9 +11,14 @@
|
||||
train things.</description>
|
||||
|
||||
<config-description>
|
||||
<parameter name="accessToken" type="text" required="true">
|
||||
<label>Access Token</label>
|
||||
<description>Access Token from Deutsche Bahn developer portal for accessing the webservice api.</description>
|
||||
<parameter name="clientId" type="text" required="true">
|
||||
<label>Client Id</label>
|
||||
<description>Client ID from Application within DB API Marketplace for accessing the timetables webservice api.</description>
|
||||
</parameter>
|
||||
<parameter name="clientSecret" type="text" required="true">
|
||||
<label>Client Secret (API Key)</label>
|
||||
<description>Client Secret (API Key) from Application within DB API Marketplace for accessing the timetables
|
||||
webservice api.</description>
|
||||
</parameter>
|
||||
<parameter name="evaNo" type="text" required="true" pattern="80\d{5,5}">
|
||||
<label>EvaNo of Station</label>
|
||||
@ -24,7 +29,7 @@
|
||||
<advanced>true</advanced>
|
||||
<default>departures</default>
|
||||
<label>Train Filter</label>
|
||||
<description>Selects the trains that will be be displayed in this timetable. If not set only departures will be
|
||||
<description>Selects the trains that will be displayed in this timetable. If not set only departures will be
|
||||
provided.</description>
|
||||
<options>
|
||||
<option value="all">All</option>
|
||||
@ -45,23 +50,23 @@
|
||||
<bridge-type-ref id="timetable"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Train</label>
|
||||
<description>Displays informations about an train within the given timetable at one station.</description>
|
||||
<description>Displays information about a train within the given timetable at one station.</description>
|
||||
<channel-groups>
|
||||
<channel-group typeId="tripAttributes" id="trip">
|
||||
<label>Trip</label>
|
||||
<description>Contains all informations about the trip of the train.
|
||||
<description>Contains all information about the trip of the train.
|
||||
</description>
|
||||
</channel-group>
|
||||
<channel-group typeId="eventAttributes" id="arrival">
|
||||
<label>Arrival</label>
|
||||
<description>Contains all informations about the arrival of the train at the station.
|
||||
<description>Contains all information about the arrival of the train at the station.
|
||||
Channels may be empty, if the
|
||||
trains starts at this station.
|
||||
</description>
|
||||
</channel-group>
|
||||
<channel-group typeId="eventAttributes" id="departure">
|
||||
<label>Departure</label>
|
||||
<description>Contains all informations about the departure of the train at the station.
|
||||
<description>Contains all information about the departure of the train at the station.
|
||||
Channels may be empty, if the
|
||||
trains ends at this station.
|
||||
</description>
|
||||
@ -77,7 +82,7 @@
|
||||
|
||||
<channel-group-type id="tripAttributes">
|
||||
<label>Trip Attributes</label>
|
||||
<description>Contains all informations about the trip of the train.</description>
|
||||
<description>Contains all information about the trip of the train.</description>
|
||||
<channels>
|
||||
<channel typeId="category" id="category"/>
|
||||
<channel typeId="number" id="number"/>
|
||||
@ -89,7 +94,7 @@
|
||||
|
||||
<channel-group-type id="eventAttributes">
|
||||
<label>Event Attributes</label>
|
||||
<description>Contains all attributes for an event (arrival / departure) of an train at the station.</description>
|
||||
<description>Contains all attributes for an event (arrival / departure) of a train at the station.</description>
|
||||
<channels>
|
||||
<channel typeId="planned-path" id="planned-path"/>
|
||||
<channel typeId="changed-path" id="changed-path"/>
|
||||
@ -227,7 +232,7 @@
|
||||
<item-type>String</item-type>
|
||||
<label>Messages</label>
|
||||
<description>Messages for this train. Contains all translated codes from the messages of the selected train stop.
|
||||
Multiple messages will be separated with an single dash.</description>
|
||||
Multiple messages will be separated with a single dash.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
@ -246,7 +251,7 @@
|
||||
For arrival, the path indicates the stations that come before the
|
||||
current station. The first element then is the trip’s
|
||||
start station. For departure, the path indicates the stations
|
||||
that come after the current station. The last ele-ment
|
||||
that come after the current station. The last element
|
||||
in the path then is the trip’s destination station. Note that
|
||||
the current station is never included in the path
|
||||
(neither for arrival nor for departure).</description>
|
||||
@ -260,7 +265,7 @@
|
||||
For arrival, the path indicates the stations that come before the
|
||||
current station. The first element then is the trip’s
|
||||
start station. For departure, the path indicates the stations
|
||||
that come after the current station. The last ele-ment
|
||||
that come after the current station. The last element
|
||||
in the path then is the trip’s destination station. Note that
|
||||
the current station is never included in the path
|
||||
(neither for arrival nor for departure).</description>
|
||||
|
@ -12,8 +12,13 @@
|
||||
*/
|
||||
package org.openhab.binding.deutschebahn.internal;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
@ -172,7 +177,7 @@ public class DeutscheBahnTimetableHandlerTest implements TimetablesV1ImplTestHel
|
||||
final TimetablesV1ApiStub stubWithError = TimetablesV1ApiStub.createWithException();
|
||||
|
||||
final DeutscheBahnTimetableHandler handler = createAndInitHandler(callback, bridge,
|
||||
(String authToken, HttpCallable httpCallable) -> stubWithError);
|
||||
(String clientId, String clientSecret, HttpCallable httpCallable) -> stubWithError);
|
||||
|
||||
try {
|
||||
verify(callback).statusUpdated(eq(bridge), argThat(arg -> arg.getStatus().equals(ThingStatus.UNKNOWN)));
|
||||
@ -212,7 +217,7 @@ public class DeutscheBahnTimetableHandlerTest implements TimetablesV1ImplTestHel
|
||||
final TimetablesV1ApiStub stubWithData = TimetablesV1ApiStub.createWithResult(timetable);
|
||||
|
||||
final DeutscheBahnTimetableHandler handler = createAndInitHandler(callback, bridge,
|
||||
(String authToken, HttpCallable httpCallable) -> stubWithData);
|
||||
(String clientId, String clientSecret, HttpCallable httpCallable) -> stubWithData);
|
||||
|
||||
try {
|
||||
verify(callback).statusUpdated(eq(bridge), argThat(arg -> arg.getStatus().equals(ThingStatus.UNKNOWN)));
|
||||
|
@ -45,11 +45,11 @@ public class TimetableLoaderTest implements TimetablesV1ImplTestHelper {
|
||||
|
||||
final List<TimetableStop> stops = loader.getTimetableStops();
|
||||
assertThat(timeTableTestModule.getRequestedPlanUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/plan/8000226/210816/09",
|
||||
"https://api.deutschebahn.com/timetables/v1/plan/8000226/210816/10",
|
||||
"https://api.deutschebahn.com/timetables/v1/plan/8000226/210816/11"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/8000226/210816/09",
|
||||
"https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/8000226/210816/10",
|
||||
"https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/8000226/210816/11"));
|
||||
assertThat(timeTableTestModule.getRequestedFullChangesUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/fchg/8000226"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/fchg/8000226"));
|
||||
assertThat(timeTableTestModule.getRequestedRecentChangesUrls(), empty());
|
||||
|
||||
assertThat(stops, hasSize(21));
|
||||
@ -75,9 +75,9 @@ public class TimetableLoaderTest implements TimetablesV1ImplTestHelper {
|
||||
|
||||
final List<TimetableStop> stops = loader.getTimetableStops();
|
||||
assertThat(timeTableTestModule.getRequestedPlanUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/plan/8000226/210816/09"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/8000226/210816/09"));
|
||||
assertThat(timeTableTestModule.getRequestedFullChangesUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/fchg/8000226"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/fchg/8000226"));
|
||||
assertThat(timeTableTestModule.getRequestedRecentChangesUrls(), empty());
|
||||
|
||||
assertThat(stops, hasSize(8));
|
||||
@ -91,11 +91,11 @@ public class TimetableLoaderTest implements TimetablesV1ImplTestHelper {
|
||||
final List<TimetableStop> stops02 = loader.getTimetableStops();
|
||||
assertThat(stops02, hasSize(13));
|
||||
assertThat(timeTableTestModule.getRequestedPlanUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/plan/8000226/210816/09",
|
||||
"https://api.deutschebahn.com/timetables/v1/plan/8000226/210816/10"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/8000226/210816/09",
|
||||
"https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/8000226/210816/10"));
|
||||
assertThat(timeTableTestModule.getRequestedFullChangesUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/fchg/8000226",
|
||||
"https://api.deutschebahn.com/timetables/v1/fchg/8000226"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/fchg/8000226",
|
||||
"https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/fchg/8000226"));
|
||||
assertThat(timeTableTestModule.getRequestedRecentChangesUrls(), empty());
|
||||
|
||||
assertEquals("-5296516961807204721-2108160906-5", stops02.get(0).getId());
|
||||
@ -114,9 +114,9 @@ public class TimetableLoaderTest implements TimetablesV1ImplTestHelper {
|
||||
// First call - plan and full changes are requested.
|
||||
loader.getTimetableStops();
|
||||
assertThat(timeTableTestModule.getRequestedPlanUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/plan/8000226/210816/09"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/8000226/210816/09"));
|
||||
assertThat(timeTableTestModule.getRequestedFullChangesUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/fchg/8000226"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/fchg/8000226"));
|
||||
assertThat(timeTableTestModule.getRequestedRecentChangesUrls(), empty());
|
||||
|
||||
// Changes are updated only every 30 seconds, so move clock ahead 20 seconds, no request is made
|
||||
@ -124,43 +124,43 @@ public class TimetableLoaderTest implements TimetablesV1ImplTestHelper {
|
||||
loader.getTimetableStops();
|
||||
|
||||
assertThat(timeTableTestModule.getRequestedPlanUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/plan/8000226/210816/09"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/8000226/210816/09"));
|
||||
assertThat(timeTableTestModule.getRequestedFullChangesUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/fchg/8000226"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/fchg/8000226"));
|
||||
assertThat(timeTableTestModule.getRequestedRecentChangesUrls(), empty());
|
||||
|
||||
// Move ahead 10 seconds, so recent changes are fetched
|
||||
timeProvider.moveAhead(10);
|
||||
loader.getTimetableStops();
|
||||
assertThat(timeTableTestModule.getRequestedPlanUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/plan/8000226/210816/09"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/8000226/210816/09"));
|
||||
assertThat(timeTableTestModule.getRequestedFullChangesUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/fchg/8000226"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/fchg/8000226"));
|
||||
assertThat(timeTableTestModule.getRequestedRecentChangesUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/rchg/8000226"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/rchg/8000226"));
|
||||
|
||||
// Move again ahead 30 seconds, recent changes are fetched again
|
||||
timeProvider.moveAhead(30);
|
||||
loader.getTimetableStops();
|
||||
assertThat(timeTableTestModule.getRequestedPlanUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/plan/8000226/210816/09"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/8000226/210816/09"));
|
||||
assertThat(timeTableTestModule.getRequestedFullChangesUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/fchg/8000226"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/fchg/8000226"));
|
||||
assertThat(timeTableTestModule.getRequestedRecentChangesUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/rchg/8000226",
|
||||
"https://api.deutschebahn.com/timetables/v1/rchg/8000226"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/rchg/8000226",
|
||||
"https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/rchg/8000226"));
|
||||
|
||||
// If recent change were not updated last 120 seconds the full changes must be requested
|
||||
timeProvider.moveAhead(120);
|
||||
loader.getTimetableStops();
|
||||
assertThat(timeTableTestModule.getRequestedPlanUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/plan/8000226/210816/09"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/8000226/210816/09"));
|
||||
assertThat(timeTableTestModule.getRequestedFullChangesUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/fchg/8000226",
|
||||
"https://api.deutschebahn.com/timetables/v1/fchg/8000226"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/fchg/8000226",
|
||||
"https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/fchg/8000226"));
|
||||
assertThat(timeTableTestModule.getRequestedRecentChangesUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/rchg/8000226",
|
||||
"https://api.deutschebahn.com/timetables/v1/rchg/8000226"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/rchg/8000226",
|
||||
"https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/rchg/8000226"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -171,7 +171,8 @@ public class TimetableLoaderTest implements TimetablesV1ImplTestHelper {
|
||||
EventType.ARRIVAL, timeProvider, EVA_LEHRTE, 20);
|
||||
|
||||
// Simulate that only one url is available
|
||||
timeTableTestModule.addAvailableUrl("https://api.deutschebahn.com/timetables/v1/plan/8000226/210816/09");
|
||||
timeTableTestModule.addAvailableUrl(
|
||||
"https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/8000226/210816/09");
|
||||
|
||||
timeProvider.time = new GregorianCalendar(2021, Calendar.AUGUST, 16, 9, 0);
|
||||
|
||||
@ -191,7 +192,8 @@ public class TimetableLoaderTest implements TimetablesV1ImplTestHelper {
|
||||
EventType.DEPARTURE, timeProvider, EVA_LEHRTE, 20);
|
||||
|
||||
// Simulate that only one url is available
|
||||
timeTableTestModule.addAvailableUrl("https://api.deutschebahn.com/timetables/v1/plan/8000226/210816/09");
|
||||
timeTableTestModule.addAvailableUrl(
|
||||
"https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/8000226/210816/09");
|
||||
|
||||
timeProvider.time = new GregorianCalendar(2021, Calendar.AUGUST, 16, 9, 0);
|
||||
|
||||
@ -214,9 +216,9 @@ public class TimetableLoaderTest implements TimetablesV1ImplTestHelper {
|
||||
|
||||
final List<TimetableStop> stops = loader.getTimetableStops();
|
||||
assertThat(timeTableTestModule.getRequestedPlanUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/plan/8000226/210816/09"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/8000226/210816/09"));
|
||||
assertThat(timeTableTestModule.getRequestedFullChangesUrls(),
|
||||
contains("https://api.deutschebahn.com/timetables/v1/fchg/8000226"));
|
||||
contains("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/fchg/8000226"));
|
||||
assertThat(timeTableTestModule.getRequestedRecentChangesUrls(), empty());
|
||||
|
||||
// Stop -5296516961807204721-2108160906-5 has its planned time at 9:34, but its included because its changed
|
||||
|
@ -39,11 +39,11 @@ import org.openhab.binding.deutschebahn.internal.timetable.TimetablesV1Impl.Http
|
||||
public class TimetableStubHttpCallable implements HttpCallable {
|
||||
|
||||
private static final Pattern PLAN_URL_PATTERN = Pattern
|
||||
.compile("https://api.deutschebahn.com/timetables/v1/plan/(\\d+)/(\\d+)/(\\d+)");
|
||||
.compile("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/(\\d+)/(\\d+)/(\\d+)");
|
||||
private static final Pattern FULL_CHANGES_URL_PATTERN = Pattern
|
||||
.compile("https://api.deutschebahn.com/timetables/v1/fchg/(\\d+)");
|
||||
.compile("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/fchg/(\\d+)");
|
||||
private static final Pattern RECENT_CHANGES_URL_PATTERN = Pattern
|
||||
.compile("https://api.deutschebahn.com/timetables/v1/rchg/(\\d+)");
|
||||
.compile("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/rchg/(\\d+)");
|
||||
|
||||
private final File testdataDir;
|
||||
private final List<String> requestedPlanUrls;
|
||||
|
@ -12,14 +12,10 @@
|
||||
*/
|
||||
package org.openhab.binding.deutschebahn.internal.timetable;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.deutschebahn.internal.timetable.TimetablesV1Impl.HttpCallable;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Testmodule that contains the {@link TimetablesV1Api} and {@link TimetableStubHttpCallable}.
|
||||
@ -59,13 +55,6 @@ public final class TimetablesApiTestModule {
|
||||
}
|
||||
|
||||
public TimetablesV1ApiFactory getApiFactory() {
|
||||
return new TimetablesV1ApiFactory() {
|
||||
|
||||
@Override
|
||||
public TimetablesV1Api create(String authToken, HttpCallable httpCallable)
|
||||
throws JAXBException, SAXException, URISyntaxException {
|
||||
return api;
|
||||
}
|
||||
};
|
||||
return (String clientId, String clientSecret, HttpCallable httpCallable) -> api;
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ public class TimetablesV1ImplTest implements TimetablesV1ImplTestHelper {
|
||||
public void testGetDataForHannoverHBF() throws Exception {
|
||||
TimetablesV1Api timeTableApi = createApiWithTestdata().getApi();
|
||||
|
||||
Date time = new GregorianCalendar(2021, Calendar.OCTOBER, 14, 11, 00).getTime();
|
||||
Date time = new GregorianCalendar(2021, Calendar.OCTOBER, 14, 11, 0).getTime();
|
||||
|
||||
Timetable timeTable = timeTableApi.getPlan(EVA_HANNOVER_HBF, time);
|
||||
assertNotNull(timeTable);
|
||||
|
@ -29,7 +29,8 @@ public interface TimetablesV1ImplTestHelper {
|
||||
|
||||
public static final String EVA_LEHRTE = "8000226";
|
||||
public static final String EVA_HANNOVER_HBF = "8000152";
|
||||
public static final String AUTH_TOKEN = "354c8161cd7fb0936c840240280c131e";
|
||||
public static final String CLIENT_ID = "bdwrpmxuo6157jrekftlbcc6ju9awo";
|
||||
public static final String CLIENT_SECRET = "354c8161cd7fb0936c840240280c131e";
|
||||
|
||||
/**
|
||||
* Creates an {@link TimetablesApiTestModule} that uses http response data from file system.
|
||||
@ -49,7 +50,7 @@ public interface TimetablesV1ImplTestHelper {
|
||||
assertNotNull(timetablesData);
|
||||
final File testDataDir = new File(timetablesData.toURI());
|
||||
final TimetableStubHttpCallable httpStub = new TimetableStubHttpCallable(testDataDir);
|
||||
final TimetablesV1Impl timeTableApi = new TimetablesV1Impl(AUTH_TOKEN, httpStub);
|
||||
final TimetablesV1Impl timeTableApi = new TimetablesV1Impl(CLIENT_ID, CLIENT_SECRET, httpStub);
|
||||
return new TimetablesApiTestModule(timeTableApi, httpStub);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user