diff options
| author | Birte Kristina Friesel <derf@finalrewind.org> | 2024-09-27 19:11:30 +0200 | 
|---|---|---|
| committer | Birte Kristina Friesel <derf@finalrewind.org> | 2024-09-27 19:11:30 +0200 | 
| commit | 8977ed62d4d59d9f65235cb8214def781dc5674a (patch) | |
| tree | d56fd62745b772a2f40c42515114d55947213c14 | |
| parent | 62eb6d374ac1ec08d093a8e035157c85952d7a2d (diff) | |
Switch to transport-apis repo for enhanced backend definitions
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | .gitmodules | 3 | ||||
| -rw-r--r-- | Changelog | 6 | ||||
| -rwxr-xr-x | bin/efa-m | 20 | ||||
| m--------- | ext/transport-apis | 0 | ||||
| -rw-r--r-- | lib/Travel/Status/DE/EFA.pm | 133 | ||||
| -rw-r--r-- | lib/Travel/Status/DE/EFA/Services.pm.PL | 147 | 
7 files changed, 187 insertions, 123 deletions
@@ -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 @@ -4,11 +4,13 @@ git HEAD      * Switch API language from XML to JSON      * Rename Travel::Status::DE::EFA::Result to Travel::Status::DE::EFA::Departure      * EFA: Remove "identified_data" accessor (not supported by JSON backends) -    * Result/Departure: Remove "info" accessor      * Result/Departure: Add "hints" accessor -    * Stop: Remove "name_suf" accessor +    * Result/Departure: Remove "info" accessor; use "hints" instead      * Stop: Add "place", "full_name" and "occupancy" accessors +    * Stop: Remove "name_suf" accessor; use "name" instead      * Line: Add "number" accessor +    * EFA: Remove "get_efa_urls" and "get_service" functions; use the newly +      introduced Travel::Status::DE::EFA::Services package instead.      * efa-m: -Oa, -Ob, -Of: show per-stop occupancy, if available  Travel::Status::DE::VRR 2.02 - Sun May 19 2024 @@ -12,6 +12,7 @@ use Encode       qw(decode);  use Getopt::Long qw(:config no_ignore_case bundling);  use List::Util   qw(first max none);  use Travel::Status::DE::EFA; +use Travel::Status::DE::EFA::Services;  my $service = 'VRR';  my $efa_url; @@ -112,7 +113,7 @@ if ($efa_url) {  	$service = undef;  }  elsif ($service) { -	my $service_ref = Travel::Status::DE::EFA::get_service($service); +	my $service_ref = Travel::Status::DE::EFA::Services::get_service($service);  	if ( not $service_ref ) {  		printf STDERR (  			"Error: Unknown service '%s'. See 'efa-m --list' for a " @@ -156,8 +157,11 @@ 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::Services::get_service_ids() ) { +		my $service +		  = Travel::Status::DE::EFA::Services::get_service($shortname); +		printf( "%-45s %-14s %s\n", +			$service->{name}, $shortname, $service->{url} );  	}  	exit 0; @@ -437,16 +441,18 @@ sub show_results {  }  if ( $discover or $discover_and_print ) { -	for my $service_ref ( Travel::Status::DE::EFA::get_efa_urls() ) { -		$efa = new_efa( $service_ref->{shortname} ); +	for my $shortname ( Travel::Status::DE::EFA::Services::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::Services::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 ),  			);  		}  	} diff --git a/ext/transport-apis b/ext/transport-apis new file mode 160000 +Subproject 16ded4b86256cba98c19fc0967c54ad7554f77e diff --git a/lib/Travel/Status/DE/EFA.pm b/lib/Travel/Status/DE/EFA.pm index bd1fe48..b95ff41 100644 --- a/lib/Travel/Status/DE/EFA.pm +++ b/lib/Travel/Status/DE/EFA.pm @@ -12,79 +12,13 @@ use DateTime;  use DateTime::Format::Strptime;  use Encode qw(encode);  use JSON; -use Travel::Status::DE::EFA::Line;  use Travel::Status::DE::EFA::Departure; +use Travel::Status::DE::EFA::Line; +use Travel::Status::DE::EFA::Services;  use Travel::Status::DE::EFA::Stop;  use Travel::Status::DE::EFA::Trip;  use LWP::UserAgent; -my %efa_instance = ( -	BSVG => { -		url  => 'https://bsvg.efa.de/bsvagstd', -		name => 'Braunschweiger Verkehrs-GmbH', -	}, -	DING => { -		url  => 'https://www.ding.eu/ding3', -		name => 'Donau-Iller Nahverkehrsverbund', -	}, -	KVV => { -		url  => 'https://projekte.kvv-efa.de/sl3-alone', -		name => 'Karlsruher Verkehrsverbund', -	}, -	LinzAG => { -		url      => 'https://www.linzag.at/static', -		name     => 'Linz AG', -		encoding => 'iso-8859-15', -	}, -	MVV => { -		url  => 'https://efa.mvv-muenchen.de/mobile', -		name => 'Münchner Verkehrs- und Tarifverbund', -	}, -	NVBW => { -		url  => 'https://www.efa-bw.de/nvbw', -		name => 'Nahverkehrsgesellschaft Baden-Württemberg', -	}, -	VAG => { -		url  => 'https://efa.vagfr.de/vagfr3', -		name => 'Freiburger Verkehrs AG', -	}, -	VGN => { -		url  => 'https://efa.vgn.de/vgnExt_oeffi', -		name => 'Verkehrsverbund Grossraum Nuernberg', -	}, - -	# HTTPS: certificate verification fails -	VMV => { -		url  => 'http://efa.vmv-mbh.de/vmv', -		name => 'Verkehrsgesellschaft Mecklenburg-Vorpommern', -	}, -	VRN => { -		url  => 'https://www.vrn.de/mngvrn/', -		name => 'Verkehrsverbund Rhein-Neckar', -	}, -	VRR => { -		url  => 'https://efa.vrr.de/vrr', -		name => 'Verkehrsverbund Rhein-Ruhr', -	}, -	VRR2 => { -		url  => 'https://app.vrr.de/standard', -		name => 'Verkehrsverbund Rhein-Ruhr (alternative)', -	}, -	VRR3 => { -		url  => 'https://efa.vrr.de/rbgstd3', -		name => 'Verkehrsverbund Rhein-Ruhr (alternative alternative)', -	}, -	VVO => { -		url  => 'https://efa.vvo-online.de/VMSSL3', -		name => 'Verkehrsverbund Oberelbe', -	}, -	VVS => { -		url  => 'https://www2.vvs.de/vvs', -		name => 'Verkehrsverbund Stuttgart', -	}, - -); -  sub new_p {  	my ( $class, %opt ) = @_;  	my $promise = $opt{promise}->new; @@ -153,22 +87,27 @@ sub new {  		confess('type must be stop, stopID, address, or poi');  	} -	if ( $opt{service} and exists $efa_instance{ $opt{service} } ) { -		$opt{efa_url} = $efa_instance{ $opt{service} }{url}; -		if ( $opt{stopseq} ) { -			$opt{efa_url} .= '/XML_STOPSEQCOORD_REQUEST'; -		} -		else { -			$opt{efa_url} .= '/XML_DM_REQUEST'; +	if ( $opt{service} ) { +		if ( my $service +			= Travel::Status::DE::EFA::Services::get_service( $opt{service} ) ) +		{ +			$opt{efa_url} = $service->{url}; +			if ( $opt{stopseq} ) { +				$opt{efa_url} .= '/XML_STOPSEQCOORD_REQUEST'; +			} +			else { +				$opt{efa_url} .= '/XML_DM_REQUEST'; +			} +			$opt{time_zone} //= $service->{time_zone};  		} -		$opt{time_zone} //= $efa_instance{ $opt{service} }{time_zone};  	} +	$opt{time_zone} //= 'Europe/Berlin'; +  	if ( not $opt{efa_url} ) {  		confess('service or efa_url must be specified');  	} -	my $dt = $opt{datetime} -	  // DateTime->now( time_zone => $opt{time_zone} // 'Europe/Berlin' ); +	my $dt = $opt{datetime} // DateTime->now( time_zone => $opt{time_zone} );  	## no critic (RegularExpressions::ProhibitUnusedCapture)  	## no critic (Variables::ProhibitPunctuationVars) @@ -216,11 +155,11 @@ sub new {  		service        => $opt{service},  		strp_stopseq   => DateTime::Format::Strptime->new(  			pattern   => '%Y%m%d %H:%M', -			time_zone => 'Europe/Berlin', +			time_zone => $opt{time_zone},  		),  		strp_stopseq_s => DateTime::Format::Strptime->new(  			pattern   => '%Y%m%d %H:%M:%S', -			time_zone => 'Europe/Berlin', +			time_zone => $opt{time_zone},  		),  		json => JSON->new->utf8, @@ -465,18 +404,6 @@ sub result {  	return Travel::Status::DE::EFA::Trip->new( json => $self->{response} );  } -# static -sub get_efa_urls { -	return map { -		{ %{ $efa_instance{$_} }, shortname => $_ } -	} sort keys %efa_instance; -} - -sub get_service { -	my ($service) = @_; -	return $efa_instance{$service}; -} -  1;  __END__ @@ -620,28 +547,6 @@ nothing (undef / empty list) otherwise.  Returns a list of Travel::Status::DE::EFA::Departure(3pm) objects, each one describing  one departure. -=item Travel::Status::DE::EFA::get_efa_urls() - -Returns a list of known EFA entry points. Each list element is a hashref with -the following elements. - -=over - -=item B<url>: service URL as passed to B<efa_url> - -=item B<name>: Name of the entity operating this service - -=item B<shortname>: Short name of the entity - -=item B<encoding>: Server-side encoding override for B<efa_encoding> (optional) - -=back - -=item Travel::Status::DE::EFA::service(I<$service>) - -Returns a hashref describing the service I<$service>, or undef if it is not -known. See B<get_efa_urls> for the hashref layout. -  =back  =head1 DIAGNOSTICS 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..be3bffb --- /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; +} + +my %efa_instance = ( +	BSVG => { +		url  => 'https://bsvg.efa.de/bsvagstd', +		name => 'Braunschweiger Verkehrs-GmbH', +	}, +	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 => { +		url  => 'https://efa.mvv-muenchen.de/mobile', +		name => 'Münchner Verkehrs- und Tarifverbund', +	}, +	NVBW => { +		url  => 'https://www.efa-bw.de/nvbw', +		name => 'Nahverkehrsgesellschaft Baden-Württemberg', +	}, +	VAG => { +		url  => 'https://efa.vagfr.de/vagfr3', +		name => 'Freiburger Verkehrs AG', +	}, +	VGN => { +		url  => 'https://efa.vgn.de/vgnExt_oeffi', +		name => 'Verkehrsverbund Grossraum Nuernberg', +	}, + +	# HTTPS: certificate verification fails +	VMV => { +		url  => 'http://efa.vmv-mbh.de/vmv', +		name => 'Verkehrsgesellschaft Mecklenburg-Vorpommern', +	}, +	VRN => { +		url  => 'https://www.vrn.de/mngvrn/', +		name => 'Verkehrsverbund Rhein-Neckar', +	}, +	VRR => { +		url  => 'https://efa.vrr.de/vrr', +		name => 'Verkehrsverbund Rhein-Ruhr', +	}, +	VRR2 => { +		url  => 'https://app.vrr.de/standard', +		name => 'Verkehrsverbund Rhein-Ruhr (alternative)', +	}, +	VRR3 => { +		url  => 'https://efa.vrr.de/rbgstd3', +		name => 'Verkehrsverbund Rhein-Ruhr (alternative alternative)', +	}, +	VVO => { +		url  => 'https://efa.vvo-online.de/VMSSL3', +		name => 'Verkehrsverbund Oberelbe', +	}, +	VVS => { +		url  => 'https://www2.vvs.de/vvs', +		name => 'Verkehrsverbund Stuttgart', +	}, + +); + +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.00'; + +# 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 );  | 
