summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.gitmodules3
-rw-r--r--.mailmap2
-rw-r--r--Build.PL36
-rw-r--r--COPYING2
-rw-r--r--Changelog165
-rw-r--r--Dockerfile5
-rw-r--r--README.md68
-rwxr-xr-xbin/efa-m587
-rw-r--r--cpanfile14
m---------ext/transport-apis0
-rw-r--r--lib/Travel/Status/DE/EFA.pm1083
-rw-r--r--lib/Travel/Status/DE/EFA/Departure.pm528
-rw-r--r--lib/Travel/Status/DE/EFA/Info.pm127
-rw-r--r--lib/Travel/Status/DE/EFA/Line.pm8
-rw-r--r--lib/Travel/Status/DE/EFA/Result.pm330
-rw-r--r--lib/Travel/Status/DE/EFA/Services.pm.PL147
-rw-r--r--lib/Travel/Status/DE/EFA/Stop.pm133
-rw-r--r--lib/Travel/Status/DE/EFA/Trip.pm342
-rw-r--r--lib/Travel/Status/DE/VRR.pm11
-rwxr-xr-xscripts/check-efa-urls14
-rwxr-xr-xscripts/makedeb-docker-helper7
-rw-r--r--t/20-vrr.t105
-rw-r--r--t/21-vrr-ambig.t35
-rw-r--r--t/in/essen_alfred_ambiguous.json327
-rw-r--r--t/in/essen_alfredusbad_ambiguous.xml81
-rw-r--r--t/in/essen_bp.html762
-rw-r--r--t/in/essen_bp.json3979
-rw-r--r--t/in/essen_hb.xml1034
-rw-r--r--t/in/essen_hb_invalid.xml80
-rwxr-xr-xxt/00-compile-pm.t8
-rwxr-xr-xxt/01-compile-pl.t8
32 files changed, 6999 insertions, 3033 deletions
diff --git a/.gitignore b/.gitignore
index c0525c3..afb2f20 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,4 @@
/META.json
/MYMETA.yml
/MYMETA.json
+/lib/Travel/Status/DE/EFA/Services.pm
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..e1af5dd
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "ext/transport-apis"]
+ path = ext/transport-apis
+ url = https://github.com/public-transport/transport-apis.git
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 0000000..b1c1914
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,2 @@
+Birte Kristina Friesel <derf@chaosdorf.de>
+Birte Kristina Friesel <derf@finalrewind.org>
diff --git a/Build.PL b/Build.PL
index b135755..a5eeab4 100644
--- a/Build.PL
+++ b/Build.PL
@@ -8,28 +8,32 @@ Module::Build->new(
build_requires => {
'File::Slurp' => 0,
- 'Test::More' => 0,
- 'Test::Pod' => 0,
+ 'Test::More' => 0,
},
configure_requires => {
'Module::Build' => 0.40,
},
module_name => 'Travel::Status::DE::VRR',
- license => 'perl',
- requires => {
- 'perl' => '5.10.1',
- 'Carp' => 0,
- 'Class::Accessor' => 0,
- 'Getopt::Long' => 0,
- 'List::Util' => 0,
- 'LWP::UserAgent' => 0,
- 'LWP::Protocol::https' => 0,
- 'XML::LibXML' => 0,
+ license => 'perl',
+ recommends => {
+ 'Cache::File' => 0,
+ 'GIS::Distance' => 0,
},
- sign => 1,
+ requires => {
+ 'perl' => '5.10.1',
+ 'Carp' => 0,
+ 'Class::Accessor' => 0,
+ 'DateTime' => 0,
+ 'DateTime::Format::Strptime' => 0,
+ 'Getopt::Long' => 0,
+ 'JSON' => 0,
+ 'List::Util' => 0,
+ 'LWP::UserAgent' => 0,
+ 'LWP::Protocol::https' => 0,
+ },
+ sign => 1,
meta_merge => {
- resources => {
- repository => 'https://github.com/derf/Travel-Status-DE-VRR'
- }
+ resources =>
+ { repository => 'https://github.com/derf/Travel-Status-DE-VRR' }
},
)->create_build_script();
diff --git a/COPYING b/COPYING
index 67e99cd..4d4dae2 100644
--- a/COPYING
+++ b/COPYING
@@ -1,4 +1,4 @@
-Copyright (C) 2011-2014 Daniel Friesel <derf@finalrewind.org>
+Copyright (C) 2011-2025 Birte Kristina Friesel <derf@finalrewind.org>
All files in this distribution are licensed under the same terms as Perl
itself.
diff --git a/Changelog b/Changelog
index 921e4e3..69a5783 100644
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,168 @@
+Travel::Status::DE::VRR 3.13 - Thu Jun 19 2025
+
+ * EFA->new_p: Return $self in case of error so that clients can access
+ place_candidates and name_candidates. This behaviour was already
+ documented, but not implemented.
+
+Travel::Status::DE::VRR 3.12 - Wed Jun 18 2025
+
+ * Departure->id: Include the scheduled departure time. This fixes cases
+ where the trip details (stopseq) endpoint would randomly return
+ yesterday's details or no usable data at all.
+ * efa-m: Trip detail mode now only accepts trip IDs obtained from v3.12+
+
+Travel::Status::DE::VRR 3.11 - Mon Jun 16 2025
+
+ * efa-m: Show occupancy in trip details
+ * Trip->route: Provide occupancy data
+
+Travel::Status::DE::VRR 3.10 - Sun Jun 15 2025
+
+ * Stop: Add is_cancelled accessor
+ * Add BEG, RVV service definitions
+ * Breaking change: $efa->name_candidates and $efa->place_candidates now
+ return lists of Travel::Status::DE::EFA::Stop objects rather than
+ just strings.
+
+Travel::Status::DE::VRR 3.09 - Sun Mar 23 2025
+
+ * Trip: Add polyline accessor
+
+Travel::Status::DE::VRR 3.08 - Sat Feb 08 2025
+
+ * EFA->new_p: Return $efa instance in rejected promise if it was
+ rejected after parsing (e.g. due to ambiguous name/place parameter)
+
+Travel::Status::DE::VRR 3.07 - Mon Jan 27 2025
+
+ * Departure: Fix ->id accessor
+ * Add "Rolph" service definition
+
+Travel::Status::DE::VRR 3.06 - Sun Jan 05 2025
+
+ * EFA APIs know two types of stop IDs: numbers and codes. This module now
+ consistently refers to numeric stop IDs as "id_num" and stop ID codes as
+ "id_code".
+ * Departure: Rename ->stop_id to ->stop_id_num
+ * Stop: Rename ->id to ->id_num
+ * Stop: Rename ->stop_id to ->id_code
+ * Departure: Add ->id accessor.
+
+Travel::Status::DE::VRR 3.05 - Mon Dec 30 2024
+
+ * efa-m: add --raw-json option
+ * EFA stopFinder: add special handling for #results == 1
+
+Travel::Status::DE::VRR 3.04 - Sun Dec 22 2024
+
+ * EFA: Add NWL service definition
+
+Travel::Status::DE::VRR 3.03 - Sat Nov 09 2024
+
+ * efa-m: handle undefined platforms
+ * Trip->polyline: pass `fallback => 1` to return beeline between stops
+ if the backend did not provide a polyline.
+
+Travel::Status::DE::VRR 3.02 - Wed Oct 16 2024
+
+ * Stop: Add ar_delay, dep_delay, delay, stop_id accessos
+ * EFA: Fix place_candidates
+ * EFA: Add stop and stops functions
+ * EFA: Add static get_services method
+ * efa-m: Add -j / --with-jid option
+ * efa-m -Oa, -Ob, -Of: Show delays
+ * EFA, efa-m: Add stopfinder ("?foo") and stop search ("lat:lon") modes
+ * Add ...::Trip and ...::Info modules
+ * Info, Stop, Trip: Note that the API of these modules is not yet final
+ and may change between minor versions
+
+Travel::Status::DE::VRR 3.01 - Thu Oct 03 2024
+
+ * Fix Departure->route_interesting
+ * efa-m: Add --json option
+
+Travel::Status::DE::VRR 3.00 - Sun Sep 29 2024
+
+ * Drop XML::LibXML dependency
+ * New dependencies: DateTime::Format::Strptime, JSON
+ * Switch API language from XML to JSON
+ * Rename Travel::Status::DE::EFA::Result to Travel::Status::DE::EFA::Departure
+ * EFA: Add static "get_service_ids" function
+ * EFA: Add bwegt backend service
+ * EFA: Remove "identified_data" accessor (not supported by JSON backends)
+ * EFA: Remove static "get_efa_urls" function; use "get_service_ids" instead
+ * EFA->new, EFA->new_p: Add optional "cache" key
+ * Result/Departure: Add "hints" accessor
+ * Result/Departure: Remove "info" accessor; use "hints" instead
+ * Stop: Add "place", "full_name" and "occupancy" accessors
+ * Line: Add "number" accessor
+ * Stop: Remove "name_suf" accessor; use "name" instead
+ * efa-m: -Oa, -Ob, -Of: show per-stop occupancy, if available
+
+Travel::Status::DE::VRR 2.02 - Sun May 19 2024
+ * EFA->new: Deprecate "efa_url" option. Use "service" instead.
+ "efa_url" is still supported, just not documented anymore.
+ * EFA->new: Request departures in Europe/Berlin by default rather than
+ using the system time zone. Fixes EFA operation on machines using UTC.
+ * efa-m: Support "FULL" occupancy; change indicators from _ * ! to . o * !
+
+Travel::Status::DE::VRR 2.01 - Fri May 17 2024
+
+ * efa-m: Deprecate --efa-url in favour of --service. It is still supported,
+ just not documented anymore.
+ * EFA: Add new_p constructor for asynchronous operation with promises
+ * EFA: Add static get_service function
+
+Travel::Status::DE::VRR 2.00 - Sun Dec 03 2023
+
+ * New dependency: DateTime
+ * Result: Add datetime, sched_datetime, rt_datetime accessors.
+ * Result: Remove date, time, sched_date, sched_time accessors.
+ Use datetime->strftime('%H:%M') etc. instead. (BREAKING CHANGE)
+ * Stop: Add arr, dep accessors.
+ * Stop: Remove arr_date, arr_time, dep_date, dep_time accessors.
+ Use arr->strftime('%d.%m.%Y') etc. instead. (BREAKING CHANGE)
+ * efa-m: Remove --track-via option, its behaviour is now included in --via
+ (BREAKING CHANGE)
+
+Travel::Status::DE::VRR 1.24 - Sat Dec 02 2023
+
+ * EFA: Fix full_route creating route elements with invalid data
+ * efa-m: Fix -v / -V (as a consequence of the fix above)
+
+Travel::Status::DE::VRR 1.23 - Fri Nov 24 2023
+
+ * efa-m: Do not show free-text messages by default. Use the newly
+ introduced -Om option to show them
+ * efa-m: Show real-time departure rather than scheduled time + delay
+ * Result: Add train_type and train_name accessors
+
+Travel::Status::DE::VRR 1.22 - Sat Sep 02 2023
+
+ * Do not use now-deprecated smartmatch features
+
+Travel::Status::DE::VRR 1.21 - Sat Jul 22 2023
+
+ * Add service VRR3
+ * Update service URLs for VVO, VRN
+ * Remove discontinued services SVV, TLEM, VBL, Verbundlinie, VOR
+
+Travel::Status::DE::VRR 1.20 - Sun Mar 28 2021
+
+ * efa-m, EFA: Accept "stopID" stop type
+ * EFA: Add proximity_search (useProxFootSearch) option
+
+Travel::Status::DE::VRR 1.19 - Sat Mar 27 2021
+
+ * Result: Add ->train_no accessor
+
+Travel::Status::DE::VRR 1.18 - Thu Mar 25 2021
+
+ * EFA: "place" is now optional
+ * Result: Add ->occupancy accessor
+ * efa-m: The "place" argument is now optional
+ * efa-m: Show expected vehicle occupancy, if available
+
Travel::Status::DE::VRR 1.17 - Sat May 02 2020
* Add MVV (Münchner Verkehrs- und Tarifverbund) and VAG (Freiburger
diff --git a/Dockerfile b/Dockerfile
index fdd0a85..1b1d2c1 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,7 @@
FROM perl:5.30-slim
COPY bin/ /app/bin/
+COPY ext/ /app/ext/
COPY lib/ /app/lib/
COPY Build.PL cpanfile* /app/
@@ -9,12 +10,12 @@ WORKDIR /app
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
- && apt-get -y --no-install-recommends install ca-certificates curl gcc libc6-dev libssl1.1 libssl-dev libxml2 libxml2-dev make zlib1g-dev \
+ && apt-get -y --no-install-recommends install ca-certificates curl gcc libc6-dev libssl1.1 libssl-dev make zlib1g-dev \
&& cpanm -n --no-man-pages --installdeps . \
&& perl Build.PL \
&& perl Build \
&& rm -rf ~/.cpanm \
- && apt-get -y purge curl gcc libc6-dev libssl-dev libxml2-dev make zlib1g-dev \
+ && apt-get -y purge curl gcc libc6-dev libssl-dev make zlib1g-dev \
&& apt-get -y autoremove \
&& apt-get -y clean \
&& rm -rf /var/cache/apt/* /var/lib/apt/lists/*
diff --git a/README.md b/README.md
index 86b8680..3822dea 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,16 @@
# efa-m - Commandline Public Transit Departure Monitor
-efa-m is a commandline client and Perl module for EFA public transit departure
+**efa-m** is a commandline client and Perl module for EFA public transit departure
interfaces such as [efa.vrr.de](https://efa.vrr.de/vrr/XSLT_DM_REQUEST). See
the [Travel::Status::DE::VRR
homepage](https://finalrewind.org/projects/Travel-Status-DE-VRR/) for details.
## Installation
-efa-m is available as
-[perl-travel-status-de-vrr-git](https://aur.archlinux.org/packages/perl-travel-status-de-vrr-git/)
-in the archlinux User Repository (AUR).
+You have five installation options:
-For other distributions, you have four installation options:
-
-* Nightly `.deb` builds for Debian-based distributions
+* `.deb` releases for Debian-based distributions
+* finalrewind.org APT repository for Debian-based distributions
* Installing the latest release from CPAN
* Installation from source
* Using a Docker image
@@ -22,43 +19,61 @@ Except for Docker, __efa-m__ is available in your PATH after installation. You
can run `efa-m --version` to verify this. Documentation is available via
`man efa-m`.
-### Nightly Builds for Debian
+### Release Builds for Debian
[lib.finalrewind.org/deb](https://lib.finalrewind.org/deb) provides Debian
-packages of both development and release versions. Note that these are not part
-of the official Debian repository and are not covered by its quality assurance
-process.
+packages of all release versions. Note that these are not part of the official
+Debian repository and are not covered by its quality assurance process.
To install the latest release, run:
```
wget https://lib.finalrewind.org/deb/libtravel-status-de-vrr-perl_latest_all.deb
-sudo dpkg -i libtravel-statusg-de-vrr-perl_latest_all.deb
-sudo apt --fix-broken install
+sudo apt install ./libtravel-status-de-vrr-perl_latest_all.deb
rm libtravel-status-de-vrr-perl_latest_all.deb
```
-For a (possibly broken) development snapshot of the Git master branch, run:
+Uninstallation works as usual:
```
-wget https://lib.finalrewind.org/deb/libtravel-status-de-vrr-perl_dev_all.deb
-sudo dpkg -i libtravel-status-de-vrr-perl_dev_all.deb
-sudo apt --fix-broken install
-rm libtravel-status-de-vrr-perl_dev_all.deb
+sudo apt remove libtravel-status-de-vrr-perl
```
-Note that dpkg, unlike apt, does not automatically install missing
-dependencies. If a dependency is not satisfied yet, `dpkg -i` will complain
-about unmet dependencies and bail out. `apt --fix-broken install` installs
-these dependencies and also silently finishes the Travel::Status::DE::VRR
-installation.
+### finalrewind.org APT repository
-Uninstallation works as usual:
+[lib.finalrewind.org/apt](https://lib.finalrewind.org/apt) provides an APT
+repository with Debian packages of the latest release versions. Note that this
+is not a Debian repository; it is operated under a best-effort SLA and if you
+use it you will have to trust me not to screw up your system with bogus
+packages. Also, note that the packages are not part of the official Debian
+repository and are not covered by its quality assurance process.
+
+To set up the repository and install the latest Travel::Status::DE::VRR
+release, run:
+
+```
+curl -s https://finalrewind.org/apt.asc | sudo tee /etc/apt/trusted.gpg.d/finalrewind.asc
+echo 'deb https://lib.finalrewind.org/apt stable main' | sudo tee /etc/apt/sources.list.d/finalrewind.list
+sudo apt update
+sudo apt install libtravel-status-de-vrr-perl
+```
+
+Afterwards, `apt update` and `apt upgrade` will automatically install new
+Travel::Status::DE::VRR releases.
+
+Uninstallation of Travel::Status::DE::VRR works as usual:
```
sudo apt remove libtravel-status-de-vrr-perl
```
+To remove the APT repository from your system, run:
+
+```
+sudo rm /etc/apt/trusted.gpg.d/finalrewind.asc \
+ /etc/apt/sources.list.d/finalrewind.list
+```
+
### Installation from CPAN
Travel::Status::DE::VRR releases are published on the Comprehensive Perl
@@ -70,7 +85,6 @@ pkg-config and a C compiler) installed. You will also need the following
libraries with development headers:
* libssl
-* libxml2
* zlib
Now, use a tool of your choice to install the module. Minimum working example:
@@ -113,12 +127,16 @@ sudo ./Build install
If you are using the Git repository, use the following commands:
```
+git submodule update --init
./Build
./Build manifest
./Build test
sudo ./Build install
```
+Note that system-wide installation does not have a well-defined uninstallation
+procedure.
+
If you do not have superuser rights or do not want to perform a system-wide
installation, you may leave out `Build install` and use **efa-m** from the
current working directory.
diff --git a/bin/efa-m b/bin/efa-m
index 326d2cb..0f7fb44 100755
--- a/bin/efa-m
+++ b/bin/efa-m
@@ -4,28 +4,38 @@ use warnings;
use 5.010;
use utf8;
-no if $] >= 5.018, warnings => 'experimental::smartmatch';
-
-our $VERSION = '1.17';
+our $VERSION = '3.13';
binmode( STDOUT, ':encoding(utf-8)' );
-use Encode qw(decode);
+use Encode qw(decode);
use Getopt::Long qw(:config no_ignore_case bundling);
-use List::Util qw(first max);
+use JSON;
+use List::Util qw(first max none);
use Travel::Status::DE::EFA;
-my $efa_url = 'https://efa.vrr.de/vrr/XSLT_DM_REQUEST';
+my $service = 'VRR';
+my $efa_url;
my $efa_encoding;
-my ( $date, $time, $input_type, $list_lines, $offset, $relative_times );
-my ($full_routes);
-my ( $filter_via, $track_via );
-my ( $timeout, $developer_mode );
-my ( @grep_lines, @grep_platforms, @grep_mots );
-my ( %edata, @edata_pre );
-my ( $list_services, $service, $discover_and_print, $discover );
+my $use_cache = 1;
+my $cache;
+my ( $json_output, $raw_json_output );
+my ( $date, $time, $input_type, $list_lines, $offset, $relative_times );
+my ( $full_routes, $filter_via, $show_jid );
+my ( $timeout, $developer_mode );
+my ( @grep_lines, @grep_platforms, @grep_mots );
+my ( %edata, @edata_pre );
+my ( $list_services, $discover_and_print, $discover );
my $efa;
+my %occupancy_map = (
+ MANY_SEATS => '.',
+ FEW_SEATS => 'o',
+ STANDING_ONLY => '*',
+ FULL => '!',
+ unknown => '?',
+);
+
@ARGV = map { decode( 'UTF-8', $_ ) } @ARGV;
GetOptions(
@@ -33,6 +43,7 @@ GetOptions(
'd|date=s' => \$date,
'D|discover' => \$discover,
'h|help' => sub { show_help(0) },
+ 'j|with-jid' => \$show_jid,
'l|line=s@' => \@grep_lines,
'L|linelist' => \$list_lines,
'list' => \$list_services,
@@ -46,9 +57,12 @@ GetOptions(
'timeout=i' => \$timeout,
'u|efa-url=s' => \$efa_url,
'v|via=s' => \$filter_via,
- 'V|track-via=s' => sub { $filter_via = $track_via = $_[1] },
- 'version' => \&show_version,
+ 'V|track-via=s' => \$filter_via,
+ 'cache!' => \$use_cache,
+ 'json' => \$json_output,
+ 'raw-json' => \$raw_json_output,
'devmode' => \$developer_mode,
+ 'version' => \&show_version,
) or show_help(1);
@@ -56,38 +70,87 @@ if ($list_services) {
show_services();
}
-if ( @ARGV != 2 ) {
+if ( @ARGV < 1 or @ARGV > 2 ) {
show_help(1);
}
+if ($use_cache) {
+ my $cache_path = ( $ENV{XDG_CACHE_HOME} // "$ENV{HOME}/.cache" )
+ . '/Travel-Status-DE-EFA';
+ eval {
+ require Cache::File;
+ $cache = Cache::File->new(
+ cache_root => $cache_path,
+ default_expires => '90 seconds',
+ lock_level => Cache::File::LOCK_LOCAL(),
+ );
+ };
+ if ($@) {
+ $cache = undef;
+ }
+}
+
# --line=foo,bar support
@edata_pre = split( qr{,}, join( q{,}, @edata_pre ) );
@grep_lines = split( qr{,}, join( q{,}, @grep_lines ) );
@grep_mots = split( qr{,}, join( q{,}, @grep_mots ) );
@grep_platforms = split( qr{,}, join( q{,}, @grep_platforms ) );
-my ( $place, $input ) = @ARGV;
+my ( $place, $input, $coord, $stopseq, $stopfinder );
+
+if ( @ARGV == 1 ) {
+ if ( $ARGV[0]
+ =~ m{ ^ ([^@]*) @ ([^@]*) [(] ([^T]*) T ([^)]*) [)] (.*) $ }x )
+ {
+ $stopseq = {
+ stateless => $1,
+ stop_id => $2,
+ date => $3,
+ time => $4,
+ key => $5
+ };
+ }
+ elsif ( $ARGV[0] =~ m{ ^ [?] (?<name> .*) $ }x ) {
+ $stopfinder = {
+ name => $+{name},
+ };
+ }
+ elsif ( $ARGV[0] =~ m{ ^ (?<lat> [0-9.]+ ) : (?<lon> [0-9].+ ) $ }x ) {
+ $coord = {
+ lat => $+{lat},
+ lon => $+{lon},
+ };
+ }
+ else {
+ $input = $ARGV[0];
+ }
+}
+else {
+ ( $place, $input ) = @ARGV;
+}
-if ( $input =~ s{ ^ (?<type> address|poi|stop) : }{}x ) {
+if ( $input and $input =~ s{ ^ (?<type> address|poi|stop|stopID) : }{}x ) {
$input_type = $+{type};
}
for my $efield (@edata_pre) {
- given ($efield) {
- when ('a') { $edata{route_after} = 1; $full_routes = 1 }
- when ('b') { $edata{route_before} = 1; $full_routes = 1 }
- when ('f') { $edata{fullroute} = 1; $full_routes = 1 }
- when ('r') { $edata{route} = 1; $full_routes = 1 }
- default { $edata{$efield} = 1 }
- }
+ if ( $efield eq 'a' ) { $edata{route_after} = 1; $full_routes = 1 }
+ elsif ( $efield eq 'b' ) { $edata{route_before} = 1; $full_routes = 1 }
+ elsif ( $efield eq 'f' ) { $edata{fullroute} = 1; $full_routes = 1 }
+ elsif ( $efield eq 'r' ) { $edata{route} = 1; $full_routes = 1 }
+ elsif ( $efield eq 'i' ) { $edata{info} = 1 }
+ elsif ( $efield eq 'm' ) { $edata{messages} = 1 }
+ else { $edata{$efield} = 1 }
}
if ($filter_via) {
$full_routes = 1;
}
-if ($service) {
- my $service_ref = first { lc( $_->{shortname} ) eq lc($service) }
- Travel::Status::DE::EFA::get_efa_urls();
+if ($efa_url) {
+ $service = undef;
+}
+elsif ($service) {
+ my $service_ref = Travel::Status::DE::EFA::get_service($service);
if ( not $service_ref ) {
printf STDERR (
"Error: Unknown service '%s'. See 'efa-m --list' for a "
@@ -96,20 +159,25 @@ if ($service) {
);
exit 1;
}
- $efa_url = $service_ref->{url};
$efa_encoding = $service_ref->{encoding};
+ $efa_url = undef;
}
-sub new_efa_by_url {
- my ($url) = @_;
+sub new_efa {
+ my ( $s, $u ) = @_;
my $res = Travel::Status::DE::EFA->new(
+ service => $s,
+ efa_url => $u,
+ cache => $cache,
date => $date,
developer_mode => $developer_mode,
- efa_url => $url,
efa_encoding => $efa_encoding,
full_routes => $full_routes,
place => $place,
name => $input,
+ coord => $coord,
+ stopfinder => $stopfinder,
+ stopseq => $stopseq,
time => $time,
type => $input_type,
timeout => $timeout,
@@ -121,7 +189,7 @@ sub new_efa_by_url {
sub show_help {
my ($code) = @_;
- print "Usage: efa-m [-d <dd.mm.yyyy>] [-t <hh:mm>] <city> <station>\n"
+ print "Usage: efa-m [-d <dd.mm.yyyy>] [-t <hh:mm>] <stop>\n"
. "See also: man efa-m\n";
exit $code;
@@ -129,8 +197,10 @@ sub show_help {
sub show_services {
printf( "%-45s %-14s %s\n\n", 'service', 'abbr. (-s)', 'url (-u)' );
- for my $service ( Travel::Status::DE::EFA::get_efa_urls() ) {
- printf( "%-45s %-14s %s\n", @{$service}{qw(name shortname url)} );
+ for my $shortname ( Travel::Status::DE::EFA::get_service_ids() ) {
+ my $service = Travel::Status::DE::EFA::get_service($shortname);
+ printf( "%-45s %-14s %s\n",
+ $service->{name}, $shortname, $service->{url} );
}
exit 0;
@@ -142,6 +212,14 @@ sub show_version {
exit 0;
}
+sub format_delay {
+ my ( $delay, $len ) = @_;
+ if ( $delay and $len ) {
+ return sprintf( "(%+${len}d)", $delay );
+ }
+ return q{};
+}
+
sub format_route {
my (@route) = @_;
@@ -152,25 +230,60 @@ sub format_route {
say 'BUG';
next;
}
- if ( not defined $stop->arr_time ) {
- $output .= sprintf( " %5s %40s %s\n",
- $stop->dep_time, $stop->name, $stop->platform, );
+ my $occupancy
+ = $stop->occupancy ? format_occupancy( $stop->occupancy ) : q{ };
+ my $delay = q{ };
+ if ( $stop->delay ) {
+ $delay = sprintf( '(%+3d)', $stop->delay );
}
- elsif ( not defined $stop->dep_time ) {
- $output .= sprintf( "%5s %40s %s\n",
- $stop->arr_time, $stop->name, $stop->platform, );
+ if ( $stop->is_cancelled ) {
+ $output .= sprintf(
+ " --:-- %s %s %35s %s\n",
+ $delay, $occupancy, $stop->full_name, $stop->platform // q{},
+ );
}
- elsif ( $stop->arr_time eq $stop->dep_time ) {
- $output .= sprintf( " %5s %40s %s\n",
- $stop->dep_time, $stop->name, $stop->platform, );
+ elsif ( defined $stop->arr and defined $stop->dep ) {
+ if ( $stop->arr->epoch == $stop->dep->epoch ) {
+ $output .= sprintf(
+ " %5s %s %s %35s %s\n",
+ $stop->arr->strftime('%H:%M'),
+ $delay, $occupancy, $stop->full_name,
+ $stop->platform // q{},
+ );
+ }
+ else {
+ $output .= sprintf(
+ "%5s → %5s %s %s %35s %s\n",
+ $stop->arr->strftime('%H:%M'),
+ $stop->dep->strftime('%H:%M'),
+ $delay,
+ $occupancy,
+ $stop->full_name,
+ $stop->platform // q{},
+ );
+ }
}
- else {
+ elsif ( defined $stop->arr ) {
$output .= sprintf(
- "%5s → %5s %40s %s\n",
- $stop->arr_time, $stop->dep_time,
- $stop->name, $stop->platform,
+ "%5s %s %s %35s %s\n",
+ $stop->arr->strftime('%H:%M'),
+ $delay, $occupancy, $stop->full_name, $stop->platform,
);
}
+ elsif ( defined $stop->dep ) {
+ $output .= sprintf(
+ " %5s %s %s %35s %s\n",
+ $stop->dep->strftime('%H:%M'),
+ $delay, $occupancy, $stop->full_name, $stop->platform,
+ );
+ }
+ elsif ( $stop->full_name ) {
+ $output .= sprintf( " %s %s %35s %s\n",
+ $delay, $occupancy, $stop->full_name, $stop->platform, );
+ }
+ else {
+ $output .= "?\n";
+ }
}
return $output;
}
@@ -190,12 +303,12 @@ sub display_result {
for my $line (@lines) {
- if ( length( $line->[5] ) ) {
- $line->[5] =~ tr{\n\x0d}{ }s;
- chomp $line->[5];
+ if ( $edata{messages} and $line->[5]->hints ) {
print "\n";
- for my $info_line ( split( qr{\n}, $line->[5] ) ) {
- say "# ${info_line}";
+ for my $hint ( $line->[5]->hints ) {
+ $hint =~ tr{\n\x0d}{ }s;
+ chomp $hint;
+ say "# ${hint}";
}
}
@@ -212,23 +325,96 @@ sub display_result {
return;
}
+sub show_coord {
+ my $max_len = max map { length( $_->full_name ) } $efa->results;
+ for my $stop ( $efa->results ) {
+ printf(
+ "%5.1f km %-${max_len}s %s\n",
+ $stop->distance_m * 1e-3,
+ $stop->full_name, $stop->id_code
+ );
+ }
+}
+
+sub show_stopfinder {
+ my $max_len = max map { length( $_->full_name ) } $efa->results;
+ for my $stop ( $efa->results ) {
+ printf( "%-${max_len}s %s %s\n",
+ $stop->full_name, $stop->id_num, $stop->id_code );
+ }
+}
+
+sub show_stopseq {
+ my $trip = $efa->result;
+
+ printf( "%s %s → %s\n", $trip->type, $trip->line // q{}, $trip->dest_name );
+
+ printf(
+ "Fahrt %s am %s\n",
+ $trip->number || $stopseq->{stateless},
+ ( $trip->route )[0]->sched_dep->strftime('%d.%m.%Y'),
+ );
+ say q{};
+
+ my $occupancy_len = 0;
+ my $delay_len = 0;
+ my $inner_delay_len = 0;
+ my $max_delay = max map { abs( $_->delay // 0 ) } $trip->route;
+ if ($max_delay) {
+ $inner_delay_len = length($max_delay) + 1;
+ $delay_len = length( sprintf( '(%+d)', $max_delay ) ) + 1;
+ }
+ if ( first { $_->occupancy } $trip->route ) {
+ $occupancy_len = 2;
+ }
+
+ if ( first { $_->is_cancelled } $trip->route and $delay_len < 3 ) {
+ $delay_len = 3;
+ }
+
+ for my $stop ( $trip->route ) {
+ printf(
+ "%s → %s%${delay_len}s %-${occupancy_len}s%s (%s) %s\n",
+ $stop->arr ? $stop->arr->strftime('%H:%M')
+ : q{ },
+ $stop->dep ? $stop->dep->strftime('%H:%M')
+ : q{ },
+ $stop->is_cancelled ? 'XX'
+ : (
+ $stop->delay
+ ? sprintf( " (%+${inner_delay_len}d)", $stop->delay )
+ : q{}
+ ),
+ $stop->occupancy ? format_occupancy( $stop->occupancy ) : q{},
+ $stop->full_name,
+ $stop->niveau,
+ $stop->platform
+ );
+ }
+}
+
sub show_lines {
my @output;
for my $l ( $efa->lines ) {
- if ( ( @grep_lines and not( $l->name ~~ \@grep_lines ) )
- or ( @grep_mots and not( $l->mot_name ~~ \@grep_mots ) ) )
+ if ( ( @grep_lines and none { $l->number eq $_ } @grep_lines )
+ or ( @grep_mots and none { $l->mot_name eq $_ } @grep_mots ) )
{
next;
}
- if ( @grep_mots and not( $l->mot_name ~~ \@grep_mots ) ) {
+ if ( @grep_mots and none { $l->mot_name eq $_ } @grep_mots ) {
next;
}
- push( @output,
- [ $l->type, $l->name, $l->direction // q{}, q{}, $l->route // q{} ]
+ push(
+ @output,
+ [
+ $l->type, $l->number,
+ $l->direction // q{}, q{},
+ $l->route // q{}
+ ]
);
}
@@ -237,9 +423,35 @@ sub show_lines {
return;
}
+sub format_occupancy {
+ my ($occupancy) = @_;
+
+ return $occupancy_map{$occupancy} // $occupancy_map{unknown};
+}
+
sub show_results {
my @output;
+ my $delay_len = 0;
+ my $delay_fmt = 0;
+ for my $d ( $efa->results ) {
+ if ( $d->delay ) {
+ $delay_len = max( $delay_len, length( $d->delay ) + 1 );
+ }
+ }
+ if ($delay_len) {
+ $delay_fmt = $delay_len + 3;
+ }
+
+ if ( scalar $efa->stops > 1 ) {
+ for my $stop ( $efa->stops ) {
+ say $stop->full_name;
+ }
+ }
+ elsif ( $efa->stop->full_name ) {
+ say $efa->stop->full_name;
+ }
+
for my $d ( $efa->results ) {
my @output_line;
@@ -247,18 +459,14 @@ sub show_results {
my $dtime = (
$relative_times
? sprintf( '%2d min', $d->countdown )
- : $d->sched_time
+ : $d->datetime->strftime('%H:%M')
);
- if ( $d->platform_db ) {
- $platform .= ' (DB)';
- }
-
if (
- ( @grep_lines and not( $d->line ~~ \@grep_lines ) )
- or ( @grep_mots and not( $d->mot_name ~~ \@grep_mots ) )
+ ( @grep_lines and none { $d->line eq $_ } @grep_lines )
+ or ( @grep_mots and none { $d->mot_name eq $_ } @grep_mots )
or ( @grep_platforms
- and not( $platform ~~ \@grep_platforms ) )
+ and none { $platform eq $_ } @grep_platforms )
or ( $offset and $d->countdown < $offset )
or ( $filter_via
and
@@ -273,28 +481,40 @@ sub show_results {
next;
}
else {
- $dtime .= ' CANCELED';
+ $dtime = '--:--';
}
}
- elsif ($track_via) {
+ elsif ($filter_via) {
my $via = first { $_->name =~ m{$filter_via}io } $d->route_post;
- $dtime .= ' → ' . $via->arr_time;
+ $dtime
+ .= ' → '
+ . $via->arr->clone->add( minutes => $d->delay // 0 )
+ ->strftime('%H:%M');
}
if ( $d->delay ) {
- if ($relative_times) {
- $dtime .= ' (+' . $d->delay . ')';
- }
- else {
- $dtime .= ' +' . $d->delay;
- }
+ $dtime .= ' ' . format_delay( $d->delay, $delay_len );
}
- @output_line
- = ( $dtime, $platform, $d->line, q{}, $d->destination, $d->info );
+ my $line = $d->line;
+ if ( ( length($line) > 10 or not $line )
+ and $d->train_type
+ and $d->train_no )
+ {
+ $line = $d->train_type . ' ' . $d->train_no;
+ }
+
+ @output_line = ( $dtime, $platform, $line, q{}, $d->destination, $d );
+
+ if ($show_jid) {
+ $output_line[2] .= ' ' . $d->id;
+ }
if ( $edata{route} ) {
$output_line[3]
- = join( q{ }, map { $_->name_suf } $d->route_interesting );
+ = join( q{ }, map { $_->name } $d->route_interesting );
+ }
+ elsif ( $d->occupancy ) {
+ $output_line[3] = format_occupancy( $d->occupancy );
}
if ( $edata{fullroute} ) {
@@ -315,20 +535,33 @@ sub show_results {
display_result(@output);
+ if ( $edata{info} ) {
+ for my $info ( $efa->infos ) {
+ say q{};
+ if ( $info->subject and $info->subtitle ne $info->subject ) {
+ printf( "# %s\n%s\n", $info->subtitle, $info->subject );
+ }
+ else {
+ printf( "# %s\n", $info->subtitle );
+ }
+ }
+ }
+
return;
}
if ( $discover or $discover_and_print ) {
- for my $service_ref ( Travel::Status::DE::EFA::get_efa_urls() ) {
- $efa = new_efa_by_url( $service_ref->{url} );
+ for my $shortname ( Travel::Status::DE::EFA::get_service_ids() ) {
+ $efa = new_efa($shortname);
if ( $efa and not $efa->errstr ) {
if ($discover_and_print) {
last;
}
+ my $service_ref = Travel::Status::DE::EFA::get_service($shortname);
printf(
"%s / %s (%s)\n -> efa-m -s %s %s\n\n",
- @{$service_ref}{qw(name shortname url shortname)},
- join( q{ }, map { "'$_'" } @ARGV ),
+ $service_ref->{name}, $shortname, $service_ref->{url},
+ $shortname, join( q{ }, map { "'$_'" } @ARGV ),
);
}
}
@@ -337,24 +570,48 @@ if ( $discover or $discover_and_print ) {
}
}
-$efa = new_efa_by_url($efa_url);
+$efa = new_efa( $service, $efa_url );
if ( my $err = $efa->errstr ) {
say STDERR "Request error: ${err}";
if ( $efa->place_candidates ) {
say 'You might want to try one of the following places:';
- say join( "\n", $efa->place_candidates );
+ for my $candidate ( $efa->place_candidates ) {
+ printf( "%d %s\n", $candidate->id_num, $candidate->name );
+ }
}
elsif ( $efa->name_candidates ) {
say 'You might want to try one of the following names:';
- say join( "\n", $efa->name_candidates );
+ for my $candidate ( $efa->name_candidates ) {
+ printf( "%d %s\n", $candidate->id_num, $candidate->name );
+ }
}
exit 2;
}
-if ($list_lines) {
+if ($json_output) {
+ if ($stopseq) {
+ say JSON->new->convert_blessed->encode( $efa->result );
+ }
+ else {
+ say JSON->new->convert_blessed->encode( [ $efa->results ] );
+ }
+}
+elsif ($raw_json_output) {
+ say JSON->new->convert_blessed->encode( $efa->{response} );
+}
+elsif ($coord) {
+ show_coord();
+}
+elsif ($stopfinder) {
+ show_stopfinder();
+}
+elsif ($stopseq) {
+ show_stopseq();
+}
+elsif ($list_lines) {
show_lines();
}
else {
@@ -365,58 +622,117 @@ __END__
=head1 NAME
-efa-m - Unofficial interface to the efa.vrr.de departure monitor
+efa-m - Unofficial interface to the efa.vrr.de departure and trip monitor
=head1 SYNOPSIS
-B<efa-m> [B<-Lr>] [B<-d> I<dd.mm.yyyy>] [B<-t> I<hh:mm>]
-[B<-l> I<lines>] [B<-p> I<platforms>] [B<-u> I<url>]
-I<city> [I<type>B<:>]I<name>
+B<efa-m> [B<-jLr>] [B<-d> I<dd.mm.yyyy>] [B<-t> I<hh:mm>]
+[B<-l> I<lines>] [B<-p> I<platforms>] [B<-s> I<service>]
+[I<city>] [I<type>B<:>]I<name>
+
+B<efa-m> [B<-s> I<service>] B<?>I<query>|I<lat>B<:>I<lon>
+
+B<efa-m> [B<-s> I<service>] I<tripid>
=head1 VERSION
-version 1.17
+version 3.13
=head1 DESCRIPTION
-B<efa-m> lists scheduled tram, bus and train departures at the location I<name>
-in I<city>. Realtime data (i.e. delays) is included if available, it's
-visible in the output as a "+x" remark (meaning a delay of x minutes).
+B<efa-m> is an interface to EFA public transport services.
+
+It can serve as a departure monitor, request details about a specific
+trip/journey, and look up public transport stops by name or geolocation.
+The operating mode depends on the contents of its mandatory argument.
+
+=head2 Departure Monitor (I<name>)
+
+Shows departures at I<name> or I<city> I<name>; I<name> may also be a stop ID
+number or code. For each departure, B<efa-m> shows
+
+=over
+
+=item * estimated departure time (including delay, if available),
+
+=item * delay in minutes,
+
+=item * platform,
+
+=item * line,
+
+=item * expected occupation (range . o * !, if available), and
+
+=item * destination.
+
+=back
+
+If I<city> is specified, I<name> refers to a location within I<city>.
+Otherwise, I<name> must be self-contained. I.e., both C<< efa-m Essen Hbf >>
+and C<< efa-m "Essen Hbf" >> are valid. Note, however, than C<< efa-m E Hbf >>
+works, but C<< efa-m "E Hbf" >> does not.
By default, I<name> refers to a stop, this can be changed by specifying
I<type>. Supported types are B<address> and B<poi> (point of interest).
+=head2 Location Search (B<?>I<query>|I<lat>B<:>I<lon>)
+
+List stops that match I<query> or that are located in the vicinity of
+I<lat>B<:>I<lon> geocoordinates. In addition to stop names, the output also
+includes stop ID codes (both modes) and numbers (only available in I<query>
+mode).
+
+=head2 Trip Details (I<JourneyID>)
+
+List trip information including arrival and departure time, name, and platform
+of each stop on the trip's route.
+
=head1 OPTIONS
+Values in brackets indicate options that only apply to the corresponding
+operating mode(s).
+
=over
-=item B<-A>, B<--auto-url>, B<--discover-and-print>
+=item B<-A>, B<--auto-url>, B<--discover-and-print> (monitor)
-Probe all known EFA entry points for the specified stop. Print the first
-result which was not an error.
+Probe all known EFA services for the specified stop. Print the first result
+which was not an error.
Note that this may take a while and will not necessarily return the best
result. Also, using thi option by default is not recommended, as it puts EFA
services under considerable additional load.
-=item B<-d>, B<--date> I<dd.mm.yyyy>
+=item B<-d>, B<--date> I<dd.mm.yyyy> (monitor)
Show departures for I<date> instead of today.
May also be specified as I<dd.mm.>
-=item B<-D>, B<--discover>
+=item B<-D>, B<--discover> (monitor)
+
+Probe all known EFA services for the specified stop. Print the URLs and names
+of all services which did not return an error.
+
+=item B<-j>, B<--with-jid> (monitor)
+
+Show journey ID for each departure.
+The ID can be used to query details with a subsequent B<efa-m> invocation
+(trip details mode).
+
+=item B<--json>
-Probe all known EFA entry points for the specified stop. Print the URLs and
-names of all entry points which did not return an error.
+Print result(s) as JSON and exit. This is a dump of internal data structures
+and not guaranteed to remain stable between minor versions. Please use the
+Travel::Status::DE::EFA(3pm) module if you need a proper API.
-=item B<-L>, B<--linelist>
+=item B<-L>, B<--linelist> (monitor)
Do not show departures. Instead, list all lines serving the specified place.
Note that this information may be incomplete -- only lines which are in
service either at the time of the B<efa-m> call or at the time specifed
using B<--date> and B<--time> are guaranteed to be included.
-=item B<-l>, B<--line> I<lines>
+=item B<-l>, B<--line> I<lines> (monitor)
Only show departures of I<lines> (comma-separatad list, option may be
repeated)
@@ -426,7 +742,7 @@ repeated)
List supported EFA services with their URLs (see B<-u>) and abbreviations (see
B<-s>).
-=item B<-m>, B<--mot> I<motlist>
+=item B<-m>, B<--mot> I<motlist> (monitor)
Only show departures whose type appears in I<motlist> (comma-separated list,
this option may be repeated).
@@ -435,11 +751,11 @@ The following departure types ("modes of transport") are supported:
zug, s-bahn, u-bahn, stadtbahn, tram, stadtbus, regionalbus, schnellbus,
seilbahn, schiff, ast, sonstige
-=item B<-o>, B<--offset> I<minutes>
+=item B<-o>, B<--offset> I<minutes> (monitor)
Ignore departures which are less than I<minutes> from now.
-=item B<-O>, B<--output> I<outputtypes>
+=item B<-O>, B<--output> I<outputtypes> (monitor)
For each result, show additional information as specified by I<outputtypes>.
I<outputtypes> is a comma-separated list, the B<-O>/B<--output> option may
@@ -465,20 +781,37 @@ requested station.
Show each departure's full route (timestamps and stop names) before and
after the requested station.
+=item i / info
+
+Show station-specific information messages. These typically relate to
+construction work, broken elevators or escalators, or special announcements
+for large-scale events.
+
=item r / route
Show up to three stops between the requested station and the departure's
destination. B<efa-m> tries to display the three most important stops,
however these are heuristically determined and may not be optimal.
+=item m / messages
+
+Show free-text messages associated with individual departures. These can
+include generic information such is bicycle transportation options or Wi-Fi
+availability, delay reasons, and more.
+
=back
-=item B<-p>, B<--platform> I<platforms>
+=item B<-p>, B<--platform> I<platforms> (monitor)
Only show departures at I<platforms> (comma-separated list, option may be
repeated). Note that the C<< Bstg. >> / C<< Gleis >> prefix must be omitted.
-=item B<-r>, B<--relative>
+=item B<--raw-json>
+
+Print unprocessed EFA response as JSON and exit.
+Useful for debugging and development purposes.
+
+=item B<-r>, B<--relative> (monitor)
Show relative departure times in minutes (i.e. the time difference between
the departure and the time of the request). In this case, realtime data is
@@ -486,36 +819,24 @@ already included.
=item B<-s>, B<--service> I<name>
-Short name of the EFA entry point. See Travel::Status::DE::EFA(3pm) and the
+Short name of the EFA service. See Travel::Status::DE::EFA(3pm) and the
B<--list> option for a list of services.
-=item B<-t>, B<--time> I<hh:mm>
+=item B<-t>, B<--time> I<hh:mm> (monitor)
Show departures starting at I<time> instead of now.
-=item B<-u>, B<--efa-url> I<url>
-
-URL to the EFA entry point, defaults to
-L<http://efa.vrr.de/vrr/XSLT_DM_REQUEST>. Depending on your location, some
-I<url>s may contain more specific data than others. See
-Travel::Status::DE::EFA(3pm) and the B<--list> option for alternatives.
-
=item B<--timeout> I<seconds>
Set timeout for HTTP requests. Default: 10 seconds. Set to 0 or a negative
value to disable it.
-=item B<-v>, B<--via> I<station>
+=item B<-v>, B<--via> I<station> (monitor)
-Only show trains serving I<station> after the requseted stop. I<station>
-is matched against the "I<city> I<stop>" fields in each line's route.
-Regular expressions are also supported.
-
-=item B<-V>, B<--track-via> I<station>
-
-Lik B<--via>: Only show trains serving I<station> after the requseted stop.
-Also, show the arrival time at I<station> after the departure time at the
-current stop.
+Only show trains serving I<station> after the requseted stop, and show the
+arrival time at I<station> after the departure time at the current stop.
+I<station> is matched against the "I<city> I<stop>" fields in each line's
+route. Regular expressions are also supported.
=item B<--version>
@@ -542,8 +863,6 @@ None.
=item * Travel::Status::DE::EFA(3pm)
-=item * XML::LibXML(3pm)
-
=back
=head1 BUGS AND LIMITATIONS
@@ -555,9 +874,17 @@ choose the appropriate EFA URL for these by itself. In these cases, you should
find an appropriate EFA service using the B<-D>/B<--discover> option and then
use B<-s> I<service> when making requests.
+=over
+
+=item * EFA does not provide real-time data for the routes of requested
+departures. Hence, B<--via> estimates the arrival time from scheduled
+departure and departure delay
+
+=back
+
=head1 AUTHOR
-Copyright (C) 2011-2020 by Daniel Friesel E<lt>derf@finalrewind.orgE<gt>
+Copyright (C) 2011-2023 Birte Kristina Friesel E<lt>derf@finalrewind.orgE<gt>
=head1 LICENSE
diff --git a/cpanfile b/cpanfile
new file mode 100644
index 0000000..c88d11b
--- /dev/null
+++ b/cpanfile
@@ -0,0 +1,14 @@
+requires 'Carp';
+requires 'Class::Accessor';
+requires 'DateTime';
+requires 'DateTime::Format::Strptime';
+requires 'Getopt::Long';
+requires 'JSON';
+requires 'List::Util';
+requires 'LWP::UserAgent';
+requires 'LWP::Protocol::https';
+
+on test => sub {
+ requires 'File::Slurp';
+ requires 'Test::More';
+};
diff --git a/ext/transport-apis b/ext/transport-apis
new file mode 160000
+Subproject ef57e8b8158653b4f5f400fff109a417e9117c5
diff --git a/lib/Travel/Status/DE/EFA.pm b/lib/Travel/Status/DE/EFA.pm
index d79f3d1..be08b9a 100644
--- a/lib/Travel/Status/DE/EFA.pm
+++ b/lib/Travel/Status/DE/EFA.pm
@@ -5,17 +5,63 @@ use warnings;
use 5.010;
use utf8;
-no if $] >= 5.018, warnings => 'experimental::smartmatch';
-
-our $VERSION = '1.17';
+our $VERSION = '3.13';
use Carp qw(confess cluck);
+use DateTime;
+use DateTime::Format::Strptime;
use Encode qw(encode);
+use JSON;
+use Travel::Status::DE::EFA::Departure;
+use Travel::Status::DE::EFA::Info;
use Travel::Status::DE::EFA::Line;
-use Travel::Status::DE::EFA::Result;
+use Travel::Status::DE::EFA::Services;
use Travel::Status::DE::EFA::Stop;
+use Travel::Status::DE::EFA::Trip;
use LWP::UserAgent;
-use XML::LibXML;
+
+sub new_p {
+ my ( $class, %opt ) = @_;
+ my $promise = $opt{promise}->new;
+
+ my $self;
+
+ eval { $self = $class->new( %opt, async => 1 ); };
+ if ($@) {
+ return $promise->reject($@);
+ }
+
+ $self->{promise} = $opt{promise};
+
+ $self->post_with_cache_p->then(
+ sub {
+ my ($content) = @_;
+ $self->{response} = $self->{json}->decode($content);
+
+ if ( $self->{developer_mode} ) {
+ say $self->{json}->pretty->encode( $self->{response} );
+ }
+
+ $self->check_for_ambiguous();
+
+ if ( $self->{errstr} ) {
+ $promise->reject( $self->{errstr}, $self );
+ return;
+ }
+
+ $promise->resolve($self);
+ return;
+ }
+ )->catch(
+ sub {
+ my ( $err, $self ) = @_;
+ $promise->reject($err);
+ return;
+ }
+ )->wait;
+
+ return $promise;
+}
sub new {
my ( $class, %opt ) = @_;
@@ -25,22 +71,49 @@ sub new {
delete $opt{timeout};
}
- my $ua = LWP::UserAgent->new(%opt);
- my @now = localtime( time() );
-
- my @time = @now[ 2, 1 ];
- my @date = ( $now[3], $now[4] + 1, $now[5] + 1900 );
-
- if ( not( $opt{place} and $opt{name} ) ) {
- confess('You need to specify a place and a name');
+ if (
+ not( $opt{coord}
+ or $opt{name}
+ or $opt{stopfinder}
+ or $opt{stopseq}
+ or $opt{from_json} )
+ )
+ {
+ confess('You must specify a name');
}
- if ( $opt{type} and not( $opt{type} ~~ [qw[stop address poi]] ) ) {
- confess('type must be stop, address or poi');
+ if ( $opt{type}
+ and not( $opt{type} =~ m{ ^ (?: stop | stopID | address | poi ) $ }x ) )
+ {
+ confess('type must be stop, stopID, address, or poi');
}
+ if ( $opt{service} ) {
+ if ( my $service
+ = Travel::Status::DE::EFA::Services::get_service( $opt{service} ) )
+ {
+ $opt{efa_url} = $service->{url};
+ if ( $opt{coord} ) {
+ $opt{efa_url} .= '/XML_COORD_REQUEST';
+ }
+ elsif ( $opt{stopfinder} ) {
+ $opt{efa_url} .= '/XML_STOPFINDER_REQUEST';
+ }
+ elsif ( $opt{stopseq} ) {
+ $opt{efa_url} .= '/XML_STOPSEQCOORD_REQUEST';
+ }
+ else {
+ $opt{efa_url} .= '/XML_DM_REQUEST';
+ }
+ $opt{time_zone} //= $service->{time_zone};
+ }
+ }
+
+ $opt{time_zone} //= 'Europe/Berlin';
+
if ( not $opt{efa_url} ) {
- confess('efa_url is mandatory');
+ confess('service or efa_url must be specified');
}
+ my $dt = $opt{datetime} // DateTime->now( time_zone => $opt{time_zone} );
## no critic (RegularExpressions::ProhibitUnusedCapture)
## no critic (Variables::ProhibitPunctuationVars)
@@ -48,7 +121,10 @@ sub new {
if ( $opt{time}
and $opt{time} =~ m{ ^ (?<hour> \d\d? ) : (?<minute> \d\d ) $ }x )
{
- @time = @+{qw{hour minute}};
+ $dt->set(
+ hour => $+{hour},
+ minute => $+{minute}
+ );
}
elsif ( $opt{time} ) {
confess('Invalid time specified');
@@ -61,10 +137,17 @@ sub new {
)
{
if ( $+{year} ) {
- @date = @+{qw{day month year}};
+ $dt->set(
+ day => $+{day},
+ month => $+{month},
+ year => $+{year}
+ );
}
else {
- @date[ 0, 1 ] = @+{qw{day month}};
+ $dt->set(
+ day => $+{day},
+ month => $+{month}
+ );
}
}
elsif ( $opt{date} ) {
@@ -72,43 +155,86 @@ sub new {
}
my $self = {
- post => {
- command => q{},
- deleteAssignedStops_dm => '1',
- help => 'Hilfe',
- itdDateDay => $date[0],
- itdDateMonth => $date[1],
- itdDateYear => $date[2],
- itdLPxx_id_dm => ':dm',
- itdLPxx_mapState_dm => q{},
- itdLPxx_mdvMap2_dm => q{},
- itdLPxx_mdvMap_dm => '3406199:401077:NAV3',
- itdLPxx_transpCompany => 'vrr',
- itdLPxx_view => q{},
- itdTimeHour => $time[0],
- itdTimeMinute => $time[1],
- language => 'de',
- mode => 'direct',
- nameInfo_dm => 'invalid',
- nameState_dm => 'empty',
- name_dm => encode( 'UTF-8', $opt{name} ),
- outputFormat => 'XML',
- placeInfo_dm => 'invalid',
- placeState_dm => 'empty',
- place_dm => encode( 'UTF-8', $opt{place} ),
- ptOptionsActive => '1',
- requestID => '0',
- reset => 'neue Anfrage',
- sessionID => '0',
- submitButton => 'anfordern',
- typeInfo_dm => 'invalid',
- type_dm => $opt{type} // 'stop',
- useProxFootSearch => '0',
- useRealtime => '1',
- },
+ cache => $opt{cache},
+ response => $opt{from_json},
developer_mode => $opt{developer_mode},
+ efa_url => $opt{efa_url},
+ service => $opt{service},
+ strp_stopseq => DateTime::Format::Strptime->new(
+ pattern => '%Y%m%d %H:%M',
+ time_zone => $opt{time_zone},
+ ),
+ strp_stopseq_s => DateTime::Format::Strptime->new(
+ pattern => '%Y%m%d %H:%M:%S',
+ time_zone => $opt{time_zone},
+ ),
+
+ json => JSON->new->utf8,
};
+ if ( $opt{coord} ) {
+
+ # outputFormat => 'JSON' returns invalid JSON
+ $self->{post} = {
+ coord => sprintf( '%.7f:%.7f:%s',
+ $opt{coord}{lon}, $opt{coord}{lat}, 'WGS84[DD.ddddd]' ),
+ radius_1 => 1320,
+ type_1 => 'STOP',
+ coordListOutputFormat => 'list',
+ max => 30,
+ inclFilter => 1,
+ outputFormat => 'rapidJson',
+ };
+ }
+ elsif ( $opt{stopfinder} ) {
+
+ # filter: 2 (stop) | 4 (street) | 8 (address) | 16 (crossing) | 32 (poi) | 64 (postcod)
+ $self->{post} = {
+ locationServerActive => 1,
+ type_sf => 'any',
+ name_sf => $opt{stopfinder}{name},
+ anyObjFilter_sf => 2,
+ coordOutputFormat => 'WGS84[DD.DDDDD]',
+ outputFormat => 'JSON',
+ };
+ }
+ elsif ( $opt{stopseq} ) {
+
+ # outputFormat => 'JSON' also works; leads to different output
+ $self->{post} = {
+ line => $opt{stopseq}{stateless},
+ stop => $opt{stopseq}{stop_id},
+ tripCode => $opt{stopseq}{key},
+ date => $opt{stopseq}{date},
+ time => $opt{stopseq}{time},
+ coordOutputFormat => 'WGS84[DD.DDDDD]',
+ outputFormat => 'rapidJson',
+ useRealtime => '1',
+ };
+ }
+ else {
+ $self->{post} = {
+ language => 'de',
+ mode => 'direct',
+ outputFormat => 'JSON',
+ type_dm => $opt{type} // 'stop',
+ useProxFootSearch => $opt{proximity_search} ? '1' : '0',
+ useRealtime => '1',
+ itdDateDay => $dt->day,
+ itdDateMonth => $dt->month,
+ itdDateYear => $dt->year,
+ itdTimeHour => $dt->hour,
+ itdTimeMinute => $dt->minute,
+ name_dm => encode( 'UTF-8', $opt{name} ),
+ };
+ }
+
+ if ( $opt{place} ) {
+ $self->{post}{placeInfo_dm} = 'invalid';
+ $self->{post}{placeState_dm} = 'empty';
+ $self->{post}{place_dm} = encode( 'UTF-8', $opt{place} );
+ }
+
if ( $opt{full_routes} ) {
$self->{post}->{depType} = 'stopEvents';
$self->{post}->{includeCompleteStopSeq} = 1;
@@ -117,35 +243,46 @@ sub new {
bless( $self, $class );
- $ua->env_proxy;
+ if ( $opt{user_agent} ) {
+ $self->{ua} = $opt{user_agent};
+ }
+ else {
+ my %lwp_options = %{ $opt{lwp_options} // { timeout => 10 } };
+ $self->{ua} = LWP::UserAgent->new(%lwp_options);
+ $self->{ua}->env_proxy;
+ }
- my $response = $ua->post( $opt{efa_url}, $self->{post} );
+ if ( $self->{cache} ) {
+ $self->{cache_key}
+ = $self->{efa_url} . '?'
+ . join( '&',
+ map { $_ . '=' . $self->{post}{$_} } sort keys %{ $self->{post} } );
+ }
- if ( $response->is_error ) {
- $self->{errstr} = $response->status_line;
+ if ( $opt{async} ) {
return $self;
}
- if ( $opt{efa_encoding} ) {
- $self->{xml} = encode( $opt{efa_encoding}, $response->content );
- }
- else {
- $self->{xml} = $response->decoded_content;
+ if ( $self->{developer_mode} ) {
+ say 'POST ' . $self->{efa_url};
+ while ( my ( $key, $value ) = each %{ $self->{post} } ) {
+ printf( "%30s = %s\n", $key, $value );
+ }
}
- if ( not $self->{xml} ) {
+ if ( not $self->{response} ) {
+ my ( $response, $error ) = $self->post_with_cache;
- # LibXML doesn't like empty documents
- $self->{errstr} = 'Server returned nothing (empty result)';
- return $self;
- }
+ if ($error) {
+ $self->{errstr} = $error;
+ return $self;
+ }
- $self->{tree} = XML::LibXML->load_xml(
- string => $self->{xml},
- );
+ $self->{response} = $self->{json}->decode($response);
+ }
if ( $self->{developer_mode} ) {
- say $self->{tree}->toString(1);
+ say $self->{json}->pretty->encode( $self->{response} );
}
$self->check_for_ambiguous();
@@ -153,18 +290,92 @@ sub new {
return $self;
}
-sub new_from_xml {
- my ( $class, %opt ) = @_;
+sub post_with_cache {
+ my ($self) = @_;
+ my $cache = $self->{cache};
+ my $url = $self->{efa_url};
- my $self = {
- xml => $opt{xml},
- };
+ if ( $self->{developer_mode} ) {
+ say 'POST ' . ( $self->{cache_key} // $url );
+ }
- $self->{tree} = XML::LibXML->load_xml(
- string => $self->{xml},
- );
+ if ($cache) {
+ my $content = $cache->thaw( $self->{cache_key} );
+ if ($content) {
+ if ( $self->{developer_mode} ) {
+ say ' cache hit';
+ }
+ return ( ${$content}, undef );
+ }
+ }
+
+ if ( $self->{developer_mode} ) {
+ say ' cache miss';
+ }
+
+ my $reply = $self->{ua}->post( $url, $self->{post} );
+
+ if ( $reply->is_error ) {
+ return ( undef, $reply->status_line );
+ }
+ my $content = $reply->content;
+
+ if ($cache) {
+ $cache->freeze( $self->{cache_key}, \$content );
+ }
- return bless( $self, $class );
+ return ( $content, undef );
+}
+
+sub post_with_cache_p {
+ my ($self) = @_;
+ my $cache = $self->{cache};
+ my $url = $self->{efa_url};
+
+ if ( $self->{developer_mode} ) {
+ say 'POST ' . ( $self->{cache_key} // $url );
+ }
+
+ my $promise = $self->{promise}->new;
+
+ if ($cache) {
+ my $content = $cache->thaw( $self->{cache_key} );
+ if ($content) {
+ if ( $self->{developer_mode} ) {
+ say ' cache hit';
+ }
+ return $promise->resolve( ${$content} );
+ }
+ }
+
+ if ( $self->{developer_mode} ) {
+ say ' cache miss';
+ }
+
+ $self->{ua}->post_p( $url, form => $self->{post} )->then(
+ sub {
+ my ($tx) = @_;
+ if ( my $err = $tx->error ) {
+ $promise->reject(
+ "POST $url returned HTTP $err->{code} $err->{message}");
+ return;
+ }
+ my $content = $tx->res->body;
+ if ($cache) {
+ $cache->freeze( $self->{cache_key}, \$content );
+ }
+ $promise->resolve($content);
+ return;
+ }
+ )->catch(
+ sub {
+ my ($err) = @_;
+ $promise->reject($err);
+ return;
+ }
+ )->wait;
+
+ return $promise;
}
sub errstr {
@@ -191,322 +402,245 @@ sub place_candidates {
return;
}
-sub sprintf_date {
- my ($e) = @_;
+sub check_for_ambiguous {
+ my ($self) = @_;
+
+ my $json = $self->{response};
- if ( $e->getAttribute('day') == -1 ) {
+ if ( $json->{departureList} ) {
return;
}
- return sprintf( '%02d.%02d.%d',
- $e->getAttribute('day'),
- $e->getAttribute('month'),
- $e->getAttribute('year'),
- );
-}
-
-sub sprintf_time {
- my ($e) = @_;
-
- if ( $e->getAttribute('minute') == -1 ) {
- return;
+ for my $m ( @{ $json->{dm}{message} // [] } ) {
+ if ( $m->{name} eq 'error' and $m->{value} eq 'name list' ) {
+ $self->{errstr} = "ambiguous name parameter";
+ $self->{name_candidates} = [];
+ for my $point ( @{ $json->{dm}{points} // [] } ) {
+ my $place = $point->{ref}{place};
+ push(
+ @{ $self->{name_candidates} },
+ Travel::Status::DE::EFA::Stop->new(
+ place => $place,
+ full_name => $point->{name},
+ name => $point->{name} =~ s{\Q$place\E,? ?}{}r,
+ id_num => $point->{ref}{id},
+ )
+ );
+ }
+ return;
+ }
+ if ( $m->{name} eq 'error' and $m->{value} eq 'place list' ) {
+ $self->{errstr} = "ambiguous name parameter";
+ $self->{place_candidates} = [];
+ for my $point ( @{ $json->{dm}{points} // [] } ) {
+ my $place = $point->{ref}{place};
+ push(
+ @{ $self->{place_candidates} },
+ Travel::Status::DE::EFA::Stop->new(
+ place => $place,
+ full_name => $point->{name},
+ name => $point->{name} =~ s{\Q$place\E,? ?}{}r,
+ id_num => $point->{ref}{id},
+ )
+ );
+ }
+ return;
+ }
}
- return sprintf( '%02d:%02d',
- $e->getAttribute('hour'),
- $e->getAttribute('minute'),
- );
+ return;
}
-sub check_for_ambiguous {
+sub stop {
my ($self) = @_;
+ if ( $self->{stop} ) {
+ return $self->{stop};
+ }
- my $xml = $self->{tree};
-
- my $xp_place = XML::LibXML::XPathExpression->new('//itdOdv/itdOdvPlace');
- my $xp_name = XML::LibXML::XPathExpression->new('//itdOdv/itdOdvName');
- my $xp_mesg
- = XML::LibXML::XPathExpression->new('//itdMessage[@type="error"]');
+ my $point = $self->{response}{dm}{points}{point};
+ my $place = $point->{ref}{place};
- my $xp_place_elem = XML::LibXML::XPathExpression->new('./odvPlaceElem');
- my $xp_name_elem = XML::LibXML::XPathExpression->new('./odvNameElem');
+ $self->{stop} = Travel::Status::DE::EFA::Stop->new(
+ place => $place,
+ full_name => $point->{name},
+ name => $point->{name} =~ s{\Q$place\E,? ?}{}r,
+ id_num => $point->{ref}{id},
+ id_code => $point->{ref}{gid},
+ );
- my $e_place = ( $xml->findnodes($xp_place) )[0];
- my $e_name = ( $xml->findnodes($xp_name) )[0];
- my @e_mesg = $xml->findnodes($xp_mesg);
+ return $self->{stop};
+}
- if ( not( $e_place and $e_name ) ) {
+sub stops {
+ my ($self) = @_;
- # this should not happen[tm]
- cluck('skipping ambiguity check- itdOdvPlace/itdOdvName missing');
- return;
+ if ( $self->{stops} ) {
+ return @{ $self->{stops} };
}
- my $s_place = $e_place->getAttribute('state');
- my $s_name = $e_name->getAttribute('state');
+ my $stops = $self->{response}{dm}{itdOdvAssignedStops} // [];
- if ( $s_place eq 'list' ) {
- $self->{place_candidates} = [ map { $_->textContent }
- @{ $e_place->findnodes($xp_place_elem) } ];
- $self->{errstr} = 'ambiguous place parameter';
- return;
+ if ( ref($stops) eq 'HASH' ) {
+ $stops = [$stops];
}
- if ( $s_name eq 'list' ) {
- $self->{name_candidates}
- = [ map { $_->textContent } @{ $e_name->findnodes($xp_name_elem) } ];
- $self->{errstr} = 'ambiguous name parameter';
- return;
- }
- if ( $s_place eq 'notidentified' ) {
- $self->{errstr} = 'invalid place parameter';
- return;
- }
- if ( $s_name eq 'notidentified' ) {
- $self->{errstr} = 'invalid name parameter';
- return;
- }
- if (@e_mesg) {
- $self->{errstr} = join( q{; }, map { $_->textContent } @e_mesg );
- return;
+ my @stops;
+ for my $stop ( @{$stops} ) {
+ push(
+ @stops,
+ Travel::Status::DE::EFA::Stop->new(
+ place => $stop->{place},
+ name => $stop->{name},
+ full_name => $stop->{nameWithPlace},
+ id_num => $stop->{stopID},
+ id_code => $stop->{gid},
+ )
+ );
}
- return;
+ $self->{stops} = \@stops;
+ return @stops;
}
-sub identified_data {
+sub infos {
my ($self) = @_;
- if ( not $self->{tree} ) {
- return;
+ if ( $self->{infos} ) {
+ return @{ $self->{infos} };
}
- my $xp_place
- = XML::LibXML::XPathExpression->new('//itdOdv/itdOdvPlace/odvPlaceElem');
- my $xp_name
- = XML::LibXML::XPathExpression->new('//itdOdv/itdOdvName/odvNameElem');
-
- my $e_place = ( $self->{tree}->findnodes($xp_place) )[0];
- my $e_name = ( $self->{tree}->findnodes($xp_name) )[0];
+ for my $info ( @{ $self->{response}{dm}{points}{point}{infos} // [] } ) {
+ push(
+ @{ $self->{infos} },
+ Travel::Status::DE::EFA::Info->new( json => $info )
+ );
+ }
- return ( $e_place->textContent, $e_name->textContent );
+ return @{ $self->{infos} // [] };
}
sub lines {
my ($self) = @_;
- my @lines;
if ( $self->{lines} ) {
return @{ $self->{lines} };
}
- if ( not $self->{tree} ) {
- return;
+ for my $line ( @{ $self->{response}{servingLines}{lines} // [] } ) {
+ push( @{ $self->{lines} }, $self->parse_line($line) );
}
- my $xp_element
- = XML::LibXML::XPathExpression->new('//itdServingLines/itdServingLine');
+ return @{ $self->{lines} // [] };
+}
- my $xp_info = XML::LibXML::XPathExpression->new('./itdNoTrain');
- my $xp_route = XML::LibXML::XPathExpression->new('./itdRouteDescText');
- my $xp_oper = XML::LibXML::XPathExpression->new('./itdOperator/name');
+sub parse_line {
+ my ( $self, $line ) = @_;
- for my $e ( $self->{tree}->findnodes($xp_element) ) {
+ my $mode = $line->{mode} // {};
- my $e_info = ( $e->findnodes($xp_info) )[0];
- my $e_route = ( $e->findnodes($xp_route) )[0];
- my $e_oper = ( $e->findnodes($xp_oper) )[0];
+ return Travel::Status::DE::EFA::Line->new(
+ type => $mode->{product},
+ name => $mode->{name},
+ number => $mode->{number},
+ direction => $mode->{destination},
+ valid => $mode->{timetablePeriod},
+ mot => $mode->{product},
+ operator => $mode->{diva}{operator},
+ identifier => $mode->{diva}{globalId},
- if ( not($e_info) ) {
- cluck( 'node with insufficient data. This should not happen. '
- . $e->getAttribute('number') );
- next;
- }
+ );
+}
- my $line = $e->getAttribute('number');
- my $direction = $e->getAttribute('direction');
- my $valid = $e->getAttribute('valid');
- my $type = $e_info->getAttribute('name');
- my $mot = $e->getAttribute('motType');
- my $route = ( $e_route ? $e_route->textContent : undef );
- my $operator = ( $e_oper ? $e_oper->textContent : undef );
- my $identifier = $e->getAttribute('stateless');
+sub results {
+ my ($self) = @_;
- push(
- @lines,
- Travel::Status::DE::EFA::Line->new(
- name => $line,
- direction => $direction,
- valid => $valid,
- type => $type,
- mot => $mot,
- route => $route,
- operator => $operator,
- identifier => $identifier,
- )
- );
+ if ( $self->{results} ) {
+ return @{ $self->{results} };
}
- $self->{lines} = \@lines;
-
- return @lines;
+ if ( $self->{post}{coord} ) {
+ return $self->results_coord;
+ }
+ elsif ( $self->{post}{name_sf} ) {
+ return $self->results_stopfinder;
+ }
+ else {
+ return $self->results_dm;
+ }
}
-sub parse_route {
- my ( $self, @nodes ) = @_;
- my $xp_routepoint_date
- = XML::LibXML::XPathExpression->new('./itdDateTime/itdDate');
- my $xp_routepoint_time
- = XML::LibXML::XPathExpression->new('./itdDateTime/itdTime');
-
- my @ret;
-
- for my $e (@nodes) {
- my @dates = $e->findnodes($xp_routepoint_date);
- my @times = $e->findnodes($xp_routepoint_time);
+sub results_coord {
+ my ($self) = @_;
+ my $json = $self->{response};
- # note that the first stop has an arrival node with an invalid
- # timestamp and the terminal stop has a departure node with an
- # invalid timestamp. sprintf_{date,time} return undef in these
- # cases.
+ my @results;
+ for my $stop ( @{ $json->{locations} // [] } ) {
push(
- @ret,
+ @results,
Travel::Status::DE::EFA::Stop->new(
- arr_date => sprintf_date( $dates[0] ),
- arr_time => sprintf_time( $times[0] ),
- dep_date => sprintf_date( $dates[-1] ),
- dep_time => sprintf_time( $times[-1] ),
- name => $e->getAttribute('name'),
- name_suf => $e->getAttribute('nameWO'),
- platform => $e->getAttribute('platformName'),
+ place => $stop->{parent}{name},
+ full_name => $stop->{properties}{STOP_NAME_WITH_PLACE},
+ distance_m => $stop->{properties}{distance},
+ name => $stop->{name},
+ id_code => $stop->{id},
)
);
}
- return @ret;
+ $self->{results} = \@results;
+
+ return @results;
}
-sub results {
+sub results_stopfinder {
my ($self) = @_;
+ my $json = $self->{response};
+
my @results;
- if ( $self->{results} ) {
- return @{ $self->{results} };
+ # Edge case: there is just a single result.
+ # Oh EFA, you so silly.
+ if ( ref( $json->{stopFinder}{points} ) eq 'HASH'
+ and exists $json->{stopFinder}{points}{point} )
+ {
+ $json->{stopFinder}{points} = [ $json->{stopFinder}{points}{point} ];
}
- if ( not $self->{tree} ) {
- return;
+ for my $stop ( @{ $json->{stopFinder}{points} // [] } ) {
+ push(
+ @results,
+ Travel::Status::DE::EFA::Stop->new(
+ place => $stop->{ref}{place},
+ full_name => $stop->{name},
+ name => $stop->{object},
+ id_num => $stop->{ref}{id},
+ id_code => $stop->{ref}{gid},
+ )
+ );
}
- my $xp_element = XML::LibXML::XPathExpression->new('//itdDeparture');
-
- my $xp_date = XML::LibXML::XPathExpression->new('./itdDateTime/itdDate');
- my $xp_time = XML::LibXML::XPathExpression->new('./itdDateTime/itdTime');
- my $xp_rdate = XML::LibXML::XPathExpression->new('./itdRTDateTime/itdDate');
- my $xp_rtime = XML::LibXML::XPathExpression->new('./itdRTDateTime/itdTime');
- my $xp_line = XML::LibXML::XPathExpression->new('./itdServingLine');
- my $xp_info
- = XML::LibXML::XPathExpression->new('./itdServingLine/itdNoTrain');
- my $xp_prev_route
- = XML::LibXML::XPathExpression->new('./itdPrevStopSeq/itdPoint');
- my $xp_next_route
- = XML::LibXML::XPathExpression->new('./itdOnwardStopSeq/itdPoint');
-
- $self->lines;
-
- for my $e ( $self->{tree}->findnodes($xp_element) ) {
-
- my $e_date = ( $e->findnodes($xp_date) )[0];
- my $e_time = ( $e->findnodes($xp_time) )[0];
- my $e_line = ( $e->findnodes($xp_line) )[0];
- my $e_info = ( $e->findnodes($xp_info) )[0];
-
- my $e_rdate = ( $e->findnodes($xp_rdate) )[0];
- my $e_rtime = ( $e->findnodes($xp_rtime) )[0];
-
- if ( not( $e_date and $e_time and $e_line ) ) {
- cluck('node with insufficient data. This should not happen');
- next;
- }
+ $self->{results} = \@results;
- my $date = sprintf_date($e_date);
- my $time = sprintf_time($e_time);
-
- my $rdate = $e_rdate ? sprintf_date($e_rdate) : $date;
- my $rtime = $e_rtime ? sprintf_time($e_rtime) : $time;
-
- my $platform = $e->getAttribute('platform');
- my $platform_name = $e->getAttribute('platformName');
- my $line = $e_line->getAttribute('number');
- my $dest = $e_line->getAttribute('direction');
- my $info = $e_info->textContent;
- my $key = $e_line->getAttribute('key');
- my $countdown = $e->getAttribute('countdown');
- my $delay = $e_info->getAttribute('delay');
- my $type = $e_info->getAttribute('name');
- my $mot = $e_line->getAttribute('motType');
-
- my $platform_is_db = 0;
-
- my @prev_route;
- my @next_route;
-
- if ( $self->{want_full_routes} ) {
- @prev_route
- = $self->parse_route( @{ [ $e->findnodes($xp_prev_route) ] } );
- @next_route
- = $self->parse_route( @{ [ $e->findnodes($xp_next_route) ] } );
- }
+ return @results;
+}
- my @line_obj
- = grep { $_->{identifier} eq $e_line->getAttribute('stateless') }
- @{ $self->{lines} };
-
- # platform / platformName are inconsistent. The following cases are
- # known:
- #
- # * platform="int", platformName="" : non-DB platform
- # * platform="int", platformName="Bstg. int" : non-DB platform
- # * platform="#int", platformName="Gleis int" : non-DB platform
- # * platform="#int", platformName="Gleis int" : DB platform?
- # * platform="", platformName="Gleis int" : DB platform
- # * platform="DB", platformName="Gleis int" : DB platform
- # * platform="gibberish", platformName="Gleis int" : DB platform
-
- if ( ( $platform_name and $platform_name =~ m{ ^ Gleis }ox )
- and not( $platform and $platform =~ s{ ^ \# }{}ox ) )
- {
- $platform_is_db = 1;
- }
+sub results_dm {
+ my ($self) = @_;
+ my $json = $self->{response};
- if ( $platform_name and $platform_name =~ m{ ^ (Gleis | Bstg[.])}ox ) {
- $platform = ( split( / /, $platform_name ) )[1];
- }
- elsif ( $platform_name and not $platform ) {
- $platform = $platform_name;
- }
+ # Oh EFA, you so silly
+ if ( $json->{departureList} and ref( $json->{departureList} ) eq 'HASH' ) {
+ $json->{departureList} = [ $json->{departureList}{departure} ];
+ }
+ my @results;
+ for my $departure ( @{ $json->{departureList} // [] } ) {
push(
@results,
- Travel::Status::DE::EFA::Result->new(
- date => $rdate,
- time => $rtime,
- platform => $platform,
- platform_db => $platform_is_db,
- platform_name => $platform_name,
- key => $key,
- lineref => $line_obj[0] // undef,
- line => $line,
- destination => $dest,
- countdown => $countdown,
- info => $info,
- delay => $delay,
- sched_date => $date,
- sched_time => $time,
- type => $type,
- mot => $mot,
- prev_route => \@prev_route,
- next_route => \@next_route,
+ Travel::Status::DE::EFA::Departure->new(
+ json => $departure,
+ strp_stopseq => $self->{strp_stopseq},
+ strp_stopseq_s => $self->{strp_stopseq_s}
)
);
}
@@ -520,124 +654,31 @@ sub results {
return @results;
}
-# static
-sub get_efa_urls {
-
- # sorted lexically by shortname
- return (
- {
- url => 'https://bsvg.efa.de/bsvagstd/XML_DM_REQUEST',
- name => 'Braunschweiger Verkehrs-GmbH',
- shortname => 'BSVG',
- },
- {
- url => 'https://www.ding.eu/ding3/XSLT_DM_REQUEST',
- name => 'Donau-Iller Nahverkehrsverbund',
- shortname => 'DING',
- },
- {
- url => 'https://projekte.kvv-efa.de/sl3-alone/XSLT_DM_REQUEST',
- name => 'Karlsruher Verkehrsverbund',
- shortname => 'KVV',
- },
- {
- url => 'https://www.linzag.at/static/XSLT_DM_REQUEST',
- name => 'Linz AG',
- shortname => 'LinzAG',
- encoding => 'iso-8859-15',
- },
- {
- url => 'https://efa.mvv-muenchen.de/mobile/XSLT_DM_REQUEST',
- name => 'Münchner Verkehrs- und Tarifverbund',
- shortname => 'MVV',
- },
- {
- url => 'https://www.efa-bw.de/nvbw/XSLT_DM_REQUEST',
- name => 'Nahverkehrsgesellschaft Baden-Württemberg',
- shortname => 'NVBW',
- },
-
- # HTTPS not supported
- {
- url => 'http://efa.svv-info.at/sbs/XSLT_DM_REQUEST',
- name => 'Salzburger Verkehrsverbund',
- shortname => 'SVV',
- },
-
- # HTTPS: invalid certificate
- {
- url => 'http://www.travelineeastmidlands.co.uk/em/XSLT_DM_REQUEST',
- name => 'Traveline East Midlands',
- shortname => 'TLEM',
- },
- {
- url => 'https://efa.vagfr.de/vagfr3/XSLT_DM_REQUEST',
- name => 'Freiburger Verkehrs AG',
- shortname => 'VAG',
- },
-
- # HTTPS: unsupported protocol
- {
- url => 'http://mobil.vbl.ch/vblmobil/XML_DM_REQUEST',
- name => 'Verkehrsbetriebe Luzern',
- shortname => 'VBL',
- },
-
- # HTTPS not supported
- {
- url => 'http://fahrplan.verbundlinie.at/stv/XSLT_DM_REQUEST',
- name => 'Verkehrsverbund Steiermark',
- shortname => 'Verbundlinie',
- },
- {
- url => 'https://efa.vgn.de/vgnExt_oeffi/XML_DM_REQUEST',
- name => 'Verkehrsverbund Grossraum Nuernberg',
- shortname => 'VGN',
- },
+sub result {
+ my ($self) = @_;
- # HTTPS: certificate verification fails
- {
- url => 'http://efa.vmv-mbh.de/vmv/XML_DM_REQUEST',
- name => 'Verkehrsgesellschaft Mecklenburg-Vorpommern',
- shortname => 'VMV',
- },
- {
- url => 'https://efa.vor.at/wvb/XSLT_DM_REQUEST',
- name => 'Verkehrsverbund Ost-Region',
- shortname => 'VOR',
- encoding => 'iso-8859-15',
- },
+ return Travel::Status::DE::EFA::Trip->new( json => $self->{response} );
+}
- # HTTPS not supported
- {
- url => 'http://fahrplanauskunft.vrn.de/vrn/XML_DM_REQUEST',
- name => 'Verkehrsverbund Rhein-Neckar',
- shortname => 'VRN',
- },
- {
- url => 'https://efa.vrr.de/vrr/XSLT_DM_REQUEST',
- name => 'Verkehrsverbund Rhein-Ruhr',
- shortname => 'VRR',
- },
- {
- url => 'https://app.vrr.de/standard/XML_DM_REQUEST',
- name => 'Verkehrsverbund Rhein-Ruhr (alternative)',
- shortname => 'VRR2',
- },
+# static
+sub get_service_ids {
+ return Travel::Status::DE::EFA::Services::get_service_ids(@_);
+}
- # HTTPS not supported
- {
- url => 'http://efa.vvo-online.de:8080/dvb/XSLT_DM_REQUEST',
- name => 'Verkehrsverbund Oberelbe',
- shortname => 'VVO',
- },
- {
- url => 'https://www2.vvs.de/vvs/XSLT_DM_REQUEST',
- name => 'Verkehrsverbund Stuttgart',
- shortname => 'VVS',
- },
+sub get_services {
+ my @services;
+ for my $service ( Travel::Status::DE::EFA::Services::get_service_ids() ) {
+ my %desc
+ = %{ Travel::Status::DE::EFA::Services::get_service($service) };
+ $desc{shortname} = $service;
+ push( @services, \%desc );
+ }
+ return @services;
+}
- );
+# static
+sub get_service {
+ return Travel::Status::DE::EFA::Services::get_service(@_);
}
1;
@@ -653,27 +694,30 @@ Travel::Status::DE::EFA - unofficial EFA departure monitor
use Travel::Status::DE::EFA;
my $status = Travel::Status::DE::EFA->new(
- efa_url => 'https://efa.vrr.de/vrr/XSLT_DM_REQUEST',
- place => 'Essen', name => 'Helenenstr'
+ service => 'VRR',
+ name => 'Essen Helenenstr'
);
for my $d ($status->results) {
printf(
"%s %-8s %-5s %s\n",
- $d->time, $d->platform_name, $d->line, $d->destination
+ $d->datetime->strftime('%H:%M'),
+ $d->platform_name, $d->line, $d->destination
);
}
=head1 VERSION
-version 1.17
+version 3.13
=head1 DESCRIPTION
Travel::Status::DE::EFA is an unofficial interface to EFA-based departure
monitors.
-It reports all upcoming tram/bus/train departures at a given place.
+It can serve as a departure monitor, request details about a specific
+trip/journey, and look up public transport stops by name or geolocation.
+The operating mode depends on its constructor arguments.
=head1 METHODS
@@ -681,32 +725,52 @@ It reports all upcoming tram/bus/train departures at a given place.
=item my $status = Travel::Status::DE::EFA->new(I<%opt>)
-Requests the departures as specified by I<opts> and returns a new
-Travel::Status::DE::EFA object. B<efa_url>, B<place> and B<name> are
-mandatory. Dies if the wrong I<opts> were passed.
+Requests data as specified by I<opts> and returns a new Travel::Status::DE::EFA
+object. B<service> and exactly one of B<coord>, B<stopfinder>, B<stopseq> or
+B<name> are mandatory. Dies if the wrong I<opts> were passed.
Arguments:
=over
-=item B<efa_url> => I<url>
+=item B<service> => I<name>
-URL to the EFA service. See C<< efa-m --list >> for known URLs.
-If you found a URL not listed there, please notify
+EFA service. See C<< efa-m --list >> for known services.
+If you found a service not listed there, please notify
E<lt>derf+efa@finalrewind.orgE<gt>.
+=item B<coord> => I<hashref>
+
+Look up stops in the vicinity of the given coordinates. I<hashref> must
+contain a B<lon> and a B<lat> element providing WGS84 longitude/latitude.
+
+=item B<stopfinder> => { B<name> => I<name> }
+
+Look up stops matching I<name>.
+
+=item B<stopseq> => I<hashref>
+
+Look up trip details. I<hashref> must provide B<stateless> (line ID),
+B<stop_id> (stop ID used as start for the reported route), B<key> (line trip
+number), and B<date> (departure date as YYYYMMDD string).
+
+=item B<name> => I<name>
+
+List departure for address / point of interest / stop I<name>.
+
=item B<place> => I<place>
Name of the place/city
-=item B<type> => B<address>|B<poi>|B<stop>
+=item B<type> => B<address>|B<poi>|B<stop>|B<stopID>
Type of the following I<name>. B<poi> means "point of interest". Defaults to
B<stop> (stop/station name).
-=item B<name> => I<name>
+=item B<datetime> => I<DateTime object>
-address / poi / stop name to list departures for.
+Request departures for the date/time specified by I<DateTime object>.
+Default: now.
=item B<efa_encoding> => I<encoding>
@@ -718,7 +782,12 @@ iso-8859-15.
If true: Request full routes for all departures from the backend. This
enables the B<route_pre>, B<route_post> and B<route_interesting> accessors in
-Travel::Status::DE::EFA::Result(3pm).
+Travel::Status::DE::EFA::Departure(3pm).
+
+=item B<proximity_search> => B<0>|B<1>
+
+If true: Show departures for stops in the proximity of the requested place
+as well.
=item B<timeout> => I<seconds>
@@ -727,17 +796,37 @@ Default: 10 seconds. Set to 0 or a negative value to disable it.
=back
+=item my $status_p = Travel::Status::DE::EFA->new_p(I<%opt>)
+
+Returns a promise that resolves into a Travel::Status::DE::EFA instance
+($status) on success and rejects with an error message on failure. In case
+the error occured after construction of the Travel::Status::DE::EFA object
+(e.g. due to an ambiguous name/place parameter), the second argument of the
+rejected promise holds a Travel::Status::DE::EFA instance that can be used
+to query place/name candidates (see name_candidates and place_candidates).
+
+In addition to the arguments of B<new>, the following mandatory arguments must
+be set.
+
+=over
+
+=item B<promise> => I<promises module>
+
+Promises implementation to use for internal promises as well as B<new_p> return
+value. Recommended: Mojo::Promise(3pm).
+
+=item B<user_agent> => I<user agent>
+
+User agent instance to use for asynchronous requests. The object must implement
+a B<post_p> function. Recommended: Mojo::UserAgent(3pm).
+
+=back
+
=item $status->errstr
In case of an HTTP request or EFA error, returns a string describing it. If
none occured, returns undef.
-=item $status->identified_data
-
-Returns a list of the identified values for I<place> and I<name>.
-For instance, when requesting data for "E", "MartinSTR", B<identified_data>
-will return ("Essen", "Martinstr.").
-
=item $status->lines
Returns a list of Travel::Status::DE::EFA::Line(3pm) objects, each one
@@ -753,28 +842,70 @@ nothing (undef / empty list) otherwise.
Returns a list of B<place> candidates if I<place> is ambiguous. Returns
nothing (undef / empty list) otherwise.
+=item $status->stop
+
+Returns a Travel::Status::DE::EFA::Stop(3pm) instance describing the requested
+stop.
+
+=item $status->stops
+
+In case the requested place/name is served by multiple stops and the backend
+provides a list of those: returns a list of Travel::Status::DE::EFA::Stop(3pm)
+instances describing each of them. Returns an empty list otherwise.
+
=item $status->results
-Returns a list of Travel::Status::DE::EFA::Result(3pm) objects, each one describing
-one departure.
+In departure monitor mode: returns a list of
+Travel::Status::DE::EFA::Departure(3pm) objects, each one describing one
+departure.
+
+In coord or stopfinder mode: returns a list of
+Travel::Status::DE::EFA::Stop(3pm) objects.
+
+=item $status->result
-=item Travel::Status::DE::EFA::get_efa_urls()
+In stopseq mode: Returns a Travel::Status::DE::EFA::Trip(3pm) object.
-Returns a list of known EFA entry points. Each list element is a hashref with
-the following elements.
+=item Travel::Status::DE::EFA::get_service_ids()
+
+Returns the list of supported services (backends).
+
+=item Travel::Status::DE::EFA::get_service(I<service>)
+
+Returns a hashref describing the requested I<service> ID with the following keys.
=over
-=item B<url>: service URL as passed to B<efa_url>
+=item B<name> => I<string>
+
+Provider name, e.g. Verkehrsverbund Oberelbe.
+
+=item B<url> => I<string>
+
+Backend base URL.
+
+=item B<homepage> => I<string> (optional)
+
+Provider homepage.
-=item B<name>: Name of the entity operating this service
+=item B<languages> => I<arrayref> (optional)
-=item B<shortname>: Short name of the entity
+Supportde languages, e.g. de, en.
-=item B<encoding>: Server-side encoding override for B<efa_encoding> (optional)
+=item B<coverage> => I<hashref>
+
+Area in which the service provides near-optimal coverage. Typically, this
+means a (nearly) complete list of departures and real-time data. The
+hashref contains two optional keys: B<area> (GeoJSON) and B<regions> (list of
+strings, e.g. "DE" or "CH-BE").
=back
+=item Travel::Status::DE::EFA::get_services()
+
+Returns a list of hashrefs describing all supported services. In addition
+to the keys listed above, each service contains a B<shortname> (service ID).
+
=back
=head1 DIAGNOSTICS
@@ -787,23 +918,27 @@ None.
=item * Class::Accessor(3pm)
-=item * LWP::UserAgent(3pm)
+=item * DateTime(3pm)
-=item * XML::LibXML(3pm)
+=item * DateTime::Format::Strptime(3pm)
+
+=item * JSON(3pm)
+
+=item * LWP::UserAgent(3pm)
=back
=head1 BUGS AND LIMITATIONS
-Not all features of the web interface are supported.
+The API is not exposed completely.
=head1 SEE ALSO
-efa-m(1), Travel::Status::DE::EFA::Result(3pm).
+efa-m(1), Travel::Status::DE::EFA::Departure(3pm).
=head1 AUTHOR
-Copyright (C) 2011-2015 by Daniel Friesel E<lt>derf@finalrewind.orgE<gt>
+Copyright (C) 2011-2025 Birte Kristina Friesel E<lt>derf@finalrewind.orgE<gt>
=head1 LICENSE
diff --git a/lib/Travel/Status/DE/EFA/Departure.pm b/lib/Travel/Status/DE/EFA/Departure.pm
new file mode 100644
index 0000000..ec17a12
--- /dev/null
+++ b/lib/Travel/Status/DE/EFA/Departure.pm
@@ -0,0 +1,528 @@
+package Travel::Status::DE::EFA::Departure;
+
+use strict;
+use warnings;
+use 5.010;
+
+use DateTime;
+use List::Util qw(any);
+use Travel::Status::DE::EFA::Stop;
+
+use parent 'Class::Accessor';
+
+our $VERSION = '3.13';
+
+Travel::Status::DE::EFA::Departure->mk_ro_accessors(
+ qw(countdown datetime delay destination is_cancelled key line lineref mot
+ occupancy operator origin platform platform_db platform_name rt_datetime
+ sched_datetime stateless stop_id_num train_type train_name train_no type)
+);
+
+my @mot_mapping = qw{
+ zug s-bahn u-bahn stadtbahn tram stadtbus regionalbus
+ schnellbus seilbahn schiff ast sonstige
+};
+
+sub parse_departure {
+ my ( $self, $departure ) = @_;
+}
+
+sub new {
+ my ( $obj, %conf ) = @_;
+
+ my $departure = $conf{json};
+ my ( $sched_dt, $real_dt );
+
+ if ( my $dt = $departure->{dateTime} ) {
+ $sched_dt = DateTime->new(
+ year => $dt->{year},
+ month => $dt->{month},
+ day => $dt->{day},
+ hour => $dt->{hour},
+ minute => $dt->{minute},
+ second => $dt->{second} // 0,
+ time_zone => 'Europe/Berlin',
+ );
+ }
+
+ if ( my $dt = $departure->{realDateTime} ) {
+ $real_dt = DateTime->new(
+ year => $dt->{year},
+ month => $dt->{month},
+ day => $dt->{day},
+ hour => $dt->{hour},
+ minute => $dt->{minute},
+ second => $dt->{second} // 0,
+ time_zone => 'Europe/Berlin',
+ );
+ }
+
+ my @hints
+ = map { $_->{content} } @{ $departure->{servingLine}{hints} // [] };
+
+ my $ref = {
+ strp_stopseq_s => $conf{strp_stopseq_s},
+ strp_stopseq => $conf{strp_stopseq},
+ rt_datetime => $real_dt,
+ platform => $departure->{platform},
+ platform_name => $departure->{platformName},
+ platform_type => $departure->{pointType},
+ key => $departure->{servingLine}{key},
+ stateless => $departure->{servingLine}{stateless},
+ stop_id_num => $departure->{stopID},
+ line => $departure->{servingLine}{symbol},
+ train_type => $departure->{servingLine}{trainType},
+ train_name => $departure->{servingLine}{trainName},
+ train_no => $departure->{servingLine}{trainNum},
+ origin => $departure->{servingLine}{directionFrom},
+ destination => $departure->{servingLine}{direction},
+ occupancy => $departure->{occupancy},
+ countdown => $departure->{countdown},
+ delay => $departure->{servingLine}{delay},
+ sched_datetime => $sched_dt,
+ type => $departure->{servingLine}{name},
+ mot => $departure->{servingLine}{motType},
+ hints => \@hints,
+ };
+
+ if ( defined $ref->{delay} and $ref->{delay} eq '-9999' ) {
+ $ref->{delay} = 0;
+ $ref->{is_cancelled} = 1;
+ }
+ else {
+ $ref->{is_cancelled} = 0;
+ }
+
+ $ref->{datetime} = $ref->{rt_datetime} // $ref->{sched_datetime};
+
+ bless( $ref, $obj );
+
+ if ( $departure->{prevStopSeq} ) {
+ $ref->{prev_route} = $ref->parse_route( $departure->{prevStopSeq},
+ $departure->{stopID} );
+ }
+ if ( $departure->{onwardStopSeq} ) {
+ $ref->{next_route} = $ref->parse_route( $departure->{onwardStopSeq},
+ $departure->{stopID} );
+ }
+
+ return $ref;
+}
+
+sub parse_route {
+ my ( $self, $stop_seq, $requested_id ) = @_;
+ my @ret;
+
+ if ( not $stop_seq ) {
+ return \@ret;
+ }
+
+ # Oh EFA, you so silly
+ if ( ref($stop_seq) eq 'HASH' ) {
+
+ # For lines that start or terminate at the requested stop, onwardStopSeq / prevStopSeq includes the requested stop.
+ if ( $stop_seq->{ref}{id} eq $requested_id ) {
+ return \@ret;
+ }
+ $stop_seq = [$stop_seq];
+ }
+
+ for my $stop ( @{ $stop_seq // [] } ) {
+ my $ref = $stop->{ref};
+ my ( $arr, $dep );
+
+ if ( $ref->{arrDateTimeSec} ) {
+ $arr = $self->{strp_stopseq_s}
+ ->parse_datetime( $ref->{arrDateTimeSec} );
+ }
+ elsif ( $ref->{arrDateTime} ) {
+ $arr = $self->{strp_stopseq}->parse_datetime( $ref->{arrDateTime} );
+ }
+
+ if ( $ref->{depDateTimeSec} ) {
+ $dep = $self->{strp_stopseq_s}
+ ->parse_datetime( $ref->{depDateTimeSec} );
+ }
+ elsif ( $ref->{depDateTime} ) {
+ $dep = $self->{strp_stopseq}->parse_datetime( $ref->{depDateTime} );
+ }
+
+ push(
+ @ret,
+ Travel::Status::DE::EFA::Stop->new(
+ sched_arr => $arr,
+ sched_dep => $dep,
+ arr_delay => $ref->{arrValid} ? $ref->{arrDelay} : undef,
+ dep_delay => $ref->{depValid} ? $ref->{depDelay} : undef,
+ id_num => $ref->{id},
+ id_code => $ref->{gid},
+ full_name => $stop->{name},
+ place => $stop->{place},
+ name => $stop->{nameWO},
+ occupancy => $stop->{occupancy},
+ platform => $ref->{platform} || $stop->{platformName} || undef,
+ )
+ );
+ }
+
+ return \@ret;
+}
+
+sub id {
+ my ($self) = @_;
+
+ if ( $self->{id} ) {
+ return $self->{id};
+ }
+
+ return $self->{id} = sprintf( '%s@%d(%s)%d',
+ $self->stateless =~ s{ }{}gr,
+ scalar $self->route_pre ? ( $self->route_pre )[0]->id_num
+ : $self->stop_id_num,
+ ( scalar $self->route_pre and ( $self->route_pre )[0]->sched_dep )
+ ? ( $self->route_pre )[0]->sched_dep->strftime('%Y%m%dT%H:%M')
+ : $self->sched_datetime->strftime('%Y%m%dT%H:%M'),
+ $self->key );
+}
+
+sub hints {
+ my ($self) = @_;
+
+ return @{ $self->{hints} // [] };
+}
+
+sub mot_name {
+ my ($self) = @_;
+
+ return $mot_mapping[ $self->{mot} ] // 'sonstige';
+}
+
+sub route_pre {
+ my ($self) = @_;
+
+ return @{ $self->{prev_route} // [] };
+}
+
+sub route_post {
+ my ($self) = @_;
+
+ return @{ $self->{next_route} // [] };
+}
+
+sub route_interesting {
+ my ( $self, $max_parts ) = @_;
+
+ my @via = $self->route_post;
+ my ( @via_main, @via_show, $last_stop );
+ $max_parts //= 3;
+
+ for my $stop (@via) {
+ if (
+ $stop->name =~ m{ Bf | Hbf | Flughafen | [Bb]ahnhof
+ | Krankenhaus | Klinik | (?: S $ ) }ox
+ )
+ {
+ push( @via_main, $stop );
+ }
+ }
+ $last_stop = pop(@via);
+
+ if ( @via_main and $via_main[-1] == $last_stop ) {
+ pop(@via_main);
+ }
+ if ( @via and $via[-1] == $last_stop ) {
+ pop(@via);
+ }
+
+ if ( @via_main and @via and $via[0] == $via_main[0] ) {
+ shift(@via_main);
+ }
+
+ if ( @via < $max_parts ) {
+ @via_show = @via;
+ }
+ else {
+ if ( @via_main >= $max_parts ) {
+ @via_show = ( $via[0] );
+ }
+ else {
+ @via_show = splice( @via, 0, $max_parts - @via_main );
+ }
+
+ while ( @via_show < $max_parts and @via_main ) {
+ my $stop = shift(@via_main);
+ if ( any { $_->name eq $stop->name } @via_show
+ or $stop->name eq $last_stop->name )
+ {
+ next;
+ }
+ push( @via_show, $stop );
+ }
+ }
+
+ return @via_show;
+}
+
+sub TO_JSON {
+ my ($self) = @_;
+
+ # compute on-demand keys
+ $self->id;
+
+ my $ret = { %{$self} };
+
+ delete $ret->{strp_stopseq};
+ delete $ret->{strp_stopseq_s};
+
+ for my $k (qw(datetime rt_datetime sched_datetime)) {
+ if ( $ret->{$k} ) {
+ $ret->{$k} = $ret->{$k}->epoch;
+ }
+ }
+
+ return $ret;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Travel::Status::DE::EFA::Departure - Information about a single
+departure received by Travel::Status::DE::EFA
+
+=head1 SYNOPSIS
+
+ for my $departure ($status->results) {
+ printf(
+ "At %s: %s to %s from platform %d\n",
+ $departure->datetime->strftime('%H:%M'), $departure->line,
+ $departure->destination, $departure->platform
+ );
+ }
+
+=head1 VERSION
+
+version 3.13
+
+=head1 DESCRIPTION
+
+Travel::Status::DE::EFA::Departure describes a single departure as obtained by
+Travel::Status::DE::EFA. It contains information about the time, platform,
+line number and destination.
+
+=head1 METHODS
+
+=head2 ACCESSORS
+
+=over
+
+=item $departure->countdown
+
+Time in minutes from now until the tram/bus/train will depart, including
+realtime data if available.
+
+If delay information is available, it is already included.
+
+=item $departure->datetime
+
+DateTime(3pm) object for departure date and time. Realtime data if available,
+schedule data otherwise.
+
+=item $departure->delay
+
+Expected delay from scheduled departure time in minutes. A delay of 0
+indicates departure on time. undef when no realtime information is available.
+
+=item $departure->destination
+
+Destination name.
+
+=item $departure->hints
+
+Additional information related to the departure (list of strings). If
+departures for an address were requested, this is the stop name, otherwise it
+may be recent news related to the line's schedule.
+
+=item $departure->id
+
+Stringified unique(?) identifier of this departure; suitable for passing to
+Travel::Status::DE::EFA->new(stopseq) after decomposing it again.
+The returned string combines B<stateless>, B<stop_id_num> (or the ID of the first
+stop in B<route_pre>, if present), B<sched_datetime>, and B<key>.
+
+=item $departure->is_cancelled
+
+1 if the departure got cancelled, 0 otherwise.
+
+=item $departure->key
+
+Key of this departure of the corresponding line. Unique for a given day when
+combined with B<stateless>.
+
+=item $departure->line
+
+The name/number of the line.
+
+=item $departure->lineref
+
+Travel::Status::DE::EFA::Line(3pm) object describing the departing line in
+detail.
+
+=item $departure->mot
+
+Returns the "mode of transport" number. This is usually an integer between 0
+and 11.
+
+=item $departure->mot_name
+
+Returns the "mode of transport", for instance "zug", "s-bahn", "tram" or
+"sonstige".
+
+=item $departure->occupancy
+
+Returns expected occupancy, if available, undef otherwise.
+
+Occupancy values are passed from the backend as-is. Known values are
+"MANY_SEATS" (low occupation), "FEW_SEATS" (high occupation),
+"STANDING_ONLY" (very high occupation), and "FULL" (boarding not advised).
+
+=item $departure->origin
+
+Origin name.
+
+=item $departure->platform
+
+Departure platform number (may not be a number).
+
+=item $departure->platform_db
+
+true if the platform number is operated by DB ("Gleis x"), false ("Bstg. x")
+otherwise.
+
+Unfortunately, there is no distinction between tram and bus platforms yet,
+which may also have the same numbers.
+
+=item $departure->route_interesting
+
+List of up to three "interesting" stations served by this departure. Is a
+subset of B<route_post>. Each station is a Travel::Status::DE::EFA::Stop(3pm)
+object.
+
+=item $departure->route_pre
+
+List of stations the vehicle passed (or will have passed) before this stop.
+Each station is a Travel::Status::DE::EFA::Stop(3pm) object.
+
+=item $departure->route_post
+
+List of stations the vehicle will pass after this stop.
+Each station is a Travel::Status::DE::EFA::Stop(3pm) object.
+
+=item $departure->rt_datetime
+
+DateTime(3pm) object holding the departure date and time according to
+realtime data. Undef if unknown / unavailable.
+
+=item $departure->sched_datetime
+
+DateTime(3pm) object holding the scheduled departure date and time.
+
+=item $departure->stateless
+
+Unique line identifier.
+
+=item $departure->train_type
+
+Train type, e.g. "ICE". Typically only defined for long-distance trains.
+
+=item $departure->train_name
+
+Train name, e.g. "ICE International" or "InterCityExpresS" or "Deichgraf".
+Typically only defined for long-distance trains.
+
+=item $departure->train_no
+
+Train number. Only defined if departure is a train.
+
+=item $departure->type
+
+Type of the departure. Note that efa.vrr.de sometimes puts bogus data in this
+field. See L</DEPARTURE TYPES>.
+
+=back
+
+=head2 INTERNAL
+
+=over
+
+=item $departure = Travel::Status::DE::EFA::Departure->new(I<%data>)
+
+Returns a new Travel::Status::DE::EFA::Departure object. You should not need to
+call this.
+
+=item $departure->TO_JSON
+
+Allows the object data to be serialized to JSON.
+
+=back
+
+=head1 DEPARTURE TYPES
+
+The following are known so far:
+
+=over
+
+=item * Abellio-Zug
+
+=item * Bus
+
+=item * Eurocity
+
+=item * Intercity-Express
+
+=item * NE (NachtExpress / night bus)
+
+=item * Niederflurbus
+
+=item * R-Bahn (RE / RegionalExpress)
+
+=item * S-Bahn
+
+=item * SB (Schnellbus)
+
+=item * StraE<szlig>enbahn
+
+=item * U-Bahn
+
+=back
+
+=head1 DIAGNOSTICS
+
+None.
+
+=head1 DEPENDENCIES
+
+=over
+
+=item Class::Accessor(3pm)
+
+=back
+
+=head1 BUGS AND LIMITATIONS
+
+C<< $result->type >> may contain bogus data. This comes from the efa.vrr.de
+interface.
+
+=head1 SEE ALSO
+
+Travel::Status::DE::EFA(3pm).
+
+=head1 AUTHOR
+
+Copyright (C) 2011-2025 Birte Kristina Friesel E<lt>derf@finalrewind.orgE<gt>
+
+=head1 LICENSE
+
+This module is licensed under the same terms as Perl itself.
diff --git a/lib/Travel/Status/DE/EFA/Info.pm b/lib/Travel/Status/DE/EFA/Info.pm
new file mode 100644
index 0000000..424c9f1
--- /dev/null
+++ b/lib/Travel/Status/DE/EFA/Info.pm
@@ -0,0 +1,127 @@
+package Travel::Status::DE::EFA::Info;
+
+use strict;
+use warnings;
+use 5.010;
+
+use parent 'Class::Accessor';
+
+our $VERSION = '3.13';
+
+Travel::Status::DE::EFA::Info->mk_ro_accessors(
+ qw(link_url link_text subject content subtitle additional_text));
+
+sub new {
+ my ( $obj, %opt ) = @_;
+
+ my $json = $opt{json};
+
+ my $ref = {
+ param => {},
+ link_url => $json->{infoLinkURL},
+ link_text => $json->{infoLinkText},
+ subject => $json->{infoText}{subject},
+ content => $json->{infoText}{content},
+ subtitle => $json->{infoText}{subtitle},
+ additional_text => $json->{infoText}{additionalText},
+ };
+
+ for my $param ( @{ $json->{paramList} // [] } ) {
+ $ref->{param}{ $param->{name} } = $param->{value};
+ }
+
+ return bless( $ref, $obj );
+}
+
+sub TO_JSON {
+ my ($self) = @_;
+
+ return { %{$self} };
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Travel::Status::DE::EFA::Info - Information about a public transit stop
+
+=head1 SYNOPSIS
+
+ if ( $info->subject and $info->subtitle ne $info->subject ) {
+ printf( "# %s\n%s\n", $info->subtitle, $info->subject );
+ }
+ else {
+ printf( "# %s\n", $info->subtitle );
+ }
+
+=head1 VERSION
+
+version 3.13
+
+=head1 DESCRIPTION
+
+Travel::Status::DE::EFA::Info holds a single information message related to
+a specific public transit stop.
+
+=head1 ACCESSORS
+
+All accessors may return undef.
+Individual accessors may return identical strings.
+Strings may contain HTML elements.
+
+=over
+
+=item $info->additional_text
+
+=item $info->content
+
+=item $info->link_url
+
+URL to a site related to this information message.
+The site may or may not hold additional data.
+
+=item $info->link_text
+
+Text for linking to link_url.
+
+=item $info->param
+
+Hashref of parameters, e.g. C<< incidentDateTime >> (string describing the
+date/time range during which this message is valid).
+
+=item $info->subject
+
+=item $info->subtitle
+
+=back
+
+=head1 DIAGNOSTICS
+
+None.
+
+=head1 DEPENDENCIES
+
+=over
+
+=item Class::Accessor(3pm)
+
+=back
+
+=head1 BUGS AND LIMITATIONS
+
+This module is a Work in Progress.
+Its API may change between minor versions.
+
+=head1 SEE ALSO
+
+Travel::Status::DE::EFA(3pm).
+
+=head1 AUTHOR
+
+Copyright (C) 2024-2025 Birte Kristina Friesel E<lt>derf@finalrewind.orgE<gt>
+
+=head1 LICENSE
+
+This module is licensed under the same terms as Perl itself.
diff --git a/lib/Travel/Status/DE/EFA/Line.pm b/lib/Travel/Status/DE/EFA/Line.pm
index e5cb3a3..061c904 100644
--- a/lib/Travel/Status/DE/EFA/Line.pm
+++ b/lib/Travel/Status/DE/EFA/Line.pm
@@ -6,10 +6,10 @@ use 5.010;
use parent 'Class::Accessor';
-our $VERSION = '1.17';
+our $VERSION = '3.13';
Travel::Status::DE::EFA::Line->mk_ro_accessors(
- qw(direction mot name operator route type valid));
+ qw(direction mot name number operator route type valid));
my @mot_mapping = qw{
zug s-bahn u-bahn stadtbahn tram stadtbus regionalbus
@@ -57,7 +57,7 @@ requested station
=head1 VERSION
-version 1.17
+version 3.13
=head1 DESCRIPTION
@@ -151,7 +151,7 @@ Travel::Status::DE::EFA(3pm).
=head1 AUTHOR
-Copyright (C) 2011-2015 by Daniel Friesel E<lt>derf@finalrewind.orgE<gt>
+Copyright (C) 2011-2025 Birte Kristina Friesel E<lt>derf@finalrewind.orgE<gt>
=head1 LICENSE
diff --git a/lib/Travel/Status/DE/EFA/Result.pm b/lib/Travel/Status/DE/EFA/Result.pm
deleted file mode 100644
index b8553d7..0000000
--- a/lib/Travel/Status/DE/EFA/Result.pm
+++ /dev/null
@@ -1,330 +0,0 @@
-package Travel::Status::DE::EFA::Result;
-
-use strict;
-use warnings;
-use 5.010;
-
-no if $] >= 5.018, warnings => 'experimental::smartmatch';
-
-use parent 'Class::Accessor';
-
-our $VERSION = '1.17';
-
-Travel::Status::DE::EFA::Result->mk_ro_accessors(
- qw(countdown date delay destination is_cancelled info key line lineref
- mot platform platform_db platform_name sched_date sched_time time type)
-);
-
-my @mot_mapping = qw{
- zug s-bahn u-bahn stadtbahn tram stadtbus regionalbus
- schnellbus seilbahn schiff ast sonstige
-};
-
-sub new {
- my ( $obj, %conf ) = @_;
-
- my $ref = \%conf;
-
- if ( defined $ref->{delay} and $ref->{delay} eq '-9999' ) {
- $ref->{delay} = 0;
- $ref->{is_cancelled} = 1;
- }
- else {
- $ref->{is_cancelled} = 0;
- }
-
- return bless( $ref, $obj );
-}
-
-sub mot_name {
- my ($self) = @_;
-
- return $mot_mapping[ $self->{mot} ] // 'sonstige';
-}
-
-sub route_pre {
- my ($self) = @_;
-
- return @{ $self->{prev_route} };
-}
-
-sub route_post {
- my ($self) = @_;
-
- return @{ $self->{next_route} };
-}
-
-sub route_interesting {
- my ( $self, $max_parts ) = @_;
-
- my @via = $self->route_post;
- my ( @via_main, @via_show, $last_stop );
- $max_parts //= 3;
-
- for my $stop (@via) {
- if (
- $stop->name_suf =~ m{ Bf | Hbf | Flughafen | Hauptbahnhof
- | Krankenhaus | Klinik | (?: S $ ) }ox
- )
- {
- push( @via_main, $stop );
- }
- }
- $last_stop = pop(@via);
-
- if ( @via_main and $via_main[-1] == $last_stop ) {
- pop(@via_main);
- }
- if ( @via and $via[-1] == $last_stop ) {
- pop(@via);
- }
-
- if ( @via_main and @via and $via[0] == $via_main[0] ) {
- shift(@via_main);
- }
-
- if ( @via < $max_parts ) {
- @via_show = @via;
- }
- else {
- if ( @via_main >= $max_parts ) {
- @via_show = ( $via[0] );
- }
- else {
- @via_show = splice( @via, 0, $max_parts - @via_main );
- }
-
- while ( @via_show < $max_parts and @via_main ) {
- my $stop = shift(@via_main);
-
- # FIXME cannot smartmatch $stop since it became an object
- # if ( $stop ~~ \@via_show or $stop == $last_stop ) {
- # next;
- # }
- push( @via_show, $stop );
- }
- }
-
- return @via_show;
-}
-
-sub TO_JSON {
- my ($self) = @_;
-
- return { %{$self} };
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Travel::Status::DE::EFA::Result - Information about a single
-departure received by Travel::Status::DE::EFA
-
-=head1 SYNOPSIS
-
- for my $departure ($status->results) {
- printf(
- "At %s: %s to %s from platform %d\n",
- $departure->time, $departure->line, $departure->destination,
- $departure->platform
- );
- }
-
-=head1 VERSION
-
-version 1.17
-
-=head1 DESCRIPTION
-
-Travel::Status::DE::EFA::Result describes a single departure as obtained by
-Travel::Status::DE::EFA. It contains information about the time, platform,
-line number and destination.
-
-=head1 METHODS
-
-=head2 ACCESSORS
-
-"Actual" in the description means that the delay (if available) is already
-included in the calculation, "Scheduled" means it isn't.
-
-=over
-
-=item $departure->countdown
-
-Actual time in minutes from now until the tram/bus/train will depart.
-
-If delay information is available, it is already included.
-
-=item $departure->date
-
-Actual departure date (DD.MM.YYYY).
-
-=item $departure->delay
-
-Expected delay from scheduled departure time in minutes. A delay of 0
-indicates departure on time. undef when no realtime information is available.
-
-=item $departure->destination
-
-Destination name.
-
-=item $departure->info
-
-Additional information related to the departure (string). If departures for
-an address were requested, this is the stop name, otherwise it may be recent
-news related to the line's schedule. If no information is available, returns
-an empty string.
-
-=item $departure->is_cancelled
-
-1 if the departure got cancelled, 0 otherwise.
-
-=item $departure->key
-
-Unknown. Unlike the name may suggest, this is not a unique key / UUID for a
-departure: On the same day, different lines departing at the same station
-may have the same key. It might, however, be unique when combined with the
-B<line> information.
-
-=item $departure->line
-
-The name/number of the line.
-
-=item $departure->lineref
-
-Travel::Status::DE::EFA::Line(3pm) object describing the departing line in
-detail.
-
-=item $departure->mot
-
-Returns the "mode of transport" number. This is usually an integer between 0
-and 11.
-
-=item $departure->mot_name
-
-Returns the "mode of transport", for instance "zug", "s-bahn", "tram" or
-"sonstige".
-
-=item $departure->platform
-
-Departure platform number (may not be a number).
-
-=item $departure->platform_db
-
-true if the platform number is operated by DB ("Gleis x"), false ("Bstg. x")
-otherwise.
-
-Unfortunately, there is no distinction between tram and bus platforms yet,
-which may also have the same numbers.
-
-=item $departure->route_interesting
-
-List of up to three "interesting" stations served by this departure. Is a
-subset of B<route_post>. Each station is a Travel::Status::DE::EFA::Stop(3pm)
-object.
-
-=item $departure->route_pre
-
-List of stations the train passed (or will have passed) befoe this stop.
-Each station is a Travel::Status::DE::EFA::Stop(3pm) object.
-
-=item $departure->route_post
-
-List of stations the train will pass after this stop.
-Each station is a Travel::Status::DE::EFA::Stop(3pm) object.
-
-=item $departure->sched_date
-
-Scheduled departure date (DD.MM.YYYY).
-
-=item $departure->sched_time
-
-Scheduled departure time (HH:MM).
-
-=item $departure->time
-
-Actual departure time (HH:MM).
-
-=item $departure->type
-
-Type of the departure. Note that efa.vrr.de sometimes puts bogus data in this
-field. See L</DEPARTURE TYPES>.
-
-=back
-
-=head2 INTERNAL
-
-=over
-
-=item $departure = Travel::Status::DE::EFA::Result->new(I<%data>)
-
-Returns a new Travel::Status::DE::EFA::Result object. You should not need to
-call this.
-
-=item $departure->TO_JSON
-
-Allows the object data to be serialized to JSON.
-
-=back
-
-=head1 DEPARTURE TYPES
-
-The following are known so far:
-
-=over
-
-=item * Abellio-Zug
-
-=item * Bus
-
-=item * Eurocity
-
-=item * Intercity-Express
-
-=item * NE (NachtExpress / night bus)
-
-=item * Niederflurbus
-
-=item * R-Bahn (RE / RegionalExpress)
-
-=item * S-Bahn
-
-=item * SB (Schnellbus)
-
-=item * StraE<szlig>enbahn
-
-=item * U-Bahn
-
-=back
-
-=head1 DIAGNOSTICS
-
-None.
-
-=head1 DEPENDENCIES
-
-=over
-
-=item Class::Accessor(3pm)
-
-=back
-
-=head1 BUGS AND LIMITATIONS
-
-C<< $result->type >> may contain bogus data. This comes from the efa.vrr.de
-interface.
-
-=head1 SEE ALSO
-
-Travel::Status::DE::EFA(3pm).
-
-=head1 AUTHOR
-
-Copyright (C) 2011-2015 by Daniel Friesel E<lt>derf@finalrewind.orgE<gt>
-
-=head1 LICENSE
-
-This module is licensed under the same terms as Perl itself.
diff --git a/lib/Travel/Status/DE/EFA/Services.pm.PL b/lib/Travel/Status/DE/EFA/Services.pm.PL
new file mode 100644
index 0000000..81027d7
--- /dev/null
+++ b/lib/Travel/Status/DE/EFA/Services.pm.PL
@@ -0,0 +1,147 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+use 5.014;
+use utf8;
+use Data::Dumper;
+use Encode qw(encode);
+use File::Slurp qw(read_file write_file);
+use JSON;
+
+my $json = JSON->new->utf8;
+
+sub load_instance {
+ my ( $path, %opt ) = @_;
+
+ my $data = $json->decode(
+ scalar read_file("ext/transport-apis/data/${path}-efa.json") );
+ my %ret = (
+ name => $opt{name} // $data->{name} =~ s{ *[(][^)]+[)]}{}r,
+ homepage => $data->{attribution}{homepage},
+ url => $opt{url} // $data->{options}{endpoint} =~ s{ / $ }{}rx,
+ time_zone => $data->{timezone},
+ languages => $data->{supportedLanguages},
+ coverage => {
+ area => $data->{coverage}{realtimeCoverage}{area},
+ regions => $data->{coverage}{realtimeCoverage}{region} // []
+ },
+ );
+
+ return %ret;
+}
+
+# GVH: 403
+# VRT: Encoding issues
+# VVSt: NXDOMAIN
+my %efa_instance = (
+ BEG => {
+ url => 'https://bahnland-bayern.de/efa',
+ name => 'Bayerische Eisenbahngesellschaft',
+ },
+ BSVG => {
+ url => 'https://bsvg.efa.de/bsvagstd',
+ name => 'Braunschweiger Verkehrs-GmbH',
+ },
+ bwegt => { load_instance('de/bwegt') },
+ DING => {
+ url => 'https://www.ding.eu/ding3',
+ name => 'Donau-Iller Nahverkehrsverbund',
+ },
+ KVV => { load_instance('de/kvv') },
+ LinzAG => {
+ url => 'https://www.linzag.at/static',
+ name => 'Linz AG',
+ encoding => 'iso-8859-15',
+ },
+ MVV => { load_instance('de/mvv') },
+ NVBW => {
+ url => 'https://www.efa-bw.de/nvbw',
+ name => 'Nahverkehrsgesellschaft Baden-Württemberg',
+ },
+ NWL => {
+ url => 'https://westfalenfahrplan.de/nwl-efa',
+ name => 'Nahverkehr Westfalen-Lippe',
+ },
+ Rolph => { load_instance('de/rolph') },
+ RVV => {
+ url => 'https://efa.rvv.de/efa',
+ name => 'Regensburger Verkehrsverbund',
+ },
+ VAG => {
+ url => 'https://efa.vagfr.de/vagfr3',
+ name => 'Freiburger Verkehrs AG',
+ },
+ VGN =>
+ { load_instance( 'de/vgn', url => 'https://efa.vgn.de/vgnExt_oeffi' ) },
+ VMV => { load_instance('de/vmv') },
+ VRN => {
+ url => 'https://www.vrn.de/mngvrn/',
+ name => 'Verkehrsverbund Rhein-Neckar',
+ },
+ VRR => {
+ load_instance(
+ 'de/vrr',
+ url => 'https://efa.vrr.de/vrr',
+ ),
+ },
+ VRR2 => { load_instance('de/vrr') },
+ VRR3 => { load_instance( 'de/vrr', url => 'https://efa.vrr.de/rbgstd3' ) },
+ VVO => {
+ url => 'https://efa.vvo-online.de/VMSSL3',
+ name => 'Verkehrsverbund Oberelbe',
+ },
+ VVS => { load_instance('de/vvs') },
+
+);
+
+my $buf = <<'__EOF__';
+package Travel::Status::DE::EFA::Services;
+
+# vim:readonly
+# This package has been automatically generated
+# by lib/Travel/Status/DE/EFA/Services.pm.PL.
+# Do not edit, changes will be lost.
+
+use strict;
+use warnings;
+use 5.014;
+use utf8;
+
+our $VERSION = '3.13';
+
+# Most of these have been adapted from
+# <https://github.com/public-transport/transport-apis> and
+# <https://github.com/public-transport/hafas-client/tree/main/p>.
+# Many thanks to Jannis R / @derhuerst and all contributors for maintaining
+# these resources.
+
+__EOF__
+
+my $perlobj = Data::Dumper->new( [ \%efa_instance ], ['efa_instance'] );
+
+$buf .= 'my ' . $perlobj->Sortkeys(1)->Indent(0)->Dump;
+
+$buf .= <<'__EOF__';
+
+sub get_service_ids {
+ return sort keys %{$efa_instance};
+}
+
+sub get_service {
+ my ($service) = @_;
+ return $efa_instance->{$service};
+}
+
+sub get_service_ref {
+ return $efa_instance;
+}
+
+sub get_service_map {
+ return %{$efa_instance};
+}
+
+1;
+__EOF__
+
+write_file( $ARGV[0], { binmode => ':utf8' }, $buf );
diff --git a/lib/Travel/Status/DE/EFA/Stop.pm b/lib/Travel/Status/DE/EFA/Stop.pm
index 566caa8..910111e 100644
--- a/lib/Travel/Status/DE/EFA/Stop.pm
+++ b/lib/Travel/Status/DE/EFA/Stop.pm
@@ -4,27 +4,71 @@ use strict;
use warnings;
use 5.010;
-no if $] >= 5.018, warnings => 'experimental::smartmatch';
-
use parent 'Class::Accessor';
-our $VERSION = '1.17';
+our $VERSION = '3.13';
Travel::Status::DE::EFA::Stop->mk_ro_accessors(
- qw(arr_date arr_time dep_date dep_time name name_suf platform));
+ qw(sched_arr rt_arr arr arr_delay
+ sched_dep rt_dep dep dep_delay
+ occupancy delay distance_m is_cancelled
+ place name full_name id_num id_code latlon
+ platform niveau)
+);
sub new {
my ( $obj, %conf ) = @_;
my $ref = \%conf;
+ if ( $ref->{sched_arr} and $ref->{arr_delay} and not $ref->{rt_arr} ) {
+ $ref->{rt_arr}
+ = $ref->{sched_arr}->clone->add( minutes => $ref->{arr_delay} );
+ }
+
+ if ( $ref->{sched_dep} and $ref->{dep_delay} and not $ref->{rt_dep} ) {
+ $ref->{rt_dep}
+ = $ref->{sched_dep}->clone->add( minutes => $ref->{dep_delay} );
+ }
+
+ $ref->{arr} //= $ref->{rt_arr} // $ref->{sched_arr};
+ $ref->{dep} //= $ref->{rt_dep} // $ref->{sched_dep};
+
+ if ( $ref->{rt_arr}
+ and $ref->{sched_arr}
+ and not defined $ref->{arr_delay} )
+ {
+ $ref->{arr_delay}
+ = $ref->{rt_arr}->subtract_datetime( $ref->{sched_arr} )
+ ->in_units('minutes');
+ }
+
+ if ( $ref->{rt_dep}
+ and $ref->{sched_dep}
+ and not defined $ref->{dep_delay} )
+ {
+ $ref->{dep_delay}
+ = $ref->{rt_dep}->subtract_datetime( $ref->{sched_dep} )
+ ->in_units('minutes');
+ }
+
+ $ref->{delay} = $ref->{dep_delay} // $ref->{arr_delay};
+
return bless( $ref, $obj );
}
sub TO_JSON {
my ($self) = @_;
- return { %{$self} };
+ my $ret = { %{$self} };
+
+ for my $k (qw(sched_arr rt_arr arr sched_dep rt_dep dep)) {
+ if ( $ret->{$k} ) {
+ $ret->{$k} = $ret->{$k}->epoch;
+ }
+ }
+
+ return $ret;
}
1;
@@ -41,14 +85,15 @@ in a Travel::Status::DE::EFA::Result's route
for my $stop ($departure->route_post) {
printf(
"%s -> %s : %40s %s\n",
- $stop->arr_time // q{ }, $stop->dep_time // q{ },
+ $stop->arr ? $stop->arr->strftime('%H:%M') : q{--:--},
+ $stop->dep ? $stop->dep->strftime('%H:%M') : q{--:--},
$stop->name, $stop->platform
);
}
=head1 VERSION
-version 1.17
+version 3.13
=head1 DESCRIPTION
@@ -60,32 +105,77 @@ delays or changed platforms are not taken into account.
=head2 ACCESSORS
+Most accessors return undef if the corresponding data is not available.
+
=over
-=item $stop->arr_date
+=item $stop->sched_arr
-arrival date (DD.MM.YYYY). undef if this is the first scheduled stop.
+DateTime(3pm) object holding scheduled arrival date and time.
-=item $stop->arr_time
+=item $stop->rt_arr
-arrival time (HH:MM). undef if this is the first scheduled stop.
+DateTime(3pm) object holding estimated (real-time) arrival date and time.
-=item $stop->dep_date
+=item $stop->arr
-departure date (DD.MM.YYYY). undef if this is the final scehduled stop.
+DateTime(3pm) object holding arrival date and time. Real-time data if
+available, schedule data otherwise.
-=item $stop->dep_time
+=item $stop->arr_delay
-departure time (HH:MM). undef if this is the final scehduled stop.
+Arrival delay in minutes.
-=item $stop->name
+=item $stop->sched_dep
+
+DateTime(3pm) object holding scheduled departure date and time.
+
+=item $stop->rt_dep
+
+DateTime(3pm) object holding estimated (real-time) departure date and time.
+
+=item $stop->dep
+
+DateTime(3pm) object holding departure date and time. Real-time data if
+available, schedule data otherwise.
+
+=item $stop->dep_delay
+
+Departure delay in minutes.
+
+=item $stop->delay
-stop name with city prefix ("I<City> I<Stop>", for instance
+Delay in minutes. Departure delya if available, arrival delay otherwise.
+
+=item $stop->distance_m
+
+Distance from request coordinates in meters. undef if the object has not
+been obtained by means of a coord request.
+
+=item $stop->id_num
+
+Stop ID (numeric).
+
+=item $stop->id_code
+
+Stop ID (code).
+
+=item $stop->place
+
+Place or city name, for instance "Essen".
+
+=item $stop->full_name
+
+stop name with place or city prefix ("I<City> I<Stop>", for instance
"Essen RE<uuml>ttenscheider Stern").
-=item $stop->name_suf
+=item $stop->name
+
+stop name without place or city prefix, for instance "RE<uuml>ttenscheider Stern".
+
+=item $stop->latlon
-stop name without city prefix, for instance "RE<uuml>ttenscheider Stern".
+Arrayref describing the stop's latitude and longitude in WGS84 coordinates.
=item $stop->platform
@@ -122,7 +212,8 @@ None.
=head1 BUGS AND LIMITATIONS
-None known.
+This module is a Work in Progress.
+Its API may change between minor versions.
=head1 SEE ALSO
@@ -130,7 +221,7 @@ Travel::Status::DE::EFA(3pm).
=head1 AUTHOR
-Copyright (C) 2015 by Daniel Friesel E<lt>derf@finalrewind.orgE<gt>
+Copyright (C) 2015-2025 Birte Kristina Friesel E<lt>derf@finalrewind.orgE<gt>
=head1 LICENSE
diff --git a/lib/Travel/Status/DE/EFA/Trip.pm b/lib/Travel/Status/DE/EFA/Trip.pm
new file mode 100644
index 0000000..5b86695
--- /dev/null
+++ b/lib/Travel/Status/DE/EFA/Trip.pm
@@ -0,0 +1,342 @@
+package Travel::Status::DE::EFA::Trip;
+
+use strict;
+use warnings;
+use 5.010;
+
+use DateTime::Format::Strptime;
+use Travel::Status::DE::EFA::Stop;
+
+use parent 'Class::Accessor';
+
+our $VERSION = '3.13';
+
+Travel::Status::DE::EFA::Trip->mk_ro_accessors(
+ qw(operator product product_class name line number type id dest_name dest_id)
+);
+
+sub new {
+ my ( $obj, %conf ) = @_;
+
+ my $json = $conf{json}{transportation} // $conf{json}{leg}{transportation};
+
+ my $ref = {
+ operator => $json->{operator}{name},
+ product => $json->{product}{name},
+ product_class => $json->{product}{class},
+ polyline_raw => $conf{json}{leg}{coords},
+ name => $json->{name},
+ line => $json->{disassembledName},
+ number => $json->{properties}{trainNumber},
+ type => $json->{properties}{trainType} // $json->{product}{name},
+ id => $json->{id},
+ dest_name => $json->{destination}{name},
+ dest_id => $json->{destination}{id},
+ route_raw => $json->{locationSequence}
+ // $conf{json}{leg}{stopSequence},
+ strptime_obj => DateTime::Format::Strptime->new(
+ pattern => '%Y-%m-%dT%H:%M:%SZ',
+ time_zone => 'UTC'
+ ),
+ };
+ if ( ref( $ref->{polyline_raw} ) eq 'ARRAY'
+ and @{ $ref->{polyline_raw} } == 1 )
+ {
+ $ref->{polyline_raw} = $ref->{polyline_raw}[0];
+ }
+ return bless( $ref, $obj );
+}
+
+sub polyline {
+ my ( $self, %opt ) = @_;
+
+ if ( $self->{polyline} ) {
+ return @{ $self->{polyline} };
+ }
+
+ if ( not @{ $self->{polyline_raw} // [] } ) {
+ if ( $opt{fallback} ) {
+ return map {
+ {
+ lat => $_->{latlon}[0],
+ lon => $_->{latlon}[1],
+ stop => $_,
+ }
+ } $self->route;
+ }
+ return;
+ }
+
+ $self->{polyline} = [ map { { lat => $_->[0], lon => $_->[1] } }
+ @{ $self->{polyline_raw} } ];
+ my $distance;
+
+ eval {
+ require GIS::Distance;
+ $distance = GIS::Distance->new;
+ };
+
+ if ($distance) {
+ my %min_dist;
+ for my $stop ( $self->route ) {
+ for my $polyline_index ( 0 .. $#{ $self->{polyline} } ) {
+ my $pl = $self->{polyline}[$polyline_index];
+ my $dist = $distance->distance_metal(
+ $stop->{latlon}[0],
+ $stop->{latlon}[1],
+ $pl->{lat}, $pl->{lon}
+ );
+ if ( not $min_dist{ $stop->{id_code} }
+ or $min_dist{ $stop->{id_code} }{dist} > $dist )
+ {
+ $min_dist{ $stop->{id_code} } = {
+ dist => $dist,
+ index => $polyline_index,
+ };
+ }
+ }
+ }
+ for my $stop ( $self->route ) {
+ if ( $min_dist{ $stop->{id_code} } ) {
+ $self->{polyline}[ $min_dist{ $stop->{id_code} }{index} ]{stop}
+ = $stop;
+ }
+ }
+ }
+
+ return @{ $self->{polyline} };
+}
+
+sub parse_dt {
+ my ( $self, $value ) = @_;
+
+ if ($value) {
+ my $dt = $self->{strptime_obj}->parse_datetime($value);
+ if ($dt) {
+ return $dt->set_time_zone('Europe/Berlin');
+ }
+ }
+ return undef;
+}
+
+sub route {
+ my ($self) = @_;
+
+ if ( $self->{route} ) {
+ return @{ $self->{route} };
+ }
+
+ for my $stop ( @{ $self->{route_raw} // [] } ) {
+ my $chain = $stop;
+ my ( $platform, $place, $name, $name_full, $id_num, $id_code );
+ while ( $chain->{type} ) {
+ if ( $chain->{type} eq 'platform' ) {
+ $platform = $chain->{properties}{platformName}
+ // $chain->{properties}{platform};
+ }
+ elsif ( $chain->{type} eq 'stop' ) {
+ $name = $chain->{disassembledName};
+ $name_full = $chain->{name};
+ $id_code = $chain->{id};
+ $id_num = $chain->{properties}{stopId};
+ }
+ elsif ( $chain->{type} eq 'locality' ) {
+ $place = $chain->{name};
+ }
+ $chain = $chain->{parent};
+ }
+ push(
+ @{ $self->{route} },
+ Travel::Status::DE::EFA::Stop->new(
+ sched_arr => $self->parse_dt( $stop->{arrivalTimePlanned} ),
+ sched_dep => $self->parse_dt( $stop->{departureTimePlanned} ),
+ rt_arr => $self->parse_dt( $stop->{arrivalTimeEstimated} ),
+ rt_dep => $self->parse_dt( $stop->{departureTimeEstimated} ),
+ occupancy => $stop->{properties}{occupancy},
+ is_cancelled => $stop->{isCancelled},
+ latlon => $stop->{coord},
+ full_name => $name_full,
+ name => $name,
+ place => $place,
+ niveau => $stop->{niveau},
+ platform => $platform,
+ id_code => $id_code,
+ id_num => $id_num,
+ )
+ );
+ }
+
+ delete $self->{route_raw};
+
+ return @{ $self->{route} // [] };
+}
+
+sub TO_JSON {
+ my ($self) = @_;
+
+ # lazy loading
+ $self->route;
+
+ # lazy loading
+ $self->polyline;
+
+ my $ret = { %{$self} };
+
+ delete $ret->{strptime_obj};
+
+ return $ret;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Travel::Status::DE::EFA::Trip - Information about an individual public transit
+trip
+
+=head1 SYNOPSIS
+
+ printf( "%s %s -> %s\n", $trip->type, $trip->line // q{}, $trip->dest_name );
+ for my $stop ( $trip->route ) {
+ ...;
+ }
+
+=head1 VERSION
+
+version 3.13
+
+=head1 DESCRIPTION
+
+Travel::Status::DE::EFA::Trip describes a single trip / journey of a public
+transport line.
+
+=head1 METHODS
+
+=head2 ACCESSORS
+
+Most accessors return undef if the corresponding data is not available.
+
+=over
+
+=item $trip->operator
+
+Operator name.
+
+=item $trip->product
+
+Product name.
+
+=item $trip->product_class
+
+Product class.
+
+=item $trip->name
+
+Trip or line name.
+
+=item $trip->line
+
+Line identifier. Note that this is not necessarily numeric.
+
+=item $trip->number
+
+Trip/journey number.
+
+=item $trip->type
+
+Transport / vehicle type, e.g. "RE" or "Bus".
+
+=item $trip->id
+
+Unique(?) trip ID
+
+=item $trip->dest_name
+
+Name of the trip's destination stop
+
+=item $trip->dest_id
+
+ID of the trip's destination stop
+
+=item $trip->route
+
+List of Travel::Status::DE::EFA::Stop(3pm) objects describing the route of this
+trip.
+
+Note: The EFA API requires a stop to be specified when requesting trip details.
+The stops returned by this accessor appear to be limited to stops after the
+requested stop; earlier ones may be missing.
+
+=item $journey->polyline(I<%opt>)
+
+List of geocoordinates that describe the trips's route.
+Each list entry is a hash with the following keys.
+
+=over
+
+=item * lon (longitude)
+
+=item * lat (latitude)
+
+=item * stop (Stop object for this location, if any. undef otherwise)
+
+=back
+
+Note that stop is not provided by the backend and instead inferred by this
+module.
+
+If the backend does not provide geocoordinates and this accessor was called
+with B< fallback > set to a true value, it returns the list of stop coordinates
+instead. Otherwise, it returns an empty list.
+
+=back
+
+=head2 INTERNAL
+
+=over
+
+=item $trip = Travel::Status::DE::EFA::Trip->new(I<%data>)
+
+Returns a new Travel::Status::DE::EFA::Trip object. You should not need to
+call this.
+
+=item $trip->TO_JSON
+
+Allows the object data to be serialized to JSON.
+
+=back
+
+=head1 DIAGNOSTICS
+
+None.
+
+=head1 DEPENDENCIES
+
+=over
+
+=item Class::Accessor(3pm)
+
+=item DateTime::Format::Strptime(3pm)
+
+=item Travel::Status::DE::EFA::Stop(3pm)
+
+=back
+
+=head1 BUGS AND LIMITATIONS
+
+This module is a Work in Progress.
+Its API may change between minor versions.
+
+=head1 SEE ALSO
+
+Travel::Status::DE::EFA(3pm).
+
+=head1 AUTHOR
+
+Copyright (C) 2024-2025 Birte Kristina Friesel E<lt>derf@finalrewind.orgE<gt>
+
+=head1 LICENSE
+
+This module is licensed under the same terms as Perl itself.
diff --git a/lib/Travel/Status/DE/VRR.pm b/lib/Travel/Status/DE/VRR.pm
index 9552e73..6782523 100644
--- a/lib/Travel/Status/DE/VRR.pm
+++ b/lib/Travel/Status/DE/VRR.pm
@@ -4,9 +4,7 @@ use strict;
use warnings;
use 5.010;
-no if $] >= 5.018, warnings => "experimental::smartmatch";
-
-our $VERSION = '1.17';
+our $VERSION = '3.13';
use parent 'Travel::Status::DE::EFA';
@@ -37,14 +35,15 @@ Travel::Status::DE::VRR - unofficial VRR departure monitor.
for my $d ($status->results) {
printf(
"%s %d %-5s %s\n",
- $d->time, $d->platform, $d->line, $d->destination
+ $d->datetime->strftime('%H:%M'),
+ $d->platform, $d->line, $d->destination
);
}
=head1 VERSION
-version 1.17
+version 3.13
=head1 DESCRIPTION
@@ -96,7 +95,7 @@ efa-m(1), Travel::Status::DE::EFA(3pm).
=head1 AUTHOR
-Copyright (C) 2013-2015 by Daniel Friesel E<lt>derf@finalrewind.orgE<gt>
+Copyright (C) 2013-2023 Birte Kristina Friesel E<lt>derf@finalrewind.orgE<gt>
=head1 LICENSE
diff --git a/scripts/check-efa-urls b/scripts/check-efa-urls
index 6ae1473..3cb8a35 100755
--- a/scripts/check-efa-urls
+++ b/scripts/check-efa-urls
@@ -2,29 +2,27 @@
export PERL5LIB=lib
-checks="BSVG Braunschweig Hbf
+checks="BEG Dachau Dachau Bahnhof
+BSVG Braunschweig Hbf
DING Ulm Hbf
KVV Karlsruhe Hbf
-LinzAG Linz Hbf
+LinzAG Linz/Donau Hbf
MVV München Hackerbrücke
NVBW Stuttgart Hbf (A.-Klett-Pl.)
-SVV Salzburg Hbf
-TLEM London Waterloo East
+RVV Regensburg Hbf
VAG Schallstadt Bf
-VBL Luzern Bf
-Verbundlinie Graz Hbf
VGN Nürnberg Hbf
VMV Schwerin Hbf
-VOR Wien Hbf
VRN Mannheim Hbf
VRR Essen Hbf
VRR2 Essen Hbf
+VRR3 Essen Hbf
VVO Dresden Hbf
VVS Stuttgart Schwabstraße"
echo $checks | while read service name place; do
echo -n "${service} ... "
- if bin/efa-m -s $service $name $place > /dev/null; then
+ if perl -Ilib bin/efa-m -s $service $name $place > /dev/null; then
echo OK
fi
done
diff --git a/scripts/makedeb-docker-helper b/scripts/makedeb-docker-helper
index c249efd..f6f309d 100755
--- a/scripts/makedeb-docker-helper
+++ b/scripts/makedeb-docker-helper
@@ -8,8 +8,9 @@ export APT_LISTCHANGES_FRONTEND=none
apt-get update
apt-get -y install \
apt-file dh-make-perl libmodule-build-perl \
- libclass-accessor-perl libexception-class-perl libfile-slurp-perl \
- libwww-perl libxml-libxml-perl \
+ libclass-accessor-perl libdatetime-perl libdatetime-format-strptime-perl \
+ libexception-class-perl libfile-slurp-perl libwww-perl \
+ libjson-perl libjson-xs-perl \
libtest-compile-perl libtest-pod-perl \
libtest-fatal-perl libtest-simple-perl
@@ -18,7 +19,7 @@ apt-cache dumpavail | dpkg --merge-avail
mkdir -p /src/app
cp -a /orig/Build.PL /orig/Changelog /orig/README.md /src/app
-cp -a /orig/bin /orig/lib /orig/t /src/app
+cp -a /orig/bin /orig/ext /orig/lib /orig/t /src/app
cd /src/app
sed -i 's/sign *=> *1/sign => 0/' Build.PL
diff --git a/t/20-vrr.t b/t/20-vrr.t
index 31fa6ca..52c7941 100644
--- a/t/20-vrr.t
+++ b/t/20-vrr.t
@@ -4,64 +4,83 @@ use warnings;
use 5.010;
use utf8;
-use Encode qw(decode);
+use Encode qw(decode);
use File::Slurp qw(slurp);
-use Test::More tests => 113;
+use JSON;
+use Test::More tests => 112;
BEGIN {
use_ok('Travel::Status::DE::VRR');
}
require_ok('Travel::Status::DE::VRR');
-my $xml = slurp('t/in/essen_hb.xml');
+my $json = JSON->new->utf8->decode( scalar slurp('t/in/essen_bp.json') );
-my $status = Travel::Status::DE::VRR->new_from_xml(xml => $xml);
+my $status = Travel::Status::DE::VRR->new( from_json => $json );
-isa_ok($status, 'Travel::Status::DE::EFA');
-can_ok($status, qw(errstr results));
+isa_ok( $status, 'Travel::Status::DE::EFA' );
+can_ok( $status, qw(errstr results) );
-is($status->errstr, undef, 'no error');
-is_deeply([$status->identified_data], [qw[Essen Hauptbahnhof]], 'identified_data');
+is( $status->errstr, undef, 'no error' );
my @results = $status->results;
for my $result (@results) {
- isa_ok($result, 'Travel::Status::DE::EFA::Result');
- can_ok($result, qw(date destination info line time type platform));
+ isa_ok( $result, 'Travel::Status::DE::EFA::Departure' );
+ can_ok( $result,
+ qw(datetime destination hints line type platform sched_datetime) );
}
-is($results[0]->destination, 'Düsseldorf Hbf', 'first result: destination ok');
-is($results[0]->info, 'Bordrestaurant', 'first result: no info');
-is($results[0]->line, 'ICE 946 Intercity-Express', 'first result: line ok');
-is($results[0]->date, '16.11.2011', 'first result: real date ok');
-is($results[0]->time, '09:40', 'first result: real time ok');
-is($results[0]->delay, 4, 'first result: delay 4');
-is($results[0]->sched_date, '16.11.2011', 'first result: scheduled date ok');
-is($results[0]->sched_time, '09:36', 'first result: scheduled time ok');
-is($results[0]->mot_name, 'zug', 'first result: mot_name ok');
-#is($results[0]->platform, '1', 'first result: platform ok');
-#is($results[0]->platform_db, 1, 'first result: platform_db ok');
+is(
+ $results[0]->destination,
+ 'Essen Germaniaplatz',
+ 'first result: destination ok'
+);
+is_deeply( [ $results[0]->hints ], [], 'first result: no hints' );
+is( $results[0]->line, '106', 'first result: line ok' );
+is( $results[0]->datetime->strftime('%d.%m.%Y'),
+ '21.09.2024', 'first result: real date ok' );
+is( $results[0]->datetime->strftime('%H:%M'),
+ '18:35', 'first result: real time ok' );
+is( $results[0]->delay, 0, 'first result: delay 0' );
+is( $results[0]->sched_datetime->strftime('%d.%m.%Y'),
+ '21.09.2024', 'first result: scheduled date ok' );
+is( $results[0]->sched_datetime->strftime('%H:%M'),
+ '18:35', 'first result: scheduled time ok' );
+is( $results[0]->mot_name, 'tram', 'first result: mot_name ok' );
-is($results[3]->destination, 'Mülheim Heißen Kirche', 'fourth result: destination ok');
-is($results[3]->info, 'Ab (H) Heißen Kirche, Umstieg in den SEV Ri. Mülheim Hbf.', 'fourth result: no info');
-is($results[3]->line, '18', 'fourth result: line ok');
-is($results[3]->date, '16.11.2011', 'fourth result: real date ok');
-is($results[3]->time, '09:39', 'fourth result: real time ok');
-is($results[3]->delay, undef, 'fourth result: delay undef');
-is($results[3]->sched_date, '16.11.2011', 'fourth result: scheduled date ok');
-is($results[3]->sched_time, '09:39', 'fourth result: scheduled time ok');
-is($results[3]->mot_name, 'u-bahn', 'fourth result: mot_name ok');
-#is($results[3]->platform, '2', 'fourth result: platform ok');
-#is($results[3]->platform_db, 0, 'fourth result: platform_db ok');
+is(
+ $results[3]->destination,
+ 'Gelsenkirchen Buerer Str.',
+ 'fourth result: destination ok'
+);
+is_deeply( [ $results[3]->hints ], [], 'fourth result: no hints' );
+is( $results[3]->line, 'U11', 'fourth result: line ok' );
+is( $results[3]->datetime->strftime('%d.%m.%Y'),
+ '21.09.2024', 'fourth result: real date ok' );
+is( $results[3]->datetime->strftime('%H:%M'),
+ '18:36', 'fourth result: real time ok' );
+is( $results[3]->delay, 0, 'fourth result: delay 0' );
+is( $results[3]->sched_datetime->strftime('%d.%m.%Y'),
+ '21.09.2024', 'fourth result: scheduled date ok' );
+is( $results[3]->sched_datetime->strftime('%H:%M'),
+ '18:36', 'fourth result: scheduled time ok' );
+is( $results[3]->mot_name, 'u-bahn', 'fourth result: mot_name ok' );
-is($results[-1]->destination, 'Hamm (Westf)', 'last result: destination ok');
-is($results[-1]->info, 'Fahrradmitnahme begrenzt möglich', 'last result: info ok');
-is($results[-1]->delay, 12, 'last result: delay 12');
-is($results[-1]->line, 'RE1', 'last result: line ok');
-is($results[-1]->date, '16.11.2011', 'last result: date ok');
-is($results[-1]->time, '10:05', 'last result: time ok');
-is($results[-1]->sched_date, '16.11.2011', 'first result: scheduled date ok');
-is($results[-1]->sched_time, '09:53', 'last result: scheduled time ok');
-is($results[-1]->mot_name, 'zug', 'last result: mot_name ok');
-#is($results[-1]->platform, '6', 'last result: platform ok');
-#is($results[-1]->platform_db, 1, 'last result: platform ok');
+is(
+ $results[-1]->destination,
+ 'Essen Zeche Ludwig',
+ 'last result: destination ok'
+);
+is_deeply( [ $results[-1]->hints ], [], 'last result: no hints' );
+is( $results[-1]->delay, 0, 'last result: delay 0' );
+is( $results[-1]->line, '105', 'last result: line ok' );
+is( $results[-1]->datetime->strftime('%d.%m.%Y'),
+ '21.09.2024', 'last result: date ok' );
+is( $results[-1]->datetime->strftime('%H:%M'), '19:08',
+ 'last result: time ok' );
+is( $results[-1]->sched_datetime->strftime('%d.%m.%Y'),
+ '21.09.2024', 'first result: scheduled date ok' );
+is( $results[-1]->sched_datetime->strftime('%H:%M'),
+ '19:08', 'last result: scheduled time ok' );
+is( $results[-1]->mot_name, 'tram', 'last result: mot_name ok' );
diff --git a/t/21-vrr-ambig.t b/t/21-vrr-ambig.t
index e4783f5..de03b30 100644
--- a/t/21-vrr-ambig.t
+++ b/t/21-vrr-ambig.t
@@ -5,27 +5,36 @@ use 5.010;
use utf8;
use File::Slurp qw(slurp);
-use Test::More tests => 10;
+use JSON;
+use Test::More tests => 9;
BEGIN {
use_ok('Travel::Status::DE::VRR');
}
require_ok('Travel::Status::DE::VRR');
-my $xml = slurp('t/in/essen_alfredusbad_ambiguous.xml');
+my $json
+ = JSON->new->utf8->decode( scalar slurp('t/in/essen_alfred_ambiguous.json') );
-my $status = Travel::Status::DE::VRR->new_from_xml(xml => $xml);
+my $status = Travel::Status::DE::VRR->new( from_json => $json );
-isa_ok($status, 'Travel::Status::DE::VRR');
-can_ok($status, qw(errstr results));
+isa_ok( $status, 'Travel::Status::DE::VRR' );
+can_ok( $status, qw(errstr results) );
$status->check_for_ambiguous();
-is($status->errstr, 'ambiguous name parameter', 'errstr ok');
-
-is_deeply([$status->place_candidates], [], 'place candidates ok');
-is_deeply([$status->name_candidates], ['Alfredusbad', 'Am Alfredusbad'], 'name candidates ok');
-
-is_deeply([$status->lines], [], 'no lines');
-is_deeply([$status->results], [], 'no results');
-is_deeply([$status->identified_data], [qw[Essen Alfredusbad]], 'identified data');
+is( $status->errstr, 'ambiguous name parameter', 'errstr ok' );
+
+is_deeply( [ $status->place_candidates ], [], 'place candidates ok' );
+is_deeply(
+ [ map { $_->id_num . ' ' . $_->full_name } $status->name_candidates ],
+ [
+ '20009114 Essen, Alfred-Krupp-Schule',
+ '20009113 Essen, Alfredbrücke',
+ '20009115 Essen, Alfredusbad',
+ ],
+ 'name candidates ok'
+);
+
+is_deeply( [ $status->lines ], [], 'no lines' );
+is_deeply( [ $status->results ], [], 'no results' );
diff --git a/t/in/essen_alfred_ambiguous.json b/t/in/essen_alfred_ambiguous.json
new file mode 100644
index 0000000..1cf215e
--- /dev/null
+++ b/t/in/essen_alfred_ambiguous.json
@@ -0,0 +1,327 @@
+{
+ "dm" : {
+ "message" : [
+ {
+ "value" : "1",
+ "name" : "code"
+ },
+ {
+ "value" : "name list",
+ "name" : "error"
+ },
+ {
+ "name" : "type",
+ "value" : ""
+ },
+ {
+ "name" : "module",
+ "value" : "BROKER"
+ }
+ ],
+ "input" : {
+ "input" : "Alfred"
+ },
+ "points" : [
+ {
+ "usage" : "dm",
+ "tariffLayer2" : "",
+ "stateless" : "20009114",
+ "type" : "stop",
+ "name" : "Essen, Alfred-Krupp-Schule",
+ "tariffAreaName" : "",
+ "tariffArea" : "",
+ "ref" : {
+ "gid" : "",
+ "place" : "Essen",
+ "omc" : "5113000",
+ "id" : "20009114",
+ "placeID" : "18"
+ },
+ "tariffLayer1" : ""
+ },
+ {
+ "name" : "Essen, Alfredbrücke",
+ "type" : "stop",
+ "stateless" : "20009113",
+ "tariffLayer2" : "",
+ "usage" : "dm",
+ "tariffAreaName" : "",
+ "ref" : {
+ "gid" : "",
+ "place" : "Essen",
+ "placeID" : "18",
+ "omc" : "5113000",
+ "id" : "20009113"
+ },
+ "tariffArea" : "",
+ "tariffLayer1" : ""
+ },
+ {
+ "ref" : {
+ "omc" : "5113000",
+ "id" : "20009115",
+ "placeID" : "18",
+ "gid" : "",
+ "place" : "Essen"
+ },
+ "tariffArea" : "",
+ "tariffLayer1" : "",
+ "name" : "Essen, Alfredusbad",
+ "type" : "stop",
+ "stateless" : "20009115",
+ "usage" : "dm",
+ "tariffLayer2" : "",
+ "tariffAreaName" : ""
+ }
+ ]
+ },
+ "arr" : {
+ "points" : null,
+ "input" : {
+ "input" : ""
+ }
+ },
+ "servingLines" : {
+ "lines" : null
+ },
+ "departureList" : null,
+ "dateRange" : [
+ {
+ "year" : "2024",
+ "day" : "21",
+ "weekday" : "7",
+ "month" : "09"
+ },
+ {
+ "month" : "09",
+ "day" : "22",
+ "weekday" : "1",
+ "year" : "2024"
+ },
+ {
+ "day" : "23",
+ "weekday" : "2",
+ "month" : "09",
+ "year" : "2024"
+ },
+ {
+ "year" : "2024",
+ "day" : "24",
+ "weekday" : "3",
+ "month" : "09"
+ },
+ {
+ "year" : "2024",
+ "day" : "25",
+ "weekday" : "4",
+ "month" : "09"
+ },
+ {
+ "month" : "09",
+ "day" : "26",
+ "weekday" : "5",
+ "year" : "2024"
+ },
+ {
+ "year" : "2024",
+ "month" : "09",
+ "day" : "27",
+ "weekday" : "6"
+ },
+ {
+ "year" : "2024",
+ "weekday" : "7",
+ "day" : "28",
+ "month" : "09"
+ },
+ {
+ "year" : "2024",
+ "month" : "09",
+ "weekday" : "1",
+ "day" : "29"
+ },
+ {
+ "year" : "2024",
+ "weekday" : "2",
+ "day" : "30",
+ "month" : "09"
+ },
+ {
+ "weekday" : "3",
+ "day" : "01",
+ "month" : "10",
+ "year" : "2024"
+ },
+ {
+ "month" : "10",
+ "day" : "02",
+ "weekday" : "4",
+ "year" : "2024"
+ },
+ {
+ "day" : "03",
+ "weekday" : "5",
+ "month" : "10",
+ "year" : "2024"
+ },
+ {
+ "year" : "2024",
+ "day" : "04",
+ "weekday" : "6",
+ "month" : "10"
+ },
+ {
+ "year" : "2024",
+ "day" : "05",
+ "weekday" : "7",
+ "month" : "10"
+ }
+ ],
+ "dateTime" : {
+ "hour" : "18",
+ "minute" : "33",
+ "ttpTo" : "20250228",
+ "ttpFrom" : "20240601",
+ "deparr" : "dep",
+ "year" : "2024",
+ "day" : "21",
+ "month" : "9"
+ },
+ "option" : {
+ "ptOption" : {
+ "assistance" : "0",
+ "lowPlatformVhcl" : "0",
+ "useProxFootSearchDestination" : "0",
+ "useProxFootSearch" : "0",
+ "privateTransport" : "0",
+ "noSolidStairs" : "0",
+ "activeCom" : "-1",
+ "noCrowded" : "0",
+ "noInsecurePlaces" : "0",
+ "maxChanges" : "9",
+ "useProxFootSearchOrigin" : "0",
+ "routeType" : "LEASTTIME",
+ "active" : "-1",
+ "changeSpeed" : "normal",
+ "illumTransfer" : "0",
+ "activeSec" : "-1",
+ "excludedMeans" : [
+ {
+ "selected" : "0",
+ "value" : "0"
+ },
+ {
+ "value" : "1",
+ "selected" : "0"
+ },
+ {
+ "selected" : "0",
+ "value" : "2"
+ },
+ {
+ "selected" : "0",
+ "value" : "3"
+ },
+ {
+ "selected" : "0",
+ "value" : "4"
+ },
+ {
+ "selected" : "0",
+ "value" : "5"
+ },
+ {
+ "selected" : "0",
+ "value" : "6"
+ },
+ {
+ "selected" : "0",
+ "value" : "7"
+ },
+ {
+ "value" : "8",
+ "selected" : "0"
+ },
+ {
+ "value" : "9",
+ "selected" : "0"
+ },
+ {
+ "value" : "10",
+ "selected" : "0"
+ },
+ {
+ "value" : "11",
+ "selected" : "0"
+ },
+ {
+ "selected" : "0",
+ "value" : "12"
+ },
+ {
+ "value" : "13",
+ "selected" : "0"
+ },
+ {
+ "selected" : "0",
+ "value" : "14"
+ },
+ {
+ "value" : "15",
+ "selected" : "0"
+ },
+ {
+ "selected" : "0",
+ "value" : "16"
+ },
+ {
+ "value" : "17",
+ "selected" : "0"
+ },
+ {
+ "value" : "18",
+ "selected" : "0"
+ },
+ {
+ "selected" : "0",
+ "value" : "19"
+ }
+ ],
+ "plane" : "0",
+ "maxWait" : "120",
+ "maxTime" : "360",
+ "noElevators" : "0",
+ "overgroundTransfer" : "0",
+ "activeImp" : "-1",
+ "noEscalators" : "0",
+ "needElevatedPlt" : "0",
+ "bike" : "0",
+ "SOSAvail" : "0",
+ "lineRestriction" : "403",
+ "noLonelyTransfer" : "0",
+ "wheelchair" : "0"
+ }
+ },
+ "parameters" : [
+ {
+ "name" : "serverID",
+ "value" : "EFA2_"
+ },
+ {
+ "name" : "requestID",
+ "value" : "0"
+ },
+ {
+ "name" : "sessionID",
+ "value" : "0"
+ },
+ {
+ "name" : "calcTime",
+ "value" : "166.310"
+ },
+ {
+ "value" : "2024-09-21T18:33:39",
+ "name" : "serverTime"
+ }
+ ]
+}
diff --git a/t/in/essen_alfredusbad_ambiguous.xml b/t/in/essen_alfredusbad_ambiguous.xml
deleted file mode 100644
index 9b3e589..0000000
--- a/t/in/essen_alfredusbad_ambiguous.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<itdRequest version="9.16.27.53" language="de" lengthUnit="METER" sessionID="efa1.vrr.de_36925562" client="libwww-perl/6.03" clientIP="87.147.17.185" serverID="efa1.vrr.de_" virtDir="vrr" now="2011-11-20T12:18:48" nowWD="1">
- <itdLayoutParams>
- <itdLayoutParam name="mdvMap2_dm" value="" />
- <itdLayoutParam name="mapState_dm" value="" />
- <itdLayoutParam name="mdvMap_dm" value="3406199:401077:NAV3" />
- <itdLayoutParam name="view" value="" />
- <itdLayoutParam name="id_dm" value=":dm" />
- <itdLayoutParam name="transpCompany" value="vrr" />
- </itdLayoutParams>
- <itdDepartureMonitorRequest requestID="1">
- <itdOdv type="stop" usage="dm">
- <itdOdvPlace state="identified" method="itp">
- <odvPlaceElem omc="5113000" placeID="18" value="5113000:18" span="0" type="remote" mainPlace="1">Essen</odvPlaceElem>
- <odvPlaceInput>E</odvPlaceInput>
- </itdOdvPlace>
- <itdOdvName state="list" method="itp">
- <itdMessage type="error" module="BROKER" code="1">name list</itdMessage>
- <odvNameElem listIndex="0" selected="0" matchQuality="999010" stopID="20009115" value="0:1">Alfredusbad</odvNameElem>
- <odvNameElem listIndex="1" selected="0" matchQuality="996010" stopID="20009903" value="1:2">Am Alfredusbad</odvNameElem>
- <odvNameInput>Afredusbad</odvNameInput>
- </itdOdvName>
- </itdOdv>
- <itdDateTime ttpFrom="20110901" ttpTo="20120531">
- <itdDate weekday="1" year="2011" month="11" day="20" />
- <itdTime hour="12" minute="20" />
- </itdDateTime>
- <itdDateRange>
- <itdDate day="20" month="11" year="2011" weekday="1" />
- <itdDate day="21" month="11" year="2011" weekday="2" />
- <itdDate day="22" month="11" year="2011" weekday="3" />
- <itdDate day="23" month="11" year="2011" weekday="4" />
- <itdDate day="24" month="11" year="2011" weekday="5" />
- <itdDate day="25" month="11" year="2011" weekday="6" />
- <itdDate day="26" month="11" year="2011" weekday="7" />
- <itdDate day="27" month="11" year="2011" weekday="1" />
- <itdDate day="28" month="11" year="2011" weekday="2" />
- <itdDate day="29" month="11" year="2011" weekday="3" />
- <itdDate day="30" month="11" year="2011" weekday="4" />
- <itdDate day="01" month="12" year="2011" weekday="5" />
- <itdDate day="02" month="12" year="2011" weekday="6" />
- <itdDate day="03" month="12" year="2011" weekday="7" />
- <itdDate day="04" month="12" year="2011" weekday="1" />
- </itdDateRange>
- <itdTripOptions>
- <itdPtOptions>
- <excludedMeans>
- <meansElem value="0" selected="0">Zug</meansElem>
- <meansElem value="1" selected="0">S-Bahn</meansElem>
- <meansElem value="2" selected="0">U-Bahn</meansElem>
- <meansElem value="3" selected="0">Stadtbahn</meansElem>
- <meansElem value="4" selected="0">Straßen-/Trambahn</meansElem>
- <meansElem value="5" selected="0">Stadtbus</meansElem>
- <meansElem value="6" selected="0">Regionalbus</meansElem>
- <meansElem value="7" selected="0">Schnellbus</meansElem>
- <meansElem value="8" selected="0">Seil-/Zahnradbahn</meansElem>
- <meansElem value="9" selected="0">Schiff</meansElem>
- <meansElem value="10" selected="0">AST/Rufbus</meansElem>
- <meansElem value="11" selected="0">Sonstige</meansElem>
- </excludedMeans>
- </itdPtOptions>
- <itdItOptions>
- <itRouter logASCII="false" logSVG="false" />
- <itPedestrian computeMonomodalTrip="false" computationType="PT_AND_IT" itIncidentData="false" useElevation="false" speedFactor="100" costFactor="0" distanceFactor="50" traveltimeFactor="50" noTunnel="false" noBridge="false" noFerry="false" maxTime="20" maxLength="2147483647" ignoreRestrictions="false" />
- <itBicycle preferAsphaltTracks="false" preferGreenTracks="false" usePseudoRouting="false" useSignedRoute="false" cycleSpeed="20" prefHikePath="false" elevFac="50" bikeProf="UNKNOWN" computeMonomodalTrip="false" computationType="PT_AND_IT" itIncidentData="false" useElevation="false" speedFactor="100" costFactor="0" distanceFactor="50" traveltimeFactor="50" noTunnel="false" noBridge="false" noFerry="false" maxTime="15" maxLength="2147483647" ignoreRestrictions="false" />
- <mitCar computeMonomodalTrip="false" computationType="PT_AND_IT" itIncidentData="false" useElevation="false" speedFactor="100" costFactor="0" distanceFactor="10" traveltimeFactor="90" noTunnel="false" noBridge="false" noFerry="false" maxTime="90" maxLength="2147483647" ignoreRestrictions="false" mitProfileData="false" mitIncidentData="false" mitOnlineData="false" noHighway="false" noTollRoad="false" />
- <departureTransport>
- <individualTransport meansCode="100" value="8" speed="normal" selected="1" />
- <individualTransport meansCode="101" value="15" speed="normal" selected="0" />
- <individualTransport meansCode="102" value="15" speed="normal" selected="0" />
- <individualTransport meansCode="103" value="10" speed="normal" selected="0" />
- <individualTransport meansCode="104" value="10" speed="normal" selected="0" />
- <individualTransport meansCode="105" value="30" speed="normal" selected="0" />
- <individualTransport meansCode="106" value="15" speed="normal" selected="0" />
- <individualTransport meansCode="107" value="15" speed="normal" selected="0" />
- </departureTransport>
- </itdItOptions>
- </itdTripOptions>
- </itdDepartureMonitorRequest>
-</itdRequest>
-
diff --git a/t/in/essen_bp.html b/t/in/essen_bp.html
deleted file mode 100644
index f8cc826..0000000
--- a/t/in/essen_bp.html
+++ /dev/null
@@ -1,762 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html xmlns:vrr="http://www.vrr.de/" xmlns:mdv="http://www.mentzdv.de/">
-<head>
-<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-<title>Fahrplanauskunft</title>
-<link rel="stylesheet" type="text/css" href="css/map.css">
-<link rel="stylesheet" type="text/css" href="css/MDVMapContextMenu.css">
-<link rel="stylesheet" type="text/css" href="css/MDVMapControl.css">
-<link rel="stylesheet" type="text/css" href="css/calendar.css">
-<link rel="stylesheet" type="text/css" href="css/itpTravelService.css">
-<link rel="stylesheet" type="text/css" href="css/vrr.css"><script type="text/javascript"><!--
-
- function attachEventListener(target, eventType, functionRef, capture) {
- if (typeof target.addEventListener != "undefined") {
- target.addEventListener(eventType, functionRef, capture);
- }
- else if (typeof target.attachEvent != "undefined") {
- target.attachEvent("on" + eventType, functionRef);
- }
- else {
- eventType = "on" + eventType;
-
- if (typeof target[eventType] == "function") {
- var oldListener = target[eventType];
-
- target[eventType] = function() {
- oldListener();
-
- return functionRef();
- }
- }
- else {
- target[eventType] = functionRef;
- }
- }
-
- return true;
- }
-
- function checkPwdBoxes()
- {
- if(document.forms[0].ppPersonNetPassword.value!=document.forms[0].ppPersonConfirmNetPassword.value || document.forms[0].ppPersonNetPassword.value=='')
- {
- alert('Ihre Passwortangaben sind ungültig. Bitte geben Sie zweimal dasselbe Passwort ein.');
- document.forms[0].ppPersonNetPassword.value="";
- document.forms[0].ppPersonConfirmNetPassword.value="";
- return false;
- }
- else return true;
- }
-
- function concatDate()
- {
- var completDate;
- completDate = document.forms[0].itdLPxx_date.value;
- completDate = completDate + "-" + document.forms[0].itdLPxx_month.value;
- completDate = completDate + "-" + document.forms[0].itdLPxx_year.value;
-
- document.forms[0].filterDateValid.value=completDate;
- }
-
- var viaInMobilityRestrictionOptions = 'true';
- var viaFlag = 'false';
- var identifiedOdv = {
- 'origin' : '',
- 'destination' : '',
- 'via' : '',
- 'command' : ''
- };
- var sid = 'efa10.vrr.de_40963484';
- var curLanguage = 'de';
- var dmStop = "Haltestelle";
- var dmPOI = "wichtiger Punkt";
-
- var includedMeans = [];
-
- var excludedMeans = [];
-
-
- function checkMeans() {
-
- var f = document.getElementsByName('jp')[0];
-
- if (!f || sid!=='0') {
- return true;
- }
-
- if (includedMeans.length >=1) {
- for (var i=0; i < includedMeans.length; i++) {
- if(f['inclMOT_' + includedMeans[i]]) {
- f['inclMOT_' + includedMeans[i]].checked = false;
- }
- }
- } else if (excludedMeans.length >=1) {
- for (var j=0; j < excludedMeans.length; j++) {
- if (f['inclMOT_' + excludedMeans[j]]) {
- f['inclMOT_' + excludedMeans[j]].checked = false;
- }
- }
- }
- }
-
- attachEventListener(window, 'load', checkMeans, false);
- //--></script><script type="text/javascript" src="JavaScriptFunctions/mdv.js"></script><script type="text/javascript" src="JavaScriptFunctions/odvScript.js"></script><script type="text/javascript" src="/mdv/mdvMap/mdvMap.js"></script><link type="text/css" href="css/jquery-ui-1.8.6.custom.css" rel="stylesheet"><!--[if IE]><style>.ui-datepicker { margin-top: -150px; }</style><![endif]--><script type="text/javascript" src="JavaScriptFunctions/jquery-1.4.2.min.js"></script><script type="text/javascript" src="JavaScriptFunctions/jquery-ui-1.8.6.custom.min.js"></script><script type="text/javascript" src="JavaScriptFunctions/datepicker-de.js"></script><script type="text/javascript" src="mdvMapSettings.js"></script><script type="text/javascript" src="miniMapSettings.js"></script><script type="text/javascript" src="JavaScriptFunctions/mdvMapHandler.js"></script><script type="text/javascript"><!--
- var bCreateMapRequest = false;
- --></script><script type="text/javascript"><!--
- /* language of the map */
- var mapLanguage = 'de';
- var odv = new Array();
- --></script><script>function initMdvMapConfig() {var usages = new Array("origin", "destination", "via", "dm", "stt");for(var i=0; i<usages.length; i++) {var usage = usages[i];mdvMapConfigs[usage] = mdvMapConfig.clone();mdvMapConfigs[usage].add("serverURL", "http://efa.vrr.de/maps/nrw/");mdvMapConfigs[usage].add("efaURL", "../lite/XSLT_COORD_REQUEST");mdvMapConfigs[usage].add("transparentImg", "images/transparent.gif");mdvMapConfigs[usage].add("defaultScale", "2");mdvMapConfigs[usage].add("toolTimeOut", "20");mdvMapConfigs[usage].add("zoomOnDoubleClick", "true");mdvMapConfigs[usage].add("useMagnifyGlass", "true");mdvMapConfigs[usage].add("cursorMove", "images/grabbing.cur");mdvMapConfigs[usage].add("poiArea", "true");mdvMapConfigs[usage].add("poiPoint", "true");mdvMapConfigs[usage].add("language", "de");mdvMapConfigs[usage].add("imagePath", "images/mdvMap/");mdvMapConfigs[usage].add("xCenterReal", "3368363");mdvMapConfigs[usage].add("yCenterReal", "450530");mdvMapConfigs[usage].add("mapName", "NAV3");mdvMapConfigs[usage].add("network", "NRW");mdvMapConfigs[usage].add("useBubbleForEFAInfo", "true");mdvMapConfigs[usage].add("info.stop.size.width", "250");mdvMapConfigs[usage].add("info.stop.size.height", "200");mdvMapConfigs[usage].add("info.poi.size.width", "250");mdvMapConfigs[usage].add("info.poi.size.height", "120");mdvMapConfigs[usage].add("useBubbleOverflowForEFAInfo", "true");mdvMapConfigs[usage].add("block", "100");mdvMapConfigs[usage].add("language", "de");mdvMiniMapConfigs[usage] = mdvMiniMapConfig.clone();mdvMiniMapConfigs[usage].add("serverURL", "http://efa.vrr.de/maps/nrw/");mdvMiniMapConfigs[usage].add("efaURL", "../lite/XSLT_COORD_REQUEST");mdvMiniMapConfigs[usage].add("transparentImg", "images/transparent.gif");mdvMiniMapConfigs[usage].add("defaultScale", "2");mdvMiniMapConfigs[usage].add("toolTimeOut", "20");mdvMiniMapConfigs[usage].add("zoomOnDoubleClick", "true");mdvMiniMapConfigs[usage].add("useMagnifyGlass", "true");mdvMiniMapConfigs[usage].add("cursorMove", "images/grabbing.cur");mdvMiniMapConfigs[usage].add("language", "de");mdvMiniMapConfigs[usage].add("imagePath", "images/mdvMap/");mdvMiniMapConfigs[usage].add("xCenterReal", "3368363");mdvMiniMapConfigs[usage].add("yCenterReal", "450530");mdvMiniMapConfigs[usage].add("mapName", "NAV3");mdvMiniMapConfigs[usage].add("network", "NRW");mdvMiniMapConfigs[usage].add("block", "100");mdvMiniMapConfigs[usage].add("language", "de");}}
- </script></head>
-<body onload="">
-<form action="XSLT_DM_REQUEST" name="jp" method="POST"><input type="hidden" name="sessionID" id="sessionID" value="efa10.vrr.de_40963484"><input type="hidden" name="language" id="language" value="de"><input type="hidden" name="requestID" id="requestID" value="1"><input type="hidden" name="command" id="command" value=""><input type="hidden" name="useRealtime" value="1"><input type="hidden" name="itdLPxx_view" value=""><input type="hidden" name="ptOptionsActive" value="1"><input type="hidden" name="useProxFootSearch" value="0"><input type="hidden" name="deleteAssignedStops_dm" value="1"><input type="hidden" name="itdLPxx_mdvMap2_dm" id="itdLPxx_mdvMap2_dm" value="3406199:401077:NAV3"><input type="hidden" name="itdLPxx_mapState_dm" id="itdLPxx_mapState_dm" value=""><input type="hidden" name="itdLPxx_mdvMap_dm" id="itdLPxx_mdvMap_dm" value="3406199:401077:NAV3"><input type="hidden" name="itdLPxx_transpCompany" value="vrr"><table cellspacing="0" cellpadding="0" border="0">
-<tr>
-<td rowspan="3" valign="top" align="left" width="155">
-<table id="tabNav">
-<tr>
-<td class="leftHeader"></td>
-</tr>
-<tr>
-<td><a title="en" href="XSLT_TRIP_REQUEST2?language=en&amp;itdLPxx_transpCompany=vrr"><img src="images/flag/flag_en.gif" border="0"></a> <a title="fr" href="XSLT_TRIP_REQUEST2?language=fr&amp;itdLPxx_transpCompany=vrr"><img src="images/flag/flag_fr.gif" border="0"></a> <a title="es" href="XSLT_TRIP_REQUEST2?language=es&amp;itdLPxx_transpCompany=vrr"><img src="images/flag/flag_es.gif" border="0"></a> <a title="tr" href="XSLT_TRIP_REQUEST2?language=tr&amp;itdLPxx_transpCompany=vrr"><img src="images/flag/flag_tr.gif" border="0"></a></td>
-</tr>
-<tr>
-<td class="navLabelTextBoldColor"><a href="XSLT_TRIP_REQUEST2?language=de&amp;itdLPxx_transpCompany=vrr&amp;">Fahrplanauskunft</a></td>
-</tr>
-<tr>
-<td><a href="XSLT_STT_REQUEST?language=de&amp;itdLPxx_transpCompany=vrr&amp;">Aushangfahrplan</a></td>
-</tr>
-<tr>
-<td><a href="XSLT_DM_REQUEST?language=de&amp;itdLPxx_transpCompany=vrr&amp;">Abfahrtsmonitor</a></td>
-</tr>
-<tr>
-<td><a href="XSLT_PS_REQUEST2?language=de&amp;itdLPxx_transpCompany=vrr&amp;">Persönlicher Fahrplan</a></td>
-</tr>
-<tr>
-<td><a href="http://www.vrr.de/de/fahrplanauskunft/fahr_und_linienplaene/verbundfahrplan_schnellverkehr/index.html" target="vrr">Verbundfahrplan Schnellverkehr</a></td>
-</tr>
-<tr>
-<td><a href="http://www.vrr.de/de/fahrplanauskunft/fahr_und_linienplaene/linienplan_schnellverkehr/index.html" target="vrr">Linienplan Schnellverkehr</a></td>
-</tr>
-<tr>
-<td><a href="http://www.vrr.de/de/fahrplanauskunft/fahr_und_linienplaene/stadtlinienplaene/index.html" target="vrr">Stadtlinienpläne</a></td>
-</tr>
-<tr>
-<td><a href="./Bedienungshinweise_de.htm" target="vrr">Bedienungshinweise</a></td>
-</tr>
-<tr>
-<td><a href="XSLT_SCREEN_SAVER_REQUEST?language=de&amp;itdLPxx_transpCompany=vrr&amp;">Bildschirmschoner</a></td>
-</tr>
-<tr>
-<td><a href="XSLT_ADDINFO_REQUEST?language=de&amp;itdLPxx_transpCompany=vrr&amp;filterPublicationStatus=current&amp;filterShowPlaceList=1&amp;filterShowLineList=1&amp;filterShowStopList=0&amp;filterShowPlaceList=0&amp;">Aktuelle Hinweise</a></td>
-</tr>
-<tr>
-<td><a href="XSLT_TRIP_REQUEST2?language=de&amp;itdLPxx_transpCompany=vrr&amp;itdLPxx_urlGenerator=true&amp;">Ihr Link zu uns</a></td>
-</tr>
-<tr>
-<td><a href="http://www.vrr.de/de/global/impressum/index.html">Impressum</a></td>
-</tr>
-<tr>
-<td><a href="http://www.vrr.de/">Homepage</a></td>
-</tr>
-</table>
-</td>
-<td rowspan="3"> </td>
-<td valign="top" width="630" height="55">
-<table cellspacing="0" cellpadding="0" width="100%" border="0">
-<tr>
-<td colspan="3" height="35" align="left" class="logoHeader">
-<div class="textHeader">Abfahrtsmonitor</div>
-</td>
-</tr>
-<tr>
-<td colspan="3"><img src="images/dummy.gif" width="100%" height="5"></td>
-</tr>
-</table>
-<table cellspacing="0" cellpadding="0" width="630" border="0">
-<tr class="bgColor">
-<td colspan="3">
-<table cellspacing="0" cellpadding="0" width="100%" border="0">
-<tr>
-<td colspan="5"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-<tr>
-<td width="2%" align="top" class="kaestchen"><img src="images/dummy.gif" width="7" height="13" border="0" alt="*"></td>
-<td width="10%"><span class="labelTextBold"> von:</span></td>
-<td width="40%"><span class="labelText">Essen / Berliner Platz</span></td>
-<td width="10%"><span class="labelTextBold"> </span></td>
-<td width="38%"><span class="labelText"> </span></td>
-</tr>
-<tr>
-<td width="2%" align="top"> </td>
-<td width="10%"><span class="labelTextBold"> Abfahrt:</span></td>
-<td width="40%"><span class="labelText">20:19</span><span class="labelText"> Uhr</span></td>
-<td width="10%"><span class="labelTextBold">Datum:</span></td>
-<td width="38%"><span class="labelText">11.09.2011</span></td>
-</tr>
-</table>
-</td>
-</tr>
-<tr>
-<td colspan="3"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-<tr class="bgColor">
-<td colspan="3"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-<tr class="bgColor">
-<td colspan="3">
-<table cellspacing="0" cellpadding="0" width="100%" border="0">
-<tr>
-<td width="2%" align="top"><img src="images/dummy.gif" width="7" height="13" border="0" alt="*"></td>
-<td width="5%" align="center"><a href="javascript:document.forms[0].itdLPxx_view.value='printview';document.forms[0].command.value='nop';document.forms[0].submit();"><img src="images/drucker.jpg" width="20" height="20" border="0" alt="zur Druckversion"></a></td>
-<td width="55%"><span class="labelTextBold">zur Druckversion</span></td>
-<td width="38%" align="right"> </td>
-</tr>
-<tr>
-<td colspan="4"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-</table>
-</td>
-</tr>
-<tr class="bgColor">
-<td colspan="3"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-<tr>
-<td colspan="3"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-<tr class="bgColor">
-<td colspan="3"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-<tr class="bgColor">
-<td colspan="3">
-<table cellspacing="0" cellpadding="3" width="100%" border="0">
-<tr>
-<TD> </TD>
-<TD align="center" class="labelTextBold"> Zeit </TD>
-<TD align="center" class="labelTextBold">Abfahrt  </TD>
-<td></td>
-<TD class="labelTextBold">Linie </TD>
-<TD> </TD>
-<TD class="labelTextBold">Richtung </TD>
-<TD> </TD>
-<TD class="labelTextBold">Hinweise</TD>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">20:19</td>
-<td class="labelText" align="left">Bstg. 1</td>
-<td class="labelText" align="middle"><img src="images/means/tram.gif" width="32" height="32" alt="Tram"></td>
-<td class="labelText">103</td>
-<td> </td>
-<td class="labelText">Essen Wertstr.</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">20:19</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/tram.gif" width="32" height="32" alt="Tram"></td>
-<td class="labelText">101</td>
-<td> </td>
-<td class="labelText">Essen Hauptbahnhof</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">20:19</td>
-<td class="labelText" align="left">Bstg. 3</td>
-<td class="labelText" align="middle"><img src="images/means/nf_bus.gif" width="32" height="32" alt="Niederflurbus"></td>
-<td class="labelText">166</td>
-<td> </td>
-<td class="labelText">E-Burgaltendorf Burgruine</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">20:21</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/u_bahn.gif" width="32" height="32" alt="U-Bahn"></td>
-<td class="labelText">U11</td>
-<td> </td>
-<td class="labelText">Essen Messe W.-Süd/Gruga</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">20:21</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/tram.gif" width="32" height="32" alt="Tram"></td>
-<td class="labelText">105</td>
-<td> </td>
-<td class="labelText">Essen Finefraustr.</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">20:21</td>
-<td class="labelText" align="left">Bstg. 1</td>
-<td class="labelText" align="middle"><img src="images/means/u_bahn.gif" width="32" height="32" alt="U-Bahn"></td>
-<td class="labelText">U17</td>
-<td> </td>
-<td class="labelText">Essen Karlsplatz</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">20:26</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/tram.gif" width="32" height="32" alt="Tram"></td>
-<td class="labelText">109</td>
-<td> </td>
-<td class="labelText">Essen Steele S</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">20:27</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/nf_bus.gif" width="32" height="32" alt="Niederflurbus"></td>
-<td class="labelText">147</td>
-<td> </td>
-<td class="labelText">Essen Grimbergstr.</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">20:29</td>
-<td class="labelText" align="left">Bstg. 1</td>
-<td class="labelText" align="middle"><img src="images/means/u_bahn.gif" width="32" height="32" alt="U-Bahn"></td>
-<td class="labelText">U11</td>
-<td> </td>
-<td class="labelText">Gelsenkirchen Buerer Str.</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">20:29</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/u_bahn.gif" width="32" height="32" alt="U-Bahn"></td>
-<td class="labelText">U17</td>
-<td> </td>
-<td class="labelText">Essen Margarethenhöhe</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">20:30</td>
-<td class="labelText" align="left">Bstg. 1</td>
-<td class="labelText" align="middle"><img src="images/means/nf_bus.gif" width="32" height="32" alt="Niederflurbus"></td>
-<td class="labelText">147</td>
-<td> </td>
-<td class="labelText">Essen Erbach</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">20:31</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/u_bahn.gif" width="32" height="32" alt="U-Bahn"></td>
-<td class="labelText">U18</td>
-<td> </td>
-<td class="labelText">Mülheim Hbf</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">20:32</td>
-<td class="labelText" align="left">Bstg. 1</td>
-<td class="labelText" align="middle"><img src="images/means/tram.gif" width="32" height="32" alt="Tram"></td>
-<td class="labelText">109</td>
-<td> </td>
-<td class="labelText">Essen Frohnhausen Breilsort</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">20:34</td>
-<td class="labelText" align="left">Bstg. 1</td>
-<td class="labelText" align="middle"><img src="images/means/tram.gif" width="32" height="32" alt="Tram"></td>
-<td class="labelText">105</td>
-<td> </td>
-<td class="labelText">Essen Unterstr.</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">20:36</td>
-<td class="labelText" align="left">Bstg. 4</td>
-<td class="labelText" align="middle"><img src="images/means/nf_bus.gif" width="32" height="32" alt="Niederflurbus"></td>
-<td class="labelText">166</td>
-<td> </td>
-<td class="labelText">Essen Dellwig Bahnhof</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">20:36</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/u_bahn.gif" width="32" height="32" alt="U-Bahn"></td>
-<td class="labelText">U11</td>
-<td> </td>
-<td class="labelText">Essen Messe W.-Süd/Gruga</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">20:36</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/tram.gif" width="32" height="32" alt="Tram"></td>
-<td class="labelText">103</td>
-<td> </td>
-<td class="labelText">Essen Hauptbahnhof</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">20:37</td>
-<td class="labelText" align="left">Bstg. 1</td>
-<td class="labelText" align="middle"><img src="images/means/tram.gif" width="32" height="32" alt="Tram"></td>
-<td class="labelText">101</td>
-<td> </td>
-<td class="labelText">Essen Germaniaplatz</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">20:40</td>
-<td class="labelText" align="left">Bstg. 1</td>
-<td class="labelText" align="middle"><img src="images/means/nf_bus.gif" width="32" height="32" alt="Niederflurbus"></td>
-<td class="labelText">145</td>
-<td> </td>
-<td class="labelText">Essen Fängershof Schleife</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">20:41</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/tram.gif" width="32" height="32" alt="Tram"></td>
-<td class="labelText">109</td>
-<td> </td>
-<td class="labelText">Essen Steele S</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">20:44</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/u_bahn.gif" width="32" height="32" alt="U-Bahn"></td>
-<td class="labelText">U17</td>
-<td> </td>
-<td class="labelText">Essen Margarethenhöhe</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">20:44</td>
-<td class="labelText" align="left">Bstg. 1</td>
-<td class="labelText" align="middle"><img src="images/means/u_bahn.gif" width="32" height="32" alt="U-Bahn"></td>
-<td class="labelText">U11</td>
-<td> </td>
-<td class="labelText">Gelsenkirchen Buerer Str.</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">20:46</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/u_bahn.gif" width="32" height="32" alt="U-Bahn"></td>
-<td class="labelText">U18</td>
-<td> </td>
-<td class="labelText">Mülheim Hbf</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">20:46</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/nf_bus.gif" width="32" height="32" alt="Niederflurbus"></td>
-<td class="labelText">145</td>
-<td> </td>
-<td class="labelText">Essen Heisingen Baldeneysee</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">20:47</td>
-<td class="labelText" align="left">Bstg. 1</td>
-<td class="labelText" align="middle"><img src="images/means/tram.gif" width="32" height="32" alt="Tram"></td>
-<td class="labelText">109</td>
-<td> </td>
-<td class="labelText">Essen Frohnhausen Breilsort</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">20:49</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/tram.gif" width="32" height="32" alt="Tram"></td>
-<td class="labelText">101</td>
-<td> </td>
-<td class="labelText">Essen Hauptbahnhof</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">20:49</td>
-<td class="labelText" align="left">Bstg. 1</td>
-<td class="labelText" align="middle"><img src="images/means/tram.gif" width="32" height="32" alt="Tram"></td>
-<td class="labelText">103</td>
-<td> </td>
-<td class="labelText">Essen Wertstr.</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">20:49</td>
-<td class="labelText" align="left">Bstg. 3</td>
-<td class="labelText" align="middle"><img src="images/means/nf_bus.gif" width="32" height="32" alt="Niederflurbus"></td>
-<td class="labelText">166</td>
-<td> </td>
-<td class="labelText">Hattingen Märkische Str</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">20:51</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/tram.gif" width="32" height="32" alt="Tram"></td>
-<td class="labelText">105</td>
-<td> </td>
-<td class="labelText">Essen Finefraustr.</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">20:52</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/u_bahn.gif" width="32" height="32" alt="U-Bahn"></td>
-<td class="labelText">U11</td>
-<td> </td>
-<td class="labelText">Essen Messe W.-Süd/Gruga</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">20:56</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/tram.gif" width="32" height="32" alt="Tram"></td>
-<td class="labelText">109</td>
-<td> </td>
-<td class="labelText">Essen Hollestr.</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">20:57</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/nf_bus.gif" width="32" height="32" alt="Niederflurbus"></td>
-<td class="labelText">147</td>
-<td> </td>
-<td class="labelText">Essen Grimbergstr.</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">20:59</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/u_bahn.gif" width="32" height="32" alt="U-Bahn"></td>
-<td class="labelText">U17</td>
-<td> </td>
-<td class="labelText">Essen Margarethenhöhe</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">21:00</td>
-<td class="labelText" align="left">Bstg. 1</td>
-<td class="labelText" align="middle"><img src="images/means/nf_bus.gif" width="32" height="32" alt="Niederflurbus"></td>
-<td class="labelText">147</td>
-<td> </td>
-<td class="labelText">Essen Erbach</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">21:01</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/u_bahn.gif" width="32" height="32" alt="U-Bahn"></td>
-<td class="labelText">U18</td>
-<td> </td>
-<td class="labelText">Mülheim Hbf</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">21:03</td>
-<td class="labelText" align="left">Bstg. 1</td>
-<td class="labelText" align="middle"><img src="images/means/u_bahn.gif" width="32" height="32" alt="U-Bahn"></td>
-<td class="labelText">U11</td>
-<td> </td>
-<td class="labelText">Gelsenkirchen Buerer Str.</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">21:04</td>
-<td class="labelText" align="left">Bstg. 1</td>
-<td class="labelText" align="middle"><img src="images/means/tram.gif" width="32" height="32" alt="Tram"></td>
-<td class="labelText">105</td>
-<td> </td>
-<td class="labelText">Essen Unterstr.</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">21:06</td>
-<td class="labelText" align="left">Bstg. 2</td>
-<td class="labelText" align="middle"><img src="images/means/tram.gif" width="32" height="32" alt="Tram"></td>
-<td class="labelText">103</td>
-<td> </td>
-<td class="labelText">Essen Hauptbahnhof</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor">
-<td> </td>
-<td class="labelText" align="middle">21:06</td>
-<td class="labelText" align="left">Bstg. 4</td>
-<td class="labelText" align="middle"><img src="images/means/nf_bus.gif" width="32" height="32" alt="Niederflurbus"></td>
-<td class="labelText">166</td>
-<td> </td>
-<td class="labelText">Essen Dellwig Bahnhof</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-<tr class="bgColor2">
-<td> </td>
-<td class="labelText" align="middle">21:07</td>
-<td class="labelText" align="left">Bstg. 1</td>
-<td class="labelText" align="middle"><img src="images/means/tram.gif" width="32" height="32" alt="Tram"></td>
-<td class="labelText">101</td>
-<td> </td>
-<td class="labelText">Essen Germaniaplatz</td>
-<td> </td>
-<td class="labelText"></td>
-</tr>
-</table>
-</td>
-</tr>
-<tr class="bgColor">
-<td colspan="3"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-<tr>
-<td colspan="3"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-<tr class="bgColor">
-<td colspan="3"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-<tr class="bgColor">
-<td colspan="3">
-<table cellspacing="0" cellpadding="0" width="100%" border="0">
-<tr>
-<td width="2%"></td>
-<td valign="center"><img src="images/Rbl_nOK.gif" width="13" height="30" border="0" title="Abweichung" alt="Abweichung"></td>
-<td valign="center"><span class="labelText" valign="center">Verspätungen sind berücksichtigt</span></td>
-<td width="2%"></td>
-<td valign="center"><img src="images/Rbl.gif" width="13" height="30" border="0" title="Pünktlich" alt="Pünktlich"></td>
-<td valign="center"><span class="labelText" valign="center">Fahrt voraussichtlich pünktlich</span></td>
-</tr>
-</table>
-</td>
-</tr>
-<tr class="bgColor">
-<td colspan="3"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-<tr>
-<td colspan="3"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-<tr class="bgColor">
-<td colspan="3"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-<tr class="bgColor">
-<td colspan="3">
-<table cellspacing="0" cellpadding="0" width="100%" border="0">
-<tr>
-<td width="2%" align="top"><img src="images/dummy.gif" width="7" height="13" border="0" alt="*"></td>
-<td width="5%" align="center"><a href="javascript:document.forms[0].itdLPxx_view.value='printview';document.forms[0].command.value='nop';document.forms[0].submit();"><img src="images/drucker.jpg" width="20" height="20" border="0" alt="zur Druckversion"></a></td>
-<td width="55%"><span class="labelTextBold">zur Druckversion</span></td>
-<td width="38%" align="right"> </td>
-</tr>
-<tr>
-<td colspan="4"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-</table>
-</td>
-</tr>
-<tr class="bgColor">
-<td colspan="3"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-<tr>
-<td colspan="3"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-<tr class="buttonBgColor">
-<td colspan="3"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-<tr class="buttonBgColor">
-<td colspan="3" align="center"><input type="button" name="reset" value="neue Anfrage" onClick="document.location.href='XSLT_DM_REQUEST?language=de&amp;itdLPxx_transpCompany=vrr'"></td>
-</tr>
-<tr class="buttonBgColor">
-<td colspan="3"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-</tr>
-<tr>
-<td colspan="3">
-<table cellspacing="0" cellpadding="0" width="100%" border="0">
-<td height="40" valign="middle" align="left"><img src="images/dummy.gif" width="1" height="5" alt="*"></td>
-<td width="220" valign="bottom"><img src="images/ein-Service-des-VRR.gif" width="220" height="36" alt="*" align="right"></td>
-</table>
-</td>
-</tr>
-</table>
-</td>
-</tr>
-</table>
-</form>
-</body>
-</html>
diff --git a/t/in/essen_bp.json b/t/in/essen_bp.json
new file mode 100644
index 0000000..5462a81
--- /dev/null
+++ b/t/in/essen_bp.json
@@ -0,0 +1,3979 @@
+{
+ "parameters" : [
+ {
+ "value" : "EFAMOBIL3_",
+ "name" : "serverID"
+ },
+ {
+ "name" : "requestID",
+ "value" : "0"
+ },
+ {
+ "name" : "sessionID",
+ "value" : "0"
+ },
+ {
+ "name" : "calcTime",
+ "value" : "218.700"
+ },
+ {
+ "value" : "2024-09-21T18:34:21",
+ "name" : "serverTime"
+ }
+ ],
+ "dateTime" : {
+ "day" : "21",
+ "deparr" : "dep",
+ "month" : "9",
+ "year" : "2024",
+ "ttpTo" : "20250228",
+ "ttpFrom" : "20240601",
+ "hour" : "18",
+ "minute" : "34"
+ },
+ "departureList" : [
+ {
+ "stopName" : "Essen Berliner Platz",
+ "stopID" : "20009153",
+ "x" : "779634",
+ "nameWO" : "Berliner Platz",
+ "y" : "5297058",
+ "realDateTime" : {
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21",
+ "weekday" : "7",
+ "hour" : "18",
+ "minute" : "40"
+ },
+ "operator" : {
+ "publicCode" : "EV-B",
+ "code" : "12",
+ "name" : "EVAG Bus"
+ },
+ "countdown" : "6",
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "minute" : "33",
+ "hour" : "18",
+ "weekday" : "7",
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21"
+ },
+ "area" : "4",
+ "servingLine" : {
+ "code" : "5",
+ "destID" : "20009222",
+ "name" : "Niederflurbus",
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "symbol" : "145",
+ "liErgRiProj" : {
+ "supplement" : " ",
+ "project" : "j24",
+ "network" : "eva",
+ "direction" : "R",
+ "line" : "12145",
+ "gid" : "de:vrr:eva-12-145:"
+ },
+ "key" : "558",
+ "delay" : "7",
+ "motType" : "5",
+ "direction" : "Essen Erbach",
+ "stateless" : "eva:12145: :R:j24",
+ "number" : "145",
+ "directionFrom" : "Essen Heisingen Baldeneysee",
+ "lineDisplay" : "line"
+ },
+ "platformName" : "1",
+ "platform" : "1",
+ "attrs" : [
+ {
+ "name" : "AVMSTripID",
+ "value" : "RB_EVAG.84932"
+ }
+ ],
+ "mapName" : "MRCV"
+ },
+ {
+ "platformName" : "Gleis 3",
+ "platform" : "3",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.2992",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "mapName" : "MRCV",
+ "area" : "2",
+ "servingLine" : {
+ "name" : "Straßenbahn",
+ "destID" : "20009254",
+ "code" : "4",
+ "mtSubcode" : "0",
+ "realtime" : "1",
+ "symbol" : "106",
+ "liErgRiProj" : {
+ "direction" : "H",
+ "line" : "11106",
+ "gid" : "de:vrr:eva-11-106:",
+ "supplement" : " ",
+ "project" : "j24",
+ "network" : "eva"
+ },
+ "key" : "167",
+ "delay" : "0",
+ "direction" : "Essen Germaniaplatz",
+ "motType" : "4",
+ "stateless" : "eva:11106: :H:j24",
+ "lineDisplay" : "line",
+ "number" : "106",
+ "directionFrom" : "Essen Helenenstr."
+ },
+ "operator" : {
+ "name" : "EVAG Strab",
+ "publicCode" : "EV-T",
+ "code" : "11"
+ },
+ "countdown" : "1",
+ "dateTime" : {
+ "weekday" : "7",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024",
+ "minute" : "35",
+ "hour" : "18"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "realDateTime" : {
+ "hour" : "18",
+ "minute" : "35",
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21",
+ "weekday" : "7"
+ },
+ "y" : "5296977",
+ "x" : "779748",
+ "stopID" : "20009153",
+ "nameWO" : "Berliner Platz",
+ "stopName" : "Essen Berliner Platz"
+ },
+ {
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "weekday" : "7",
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21",
+ "minute" : "35",
+ "hour" : "18"
+ },
+ "operator" : {
+ "code" : "11",
+ "publicCode" : "EV-T",
+ "name" : "EVAG Strab"
+ },
+ "countdown" : "1",
+ "realDateTime" : {
+ "hour" : "18",
+ "minute" : "35",
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9",
+ "weekday" : "7"
+ },
+ "platform" : "4",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.3140",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "platformName" : "Gleis 4",
+ "servingLine" : {
+ "delay" : "0",
+ "motType" : "4",
+ "direction" : "Essen Helenenstr.",
+ "stateless" : "eva:11101: :H:j24",
+ "directionFrom" : "Essen Philippusstift",
+ "number" : "101",
+ "lineDisplay" : "line",
+ "code" : "4",
+ "name" : "Straßenbahn",
+ "destID" : "20009306",
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "liErgRiProj" : {
+ "supplement" : " ",
+ "network" : "eva",
+ "project" : "j24",
+ "direction" : "H",
+ "line" : "11101",
+ "gid" : "de:vrr:eva-11-101:"
+ },
+ "symbol" : "101",
+ "key" : "155"
+ },
+ "area" : "2",
+ "stopName" : "Essen Berliner Platz",
+ "y" : "5297057",
+ "nameWO" : "Berliner Platz",
+ "stopID" : "20009153",
+ "x" : "779692"
+ },
+ {
+ "stopID" : "20009153",
+ "x" : "779713",
+ "nameWO" : "Berliner Platz",
+ "y" : "5297149",
+ "stopName" : "Essen Berliner Platz",
+ "area" : "1",
+ "servingLine" : {
+ "destID" : "20009447",
+ "code" : "1",
+ "name" : "U-Bahn",
+ "mtSubcode" : "0",
+ "realtime" : "1",
+ "liErgRiProj" : {
+ "direction" : "H",
+ "gid" : "de:vrr:eva-10-U17:",
+ "line" : "10U17",
+ "supplement" : " ",
+ "project" : "j24",
+ "network" : "eva"
+ },
+ "symbol" : "U17",
+ "key" : "109",
+ "delay" : "0",
+ "direction" : "Essen Margarethenhöhe",
+ "motType" : "2",
+ "stateless" : "eva:10U17: :H:j24",
+ "lineDisplay" : "line",
+ "directionFrom" : "Essen Karlsplatz",
+ "number" : "U17"
+ },
+ "platformName" : "2",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.274590",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "platform" : "2",
+ "realDateTime" : {
+ "minute" : "35",
+ "hour" : "18",
+ "weekday" : "7",
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21"
+ },
+ "countdown" : "1",
+ "operator" : {
+ "name" : "EVAG U-Bahn",
+ "publicCode" : "EV-U",
+ "code" : "10"
+ },
+ "dateTime" : {
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21",
+ "weekday" : "7",
+ "hour" : "18",
+ "minute" : "35"
+ },
+ "realtimeTripStatus" : "MONITORED"
+ },
+ {
+ "stopName" : "Essen Berliner Platz",
+ "y" : "5297142",
+ "nameWO" : "Berliner Platz",
+ "x" : "779741",
+ "stopID" : "20009153",
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "hour" : "18",
+ "minute" : "36",
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21",
+ "weekday" : "7"
+ },
+ "operator" : {
+ "publicCode" : "EV-U",
+ "name" : "EVAG U-Bahn",
+ "code" : "10"
+ },
+ "countdown" : "2",
+ "realDateTime" : {
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21",
+ "weekday" : "7",
+ "hour" : "18",
+ "minute" : "36"
+ },
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.274934",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "mapName" : "MRCV",
+ "platform" : "1",
+ "platformName" : "1",
+ "servingLine" : {
+ "motType" : "2",
+ "direction" : "Gelsenkirchen Buerer Str.",
+ "delay" : "0",
+ "directionFrom" : "Essen Messe W.-Süd/Gruga",
+ "number" : "U11",
+ "lineDisplay" : "line",
+ "stateless" : "eva:10U11: :R:j24",
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "code" : "1",
+ "name" : "U-Bahn",
+ "destID" : "20005579",
+ "key" : "709",
+ "liErgRiProj" : {
+ "network" : "eva",
+ "project" : "j24",
+ "supplement" : " ",
+ "line" : "10U11",
+ "gid" : "de:vrr:eva-10-U11:",
+ "direction" : "R"
+ },
+ "symbol" : "U11"
+ },
+ "area" : "1"
+ },
+ {
+ "operator" : {
+ "code" : "12",
+ "publicCode" : "EV-B",
+ "name" : "EVAG Bus"
+ },
+ "countdown" : "2",
+ "dateTime" : {
+ "hour" : "18",
+ "minute" : "36",
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9",
+ "weekday" : "7"
+ },
+ "platformName" : "4",
+ "mapName" : "MRCV",
+ "platform" : "4",
+ "area" : "3",
+ "servingLine" : {
+ "realtime" : "0",
+ "mtSubcode" : "0",
+ "name" : "Niederflurbus",
+ "code" : "5",
+ "destID" : "20009197",
+ "key" : "190",
+ "liErgRiProj" : {
+ "supplement" : " ",
+ "network" : "eva",
+ "project" : "j24",
+ "direction" : "R",
+ "line" : "12166",
+ "gid" : "de:vrr:eva-12-166:"
+ },
+ "symbol" : "166",
+ "motType" : "5",
+ "direction" : "Essen Dellwig Bahnhof",
+ "directionFrom" : "E-Burgaltendorf Burgruine",
+ "number" : "166",
+ "lineDisplay" : "line",
+ "stateless" : "eva:12166: :R:j24"
+ },
+ "stopName" : "Essen Berliner Platz",
+ "y" : "5296893",
+ "x" : "779748",
+ "stopID" : "20009153",
+ "nameWO" : "Berliner Platz"
+ },
+ {
+ "area" : "2",
+ "servingLine" : {
+ "liErgRiProj" : {
+ "network" : "eva",
+ "project" : "j24",
+ "supplement" : " ",
+ "gid" : "de:vrr:eva-11-103:",
+ "line" : "11103",
+ "direction" : "R"
+ },
+ "symbol" : "103",
+ "key" : "462",
+ "code" : "4",
+ "destID" : "20009641",
+ "name" : "Straßenbahn",
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "stateless" : "eva:11103: :R:j24",
+ "directionFrom" : "Essen Steele S",
+ "number" : "103",
+ "lineDisplay" : "line",
+ "delay" : "0",
+ "motType" : "4",
+ "direction" : "Essen Wertstr."
+ },
+ "platformName" : "Gleis 3",
+ "platform" : "3",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.2316",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "realDateTime" : {
+ "weekday" : "7",
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9",
+ "minute" : "37",
+ "hour" : "18"
+ },
+ "countdown" : "3",
+ "operator" : {
+ "name" : "EVAG Strab",
+ "publicCode" : "EV-T",
+ "code" : "11"
+ },
+ "dateTime" : {
+ "minute" : "37",
+ "hour" : "18",
+ "weekday" : "7",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "stopID" : "20009153",
+ "x" : "779748",
+ "nameWO" : "Berliner Platz",
+ "y" : "5296977",
+ "stopName" : "Essen Berliner Platz"
+ },
+ {
+ "realDateTime" : {
+ "minute" : "38",
+ "hour" : "18",
+ "weekday" : "7",
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21"
+ },
+ "dateTime" : {
+ "hour" : "18",
+ "minute" : "38",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024",
+ "weekday" : "7"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "countdown" : "4",
+ "operator" : {
+ "publicCode" : "EV-T",
+ "name" : "EVAG Strab",
+ "code" : "11"
+ },
+ "servingLine" : {
+ "mtSubcode" : "0",
+ "realtime" : "1",
+ "code" : "4",
+ "name" : "Straßenbahn",
+ "destID" : "20009665",
+ "key" : "365",
+ "symbol" : "105",
+ "liErgRiProj" : {
+ "direction" : "H",
+ "line" : "11105",
+ "gid" : "de:vrr:eva-11-105:",
+ "supplement" : " ",
+ "project" : "j24",
+ "network" : "eva"
+ },
+ "direction" : "Essen Zeche Ludwig",
+ "motType" : "4",
+ "delay" : "0",
+ "lineDisplay" : "line",
+ "number" : "105",
+ "directionFrom" : "Essen Unterstr.",
+ "stateless" : "eva:11105: :H:j24"
+ },
+ "area" : "2",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.2585",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "platform" : "4",
+ "platformName" : "Gleis 4",
+ "stopName" : "Essen Berliner Platz",
+ "nameWO" : "Berliner Platz",
+ "stopID" : "20009153",
+ "x" : "779692",
+ "y" : "5297057"
+ },
+ {
+ "servingLine" : {
+ "name" : "Straßenbahn",
+ "code" : "4",
+ "destID" : "20009582",
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "liErgRiProj" : {
+ "line" : "11109",
+ "gid" : "de:vrr:eva-11-109:",
+ "direction" : "H",
+ "project" : "j24",
+ "network" : "eva",
+ "supplement" : " "
+ },
+ "symbol" : "109",
+ "key" : "195",
+ "delay" : "0",
+ "motType" : "4",
+ "direction" : "Essen Steele S",
+ "stateless" : "eva:11109: :H:j24",
+ "directionFrom" : "Frohnhausen Breilsort",
+ "number" : "109",
+ "lineDisplay" : "line"
+ },
+ "area" : "2",
+ "attrs" : [
+ {
+ "name" : "AVMSTripID",
+ "value" : "RB_EVAG.3690"
+ }
+ ],
+ "mapName" : "MRCV",
+ "platform" : "4",
+ "platformName" : "Gleis 4",
+ "realDateTime" : {
+ "weekday" : "7",
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9",
+ "minute" : "40",
+ "hour" : "18"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024",
+ "weekday" : "7",
+ "hour" : "18",
+ "minute" : "40"
+ },
+ "countdown" : "6",
+ "operator" : {
+ "publicCode" : "EV-T",
+ "code" : "11",
+ "name" : "EVAG Strab"
+ },
+ "nameWO" : "Berliner Platz",
+ "stopID" : "20009153",
+ "x" : "779692",
+ "y" : "5297057",
+ "stopName" : "Essen Berliner Platz"
+ },
+ {
+ "stopInfos" : null,
+ "stopName" : "Essen Berliner Platz",
+ "y" : "5296897",
+ "nameWO" : "Berliner Platz",
+ "stopID" : "20009153",
+ "x" : "779732",
+ "dateTime" : {
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21",
+ "weekday" : "7",
+ "hour" : "18",
+ "minute" : "41"
+ },
+ "tripInfos" : null,
+ "operator" : {
+ "name" : "DB Bahn Rheinlandbus",
+ "publicCode" : "BVR",
+ "code" : "88"
+ },
+ "countdown" : "7",
+ "lineInfos" : {
+ "lineInfo" : {
+ "infoLinkText" : "Linie SB16 - Haltestellenausfall - Zwischen (H) Essen, Hollestr. und (H) Essen, Hollestr. - Grund: Baumaßnahme",
+ "infoLinkURL" : "http://ems.vrr.de/info-link/5efeb629-f5df-5464-b4ff-753f43edd18f",
+ "paramList" : [
+ {
+ "name" : "publisher",
+ "type" : "addInfoParam",
+ "value" : "ems.comm.addinfo",
+ "edit" : "0"
+ },
+ {
+ "edit" : "0",
+ "value" : "lineInfo",
+ "name" : "infoType",
+ "type" : "addInfoParam"
+ },
+ {
+ "type" : "system",
+ "name" : "infoID",
+ "edit" : "0",
+ "value" : "ems-19119"
+ },
+ {
+ "edit" : "0",
+ "value" : "5356663",
+ "type" : "system",
+ "name" : "seqID"
+ },
+ {
+ "name" : "priority",
+ "type" : "addInfoParam",
+ "edit" : "0",
+ "value" : "normal"
+ },
+ {
+ "name" : "incidentDateTime",
+ "type" : "system",
+ "edit" : "0",
+ "value" : "08/01/2024 03:00 - 08/01/2026 23:50"
+ }
+ ],
+ "infoText" : {
+ "content" : "<b>Linie SB16: </b>Zwischen <b>(H) Essen, Hollestr.</b> und <b>(H) Essen, Hollestr.</b> kommt es zu <b>einem Haltestellenausfall</b>.<br><br> Dauer: 08.01.24, 03:00 Uhr bis 08.01.26, 23:50 Uhr<br><br>Die Haltestelle wird nicht angefahren. Abfahrtshaltestelle (Bussteig 6)",
+ "subject" : "Haltestellenausfall durch Baumaßnahme",
+ "speechText" : "",
+ "smsText" : "Linie SB16 - Haltestellenausfall - Zwischen (H) Essen, Hollestr. und (H) Essen, Hollestr. - Grund: Baumaßnahme",
+ "htmlText" : "",
+ "additionalText" : "Die beschriebenen Änderungen sind in der elektronischen Fahrplanauskunft (EFA) <b>nicht</b> berücksichtigt.",
+ "subtitle" : "Haltestellenausfall durch Baumaßnahme",
+ "wmlText" : ""
+ }
+ }
+ },
+ "mapName" : "MRCV",
+ "platform" : "3",
+ "platformName" : "3",
+ "servingLine" : {
+ "lineDisplay" : "line",
+ "number" : "SB16",
+ "directionFrom" : "BOT St.-Anto.-Hosp./Gartenstr.",
+ "stateless" : "bvr:88016:K:R:j24",
+ "direction" : "Essen Hauptbahnhof",
+ "motType" : "7",
+ "key" : "92",
+ "symbol" : "SB16",
+ "liErgRiProj" : {
+ "direction" : "R",
+ "gid" : "de:vrr:bvr-88-16:K",
+ "line" : "88016",
+ "supplement" : "K",
+ "network" : "bvr",
+ "project" : "j24"
+ },
+ "mtSubcode" : "0",
+ "realtime" : "0",
+ "destID" : "20009289",
+ "name" : "SB",
+ "code" : "5"
+ },
+ "area" : "3"
+ },
+ {
+ "stopName" : "Essen Berliner Platz",
+ "y" : "5297149",
+ "nameWO" : "Berliner Platz",
+ "stopID" : "20009153",
+ "x" : "779713",
+ "dateTime" : {
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9",
+ "weekday" : "7",
+ "hour" : "18",
+ "minute" : "42"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "countdown" : "8",
+ "operator" : {
+ "code" : "10",
+ "publicCode" : "EV-U",
+ "name" : "EVAG U-Bahn"
+ },
+ "realDateTime" : {
+ "minute" : "42",
+ "hour" : "18",
+ "weekday" : "7",
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21"
+ },
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.274464",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "platform" : "2",
+ "platformName" : "2",
+ "servingLine" : {
+ "motType" : "2",
+ "direction" : "Essen Messe W.-Süd/Gruga",
+ "delay" : "0",
+ "directionFrom" : "Gelsenkirchen Buerer Str.",
+ "number" : "U11",
+ "lineDisplay" : "line",
+ "stateless" : "eva:10U11: :H:j24",
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "code" : "1",
+ "destID" : "20009270",
+ "name" : "U-Bahn",
+ "key" : "271",
+ "liErgRiProj" : {
+ "supplement" : " ",
+ "project" : "j24",
+ "network" : "eva",
+ "direction" : "H",
+ "gid" : "de:vrr:eva-10-U11:",
+ "line" : "10U11"
+ },
+ "symbol" : "U11"
+ },
+ "area" : "1"
+ },
+ {
+ "y" : "5296977",
+ "stopID" : "20009153",
+ "x" : "779748",
+ "nameWO" : "Berliner Platz",
+ "stopName" : "Essen Berliner Platz",
+ "platformName" : "Gleis 3",
+ "attrs" : [
+ {
+ "name" : "AVMSTripID",
+ "value" : "RB_EVAG.3840"
+ }
+ ],
+ "mapName" : "MRCV",
+ "platform" : "3",
+ "area" : "2",
+ "servingLine" : {
+ "lineDisplay" : "line",
+ "directionFrom" : "Essen Steele S",
+ "number" : "109",
+ "stateless" : "eva:11109: :R:j24",
+ "direction" : "Frohnhausen Breilsort",
+ "motType" : "4",
+ "delay" : "0",
+ "key" : "370",
+ "liErgRiProj" : {
+ "supplement" : " ",
+ "network" : "eva",
+ "project" : "j24",
+ "direction" : "R",
+ "line" : "11109",
+ "gid" : "de:vrr:eva-11-109:"
+ },
+ "symbol" : "109",
+ "mtSubcode" : "0",
+ "realtime" : "1",
+ "code" : "4",
+ "name" : "Straßenbahn",
+ "destID" : "20009243"
+ },
+ "operator" : {
+ "code" : "11",
+ "publicCode" : "EV-T",
+ "name" : "EVAG Strab"
+ },
+ "countdown" : "8",
+ "dateTime" : {
+ "weekday" : "7",
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21",
+ "minute" : "42",
+ "hour" : "18"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "realDateTime" : {
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21",
+ "weekday" : "7",
+ "hour" : "18",
+ "minute" : "42"
+ }
+ },
+ {
+ "servingLine" : {
+ "motType" : "2",
+ "direction" : "Essen Karlsplatz",
+ "delay" : "0",
+ "number" : "U17",
+ "directionFrom" : "Essen Margarethenhöhe",
+ "lineDisplay" : "line",
+ "stateless" : "eva:10U17: :R:j24",
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "code" : "1",
+ "name" : "U-Bahn",
+ "destID" : "20009370",
+ "key" : "263",
+ "symbol" : "U17",
+ "liErgRiProj" : {
+ "network" : "eva",
+ "project" : "j24",
+ "supplement" : " ",
+ "gid" : "de:vrr:eva-10-U17:",
+ "line" : "10U17",
+ "direction" : "R"
+ }
+ },
+ "area" : "1",
+ "platform" : "1",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "name" : "AVMSTripID",
+ "value" : "RB_EVAG.274832"
+ }
+ ],
+ "platformName" : "1",
+ "realDateTime" : {
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21",
+ "weekday" : "7",
+ "hour" : "18",
+ "minute" : "43"
+ },
+ "dateTime" : {
+ "hour" : "18",
+ "minute" : "43",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024",
+ "weekday" : "7"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "operator" : {
+ "code" : "10",
+ "publicCode" : "EV-U",
+ "name" : "EVAG U-Bahn"
+ },
+ "countdown" : "9",
+ "nameWO" : "Berliner Platz",
+ "stopID" : "20009153",
+ "x" : "779741",
+ "y" : "5297142",
+ "stopName" : "Essen Berliner Platz"
+ },
+ {
+ "stopName" : "Essen Berliner Platz",
+ "x" : "779748",
+ "stopID" : "20009153",
+ "nameWO" : "Berliner Platz",
+ "y" : "5296893",
+ "realDateTime" : {
+ "weekday" : "7",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024",
+ "minute" : "44",
+ "hour" : "18"
+ },
+ "countdown" : "10",
+ "operator" : {
+ "name" : "Vestische",
+ "publicCode" : "VEST",
+ "code" : "40"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "minute" : "44",
+ "hour" : "18",
+ "weekday" : "7",
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9"
+ },
+ "area" : "3",
+ "servingLine" : {
+ "symbol" : "SB16",
+ "liErgRiProj" : {
+ "supplement" : " ",
+ "project" : "j24",
+ "network" : "ves",
+ "direction" : "H",
+ "line" : "40016",
+ "gid" : "de:vrr:SB16:VES-40-16"
+ },
+ "key" : "76",
+ "name" : "Niederflurbus",
+ "code" : "5",
+ "destID" : "20003174",
+ "mtSubcode" : "0",
+ "realtime" : "1",
+ "stateless" : "ves:40016: :H:j24",
+ "lineDisplay" : "line",
+ "number" : "SB16",
+ "directionFrom" : "Essen Hauptbahnhof",
+ "delay" : "0",
+ "direction" : "BOT St.-Anto.-Hosp./Gartenstr.",
+ "motType" : "5"
+ },
+ "platformName" : "4",
+ "platform" : "4",
+ "attrs" : [
+ {
+ "value" : "4001610010160413",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "mapName" : "MRCV"
+ },
+ {
+ "stopName" : "Essen Berliner Platz",
+ "x" : "779692",
+ "stopID" : "20009153",
+ "nameWO" : "Berliner Platz",
+ "y" : "5297057",
+ "realDateTime" : {
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21",
+ "weekday" : "7",
+ "hour" : "18",
+ "minute" : "45"
+ },
+ "countdown" : "11",
+ "operator" : {
+ "publicCode" : "EV-T",
+ "code" : "11",
+ "name" : "EVAG Strab"
+ },
+ "dateTime" : {
+ "minute" : "45",
+ "hour" : "18",
+ "weekday" : "7",
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "area" : "2",
+ "servingLine" : {
+ "liErgRiProj" : {
+ "project" : "j24",
+ "network" : "eva",
+ "supplement" : " ",
+ "gid" : "de:vrr:eva-11-103:",
+ "line" : "11103",
+ "direction" : "H"
+ },
+ "symbol" : "103",
+ "key" : "139",
+ "code" : "4",
+ "name" : "Straßenbahn",
+ "destID" : "20009289",
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "stateless" : "eva:11103: :H:j24",
+ "directionFrom" : "Essen Wertstr.",
+ "number" : "103",
+ "lineDisplay" : "line",
+ "delay" : "0",
+ "motType" : "4",
+ "direction" : "Essen Hauptbahnhof"
+ },
+ "platformName" : "Gleis 4",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "name" : "AVMSTripID",
+ "value" : "RB_EVAG.1938"
+ }
+ ],
+ "platform" : "4"
+ },
+ {
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "minute" : "45",
+ "hour" : "18",
+ "weekday" : "7",
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21"
+ },
+ "operator" : {
+ "publicCode" : "",
+ "code" : "13",
+ "name" : "Ruhrbahn Mülheim"
+ },
+ "countdown" : "11",
+ "realDateTime" : {
+ "hour" : "18",
+ "minute" : "45",
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21",
+ "weekday" : "7"
+ },
+ "platform" : "2",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.274790",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "mapName" : "MRCV",
+ "platformName" : "2",
+ "servingLine" : {
+ "key" : "77",
+ "symbol" : "U18",
+ "liErgRiProj" : {
+ "supplement" : " ",
+ "network" : "btm",
+ "project" : "j24",
+ "direction" : "H",
+ "line" : "13U18",
+ "gid" : "de:vrr:btm-13-U18:"
+ },
+ "mtSubcode" : "0",
+ "realtime" : "1",
+ "name" : "U-Bahn",
+ "destID" : "20015225",
+ "code" : "1",
+ "lineDisplay" : "line",
+ "number" : "U18",
+ "directionFrom" : "Essen Berliner Platz",
+ "stateless" : "btm:13U18: :H:j24",
+ "direction" : "Mülheim Hauptbahnhof",
+ "motType" : "2",
+ "delay" : "0"
+ },
+ "area" : "1",
+ "stopName" : "Essen Berliner Platz",
+ "y" : "5297149",
+ "nameWO" : "Berliner Platz",
+ "stopID" : "20009153",
+ "x" : "779713"
+ },
+ {
+ "platformName" : "Gleis 3",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "name" : "AVMSTripID",
+ "value" : "RB_EVAG.2888"
+ }
+ ],
+ "platform" : "3",
+ "area" : "2",
+ "servingLine" : {
+ "delay" : "0",
+ "direction" : "Essen Unterstr.",
+ "motType" : "4",
+ "stateless" : "eva:11105: :R:j24",
+ "lineDisplay" : "line",
+ "number" : "105",
+ "directionFrom" : "Essen Zeche Ludwig",
+ "code" : "4",
+ "destID" : "20009614",
+ "name" : "Straßenbahn",
+ "mtSubcode" : "0",
+ "realtime" : "1",
+ "symbol" : "105",
+ "liErgRiProj" : {
+ "supplement" : " ",
+ "network" : "eva",
+ "project" : "j24",
+ "direction" : "R",
+ "gid" : "de:vrr:eva-11-105:",
+ "line" : "11105"
+ },
+ "key" : "753"
+ },
+ "countdown" : "11",
+ "operator" : {
+ "publicCode" : "EV-T",
+ "code" : "11",
+ "name" : "EVAG Strab"
+ },
+ "dateTime" : {
+ "weekday" : "7",
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9",
+ "minute" : "45",
+ "hour" : "18"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "realDateTime" : {
+ "hour" : "18",
+ "minute" : "45",
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9",
+ "weekday" : "7"
+ },
+ "y" : "5296977",
+ "stopID" : "20009153",
+ "x" : "779748",
+ "nameWO" : "Berliner Platz",
+ "stopName" : "Essen Berliner Platz"
+ },
+ {
+ "y" : "5297057",
+ "stopID" : "20009153",
+ "x" : "779692",
+ "nameWO" : "Berliner Platz",
+ "stopName" : "Essen Berliner Platz",
+ "platformName" : "Gleis 4",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "name" : "AVMSTripID",
+ "value" : "RB_EVAG.3175"
+ }
+ ],
+ "platform" : "4",
+ "area" : "2",
+ "servingLine" : {
+ "direction" : "Essen Helenenstr.",
+ "motType" : "4",
+ "delay" : "1",
+ "lineDisplay" : "line",
+ "directionFrom" : "Essen Philippusstift",
+ "number" : "101",
+ "stateless" : "eva:11101: :H:j24",
+ "mtSubcode" : "0",
+ "realtime" : "1",
+ "name" : "Straßenbahn",
+ "code" : "4",
+ "destID" : "20009306",
+ "key" : "159",
+ "liErgRiProj" : {
+ "supplement" : " ",
+ "project" : "j24",
+ "network" : "eva",
+ "direction" : "H",
+ "line" : "11101",
+ "gid" : "de:vrr:eva-11-101:"
+ },
+ "symbol" : "101"
+ },
+ "countdown" : "17",
+ "operator" : {
+ "publicCode" : "EV-T",
+ "code" : "11",
+ "name" : "EVAG Strab"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "minute" : "50",
+ "hour" : "18",
+ "weekday" : "7",
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21"
+ },
+ "realDateTime" : {
+ "minute" : "51",
+ "hour" : "18",
+ "weekday" : "7",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024"
+ }
+ },
+ {
+ "realDateTime" : {
+ "weekday" : "7",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024",
+ "minute" : "50",
+ "hour" : "18"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "weekday" : "7",
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9",
+ "minute" : "50",
+ "hour" : "18"
+ },
+ "operator" : {
+ "publicCode" : "EV-T",
+ "name" : "EVAG Strab",
+ "code" : "11"
+ },
+ "countdown" : "16",
+ "servingLine" : {
+ "liErgRiProj" : {
+ "supplement" : " ",
+ "project" : "j24",
+ "network" : "eva",
+ "direction" : "H",
+ "line" : "11106",
+ "gid" : "de:vrr:eva-11-106:"
+ },
+ "symbol" : "106",
+ "key" : "171",
+ "code" : "4",
+ "name" : "Straßenbahn",
+ "destID" : "20009254",
+ "mtSubcode" : "0",
+ "realtime" : "1",
+ "stateless" : "eva:11106: :H:j24",
+ "lineDisplay" : "line",
+ "directionFrom" : "Essen Helenenstr.",
+ "number" : "106",
+ "delay" : "0",
+ "direction" : "Essen Germaniaplatz",
+ "motType" : "4"
+ },
+ "area" : "2",
+ "platform" : "3",
+ "attrs" : [
+ {
+ "name" : "AVMSTripID",
+ "value" : "RB_EVAG.1072"
+ }
+ ],
+ "mapName" : "MRCV",
+ "platformName" : "Gleis 3",
+ "stopName" : "Essen Berliner Platz",
+ "nameWO" : "Berliner Platz",
+ "stopID" : "20009153",
+ "x" : "779748",
+ "y" : "5296977"
+ },
+ {
+ "platform" : "2",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.274551",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "platformName" : "2",
+ "servingLine" : {
+ "delay" : "0",
+ "direction" : "Essen Margarethenhöhe",
+ "motType" : "2",
+ "stateless" : "eva:10U17: :H:j24",
+ "lineDisplay" : "line",
+ "number" : "U17",
+ "directionFrom" : "Essen Karlsplatz",
+ "name" : "U-Bahn",
+ "code" : "1",
+ "destID" : "20009447",
+ "mtSubcode" : "0",
+ "realtime" : "1",
+ "symbol" : "U17",
+ "liErgRiProj" : {
+ "project" : "j24",
+ "network" : "eva",
+ "supplement" : " ",
+ "line" : "10U17",
+ "gid" : "de:vrr:eva-10-U17:",
+ "direction" : "H"
+ },
+ "key" : "111"
+ },
+ "area" : "1",
+ "dateTime" : {
+ "weekday" : "7",
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21",
+ "minute" : "50",
+ "hour" : "18"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "countdown" : "16",
+ "operator" : {
+ "code" : "10",
+ "publicCode" : "EV-U",
+ "name" : "EVAG U-Bahn"
+ },
+ "realDateTime" : {
+ "weekday" : "7",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024",
+ "minute" : "50",
+ "hour" : "18"
+ },
+ "y" : "5297149",
+ "nameWO" : "Berliner Platz",
+ "x" : "779713",
+ "stopID" : "20009153",
+ "stopName" : "Essen Berliner Platz"
+ },
+ {
+ "y" : "5296897",
+ "stopID" : "20009153",
+ "x" : "779732",
+ "nameWO" : "Berliner Platz",
+ "stopName" : "Essen Berliner Platz",
+ "platformName" : "3",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.87593",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "mapName" : "MRCV",
+ "platform" : "3",
+ "area" : "3",
+ "servingLine" : {
+ "symbol" : "166",
+ "liErgRiProj" : {
+ "direction" : "H",
+ "line" : "12166",
+ "gid" : "de:vrr:eva-12-166:",
+ "supplement" : " ",
+ "project" : "j24",
+ "network" : "eva"
+ },
+ "key" : "316",
+ "name" : "Niederflurbus",
+ "destID" : "20008454",
+ "code" : "5",
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "stateless" : "eva:12166: :H:j24",
+ "number" : "166",
+ "directionFrom" : "Essen Dellwig Bahnhof",
+ "lineDisplay" : "line",
+ "delay" : "0",
+ "motType" : "5",
+ "direction" : "Hattingen Märkische Str."
+ },
+ "countdown" : "16",
+ "operator" : {
+ "name" : "EVAG Bus",
+ "publicCode" : "EV-B",
+ "code" : "12"
+ },
+ "dateTime" : {
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21",
+ "weekday" : "7",
+ "hour" : "18",
+ "minute" : "50"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "realDateTime" : {
+ "hour" : "18",
+ "minute" : "50",
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21",
+ "weekday" : "7"
+ }
+ },
+ {
+ "area" : "4",
+ "servingLine" : {
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "name" : "Niederflurbus",
+ "code" : "5",
+ "destID" : "20009302",
+ "key" : "280",
+ "symbol" : "145",
+ "liErgRiProj" : {
+ "gid" : "de:vrr:eva-12-145:",
+ "line" : "12145",
+ "direction" : "H",
+ "project" : "j24",
+ "network" : "eva",
+ "supplement" : " "
+ },
+ "motType" : "5",
+ "direction" : "Essen Heisingen Baldeneysee",
+ "delay" : "0",
+ "number" : "145",
+ "directionFrom" : "Essen Erbach",
+ "lineDisplay" : "line",
+ "stateless" : "eva:12145: :H:j24"
+ },
+ "platformName" : "2",
+ "platform" : "2",
+ "attrs" : [
+ {
+ "name" : "AVMSTripID",
+ "value" : "RB_EVAG.84849"
+ }
+ ],
+ "mapName" : "MRCV",
+ "realDateTime" : {
+ "minute" : "51",
+ "hour" : "18",
+ "weekday" : "7",
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21"
+ },
+ "countdown" : "17",
+ "operator" : {
+ "publicCode" : "EV-B",
+ "name" : "EVAG Bus",
+ "code" : "12"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21",
+ "weekday" : "7",
+ "hour" : "18",
+ "minute" : "51"
+ },
+ "x" : "779673",
+ "stopID" : "20009153",
+ "nameWO" : "Berliner Platz",
+ "y" : "5297075",
+ "stopName" : "Essen Berliner Platz"
+ },
+ {
+ "realDateTime" : {
+ "hour" : "18",
+ "minute" : "51",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024",
+ "weekday" : "7"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "weekday" : "7",
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21",
+ "minute" : "51",
+ "hour" : "18"
+ },
+ "operator" : {
+ "publicCode" : "EV-U",
+ "name" : "EVAG U-Bahn",
+ "code" : "10"
+ },
+ "countdown" : "17",
+ "servingLine" : {
+ "lineDisplay" : "line",
+ "directionFrom" : "Essen Messe W.-Süd/Gruga",
+ "number" : "U11",
+ "stateless" : "eva:10U11: :R:j24",
+ "direction" : "Gelsenkirchen Buerer Str.",
+ "motType" : "2",
+ "delay" : "0",
+ "key" : "712",
+ "liErgRiProj" : {
+ "supplement" : " ",
+ "network" : "eva",
+ "project" : "j24",
+ "direction" : "R",
+ "line" : "10U11",
+ "gid" : "de:vrr:eva-10-U11:"
+ },
+ "symbol" : "U11",
+ "mtSubcode" : "0",
+ "realtime" : "1",
+ "name" : "U-Bahn",
+ "code" : "1",
+ "destID" : "20005579"
+ },
+ "area" : "1",
+ "platform" : "1",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.274438",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "platformName" : "1",
+ "stopName" : "Essen Berliner Platz",
+ "nameWO" : "Berliner Platz",
+ "x" : "779741",
+ "stopID" : "20009153",
+ "y" : "5297142"
+ },
+ {
+ "stopName" : "Essen Berliner Platz",
+ "y" : "5296977",
+ "x" : "779748",
+ "stopID" : "20009153",
+ "nameWO" : "Berliner Platz",
+ "countdown" : "18",
+ "operator" : {
+ "code" : "11",
+ "publicCode" : "EV-T",
+ "name" : "EVAG Strab"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "hour" : "18",
+ "minute" : "52",
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9",
+ "weekday" : "7"
+ },
+ "realDateTime" : {
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024",
+ "weekday" : "7",
+ "hour" : "18",
+ "minute" : "52"
+ },
+ "platformName" : "Gleis 3",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "name" : "AVMSTripID",
+ "value" : "RB_EVAG.3554"
+ }
+ ],
+ "platform" : "3",
+ "area" : "2",
+ "servingLine" : {
+ "delay" : "0",
+ "motType" : "4",
+ "direction" : "Essen Wertstr.",
+ "stateless" : "eva:11103: :R:j24",
+ "number" : "103",
+ "directionFrom" : "Essen Steele S",
+ "lineDisplay" : "line",
+ "name" : "Straßenbahn",
+ "code" : "4",
+ "destID" : "20009641",
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "symbol" : "103",
+ "liErgRiProj" : {
+ "gid" : "de:vrr:eva-11-103:",
+ "line" : "11103",
+ "direction" : "R",
+ "network" : "eva",
+ "project" : "j24",
+ "supplement" : " "
+ },
+ "key" : "463"
+ }
+ },
+ {
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.2648",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "mapName" : "MRCV",
+ "platform" : "4",
+ "platformName" : "Gleis 4",
+ "servingLine" : {
+ "motType" : "4",
+ "direction" : "Essen Zeche Ludwig",
+ "delay" : "0",
+ "directionFrom" : "Essen Unterstr.",
+ "number" : "105",
+ "lineDisplay" : "line",
+ "stateless" : "eva:11105: :H:j24",
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "name" : "Straßenbahn",
+ "code" : "4",
+ "destID" : "20009665",
+ "key" : "369",
+ "liErgRiProj" : {
+ "gid" : "de:vrr:eva-11-105:",
+ "line" : "11105",
+ "direction" : "H",
+ "network" : "eva",
+ "project" : "j24",
+ "supplement" : " "
+ },
+ "symbol" : "105"
+ },
+ "area" : "2",
+ "dateTime" : {
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21",
+ "weekday" : "7",
+ "hour" : "18",
+ "minute" : "53"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "countdown" : "19",
+ "operator" : {
+ "name" : "EVAG Strab",
+ "publicCode" : "EV-T",
+ "code" : "11"
+ },
+ "realDateTime" : {
+ "minute" : "53",
+ "hour" : "18",
+ "weekday" : "7",
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9"
+ },
+ "y" : "5297057",
+ "nameWO" : "Berliner Platz",
+ "stopID" : "20009153",
+ "x" : "779692",
+ "stopName" : "Essen Berliner Platz"
+ },
+ {
+ "platformName" : "Gleis 4",
+ "platform" : "4",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.3745",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "area" : "2",
+ "servingLine" : {
+ "lineDisplay" : "line",
+ "directionFrom" : "Frohnhausen Breilsort",
+ "number" : "109",
+ "stateless" : "eva:11109: :H:j24",
+ "direction" : "Essen Steele S",
+ "motType" : "4",
+ "delay" : "0",
+ "key" : "123",
+ "liErgRiProj" : {
+ "supplement" : " ",
+ "network" : "eva",
+ "project" : "j24",
+ "direction" : "H",
+ "line" : "11109",
+ "gid" : "de:vrr:eva-11-109:"
+ },
+ "symbol" : "109",
+ "mtSubcode" : "0",
+ "realtime" : "1",
+ "name" : "Straßenbahn",
+ "code" : "4",
+ "destID" : "20009582"
+ },
+ "countdown" : "21",
+ "operator" : {
+ "code" : "11",
+ "publicCode" : "EV-T",
+ "name" : "EVAG Strab"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "minute" : "55",
+ "hour" : "18",
+ "weekday" : "7",
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9"
+ },
+ "realDateTime" : {
+ "hour" : "18",
+ "minute" : "55",
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21",
+ "weekday" : "7"
+ },
+ "y" : "5297057",
+ "stopID" : "20009153",
+ "x" : "779692",
+ "nameWO" : "Berliner Platz",
+ "stopName" : "Essen Berliner Platz"
+ },
+ {
+ "operator" : {
+ "code" : "11",
+ "publicCode" : "EV-T",
+ "name" : "EVAG Strab"
+ },
+ "countdown" : "23",
+ "dateTime" : {
+ "weekday" : "7",
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21",
+ "minute" : "57",
+ "hour" : "18"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "realDateTime" : {
+ "hour" : "18",
+ "minute" : "57",
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9",
+ "weekday" : "7"
+ },
+ "platformName" : "Gleis 3",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.1560",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "mapName" : "MRCV",
+ "platform" : "3",
+ "area" : "2",
+ "servingLine" : {
+ "mtSubcode" : "0",
+ "realtime" : "1",
+ "destID" : "20009243",
+ "code" : "4",
+ "name" : "Straßenbahn",
+ "key" : "374",
+ "symbol" : "109",
+ "liErgRiProj" : {
+ "project" : "j24",
+ "network" : "eva",
+ "supplement" : " ",
+ "gid" : "de:vrr:eva-11-109:",
+ "line" : "11109",
+ "direction" : "R"
+ },
+ "direction" : "Frohnhausen Breilsort",
+ "motType" : "4",
+ "delay" : "0",
+ "lineDisplay" : "line",
+ "number" : "109",
+ "directionFrom" : "Essen Steele S",
+ "stateless" : "eva:11109: :R:j24"
+ },
+ "stopName" : "Essen Berliner Platz",
+ "y" : "5296977",
+ "stopID" : "20009153",
+ "x" : "779748",
+ "nameWO" : "Berliner Platz"
+ },
+ {
+ "servingLine" : {
+ "liErgRiProj" : {
+ "network" : "eva",
+ "project" : "j24",
+ "supplement" : " ",
+ "gid" : "de:vrr:eva-10-U11:",
+ "line" : "10U11",
+ "direction" : "H"
+ },
+ "symbol" : "U11",
+ "key" : "275",
+ "destID" : "20009270",
+ "name" : "U-Bahn",
+ "code" : "1",
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "stateless" : "eva:10U11: :H:j24",
+ "directionFrom" : "Gelsenkirchen Buerer Str.",
+ "number" : "U11",
+ "lineDisplay" : "line",
+ "delay" : "0",
+ "motType" : "2",
+ "direction" : "Essen Messe W.-Süd/Gruga"
+ },
+ "area" : "1",
+ "platform" : "2",
+ "attrs" : [
+ {
+ "name" : "AVMSTripID",
+ "value" : "RB_EVAG.274909"
+ }
+ ],
+ "mapName" : "MRCV",
+ "platformName" : "2",
+ "realDateTime" : {
+ "weekday" : "7",
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21",
+ "minute" : "57",
+ "hour" : "18"
+ },
+ "dateTime" : {
+ "minute" : "57",
+ "hour" : "18",
+ "weekday" : "7",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "operator" : {
+ "name" : "EVAG U-Bahn",
+ "publicCode" : "EV-U",
+ "code" : "10"
+ },
+ "countdown" : "23",
+ "nameWO" : "Berliner Platz",
+ "x" : "779713",
+ "stopID" : "20009153",
+ "y" : "5297149",
+ "stopName" : "Essen Berliner Platz"
+ },
+ {
+ "stopName" : "Essen Berliner Platz",
+ "nameWO" : "Berliner Platz",
+ "stopID" : "20009153",
+ "x" : "779741",
+ "y" : "5297142",
+ "realDateTime" : {
+ "hour" : "18",
+ "minute" : "58",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024",
+ "weekday" : "7"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "hour" : "18",
+ "minute" : "58",
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21",
+ "weekday" : "7"
+ },
+ "operator" : {
+ "publicCode" : "EV-U",
+ "name" : "EVAG U-Bahn",
+ "code" : "10"
+ },
+ "countdown" : "24",
+ "servingLine" : {
+ "stateless" : "eva:10U17: :R:j24",
+ "number" : "U17",
+ "directionFrom" : "Essen Margarethenhöhe",
+ "lineDisplay" : "line",
+ "delay" : "0",
+ "motType" : "2",
+ "direction" : "Essen Karlsplatz",
+ "symbol" : "U17",
+ "liErgRiProj" : {
+ "direction" : "R",
+ "gid" : "de:vrr:eva-10-U17:",
+ "line" : "10U17",
+ "supplement" : " ",
+ "network" : "eva",
+ "project" : "j24"
+ },
+ "key" : "266",
+ "code" : "1",
+ "name" : "U-Bahn",
+ "destID" : "20009370",
+ "realtime" : "1",
+ "mtSubcode" : "0"
+ },
+ "area" : "1",
+ "attrs" : [
+ {
+ "name" : "AVMSTripID",
+ "value" : "RB_EVAG.274889"
+ }
+ ],
+ "mapName" : "MRCV",
+ "platform" : "1",
+ "platformName" : "1"
+ },
+ {
+ "stopName" : "Essen Berliner Platz",
+ "x" : "779692",
+ "stopID" : "20009153",
+ "nameWO" : "Berliner Platz",
+ "y" : "5297057",
+ "realDateTime" : {
+ "weekday" : "7",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024",
+ "minute" : "0",
+ "hour" : "19"
+ },
+ "countdown" : "26",
+ "operator" : {
+ "name" : "EVAG Strab",
+ "publicCode" : "EV-T",
+ "code" : "11"
+ },
+ "dateTime" : {
+ "hour" : "19",
+ "minute" : "0",
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21",
+ "weekday" : "7"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "area" : "2",
+ "servingLine" : {
+ "stateless" : "eva:11103: :H:j24",
+ "directionFrom" : "Essen Wertstr.",
+ "number" : "103",
+ "lineDisplay" : "line",
+ "delay" : "0",
+ "motType" : "4",
+ "direction" : "Essen Hauptbahnhof",
+ "liErgRiProj" : {
+ "network" : "eva",
+ "project" : "j24",
+ "supplement" : " ",
+ "gid" : "de:vrr:eva-11-103:",
+ "line" : "11103",
+ "direction" : "H"
+ },
+ "symbol" : "103",
+ "key" : "141",
+ "name" : "Straßenbahn",
+ "code" : "4",
+ "destID" : "20009289",
+ "realtime" : "1",
+ "mtSubcode" : "0"
+ },
+ "platformName" : "Gleis 4",
+ "attrs" : [
+ {
+ "name" : "AVMSTripID",
+ "value" : "RB_EVAG.2069"
+ }
+ ],
+ "mapName" : "MRCV",
+ "platform" : "4"
+ },
+ {
+ "countdown" : "26",
+ "operator" : {
+ "code" : "13",
+ "publicCode" : "",
+ "name" : "Ruhrbahn Mülheim"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "weekday" : "7",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024",
+ "minute" : "0",
+ "hour" : "19"
+ },
+ "realDateTime" : {
+ "minute" : "0",
+ "hour" : "19",
+ "weekday" : "7",
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21"
+ },
+ "platformName" : "2",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.274647",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "mapName" : "MRCV",
+ "platform" : "2",
+ "area" : "1",
+ "servingLine" : {
+ "delay" : "0",
+ "motType" : "2",
+ "direction" : "Mülheim Hauptbahnhof",
+ "stateless" : "btm:13U18: :H:j24",
+ "number" : "U18",
+ "directionFrom" : "Essen Berliner Platz",
+ "lineDisplay" : "line",
+ "name" : "U-Bahn",
+ "destID" : "20015225",
+ "code" : "1",
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "symbol" : "U18",
+ "liErgRiProj" : {
+ "project" : "j24",
+ "network" : "btm",
+ "supplement" : " ",
+ "line" : "13U18",
+ "gid" : "de:vrr:btm-13-U18:",
+ "direction" : "H"
+ },
+ "key" : "78"
+ },
+ "stopName" : "Essen Berliner Platz",
+ "y" : "5297149",
+ "x" : "779713",
+ "stopID" : "20009153",
+ "nameWO" : "Berliner Platz"
+ },
+ {
+ "nameWO" : "Berliner Platz",
+ "x" : "779748",
+ "stopID" : "20009153",
+ "y" : "5296977",
+ "stopName" : "Essen Berliner Platz",
+ "servingLine" : {
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "code" : "4",
+ "name" : "Straßenbahn",
+ "destID" : "20009614",
+ "key" : "755",
+ "symbol" : "105",
+ "liErgRiProj" : {
+ "direction" : "R",
+ "gid" : "de:vrr:eva-11-105:",
+ "line" : "11105",
+ "supplement" : " ",
+ "network" : "eva",
+ "project" : "j24"
+ },
+ "motType" : "4",
+ "direction" : "Essen Unterstr.",
+ "delay" : "0",
+ "number" : "105",
+ "directionFrom" : "Essen Zeche Ludwig",
+ "lineDisplay" : "line",
+ "stateless" : "eva:11105: :R:j24"
+ },
+ "area" : "2",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.2412",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "platform" : "3",
+ "platformName" : "Gleis 3",
+ "realDateTime" : {
+ "hour" : "19",
+ "minute" : "0",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024",
+ "weekday" : "7"
+ },
+ "dateTime" : {
+ "weekday" : "7",
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21",
+ "minute" : "0",
+ "hour" : "19"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "countdown" : "26",
+ "operator" : {
+ "publicCode" : "EV-T",
+ "code" : "11",
+ "name" : "EVAG Strab"
+ }
+ },
+ {
+ "countdown" : "30",
+ "operator" : {
+ "code" : "12",
+ "publicCode" : "EV-B",
+ "name" : "EVAG Bus"
+ },
+ "dateTime" : {
+ "weekday" : "7",
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9",
+ "minute" : "4",
+ "hour" : "19"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "realDateTime" : {
+ "weekday" : "7",
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9",
+ "minute" : "4",
+ "hour" : "19"
+ },
+ "platformName" : "1",
+ "platform" : "1",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "name" : "AVMSTripID",
+ "value" : "RB_EVAG.84908"
+ }
+ ],
+ "area" : "4",
+ "servingLine" : {
+ "name" : "Niederflurbus",
+ "destID" : "20009222",
+ "code" : "5",
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "liErgRiProj" : {
+ "supplement" : " ",
+ "project" : "j24",
+ "network" : "eva",
+ "direction" : "R",
+ "line" : "12145",
+ "gid" : "de:vrr:eva-12-145:"
+ },
+ "symbol" : "145",
+ "key" : "561",
+ "delay" : "0",
+ "motType" : "5",
+ "direction" : "Essen Erbach",
+ "stateless" : "eva:12145: :R:j24",
+ "directionFrom" : "Essen Heisingen Baldeneysee",
+ "number" : "145",
+ "lineDisplay" : "line"
+ },
+ "stopName" : "Essen Berliner Platz",
+ "y" : "5297058",
+ "stopID" : "20009153",
+ "x" : "779634",
+ "nameWO" : "Berliner Platz"
+ },
+ {
+ "nameWO" : "Berliner Platz",
+ "stopID" : "20009153",
+ "x" : "779748",
+ "y" : "5296893",
+ "stopName" : "Essen Berliner Platz",
+ "servingLine" : {
+ "liErgRiProj" : {
+ "supplement" : " ",
+ "project" : "j24",
+ "network" : "eva",
+ "direction" : "R",
+ "line" : "12166",
+ "gid" : "de:vrr:eva-12-166:"
+ },
+ "symbol" : "166",
+ "key" : "246",
+ "name" : "Niederflurbus",
+ "code" : "5",
+ "destID" : "20009197",
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "stateless" : "eva:12166: :R:j24",
+ "directionFrom" : "Hattingen Märkische Str.",
+ "number" : "166",
+ "lineDisplay" : "line",
+ "delay" : "0",
+ "motType" : "5",
+ "direction" : "Essen Dellwig Bahnhof"
+ },
+ "area" : "3",
+ "platform" : "4",
+ "attrs" : [
+ {
+ "name" : "AVMSTripID",
+ "value" : "RB_EVAG.87911"
+ }
+ ],
+ "mapName" : "MRCV",
+ "platformName" : "4",
+ "realDateTime" : {
+ "weekday" : "7",
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9",
+ "minute" : "4",
+ "hour" : "19"
+ },
+ "dateTime" : {
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9",
+ "weekday" : "7",
+ "hour" : "19",
+ "minute" : "4"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "countdown" : "30",
+ "operator" : {
+ "publicCode" : "EV-B",
+ "code" : "12",
+ "name" : "EVAG Bus"
+ }
+ },
+ {
+ "realDateTime" : {
+ "minute" : "5",
+ "hour" : "19",
+ "weekday" : "7",
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21"
+ },
+ "countdown" : "31",
+ "operator" : {
+ "publicCode" : "EV-T",
+ "code" : "11",
+ "name" : "EVAG Strab"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "minute" : "5",
+ "hour" : "19",
+ "weekday" : "7",
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9"
+ },
+ "area" : "2",
+ "servingLine" : {
+ "mtSubcode" : "0",
+ "realtime" : "1",
+ "code" : "4",
+ "name" : "Straßenbahn",
+ "destID" : "20009254",
+ "key" : "174",
+ "symbol" : "106",
+ "liErgRiProj" : {
+ "line" : "11106",
+ "gid" : "de:vrr:eva-11-106:",
+ "direction" : "H",
+ "project" : "j24",
+ "network" : "eva",
+ "supplement" : " "
+ },
+ "direction" : "Essen Germaniaplatz",
+ "motType" : "4",
+ "delay" : "0",
+ "lineDisplay" : "line",
+ "number" : "106",
+ "directionFrom" : "Essen Helenenstr.",
+ "stateless" : "eva:11106: :H:j24"
+ },
+ "platformName" : "Gleis 3",
+ "platform" : "3",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.1395",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "mapName" : "MRCV",
+ "stopName" : "Essen Berliner Platz",
+ "stopID" : "20009153",
+ "x" : "779748",
+ "nameWO" : "Berliner Platz",
+ "y" : "5296977"
+ },
+ {
+ "x" : "779748",
+ "stopID" : "20009153",
+ "nameWO" : "Berliner Platz",
+ "y" : "5296977",
+ "stopName" : "Essen Berliner Platz",
+ "area" : "2",
+ "servingLine" : {
+ "stateless" : "eva:11103: :R:j24",
+ "lineDisplay" : "line",
+ "number" : "103",
+ "directionFrom" : "Essen Hauptbahnhof",
+ "delay" : "0",
+ "direction" : "Essen Wertstr.",
+ "motType" : "4",
+ "symbol" : "103",
+ "liErgRiProj" : {
+ "supplement" : " ",
+ "project" : "j24",
+ "network" : "eva",
+ "direction" : "R",
+ "gid" : "de:vrr:eva-11-103:",
+ "line" : "11103"
+ },
+ "key" : "524",
+ "name" : "Straßenbahn",
+ "destID" : "20009641",
+ "code" : "4",
+ "mtSubcode" : "0",
+ "realtime" : "1"
+ },
+ "platformName" : "Gleis 3",
+ "platform" : "3",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.1956",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "realDateTime" : {
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024",
+ "weekday" : "7",
+ "hour" : "19",
+ "minute" : "5"
+ },
+ "operator" : {
+ "publicCode" : "EV-T",
+ "name" : "EVAG Strab",
+ "code" : "11"
+ },
+ "countdown" : "31",
+ "dateTime" : {
+ "weekday" : "7",
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21",
+ "minute" : "5",
+ "hour" : "19"
+ },
+ "realtimeTripStatus" : "MONITORED"
+ },
+ {
+ "stopName" : "Essen Berliner Platz",
+ "stopID" : "20009153",
+ "x" : "779713",
+ "nameWO" : "Berliner Platz",
+ "y" : "5297149",
+ "realDateTime" : {
+ "minute" : "5",
+ "hour" : "19",
+ "weekday" : "7",
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21"
+ },
+ "operator" : {
+ "publicCode" : "EV-U",
+ "code" : "10",
+ "name" : "EVAG U-Bahn"
+ },
+ "countdown" : "31",
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "minute" : "5",
+ "hour" : "19",
+ "weekday" : "7",
+ "month" : "9",
+ "year" : "2024",
+ "day" : "21"
+ },
+ "area" : "1",
+ "servingLine" : {
+ "code" : "1",
+ "name" : "U-Bahn",
+ "destID" : "20009447",
+ "mtSubcode" : "0",
+ "realtime" : "1",
+ "liErgRiProj" : {
+ "line" : "10U17",
+ "gid" : "de:vrr:eva-10-U17:",
+ "direction" : "H",
+ "project" : "j24",
+ "network" : "eva",
+ "supplement" : " "
+ },
+ "symbol" : "U17",
+ "key" : "114",
+ "delay" : "0",
+ "direction" : "Essen Margarethenhöhe",
+ "motType" : "2",
+ "stateless" : "eva:10U17: :H:j24",
+ "lineDisplay" : "line",
+ "directionFrom" : "Essen Karlsplatz",
+ "number" : "U17"
+ },
+ "platformName" : "2",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.274834",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "platform" : "2"
+ },
+ {
+ "stopName" : "Essen Berliner Platz",
+ "x" : "779692",
+ "stopID" : "20009153",
+ "nameWO" : "Berliner Platz",
+ "y" : "5297057",
+ "realDateTime" : {
+ "hour" : "19",
+ "minute" : "5",
+ "day" : "21",
+ "year" : "2024",
+ "month" : "9",
+ "weekday" : "7"
+ },
+ "countdown" : "31",
+ "operator" : {
+ "code" : "11",
+ "publicCode" : "EV-T",
+ "name" : "EVAG Strab"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "minute" : "5",
+ "hour" : "19",
+ "weekday" : "7",
+ "year" : "2024",
+ "month" : "9",
+ "day" : "21"
+ },
+ "area" : "2",
+ "servingLine" : {
+ "key" : "162",
+ "symbol" : "101",
+ "liErgRiProj" : {
+ "supplement" : " ",
+ "network" : "eva",
+ "project" : "j24",
+ "direction" : "H",
+ "gid" : "de:vrr:eva-11-101:",
+ "line" : "11101"
+ },
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "name" : "Straßenbahn",
+ "code" : "4",
+ "destID" : "20009306",
+ "number" : "101",
+ "directionFrom" : "Essen Philippusstift",
+ "lineDisplay" : "line",
+ "stateless" : "eva:11101: :H:j24",
+ "motType" : "4",
+ "direction" : "Essen Helenenstr.",
+ "delay" : "0"
+ },
+ "platformName" : "Gleis 4",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.3224",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "platform" : "4"
+ },
+ {
+ "platformName" : "1",
+ "platform" : "1",
+ "mapName" : "MRCV",
+ "attrs" : [
+ {
+ "name" : "AVMSTripID",
+ "value" : "RB_EVAG.274465"
+ }
+ ],
+ "area" : "1",
+ "servingLine" : {
+ "key" : "714",
+ "symbol" : "U11",
+ "liErgRiProj" : {
+ "supplement" : " ",
+ "project" : "j24",
+ "network" : "eva",
+ "direction" : "R",
+ "gid" : "de:vrr:eva-10-U11:",
+ "line" : "10U11"
+ },
+ "mtSubcode" : "0",
+ "realtime" : "1",
+ "code" : "1",
+ "name" : "U-Bahn",
+ "destID" : "20005579",
+ "lineDisplay" : "line",
+ "number" : "U11",
+ "directionFrom" : "Essen Messe W.-Süd/Gruga",
+ "stateless" : "eva:10U11: :R:j24",
+ "direction" : "Gelsenkirchen Buerer Str.",
+ "motType" : "2",
+ "delay" : "0"
+ },
+ "operator" : {
+ "code" : "10",
+ "publicCode" : "EV-U",
+ "name" : "EVAG U-Bahn"
+ },
+ "countdown" : "32",
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "hour" : "19",
+ "minute" : "6",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024",
+ "weekday" : "7"
+ },
+ "realDateTime" : {
+ "hour" : "19",
+ "minute" : "6",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024",
+ "weekday" : "7"
+ },
+ "y" : "5297142",
+ "x" : "779741",
+ "stopID" : "20009153",
+ "nameWO" : "Berliner Platz",
+ "stopName" : "Essen Berliner Platz"
+ },
+ {
+ "y" : "5297057",
+ "stopID" : "20009153",
+ "x" : "779692",
+ "nameWO" : "Berliner Platz",
+ "stopName" : "Essen Berliner Platz",
+ "platformName" : "Gleis 4",
+ "attrs" : [
+ {
+ "value" : "RB_EVAG.2735",
+ "name" : "AVMSTripID"
+ }
+ ],
+ "mapName" : "MRCV",
+ "platform" : "4",
+ "area" : "2",
+ "servingLine" : {
+ "motType" : "4",
+ "direction" : "Essen Zeche Ludwig",
+ "delay" : "0",
+ "directionFrom" : "Essen Unterstr.",
+ "number" : "105",
+ "lineDisplay" : "line",
+ "stateless" : "eva:11105: :H:j24",
+ "realtime" : "1",
+ "mtSubcode" : "0",
+ "destID" : "20009665",
+ "code" : "4",
+ "name" : "Straßenbahn",
+ "key" : "372",
+ "liErgRiProj" : {
+ "direction" : "H",
+ "line" : "11105",
+ "gid" : "de:vrr:eva-11-105:",
+ "supplement" : " ",
+ "network" : "eva",
+ "project" : "j24"
+ },
+ "symbol" : "105"
+ },
+ "countdown" : "34",
+ "operator" : {
+ "publicCode" : "EV-T",
+ "code" : "11",
+ "name" : "EVAG Strab"
+ },
+ "realtimeTripStatus" : "MONITORED",
+ "dateTime" : {
+ "weekday" : "7",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024",
+ "minute" : "8",
+ "hour" : "19"
+ },
+ "realDateTime" : {
+ "minute" : "8",
+ "hour" : "19",
+ "weekday" : "7",
+ "day" : "21",
+ "month" : "9",
+ "year" : "2024"
+ }
+ }
+ ],
+ "arr" : {
+ "points" : null,
+ "input" : {
+ "input" : ""
+ }
+ },
+ "dateRange" : [
+ {
+ "month" : "09",
+ "year" : "2024",
+ "day" : "21",
+ "weekday" : "7"
+ },
+ {
+ "year" : "2024",
+ "month" : "09",
+ "day" : "22",
+ "weekday" : "1"
+ },
+ {
+ "day" : "23",
+ "year" : "2024",
+ "month" : "09",
+ "weekday" : "2"
+ },
+ {
+ "day" : "24",
+ "month" : "09",
+ "year" : "2024",
+ "weekday" : "3"
+ },
+ {
+ "weekday" : "4",
+ "day" : "25",
+ "year" : "2024",
+ "month" : "09"
+ },
+ {
+ "weekday" : "5",
+ "day" : "26",
+ "year" : "2024",
+ "month" : "09"
+ },
+ {
+ "month" : "09",
+ "year" : "2024",
+ "day" : "27",
+ "weekday" : "6"
+ },
+ {
+ "year" : "2024",
+ "month" : "09",
+ "day" : "28",
+ "weekday" : "7"
+ },
+ {
+ "month" : "09",
+ "year" : "2024",
+ "day" : "29",
+ "weekday" : "1"
+ },
+ {
+ "month" : "09",
+ "year" : "2024",
+ "day" : "30",
+ "weekday" : "2"
+ },
+ {
+ "weekday" : "3",
+ "day" : "01",
+ "year" : "2024",
+ "month" : "10"
+ },
+ {
+ "day" : "02",
+ "month" : "10",
+ "year" : "2024",
+ "weekday" : "4"
+ },
+ {
+ "weekday" : "5",
+ "year" : "2024",
+ "month" : "10",
+ "day" : "03"
+ },
+ {
+ "weekday" : "6",
+ "day" : "04",
+ "year" : "2024",
+ "month" : "10"
+ },
+ {
+ "month" : "10",
+ "year" : "2024",
+ "day" : "05",
+ "weekday" : "7"
+ }
+ ],
+ "dm" : {
+ "points" : {
+ "point" : {
+ "stateless" : "20009153",
+ "infos" : [
+ {
+ "infoText" : {
+ "smsText" : "Die Fahrtreppe (Eingang D (abwärts) von Straßenebene zur Verteilerebene) an der Haltestelle Essen Berliner Platz ist ausser Betrieb.",
+ "additionalText" : "Die beschriebenen Änderungen sind in der elektronischen Fahrplanauskunft (EFA) <b>nicht</b> berücksichtigt.",
+ "htmlText" : "",
+ "subtitle" : "Haltestelle Essen Berliner Platz: Die Fahrtreppe ist nicht verfügbar. (Eingang D (abwaerts) von Strassenebene zur Verteilerebene)",
+ "wmlText" : "Die Fahrtreppe (Eingang D (abwärts) von Straßenebene zur Verteilerebene) an der Haltestelle Essen Berliner Platz ist ausser Betrieb.",
+ "content" : "Vom 29.12. 07:46 Uhr bis voraussichtlich 21.09. 23:59 Uhr.",
+ "subject" : "",
+ "speechText" : ""
+ },
+ "paramList" : [
+ {
+ "type" : "addInfoParam",
+ "name" : "infoType",
+ "edit" : "0",
+ "value" : "stopInfo"
+ },
+ {
+ "type" : "system",
+ "name" : "infoID",
+ "edit" : "0",
+ "value" : "20240514915345"
+ },
+ {
+ "type" : "system",
+ "name" : "seqID",
+ "edit" : "0",
+ "value" : "150"
+ },
+ {
+ "name" : "incidentDateTime",
+ "type" : "system",
+ "value" : "29/12/2023 07:46 - 22/09/2024 00:00",
+ "edit" : "0"
+ }
+ ],
+ "infoLinkText" : "Haltestelle Essen Berliner Platz: Die Fahrtreppe ist nicht verfügbar. (Eingang D (abwaerts) von Strassenebene zur Verteilerebene)",
+ "infoLinkURL" : "http://217.70.161.100:80/cm/XSLT_CM_SHOWADDINFO_REQUEST?infoID=20240514915345&seqID=150"
+ },
+ {
+ "paramList" : [
+ {
+ "name" : "infoType",
+ "type" : "addInfoParam",
+ "edit" : "0",
+ "value" : "stopInfo"
+ },
+ {
+ "type" : "system",
+ "name" : "infoID",
+ "edit" : "0",
+ "value" : "20240514915357"
+ },
+ {
+ "value" : "132",
+ "edit" : "0",
+ "name" : "seqID",
+ "type" : "system"
+ },
+ {
+ "edit" : "0",
+ "value" : "13/02/2024 08:13 - 22/09/2024 00:00",
+ "type" : "system",
+ "name" : "incidentDateTime"
+ }
+ ],
+ "infoText" : {
+ "content" : "Vom 13.02. 08:13 Uhr bis voraussichtlich 21.09. 23:59 Uhr.",
+ "subject" : "",
+ "speechText" : "",
+ "smsText" : "Die Fahrtreppe (Verteilerebene (abwärts) zum Bahnsteig -2 Ebene) an der Haltestelle Essen Berliner Platz ist ausser Betrieb.",
+ "htmlText" : "",
+ "additionalText" : "Die beschriebenen Änderungen sind in der elektronischen Fahrplanauskunft (EFA) <b>nicht</b> berücksichtigt.",
+ "subtitle" : "Haltestelle Essen Berliner Platz: Die Fahrtreppe ist nicht verfügbar. (Verteilerebene (abwaerts) zum Bahnsteig -2 Ebene)",
+ "wmlText" : "Die Fahrtreppe (Verteilerebene (abwärts) zum Bahnsteig -2 Ebene) an der Haltestelle Essen Berliner Platz ist ausser Betrieb."
+ },
+ "infoLinkURL" : "http://217.70.161.100:80/cm/XSLT_CM_SHOWADDINFO_REQUEST?infoID=20240514915357&seqID=132",
+ "infoLinkText" : "Haltestelle Essen Berliner Platz: Die Fahrtreppe ist nicht verfügbar. (Verteilerebene (abwaerts) zum Bahnsteig -2 Ebene)"
+ }
+ ],
+ "tariffArea" : "",
+ "ref" : {
+ "id" : "20009153",
+ "place" : "Essen",
+ "gid" : "de:05113:9153",
+ "coords" : "779595.00000,5297077.00000",
+ "placeID" : "18",
+ "omc" : "5113000"
+ },
+ "tariffLayer1" : "",
+ "type" : "stop",
+ "name" : "Essen, Berliner Platz",
+ "tariffLayer2" : "",
+ "tariffAreaName" : "",
+ "usage" : "dm"
+ }
+ },
+ "input" : {
+ "input" : "Berliner Platz"
+ }
+ },
+ "servingLines" : {
+ "lines" : [
+ {
+ "mode" : {
+ "diva" : {
+ "isSTT" : "1",
+ "isROP" : "1",
+ "vF" : "20240601",
+ "dir" : "H",
+ "opPublicCode" : "EV-U",
+ "project" : "j24",
+ "branch" : "10",
+ "stateless" : "eva:10U11: :H:j24",
+ "operator" : "EVAG U-Bahn",
+ "network" : "eva",
+ "lineDisplay" : "line",
+ "globalId" : "de:vrr:eva-10-U11:",
+ "supplement" : " ",
+ "attrs" : [],
+ "opCode" : "10",
+ "line" : "10U11",
+ "vTo" : "20250228",
+ "tripCode" : "0"
+ },
+ "product" : "U-Bahn",
+ "type" : "2",
+ "destID" : "20009270",
+ "name" : "U-Bahn U11",
+ "code" : "1",
+ "number" : "U11",
+ "productId" : "0",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "destination" : "Essen Messe W.-Süd/Gruga",
+ "desc" : "GE-Buerer Str. - E-Karnap - Altenessen - Essen Hbf - Rüttenscheid - Messe/Gruga"
+ },
+ "index" : "2:0"
+ },
+ {
+ "mode" : {
+ "productId" : "0",
+ "number" : "U11",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "destination" : "Gelsenkirchen Buerer Str.",
+ "desc" : "Messe/Gruga - Rüttenscheid - Essen Hbf - Altenessen - E-Karnap - GE-Buerer Str.",
+ "diva" : {
+ "vTo" : "20250228",
+ "tripCode" : "0",
+ "opCode" : "10",
+ "attrs" : [],
+ "line" : "10U11",
+ "globalId" : "de:vrr:eva-10-U11:",
+ "lineDisplay" : "line",
+ "supplement" : " ",
+ "branch" : "10",
+ "project" : "j24",
+ "operator" : "EVAG U-Bahn",
+ "network" : "eva",
+ "stateless" : "eva:10U11: :R:j24",
+ "opPublicCode" : "EV-U",
+ "dir" : "R",
+ "vF" : "20240601",
+ "isROP" : "1",
+ "isSTT" : "1"
+ },
+ "product" : "U-Bahn",
+ "type" : "2",
+ "destID" : "20005579",
+ "name" : "U-Bahn U11",
+ "code" : "1"
+ },
+ "index" : "2:1"
+ },
+ {
+ "mode" : {
+ "product" : "U-Bahn",
+ "diva" : {
+ "vF" : "20240601",
+ "dir" : "H",
+ "opPublicCode" : "EV-U",
+ "isSTT" : "1",
+ "isROP" : "1",
+ "opCode" : "10",
+ "attrs" : [],
+ "line" : "10U17",
+ "vTo" : "20250228",
+ "tripCode" : "0",
+ "branch" : "10",
+ "project" : "j24",
+ "network" : "eva",
+ "operator" : "EVAG U-Bahn",
+ "stateless" : "eva:10U17: :H:j24",
+ "globalId" : "de:vrr:eva-10-U17:",
+ "lineDisplay" : "line",
+ "supplement" : " "
+ },
+ "name" : "U-Bahn U17",
+ "destID" : "20009447",
+ "code" : "1",
+ "type" : "2",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "number" : "U17",
+ "productId" : "0",
+ "desc" : "Altenessen - Essen Hbf - Holsterhausen - Margarethenhöhe",
+ "destination" : "Essen Margarethenhöhe"
+ },
+ "index" : "2:2"
+ },
+ {
+ "mode" : {
+ "product" : "U-Bahn",
+ "diva" : {
+ "dir" : "R",
+ "opPublicCode" : "EV-U",
+ "vF" : "20240601",
+ "isROP" : "1",
+ "isSTT" : "1",
+ "vTo" : "20250228",
+ "tripCode" : "0",
+ "opCode" : "10",
+ "attrs" : [],
+ "line" : "10U17",
+ "globalId" : "de:vrr:eva-10-U17:",
+ "lineDisplay" : "line",
+ "supplement" : " ",
+ "branch" : "10",
+ "project" : "j24",
+ "operator" : "EVAG U-Bahn",
+ "network" : "eva",
+ "stateless" : "eva:10U17: :R:j24"
+ },
+ "code" : "1",
+ "destID" : "20009370",
+ "name" : "U-Bahn U17",
+ "type" : "2",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "number" : "U17",
+ "productId" : "0",
+ "desc" : "Margarethenhöhe - Holsterhausen - Essen Hbf - Altenessen",
+ "destination" : "Essen Karlsplatz"
+ },
+ "index" : "2:3"
+ },
+ {
+ "index" : "2:4",
+ "mode" : {
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "productId" : "0",
+ "number" : "U18",
+ "desc" : "E-Berliner Platz - Essen Hbf - MH-Rhein-Ruhr-Zentrum - Mülheim Hbf",
+ "destination" : "Mülheim Hauptbahnhof",
+ "product" : "U-Bahn",
+ "diva" : {
+ "isSTT" : "1",
+ "isROP" : "1",
+ "vF" : "20240601",
+ "dir" : "H",
+ "opPublicCode" : "EV-U",
+ "project" : "j24",
+ "branch" : "10",
+ "stateless" : "eva:10U18: :H:j24",
+ "network" : "eva",
+ "operator" : "EVAG U-Bahn",
+ "lineDisplay" : "line",
+ "globalId" : "de:vrr:eva-10-U18:",
+ "supplement" : " ",
+ "attrs" : [],
+ "opCode" : "10",
+ "line" : "10U18",
+ "tripCode" : "0",
+ "vTo" : "20250228"
+ },
+ "name" : "U-Bahn U18",
+ "destID" : "20015225",
+ "code" : "1",
+ "type" : "2"
+ }
+ },
+ {
+ "index" : "2:5",
+ "mode" : {
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "productId" : "0",
+ "number" : "U18",
+ "desc" : "Berliner Platz - Essen Hbf - MH-Rhein-Ruhr-Zentrum - Mülheim Hbf",
+ "destination" : "Mülheim Hauptbahnhof",
+ "product" : "U-Bahn",
+ "diva" : {
+ "branch" : "13",
+ "project" : "j24",
+ "operator" : "Ruhrbahn Mülheim",
+ "network" : "btm",
+ "stateless" : "btm:13U18: :H:j24",
+ "globalId" : "de:vrr:btm-13-U18:",
+ "lineDisplay" : "line",
+ "supplement" : " ",
+ "opCode" : "13",
+ "attrs" : [],
+ "line" : "13U18",
+ "vTo" : "20250228",
+ "tripCode" : "0",
+ "vF" : "20240601",
+ "dir" : "H"
+ },
+ "destID" : "20015225",
+ "name" : "U-Bahn U18",
+ "code" : "1",
+ "type" : "2"
+ }
+ },
+ {
+ "index" : "4:0",
+ "mode" : {
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "number" : "101",
+ "productId" : "1",
+ "desc" : "Borbeck - Helenenstr. - Essen Hbf Rüttenscheid - Helenenstr.",
+ "destination" : "Essen Helenenstr.",
+ "product" : "Straßenbahn",
+ "diva" : {
+ "vF" : "20240601",
+ "dir" : "H",
+ "opPublicCode" : "EV-T",
+ "isSTT" : "1",
+ "isROP" : "1",
+ "opCode" : "11",
+ "attrs" : [],
+ "line" : "11101",
+ "vTo" : "20250228",
+ "tripCode" : "0",
+ "branch" : "11",
+ "project" : "j24",
+ "operator" : "EVAG Strab",
+ "network" : "eva",
+ "stateless" : "eva:11101: :H:j24",
+ "globalId" : "de:vrr:eva-11-101:",
+ "lineDisplay" : "line",
+ "supplement" : " "
+ },
+ "name" : "Straßenbahn 101",
+ "destID" : "20009306",
+ "code" : "4",
+ "type" : "4"
+ }
+ },
+ {
+ "index" : "4:1",
+ "mode" : {
+ "product" : "Straßenbahn",
+ "diva" : {
+ "network" : "eva",
+ "operator" : "EVAG Strab",
+ "stateless" : "eva:11103: :H:j24",
+ "branch" : "11",
+ "project" : "j24",
+ "supplement" : " ",
+ "globalId" : "de:vrr:eva-11-103:",
+ "lineDisplay" : "line",
+ "line" : "11103",
+ "opCode" : "11",
+ "attrs" : [],
+ "tripCode" : "0",
+ "vTo" : "20250228",
+ "vF" : "20240601",
+ "dir" : "H",
+ "opPublicCode" : "EV-T"
+ },
+ "code" : "4",
+ "destID" : "20009582",
+ "name" : "Straßenbahn 103",
+ "type" : "4",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "productId" : "1",
+ "number" : "103",
+ "desc" : "Dellwig - Borbeck - Altendorf - Rathaus Essen - Essen Hbf - Steele",
+ "destination" : "Essen Steele S"
+ }
+ },
+ {
+ "mode" : {
+ "diva" : {
+ "vTo" : "20250228",
+ "tripCode" : "0",
+ "attrs" : [],
+ "opCode" : "11",
+ "line" : "11103",
+ "lineDisplay" : "line",
+ "globalId" : "de:vrr:eva-11-103:",
+ "supplement" : " ",
+ "project" : "j24",
+ "branch" : "11",
+ "stateless" : "eva:11103: :R:j24",
+ "operator" : "EVAG Strab",
+ "network" : "eva",
+ "opPublicCode" : "EV-T",
+ "dir" : "R",
+ "vF" : "20240601"
+ },
+ "product" : "Straßenbahn",
+ "type" : "4",
+ "destID" : "20009641",
+ "code" : "4",
+ "name" : "Straßenbahn 103",
+ "number" : "103",
+ "productId" : "1",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "destination" : "Essen Wertstr.",
+ "desc" : "Steele - Essen Hbf - Rathaus Essen - Altendorf - Borbeck - Dellwig"
+ },
+ "index" : "4:2"
+ },
+ {
+ "mode" : {
+ "product" : "Straßenbahn",
+ "diva" : {
+ "supplement" : " ",
+ "globalId" : "de:vrr:eva-11-105:",
+ "lineDisplay" : "line",
+ "operator" : "EVAG Strab",
+ "network" : "eva",
+ "stateless" : "eva:11105: :H:j24",
+ "branch" : "11",
+ "project" : "j24",
+ "vTo" : "20250228",
+ "tripCode" : "0",
+ "line" : "11105",
+ "opCode" : "11",
+ "attrs" : [],
+ "isROP" : "1",
+ "isSTT" : "1",
+ "dir" : "H",
+ "opPublicCode" : "EV-T",
+ "vF" : "20240601"
+ },
+ "name" : "Straßenbahn 105",
+ "destID" : "20009665",
+ "code" : "4",
+ "type" : "4",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "productId" : "1",
+ "number" : "105",
+ "desc" : "Frintrop - Altendorf - Essen Hbf - Bergerhausen - Rellinghausen",
+ "destination" : "Essen Zeche Ludwig"
+ },
+ "index" : "4:3"
+ },
+ {
+ "mode" : {
+ "product" : "Straßenbahn",
+ "diva" : {
+ "vTo" : "20250228",
+ "tripCode" : "0",
+ "opCode" : "11",
+ "attrs" : [],
+ "line" : "11105",
+ "globalId" : "de:vrr:eva-11-105:",
+ "lineDisplay" : "line",
+ "supplement" : " ",
+ "branch" : "11",
+ "project" : "j24",
+ "operator" : "EVAG Strab",
+ "network" : "eva",
+ "stateless" : "eva:11105: :R:j24",
+ "dir" : "R",
+ "opPublicCode" : "EV-T",
+ "vF" : "20240601",
+ "isROP" : "1",
+ "isSTT" : "1"
+ },
+ "destID" : "20009614",
+ "name" : "Straßenbahn 105",
+ "code" : "4",
+ "type" : "4",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "number" : "105",
+ "productId" : "1",
+ "desc" : "Rellinghausen - Bergerhausen - Essen Hbf - Altendorf - Frintrop",
+ "destination" : "Essen Unterstr."
+ },
+ "index" : "4:4"
+ },
+ {
+ "mode" : {
+ "desc" : "Helenenstr. - Rüttenscheid - Essen Hbf - Helenenstr. - Borbeck",
+ "destination" : "Essen Germaniaplatz",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "number" : "106",
+ "productId" : "1",
+ "destID" : "20009254",
+ "name" : "Straßenbahn 106",
+ "code" : "4",
+ "type" : "4",
+ "product" : "Straßenbahn",
+ "diva" : {
+ "isSTT" : "1",
+ "isROP" : "1",
+ "vF" : "20240601",
+ "dir" : "H",
+ "opPublicCode" : "EV-T",
+ "project" : "j24",
+ "branch" : "11",
+ "stateless" : "eva:11106: :H:j24",
+ "operator" : "EVAG Strab",
+ "network" : "eva",
+ "lineDisplay" : "line",
+ "globalId" : "de:vrr:eva-11-106:",
+ "supplement" : " ",
+ "attrs" : [],
+ "opCode" : "11",
+ "line" : "11106",
+ "tripCode" : "0",
+ "vTo" : "20250228"
+ }
+ },
+ "index" : "4:5"
+ },
+ {
+ "mode" : {
+ "product" : "Straßenbahn",
+ "diva" : {
+ "network" : "eva",
+ "operator" : "EVAG Strab",
+ "stateless" : "eva:11109: :H:j24",
+ "branch" : "11",
+ "project" : "j24",
+ "supplement" : " ",
+ "globalId" : "de:vrr:eva-11-109:",
+ "lineDisplay" : "line",
+ "line" : "11109",
+ "opCode" : "11",
+ "attrs" : [],
+ "vTo" : "20250228",
+ "tripCode" : "0",
+ "isSTT" : "1",
+ "isROP" : "1",
+ "vF" : "20240601",
+ "opPublicCode" : "EV-T",
+ "dir" : "H"
+ },
+ "destID" : "20009582",
+ "code" : "4",
+ "name" : "Straßenbahn 109",
+ "type" : "4",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "number" : "109",
+ "productId" : "1",
+ "desc" : "Frohnhausen - Holsterhausen - Rathaus Essen - Steele",
+ "destination" : "Essen Steele S"
+ },
+ "index" : "4:6"
+ },
+ {
+ "mode" : {
+ "desc" : "Steele - Rathaus Essen - Holsterhausen - Frohnhausen",
+ "destination" : "Frohnhausen Breilsort",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "number" : "109",
+ "productId" : "1",
+ "name" : "Straßenbahn 109",
+ "destID" : "20009243",
+ "code" : "4",
+ "type" : "4",
+ "product" : "Straßenbahn",
+ "diva" : {
+ "opCode" : "11",
+ "attrs" : [],
+ "line" : "11109",
+ "tripCode" : "0",
+ "vTo" : "20250228",
+ "branch" : "11",
+ "project" : "j24",
+ "operator" : "EVAG Strab",
+ "network" : "eva",
+ "stateless" : "eva:11109: :R:j24",
+ "globalId" : "de:vrr:eva-11-109:",
+ "lineDisplay" : "line",
+ "supplement" : " ",
+ "vF" : "20240601",
+ "opPublicCode" : "EV-T",
+ "dir" : "R",
+ "isSTT" : "1",
+ "isROP" : "1"
+ }
+ },
+ "index" : "4:7"
+ },
+ {
+ "index" : "5:0",
+ "mode" : {
+ "diva" : {
+ "isROP" : "1",
+ "isSTT" : "1",
+ "dir" : "H",
+ "opPublicCode" : "EV-B",
+ "vF" : "20240601",
+ "globalId" : "de:vrr:eva-12-145:",
+ "lineDisplay" : "line",
+ "supplement" : " ",
+ "branch" : "12",
+ "project" : "j24",
+ "network" : "eva",
+ "operator" : "EVAG Bus",
+ "stateless" : "eva:12145: :H:j24",
+ "vTo" : "20250228",
+ "tripCode" : "0",
+ "opCode" : "12",
+ "attrs" : [],
+ "line" : "12145"
+ },
+ "product" : "Niederflurbus",
+ "type" : "5",
+ "name" : "Niederflurbus 145",
+ "destID" : "20009302",
+ "code" : "5",
+ "productId" : "13",
+ "number" : "145",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "destination" : "Essen Heisingen Baldeneysee",
+ "desc" : "Haarzopf - Essen Hbf - Stadtwald - Heisingen"
+ }
+ },
+ {
+ "mode" : {
+ "code" : "5",
+ "destID" : "20009222",
+ "name" : "Niederflurbus 145",
+ "type" : "5",
+ "product" : "Niederflurbus",
+ "diva" : {
+ "isROP" : "1",
+ "isSTT" : "1",
+ "opPublicCode" : "EV-B",
+ "dir" : "R",
+ "vF" : "20240601",
+ "lineDisplay" : "line",
+ "globalId" : "de:vrr:eva-12-145:",
+ "supplement" : " ",
+ "project" : "j24",
+ "branch" : "12",
+ "stateless" : "eva:12145: :R:j24",
+ "operator" : "EVAG Bus",
+ "network" : "eva",
+ "vTo" : "20250228",
+ "tripCode" : "0",
+ "attrs" : [],
+ "opCode" : "12",
+ "line" : "12145"
+ },
+ "desc" : "Heisingen - Stadtwald - Essen Hbf - Haarzopf",
+ "destination" : "Essen Erbach",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "number" : "145",
+ "productId" : "13"
+ },
+ "index" : "5:1"
+ },
+ {
+ "mode" : {
+ "productId" : "13",
+ "number" : "166",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "destination" : "E-Burgaltendorf Burgruine",
+ "desc" : "Dellwig - Essen Hbf - Steele - E-Burgaltendorf - HAT-Niederwenigern",
+ "diva" : {
+ "globalId" : "de:vrr:eva-12-166:",
+ "lineDisplay" : "line",
+ "supplement" : " ",
+ "branch" : "12",
+ "project" : "j24",
+ "network" : "eva",
+ "operator" : "EVAG Bus",
+ "stateless" : "eva:12166: :H:j24",
+ "tripCode" : "0",
+ "vTo" : "20250228",
+ "opCode" : "12",
+ "attrs" : [],
+ "line" : "12166",
+ "isROP" : "1",
+ "isSTT" : "1",
+ "dir" : "H",
+ "opPublicCode" : "EV-B",
+ "vF" : "20240601"
+ },
+ "product" : "Niederflurbus",
+ "type" : "5",
+ "destID" : "20009182",
+ "name" : "Niederflurbus 166",
+ "code" : "5"
+ },
+ "index" : "5:2"
+ },
+ {
+ "mode" : {
+ "number" : "166",
+ "productId" : "13",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "destination" : "Essen Dellwig Bahnhof",
+ "desc" : "HAT-Niederwenigern - E-Burgaltendorf - Steele - Essen Hbf - Dellwig",
+ "diva" : {
+ "dir" : "R",
+ "opPublicCode" : "EV-B",
+ "vF" : "20240601",
+ "isROP" : "1",
+ "isSTT" : "1",
+ "vTo" : "20250228",
+ "tripCode" : "0",
+ "attrs" : [],
+ "opCode" : "12",
+ "line" : "12166",
+ "lineDisplay" : "line",
+ "globalId" : "de:vrr:eva-12-166:",
+ "supplement" : " ",
+ "project" : "j24",
+ "branch" : "12",
+ "stateless" : "eva:12166: :R:j24",
+ "operator" : "EVAG Bus",
+ "network" : "eva"
+ },
+ "product" : "Niederflurbus",
+ "type" : "5",
+ "destID" : "20009197",
+ "code" : "5",
+ "name" : "Niederflurbus 166"
+ },
+ "index" : "5:3"
+ },
+ {
+ "mode" : {
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "productId" : "13",
+ "number" : "NE10",
+ "desc" : "Essen Hbf - Frohnhausen - Haarzopf",
+ "destination" : "Essen Erbach",
+ "product" : "Niederflurbus",
+ "diva" : {
+ "line" : "12M10",
+ "opCode" : "12",
+ "attrs" : [],
+ "vTo" : "20250228",
+ "tripCode" : "0",
+ "network" : "eva",
+ "operator" : "EVAG Bus",
+ "stateless" : "eva:12M10: :H:j24",
+ "branch" : "12",
+ "project" : "j24",
+ "supplement" : " ",
+ "globalId" : "de:vrr:eva-12-M10:",
+ "lineDisplay" : "line",
+ "vF" : "20240601",
+ "dir" : "H",
+ "opPublicCode" : "EV-B",
+ "isSTT" : "1",
+ "isROP" : "1"
+ },
+ "name" : "Niederflurbus NE10",
+ "destID" : "20009222",
+ "code" : "5",
+ "type" : "5"
+ },
+ "index" : "5:4"
+ },
+ {
+ "index" : "5:5",
+ "mode" : {
+ "type" : "5",
+ "code" : "5",
+ "destID" : "20009289",
+ "name" : "Niederflurbus NE10",
+ "diva" : {
+ "lineDisplay" : "line",
+ "globalId" : "de:vrr:eva-12-M10:",
+ "supplement" : " ",
+ "project" : "j24",
+ "branch" : "12",
+ "stateless" : "eva:12M10: :R:j24",
+ "operator" : "EVAG Bus",
+ "network" : "eva",
+ "vTo" : "20250228",
+ "tripCode" : "0",
+ "attrs" : [],
+ "opCode" : "12",
+ "line" : "12M10",
+ "isROP" : "1",
+ "isSTT" : "1",
+ "opPublicCode" : "EV-B",
+ "dir" : "R",
+ "vF" : "20240601"
+ },
+ "product" : "Niederflurbus",
+ "destination" : "Essen Hauptbahnhof",
+ "desc" : "Haarzopf - Frohnhausen - Essen Hbf",
+ "number" : "NE10",
+ "productId" : "13",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)"
+ }
+ },
+ {
+ "index" : "5:6",
+ "mode" : {
+ "code" : "5",
+ "destID" : "20014022",
+ "name" : "Niederflurbus NE11",
+ "type" : "5",
+ "product" : "Niederflurbus",
+ "diva" : {
+ "vTo" : "20250228",
+ "tripCode" : "0",
+ "line" : "12M11",
+ "attrs" : [],
+ "opCode" : "12",
+ "supplement" : " ",
+ "lineDisplay" : "line",
+ "globalId" : "de:vrr:eva-12-M11:",
+ "stateless" : "eva:12M11: :H:j24",
+ "operator" : "EVAG Bus",
+ "network" : "eva",
+ "project" : "j24",
+ "branch" : "12",
+ "dir" : "H",
+ "opPublicCode" : "EV-B",
+ "vF" : "20240601",
+ "isROP" : "1",
+ "isSTT" : "1"
+ },
+ "desc" : "Essen Hbf - Altendorf - Essen Frintrop - Oberhausen",
+ "destination" : "Oberhausen Hbf",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "number" : "NE11",
+ "productId" : "13"
+ }
+ },
+ {
+ "index" : "5:7",
+ "mode" : {
+ "type" : "5",
+ "destID" : "20009289",
+ "code" : "5",
+ "name" : "Niederflurbus NE11",
+ "diva" : {
+ "vF" : "20240601",
+ "dir" : "R",
+ "opPublicCode" : "EV-B",
+ "isSTT" : "1",
+ "isROP" : "1",
+ "line" : "12M11",
+ "attrs" : [],
+ "opCode" : "12",
+ "tripCode" : "0",
+ "vTo" : "20250228",
+ "stateless" : "eva:12M11: :R:j24",
+ "network" : "eva",
+ "operator" : "EVAG Bus",
+ "project" : "j24",
+ "branch" : "12",
+ "supplement" : " ",
+ "lineDisplay" : "line",
+ "globalId" : "de:vrr:eva-12-M11:"
+ },
+ "product" : "Niederflurbus",
+ "destination" : "Essen Hauptbahnhof",
+ "desc" : "Oberhausen - Essen Frintrop - Altendorf - Essen Hbf",
+ "productId" : "13",
+ "number" : "NE11",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)"
+ }
+ },
+ {
+ "index" : "5:8",
+ "mode" : {
+ "productId" : "13",
+ "number" : "NE12",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "destination" : "Essen Borbeck Bf",
+ "desc" : "Essen Hbf - Altendorf - Bergeborbeck - Dellwig - Borbeck",
+ "diva" : {
+ "isROP" : "1",
+ "isSTT" : "1",
+ "dir" : "H",
+ "opPublicCode" : "EV-B",
+ "vF" : "20240601",
+ "lineDisplay" : "line",
+ "globalId" : "de:vrr:eva-12-M12:",
+ "supplement" : " ",
+ "project" : "j24",
+ "branch" : "12",
+ "stateless" : "eva:12M12: :H:j24",
+ "network" : "eva",
+ "operator" : "EVAG Bus",
+ "tripCode" : "0",
+ "vTo" : "20250228",
+ "attrs" : [],
+ "opCode" : "12",
+ "line" : "12M12"
+ },
+ "product" : "Niederflurbus",
+ "type" : "5",
+ "name" : "Niederflurbus NE12",
+ "destID" : "20009158",
+ "code" : "5"
+ }
+ },
+ {
+ "index" : "5:9",
+ "mode" : {
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "number" : "NE12",
+ "productId" : "13",
+ "desc" : "Borbeck - Dellwig - Bergeborbeck - Altendorf - Essen Hbf",
+ "destination" : "Essen Hauptbahnhof",
+ "product" : "Niederflurbus",
+ "diva" : {
+ "operator" : "EVAG Bus",
+ "network" : "eva",
+ "stateless" : "eva:12M12: :R:j24",
+ "branch" : "12",
+ "project" : "j24",
+ "supplement" : " ",
+ "globalId" : "de:vrr:eva-12-M12:",
+ "lineDisplay" : "line",
+ "line" : "12M12",
+ "opCode" : "12",
+ "attrs" : [],
+ "tripCode" : "0",
+ "vTo" : "20250228",
+ "isSTT" : "1",
+ "isROP" : "1",
+ "vF" : "20240601",
+ "opPublicCode" : "EV-B",
+ "dir" : "R"
+ },
+ "destID" : "20009289",
+ "code" : "5",
+ "name" : "Niederflurbus NE12",
+ "type" : "5"
+ }
+ },
+ {
+ "index" : "5:10",
+ "mode" : {
+ "destination" : "BOT ZOB Berliner Platz",
+ "desc" : "Essen Hbf - Bergeborbeck - Essen Dellwig - Bottrop",
+ "productId" : "13",
+ "number" : "NE16",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "type" : "5",
+ "destID" : "20003267",
+ "name" : "Niederflurbus NE16",
+ "code" : "5",
+ "diva" : {
+ "lineDisplay" : "line",
+ "globalId" : "de:vrr:eva-12-M16:",
+ "supplement" : " ",
+ "project" : "j24",
+ "branch" : "12",
+ "stateless" : "eva:12M16: :H:j24",
+ "network" : "eva",
+ "operator" : "EVAG Bus",
+ "tripCode" : "0",
+ "vTo" : "20250228",
+ "attrs" : [],
+ "opCode" : "12",
+ "line" : "12M16",
+ "isROP" : "1",
+ "isSTT" : "1",
+ "dir" : "H",
+ "opPublicCode" : "EV-B",
+ "vF" : "20240601"
+ },
+ "product" : "Niederflurbus"
+ }
+ },
+ {
+ "index" : "5:11",
+ "mode" : {
+ "number" : "NE16",
+ "productId" : "13",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "destination" : "Essen Hauptbahnhof",
+ "desc" : "Bottrop - Essen Dellwig - Bergeborbeck - Essen Hbf",
+ "diva" : {
+ "dir" : "R",
+ "opPublicCode" : "EV-B",
+ "vF" : "20240601",
+ "isROP" : "1",
+ "isSTT" : "1",
+ "vTo" : "20250228",
+ "tripCode" : "0",
+ "opCode" : "12",
+ "attrs" : [],
+ "line" : "12M16",
+ "globalId" : "de:vrr:eva-12-M16:",
+ "lineDisplay" : "line",
+ "supplement" : " ",
+ "branch" : "12",
+ "project" : "j24",
+ "network" : "eva",
+ "operator" : "EVAG Bus",
+ "stateless" : "eva:12M16: :R:j24"
+ },
+ "product" : "Niederflurbus",
+ "type" : "5",
+ "code" : "5",
+ "destID" : "20009289",
+ "name" : "Niederflurbus NE16"
+ }
+ },
+ {
+ "mode" : {
+ "destination" : "BOT St.-Anto.-Hosp./Gartenstr.",
+ "desc" : "Essen Hbf - Universität - BOT-Hbf - ZOB Berliner Platz - Grafenwald - Kirchhellen St.-Antonius-Hospital/Gartenstr.",
+ "number" : "SB16",
+ "productId" : "13",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "type" : "5",
+ "destID" : "20003174",
+ "code" : "5",
+ "name" : "Niederflurbus SB16",
+ "diva" : {
+ "opPublicCode" : "VEST",
+ "dir" : "H",
+ "vF" : "20240601",
+ "lineDisplay" : "line",
+ "globalId" : "de:vrr:SB16:VES-40-16",
+ "supplement" : " ",
+ "project" : "j24",
+ "branch" : "40",
+ "stateless" : "ves:40016: :H:j24",
+ "network" : "ves",
+ "operator" : "Vestische",
+ "tripCode" : "0",
+ "vTo" : "20250228",
+ "attrs" : [],
+ "opCode" : "40",
+ "line" : "40016"
+ },
+ "product" : "Niederflurbus"
+ },
+ "index" : "5:12"
+ },
+ {
+ "index" : "5:13",
+ "mode" : {
+ "product" : "Niederflurbus",
+ "diva" : {
+ "vF" : "20240601",
+ "opPublicCode" : "VEST",
+ "dir" : "R",
+ "line" : "40016",
+ "opCode" : "40",
+ "attrs" : [],
+ "vTo" : "20250228",
+ "tripCode" : "0",
+ "network" : "ves",
+ "operator" : "Vestische",
+ "stateless" : "ves:40016: :R:j24",
+ "branch" : "40",
+ "project" : "j24",
+ "supplement" : " ",
+ "globalId" : "de:vrr:SB16:VES-40-16",
+ "lineDisplay" : "line"
+ },
+ "destID" : "20009289",
+ "name" : "Niederflurbus SB16",
+ "code" : "5",
+ "type" : "5",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "number" : "SB16",
+ "productId" : "13",
+ "desc" : "BOT-Kirchhellen St..-Antonius-Hospital/ Gartenstr. - Grafenwald - ZOB Berliner Platz - BOT-Hbf - Essen Universität - Hbf",
+ "destination" : "Essen Hauptbahnhof"
+ }
+ },
+ {
+ "index" : "7:0",
+ "mode" : {
+ "type" : "7",
+ "name" : "SB SB16",
+ "destID" : "20003174",
+ "code" : "5",
+ "diva" : {
+ "tripCode" : "0",
+ "vTo" : "20250228",
+ "attrs" : [],
+ "opCode" : "88",
+ "line" : "88016",
+ "lineDisplay" : "line",
+ "globalId" : "de:vrr:bvr-88-16:K",
+ "supplement" : "K",
+ "project" : "j24",
+ "branch" : "88",
+ "stateless" : "bvr:88016:K:H:j24",
+ "network" : "bvr",
+ "operator" : "DB Bahn Rheinlandbus",
+ "dir" : "H",
+ "opPublicCode" : "BVR",
+ "vF" : "20240601"
+ },
+ "product" : "SB",
+ "destination" : "BOT St.-Anto.-Hosp./Gartenstr.",
+ "desc" : "Essen Hbf - Dorsten ZOB Dorsten",
+ "number" : "SB16",
+ "productId" : "3",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)"
+ }
+ },
+ {
+ "index" : "7:1",
+ "mode" : {
+ "product" : "SB",
+ "diva" : {
+ "vF" : "20240601",
+ "dir" : "R",
+ "opPublicCode" : "BVR",
+ "branch" : "88",
+ "project" : "j24",
+ "network" : "bvr",
+ "operator" : "DB Bahn Rheinlandbus",
+ "stateless" : "bvr:88016:K:R:j24",
+ "globalId" : "de:vrr:bvr-88-16:K",
+ "lineDisplay" : "line",
+ "supplement" : "K",
+ "opCode" : "88",
+ "attrs" : [],
+ "line" : "88016",
+ "tripCode" : "0",
+ "vTo" : "20250228"
+ },
+ "name" : "SB SB16",
+ "destID" : "20009289",
+ "code" : "5",
+ "type" : "7",
+ "timetablePeriod" : "Jahresfahrplan 2024 (08.01.2024 - 06.01.2025)",
+ "number" : "SB16",
+ "productId" : "3",
+ "desc" : "Dorsten ZOB Dorsten - Essen Hbf",
+ "destination" : "Essen Hauptbahnhof"
+ }
+ }
+ ]
+ },
+ "option" : {
+ "ptOption" : {
+ "maxTime" : "360",
+ "routeType" : "LEASTTIME",
+ "activeSec" : "-1",
+ "maxChanges" : "9",
+ "overgroundTransfer" : "0",
+ "lowPlatformVhcl" : "0",
+ "noEscalators" : "0",
+ "activeImp" : "-1",
+ "plane" : "0",
+ "wheelchair" : "0",
+ "noElevators" : "0",
+ "bike" : "0",
+ "noInsecurePlaces" : "0",
+ "useProxFootSearchDestination" : "0",
+ "noLonelyTransfer" : "0",
+ "noSolidStairs" : "0",
+ "privateTransport" : "0",
+ "illumTransfer" : "0",
+ "SOSAvail" : "0",
+ "useProxFootSearch" : "0",
+ "needElevatedPlt" : "0",
+ "maxWait" : "120",
+ "useProxFootSearchOrigin" : "0",
+ "changeSpeed" : "normal",
+ "lineRestriction" : "403",
+ "active" : "-1",
+ "activeCom" : "-1",
+ "excludedMeans" : [
+ {
+ "value" : "0",
+ "selected" : "0"
+ },
+ {
+ "value" : "1",
+ "selected" : "0"
+ },
+ {
+ "value" : "2",
+ "selected" : "0"
+ },
+ {
+ "selected" : "0",
+ "value" : "3"
+ },
+ {
+ "value" : "4",
+ "selected" : "0"
+ },
+ {
+ "value" : "5",
+ "selected" : "0"
+ },
+ {
+ "selected" : "0",
+ "value" : "6"
+ },
+ {
+ "value" : "7",
+ "selected" : "0"
+ },
+ {
+ "value" : "8",
+ "selected" : "0"
+ },
+ {
+ "selected" : "0",
+ "value" : "9"
+ },
+ {
+ "selected" : "0",
+ "value" : "10"
+ },
+ {
+ "selected" : "0",
+ "value" : "11"
+ },
+ {
+ "selected" : "0",
+ "value" : "12"
+ },
+ {
+ "selected" : "0",
+ "value" : "13"
+ },
+ {
+ "selected" : "0",
+ "value" : "14"
+ },
+ {
+ "selected" : "0",
+ "value" : "15"
+ },
+ {
+ "selected" : "0",
+ "value" : "16"
+ },
+ {
+ "value" : "17",
+ "selected" : "0"
+ },
+ {
+ "selected" : "0",
+ "value" : "18"
+ },
+ {
+ "value" : "19",
+ "selected" : "0"
+ }
+ ],
+ "assistance" : "0",
+ "noCrowded" : "0"
+ }
+ }
+}
diff --git a/t/in/essen_hb.xml b/t/in/essen_hb.xml
deleted file mode 100644
index cb25c3d..0000000
--- a/t/in/essen_hb.xml
+++ /dev/null
@@ -1,1034 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<itdRequest version="9.16.27.53" language="de" lengthUnit="METER" sessionID="efa1.vrr.de_27300218" client="libwww-perl/6.03" clientIP="93.213.85.226" serverID="efa1.vrr.de_" virtDir="vrr" now="2011-11-16T09:38:50" nowWD="4">
- <itdLayoutParams>
- <itdLayoutParam name="mdvMap2_dm" value="" />
- <itdLayoutParam name="mapState_dm" value="" />
- <itdLayoutParam name="mdvMap_dm" value="3406199:401077:NAV3" />
- <itdLayoutParam name="view" value="" />
- <itdLayoutParam name="id_dm" value=":dm" />
- <itdLayoutParam name="transpCompany" value="vrr" />
- </itdLayoutParams>
- <itdDepartureMonitorRequest requestID="1">
- <itdOdv type="stop" usage="dm">
- <itdOdvPlace state="identified" method="itp">
- <odvPlaceElem omc="5113000" placeID="18" value="5113000:18" span="0" type="remote" mainPlace="1">Essen</odvPlaceElem>
- <odvPlaceInput>E</odvPlaceInput>
- </itdOdvPlace>
- <itdOdvName state="identified" method="itp">
- <odvNameElem x="3361949" y="456292" mapName="NAV3" stopID="20009289" value="20009289:1" isTransferStop="0" matchQuality="0">Hauptbahnhof</odvNameElem>
- <odvNameInput>Hbf</odvNameInput>
- </itdOdvName>
- </itdOdv>
- <itdDateTime ttpFrom="20110901" ttpTo="20120531">
- <itdDate weekday="4" year="2011" month="11" day="16" />
- <itdTime hour="9" minute="39" />
- </itdDateTime>
- <itdDateRange>
- <itdDate day="16" month="11" year="2011" weekday="4" />
- <itdDate day="17" month="11" year="2011" weekday="5" />
- <itdDate day="18" month="11" year="2011" weekday="6" />
- <itdDate day="19" month="11" year="2011" weekday="7" />
- <itdDate day="20" month="11" year="2011" weekday="1" />
- <itdDate day="21" month="11" year="2011" weekday="2" />
- <itdDate day="22" month="11" year="2011" weekday="3" />
- <itdDate day="23" month="11" year="2011" weekday="4" />
- <itdDate day="24" month="11" year="2011" weekday="5" />
- <itdDate day="25" month="11" year="2011" weekday="6" />
- <itdDate day="26" month="11" year="2011" weekday="7" />
- <itdDate day="27" month="11" year="2011" weekday="1" />
- <itdDate day="28" month="11" year="2011" weekday="2" />
- <itdDate day="29" month="11" year="2011" weekday="3" />
- <itdDate day="30" month="11" year="2011" weekday="4" />
- </itdDateRange>
- <itdTripOptions>
- <itdPtOptions>
- <excludedMeans>
- <meansElem value="0" selected="0">Zug</meansElem>
- <meansElem value="1" selected="0">S-Bahn</meansElem>
- <meansElem value="2" selected="0">U-Bahn</meansElem>
- <meansElem value="3" selected="0">Stadtbahn</meansElem>
- <meansElem value="4" selected="0">Straßen-/Trambahn</meansElem>
- <meansElem value="5" selected="0">Stadtbus</meansElem>
- <meansElem value="6" selected="0">Regionalbus</meansElem>
- <meansElem value="7" selected="0">Schnellbus</meansElem>
- <meansElem value="8" selected="0">Seil-/Zahnradbahn</meansElem>
- <meansElem value="9" selected="0">Schiff</meansElem>
- <meansElem value="10" selected="0">AST/Rufbus</meansElem>
- <meansElem value="11" selected="0">Sonstige</meansElem>
- </excludedMeans>
- </itdPtOptions>
- <itdItOptions>
- <itRouter logASCII="false" logSVG="false" />
- <itPedestrian computeMonomodalTrip="false" computationType="PT_AND_IT" itIncidentData="false" useElevation="false" speedFactor="100" costFactor="0" distanceFactor="50" traveltimeFactor="50" noTunnel="false" noBridge="false" noFerry="false" maxTime="20" maxLength="2147483647" ignoreRestrictions="false" />
- <itBicycle preferAsphaltTracks="false" preferGreenTracks="false" usePseudoRouting="false" useSignedRoute="false" cycleSpeed="20" prefHikePath="false" elevFac="50" bikeProf="UNKNOWN" computeMonomodalTrip="false" computationType="PT_AND_IT" itIncidentData="false" useElevation="false" speedFactor="100" costFactor="0" distanceFactor="50" traveltimeFactor="50" noTunnel="false" noBridge="false" noFerry="false" maxTime="15" maxLength="2147483647" ignoreRestrictions="false" />
- <mitCar computeMonomodalTrip="false" computationType="PT_AND_IT" itIncidentData="false" useElevation="false" speedFactor="100" costFactor="0" distanceFactor="10" traveltimeFactor="90" noTunnel="false" noBridge="false" noFerry="false" maxTime="90" maxLength="2147483647" ignoreRestrictions="false" mitProfileData="false" mitIncidentData="false" mitOnlineData="false" noHighway="false" noTollRoad="false" />
- <departureTransport>
- <individualTransport meansCode="100" value="8" speed="normal" selected="1" />
- <individualTransport meansCode="101" value="15" speed="normal" selected="0" />
- <individualTransport meansCode="102" value="15" speed="normal" selected="0" />
- <individualTransport meansCode="103" value="10" speed="normal" selected="0" />
- <individualTransport meansCode="104" value="10" speed="normal" selected="0" />
- <individualTransport meansCode="105" value="30" speed="normal" selected="0" />
- <individualTransport meansCode="106" value="15" speed="normal" selected="0" />
- <individualTransport meansCode="107" value="15" speed="normal" selected="0" />
- </departureTransport>
- </itdItOptions>
- </itdTripOptions>
- <itdServingLines trainInfo="show" selected="1">
- <itdServingLine selected="1" code="2" number="S1" symbol="S1" motType="1" realtime="0" direction="Dortmund Dorstfeld S" valid="Jahresfahrplan 2010/2011" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20000131" stateless="ddb:92E01: :H:j11" trainName="" index="1:0">
- <itdNoTrain name="S-Bahn" />
- <motDivaParams line="92E01" project="j11" direction="H" supplement=" " network="ddb" />
- <itdRouteDescText>Solingen Hbf - Düsseldorf Hbf - Dortmund Hbf</itdRouteDescText>
- <itdOperator>
- <code>00</code>
- <name>Daten DB AG</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="2" number="S1" symbol="S1" motType="1" realtime="0" direction="Solingen Hbf" valid="Jahresfahrplan 2010/2011" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20013800" stateless="ddb:92E01: :R:j11" trainName="" index="1:1">
- <itdNoTrain name="S-Bahn" />
- <motDivaParams line="92E01" project="j11" direction="R" supplement=" " network="ddb" />
- <itdRouteDescText>Dortmund Hbf - Düsseldorf Hbf - Solingen Hbf</itdRouteDescText>
- <itdOperator>
- <code>00</code>
- <name>Daten DB AG</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="2" number="S2" symbol="S2" motType="1" realtime="0" direction="Dortmund Hbf" valid="Jahresfahrplan 2010/2011" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20000131" stateless="ddb:92E02: :H:j11" trainName="" index="1:2">
- <itdNoTrain name="S-Bahn" />
- <motDivaParams line="92E02" project="j11" direction="H" supplement=" " network="ddb" />
- <itdRouteDescText>Duisburg Hbf / Essen Hbf - Gelsenkirchen Hbf / Recklinghausen Hbf - Dortmund Hbf</itdRouteDescText>
- <itdOperator>
- <code>00</code>
- <name>Daten DB AG</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="2" number="S3" symbol="S3" motType="1" realtime="0" direction="Hattingen Mitte" valid="Jahresfahrplan 2010/2011" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20008437" stateless="ddb:92E03: :H:j11" trainName="" index="1:3">
- <itdNoTrain name="S-Bahn" />
- <motDivaParams line="92E03" project="j11" direction="H" supplement=" " network="ddb" />
- <itdRouteDescText>Oberhausen Hbf - Hattingen (Ruhr) Mitte</itdRouteDescText>
- <itdOperator>
- <code>00</code>
- <name>Daten DB AG</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="2" number="S3" symbol="S3" motType="1" realtime="0" direction="Oberhausen Hbf." valid="Jahresfahrplan 2010/2011" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20014022" stateless="ddb:92E03: :R:j11" trainName="" index="1:4">
- <itdNoTrain name="S-Bahn" />
- <motDivaParams line="92E03" project="j11" direction="R" supplement=" " network="ddb" />
- <itdRouteDescText>Hattingen (Ruhr) Mitte - Oberhausen Hbf</itdRouteDescText>
- <itdOperator>
- <code>00</code>
- <name>Daten DB AG</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="2" number="S6" symbol="S6" motType="1" realtime="0" direction="Nippes, Nippes S-Bahn" valid="Jahresfahrplan 2010/2011" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="22000750" stateless="ddb:92E06: :H:j11" trainName="" index="1:5">
- <itdNoTrain name="S-Bahn" />
- <motDivaParams line="92E06" project="j11" direction="H" supplement=" " network="ddb" />
- <itdRouteDescText>Essen Hbf - Düsseldorf Hbf - Köln-Nippes</itdRouteDescText>
- <itdOperator>
- <code>00</code>
- <name>Daten DB AG</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="2" number="S9" symbol="S9" motType="1" realtime="0" direction="Bottrop Hbf" valid="Jahresfahrplan 2010/2011" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20003335" stateless="ddb:92E09: :H:j11" trainName="" index="1:6">
- <itdNoTrain name="S-Bahn" />
- <motDivaParams line="92E09" project="j11" direction="H" supplement=" " network="ddb" />
- <itdRouteDescText>Wuppertal Hbf - Essen Hbf - Haltern am See</itdRouteDescText>
- <itdOperator>
- <code>00</code>
- <name>Daten DB AG</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="2" number="S9" symbol="S9" motType="1" realtime="0" direction="Wuppertal Hbf" valid="Jahresfahrplan 2010/2011" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20011019" stateless="ddb:92E09: :R:j11" trainName="" index="1:7">
- <itdNoTrain name="S-Bahn" />
- <motDivaParams line="92E09" project="j11" direction="R" supplement=" " network="ddb" />
- <itdRouteDescText>Haltern am See - Essen Hbf - Wuppertal Hbf</itdRouteDescText>
- <itdOperator>
- <code>00</code>
- <name>Daten DB AG</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="1" number="11" symbol="11" motType="2" realtime="0" direction="Essen Messe W.-Süd/Gruga" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009270" stateless="vrr:10U11: :H:911" trainName="" index="2:0">
- <itdNoTrain name="U-Bahn" />
- <motDivaParams line="10U11" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>GE-Buerer Str. - E-Karnap - Altenessen - Essen Hbf - Rüttenscheid - Messe Gruga</itdRouteDescText>
- <itdOperator>
- <code>10</code>
- <name>EVAG U-Bahn</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="1" number="11" symbol="11" motType="2" realtime="0" direction="Essen Berliner Platz" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009153" stateless="vrr:10U11: :R:911" trainName="" index="2:1">
- <itdNoTrain name="U-Bahn" />
- <motDivaParams line="10U11" project="911" direction="R" supplement=" " network="vrr" />
- <itdRouteDescText>Messe Gruga - Rüttenscheid - Essen Hbf - Altenessen - E-Karnap - GE-Buerer Str.</itdRouteDescText>
- <itdOperator>
- <code>10</code>
- <name>EVAG U-Bahn</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="1" number="18" symbol="18" motType="2" realtime="0" direction="Mülheim Heißen Kirche" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20015079" stateless="vrr:10U18:2:H:911" trainName="" index="2:2">
- <itdNoTrain name="U-Bahn" />
- <motDivaParams line="10U18" project="911" direction="H" supplement="2" network="vrr" />
- <itdRouteDescText>Berliner Platz - Essen Hbf - MH-Rhein-Ruhr-Zentrum - Heißen Kirche</itdRouteDescText>
- <itdOperator>
- <code>10</code>
- <name>EVAG U-Bahn</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="1" number="18" symbol="18" motType="2" realtime="0" direction="Essen Berliner Platz" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009153" stateless="vrr:10U18:2:R:911" trainName="" index="2:3">
- <itdNoTrain name="U-Bahn" />
- <motDivaParams line="10U18" project="911" direction="R" supplement="2" network="vrr" />
- <itdRouteDescText>Heißen Kirche - MH-Rhein-Ruhr-Zentrum - Essen Hbf - Berliner Platz</itdRouteDescText>
- <itdOperator>
- <code>10</code>
- <name>EVAG U-Bahn</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="1" number="U17" symbol="U17" motType="2" realtime="0" direction="Essen Margarethenhöhe" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009447" stateless="vrr:10U17: :H:911" trainName="" index="2:4">
- <itdNoTrain name="U-Bahn" />
- <motDivaParams line="10U17" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Altenessen - Essen Hbf - Holsterhausen - Margarethenhöhe</itdRouteDescText>
- <itdOperator>
- <code>10</code>
- <name>EVAG U-Bahn</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="1" number="U17" symbol="U17" motType="2" realtime="0" direction="Essen Karlsplatz" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009370" stateless="vrr:10U17: :R:911" trainName="" index="2:5">
- <itdNoTrain name="U-Bahn" />
- <motDivaParams line="10U17" project="911" direction="R" supplement=" " network="vrr" />
- <itdRouteDescText>Margarethenhöhe - Holsterhausen - Essen Hbf - Altenessen</itdRouteDescText>
- <itdOperator>
- <code>10</code>
- <name>EVAG U-Bahn</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="4" number="101" symbol="101" motType="4" realtime="0" direction="Essen Bredeney" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009172" stateless="vrr:11101: :H:911" trainName="" index="4:0">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11101" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Borbeck - Bergeborbeck - Essen Hbf - Bredeney</itdRouteDescText>
- <itdOperator>
- <code>11</code>
- <name>EVAG Strab</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="4" number="101" symbol="101" motType="4" realtime="0" direction="Essen Germaniaplatz" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009254" stateless="vrr:11101: :R:911" trainName="" index="4:1">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11101" project="911" direction="R" supplement=" " network="vrr" />
- <itdOperator>
- <code>11</code>
- <name>EVAG Strab</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="4" number="103" symbol="103" motType="4" realtime="0" direction="Essen Wertstr." valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009641" stateless="vrr:11103: :R:911" trainName="" index="4:2">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11103" project="911" direction="R" supplement=" " network="vrr" />
- <itdRouteDescText>Steele - Essen Hbf - Rathaus Essen - Altendorf - Borbeck - Dellwig</itdRouteDescText>
- <itdOperator>
- <code>11</code>
- <name>EVAG Strab</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="4" number="105" symbol="105" motType="4" realtime="0" direction="Essen Finefraustr." valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009232" stateless="vrr:11105: :H:911" trainName="" index="4:3">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11105" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Frintrop - Altendorf - Essen Hbf - Bergerhausen - Rellinghausen</itdRouteDescText>
- <itdOperator>
- <code>11</code>
- <name>EVAG Strab</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="4" number="105" symbol="105" motType="4" realtime="0" direction="Essen Unterstr." valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009614" stateless="vrr:11105: :R:911" trainName="" index="4:4">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11105" project="911" direction="R" supplement=" " network="vrr" />
- <itdRouteDescText>Rellinghausen - Bergerhausen - Essen Hbf - Altendorf - Frintrop</itdRouteDescText>
- <itdOperator>
- <code>11</code>
- <name>EVAG Strab</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="4" number="106" symbol="106" motType="4" realtime="0" direction="Essen Helenenstr." valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009306" stateless="vrr:11106: :H:911" trainName="" index="4:5">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11106" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Altenessen - Essen Hbf - Rüttenscheid - Helenenstr. - Bergeborbeck</itdRouteDescText>
- <itdOperator>
- <code>11</code>
- <name>EVAG Strab</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="4" number="106" symbol="106" motType="4" realtime="0" direction="Essen Altenessen Bf Schleife" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009832" stateless="vrr:11106: :R:911" trainName="" index="4:6">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11106" project="911" direction="R" supplement=" " network="vrr" />
- <itdRouteDescText>Bergeborbeck - Helenenstr. - Rüttenscheid - Essen Hbf - Altenessen</itdRouteDescText>
- <itdOperator>
- <code>11</code>
- <name>EVAG Strab</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="4" number="107" symbol="107" motType="4" realtime="0" direction="Essen Bredeney" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009172" stateless="vrr:11107: :H:911" trainName="" index="4:7">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11107" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>GE-Hauptbahnhof - Essen Katernberg - Zollverein - Essen Hbf - Bredeney</itdRouteDescText>
- <itdOperator>
- <code>11</code>
- <name>EVAG Strab</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="4" number="107" symbol="107" motType="4" realtime="0" direction="Essen Hanielstr. Schleife" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009844" stateless="vrr:11107: :R:911" trainName="" index="4:8">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11107" project="911" direction="R" supplement=" " network="vrr" />
- <itdRouteDescText>Bredeney - Essen Hbf - Zollverein - Essen Katernberg - GE-Hauptbahnhof</itdRouteDescText>
- <itdOperator>
- <code>11</code>
- <name>EVAG Strab</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="5" number="145" symbol="145" motType="5" realtime="0" direction="Essen Heisingen Baldeneysee" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009302" stateless="vrr:12145: :H:911" trainName="" index="5:0">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12145" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Mülheim Flughafen - Essen Haarzopf - Essen Hbf - Stadtwald - Heisingen</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="5" number="145" symbol="145" motType="5" realtime="0" direction="Essen Fängershof Schleife" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009847" stateless="vrr:12145: :R:911" trainName="" index="5:1">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12145" project="911" direction="R" supplement=" " network="vrr" />
- <itdRouteDescText>Heisingen - Stadtwald - Essen Hbf - Essen Haarzopf - Mülheim Flughafen</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="5" number="146" symbol="146" motType="5" realtime="0" direction="Essen Heisingen Baldeneysee" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009302" stateless="vrr:12146: :H:911" trainName="" index="5:2">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12146" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Leithe - Kray - Essen Hbf - Heisingen</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="5" number="146" symbol="146" motType="5" realtime="0" direction="Essen Wackenberg" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009628" stateless="vrr:12146: :R:911" trainName="" index="5:3">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12146" project="911" direction="R" supplement=" " network="vrr" />
- <itdRouteDescText>Heisingen - Essen Hbf - Kray - Leithe</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="5" number="154" symbol="154" motType="5" realtime="0" direction="Essen Betriebshof Ruhrallee" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009884" stateless="vrr:12154: :H:911" trainName="" index="5:4">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12154" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Beisen - E-Hbf - Bergerhausen</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="5" number="154" symbol="154" motType="5" realtime="0" direction="Essen Kraspothstr." valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009815" stateless="vrr:12154: :R:911" trainName="" index="5:5">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12154" project="911" direction="R" supplement=" " network="vrr" />
- <itdRouteDescText>Bergerhausen - E-Hbf - Beisen</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="5" number="155" symbol="155" motType="5" realtime="0" direction="Essen Kupferdreh Bahnhof" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009414" stateless="vrr:12155: :H:911" trainName="" index="5:6">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12155" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>GE-Rotths. - E-Hbf - Kupferdreh</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="5" number="155" symbol="155" motType="5" realtime="0" direction="Essen Landschede" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009421" stateless="vrr:12155: :R:911" trainName="" index="5:7">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12155" project="911" direction="R" supplement=" " network="vrr" />
- <itdRouteDescText>Kupferdreh - E-Hbf - GE-Rotths.</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="5" number="166" symbol="166" motType="5" realtime="0" direction="Hattingen Märkische Str" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20008454" stateless="vrr:12166: :H:911" trainName="" index="5:8">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12166" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Dellwig - Essen Hbf - Steele - E-Burgaltendorf - HAT-Niederwenigern</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="5" number="166" symbol="166" motType="5" realtime="0" direction="Essen Dellwig Bahnhof" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009197" stateless="vrr:12166: :R:911" trainName="" index="5:9">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12166" project="911" direction="R" supplement=" " network="vrr" />
- <itdRouteDescText>HAT-Niederwenigern - E-Burgaltendorf - Steele - Essen Hbf - Dellwig</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="5" number="193" symbol="193" motType="5" realtime="0" direction="Essen Versorgungsamt" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009617" stateless="vrr:12193: :H:911" trainName="" index="5:10">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12193" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - Versorgungsamt</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="5" number="196" symbol="196" motType="5" realtime="0" direction="Essen West S" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009643" stateless="vrr:12196: :H:911" trainName="" index="5:11">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12196" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Vogelheim - Bergeborbeck - Essen Hbf - Essen West</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="5" number="196" symbol="196" motType="5" realtime="0" direction="Essen Hafenverwaltung" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009277" stateless="vrr:12196: :R:911" trainName="" index="5:12">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12196" project="911" direction="R" supplement=" " network="vrr" />
- <itdRouteDescText>Essen West - Essen Hbf - Bergeborbeck - Vogelheim</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="3" number="NE1" symbol="NE1" motType="5" realtime="0" direction="Gelsenkirchen Essener Str." valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20006670" stateless="vrr:12m01: :H:911" trainName="" index="5:13">
- <itdNoTrain name="NE" />
- <motDivaParams line="12m01" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - Altenessen - Essen Karnap - Gelsenkirchen</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="3" number="NE2" symbol="NE2" motType="5" realtime="0" direction="Essen Hanielstr. Schleife" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009844" stateless="vrr:12m02: :H:911" trainName="" index="5:14">
- <itdNoTrain name="NE" />
- <motDivaParams line="12m02" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - Katernberg</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="3" number="NE3" symbol="NE3" motType="5" realtime="0" direction="Essen Rodenseelbrücke" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009513" stateless="vrr:12m03: :H:911" trainName="" index="5:15">
- <itdNoTrain name="NE" />
- <motDivaParams line="12m03" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - Schonnebeck - Kray - Leithe</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="3" number="NE4" symbol="NE4" motType="5" realtime="0" direction="E-Burgaltendorf Burgruine" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009182" stateless="vrr:12m04: :H:911" trainName="" index="5:16">
- <itdNoTrain name="NE" />
- <motDivaParams line="12m04" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - Frillendorf - Steele - Überruhr - Burgaltendorf</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="3" number="NE5" symbol="NE5" motType="5" realtime="0" direction="Essen Hörsterfeld" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009329" stateless="vrr:12m05: :H:911" trainName="" index="5:17">
- <itdNoTrain name="NE" />
- <motDivaParams line="12m05" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - Huttrop - Steele - Hörsterfeld</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="3" number="NE6" symbol="NE6" motType="5" realtime="0" direction="Essen Kupferdreh Bahnhof" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009414" stateless="vrr:12M06: :H:911" trainName="" index="5:18">
- <itdNoTrain name="NE" />
- <motDivaParams line="12M06" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - Rellinghausen - Überruhr - Kupferdreh</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="3" number="NE7" symbol="*120" motType="5" realtime="0" direction="Essen Heisingen Baldeneysee" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009302" stateless="vrr:12m07: :H:911" trainName="" index="5:19">
- <itdNoTrain name="NE" />
- <motDivaParams line="12m07" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - Stadtwald - Heisingen</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="3" number="NE8" symbol="NE8" motType="5" realtime="0" direction="Velbert Willy-Brandt-Platz" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20010368" stateless="vrr:12M08: :H:911" trainName="" index="5:20">
- <itdNoTrain name="NE" />
- <motDivaParams line="12M08" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - Bredeney - Essen Werden - Velbert</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="3" number="NE9" symbol="NE9" motType="5" realtime="0" direction="Essen Hatzper Str." valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009291" stateless="vrr:12M09: :H:911" trainName="" index="5:21">
- <itdNoTrain name="NE" />
- <motDivaParams line="12M09" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - Holsterhausen - Margarethenhöhe - Haarzopf</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="3" number="NE10" symbol="NE10" motType="5" realtime="0" direction="Essen Erbach" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009222" stateless="vrr:12M10: :H:911" trainName="" index="5:22">
- <itdNoTrain name="NE" />
- <motDivaParams line="12M10" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - Frohnhausen - Haarzopf</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="3" number="NE11" symbol="NE11" motType="5" realtime="0" direction="Oberhausen Hbf." valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20014022" stateless="vrr:12m11: :H:911" trainName="" index="5:23">
- <itdNoTrain name="NE" />
- <motDivaParams line="12m11" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - Altendorf - Essen Frintrop - Oberhausen</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="3" number="NE12" symbol="NE12" motType="5" realtime="0" direction="Essen Borbeck Bf" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009158" stateless="vrr:12m12: :H:911" trainName="" index="5:24">
- <itdNoTrain name="NE" />
- <motDivaParams line="12m12" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - Altendorf - Bergeborbeck - Dellwig - Borbeck</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="3" number="NE13" symbol="NE13" motType="5" realtime="0" direction="Essen Kettwig S" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009383" stateless="vrr:12M13: :H:911" trainName="" index="5:25">
- <itdNoTrain name="NE" />
- <motDivaParams line="12M13" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - Rüttenscheid - Kettwig</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="3" number="NE16" symbol="NE16" motType="5" realtime="0" direction="Bottrop ZOB Berliner Platz" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20003267" stateless="vrr:12M16: :H:911" trainName="" index="5:26">
- <itdNoTrain name="NE" />
- <motDivaParams line="12M16" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - Bergeborbeck - Essen Dellwig - Bottrop</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="5" number="SB19" symbol="SB19" motType="5" realtime="0" direction="Heiligenhaus Rathaus" valid="BVR-Fahrplan (12.6.-10.12.2011)" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20010030" stateless="vrr:88S19: :H:bv4" trainName="" index="5:27">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="88S19" project="bv4" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - Velbert - Heiligenhaus Rathaus</itdRouteDescText>
- <itdOperator>
- <code>88</code>
- <name>Busverkehr Rheinland</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="3" number="SB14" symbol="SB14" motType="7" realtime="0" direction="Essen Heisingen Baldeneysee" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20009302" stateless="vrr:12S14: :R:911" trainName="" index="7:0">
- <itdNoTrain name="SB" />
- <motDivaParams line="12S14" project="911" direction="R" supplement=" " network="vrr" />
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="3" number="SB15" symbol="SB15" motType="7" realtime="0" direction="E-Burgaltendorf Burgruine" valid="EVAG Fahrplan 7.9.2011 - 8.1.2012" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="" stateless="vrr:12S15: :H:911" trainName="" index="7:1">
- <itdNoTrain name="SB" />
- <motDivaParams line="12S15" project="911" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - Überruhr - Burgaltendorf</itdRouteDescText>
- <itdOperator>
- <code>12</code>
- <name>EVAG Bus</name>
- </itdOperator>
- </itdServingLine>
- <itdServingLine selected="1" code="3" number="SB16" symbol="SB16" motType="7" realtime="0" direction="Dorsten ZOB Dorsten" valid="Sommerfahrplan 2011" compound="0" TTB="0" STT="0" ROP="0" type="unknown" spTr="" destID="20003214" stateless="vrr:40016: :H:s11" trainName="" index="7:2">
- <itdNoTrain name="SB" />
- <motDivaParams line="40016" project="s11" direction="H" supplement=" " network="vrr" />
- <itdRouteDescText>Essen Hbf - BOT-Hbf - ZOB Berliner Platz - Kirchhellen - Movie Park /ZOB Dorsten</itdRouteDescText>
- <itdOperator>
- <code>40</code>
- <name>Vestische</name>
- </itdOperator>
- </itdServingLine>
- </itdServingLines>
- <itdDepartureList>
- <itdDeparture stopID="20009289" x="3361949" y="456292" mapName="NAV3" area="90" platform="#1" platformName="Gleis 1" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="1">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="36" ap="" />
- </itdDateTime>
- <itdRTDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="40" ap="" />
- </itdRTDateTime>
- <itdServingLine key="946" code="6" number="ICE 946 Intercity-Express" symbol="ICE 946 Intercity-Express" motType="0" realtime="1" direction="Düsseldorf Hbf" trainType="ICE" trainNum="946" destID="20018235" stateless="ddb:98010: :H:j11">
- <itdNoTrain name="Intercity-Express" delay="4">Bordrestaurant</itdNoTrain>
- <motDivaParams line="98010" project="j11" direction="H" supplement=" " network="ddb" />
- </itdServingLine>
- <genAttrList>
- <genAttrElem>
- <name>lineType</name>
- <value>HIGHSPEEDTRAIN</value>
- </genAttrElem>
- <genAttrElem>
- <name>lineType</name>
- <value>LONG_DISTANCE_TRAINS</value>
- </genAttrElem>
- <genAttrElem>
- <name>lineType</name>
- <value>SUPPLEMENT</value>
- </genAttrElem>
- </genAttrList>
- <itdServingTrip tripCode="946" AVMSTripID="946-8010255-16052600-8000085-16100500" />
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361962" y="456258" mapName="NAV3" area="4" platform="4" platformName="Bstg. 4" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="1">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="39" ap="" />
- </itdDateTime>
- <itdServingLine key="939" code="5" number="SB19" symbol="SB19" motType="5" realtime="0" direction="Velbert Willy-Brandt-Platz" destID="20010368" stateless="vrr:88S19: :H:bv4">
- <itdNoTrain name="Niederflurbus">weiter als Linie SB 66 nach Wuppertal Hbf</itdNoTrain>
- <motDivaParams line="88S19" project="bv4" direction="H" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361923" y="456436" mapName="NAV3" area="1" platform="1" platformName="Bstg. 1" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="1">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="39" ap="" />
- </itdDateTime>
- <itdServingLine key="932" code="5" number="196" symbol="196" motType="5" realtime="0" direction="Essen Hafenverwaltung" destID="20009277" stateless="vrr:12196: :R:911">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12196" project="911" direction="R" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361949" y="456327" mapName="NAV3" area="14" platform="2" platformName="Bstg. 2" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="1">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="39" ap="" />
- </itdDateTime>
- <itdServingLine key="933" code="1" number="18" symbol="18" motType="2" realtime="0" direction="Mülheim Heißen Kirche" destID="20015079" stateless="vrr:10U18:2:H:911">
- <itdNoTrain name="U-Bahn">Ab (H) Heißen Kirche, Umstieg in den SEV Ri. Mülheim Hbf.</itdNoTrain>
- <motDivaParams line="10U18" project="911" direction="H" supplement="2" network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361966" y="456306" mapName="NAV3" area="13" platform="3" platformName="Bstg. 3" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="1">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="40" ap="" />
- </itdDateTime>
- <itdServingLine key="928" code="1" number="U17" symbol="U17" motType="2" realtime="0" direction="Essen Karlsplatz" destID="20009370" stateless="vrr:10U17: :R:911">
- <itdNoTrain name="U-Bahn" />
- <motDivaParams line="10U17" project="911" direction="R" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361966" y="456306" mapName="NAV3" area="3" platform="3" platformName="Bstg. 3" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="1">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="40" ap="" />
- </itdDateTime>
- <itdServingLine key="911" code="5" number="145" symbol="145" motType="5" realtime="0" direction="Essen Fängershof Schleife" destID="20009847" stateless="vrr:12145: :R:911">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12145" project="911" direction="R" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361949" y="456292" mapName="NAV3" area="98" platform="#7" platformName="Gleis 7" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="2">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="41" ap="" />
- </itdDateTime>
- <itdRTDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="41" ap="" />
- </itdRTDateTime>
- <itdServingLine key="30942" code="2" number="S9" symbol="S9" motType="1" realtime="1" direction="Haltern am See Bf" trainNum="30942" destID="20003527" stateless="ddb:92E09: :H:j11">
- <itdNoTrain name="S-Bahn" delay="0">Fahrradmitnahme begrenzt möglich</itdNoTrain>
- <motDivaParams line="92E09" project="j11" direction="H" supplement=" " network="ddb" />
- </itdServingLine>
- <genAttrList />
- <itdServingTrip tripCode="30942" AVMSTripID="30942-8000266-16085300-8000145-16102700" />
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361962" y="456258" mapName="NAV3" area="14" platform="4" platformName="Bstg. 4" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="2">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="41" ap="" />
- </itdDateTime>
- <itdServingLine key="915" code="4" number="107" symbol="107" motType="4" realtime="0" direction="Essen Bredeney" destID="20009172" stateless="vrr:11107: :H:911">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11107" project="911" direction="H" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361923" y="456436" mapName="NAV3" area="13" platform="1" platformName="Bstg. 1" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="2">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="41" ap="" />
- </itdDateTime>
- <itdServingLine key="941" code="4" number="101" symbol="101" motType="4" realtime="0" direction="Essen Germaniaplatz" destID="20009254" stateless="vrr:11101: :R:911">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11101" project="911" direction="R" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361949" y="456292" mapName="NAV3" area="98" platform="#11" platformName="Gleis 11" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="7">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="41" ap="" />
- </itdDateTime>
- <itdRTDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="46" ap="" />
- </itdRTDateTime>
- <itdServingLine key="30937" code="2" number="S9" symbol="S9" motType="1" realtime="1" direction="Wuppertal Hbf" trainNum="30937" destID="20011019" stateless="ddb:92E09: :R:j11">
- <itdNoTrain name="S-Bahn" delay="5">Fahrradmitnahme begrenzt möglich</itdNoTrain>
- <motDivaParams line="92E09" project="j11" direction="R" supplement=" " network="ddb" />
- </itdServingLine>
- <genAttrList />
- <itdServingTrip tripCode="30937" AVMSTripID="30937-8000047-16092400-8000266-16102700" />
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361949" y="456327" mapName="NAV3" area="14" platform="2" platformName="Bstg. 2" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="3">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="42" ap="" />
- </itdDateTime>
- <itdServingLine key="931" code="1" number="U17" symbol="U17" motType="2" realtime="0" direction="Essen Margarethenhöhe" destID="20009447" stateless="vrr:10U17: :H:911">
- <itdNoTrain name="U-Bahn" />
- <motDivaParams line="10U17" project="911" direction="H" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361966" y="456306" mapName="NAV3" area="13" platform="3" platformName="Bstg. 3" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="4">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="43" ap="" />
- </itdDateTime>
- <itdServingLine key="924" code="1" number="18" symbol="18" motType="2" realtime="0" direction="Essen Berliner Platz" destID="20009153" stateless="vrr:10U18:2:R:911">
- <itdNoTrain name="U-Bahn" />
- <motDivaParams line="10U18" project="911" direction="R" supplement="2" network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361953" y="456233" mapName="NAV3" area="8" platform="8" platformName="Bstg. 8" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="5">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="44" ap="" />
- </itdDateTime>
- <itdServingLine key="914" code="5" number="146" symbol="146" motType="5" realtime="0" direction="Essen Heisingen Baldeneysee" destID="20009302" stateless="vrr:12146: :H:911">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12146" project="911" direction="H" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361949" y="456292" mapName="NAV3" area="90" platform="#4" platformName="Gleis 4" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="6">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="44" ap="" />
- </itdDateTime>
- <itdRTDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="45" ap="" />
- </itdRTDateTime>
- <itdServingLine key="10211" code="6" number="RE2" symbol="RE2" motType="0" realtime="1" direction="Münster (Westf) Hbf" trainNum="10211" destID="24041000" stateless="ddb:90425:B:H:j11">
- <itdNoTrain name="R-Bahn" delay="1">Fahrradmitnahme begrenzt möglich</itdNoTrain>
- <motDivaParams line="90425" project="j11" direction="H" supplement="B" network="ddb" />
- </itdServingLine>
- <genAttrList />
- <itdServingTrip tripCode="10211" AVMSTripID="10211-8000086-16092400-8000263-16105000" />
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361944" y="456315" mapName="NAV3" area="7" platform="7" platformName="Bstg. 7" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="5">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="44" ap="" />
- </itdDateTime>
- <itdServingLine key="917" code="5" number="155" symbol="155" motType="5" realtime="0" direction="Essen Marienbergstr." destID="20009448" stateless="vrr:12155: :H:911">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12155" project="911" direction="H" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361923" y="456436" mapName="NAV3" area="13" platform="1" platformName="Bstg. 1" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="5">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="44" ap="" />
- </itdDateTime>
- <itdServingLine key="919" code="4" number="106" symbol="106" motType="4" realtime="0" direction="Essen Altenessen Bf Schleife" destID="20009832" stateless="vrr:11106: :R:911">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11106" project="911" direction="R" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361962" y="456258" mapName="NAV3" area="14" platform="4" platformName="Bstg. 4" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="6">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="45" ap="" />
- </itdDateTime>
- <itdServingLine key="934" code="4" number="106" symbol="106" motType="4" realtime="0" direction="Essen Helenenstr." destID="20009306" stateless="vrr:11106: :H:911">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11106" project="911" direction="H" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361966" y="456306" mapName="NAV3" area="13" platform="3" platformName="Bstg. 3" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="6">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="45" ap="" />
- </itdDateTime>
- <itdServingLine key="939" code="1" number="11" symbol="11" motType="2" realtime="0" direction="Gelsenkirchen Buerer Str." destID="20005579" stateless="vrr:10U11: :R:911">
- <itdNoTrain name="U-Bahn" />
- <motDivaParams line="10U11" project="911" direction="R" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361949" y="456327" mapName="NAV3" area="14" platform="2" platformName="Bstg. 2" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="7">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="46" ap="" />
- </itdDateTime>
- <itdServingLine key="931" code="1" number="11" symbol="11" motType="2" realtime="0" direction="Essen Messe W.-Süd/Gruga" destID="20009270" stateless="vrr:10U11: :H:911">
- <itdNoTrain name="U-Bahn" />
- <motDivaParams line="10U11" project="911" direction="H" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361949" y="456292" mapName="NAV3" area="90" platform="#2" platformName="Gleis 2" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="19">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="46" ap="" />
- </itdDateTime>
- <itdRTDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="58" ap="" />
- </itdRTDateTime>
- <itdServingLine key="10008" code="6" number="RE11" symbol="RE11" motType="0" realtime="1" direction="Mönchengladbach Hbf" trainNum="10008" destID="-1" stateless="ddb:90415:C:H:j11">
- <itdNoTrain name="R-Bahn" delay="12">Fahrradmitnahme begrenzt möglich</itdNoTrain>
- <motDivaParams line="90415" project="j11" direction="H" supplement="C" network="ddb" />
- </itdServingLine>
- <genAttrList />
- <itdServingTrip tripCode="10008" AVMSTripID="10008-8000149-16085600-8000086-16095800" />
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361949" y="456292" mapName="NAV3" area="98" platform="#7" platformName="Gleis 7" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="11">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="46" ap="" />
- </itdDateTime>
- <itdRTDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="50" ap="" />
- </itdRTDateTime>
- <itdServingLine key="30342" code="2" number="S3" symbol="S3" motType="1" realtime="1" direction="Oberhausen Hbf." trainNum="30342" destID="20014022" stateless="ddb:92E03: :R:j11">
- <itdNoTrain name="S-Bahn" delay="4">Fahrradmitnahme begrenzt möglich</itdNoTrain>
- <motDivaParams line="92E03" project="j11" direction="R" supplement=" " network="ddb" />
- </itdServingLine>
- <genAttrList />
- <itdServingTrip tripCode="30342" AVMSTripID="30342-8002640-16092500-8000286-16100300" />
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361949" y="456292" mapName="NAV3" area="98" platform="#11" platformName="Gleis 11" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="8">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="46" ap="" />
- </itdDateTime>
- <itdRTDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="47" ap="" />
- </itdRTDateTime>
- <itdServingLine key="30143" code="2" number="S1" symbol="S1" motType="1" realtime="1" direction="Dortmund Hbf" trainNum="30143" destID="20000131" stateless="ddb:92E01: :H:j11">
- <itdNoTrain name="S-Bahn" delay="1">Fahrradmitnahme begrenzt möglich</itdNoTrain>
- <motDivaParams line="92E01" project="j11" direction="H" supplement=" " network="ddb" />
- </itdServingLine>
- <genAttrList />
- <itdServingTrip tripCode="30143" AVMSTripID="30143-8000087-16083300-8000080-16102600" />
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361949" y="456327" mapName="NAV3" area="2" platform="2" platformName="Bstg. 2" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="7">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="46" ap="" />
- </itdDateTime>
- <itdServingLine key="916" code="5" number="166" symbol="166" motType="5" realtime="0" direction="Hattingen Märkische Str" destID="20008454" stateless="vrr:12166: :H:911">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12166" project="911" direction="H" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361923" y="456436" mapName="NAV3" area="13" platform="1" platformName="Bstg. 1" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="7">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="46" ap="" />
- </itdDateTime>
- <itdServingLine key="929" code="4" number="105" symbol="105" motType="4" realtime="0" direction="Essen Unterstr." destID="20009614" stateless="vrr:11105: :R:911">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11105" project="911" direction="R" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361944" y="456315" mapName="NAV3" area="7" platform="7" platformName="Bstg. 7" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="7">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="46" ap="" />
- </itdDateTime>
- <itdServingLine key="946" code="3" number="SB15" symbol="SB15" motType="7" realtime="0" direction="Burgaltendorf Burgruine" destID="-1" stateless="vrr:12S15: :H:911">
- <itdNoTrain name="SB" />
- <motDivaParams line="12S15" project="911" direction="H" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361949" y="456327" mapName="NAV3" area="2" platform="2" platformName="Bstg. 2" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="7">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="46" ap="" />
- </itdDateTime>
- <itdServingLine key="912" code="5" number="155" symbol="155" motType="5" realtime="0" direction="Gelsenkirchen Achternbergstr." destID="20005885" stateless="vrr:12155: :R:911">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12155" project="911" direction="R" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361943" y="456248" mapName="NAV3" area="9" platform="9" platformName="Bstg. 9" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="8">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="47" ap="" />
- </itdDateTime>
- <itdServingLine key="916" code="5" number="196" symbol="196" motType="5" realtime="0" direction="Essen West S" destID="20009643" stateless="vrr:12196: :H:911">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12196" project="911" direction="H" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361923" y="456436" mapName="NAV3" area="13" platform="1" platformName="Bstg. 1" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="9">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="48" ap="" />
- </itdDateTime>
- <itdServingLine key="937" code="4" number="107" symbol="107" motType="4" realtime="0" direction="Gelsenkirchen Hbf" destID="20005613" stateless="vrr:11107: :R:911">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11107" project="911" direction="R" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361962" y="456258" mapName="NAV3" area="14" platform="4" platformName="Bstg. 4" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="9">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="48" ap="" />
- </itdDateTime>
- <itdServingLine key="920" code="4" number="105" symbol="105" motType="4" realtime="0" direction="Essen Finefraustr." destID="20009232" stateless="vrr:11105: :H:911">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11105" project="911" direction="H" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361949" y="456292" mapName="NAV3" area="98" platform="#12" platformName="Gleis 12" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="9">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="48" ap="" />
- </itdDateTime>
- <itdRTDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="48" ap="" />
- </itdRTDateTime>
- <itdServingLine key="30652" code="2" number="S6" symbol="S6" motType="1" realtime="1" direction="Nippes, Nippes S-Bahn" trainNum="30652" destID="22000750" stateless="ddb:92E06: :H:j11">
- <itdNoTrain name="S-Bahn" delay="0">Fahrradmitnahme begrenzt möglich</itdNoTrain>
- <motDivaParams line="92E06" project="j11" direction="H" supplement=" " network="ddb" />
- </itdServingLine>
- <genAttrList />
- <itdServingTrip tripCode="30652" AVMSTripID="30652-8000098-16094800-8003372-16112800" />
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361949" y="456327" mapName="NAV3" area="14" platform="2" platformName="Bstg. 2" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="10">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="49" ap="" />
- </itdDateTime>
- <itdServingLine key="938" code="1" number="18" symbol="18" motType="2" realtime="0" direction="Mülheim Heißen Kirche" destID="20015079" stateless="vrr:10U18:2:H:911">
- <itdNoTrain name="U-Bahn">Ab (H) Heißen Kirche, Umstieg in den SEV Ri. Mülheim Hbf.</itdNoTrain>
- <motDivaParams line="10U18" project="911" direction="H" supplement="2" network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361966" y="456306" mapName="NAV3" area="13" platform="3" platformName="Bstg. 3" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="11">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="50" ap="" />
- </itdDateTime>
- <itdServingLine key="938" code="1" number="U17" symbol="U17" motType="2" realtime="0" direction="Essen Karlsplatz" destID="20009370" stateless="vrr:10U17: :R:911">
- <itdNoTrain name="U-Bahn" />
- <motDivaParams line="10U17" project="911" direction="R" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361966" y="456306" mapName="NAV3" area="3" platform="3" platformName="Bstg. 3" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="11">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="50" ap="" />
- </itdDateTime>
- <itdServingLine key="947" code="5" number="146" symbol="146" motType="5" realtime="0" direction="Essen Wackenberg" destID="20009628" stateless="vrr:12146: :R:911">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12146" project="911" direction="R" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361962" y="456258" mapName="NAV3" area="14" platform="4" platformName="Bstg. 4" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="12">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="51" ap="" />
- </itdDateTime>
- <itdServingLine key="921" code="4" number="107" symbol="107" motType="4" realtime="0" direction="Essen Bredeney" destID="20009172" stateless="vrr:11107: :H:911">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11107" project="911" direction="H" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361923" y="456436" mapName="NAV3" area="13" platform="1" platformName="Bstg. 1" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="12">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="51" ap="" />
- </itdDateTime>
- <itdServingLine key="951" code="4" number="101" symbol="101" motType="4" realtime="0" direction="Essen Germaniaplatz" destID="20009254" stateless="vrr:11101: :R:911">
- <itdNoTrain name="Straßenbahn" />
- <motDivaParams line="11101" project="911" direction="R" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361949" y="456327" mapName="NAV3" area="14" platform="2" platformName="Bstg. 2" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="13">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="52" ap="" />
- </itdDateTime>
- <itdServingLine key="946" code="1" number="U17" symbol="U17" motType="2" realtime="0" direction="Essen Margarethenhöhe" destID="20009447" stateless="vrr:10U17: :H:911">
- <itdNoTrain name="U-Bahn" />
- <motDivaParams line="10U17" project="911" direction="H" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361923" y="456436" mapName="NAV3" area="1" platform="1" platformName="Bstg. 1" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="14">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="53" ap="" />
- </itdDateTime>
- <itdServingLine key="1020" code="3" number="SB16" symbol="SB16" motType="7" realtime="0" direction="BOT St.-Anto.-Hosp./Gartenstr" destID="20003174" stateless="vrr:40016: :H:s11">
- <itdNoTrain name="SB" />
- <motDivaParams line="40016" project="s11" direction="H" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361966" y="456306" mapName="NAV3" area="13" platform="3" platformName="Bstg. 3" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="14">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="53" ap="" />
- </itdDateTime>
- <itdServingLine key="934" code="1" number="18" symbol="18" motType="2" realtime="0" direction="Essen Berliner Platz" destID="20009153" stateless="vrr:10U18:2:R:911">
- <itdNoTrain name="U-Bahn" />
- <motDivaParams line="10U18" project="911" direction="R" supplement="2" network="vrr" />
- </itdServingLine>
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361949" y="456292" mapName="NAV3" area="90" platform="#6" platformName="Gleis 6" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="26">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="53" ap="" />
- </itdDateTime>
- <itdRTDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="10" minute="5" ap="" />
- </itdRTDateTime>
- <itdServingLine key="10115" code="6" number="RE1" symbol="RE1" motType="0" realtime="1" direction="Hamm (Westf)" trainNum="10115" destID="24007756" stateless="ddb:90415:X:R:j11">
- <itdNoTrain name="R-Bahn" delay="12">Fahrradmitnahme begrenzt möglich</itdNoTrain>
- <motDivaParams line="90415" project="j11" direction="R" supplement="X" network="ddb" />
- </itdServingLine>
- <genAttrList />
- <itdServingTrip tripCode="10115" AVMSTripID="10115-8000001-16075100-8000149-16103600" />
- </itdDeparture>
- <itdDeparture stopID="20009289" x="3361943" y="456248" mapName="NAV3" area="9" platform="9" platformName="Bstg. 9" stopName="Essen Hauptbahnhof" nameWO="Hauptbahnhof" countdown="15">
- <itdDateTime>
- <itdDate year="2011" month="11" day="16" weekday="4" />
- <itdTime hour="9" minute="54" ap="" />
- </itdDateTime>
- <itdServingLine key="908" code="5" number="166" symbol="166" motType="5" realtime="0" direction="Essen Dellwig Bahnhof" destID="20009197" stateless="vrr:12166: :R:911">
- <itdNoTrain name="Niederflurbus" />
- <motDivaParams line="12166" project="911" direction="R" supplement=" " network="vrr" />
- </itdServingLine>
- </itdDeparture>
- </itdDepartureList>
- </itdDepartureMonitorRequest>
-</itdRequest>
-
diff --git a/t/in/essen_hb_invalid.xml b/t/in/essen_hb_invalid.xml
deleted file mode 100644
index de7d10a..0000000
--- a/t/in/essen_hb_invalid.xml
+++ /dev/null
@@ -1,80 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<itdRequest version="9.16.27.53" language="de" lengthUnit="METER" sessionID="efa2.vrr.de_46148296" client="libwww-perl/6.03" clientIP="87.147.17.185" serverID="efa2.vrr.de_" virtDir="vrr" now="2011-11-20T15:31:57" nowWD="1">
- <itdLayoutParams>
- <itdLayoutParam name="mdvMap2_dm" value="" />
- <itdLayoutParam name="mapState_dm" value="" />
- <itdLayoutParam name="mdvMap_dm" value="3406199:401077:NAV3" />
- <itdLayoutParam name="view" value="" />
- <itdLayoutParam name="id_dm" value=":dm" />
- <itdLayoutParam name="transpCompany" value="vrr" />
- </itdLayoutParams>
- <itdDepartureMonitorRequest requestID="1">
- <itdOdv type="stop" usage="dm">
- <itdOdvPlace state="identified" method="itp">
- <odvPlaceElem omc="5113000" placeID="18" value="5113000:18" span="0" type="remote" mainPlace="1">Essen</odvPlaceElem>
- <odvPlaceInput>E</odvPlaceInput>
- </itdOdvPlace>
- <itdOdvName state="notidentified" method="itp">
- <itdMessage type="error" module="BROKER" code="-2000">stop invalid</itdMessage>
- <odvNameElem>Hbfoaei</odvNameElem>
- <odvNameInput>Hbfoaei</odvNameInput>
- </itdOdvName>
- </itdOdv>
- <itdDateTime ttpFrom="20110901" ttpTo="20120531">
- <itdDate weekday="1" year="2011" month="11" day="20" />
- <itdTime hour="15" minute="32" />
- </itdDateTime>
- <itdDateRange>
- <itdDate day="20" month="11" year="2011" weekday="1" />
- <itdDate day="21" month="11" year="2011" weekday="2" />
- <itdDate day="22" month="11" year="2011" weekday="3" />
- <itdDate day="23" month="11" year="2011" weekday="4" />
- <itdDate day="24" month="11" year="2011" weekday="5" />
- <itdDate day="25" month="11" year="2011" weekday="6" />
- <itdDate day="26" month="11" year="2011" weekday="7" />
- <itdDate day="27" month="11" year="2011" weekday="1" />
- <itdDate day="28" month="11" year="2011" weekday="2" />
- <itdDate day="29" month="11" year="2011" weekday="3" />
- <itdDate day="30" month="11" year="2011" weekday="4" />
- <itdDate day="01" month="12" year="2011" weekday="5" />
- <itdDate day="02" month="12" year="2011" weekday="6" />
- <itdDate day="03" month="12" year="2011" weekday="7" />
- <itdDate day="04" month="12" year="2011" weekday="1" />
- </itdDateRange>
- <itdTripOptions>
- <itdPtOptions>
- <excludedMeans>
- <meansElem value="0" selected="0">Zug</meansElem>
- <meansElem value="1" selected="0">S-Bahn</meansElem>
- <meansElem value="2" selected="0">U-Bahn</meansElem>
- <meansElem value="3" selected="0">Stadtbahn</meansElem>
- <meansElem value="4" selected="0">Straßen-/Trambahn</meansElem>
- <meansElem value="5" selected="0">Stadtbus</meansElem>
- <meansElem value="6" selected="0">Regionalbus</meansElem>
- <meansElem value="7" selected="0">Schnellbus</meansElem>
- <meansElem value="8" selected="0">Seil-/Zahnradbahn</meansElem>
- <meansElem value="9" selected="0">Schiff</meansElem>
- <meansElem value="10" selected="0">AST/Rufbus</meansElem>
- <meansElem value="11" selected="0">Sonstige</meansElem>
- </excludedMeans>
- </itdPtOptions>
- <itdItOptions>
- <itRouter logASCII="false" logSVG="false" />
- <itPedestrian computeMonomodalTrip="false" computationType="PT_AND_IT" itIncidentData="false" useElevation="false" speedFactor="100" costFactor="0" distanceFactor="50" traveltimeFactor="50" noTunnel="false" noBridge="false" noFerry="false" maxTime="20" maxLength="2147483647" ignoreRestrictions="false" />
- <itBicycle preferAsphaltTracks="false" preferGreenTracks="false" usePseudoRouting="false" useSignedRoute="false" cycleSpeed="20" prefHikePath="false" elevFac="50" bikeProf="UNKNOWN" computeMonomodalTrip="false" computationType="PT_AND_IT" itIncidentData="false" useElevation="false" speedFactor="100" costFactor="0" distanceFactor="50" traveltimeFactor="50" noTunnel="false" noBridge="false" noFerry="false" maxTime="15" maxLength="2147483647" ignoreRestrictions="false" />
- <mitCar computeMonomodalTrip="false" computationType="PT_AND_IT" itIncidentData="false" useElevation="false" speedFactor="100" costFactor="0" distanceFactor="10" traveltimeFactor="90" noTunnel="false" noBridge="false" noFerry="false" maxTime="90" maxLength="2147483647" ignoreRestrictions="false" mitProfileData="false" mitIncidentData="false" mitOnlineData="false" noHighway="false" noTollRoad="false" />
- <departureTransport>
- <individualTransport meansCode="100" value="8" speed="normal" selected="1" />
- <individualTransport meansCode="101" value="15" speed="normal" selected="0" />
- <individualTransport meansCode="102" value="15" speed="normal" selected="0" />
- <individualTransport meansCode="103" value="10" speed="normal" selected="0" />
- <individualTransport meansCode="104" value="10" speed="normal" selected="0" />
- <individualTransport meansCode="105" value="30" speed="normal" selected="0" />
- <individualTransport meansCode="106" value="15" speed="normal" selected="0" />
- <individualTransport meansCode="107" value="15" speed="normal" selected="0" />
- </departureTransport>
- </itdItOptions>
- </itdTripOptions>
- </itdDepartureMonitorRequest>
-</itdRequest>
-
diff --git a/xt/00-compile-pm.t b/xt/00-compile-pm.t
new file mode 100755
index 0000000..2476ab2
--- /dev/null
+++ b/xt/00-compile-pm.t
@@ -0,0 +1,8 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use 5.010;
+use Test::More;
+use Test::Compile;
+
+all_pm_files_ok();
diff --git a/xt/01-compile-pl.t b/xt/01-compile-pl.t
new file mode 100755
index 0000000..f130ac4
--- /dev/null
+++ b/xt/01-compile-pl.t
@@ -0,0 +1,8 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use 5.010;
+use Test::More;
+use Test::Compile;
+
+all_pl_files_ok();