From 915bad108d838716c17ac605d13d59624b2bc539 Mon Sep 17 00:00:00 2001 From: Derf Null Date: Fri, 7 Apr 2023 14:49:32 +0200 Subject: add geoSearch mode --- lib/Travel/Status/DE/HAFAS.pm | 145 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 120 insertions(+), 25 deletions(-) (limited to 'lib') diff --git a/lib/Travel/Status/DE/HAFAS.pm b/lib/Travel/Status/DE/HAFAS.pm index da6eb47..9bf33f1 100644 --- a/lib/Travel/Status/DE/HAFAS.pm +++ b/lib/Travel/Status/DE/HAFAS.pm @@ -192,8 +192,8 @@ sub new { $ua->env_proxy; } - if ( not $conf{station} and not $conf{journey} ) { - confess('station or journey must be specified'); + if ( not( $conf{station} or $conf{journey} or $conf{geoSearch} ) ) { + confess('station / journey / geoSearch must be specified'); } if ( not defined $service ) { @@ -238,6 +238,37 @@ sub new { %{ $hafas_instance{$service}{request} } }; } + elsif ( $conf{geoSearch} ) { + $req = { + svcReqL => [ + { + cfg => { polyEnc => 'GPA' }, + meth => 'LocGeoPos', + req => { + ring => { + cCrd => { + x => int( $conf{geoSearch}{lon} * 1e6 ), + y => int( $conf{geoSearch}{lat} * 1e6 ), + }, + maxDist => -1, + minDist => 0, + }, + locFltrL => [ + { + type => "PROD", + mode => "INC", + value => $self->mot_mask + } + ], + getPOIs => \0, + getStops => \1, + maxLoc => 10, + } + } + ], + %{ $hafas_instance{$service}{request} } + }; + } else { my $date = ( $conf{datetime} // $now )->strftime('%Y%m%d'); my $time = ( $conf{datetime} // $now )->strftime('%H%M%S'); @@ -340,6 +371,9 @@ sub new { if ( $conf{journey} ) { $self->parse_journey; } + elsif ( $conf{geoSearch} ) { + $self->parse_geosearch; + } else { $self->parse_board; } @@ -366,6 +400,9 @@ sub new_p { if ( $conf{journey} ) { $self->parse_journey; } + elsif ( $conf{geoSearch} ) { + $self->parse_geosearch; + } else { $self->parse_board; } @@ -575,6 +612,35 @@ sub add_message { return $message; } +sub parse_geosearch { + my ($self) = @_; + + $self->{results} = []; + + if ( $self->{errstr} ) { + return $self; + } + + my @refLocL = @{ $self->{raw_json}{svcResL}[0]{res}{common}{locL} // [] }; + my @locL = @{ $self->{raw_json}{svcResL}[0]{res}{locL} // [] }; + + for my $loc (@locL) { + push( + @{ $self->{results} }, + { + eva => 0 + $loc->{extId}, + name => $loc->{name}, + lat => $loc->{crd}{x} * 1e-6, + lon => $loc->{crd}{y} * 1e-6, + weight => $loc->{wt}, + distance_m => $loc->{dist}, + } + ); + } + + return $self; +} + sub parse_journey { my ($self) = @_; @@ -603,6 +669,8 @@ sub parse_journey { polyline => \@polyline, hafas => $self, ); + + return $self; } sub parse_board { @@ -810,8 +878,9 @@ version 4.08 Travel::Status::DE::HAFAS is an interface to HAFAS-based arrival/departure monitors using the mgate.exe interface. -It can report departures/arrivals at a specific station, or provide details -about a specific journey. It supports non-blocking operation via promises. +It can report departures/arrivals at a specific station, search for stations, +or provide details about a specific journey. It supports non-blocking operation +via promises. =head1 METHODS @@ -819,11 +888,11 @@ about a specific journey. It supports non-blocking operation via promises. =item my $status = Travel::Status::DE::HAFAS->new(I<%opt>) -Requests departures/arrivals/journey as specified by I and returns a new +Requests item(s) as specified by I and returns a new Travel::Status::DE::HAFAS element with the results. Dies if the wrong I were passed. -I must contain either a B or a B flag: +I must contain either a B, a B, or a B flag: =over @@ -834,6 +903,11 @@ Request station board (arrivals or departures) for I, e.g. "Essen HBf" EVA ID (e.g. 8000080 for Dortmund Hbf). Results are available via C<< $status->results >>. +=item B => B<{> B => I, B => I B<}> + +Search for stations near I, I. +Results are available via C<< $status->results >>. + =item B => B<{> B => I [, B => I ] B<}> Request details about the journey identified by I and I. @@ -841,14 +915,16 @@ The result is available via C<< $status->result >>. =back -The following optional flags may be set: +The following optional flags may be set. +Values in brackets indicate flags that are only relevant in certain request +modes, e.g. geoSearch or journey. =over -=item B => I +=item B => I (station) Request arrivals (if I is true) rather than departures (if I is -false or B is not specified). Only relevant in station board mode. +false or B is not specified). =item B => I @@ -856,41 +932,37 @@ Store HAFAS replies in the provided cache object. This module works with real-time data, so the object should be configured for an expiry of one to two minutes. -=item B => I +=item B => I (station) -Date and time to report for. Defaults to now. Only relevant in station board mode. +Date and time to report for. Defaults to now. -=item B => [I, I, ...] +=item B => [I, I, ...] (geoSearch, station) By default, all modes of transport (trains, trams, buses etc.) are returned. If this option is set, all modes appearing in I, I, ... will be excluded. The supported modes depend on B, use B or B to get the supported values. -Only relevant in station board mode. -=item B => [I, I, ...] +=item B => [I, I, ...] (geoSearch, station) If this option is set, only the modes of transport appearing in I, I, ... will be returned. The supported modes depend on B, use B or B to get the supported values. -Only relevant in station board mode. -=item B => I +=item B => I (station) Request arrivals/departures that occur up to I minutes after the specified datetime. Default: -1 (do not limit results by time). -Only relevant in station board mode. =item B => I<\%hashref> Passed on to C<< LWP::UserAgent->new >>. Defaults to C<< { timeout => 10 } >>, pass an empty hashref to call the LWP::UserAgent constructor without arguments. -=item B => I +=item B => I (geoSearch, station) Request up to I results. Default: 30. -Only relevant in station board mode. =item B => I @@ -898,10 +970,9 @@ Request results from I, defaults to "DB". See B (and C<< hafas-m --list >>) for a list of supported services. -=item B => I +=item B => I (journey) Request a polyline (series of geo-coordinates) indicating the train's route. -Only relevant in journey mode. =back @@ -936,18 +1007,42 @@ as string. If no backend error occurred, returns undef. In case of an error in the HTTP request or HAFAS backend, returns a string describing it. If no error occurred, returns undef. -=item $status->results +=item $status->results (geoSearch) + +Returns a list of stations. Each list element is a hash ref with the following +keys. + +=over + +=item * eva (identifier / EVA code) + +=item * name + +=item * lat (latitude) + +=item * lon (longitude) + +=item * distance_m (distance from requested coordinates, in meters) + +=item * weight (relevance / importance of result, unknown metric) + +=back + +If no matching results were found or the parser / http request failed, returns +an empty list. + +=item $status->results (station) Returns a list of arrivals/departures. Each list element is a -Travel::Status::DE::HAFAS::Journey(3pm) object. Unavailable in journey mode. +Travel::Status::DE::HAFAS::Journey(3pm) object. If no matching results were found or the parser / http request failed, returns undef. -=item $status->result +=item $status->result (journey) Returns a single Travel::Status::DE::HAFAS::Journey(3pm) object that describes -the requested journey. Unavailable in station board mode. +the requested journey. If no result was found or the parser / http request failed, returns undef. -- cgit v1.2.3