abgespaced

An API that combines The DB Bahnhof API and the Space API
git clone git://archive.git.mtrnord.blog/MTRNord/abgespaced.git
Log | Files | Refs

commit 7937f1ce88b0ca92b8d98a3414e3b09695b9b61b
Author: Marcel <marcel@radzio-sh.de>
Date:   Sat, 27 Jul 2019 10:35:14 +0200

initial comit

Diffstat:
A.gitignore | 14++++++++++++++
A.idea/misc.xml | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.idea/modules.xml | 9+++++++++
A.idea/workspace.xml | 581+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ACargo.toml | 19+++++++++++++++++++
Aabgespaced.iml | 16++++++++++++++++
Abahn_definitions/.graphqlconfig | 16++++++++++++++++
Abahn_definitions/nearby.graphql | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Abahn_definitions/schema.graphql | 389+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abahn_definitions/search.graphql | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Anearby.json | 2++
Asearch.json | 2++
Asrc/api_provider.rs | 172+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/bahnapi.rs | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main.rs | 19+++++++++++++++++++
Asrc/spaceapi.rs | 208+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
16 files changed, 1738 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,14 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it +for libraries +# More information here +https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk +/src/key.txt +tmp diff --git a/.idea/misc.xml b/.idea/misc.xml @@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="NodePackageJsonFileManager"> + <packageJsonPaths /> + </component> + <component name="ProjectInspectionProfilesVisibleTreeState"> + <entry key="Project Default"> + <profile-state> + <expanded-state> + <State> + <id /> + </State> + <State> + <id>Abstraction issuesJava</id> + </State> + <State> + <id>Android</id> + </State> + <State> + <id>Android &gt; Lint &gt; Correctness</id> + </State> + <State> + <id>Android &gt; Lint &gt; Correctness &gt; Messages</id> + </State> + <State> + <id>Android &gt; Lint &gt; Internationalization</id> + </State> + <State> + <id>Android &gt; Lint &gt; Performance</id> + </State> + <State> + <id>Android &gt; Lint &gt; Security</id> + </State> + <State> + <id>Android Lint for Kotlin</id> + </State> + <State> + <id>CollectionsScala</id> + </State> + <State> + <id>Compiler issuesJava</id> + </State> + <State> + <id>Declaration redundancyJava</id> + </State> + <State> + <id>GeneralJavaScript</id> + </State> + <State> + <id>Guice Inspections</id> + </State> + <State> + <id>Internationalization issuesJava</id> + </State> + <State> + <id>J2ME issuesJava</id> + </State> + <State> + <id>JUnit issuesJava</id> + </State> + <State> + <id>Java</id> + </State> + <State> + <id>Java EE issues</id> + </State> + <State> + <id>JavaScript</id> + </State> + <State> + <id>OtherCollectionsScala</id> + </State> + <State> + <id>Pattern Validation</id> + </State> + <State> + <id>Performance issuesJava</id> + </State> + <State> + <id>Probable bugsJava</id> + </State> + <State> + <id>Properties FilesJava</id> + </State> + <State> + <id>Resource management issuesJava</id> + </State> + <State> + <id>Scala</id> + </State> + <State> + <id>Serialization issuesJava</id> + </State> + <State> + <id>TestNGJava</id> + </State> + <State> + <id>Threading issuesJava</id> + </State> + <State> + <id>Verbose or redundant code constructsJava</id> + </State> + <State> + <id>XML</id> + </State> + <State> + <id>XSLT</id> + </State> + </expanded-state> + </profile-state> + </entry> + </component> + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK"> + <output url="file://$PROJECT_DIR$/out" /> + </component> +</project> +\ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ProjectModuleManager"> + <modules> + <module fileurl="file://$PROJECT_DIR$/abgespaced.iml" filepath="$PROJECT_DIR$/abgespaced.iml" /> + </modules> + </component> +</project> +\ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml @@ -0,0 +1,580 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="CargoProjects"> + <cargoProject FILE="$PROJECT_DIR$/Cargo.toml" /> + </component> + <component name="ChangeListManager"> + <list default="true" id="1588daaa-dae2-4b3c-9939-767f8d306ac2" name="Default Changelist" comment="" /> + <ignored path="$PROJECT_DIR$/out/" /> + <ignored path="$PROJECT_DIR$/target/" /> + <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" /> + <option name="SHOW_DIALOG" value="false" /> + <option name="HIGHLIGHT_CONFLICTS" value="true" /> + <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" /> + <option name="LAST_RESOLUTION" value="IGNORE" /> + </component> + <component name="DefaultGradleProjectSettings"> + <option name="isMigrated" value="true" /> + </component> + <component name="FileEditorManager"> + <leaf SIDE_TABS_SIZE_LIMIT_KEY="300"> + <file pinned="false" current-in-tab="true"> + <entry file="file://$PROJECT_DIR$/src/api_provider.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="245"> + <caret line="99" column="55" lean-forward="true" selection-start-line="99" selection-start-column="55" selection-end-line="99" selection-end-column="55" /> + <folding> + <element signature="e#1393#1394#0" expanded="true" /> + <element signature="e#1415#1416#0" expanded="true" /> + <element signature="e#3960#3961#0" expanded="true" /> + <element signature="e#4010#4011#0" expanded="true" /> + <element signature="e#4183#4184#0" expanded="true" /> + <element signature="e#4219#4220#0" expanded="true" /> + <element signature="e#4404#4405#0" expanded="true" /> + <element signature="e#4440#4441#0" expanded="true" /> + </folding> + </state> + </provider> + </entry> + </file> + <file pinned="false" current-in-tab="false"> + <entry file="file://$PROJECT_DIR$/bahn_definitions/nearby.graphql"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="229"> + <caret line="30" column="29" selection-start-line="30" selection-start-column="16" selection-end-line="30" selection-end-column="29" /> + </state> + </provider> + </entry> + </file> + </leaf> + </component> + <component name="FileTemplateManagerImpl"> + <option name="RECENT_TEMPLATES"> + <list> + <option value="GraphQL File" /> + <option value="Rust File" /> + </list> + </option> + </component> + <component name="FindInProjectRecents"> + <findStrings> + <find>schema</find> + <find>Search</find> + <find>stations</find> + <find>nearby</find> + <find>occupancy</find> + <find>No</find> + <find>info</find> + <find>get_spaces</find> + <find>from_re</find> + <find>find</find> + </findStrings> + </component> + <component name="IdeDocumentHistory"> + <option name="CHANGED_PATHS"> + <list> + <option value="$PROJECT_DIR$/src/flughafen.json.graphql" /> + <option value="$PROJECT_DIR$/src/flughafen.json" /> + <option value="$PROJECT_DIR$/src/flughafen.graphql" /> + <option value="$PROJECT_DIR$/src/search.graphql" /> + <option value="$PROJECT_DIR$/src/.graphqlconfig" /> + <option value="$PROJECT_DIR$/src/nearby.graphql" /> + <option value="$PROJECT_DIR$/src/schema.graphql" /> + <option value="$PROJECT_DIR$/src/bahnapi.rs" /> + <option value="$PROJECT_DIR$/Cargo.toml" /> + <option value="$PROJECT_DIR$/src/main.rs" /> + <option value="$PROJECT_DIR$/src/spaceapi.rs" /> + <option value="$PROJECT_DIR$/src/api_provider.rs" /> + </list> + </option> + </component> + <component name="MacroExpansionManager"> + <option name="directoryName" value="sNmJjqKd" /> + </component> + <component name="ProjectFrameBounds" extendedState="6"> + <option name="x" value="1268" /> + <option name="width" value="1302" /> + <option name="height" value="732" /> + </component> + <component name="ProjectView"> + <navigator proportions="" version="1"> + <foldersAlwaysOnTop value="true" /> + </navigator> + <panes> + <pane id="ProjectPane"> + <subPane> + <expand> + <path> + <item name="abgespaced" type="b2602c69:ProjectViewProjectNode" /> + <item name="abgespaced" type="462c0819:PsiDirectoryNode" /> + </path> + <path> + <item name="abgespaced" type="b2602c69:ProjectViewProjectNode" /> + <item name="abgespaced" type="462c0819:PsiDirectoryNode" /> + <item name="bahn_definitions" type="462c0819:PsiDirectoryNode" /> + </path> + <path> + <item name="abgespaced" type="b2602c69:ProjectViewProjectNode" /> + <item name="abgespaced" type="462c0819:PsiDirectoryNode" /> + <item name="src" type="462c0819:PsiDirectoryNode" /> + </path> + </expand> + <select /> + </subPane> + </pane> + <pane id="Scope" /> + <pane id="PackagesPane" /> + </panes> + </component> + <component name="PropertiesComponent"> + <property name="WebServerToolWindowFactoryState" value="false" /> + <property name="android.sdk.path" value="$USER_HOME$/AppData/Local/Android/Sdk" /> + <property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" /> + <property name="nodejs_npm_path_reset_for_default_project" value="true" /> + <property name="org.rust.cargo.project.model.PROJECT_DISCOVERY" value="true" /> + <property name="project.structure.last.edited" value="Libraries" /> + <property name="project.structure.proportion" value="0.15" /> + <property name="project.structure.side.proportion" value="0.2" /> + <property name="settings.editor.selected.configurable" value="AndroidSdkUpdater" /> + <property name="show.migrate.to.gradle.popup" value="false" /> + </component> + <component name="RecentsManager"> + <key name="MoveFile.RECENT_KEYS"> + <recent name="C:\Users\marce\IdeaProjects\abgespaced\bahn_definitions" /> + </key> + </component> + <component name="RunDashboard"> + <option name="ruleStates"> + <list> + <RuleState> + <option name="name" value="ConfigurationTypeDashboardGroupingRule" /> + </RuleState> + <RuleState> + <option name="name" value="StatusDashboardGroupingRule" /> + </RuleState> + </list> + </option> + </component> + <component name="RunManager"> + <configuration default="true" type="TestNG" factoryName="TestNG"> + <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" /> + <module name="" /> + <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" /> + <option name="ALTERNATIVE_JRE_PATH" /> + <option name="SUITE_NAME" /> + <option name="PACKAGE_NAME" /> + <option name="MAIN_CLASS_NAME" /> + <option name="METHOD_NAME" /> + <option name="GROUP_NAME" /> + <option name="TEST_OBJECT" value="CLASS" /> + <option name="VM_PARAMETERS" value="-ea" /> + <option name="PARAMETERS" /> + <option name="WORKING_DIRECTORY" value="$MODULE_DIR$" /> + <option name="OUTPUT_DIRECTORY" /> + <option name="ANNOTATION_TYPE" /> + <option name="ENV_VARIABLES" /> + <option name="PASS_PARENT_ENVS" value="true" /> + <option name="TEST_SEARCH_SCOPE"> + <value defaultName="singleModule" /> + </option> + <option name="USE_DEFAULT_REPORTERS" value="false" /> + <option name="PROPERTIES_FILE" /> + <envs /> + <properties /> + <listeners /> + <method /> + </configuration> + <configuration default="true" type="Applet"> + <option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" /> + <method v="2"> + <option name="Make" enabled="true" /> + </method> + </configuration> + <configuration default="true" type="Application" factoryName="Application"> + <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" /> + <method v="2"> + <option name="Make" enabled="true" /> + </method> + </configuration> + <configuration default="true" type="JUnit" factoryName="JUnit"> + <option name="TEST_OBJECT" value="class" /> + <option name="WORKING_DIRECTORY" value="$MODULE_DIR$" /> + <method v="2"> + <option name="Make" enabled="true" /> + </method> + </configuration> + <configuration default="true" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType"> + <module name="" /> + <option name="VM_PARAMETERS" value="-Xmx512m -Xms256m -XX:MaxPermSize=250m -ea" /> + <option name="PROGRAM_PARAMETERS" /> + <predefined_log_file enabled="true" id="idea.log" /> + <method v="2"> + <option name="Make" enabled="true" /> + </method> + </configuration> + </component> + <component name="RustProjectSettings"> + <option name="toolchainHomeDirectory" value="$USER_HOME$/.cargo/bin" /> + <option name="version" value="2" /> + </component> + <component name="SvnConfiguration"> + <configuration>C:\Users\marce\AppData\Roaming\Subversion</configuration> + </component> + <component name="TaskManager"> + <task active="true" id="Default" summary="Default task"> + <changelist id="1588daaa-dae2-4b3c-9939-767f8d306ac2" name="Default Changelist" comment="" /> + <created>1563565755872</created> + <option name="number" value="Default" /> + <option name="presentableId" value="Default" /> + <updated>1563565755872</updated> + <workItem from="1563565762152" duration="1832000" /> + <workItem from="1563569982833" duration="25555000" /> + </task> + <servers /> + </component> + <component name="TimeTrackingManager"> + <option name="totallyTimeSpent" value="27387000" /> + </component> + <component name="ToolWindowManager"> + <frame x="-7" y="-7" width="1477" height="837" extended-state="6" /> + <editor active="true" /> + <layout> + <window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.25299507" /> + <window_info id="Structure" order="1" side_tool="true" weight="0.25" /> + <window_info id="Designer" order="2" /> + <window_info id="Learn" order="3" /> + <window_info id="Favorites" order="4" side_tool="true" /> + <window_info anchor="bottom" id="GraphQL" order="0" weight="0.32941177" /> + <window_info anchor="bottom" id="Message" order="1" /> + <window_info anchor="bottom" id="Find" order="2" weight="0.32941177" /> + <window_info anchor="bottom" id="Run" order="3" weight="0.32941177" /> + <window_info anchor="bottom" id="Debug" order="4" weight="0.4" /> + <window_info anchor="bottom" id="Cvs" order="5" weight="0.25" /> + <window_info anchor="bottom" id="Inspection" order="6" weight="0.4" /> + <window_info anchor="bottom" id="TODO" order="7" /> + <window_info anchor="bottom" id="Docker" order="8" show_stripe_button="false" /> + <window_info anchor="bottom" id="Version Control" order="9" /> + <window_info anchor="bottom" id="Tool Output" order="10" /> + <window_info anchor="bottom" id="Database Changes" order="11" /> + <window_info anchor="bottom" id="Terminal" order="12" /> + <window_info anchor="bottom" id="Event Log" order="13" side_tool="true" weight="0.9558824" /> + <window_info anchor="bottom" id="Flutter Performance" order="14" side_tool="true" /> + <window_info anchor="bottom" id="ANTLR Preview" order="15" /> + <window_info anchor="right" id="Commander" order="0" weight="0.4" /> + <window_info anchor="right" id="Ant Build" order="1" weight="0.25" /> + <window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" /> + <window_info anchor="right" id="Palette&#9;" order="3" /> + <window_info anchor="right" id="Cargo" order="4" /> + <window_info anchor="right" id="Flutter Inspector" order="5" /> + <window_info anchor="right" id="Maven" order="6" /> + <window_info anchor="right" id="Flutter Outline" order="7" /> + <window_info anchor="right" id="Database" order="8" /> + </layout> + </component> + <component name="editorHistoryManager"> + <entry file="file://$PROJECT_DIR$/src/flughafen.json.graphql"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="227"> + <caret line="362" lean-forward="true" selection-end-line="362" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/foo"> + <provider selected="true" editor-type-id="text-editor"> + <state> + <caret column="104" lean-forward="true" selection-start-column="104" selection-end-column="104" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/bahn_definitions/search.graphql"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="144"> + <caret line="6" column="23" lean-forward="true" selection-end-line="47" selection-end-column="1" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/bahn_definitions/.graphqlconfig"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="216"> + <caret line="9" column="10" selection-start-line="9" selection-start-column="10" selection-end-line="9" selection-end-column="10" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/abgespaced.iml"> + <provider selected="true" editor-type-id="text-editor" /> + </entry> + <entry file="file://$PROJECT_DIR$/search.json"> + <provider selected="true" editor-type-id="text-editor"> + <state> + <caret column="38" selection-start-column="38" selection-end-column="38" /> + </state> + </provider> + </entry> + <entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_json-1.0.40/src/map.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="384"> + <caret line="28" column="26" selection-start-line="28" selection-start-column="26" selection-end-line="28" selection-end-column="26" /> + </state> + </provider> + </entry> + <entry file="file://$USER_HOME$/.rustup/toolchains/nightly-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/liballoc/collections/btree/map.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="212"> + <caret line="122" column="19" selection-start-line="122" selection-start-column="11" selection-end-line="122" selection-end-column="19" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/bahn_definitions/schema.graphql"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="175"> + <caret line="246" column="25" lean-forward="true" selection-start-line="246" selection-start-column="25" selection-end-line="246" selection-end-column="25" /> + </state> + </provider> + </entry> + <entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/juniper_rocket-0.4.0/src/lib.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="212"> + <caret line="166" column="11" selection-start-line="166" selection-start-column="11" selection-end-line="166" selection-end-column="11" /> + </state> + </provider> + </entry> + <entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.4.7/src/kv/key.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="212"> + <caret line="38" column="20" lean-forward="true" selection-start-line="38" selection-start-column="19" selection-end-line="38" selection-end-column="20" /> + </state> + </provider> + </entry> + <entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.4.7/src/kv/source.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="92"> + <caret line="104" column="1" lean-forward="true" selection-start-line="104" selection-end-line="108" /> + </state> + </provider> + </entry> + <entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/http-0.1.17/src/status.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="205"> + <caret line="53" selection-start-line="53" selection-end-line="53" /> + </state> + </provider> + </entry> + <entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_json-1.0.40/src/value/mod.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="567"> + <caret line="504" column="17" selection-start-line="504" selection-start-column="17" selection-end-line="504" selection-end-column="17" /> + </state> + </provider> + </entry> + <entry file="file://$USER_HOME$/.rustup/toolchains/nightly-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/iter/traits/iterator.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="240"> + <caret line="1848" column="65" lean-forward="true" selection-start-line="1848" selection-start-column="65" selection-end-line="1848" selection-end-column="65" /> + <folding> + <element signature="e#58#59#0" expanded="true" /> + <element signature="e#82#83#0" expanded="true" /> + </folding> + </state> + </provider> + </entry> + <entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/juniper-0.13.0/src/types/scalars.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="236"> + <caret line="282" column="28" lean-forward="true" selection-start-line="282" selection-start-column="28" selection-end-line="282" selection-end-column="28" /> + </state> + </provider> + </entry> + <entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/juniper-0.13.0/src/executor/mod.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="188"> + <caret line="189" column="41" lean-forward="true" selection-start-line="189" selection-start-column="28" selection-end-line="189" selection-end-column="41" /> + </state> + </provider> + </entry> + <entry file="file://$USER_HOME$/.rustup/toolchains/nightly-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libstd/fs.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="212"> + <caret line="1007" column="44" selection-start-line="1007" selection-start-column="44" selection-end-line="1007" selection-end-column="44" /> + </state> + </provider> + </entry> + <entry file="file://$USER_HOME$/.rustup/toolchains/nightly-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libstd/time.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="229"> + <caret line="382" column="43" selection-start-line="382" selection-start-column="43" selection-end-line="382" selection-end-column="43" /> + <folding> + <element signature="e#8337#8338#0" expanded="true" /> + <element signature="e#8374#8375#0" expanded="true" /> + </folding> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/Cargo.toml"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="408"> + <caret line="17" column="20" selection-start-line="17" selection-start-column="20" selection-end-line="17" selection-end-column="20" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/tmp/spaces/space_57North Hacklab.json"> + <provider selected="true" editor-type-id="text-editor" /> + </entry> + <entry file="file://$PROJECT_DIR$/src/main.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="96"> + <caret line="4" column="24" selection-start-line="4" selection-start-column="24" selection-end-line="4" selection-end-column="24" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/tmp/spaces/space_Hackeriet.json"> + <provider selected="true" editor-type-id="text-editor" /> + </entry> + <entry file="file://$PROJECT_DIR$/tmp/spaces/space_Entropia.json"> + <provider selected="true" editor-type-id="text-editor"> + <state> + <caret column="35" lean-forward="true" selection-start-column="35" selection-end-column="35" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/tmp/spaces/space__dev_tal.json"> + <provider selected="true" editor-type-id="text-editor"> + <state> + <caret column="30" selection-start-column="30" selection-end-column="30" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/tmp/spaces/space_[hsmr].json"> + <provider selected="true" editor-type-id="text-editor"> + <state> + <caret column="35" selection-start-column="35" selection-end-column="35" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/tmp/spaces/space_57North Hacklab.json"> + <provider selected="true" editor-type-id="text-editor" /> + </entry> + <entry file="file://$USER_HOME$/.rustup/toolchains/nightly-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/time.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="205"> + <caret line="71" column="11" selection-start-line="71" selection-start-column="11" selection-end-line="71" selection-end-column="11" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/nearby.json"> + <provider selected="true" editor-type-id="text-editor"> + <state> + <caret column="43" selection-end-column="14293" /> + </state> + </provider> + </entry> + <entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/graphql_client-0.8.0/src/lib.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="205"> + <caret line="279" column="23" selection-start-line="279" selection-start-column="23" selection-end-line="279" selection-end-column="23" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/src/bahnapi.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="277"> + <caret line="47" column="24" lean-forward="true" selection-start-line="47" selection-start-column="24" selection-end-line="47" selection-end-column="24" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/src/spaceapi.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="194"> + <caret line="154" column="7" selection-start-line="154" selection-start-column="7" selection-end-line="154" selection-end-column="7" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/tmp/spaces.json"> + <provider selected="true" editor-type-id="text-editor"> + <state> + <caret column="7" selection-start-column="7" selection-end-column="7" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/tmp/spaces/space_verschwoerhaus.json"> + <provider selected="true" editor-type-id="text-editor"> + <state> + <caret column="30" selection-start-column="30" selection-end-column="30" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/bahn_definitions/nearby.graphql"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="229"> + <caret line="30" column="29" selection-start-line="30" selection-start-column="16" selection-end-line="30" selection-end-column="29" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/src/api_provider.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="245"> + <caret line="99" column="55" lean-forward="true" selection-start-line="99" selection-start-column="55" selection-end-line="99" selection-end-column="55" /> + <folding> + <element signature="e#1393#1394#0" expanded="true" /> + <element signature="e#1415#1416#0" expanded="true" /> + <element signature="e#3960#3961#0" expanded="true" /> + <element signature="e#4010#4011#0" expanded="true" /> + <element signature="e#4183#4184#0" expanded="true" /> + <element signature="e#4219#4220#0" expanded="true" /> + <element signature="e#4404#4405#0" expanded="true" /> + <element signature="e#4440#4441#0" expanded="true" /> + </folding> + </state> + </provider> + </entry> + </component> + <component name="masterDetails"> + <states> + <state key="GlobalLibrariesConfigurable.UI"> + <settings> + <splitter-proportions> + <option name="proportions"> + <list> + <option value="0.2" /> + </list> + </option> + </splitter-proportions> + </settings> + </state> + <state key="JdkListConfigurable.UI"> + <settings> + <last-edited>1.8</last-edited> + <splitter-proportions> + <option name="proportions"> + <list> + <option value="0.2" /> + </list> + </option> + </splitter-proportions> + </settings> + </state> + <state key="ProjectJDKs.UI"> + <settings> + <last-edited>1.8</last-edited> + <splitter-proportions> + <option name="proportions"> + <list> + <option value="0.2" /> + </list> + </option> + </splitter-proportions> + </settings> + </state> + <state key="ProjectLibrariesConfigurable.UI"> + <settings> + <splitter-proportions> + <option name="proportions"> + <list> + <option value="0.2" /> + </list> + </option> + </splitter-proportions> + </settings> + </state> + </states> + </component> +</project> +\ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "abgespaced" +version = "0.1.0" +authors = ["Marcel <marcel@radzio-sh.de>"] +edition = "2018" + +[dependencies] +graphql_client = "0.8.0" +serde = "1.0" +serde_derive = "1.0" +serde_json = "1.0" +reqwest = "^0.9.0" +failure = "*" +juniper = "0.13.0" +juniper_rocket = "0.4.0" +rocket = "0.4.0" +log = "0.4.7" +env_logger = "0.6.2" +\ No newline at end of file diff --git a/abgespaced.iml b/abgespaced.iml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="RUST_MODULE" version="4"> + <component name="NewModuleRootManager" inherit-compiler-output="true"> + <exclude-output /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/examples" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" /> + <sourceFolder url="file://$MODULE_DIR$/benches" isTestSource="true" /> + <excludeFolder url="file://$MODULE_DIR$/target" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module> +\ No newline at end of file diff --git a/bahn_definitions/.graphqlconfig b/bahn_definitions/.graphqlconfig @@ -0,0 +1,15 @@ +{ + "name": "DBGraphQL Schema", + "schemaPath": "schema.graphql", + "extensions": { + "endpoints": { + "Default GraphQL Endpoint": { + "url": "https://api.deutschebahn.com/free1bahnql/v1/graphql", + "headers": { + "Accept": "application/json" + }, + "introspect": false + } + } + } +} +\ No newline at end of file diff --git a/bahn_definitions/nearby.graphql b/bahn_definitions/nearby.graphql @@ -0,0 +1,48 @@ +query Nearby($latitude: Float!, $longitude: Float!, $radius: Int = 10000, $count: Int = 10){ + nearby(latitude: $latitude, longitude: $longitude, radius: $radius) { + stations(count: $count) { + name + primaryEvaId + hasLocalPublicTransport + hasTaxiRank + hasSteplessAccess + hasWiFi + picture { + id + url + license + photographer { + name + url + } + } + location { + latitude + longitude + } + timetable { + nextArrivals{ + type + trainNumber + platform + time + stops + } + nextDepatures { + type + trainNumber + platform + time + stops + } + } + tracks { + platform + number + name + length + height + } + } + } +} +\ No newline at end of file diff --git a/bahn_definitions/schema.graphql b/bahn_definitions/schema.graphql @@ -0,0 +1,388 @@ +schema { + query: Query +} + +type Query { + routing(from: Int!, to: Int!): [Route!]! + + stationWithEvaId(evaId: Int!): Station + stationWithStationNumber(stationNumber: Int!): Station + stationWithRill100(rill100: String!): Station + + search(searchTerm: String): Searchable! + nearby(latitude: Float!, longitude: Float!, radius: Int = 10000): Nearby! + parkingSpace(id: Int): ParkingSpace +} + +type Route { + parts: [RoutePart!]! + from: Station + to: Station +} + +type RoutePart { + # Station where the part begins + from: Station! + to: Station! + delay: Int + product: Product + direction: String! + start: String! + end: String! + departingTrack: Track + arrivingTrack: Track +} + +type Product { + name: String + class: Int + productCode: Int + productName: String +} + +type Searchable { + stations: [Station!]! + operationLocations: [OperationLocation!]! +} + +type OperationLocation { + id: String + abbrev: String! + name: String! + shortName: String! + type: String! + status: String + locationCode: String + UIC: String! + regionId: String + validFrom: String! + validTill: String + timeTableRelevant: Boolean + borderStation: Boolean +} +type Station { + primaryEvaId: Int + stationNumber: Int + primaryRil100: String + name: String! + location: Location + category: Int! + priceCategory: Int! + hasParking: Boolean! + hasBicycleParking: Boolean! + hasLocalPublicTransport: Boolean! + hasPublicFacilities: Boolean! + hasLockerSystem: Boolean! + hasTaxiRank: Boolean! + hasTravelNecessities: Boolean! + hasSteplessAccess: String! + hasMobilityService: String! + federalState: String! + regionalArea: RegionalArea! + facilities: [Facility!]! + mailingAddress: MailingAddress! + DBInformationOpeningTimes: OpeningTimes + localServiceStaffAvailability: OpeningTimes + aufgabentraeger: StationContact! + timeTableOffice: StationContact + szentrale: StationContact! + stationManagement: StationContact! + timetable: Timetable! + parkingSpaces: [ParkingSpace!]! + hasSteamPermission: Boolean! + hasWiFi: Boolean! + hasTravelCenter: Boolean! + hasRailwayMission: Boolean! + hasDBLounge: Boolean! + hasLostAndFound: Boolean! + hasCarRental: Boolean! + tracks: [Track!]! + picture: Picture +} + +type Track { + platform: String! + number: String! + name: String! + # Length of the platform in cm + length: Int + # Height of the platform in cm + height: Int! +} + +type Location { + latitude: Float! + longitude: Float! +} + +type Facility { + description: String + type: FacilityType! + state: FacilityState! + equipmentNumber: Int + location: Location +} + +type Picture { + id: Int! + url: String! + license: String! + photographer: Photographer! +} + +type Photographer { + name: String! + url: String! +} + +enum FacilityState { + ACTIVE + INACTIVE + UNKNOWN +} + +enum FacilityType { + ESCALATOR + ELEVATOR +} + +type MailingAddress { + city: String! + zipcode: String! + street: String! +} + +type RegionalArea { + number: Int! + name: String! + shortName: String! +} + +type OpeningTimes { + monday: OpeningTime + tuesday: OpeningTime + wednesday: OpeningTime + thursday: OpeningTime + friday: OpeningTime + saturday: OpeningTime + sunday: OpeningTime + holiday: OpeningTime +} + +type OpeningTime { + from: String! + to: String! +} + +type StationContact { + name: String! + shortName: String + email: String + number: String + phoneNumber: String +} + +type Nearby { + stations (count: Int = 10, offset: Int = 0): [Station!]! + parkingSpaces (count: Int = 10, offset: Int = 0): [ParkingSpace!]! + travelCenters (count: Int = 10, offset: Int = 0): [TravelCenter!]! + flinksterCars (count: Int = 10, offset: Int = 0): [FlinksterCar!]! + bikes (count: Int = 10, offset: Int = 0): [FlinksterBike!]! +} + +type ParkingSpace { + type: String + id: Int! + name: String + label: String + spaceNumber: String + responsibility: String + source: String + nameDisplay: String + spaceType: String + spaceTypeEn: String + spaceTypeName: String + location: Location + url: String + operator: String + operatorUrl: String + address: MailingAddress + distance: String + facilityType: String + facilityTypeEn: String + openingHours: String + openingHoursEn: String + numberParkingPlaces: String + numberHandicapedPlaces: String + isSpecialProductDb: Boolean! + isOutOfService: Boolean! + station: Station + occupancy: Occupancy + outOfServiceText: String + outOfServiceTextEn: String + reservation: String + clearanceWidth: String + clearanceHeight: String + allowedPropulsions: String + hasChargingStation: String + tariffPrices: [ParkingPriceOption!]! + outOfService: Boolean! + isDiscountDbBahnCard: Boolean! + isMonthVendingMachine: Boolean! + isDiscountDbBahnComfort: Boolean! + isDiscountDbParkAndRail: Boolean! + isMonthParkAndRide: Boolean! + isMonthSeason: Boolean! + tariffDiscount: String + tariffFreeParkingTime: String + tariffDiscountEn: String + tariffPaymentOptions: String + tariffPaymentCustomerCards: String + tariffFreeParkingTimeEn: String + tariffPaymentOptionsEn: String + slogan: String + sloganEn: String +} + +type ParkingPriceOption { + id: Int! + duration: String! + price: Float +} + +type Occupancy { + validData: Boolean! + timestamp: String! + timeSegment: String! + category: Int! + text: String! +} + +type Timetable { + nextArrivals: [TrainInStation!]! + nextDepatures: [TrainInStation!]! +} + +type TrainInStation { + type: String! + trainNumber: String! + platform: String! + time: String! + stops: [String!]! +} + +type TravelCenter { + id: Int + name: String + address: MailingAddress + type: String + location: Location +} + +type FlinksterCar { + id: String! + name: String! + description: String! + attributes: CarAttributes! + location: Location! + priceOptions: [PriceOption]! + equipment: CarEquipment! + rentalModel: String! + parkingArea: FlinksterParkingArea! + category: String! + url: String! +} + +type FlinksterBike { + id: String! + url: String! + name: String! + description: String! + location: Location! + priceOptions: [PriceOption]! + attributes: BikeAttributes! + address: MailingAddress! + rentalModel: String! + type: String! + providerRentalObjectId: Int! + parkingArea: FlinksterParkingArea! + bookingUrl: String! +} + +type CarAttributes { + seats: Int! + color: String! + doors: Int! + transmissionType: String! + licensePlate: String + fillLevel: Int + fuel: String +} + +type CarEquipment { + cdPlayer: Boolean + airConditioning: Boolean + navigationSystem: Boolean + roofRailing: Boolean + particulateFilter: Boolean + audioInline: Boolean + tyreType: String + bluetoothHandsFreeCalling: Boolean + cruiseControl: Boolean + passengerAirbagTurnOff: Boolean + isofixSeatFittings: Boolean +} + +type FlinksterParkingArea { + id: String! + url: String! + name: String! + address: MailingAddress! + parkingDescription: String + accessDescription: String + locationDescription: String + publicTransport: String + provider: FlinksterProvider! + type: String! + position: Location! + GeoJSON: GeoJSON +} + +type GeoJSON { + type: String! + features: [GeoFeature!]! +} + +type GeoFeature { + type: String! + properties: GeoProperties! + geometry: GeoPolygon! +} + +type GeoPolygon { + type: String! + coordinates: [[[[Float]]]]! +} + +type GeoProperties { + name: String! +} + +type FlinksterProvider { + url: String! + areaId: Int! + networkIds: [Int!]! +} + +type BikeAttributes { + licensePlate: String! +} + +type PriceOption { + interval: Int + type: String! + grossamount: Float! + currency: String! + taxrate: Float! + preferredprice: Boolean! +} +\ No newline at end of file diff --git a/bahn_definitions/search.graphql b/bahn_definitions/search.graphql @@ -0,0 +1,48 @@ +query Search($searchTerm: String){ + search(searchTerm: $searchTerm) { + stations { + name + primaryEvaId + hasLocalPublicTransport + hasTaxiRank + hasSteplessAccess + hasWiFi + picture { + id + url + license + photographer { + name + url + } + } + location { + latitude + longitude + } + timetable { + nextArrivals{ + type + trainNumber + platform + time + stops + } + nextDepatures { + type + trainNumber + platform + time + stops + } + } + tracks { + platform + number + name + length + height + } + } + } +} +\ No newline at end of file diff --git a/nearby.json b/nearby.json @@ -0,0 +1 @@ +Response { data: Some(ResponseData { nearby: NearbyNearby { stations: [NearbyNearbyStations { name: "Flensburg", primary_eva_id: Some(8000103), has_local_public_transport: true, has_taxi_rank: true, has_stepless_access: "yes", has_wi_fi: false, picture: Some(NearbyNearbyStationsPicture { id: 1810, url: "https://fotos.railway-stations.org/fotos/de/1810_1.jpg", license: "CC0 1.0 Universell (CC0 1.0)", photographer: NearbyNearbyStationsPicturePhotographer { name: "@Frazer2", url: "https://twitter.com/frazer2" } }), location: Some(NearbyNearbyStationsLocation { latitude: 54.774039, longitude: 9.436526 }), timetable: NearbyNearbyStationsTimetable { next_arrivals: [NearbyNearbyStationsTimetableNextArrivals { type_: "RE", train_number: "21064", platform: "2", time: "Sat Jul 20 2019 11:42:00 GMT+0000 (UTC)", stops: ["Hamburg Hbf", "Hamburg Dammtor", "Elmshorn", "Neumünster", "Nortorf", "Rendsburg", "Owschlag", "Schleswig", "Jübek", "Tarp"] }, NearbyNearbyStationsTimetableNextArrivals { type_: "RE", train_number: "21914", platform: "4", time: "Sat Jul 20 2019 11:57:00 GMT+0000 (UTC)", stops: ["Eckernförde", "Rieseby", "Süderbrarup", "Sörup", "Husby"] }], next_depatures: [NearbyNearbyStationsTimetableNextDepatures { type_: "RE", train_number: "21923", platform: "4", time: "Sat Jul 20 2019 11:04:00 GMT+0000 (UTC)", stops: ["Husby", "Sörup", "Süderbrarup", "Rieseby", "Eckernförde"] }, NearbyNearbyStationsTimetableNextDepatures { type_: "RE", train_number: "21073", platform: "2", time: "Sat Jul 20 2019 11:15:00 GMT+0000 (UTC)", stops: ["Tarp", "Jübek", "Schleswig", "Owschlag", "Rendsburg", "Nortorf", "Neumünster", "Elmshorn", "Hamburg Dammtor", "Hamburg Hbf"] }] }, tracks: [NearbyNearbyStationsTracks { platform: "B01", number: "1", name: "Gleis 1", length: Some(324), height: 76 }, NearbyNearbyStationsTracks { platform: "B01", number: "2", name: "Gleis 2", length: Some(222), height: 76 }, NearbyNearbyStationsTracks { platform: "B02", number: "4", name: "Gleis 4", length: Some(285), height: 76 }, NearbyNearbyStationsTracks { platform: "B02", number: "5", name: "Gleis 5", length: Some(285), height: 76 }] }] } }), errors: None } +\ No newline at end of file diff --git a/search.json b/search.json @@ -0,0 +1 @@ +Response { data: Some(ResponseData { search: SearchSearch { stations: [SearchSearchStations { name: "Düsseldorf Flughafen", primary_eva_id: Some(8000082), has_local_public_transport: true, has_taxi_rank: true, has_stepless_access: "yes", has_wi_fi: true, picture: Some(SearchSearchStationsPicture { id: 1400, url: "https://fotos.railway-stations.org/fotos/de/1400_1.jpg", license: "CC0 1.0 Universell (CC0 1.0)", photographer: SearchSearchStationsPicturePhotographer { name: "@Dgerkrath", url: "https://twitter.com/Dgerkrath" } }), location: Some(SearchSearchStationsLocation { latitude: 51.292009, longitude: 6.786836 }), timetable: SearchSearchStationsTimetable { next_arrivals: [SearchSearchStationsTimetableNextArrivals { type_: "THA", train_number: "9473", platform: "5", time: "Fri Jul 19 2019 20:00:00 GMT+0000 (UTC)", stops: ["Paris Nord", "Bruxelles Midi", "Liège-Guillemins", "Aachen Hbf", "Köln Hbf", "Düsseldorf Hbf"] }, SearchSearchStationsTimetableNextArrivals { type_: "ERB", train_number: "89898", platform: "", time: "Fri Jul 19 2019 20:02:00 GMT+0000 (UTC)", stops: ["Hamm(Westf)", "Nordbögge", "Kamen", "Kamen-Methler", "Dortmund-Kurl", "Dortmund-Scharnhorst", "Dortmund Hbf", "Dortmund-Mengede", "Castrop-Rauxel Hbf", "Herne", "Wanne-Eickel Hbf", "Gelsenkirchen Hbf", "Essen-Altenessen", "Oberhausen Hbf", "Duisburg Hbf"] }, SearchSearchStationsTimetableNextArrivals { type_: "RE", train_number: "28534", platform: "5", time: "Fri Jul 19 2019 20:10:00 GMT+0000 (UTC)", stops: ["Koblenz Hbf", "Koblenz Stadtmitte", "Andernach", "Bad Breisig", "Sinzig(Rhein)", "Remagen", "Bonn-Bad Godesberg", "Bonn UN Campus", "Bonn Hbf", "Brühl", "Köln Süd", "Köln Hbf", "Köln Messe/Deutz", "Köln-Mülheim", "Leverkusen Mitte", "Düsseldorf-Benrath", "Düsseldorf Hbf"] }, SearchSearchStationsTimetableNextArrivals { type_: "Bus", train_number: "70198", platform: "", time: "Fri Jul 19 2019 20:11:00 GMT+0000 (UTC)", stops: ["Duisburg Hbf", "Duisburg-Schlenk", "Duisburg-Buchholz", "Duisburg-Großenbaum", "Duisburg-Rahm", "Angermund"] }, SearchSearchStationsTimetableNextArrivals { type_: "Bus", train_number: "71105", platform: "", time: "Fri Jul 19 2019 20:20:00 GMT+0000 (UTC)", stops: ["Düsseldorf-Unterrath"] }, SearchSearchStationsTimetableNextArrivals { type_: "RE", train_number: "10142", platform: "6", time: "Fri Jul 19 2019 20:26:00 GMT+0000 (UTC)", stops: ["Hamm(Westf)", "Kamen", "Dortmund-Kurl", "Dortmund-Scharnhorst", "Dortmund Hbf", "Gelsenkirchen Hbf", "Essen-Altenessen", "Oberhausen Hbf", "Duisburg Hbf"] }, SearchSearchStationsTimetableNextArrivals { type_: "RE", train_number: "10141", platform: "5", time: "Fri Jul 19 2019 20:28:00 GMT+0000 (UTC)", stops: ["Aachen Hbf", "Aachen-Rothe Erde", "Stolberg(Rheinl)Hbf", "Eschweiler Hbf", "Langerwehe", "Düren", "Horrem", "Köln-Ehrenfeld", "Köln Hbf", "Köln Messe/Deutz", "Köln-Mülheim", "Leverkusen Mitte", "Düsseldorf-Benrath", "Düsseldorf Hbf"] }, SearchSearchStationsTimetableNextArrivals { type_: "Bus", train_number: "71100", platform: "", time: "Fri Jul 19 2019 20:41:00 GMT+0000 (UTC)", stops: ["Duisburg Hbf", "Duisburg-Schlenk", "Duisburg-Buchholz", "Duisburg-Großenbaum", "Duisburg-Rahm", "Angermund"] }, SearchSearchStationsTimetableNextArrivals { type_: "Bus", train_number: "71107", platform: "", time: "Fri Jul 19 2019 20:50:00 GMT+0000 (UTC)", stops: ["Düsseldorf-Unterrath"] }, SearchSearchStationsTimetableNextArrivals { type_: "ERB", train_number: "89901", platform: "", time: "Fri Jul 19 2019 20:54:00 GMT+0000 (UTC)", stops: ["Düsseldorf Hbf"] }], next_depatures: [SearchSearchStationsTimetableNextDepatures { type_: "THA", train_number: "9473", platform: "5", time: "Fri Jul 19 2019 20:01:00 GMT+0000 (UTC)", stops: ["Duisburg Hbf", "Dortmund Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "ERB", train_number: "89898", platform: "", time: "Fri Jul 19 2019 20:04:00 GMT+0000 (UTC)", stops: ["Düsseldorf Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "Bus", train_number: "70198", platform: "", time: "Fri Jul 19 2019 20:11:00 GMT+0000 (UTC)", stops: ["Düsseldorf-Unterrath"] }, SearchSearchStationsTimetableNextDepatures { type_: "RE", train_number: "28534", platform: "5", time: "Fri Jul 19 2019 20:12:00 GMT+0000 (UTC)", stops: ["Duisburg Hbf", "Oberhausen Hbf", "Oberhausen-Sterkrade", "Oberhausen-Holten", "Dinslaken", "Voerde(Niederrhein)", "Friedrichsfeld(Niederrhein)", "Wesel"] }, SearchSearchStationsTimetableNextDepatures { type_: "Bus", train_number: "71105", platform: "", time: "Fri Jul 19 2019 20:20:00 GMT+0000 (UTC)", stops: ["Angermund", "Duisburg-Rahm", "Duisburg-Großenbaum", "Duisburg-Buchholz", "Duisburg-Schlenk", "Duisburg Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "RE", train_number: "10142", platform: "6", time: "Fri Jul 19 2019 20:28:00 GMT+0000 (UTC)", stops: ["Düsseldorf Hbf", "Düsseldorf-Benrath", "Leverkusen Mitte", "Köln-Mülheim", "Köln Hbf", "Köln-Ehrenfeld", "Horrem", "Düren", "Langerwehe", "Eschweiler Hbf", "Stolberg(Rheinl)Hbf", "Aachen-Rothe Erde", "Aachen Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "RE", train_number: "10141", platform: "5", time: "Fri Jul 19 2019 20:30:00 GMT+0000 (UTC)", stops: ["Duisburg Hbf", "Oberhausen Hbf", "Essen-Altenessen", "Gelsenkirchen Hbf", "Dortmund Hbf", "Dortmund-Kurl", "Kamen", "Nordbögge", "Hamm(Westf)"] }, SearchSearchStationsTimetableNextDepatures { type_: "Bus", train_number: "71100", platform: "", time: "Fri Jul 19 2019 20:41:00 GMT+0000 (UTC)", stops: ["Düsseldorf-Unterrath"] }, SearchSearchStationsTimetableNextDepatures { type_: "Bus", train_number: "71107", platform: "", time: "Fri Jul 19 2019 20:50:00 GMT+0000 (UTC)", stops: ["Angermund", "Duisburg-Rahm", "Duisburg-Großenbaum", "Duisburg-Buchholz", "Duisburg-Schlenk", "Duisburg Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "ERB", train_number: "89901", platform: "", time: "Fri Jul 19 2019 20:55:00 GMT+0000 (UTC)", stops: ["Duisburg Hbf", "Oberhausen Hbf", "Essen-Altenessen", "Gelsenkirchen Hbf", "Wanne-Eickel Hbf", "Herne", "Castrop-Rauxel Hbf", "Dortmund-Mengede", "Dortmund Hbf"] }] }, tracks: [SearchSearchStationsTracks { platform: "B01", number: "1", name: "Gleis 1", length: Some(420), height: 76 }, SearchSearchStationsTracks { platform: "B02", number: "4", name: "Gleis 4", length: Some(420), height: 76 }, SearchSearchStationsTracks { platform: "B02", number: "5", name: "Gleis 5", length: Some(287), height: 76 }, SearchSearchStationsTracks { platform: "B03", number: "6", name: "Gleis 6", length: Some(270), height: 76 }, SearchSearchStationsTracks { platform: "SB1", number: "10", name: "Gleis 10", length: Some(237), height: 96 }, SearchSearchStationsTracks { platform: "SB1", number: "11", name: "Gleis 11", length: Some(237), height: 96 }] }, SearchSearchStations { name: "Berlin-Schönefeld Flughafen", primary_eva_id: Some(8010109), has_local_public_transport: true, has_taxi_rank: true, has_stepless_access: "yes", has_wi_fi: false, picture: Some(SearchSearchStationsPicture { id: 1821, url: "https://fotos.railway-stations.org/fotos/de/1821.jpg", license: "CC0 1.0 Universell (CC0 1.0)", photographer: SearchSearchStationsPicturePhotographer { name: "Anonym", url: "https://railway-stations.org" } }), location: Some(SearchSearchStationsLocation { latitude: 52.391062, longitude: 13.51271 }), timetable: SearchSearchStationsTimetable { next_arrivals: [SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "9133", platform: "13", time: "Fri Jul 19 2019 20:09:00 GMT+0000 (UTC)", stops: ["Berlin-Spandau (S)", "Berlin-Stresow", "Berlin-Pichelsberg", "Berlin Olympiastadion", "Berlin Heerstraße", "Berlin Messe Süd (Eichkamp)", "Berlin Westkreuz", "Berlin Charlottenburg (S)", "Berlin Savignyplatz", "Berlin Zoologischer Garten (S)", "Berlin-Tiergarten", "Berlin Bellevue", "Berlin Hbf (S-Bahn)", "Berlin Friedrichstraße (S)", "Berlin Hackescher Markt", "Berlin Alexanderplatz (S)", "Berlin Jannowitzbrücke", "Berlin Ostbahnhof (S)", "Berlin Warschauer Straße", "Berlin Treptower Park", "Berlin Plänterwald", "Berlin Baumschulenweg", "Berlin-Schöneweide (S)", "Berlin Betriebsbf Schöneweide", "Berlin-Adlershof", "Berlin-Altglienicke", "Berlin Grünbergallee"] }, SearchSearchStationsTimetableNextArrivals { type_: "RB", train_number: "18135", platform: "3", time: "Fri Jul 19 2019 20:17:00 GMT+0000 (UTC)", stops: ["Königs Wusterhausen"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "45121", platform: "11", time: "Fri Jul 19 2019 20:18:00 GMT+0000 (UTC)", stops: ["Berlin Südkreuz (S)", "Berlin-Tempelhof", "Berlin Hermannstraße", "Berlin-Neukölln", "Berlin Köllnische Heide", "Berlin Baumschulenweg", "Berlin-Schöneweide (S)", "Berlin Betriebsbf Schöneweide", "Berlin-Adlershof", "Berlin-Altglienicke", "Berlin Grünbergallee"] }, SearchSearchStationsTimetableNextArrivals { type_: "RE", train_number: "93736", platform: "", time: "Fri Jul 19 2019 20:24:00 GMT+0000 (UTC)", stops: ["Berlin-Lichtenberg", "Berlin Ostkreuz"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "9135", platform: "13", time: "Fri Jul 19 2019 20:29:00 GMT+0000 (UTC)", stops: ["Berlin-Spandau (S)", "Berlin-Stresow", "Berlin-Pichelsberg", "Berlin Olympiastadion", "Berlin Heerstraße", "Berlin Messe Süd (Eichkamp)", "Berlin Westkreuz", "Berlin Charlottenburg (S)", "Berlin Savignyplatz", "Berlin Zoologischer Garten (S)", "Berlin-Tiergarten", "Berlin Bellevue", "Berlin Hbf (S-Bahn)", "Berlin Friedrichstraße (S)", "Berlin Hackescher Markt", "Berlin Alexanderplatz (S)", "Berlin Jannowitzbrücke", "Berlin Ostbahnhof (S)", "Berlin Warschauer Straße", "Berlin Treptower Park", "Berlin Plänterwald", "Berlin Baumschulenweg", "Berlin-Schöneweide (S)", "Berlin Betriebsbf Schöneweide", "Berlin-Adlershof", "Berlin-Altglienicke", "Berlin Grünbergallee"] }, SearchSearchStationsTimetableNextArrivals { type_: "RE", train_number: "93609", platform: "", time: "Fri Jul 19 2019 20:34:00 GMT+0000 (UTC)", stops: ["Wünsdorf-Waldstadt", "Zossen", "Dabendorf", "Rangsdorf", "Dahlewitz", "Blankenfelde(Teltow-Fläming)"] }, SearchSearchStationsTimetableNextArrivals { type_: "RB", train_number: "18136", platform: "3", time: "Fri Jul 19 2019 20:37:00 GMT+0000 (UTC)", stops: ["Potsdam Hbf", "Potsdam Charlottenhof", "Potsdam Park Sanssouci", "Golm", "Saarmund", "Ludwigsfelde-Struveshof"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "45123", platform: "11", time: "Fri Jul 19 2019 20:38:00 GMT+0000 (UTC)", stops: ["Berlin Südkreuz (S)", "Berlin-Tempelhof", "Berlin Hermannstraße", "Berlin-Neukölln", "Berlin Köllnische Heide", "Berlin Baumschulenweg", "Berlin-Schöneweide (S)", "Berlin Betriebsbf Schöneweide", "Berlin-Adlershof", "Berlin-Altglienicke", "Berlin Grünbergallee"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "9137", platform: "13", time: "Fri Jul 19 2019 20:49:00 GMT+0000 (UTC)", stops: ["Berlin-Spandau (S)", "Berlin-Stresow", "Berlin-Pichelsberg", "Berlin Olympiastadion", "Berlin Heerstraße", "Berlin Messe Süd (Eichkamp)", "Berlin Westkreuz", "Berlin Charlottenburg (S)", "Berlin Savignyplatz", "Berlin Zoologischer Garten (S)", "Berlin-Tiergarten", "Berlin Bellevue", "Berlin Hbf (S-Bahn)", "Berlin Friedrichstraße (S)", "Berlin Hackescher Markt", "Berlin Alexanderplatz (S)", "Berlin Jannowitzbrücke", "Berlin Ostbahnhof (S)", "Berlin Warschauer Straße", "Berlin Treptower Park", "Berlin Plänterwald", "Berlin Baumschulenweg", "Berlin-Schöneweide (S)", "Berlin Betriebsbf Schöneweide", "Berlin-Adlershof", "Berlin-Altglienicke", "Berlin Grünbergallee"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "45125", platform: "11", time: "Fri Jul 19 2019 20:58:00 GMT+0000 (UTC)", stops: ["Berlin Südkreuz (S)", "Berlin-Tempelhof", "Berlin Hermannstraße", "Berlin-Neukölln", "Berlin Köllnische Heide", "Berlin Baumschulenweg", "Berlin-Schöneweide (S)", "Berlin Betriebsbf Schöneweide", "Berlin-Adlershof", "Berlin-Altglienicke", "Berlin Grünbergallee"] }], next_depatures: [SearchSearchStationsTimetableNextDepatures { type_: "RB", train_number: "18636", platform: "4", time: "Fri Jul 19 2019 20:03:00 GMT+0000 (UTC)", stops: ["Berlin-Lichtenberg", "Berlin Gesundbrunnen", "Berlin Jungfernheide", "Berlin-Spandau", "Albrechtshof", "Seegefeld", "Falkensee", "Finkenkrug", "Brieselang", "Nauen"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "45122", platform: "11", time: "Fri Jul 19 2019 20:05:00 GMT+0000 (UTC)", stops: ["Berlin Grünbergallee", "Berlin-Altglienicke", "Berlin-Adlershof", "Berlin Betriebsbf Schöneweide", "Berlin-Schöneweide (S)", "Berlin Baumschulenweg", "Berlin Köllnische Heide", "Berlin-Neukölln", "Berlin Hermannstraße", "Berlin-Tempelhof", "Berlin Südkreuz (S)"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "9140", platform: "13", time: "Fri Jul 19 2019 20:17:00 GMT+0000 (UTC)", stops: ["Berlin Grünbergallee", "Berlin-Altglienicke", "Berlin-Adlershof", "Berlin Betriebsbf Schöneweide", "Berlin-Schöneweide (S)", "Berlin Baumschulenweg", "Berlin Plänterwald", "Berlin Treptower Park", "Berlin Warschauer Straße", "Berlin Ostbahnhof (S)", "Berlin Jannowitzbrücke", "Berlin Alexanderplatz (S)", "Berlin Hackescher Markt", "Berlin Friedrichstraße (S)", "Berlin Hbf (S-Bahn)", "Berlin Bellevue", "Berlin-Tiergarten", "Berlin Zoologischer Garten (S)", "Berlin Savignyplatz", "Berlin Charlottenburg (S)", "Berlin Westkreuz", "Berlin Messe Süd (Eichkamp)", "Berlin Heerstraße", "Berlin Olympiastadion", "Berlin-Pichelsberg", "Berlin-Stresow", "Berlin-Spandau (S)"] }, SearchSearchStationsTimetableNextDepatures { type_: "RB", train_number: "18135", platform: "3", time: "Fri Jul 19 2019 20:20:00 GMT+0000 (UTC)", stops: ["Ludwigsfelde-Struveshof", "Saarmund", "Golm", "Potsdam Park Sanssouci", "Potsdam Charlottenhof", "Potsdam Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "RE", train_number: "93736", platform: "", time: "Fri Jul 19 2019 20:24:00 GMT+0000 (UTC)", stops: ["Blankenfelde(Teltow-Fläming)", "Dahlewitz", "Rangsdorf", "Dabendorf", "Zossen", "Wünsdorf-Waldstadt"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "45124", platform: "11", time: "Fri Jul 19 2019 20:25:00 GMT+0000 (UTC)", stops: ["Berlin Grünbergallee", "Berlin-Altglienicke", "Berlin-Adlershof", "Berlin Betriebsbf Schöneweide", "Berlin-Schöneweide (S)", "Berlin Baumschulenweg", "Berlin Köllnische Heide", "Berlin-Neukölln", "Berlin Hermannstraße", "Berlin-Tempelhof", "Berlin Südkreuz (S)"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "9142", platform: "13", time: "Fri Jul 19 2019 20:37:00 GMT+0000 (UTC)", stops: ["Berlin Grünbergallee", "Berlin-Altglienicke", "Berlin-Adlershof", "Berlin Betriebsbf Schöneweide", "Berlin-Schöneweide (S)", "Berlin Baumschulenweg", "Berlin Plänterwald", "Berlin Treptower Park", "Berlin Warschauer Straße", "Berlin Ostbahnhof (S)", "Berlin Jannowitzbrücke", "Berlin Alexanderplatz (S)", "Berlin Hackescher Markt", "Berlin Friedrichstraße (S)", "Berlin Hbf (S-Bahn)", "Berlin Bellevue", "Berlin-Tiergarten", "Berlin Zoologischer Garten (S)", "Berlin Savignyplatz", "Berlin Charlottenburg (S)", "Berlin Westkreuz", "Berlin Messe Süd (Eichkamp)", "Berlin Heerstraße", "Berlin Olympiastadion", "Berlin-Pichelsberg", "Berlin-Stresow", "Berlin-Spandau (S)"] }, SearchSearchStationsTimetableNextDepatures { type_: "RB", train_number: "18136", platform: "3", time: "Fri Jul 19 2019 20:40:00 GMT+0000 (UTC)", stops: ["Königs Wusterhausen"] }, SearchSearchStationsTimetableNextDepatures { type_: "RE", train_number: "93609", platform: "", time: "Fri Jul 19 2019 20:45:00 GMT+0000 (UTC)", stops: ["Berlin Ostkreuz", "Berlin-Lichtenberg"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "45126", platform: "11", time: "Fri Jul 19 2019 20:45:00 GMT+0000 (UTC)", stops: ["Berlin Grünbergallee", "Berlin-Altglienicke", "Berlin-Adlershof", "Berlin Betriebsbf Schöneweide", "Berlin-Schöneweide (S)", "Berlin Baumschulenweg", "Berlin Köllnische Heide", "Berlin-Neukölln", "Berlin Hermannstraße", "Berlin-Tempelhof", "Berlin Südkreuz (S)"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "9144", platform: "13", time: "Fri Jul 19 2019 20:57:00 GMT+0000 (UTC)", stops: ["Berlin Grünbergallee", "Berlin-Altglienicke", "Berlin-Adlershof", "Berlin Betriebsbf Schöneweide", "Berlin-Schöneweide (S)", "Berlin Baumschulenweg", "Berlin Plänterwald", "Berlin Treptower Park", "Berlin Warschauer Straße", "Berlin Ostbahnhof (S)", "Berlin Jannowitzbrücke", "Berlin Alexanderplatz (S)", "Berlin Hackescher Markt", "Berlin Friedrichstraße (S)", "Berlin Hbf (S-Bahn)", "Berlin Bellevue", "Berlin-Tiergarten", "Berlin Zoologischer Garten (S)", "Berlin Savignyplatz", "Berlin Charlottenburg (S)", "Berlin Westkreuz", "Berlin Messe Süd (Eichkamp)", "Berlin Heerstraße", "Berlin Olympiastadion", "Berlin-Pichelsberg", "Berlin-Stresow", "Berlin-Spandau (S)"] }] }, tracks: [SearchSearchStationsTracks { platform: "B01", number: "11", name: "Gleis 11", length: Some(159), height: 96 }, SearchSearchStationsTracks { platform: "B01", number: "13", name: "Gleis 13", length: Some(159), height: 96 }, SearchSearchStationsTracks { platform: "B03", number: "3", name: "Gleis 3", length: Some(420), height: 55 }, SearchSearchStationsTracks { platform: "B03", number: "5", name: "Gleis 5", length: Some(420), height: 55 }, SearchSearchStationsTracks { platform: "B04", number: "4", name: "Gleis 4", length: Some(420), height: 55 }, SearchSearchStationsTracks { platform: "B04", number: "6", name: "Gleis 6", length: Some(420), height: 55 }] }, SearchSearchStations { name: "Flughafen München", primary_eva_id: Some(8004168), has_local_public_transport: true, has_taxi_rank: true, has_stepless_access: "yes", has_wi_fi: false, picture: Some(SearchSearchStationsPicture { id: 1822, url: "https://fotos.railway-stations.org/fotos/de/1822_1.jpg", license: "CC0 1.0 Universell (CC0 1.0)", photographer: SearchSearchStationsPicturePhotographer { name: "@stefanopitz", url: "https://twitter.com/stefanopitz" } }), location: Some(SearchSearchStationsLocation { latitude: 48.353728, longitude: 11.78597 }), timetable: SearchSearchStationsTimetable { next_arrivals: [SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8908", platform: "1", time: "Fri Jul 19 2019 20:06:00 GMT+0000 (UTC)", stops: ["München Ost", "München Rosenheimer Platz", "München Isartor", "München Marienplatz", "München Karlsplatz", "München Hbf (tief)", "München Hackerbrücke", "München Donnersbergerbrücke", "München Hirschgarten", "München-Laim", "München-Moosach", "München-Fasanerie", "München-Feldmoching", "Oberschleißheim", "Unterschleißheim", "Lohhof", "Eching", "Neufahrn(b Freising)", "München Flughafen Besucherpark"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8813", platform: "2", time: "Fri Jul 19 2019 20:15:00 GMT+0000 (UTC)", stops: ["Weßling(Oberbay)", "Neugilching", "Gilching-Argelsried", "Geisenbrunn", "Germering-Unterpfaffenhofen", "Harthaus", "München-Freiham", "München-Neuaubing", "München-Westkreuz", "München-Pasing", "München-Laim", "München Hirschgarten", "München Donnersbergerbrücke", "München Hackerbrücke", "München Hbf (tief)", "München Karlsplatz", "München Marienplatz", "München Isartor", "München Rosenheimer Platz", "München Ost", "München Leuchtenbergring", "München-Daglfing", "München-Englschalking", "München-Johanneskirchen", "Unterföhring", "Ismaning", "Hallbergmoos", "München Flughafen Besucherpark"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8910", platform: "1", time: "Fri Jul 19 2019 20:26:00 GMT+0000 (UTC)", stops: ["München Ost", "München Rosenheimer Platz", "München Isartor", "München Marienplatz", "München Karlsplatz", "München Hbf (tief)", "München Hackerbrücke", "München Donnersbergerbrücke", "München Hirschgarten", "München-Laim", "München-Moosach", "München-Fasanerie", "München-Feldmoching", "Oberschleißheim", "Unterschleißheim", "Lohhof", "Eching", "Neufahrn(b Freising)", "München Flughafen Besucherpark"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8815", platform: "2", time: "Fri Jul 19 2019 20:35:00 GMT+0000 (UTC)", stops: ["Herrsching", "Seefeld-Hechendorf", "Steinebach", "Weßling(Oberbay)", "Neugilching", "Gilching-Argelsried", "Geisenbrunn", "Germering-Unterpfaffenhofen", "Harthaus", "München-Freiham", "München-Neuaubing", "München-Westkreuz", "München-Pasing", "München-Laim", "München Hirschgarten", "München Donnersbergerbrücke", "München Hackerbrücke", "München Hbf (tief)", "München Karlsplatz", "München Marienplatz", "München Isartor", "München Rosenheimer Platz", "München Ost", "München Leuchtenbergring", "München-Daglfing", "München-Englschalking", "München-Johanneskirchen", "Unterföhring", "Ismaning", "Hallbergmoos", "München Flughafen Besucherpark"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8912", platform: "1", time: "Fri Jul 19 2019 20:46:00 GMT+0000 (UTC)", stops: ["München Ost", "München Rosenheimer Platz", "München Isartor", "München Marienplatz", "München Karlsplatz", "München Hbf (tief)", "München Hackerbrücke", "München Donnersbergerbrücke", "München Hirschgarten", "München-Laim", "München-Moosach", "München-Fasanerie", "München-Feldmoching", "Oberschleißheim", "Unterschleißheim", "Lohhof", "Eching", "Neufahrn(b Freising)", "München Flughafen Besucherpark"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8817", platform: "2", time: "Fri Jul 19 2019 20:55:00 GMT+0000 (UTC)", stops: ["Herrsching", "Seefeld-Hechendorf", "Steinebach", "Weßling(Oberbay)", "Neugilching", "Gilching-Argelsried", "Geisenbrunn", "Germering-Unterpfaffenhofen", "Harthaus", "München-Freiham", "München-Neuaubing", "München-Westkreuz", "München-Pasing", "München-Laim", "München Hirschgarten", "München Donnersbergerbrücke", "München Hackerbrücke", "München Hbf (tief)", "München Karlsplatz", "München Marienplatz", "München Isartor", "München Rosenheimer Platz", "München Ost", "München Leuchtenbergring", "München-Daglfing", "München-Englschalking", "München-Johanneskirchen", "Unterföhring", "Ismaning", "Hallbergmoos", "München Flughafen Besucherpark"] }], next_depatures: [SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8816", platform: "2", time: "Fri Jul 19 2019 20:04:00 GMT+0000 (UTC)", stops: ["München Flughafen Besucherpark", "Hallbergmoos", "Ismaning", "Unterföhring", "München-Johanneskirchen", "München-Englschalking", "München-Daglfing", "München Leuchtenbergring", "München Ost", "München Rosenheimer Platz", "München Isartor", "München Marienplatz", "München Karlsplatz", "München Hbf (tief)", "München Hackerbrücke", "München Donnersbergerbrücke", "München Hirschgarten", "München-Laim", "München-Pasing", "München-Westkreuz", "München-Neuaubing", "München-Freiham", "Harthaus", "Germering-Unterpfaffenhofen", "Geisenbrunn", "Gilching-Argelsried", "Neugilching", "Weßling(Oberbay)", "Steinebach", "Seefeld-Hechendorf", "Herrsching"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8921", platform: "1", time: "Fri Jul 19 2019 20:13:00 GMT+0000 (UTC)", stops: ["München Flughafen Besucherpark", "Neufahrn(b Freising)", "Eching", "Lohhof", "Unterschleißheim", "Oberschleißheim", "München-Feldmoching", "München-Fasanerie", "München-Moosach", "München-Laim", "München Hirschgarten", "München Donnersbergerbrücke", "München Hackerbrücke", "München Hbf (tief)", "München Karlsplatz", "München Marienplatz", "München Isartor", "München Rosenheimer Platz", "München Ost"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8818", platform: "2", time: "Fri Jul 19 2019 20:23:00 GMT+0000 (UTC)", stops: ["München Flughafen Besucherpark", "Hallbergmoos", "Ismaning", "Unterföhring", "München-Johanneskirchen", "München-Englschalking", "München-Daglfing", "München Leuchtenbergring", "München Ost", "München Rosenheimer Platz", "München Isartor", "München Marienplatz", "München Karlsplatz", "München Hbf (tief)", "München Hackerbrücke", "München Donnersbergerbrücke", "München Hirschgarten", "München-Laim", "München-Pasing", "München-Westkreuz", "München-Neuaubing", "München-Freiham", "Harthaus", "Germering-Unterpfaffenhofen", "Geisenbrunn", "Gilching-Argelsried", "Neugilching", "Weßling(Oberbay)", "Steinebach", "Seefeld-Hechendorf", "Herrsching"] }, SearchSearchStationsTimetableNextDepatures { type_: "RE", train_number: "57940", platform: "2", time: "Fri Jul 19 2019 20:28:00 GMT+0000 (UTC)", stops: ["Freising", "Moosburg", "Landshut(Bay)Hbf", "Ergoldsbach", "Eggmühl", "Hagelstadt", "Köfering", "Obertraubling", "Regensburg Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8923", platform: "1", time: "Fri Jul 19 2019 20:31:00 GMT+0000 (UTC)", stops: ["München Flughafen Besucherpark", "Neufahrn(b Freising)", "Eching", "Lohhof", "Unterschleißheim", "Oberschleißheim", "München-Feldmoching", "München-Fasanerie", "München-Moosach", "München-Laim", "München Hirschgarten", "München Donnersbergerbrücke", "München Hackerbrücke", "München Hbf (tief)", "München Karlsplatz", "München Marienplatz", "München Isartor", "München Rosenheimer Platz", "München Ost"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8820", platform: "2", time: "Fri Jul 19 2019 20:44:00 GMT+0000 (UTC)", stops: ["München Flughafen Besucherpark", "Hallbergmoos", "Ismaning", "Unterföhring", "München-Johanneskirchen", "München-Englschalking", "München-Daglfing", "München Leuchtenbergring", "München Ost", "München Rosenheimer Platz", "München Isartor", "München Marienplatz", "München Karlsplatz", "München Hbf (tief)", "München Hackerbrücke", "München Donnersbergerbrücke", "München Hirschgarten", "München-Laim", "München-Pasing", "München-Westkreuz", "München-Neuaubing", "München-Freiham", "Harthaus", "Germering-Unterpfaffenhofen", "Geisenbrunn", "Gilching-Argelsried", "Neugilching", "Weßling(Oberbay)", "Steinebach", "Seefeld-Hechendorf", "Herrsching"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8925", platform: "1", time: "Fri Jul 19 2019 20:53:00 GMT+0000 (UTC)", stops: ["München Flughafen Besucherpark", "Neufahrn(b Freising)", "Eching", "Lohhof", "Unterschleißheim", "Oberschleißheim", "München-Feldmoching", "München-Fasanerie", "München-Moosach", "München-Laim", "München Hirschgarten", "München Donnersbergerbrücke", "München Hackerbrücke", "München Hbf (tief)", "München Karlsplatz", "München Marienplatz", "München Isartor", "München Rosenheimer Platz", "München Ost"] }] }, tracks: [SearchSearchStationsTracks { platform: "SB1", number: "1", name: "Gleis 1", length: Some(232), height: 96 }, SearchSearchStationsTracks { platform: "SB1", number: "2", name: "Gleis 2", length: Some(232), height: 96 }] }, SearchSearchStations { name: "Flughafen München Besucherpark", primary_eva_id: Some(8004167), has_local_public_transport: true, has_taxi_rank: false, has_stepless_access: "yes", has_wi_fi: false, picture: Some(SearchSearchStationsPicture { id: 1823, url: "https://fotos.railway-stations.org/fotos/de/1823.jpg", license: "CC0 1.0 Universell (CC0 1.0)", photographer: SearchSearchStationsPicturePhotographer { name: "Anonym", url: "https://railway-stations.org" } }), location: Some(SearchSearchStationsLocation { latitude: 48.352095, longitude: 11.764185 }), timetable: SearchSearchStationsTimetable { next_arrivals: [SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8908", platform: "1", time: "Fri Jul 19 2019 20:04:00 GMT+0000 (UTC)", stops: ["München Ost", "München Rosenheimer Platz", "München Isartor", "München Marienplatz", "München Karlsplatz", "München Hbf (tief)", "München Hackerbrücke", "München Donnersbergerbrücke", "München Hirschgarten", "München-Laim", "München-Moosach", "München-Fasanerie", "München-Feldmoching", "Oberschleißheim", "Unterschleißheim", "Lohhof", "Eching", "Neufahrn(b Freising)"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8816", platform: "2", time: "Fri Jul 19 2019 20:06:00 GMT+0000 (UTC)", stops: ["München Flughafen Terminal"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8813", platform: "2", time: "Fri Jul 19 2019 20:13:00 GMT+0000 (UTC)", stops: ["Weßling(Oberbay)", "Neugilching", "Gilching-Argelsried", "Geisenbrunn", "Germering-Unterpfaffenhofen", "Harthaus", "München-Freiham", "München-Neuaubing", "München-Westkreuz", "München-Pasing", "München-Laim", "München Hirschgarten", "München Donnersbergerbrücke", "München Hackerbrücke", "München Hbf (tief)", "München Karlsplatz", "München Marienplatz", "München Isartor", "München Rosenheimer Platz", "München Ost", "München Leuchtenbergring", "München-Daglfing", "München-Englschalking", "München-Johanneskirchen", "Unterföhring", "Ismaning", "Hallbergmoos"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8921", platform: "1", time: "Fri Jul 19 2019 20:14:00 GMT+0000 (UTC)", stops: ["München Flughafen Terminal"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8910", platform: "1", time: "Fri Jul 19 2019 20:24:00 GMT+0000 (UTC)", stops: ["München Ost", "München Rosenheimer Platz", "München Isartor", "München Marienplatz", "München Karlsplatz", "München Hbf (tief)", "München Hackerbrücke", "München Donnersbergerbrücke", "München Hirschgarten", "München-Laim", "München-Moosach", "München-Fasanerie", "München-Feldmoching", "Oberschleißheim", "Unterschleißheim", "Lohhof", "Eching", "Neufahrn(b Freising)"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8818", platform: "2", time: "Fri Jul 19 2019 20:25:00 GMT+0000 (UTC)", stops: ["München Flughafen Terminal"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8923", platform: "1", time: "Fri Jul 19 2019 20:32:00 GMT+0000 (UTC)", stops: ["München Flughafen Terminal"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8815", platform: "2", time: "Fri Jul 19 2019 20:33:00 GMT+0000 (UTC)", stops: ["Herrsching", "Seefeld-Hechendorf", "Steinebach", "Weßling(Oberbay)", "Neugilching", "Gilching-Argelsried", "Geisenbrunn", "Germering-Unterpfaffenhofen", "Harthaus", "München-Freiham", "München-Neuaubing", "München-Westkreuz", "München-Pasing", "München-Laim", "München Hirschgarten", "München Donnersbergerbrücke", "München Hackerbrücke", "München Hbf (tief)", "München Karlsplatz", "München Marienplatz", "München Isartor", "München Rosenheimer Platz", "München Ost", "München Leuchtenbergring", "München-Daglfing", "München-Englschalking", "München-Johanneskirchen", "Unterföhring", "Ismaning", "Hallbergmoos"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8912", platform: "1", time: "Fri Jul 19 2019 20:44:00 GMT+0000 (UTC)", stops: ["München Ost", "München Rosenheimer Platz", "München Isartor", "München Marienplatz", "München Karlsplatz", "München Hbf (tief)", "München Hackerbrücke", "München Donnersbergerbrücke", "München Hirschgarten", "München-Laim", "München-Moosach", "München-Fasanerie", "München-Feldmoching", "Oberschleißheim", "Unterschleißheim", "Lohhof", "Eching", "Neufahrn(b Freising)"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8820", platform: "2", time: "Fri Jul 19 2019 20:46:00 GMT+0000 (UTC)", stops: ["München Flughafen Terminal"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8817", platform: "2", time: "Fri Jul 19 2019 20:53:00 GMT+0000 (UTC)", stops: ["Herrsching", "Seefeld-Hechendorf", "Steinebach", "Weßling(Oberbay)", "Neugilching", "Gilching-Argelsried", "Geisenbrunn", "Germering-Unterpfaffenhofen", "Harthaus", "München-Freiham", "München-Neuaubing", "München-Westkreuz", "München-Pasing", "München-Laim", "München Hirschgarten", "München Donnersbergerbrücke", "München Hackerbrücke", "München Hbf (tief)", "München Karlsplatz", "München Marienplatz", "München Isartor", "München Rosenheimer Platz", "München Ost", "München Leuchtenbergring", "München-Daglfing", "München-Englschalking", "München-Johanneskirchen", "Unterföhring", "Ismaning", "Hallbergmoos"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "8925", platform: "1", time: "Fri Jul 19 2019 20:54:00 GMT+0000 (UTC)", stops: ["München Flughafen Terminal"] }], next_depatures: [SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8908", platform: "1", time: "Fri Jul 19 2019 20:04:00 GMT+0000 (UTC)", stops: ["München Flughafen Terminal"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8816", platform: "2", time: "Fri Jul 19 2019 20:06:00 GMT+0000 (UTC)", stops: ["Hallbergmoos", "Ismaning", "Unterföhring", "München-Johanneskirchen", "München-Englschalking", "München-Daglfing", "München Leuchtenbergring", "München Ost", "München Rosenheimer Platz", "München Isartor", "München Marienplatz", "München Karlsplatz", "München Hbf (tief)", "München Hackerbrücke", "München Donnersbergerbrücke", "München Hirschgarten", "München-Laim", "München-Pasing", "München-Westkreuz", "München-Neuaubing", "München-Freiham", "Harthaus", "Germering-Unterpfaffenhofen", "Geisenbrunn", "Gilching-Argelsried", "Neugilching", "Weßling(Oberbay)", "Steinebach", "Seefeld-Hechendorf", "Herrsching"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8813", platform: "2", time: "Fri Jul 19 2019 20:13:00 GMT+0000 (UTC)", stops: ["München Flughafen Terminal"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8921", platform: "1", time: "Fri Jul 19 2019 20:15:00 GMT+0000 (UTC)", stops: ["Neufahrn(b Freising)", "Eching", "Lohhof", "Unterschleißheim", "Oberschleißheim", "München-Feldmoching", "München-Fasanerie", "München-Moosach", "München-Laim", "München Hirschgarten", "München Donnersbergerbrücke", "München Hackerbrücke", "München Hbf (tief)", "München Karlsplatz", "München Marienplatz", "München Isartor", "München Rosenheimer Platz", "München Ost"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8910", platform: "1", time: "Fri Jul 19 2019 20:24:00 GMT+0000 (UTC)", stops: ["München Flughafen Terminal"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8818", platform: "2", time: "Fri Jul 19 2019 20:25:00 GMT+0000 (UTC)", stops: ["Hallbergmoos", "Ismaning", "Unterföhring", "München-Johanneskirchen", "München-Englschalking", "München-Daglfing", "München Leuchtenbergring", "München Ost", "München Rosenheimer Platz", "München Isartor", "München Marienplatz", "München Karlsplatz", "München Hbf (tief)", "München Hackerbrücke", "München Donnersbergerbrücke", "München Hirschgarten", "München-Laim", "München-Pasing", "München-Westkreuz", "München-Neuaubing", "München-Freiham", "Harthaus", "Germering-Unterpfaffenhofen", "Geisenbrunn", "Gilching-Argelsried", "Neugilching", "Weßling(Oberbay)", "Steinebach", "Seefeld-Hechendorf", "Herrsching"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8923", platform: "1", time: "Fri Jul 19 2019 20:33:00 GMT+0000 (UTC)", stops: ["Neufahrn(b Freising)", "Eching", "Lohhof", "Unterschleißheim", "Oberschleißheim", "München-Feldmoching", "München-Fasanerie", "München-Moosach", "München-Laim", "München Hirschgarten", "München Donnersbergerbrücke", "München Hackerbrücke", "München Hbf (tief)", "München Karlsplatz", "München Marienplatz", "München Isartor", "München Rosenheimer Platz", "München Ost"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8815", platform: "2", time: "Fri Jul 19 2019 20:33:00 GMT+0000 (UTC)", stops: ["München Flughafen Terminal"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8912", platform: "1", time: "Fri Jul 19 2019 20:44:00 GMT+0000 (UTC)", stops: ["München Flughafen Terminal"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8820", platform: "2", time: "Fri Jul 19 2019 20:46:00 GMT+0000 (UTC)", stops: ["Hallbergmoos", "Ismaning", "Unterföhring", "München-Johanneskirchen", "München-Englschalking", "München-Daglfing", "München Leuchtenbergring", "München Ost", "München Rosenheimer Platz", "München Isartor", "München Marienplatz", "München Karlsplatz", "München Hbf (tief)", "München Hackerbrücke", "München Donnersbergerbrücke", "München Hirschgarten", "München-Laim", "München-Pasing", "München-Westkreuz", "München-Neuaubing", "München-Freiham", "Harthaus", "Germering-Unterpfaffenhofen", "Geisenbrunn", "Gilching-Argelsried", "Neugilching", "Weßling(Oberbay)", "Steinebach", "Seefeld-Hechendorf", "Herrsching"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8817", platform: "2", time: "Fri Jul 19 2019 20:53:00 GMT+0000 (UTC)", stops: ["München Flughafen Terminal"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "8925", platform: "1", time: "Fri Jul 19 2019 20:55:00 GMT+0000 (UTC)", stops: ["Neufahrn(b Freising)", "Eching", "Lohhof", "Unterschleißheim", "Oberschleißheim", "München-Feldmoching", "München-Fasanerie", "München-Moosach", "München-Laim", "München Hirschgarten", "München Donnersbergerbrücke", "München Hackerbrücke", "München Hbf (tief)", "München Karlsplatz", "München Marienplatz", "München Isartor", "München Rosenheimer Platz", "München Ost"] }] }, tracks: [SearchSearchStationsTracks { platform: "SB1", number: "1", name: "Gleis 1", length: Some(211), height: 96 }, SearchSearchStationsTracks { platform: "SB1", number: "2", name: "Gleis 2", length: Some(211), height: 96 }] }, SearchSearchStations { name: "Stuttgart Flughafen/Messe", primary_eva_id: Some(8005768), has_local_public_transport: true, has_taxi_rank: true, has_stepless_access: "yes", has_wi_fi: false, picture: Some(SearchSearchStationsPicture { id: 1824, url: "https://fotos.railway-stations.org/fotos/de/1824.jpg", license: "CC0 1.0 Universell (CC0 1.0)", photographer: SearchSearchStationsPicturePhotographer { name: "@tursics", url: "https://twitter.com/tursics" } }), location: Some(SearchSearchStationsLocation { latitude: 48.690648, longitude: 9.19263 }), timetable: SearchSearchStationsTimetable { next_arrivals: [SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "7268", platform: "2", time: "Fri Jul 19 2019 20:07:00 GMT+0000 (UTC)", stops: ["Filderstadt"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "7367", platform: "2", time: "Fri Jul 19 2019 20:12:00 GMT+0000 (UTC)", stops: ["Backnang", "Maubach", "Nellmersbach", "Winnenden", "Schwaikheim", "Neustadt-Hohenacker", "Waiblingen", "Fellbach", "Stuttgart-Sommerrain", "Stuttgart Nürnberger Str.", "Stuttgart-Bad Cannstatt", "Stuttgart Hbf (tief)", "Stuttgart Stadtmitte", "Stuttgart Feuersee", "Stuttgart Schwabstr.", "Stuttgart Universität", "Stuttgart-Österfeld", "Stuttgart-Vaihingen", "Stuttgart-Rohr", "Oberaichen", "Leinfelden", "Echterdingen"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "7269", platform: "1", time: "Fri Jul 19 2019 20:22:00 GMT+0000 (UTC)", stops: ["Schorndorf", "Weiler(Rems)", "Winterbach(b Schorndorf)", "Geradstetten", "Grunbach", "Beutelsbach", "Endersbach", "Stetten-Beinstein", "Rommelshausen", "Waiblingen", "Fellbach", "Stuttgart-Sommerrain", "Stuttgart Nürnberger Str.", "Stuttgart-Bad Cannstatt", "Stuttgart Hbf (tief)", "Stuttgart Stadtmitte", "Stuttgart Feuersee", "Stuttgart Schwabstr.", "Stuttgart Universität", "Stuttgart-Österfeld", "Stuttgart-Vaihingen", "Stuttgart-Rohr", "Oberaichen", "Leinfelden", "Echterdingen"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "7270", platform: "2", time: "Fri Jul 19 2019 20:37:00 GMT+0000 (UTC)", stops: ["Filderstadt"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "7369", platform: "2", time: "Fri Jul 19 2019 20:42:00 GMT+0000 (UTC)", stops: ["Backnang", "Maubach", "Nellmersbach", "Winnenden", "Schwaikheim", "Neustadt-Hohenacker", "Waiblingen", "Fellbach", "Stuttgart-Sommerrain", "Stuttgart Nürnberger Str.", "Stuttgart-Bad Cannstatt", "Stuttgart Hbf (tief)", "Stuttgart Stadtmitte", "Stuttgart Feuersee", "Stuttgart Schwabstr.", "Stuttgart Universität", "Stuttgart-Österfeld", "Stuttgart-Vaihingen", "Stuttgart-Rohr", "Oberaichen", "Leinfelden", "Echterdingen"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "7271", platform: "1", time: "Fri Jul 19 2019 20:52:00 GMT+0000 (UTC)", stops: ["Schorndorf", "Weiler(Rems)", "Winterbach(b Schorndorf)", "Geradstetten", "Grunbach", "Beutelsbach", "Endersbach", "Stetten-Beinstein", "Rommelshausen", "Waiblingen", "Fellbach", "Stuttgart-Sommerrain", "Stuttgart Nürnberger Str.", "Stuttgart-Bad Cannstatt", "Stuttgart Hbf (tief)", "Stuttgart Stadtmitte", "Stuttgart Feuersee", "Stuttgart Schwabstr.", "Stuttgart Universität", "Stuttgart-Österfeld", "Stuttgart-Vaihingen", "Stuttgart-Rohr", "Oberaichen", "Leinfelden", "Echterdingen"] }], next_depatures: [SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "7268", platform: "2", time: "Fri Jul 19 2019 20:08:00 GMT+0000 (UTC)", stops: ["Echterdingen", "Leinfelden", "Oberaichen", "Stuttgart-Rohr", "Stuttgart-Vaihingen", "Stuttgart-Österfeld", "Stuttgart Universität", "Stuttgart Schwabstr.", "Stuttgart Feuersee", "Stuttgart Stadtmitte", "Stuttgart Hbf (tief)", "Stuttgart-Bad Cannstatt", "Stuttgart Nürnberger Str.", "Stuttgart-Sommerrain", "Fellbach", "Waiblingen", "Rommelshausen", "Stetten-Beinstein", "Endersbach", "Beutelsbach", "Grunbach", "Geradstetten", "Winterbach(b Schorndorf)", "Weiler(Rems)", "Schorndorf"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "7370", platform: "2", time: "Fri Jul 19 2019 20:18:00 GMT+0000 (UTC)", stops: ["Echterdingen", "Leinfelden", "Oberaichen", "Stuttgart-Rohr", "Stuttgart-Vaihingen", "Stuttgart-Österfeld", "Stuttgart Universität", "Stuttgart Schwabstr.", "Stuttgart Feuersee", "Stuttgart Stadtmitte", "Stuttgart Hbf (tief)", "Stuttgart-Bad Cannstatt", "Stuttgart Nürnberger Str.", "Stuttgart-Sommerrain", "Fellbach", "Waiblingen", "Neustadt-Hohenacker", "Schwaikheim", "Winnenden", "Nellmersbach", "Maubach", "Backnang"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "7269", platform: "1", time: "Fri Jul 19 2019 20:22:00 GMT+0000 (UTC)", stops: ["Filderstadt"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "7270", platform: "2", time: "Fri Jul 19 2019 20:38:00 GMT+0000 (UTC)", stops: ["Echterdingen", "Leinfelden", "Oberaichen", "Stuttgart-Rohr", "Stuttgart-Vaihingen", "Stuttgart-Österfeld", "Stuttgart Universität", "Stuttgart Schwabstr.", "Stuttgart Feuersee", "Stuttgart Stadtmitte", "Stuttgart Hbf (tief)", "Stuttgart-Bad Cannstatt", "Stuttgart Nürnberger Str.", "Stuttgart-Sommerrain", "Fellbach", "Waiblingen", "Rommelshausen", "Stetten-Beinstein", "Endersbach", "Beutelsbach", "Grunbach", "Geradstetten", "Winterbach(b Schorndorf)", "Weiler(Rems)", "Schorndorf"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "7372", platform: "2", time: "Fri Jul 19 2019 20:48:00 GMT+0000 (UTC)", stops: ["Echterdingen", "Leinfelden", "Oberaichen", "Stuttgart-Rohr", "Stuttgart-Vaihingen", "Stuttgart-Österfeld", "Stuttgart Universität", "Stuttgart Schwabstr.", "Stuttgart Feuersee", "Stuttgart Stadtmitte", "Stuttgart Hbf (tief)", "Stuttgart-Bad Cannstatt", "Stuttgart Nürnberger Str.", "Stuttgart-Sommerrain", "Fellbach", "Waiblingen", "Neustadt-Hohenacker", "Schwaikheim", "Winnenden", "Nellmersbach", "Maubach", "Backnang"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "7271", platform: "1", time: "Fri Jul 19 2019 20:52:00 GMT+0000 (UTC)", stops: ["Filderstadt"] }] }, tracks: [SearchSearchStationsTracks { platform: "SB1", number: "1", name: "Gleis 1", length: Some(251), height: 96 }, SearchSearchStationsTracks { platform: "SB1", number: "2", name: "Gleis 2", length: Some(251), height: 96 }] }, SearchSearchStations { name: "Frankfurt (Main) Flughafen Regionalbahnhof", primary_eva_id: Some(8070004), has_local_public_transport: true, has_taxi_rank: true, has_stepless_access: "partial", has_wi_fi: false, picture: Some(SearchSearchStationsPicture { id: 1849, url: "https://fotos.railway-stations.org/fotos/de/1849_1.jpg", license: "CC0 1.0 Universell (CC0 1.0)", photographer: SearchSearchStationsPicturePhotographer { name: "Rudolf Starosta", url: "https://twitter.com/RudiStarosta" } }), location: Some(SearchSearchStationsLocation { latitude: 50.051219, longitude: 8.571251 }), timetable: SearchSearchStationsTimetable { next_arrivals: [SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "35872", platform: "Regio 3", time: "Fri Jul 19 2019 19:59:00 GMT+0000 (UTC)", stops: ["Offenbach(Main)Ost", "Offenbach(Main) Marktplatz", "Offenbach(Main) Ledermuseum", "Offenbach(Main) Kaiserlei", "Frankfurt(M)Mühlberg", "Frankfurt(M)Ostendstraße", "Frankfurt(M)Konstablerwache", "Frankfurt(M)Hauptwache", "Frankfurt(M)Taunusanlage", "Frankfurt Hbf (tief)", "Frankfurt-Niederrad", "Frankfurt am Main - Stadion"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "35873", platform: "Regio 1", time: "Fri Jul 19 2019 19:59:00 GMT+0000 (UTC)", stops: ["Wiesbaden Hbf", "Wiesbaden Ost", "Mainz Nord", "Mainz Hbf", "Mainz Römisches Theater", "Mainz-Gustavsburg", "Mainz-Bischofsheim", "Rüsselsheim Opelwerk", "Rüsselsheim", "Raunheim", "Kelsterbach"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "35974", platform: "Regio 3", time: "Fri Jul 19 2019 20:14:00 GMT+0000 (UTC)", stops: ["Hanau Hbf", "Steinheim(Main)", "Mühlheim(Main)-Dietesheim", "Mühlheim(Main)", "Offenbach(Main)Ost", "Offenbach(Main) Marktplatz", "Offenbach(Main) Ledermuseum", "Offenbach(Main) Kaiserlei", "Frankfurt(M)Mühlberg", "Frankfurt(M)Ostendstraße", "Frankfurt(M)Konstablerwache", "Frankfurt(M)Hauptwache", "Frankfurt(M)Taunusanlage", "Frankfurt Hbf (tief)", "Frankfurt-Niederrad", "Frankfurt am Main - Stadion"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "35975", platform: "Regio 1", time: "Fri Jul 19 2019 20:14:00 GMT+0000 (UTC)", stops: ["Wiesbaden Hbf", "Wiesbaden Ost", "Mainz-Kastel", "Mainz-Bischofsheim", "Rüsselsheim Opelwerk", "Rüsselsheim", "Raunheim", "Kelsterbach"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "35874", platform: "Regio 3", time: "Fri Jul 19 2019 20:29:00 GMT+0000 (UTC)", stops: ["Offenbach(Main)Ost", "Offenbach(Main) Marktplatz", "Offenbach(Main) Ledermuseum", "Offenbach(Main) Kaiserlei", "Frankfurt(M)Mühlberg", "Frankfurt(M)Ostendstraße", "Frankfurt(M)Konstablerwache", "Frankfurt(M)Hauptwache", "Frankfurt(M)Taunusanlage", "Frankfurt Hbf (tief)", "Frankfurt-Niederrad", "Frankfurt am Main - Stadion"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "35875", platform: "Regio 1", time: "Fri Jul 19 2019 20:29:00 GMT+0000 (UTC)", stops: ["Wiesbaden Hbf", "Wiesbaden Ost", "Mainz Nord", "Mainz Hbf", "Mainz Römisches Theater", "Mainz-Gustavsburg", "Mainz-Bischofsheim", "Rüsselsheim Opelwerk", "Rüsselsheim", "Raunheim", "Kelsterbach"] }, SearchSearchStationsTimetableNextArrivals { type_: "RE", train_number: "29538", platform: "Regio 3", time: "Fri Jul 19 2019 20:36:00 GMT+0000 (UTC)", stops: ["Frankfurt(Main)Hbf"] }, SearchSearchStationsTimetableNextArrivals { type_: "RE", train_number: "4269", platform: "Regio 1", time: "Fri Jul 19 2019 20:36:00 GMT+0000 (UTC)", stops: ["Koblenz Hbf", "Boppard Hbf", "Oberwesel", "Bacharach", "Bingen(Rhein) Hbf", "Bingen(Rhein) Stadt", "Ingelheim", "Mainz Hbf", "Mainz Römisches Theater", "Mainz-Bischofsheim", "Rüsselsheim"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "35977", platform: "Regio 1", time: "Fri Jul 19 2019 20:44:00 GMT+0000 (UTC)", stops: ["Wiesbaden Hbf", "Wiesbaden Ost", "Mainz-Kastel", "Mainz-Bischofsheim", "Rüsselsheim Opelwerk", "Rüsselsheim", "Raunheim", "Kelsterbach"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "35976", platform: "Regio 3", time: "Fri Jul 19 2019 20:44:00 GMT+0000 (UTC)", stops: ["Hanau Hbf", "Steinheim(Main)", "Mühlheim(Main)-Dietesheim", "Mühlheim(Main)", "Offenbach(Main)Ost", "Offenbach(Main) Marktplatz", "Offenbach(Main) Ledermuseum", "Offenbach(Main) Kaiserlei", "Frankfurt(M)Mühlberg", "Frankfurt(M)Ostendstraße", "Frankfurt(M)Konstablerwache", "Frankfurt(M)Hauptwache", "Frankfurt(M)Taunusanlage", "Frankfurt Hbf (tief)", "Frankfurt-Niederrad", "Frankfurt am Main - Stadion"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "35876", platform: "Regio 3", time: "Fri Jul 19 2019 20:59:00 GMT+0000 (UTC)", stops: ["Offenbach(Main)Ost", "Offenbach(Main) Marktplatz", "Offenbach(Main) Ledermuseum", "Offenbach(Main) Kaiserlei", "Frankfurt(M)Mühlberg", "Frankfurt(M)Ostendstraße", "Frankfurt(M)Konstablerwache", "Frankfurt(M)Hauptwache", "Frankfurt(M)Taunusanlage", "Frankfurt Hbf (tief)", "Frankfurt-Niederrad", "Frankfurt am Main - Stadion"] }], next_depatures: [SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "35872", platform: "Regio 3", time: "Fri Jul 19 2019 20:00:00 GMT+0000 (UTC)", stops: ["Kelsterbach", "Raunheim", "Rüsselsheim", "Rüsselsheim Opelwerk", "Mainz-Bischofsheim", "Mainz-Gustavsburg", "Mainz Römisches Theater", "Mainz Hbf", "Mainz Nord", "Wiesbaden Ost", "Wiesbaden Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "35873", platform: "Regio 1", time: "Fri Jul 19 2019 20:01:00 GMT+0000 (UTC)", stops: ["Frankfurt am Main - Stadion", "Frankfurt-Niederrad", "Frankfurt Hbf (tief)", "Frankfurt(M)Taunusanlage", "Frankfurt(M)Hauptwache", "Frankfurt(M)Konstablerwache", "Frankfurt(M)Ostendstraße", "Frankfurt(M)Mühlberg", "Offenbach(Main) Kaiserlei", "Offenbach(Main) Ledermuseum", "Offenbach(Main) Marktplatz", "Offenbach(Main)Ost"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "35974", platform: "Regio 3", time: "Fri Jul 19 2019 20:15:00 GMT+0000 (UTC)", stops: ["Kelsterbach", "Raunheim", "Rüsselsheim", "Rüsselsheim Opelwerk", "Mainz-Bischofsheim", "Mainz-Kastel", "Wiesbaden Ost", "Wiesbaden Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "35975", platform: "Regio 1", time: "Fri Jul 19 2019 20:16:00 GMT+0000 (UTC)", stops: ["Frankfurt am Main - Stadion", "Frankfurt-Niederrad", "Frankfurt Hbf (tief)", "Frankfurt(M)Taunusanlage", "Frankfurt(M)Hauptwache", "Frankfurt(M)Konstablerwache", "Frankfurt(M)Ostendstraße", "Frankfurt(M)Mühlberg", "Offenbach(Main) Kaiserlei", "Offenbach(Main) Ledermuseum", "Offenbach(Main) Marktplatz", "Offenbach(Main)Ost", "Mühlheim(Main)", "Mühlheim(Main)-Dietesheim", "Steinheim(Main)", "Hanau Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "35874", platform: "Regio 3", time: "Fri Jul 19 2019 20:30:00 GMT+0000 (UTC)", stops: ["Kelsterbach", "Raunheim", "Rüsselsheim", "Rüsselsheim Opelwerk", "Mainz-Bischofsheim", "Mainz-Gustavsburg", "Mainz Römisches Theater", "Mainz Hbf", "Mainz Nord", "Wiesbaden Ost", "Wiesbaden Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "35875", platform: "Regio 1", time: "Fri Jul 19 2019 20:31:00 GMT+0000 (UTC)", stops: ["Frankfurt am Main - Stadion", "Frankfurt-Niederrad", "Frankfurt Hbf (tief)", "Frankfurt(M)Taunusanlage", "Frankfurt(M)Hauptwache", "Frankfurt(M)Konstablerwache", "Frankfurt(M)Ostendstraße", "Frankfurt(M)Mühlberg", "Offenbach(Main) Kaiserlei", "Offenbach(Main) Ledermuseum", "Offenbach(Main) Marktplatz", "Offenbach(Main)Ost"] }, SearchSearchStationsTimetableNextDepatures { type_: "RE", train_number: "29538", platform: "Regio 3", time: "Fri Jul 19 2019 20:37:00 GMT+0000 (UTC)", stops: ["Rüsselsheim", "Mainz Hbf", "Ingelheim", "Bad Kreuznach", "Bad Münster a Stein"] }, SearchSearchStationsTimetableNextDepatures { type_: "RE", train_number: "4269", platform: "Regio 1", time: "Fri Jul 19 2019 20:37:00 GMT+0000 (UTC)", stops: ["Frankfurt-Niederrad", "Frankfurt(Main)Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "35976", platform: "Regio 3", time: "Fri Jul 19 2019 20:45:00 GMT+0000 (UTC)", stops: ["Kelsterbach", "Raunheim", "Rüsselsheim", "Rüsselsheim Opelwerk", "Mainz-Bischofsheim", "Mainz-Kastel", "Wiesbaden Ost", "Wiesbaden Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "35977", platform: "Regio 1", time: "Fri Jul 19 2019 20:46:00 GMT+0000 (UTC)", stops: ["Frankfurt am Main - Stadion", "Frankfurt-Niederrad", "Frankfurt Hbf (tief)", "Frankfurt(M)Taunusanlage", "Frankfurt(M)Hauptwache", "Frankfurt(M)Konstablerwache", "Frankfurt(M)Ostendstraße", "Frankfurt(M)Mühlberg", "Offenbach(Main) Kaiserlei", "Offenbach(Main) Ledermuseum", "Offenbach(Main) Marktplatz", "Offenbach(Main)Ost", "Mühlheim(Main)", "Mühlheim(Main)-Dietesheim", "Steinheim(Main)", "Hanau Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "35876", platform: "Regio 3", time: "Fri Jul 19 2019 21:00:00 GMT+0000 (UTC)", stops: ["Kelsterbach", "Raunheim", "Rüsselsheim", "Rüsselsheim Opelwerk", "Mainz-Bischofsheim", "Mainz-Gustavsburg", "Mainz Römisches Theater", "Mainz Hbf", "Mainz Nord", "Wiesbaden Ost", "Wiesbaden Hbf"] }] }, tracks: [SearchSearchStationsTracks { platform: "B01", number: "1", name: "Gleis 1", length: Some(229), height: 76 }, SearchSearchStationsTracks { platform: "B02", number: "2", name: "Gleis 2", length: Some(406), height: 76 }, SearchSearchStationsTracks { platform: "B02", number: "3", name: "Gleis 3", length: Some(406), height: 76 }] }, SearchSearchStations { name: "Hamburg Airport (Flughafen)", primary_eva_id: Some(8002547), has_local_public_transport: true, has_taxi_rank: true, has_stepless_access: "yes", has_wi_fi: false, picture: Some(SearchSearchStationsPicture { id: 2458, url: "https://fotos.railway-stations.org/fotos/de/2458_1.jpg", license: "CC0 1.0 Universell (CC0 1.0)", photographer: SearchSearchStationsPicturePhotographer { name: "@harald_legner", url: "https://twitter.com/harald_legner" } }), location: Some(SearchSearchStationsLocation { latitude: 53.63235, longitude: 10.006646 }), timetable: SearchSearchStationsTimetable { next_arrivals: [SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "47563", platform: "", time: "Fri Jul 19 2019 20:09:00 GMT+0000 (UTC)", stops: ["Hamburg-Altona(S)", "Hamburg Königstraße", "Hamburg Reeperbahn", "Hamburg Landungsbrücken", "Hamburg Stadthausbrücke", "Hamburg Jungfernstieg", "Hamburg Hbf (S-Bahn)", "Hamburg Berliner Tor", "Hamburg Landwehr", "Hamburg Hasselbrook", "Hamburg Wandsbeker Chaussee", "Hamburg Friedrichsberg", "Hamburg-Barmbek", "Hamburg Alte Wöhr", "Hamburg Rübenkamp", "Hamburg-Ohlsdorf"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "47567", platform: "3", time: "Fri Jul 19 2019 20:19:00 GMT+0000 (UTC)", stops: ["Hamburg-Altona(S)", "Hamburg Königstraße", "Hamburg Reeperbahn", "Hamburg Landungsbrücken", "Hamburg Stadthausbrücke", "Hamburg Jungfernstieg", "Hamburg Hbf (S-Bahn)", "Hamburg Berliner Tor", "Hamburg Landwehr", "Hamburg Hasselbrook", "Hamburg Wandsbeker Chaussee", "Hamburg Friedrichsberg", "Hamburg-Barmbek", "Hamburg Alte Wöhr", "Hamburg Rübenkamp", "Hamburg-Ohlsdorf"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "47573", platform: "", time: "Fri Jul 19 2019 20:29:00 GMT+0000 (UTC)", stops: ["Hamburg-Altona(S)", "Hamburg Königstraße", "Hamburg Reeperbahn", "Hamburg Landungsbrücken", "Hamburg Stadthausbrücke", "Hamburg Jungfernstieg", "Hamburg Hbf (S-Bahn)", "Hamburg Berliner Tor", "Hamburg Landwehr", "Hamburg Hasselbrook", "Hamburg Wandsbeker Chaussee", "Hamburg Friedrichsberg", "Hamburg-Barmbek", "Hamburg Alte Wöhr", "Hamburg Rübenkamp", "Hamburg-Ohlsdorf"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "47577", platform: "3", time: "Fri Jul 19 2019 20:39:00 GMT+0000 (UTC)", stops: ["Hamburg-Altona(S)", "Hamburg Königstraße", "Hamburg Reeperbahn", "Hamburg Landungsbrücken", "Hamburg Stadthausbrücke", "Hamburg Jungfernstieg", "Hamburg Hbf (S-Bahn)", "Hamburg Berliner Tor", "Hamburg Landwehr", "Hamburg Hasselbrook", "Hamburg Wandsbeker Chaussee", "Hamburg Friedrichsberg", "Hamburg-Barmbek", "Hamburg Alte Wöhr", "Hamburg Rübenkamp", "Hamburg-Ohlsdorf"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "47583", platform: "", time: "Fri Jul 19 2019 20:49:00 GMT+0000 (UTC)", stops: ["Hamburg-Altona(S)", "Hamburg Königstraße", "Hamburg Reeperbahn", "Hamburg Landungsbrücken", "Hamburg Stadthausbrücke", "Hamburg Jungfernstieg", "Hamburg Hbf (S-Bahn)", "Hamburg Berliner Tor", "Hamburg Landwehr", "Hamburg Hasselbrook", "Hamburg Wandsbeker Chaussee", "Hamburg Friedrichsberg", "Hamburg-Barmbek", "Hamburg Alte Wöhr", "Hamburg Rübenkamp", "Hamburg-Ohlsdorf"] }], next_depatures: [SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "27582", platform: "", time: "Fri Jul 19 2019 20:03:00 GMT+0000 (UTC)", stops: ["Hamburg-Ohlsdorf", "Hamburg Rübenkamp", "Hamburg Alte Wöhr", "Hamburg-Barmbek", "Hamburg Friedrichsberg", "Hamburg Wandsbeker Chaussee", "Hamburg Hasselbrook", "Hamburg Landwehr", "Hamburg Berliner Tor", "Hamburg Hbf (S-Bahn)", "Hamburg Jungfernstieg", "Hamburg Stadthausbrücke", "Hamburg Landungsbrücken", "Hamburg Reeperbahn", "Hamburg Königstraße", "Hamburg-Altona(S)"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "27586", platform: "3", time: "Fri Jul 19 2019 20:13:00 GMT+0000 (UTC)", stops: ["Hamburg-Ohlsdorf", "Hamburg Rübenkamp", "Hamburg Alte Wöhr", "Hamburg-Barmbek", "Hamburg Friedrichsberg", "Hamburg Wandsbeker Chaussee", "Hamburg Hasselbrook", "Hamburg Landwehr", "Hamburg Berliner Tor", "Hamburg Hbf (S-Bahn)", "Hamburg Jungfernstieg", "Hamburg Stadthausbrücke", "Hamburg Landungsbrücken", "Hamburg Reeperbahn", "Hamburg Königstraße", "Hamburg-Altona(S)"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "27592", platform: "", time: "Fri Jul 19 2019 20:23:00 GMT+0000 (UTC)", stops: ["Hamburg-Ohlsdorf", "Hamburg Rübenkamp", "Hamburg Alte Wöhr", "Hamburg-Barmbek", "Hamburg Friedrichsberg", "Hamburg Wandsbeker Chaussee", "Hamburg Hasselbrook", "Hamburg Landwehr", "Hamburg Berliner Tor", "Hamburg Hbf (S-Bahn)", "Hamburg Jungfernstieg", "Hamburg Stadthausbrücke", "Hamburg Landungsbrücken", "Hamburg Reeperbahn", "Hamburg Königstraße", "Hamburg-Altona(S)"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "27596", platform: "3", time: "Fri Jul 19 2019 20:33:00 GMT+0000 (UTC)", stops: ["Hamburg-Ohlsdorf", "Hamburg Rübenkamp", "Hamburg Alte Wöhr", "Hamburg-Barmbek", "Hamburg Friedrichsberg", "Hamburg Wandsbeker Chaussee", "Hamburg Hasselbrook", "Hamburg Landwehr", "Hamburg Berliner Tor", "Hamburg Hbf (S-Bahn)", "Hamburg Jungfernstieg", "Hamburg Stadthausbrücke", "Hamburg Landungsbrücken", "Hamburg Reeperbahn", "Hamburg Königstraße", "Hamburg-Altona(S)"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "27602", platform: "", time: "Fri Jul 19 2019 20:43:00 GMT+0000 (UTC)", stops: ["Hamburg-Ohlsdorf", "Hamburg Rübenkamp", "Hamburg Alte Wöhr", "Hamburg-Barmbek", "Hamburg Friedrichsberg", "Hamburg Wandsbeker Chaussee", "Hamburg Hasselbrook", "Hamburg Landwehr", "Hamburg Berliner Tor", "Hamburg Hbf (S-Bahn)", "Hamburg Jungfernstieg", "Hamburg Stadthausbrücke", "Hamburg Landungsbrücken", "Hamburg Reeperbahn", "Hamburg Königstraße", "Hamburg-Altona(S)"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "27606", platform: "3", time: "Fri Jul 19 2019 20:53:00 GMT+0000 (UTC)", stops: ["Hamburg-Ohlsdorf", "Hamburg Rübenkamp", "Hamburg Alte Wöhr", "Hamburg-Barmbek", "Hamburg Friedrichsberg", "Hamburg Wandsbeker Chaussee", "Hamburg Hasselbrook", "Hamburg Landwehr", "Hamburg Berliner Tor", "Hamburg Hbf (S-Bahn)", "Hamburg Jungfernstieg", "Hamburg Stadthausbrücke", "Hamburg Landungsbrücken", "Hamburg Reeperbahn", "Hamburg Königstraße", "Hamburg-Altona(S)"] }] }, tracks: [SearchSearchStationsTracks { platform: "SB1", number: "3", name: "Gleis 3", length: Some(152), height: 96 }, SearchSearchStationsTracks { platform: "SB1", number: "4", name: "Gleis 4", length: Some(152), height: 96 }] }, SearchSearchStations { name: "Lübeck-Flughafen", primary_eva_id: Some(8003781), has_local_public_transport: false, has_taxi_rank: true, has_stepless_access: "yes", has_wi_fi: false, picture: Some(SearchSearchStationsPicture { id: 3808, url: "https://fotos.railway-stations.org/fotos/de/3808_1.jpg", license: "CC0 1.0 Universell (CC0 1.0)", photographer: SearchSearchStationsPicturePhotographer { name: "Gaby Becker", url: "http://www.gaby-becker.de" } }), location: Some(SearchSearchStationsLocation { latitude: 53.804129, longitude: 10.697484 }), timetable: SearchSearchStationsTimetable { next_arrivals: [SearchSearchStationsTimetableNextArrivals { type_: "RE", train_number: "21837", platform: "1", time: "Fri Jul 19 2019 20:18:00 GMT+0000 (UTC)", stops: ["Lübeck Hbf", "Lübeck Hochschulstadtteil"] }], next_depatures: [SearchSearchStationsTimetableNextDepatures { type_: "RE", train_number: "21837", platform: "1", time: "Fri Jul 19 2019 20:19:00 GMT+0000 (UTC)", stops: ["Ratzeburg", "Mölln(Lauenb)", "Büchen", "Lauenburg(Elbe)", "Echem", "Lüneburg"] }] }, tracks: [SearchSearchStationsTracks { platform: "B01", number: "1", name: "Gleis 1", length: Some(100), height: 76 }] }, SearchSearchStations { name: "Köln/Bonn Flughafen", primary_eva_id: Some(8003330), has_local_public_transport: true, has_taxi_rank: true, has_stepless_access: "yes", has_wi_fi: false, picture: Some(SearchSearchStationsPicture { id: 4762, url: "https://fotos.railway-stations.org/fotos/de/4762_1.jpg", license: "CC0 1.0 Universell (CC0 1.0)", photographer: SearchSearchStationsPicturePhotographer { name: "Rudolf Starosta", url: "https://twitter.com/RudiStarosta" } }), location: Some(SearchSearchStationsLocation { latitude: 50.878901, longitude: 7.119302 }), timetable: SearchSearchStationsTimetable { next_arrivals: [SearchSearchStationsTimetableNextArrivals { type_: "RE", train_number: "69732", platform: "4", time: "Fri Jul 19 2019 20:11:00 GMT+0000 (UTC)", stops: ["Düsseldorf Hbf", "Neuss Hbf", "Dormagen", "Köln Hbf", "Köln Messe/Deutz"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "33375", platform: "2", time: "Fri Jul 19 2019 20:23:00 GMT+0000 (UTC)", stops: ["Troisdorf", "Spich", "Porz-Wahn"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "33390", platform: "4", time: "Fri Jul 19 2019 20:25:00 GMT+0000 (UTC)", stops: ["Sindorf", "Horrem", "Frechen-Königsdorf", "Köln-Weiden West", "Lövenich", "Köln-Müngersdorf Technologiepark", "Köln-Ehrenfeld", "Köln Hansaring", "Köln Hbf", "Köln Messe/Deutz Gl. 9-10", "Köln Trimbornstr", "Köln Frankfurter Straße"] }, SearchSearchStationsTimetableNextArrivals { type_: "ICE", train_number: "619", platform: "4", time: "Fri Jul 19 2019 20:41:00 GMT+0000 (UTC)", stops: ["Düsseldorf Hbf", "Köln Hbf"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "33377", platform: "2", time: "Fri Jul 19 2019 20:53:00 GMT+0000 (UTC)", stops: ["Hennef(Sieg)", "Siegburg/Bonn", "Troisdorf", "Spich", "Porz-Wahn"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "33392", platform: "3", time: "Fri Jul 19 2019 20:55:00 GMT+0000 (UTC)", stops: ["Düren", "Merzenich", "Buir", "Sindorf", "Horrem", "Frechen-Königsdorf", "Köln-Weiden West", "Lövenich", "Köln-Müngersdorf Technologiepark", "Köln-Ehrenfeld", "Köln Hansaring", "Köln Hbf", "Köln Messe/Deutz Gl. 9-10", "Köln Trimbornstr", "Köln Frankfurter Straße"] }], next_depatures: [SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "33375", platform: "2", time: "Fri Jul 19 2019 20:24:00 GMT+0000 (UTC)", stops: ["Köln Frankfurter Straße", "Köln Trimbornstr", "Köln Messe/Deutz Gl. 9-10", "Köln Hbf", "Köln Hansaring", "Köln-Ehrenfeld", "Köln-Müngersdorf Technologiepark", "Lövenich", "Köln-Weiden West", "Frechen-Königsdorf", "Horrem", "Sindorf", "Buir", "Merzenich", "Düren"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "33390", platform: "4", time: "Fri Jul 19 2019 20:26:00 GMT+0000 (UTC)", stops: ["Porz-Wahn", "Spich", "Troisdorf"] }, SearchSearchStationsTimetableNextDepatures { type_: "ICE", train_number: "619", platform: "4", time: "Fri Jul 19 2019 20:43:00 GMT+0000 (UTC)", stops: ["Siegburg/Bonn", "Montabaur", "Limburg Süd", "Frankfurt(M) Flughafen Fernbf", "Frankfurt(Main)Hbf", "Frankfurt(M) Flughafen Fernbf", "Mannheim Hbf", "Bruchsal", "Karlsruhe-Durlach", "Karlsruhe Hbf", "Pforzheim Hbf", "Vaihingen(Enz)", "Ludwigsburg", "Stuttgart Hbf", "Plochingen", "Ulm Hbf", "Günzburg", "Augsburg Hbf", "München-Pasing", "München Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "RE", train_number: "69741", platform: "1", time: "Fri Jul 19 2019 20:48:00 GMT+0000 (UTC)", stops: ["Köln Messe/Deutz", "Köln Hbf", "Dormagen", "Neuss Hbf", "Düsseldorf Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "33377", platform: "2", time: "Fri Jul 19 2019 20:54:00 GMT+0000 (UTC)", stops: ["Köln Frankfurter Straße", "Köln Trimbornstr", "Köln Messe/Deutz Gl. 9-10", "Köln Hbf", "Köln Hansaring", "Köln-Ehrenfeld", "Köln-Müngersdorf Technologiepark", "Lövenich", "Köln-Weiden West", "Frechen-Königsdorf", "Horrem", "Sindorf"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "33392", platform: "3", time: "Fri Jul 19 2019 20:56:00 GMT+0000 (UTC)", stops: ["Porz-Wahn", "Spich", "Troisdorf", "Siegburg/Bonn", "Hennef(Sieg)"] }] }, tracks: [SearchSearchStationsTracks { platform: "B01", number: "1", name: "Gleis 1", length: Some(419), height: 76 }, SearchSearchStationsTracks { platform: "B01", number: "2", name: "Gleis 2", length: Some(419), height: 96 }, SearchSearchStationsTracks { platform: "B02", number: "3", name: "Gleis 3", length: Some(419), height: 96 }, SearchSearchStationsTracks { platform: "B02", number: "4", name: "Gleis 4", length: Some(419), height: 76 }] }, SearchSearchStations { name: "Friedrichshafen Flughafen", primary_eva_id: Some(8002120), has_local_public_transport: true, has_taxi_rank: false, has_stepless_access: "yes", has_wi_fi: false, picture: Some(SearchSearchStationsPicture { id: 5987, url: "https://fotos.railway-stations.org/fotos/de/5987.jpg", license: "CC0 1.0 Universell (CC0 1.0)", photographer: SearchSearchStationsPicturePhotographer { name: "AndreasFranz", url: "https://railway-stations.org" } }), location: Some(SearchSearchStationsLocation { latitude: 47.672213, longitude: 9.523714 }), timetable: SearchSearchStationsTimetable { next_arrivals: [SearchSearchStationsTimetableNextArrivals { type_: "RE", train_number: "4240", platform: "1", time: "Fri Jul 19 2019 20:40:00 GMT+0000 (UTC)", stops: ["Friedrichshafen Stadt"] }], next_depatures: [SearchSearchStationsTimetableNextDepatures { type_: "RE", train_number: "4240", platform: "1", time: "Fri Jul 19 2019 20:40:00 GMT+0000 (UTC)", stops: ["Meckenbeuren", "Ravensburg", "Aulendorf", "Bad Schussenried", "Biberach(Riß)", "Schemmerberg", "Laupheim West", "Erbach(Württ)", "Ulm Hbf"] }] }, tracks: [SearchSearchStationsTracks { platform: "B01", number: "1", name: "Gleis 1", length: Some(171), height: 55 }, SearchSearchStationsTracks { platform: "B02", number: "2", name: "Gleis 2", length: Some(171), height: 55 }] }, SearchSearchStations { name: "Hannover-Flughafen", primary_eva_id: Some(8002589), has_local_public_transport: true, has_taxi_rank: true, has_stepless_access: "yes", has_wi_fi: false, picture: Some(SearchSearchStationsPicture { id: 7180, url: "https://fotos.railway-stations.org/fotos/de/7180.jpg", license: "CC0 1.0 Universell (CC0 1.0)", photographer: SearchSearchStationsPicturePhotographer { name: "N0rwi", url: "https://www.twitter.com/N0rwi" } }), location: Some(SearchSearchStationsLocation { latitude: 52.458725, longitude: 9.699105 }), timetable: SearchSearchStationsTimetable { next_arrivals: [SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "34588", platform: "1", time: "Fri Jul 19 2019 20:23:00 GMT+0000 (UTC)", stops: ["Paderborn Hbf", "Altenbeken", "Steinheim(Westf)", "Schieder", "Lügde", "Bad Pyrmont", "Emmerthal", "Hameln", "Bad Münder(Deister)", "Springe", "Völksen/Eldagsen", "Bennigsen", "Holtensen/Linderte", "Weetzen", "Hannover-Linden/Fischerhof", "Hannover Bismarckstr.", "Hannover Hbf", "Hannover-Nordstadt", "Hannover-Ledeburg", "Hannover-Vinnhorst", "Langenhagen Mitte", "Langenhagen Pferdemarkt"] }], next_depatures: [SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "34591", platform: "1", time: "Fri Jul 19 2019 20:36:00 GMT+0000 (UTC)", stops: ["Langenhagen Pferdemarkt", "Langenhagen Mitte", "Hannover-Vinnhorst", "Hannover-Ledeburg", "Hannover-Nordstadt", "Hannover Hbf", "Hannover Bismarckstr.", "Hannover-Linden/Fischerhof", "Weetzen", "Holtensen/Linderte", "Bennigsen", "Völksen/Eldagsen", "Springe", "Bad Münder(Deister)", "Hameln", "Emmerthal", "Bad Pyrmont", "Lügde", "Schieder", "Steinheim(Westf)", "Altenbeken", "Paderborn Hbf"] }] }, tracks: [SearchSearchStationsTracks { platform: "SB1", number: "1", name: "Gleis 1", length: Some(214), height: 76 }, SearchSearchStationsTracks { platform: "SB1", number: "2", name: "Gleis 2", length: Some(214), height: 76 }] }, SearchSearchStations { name: "Frankfurt am Main Flughafen Fernbahnhof", primary_eva_id: Some(8070003), has_local_public_transport: true, has_taxi_rank: true, has_stepless_access: "yes", has_wi_fi: true, picture: Some(SearchSearchStationsPicture { id: 7982, url: "https://fotos.railway-stations.org/fotos/de/7982_2.jpg", license: "CC0 1.0 Universell (CC0 1.0)", photographer: SearchSearchStationsPicturePhotographer { name: "@khgdrn", url: "https://twitter.com/khgdrn" } }), location: Some(SearchSearchStationsLocation { latitude: 50.053167, longitude: 8.570185 }), timetable: SearchSearchStationsTimetable { next_arrivals: [SearchSearchStationsTimetableNextArrivals { type_: "ICE", train_number: "22", platform: "Fern 7", time: "Fri Jul 19 2019 19:58:00 GMT+0000 (UTC)", stops: ["Passau Hbf", "Plattling", "Regensburg Hbf", "Nürnberg Hbf", "Würzburg Hbf", "Hanau Hbf", "Frankfurt(Main)Hbf"] }, SearchSearchStationsTimetableNextArrivals { type_: "IC", train_number: "2029", platform: "Fern 4", time: "Fri Jul 19 2019 19:59:00 GMT+0000 (UTC)", stops: ["Hamburg-Altona", "Hamburg Dammtor", "Hamburg Hbf", "Hamburg-Harburg", "Bremen Hbf", "Osnabrück Hbf", "Münster(Westf)Hbf", "Dortmund Hbf", "Wuppertal Hbf", "Solingen Hbf", "Köln Hbf", "Bonn Hbf", "Koblenz Hbf", "Bingen(Rhein) Hbf", "Mainz Hbf"] }, SearchSearchStationsTimetableNextArrivals { type_: "ICE", train_number: "100", platform: "Fern 6", time: "Fri Jul 19 2019 20:06:00 GMT+0000 (UTC)", stops: ["Basel SBB", "Basel Bad Bf", "Freiburg(Breisgau) Hbf", "Offenburg", "Baden-Baden", "Karlsruhe Hbf", "Mannheim Hbf"] }, SearchSearchStationsTimetableNextArrivals { type_: "ICE", train_number: "221", platform: "Fern 5", time: "Fri Jul 19 2019 20:16:00 GMT+0000 (UTC)", stops: ["Amsterdam Centraal", "Utrecht Centraal", "Arnhem Centraal", "Oberhausen Hbf", "Duisburg Hbf", "Düsseldorf Hbf", "Köln Messe/Deutz Gl.11-12"] }, SearchSearchStationsTimetableNextArrivals { type_: "ICE", train_number: "524", platform: "Fern 7", time: "Fri Jul 19 2019 20:22:00 GMT+0000 (UTC)", stops: ["München Hbf", "Nürnberg Hbf", "Würzburg Hbf", "Aschaffenburg Hbf", "Frankfurt(Main)Hbf"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "35877", platform: "Regio 2", time: "Fri Jul 19 2019 20:58:00 GMT+0000 (UTC)", stops: ["Wiesbaden Hbf", "Wiesbaden Ost", "Mainz Nord", "Mainz Hbf", "Mainz Römisches Theater", "Mainz-Gustavsburg", "Mainz-Bischofsheim", "Rüsselsheim Opelwerk", "Rüsselsheim", "Raunheim"] }, SearchSearchStationsTimetableNextArrivals { type_: "IC", train_number: "2315", platform: "Fern 4", time: "Fri Jul 19 2019 20:59:00 GMT+0000 (UTC)", stops: ["Husum", "Heide(Holst)", "Itzehoe", "Hamburg Dammtor", "Hamburg Hbf", "Hamburg-Harburg", "Bremen Hbf", "Osnabrück Hbf", "Münster(Westf)Hbf", "Recklinghausen Hbf", "Gelsenkirchen Hbf", "Duisburg Hbf", "Düsseldorf Hbf", "Köln Hbf", "Bonn Hbf", "Koblenz Hbf", "Mainz Hbf"] }], next_depatures: [SearchSearchStationsTimetableNextDepatures { type_: "ICE", train_number: "22", platform: "Fern 7", time: "Fri Jul 19 2019 20:00:00 GMT+0000 (UTC)", stops: ["Mainz Hbf", "Koblenz Hbf", "Bonn Hbf", "Köln Hbf", "Düsseldorf Hbf", "Duisburg Hbf", "Gelsenkirchen Hbf", "Dortmund Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "IC", train_number: "2029", platform: "Fern 4", time: "Fri Jul 19 2019 20:02:00 GMT+0000 (UTC)", stops: ["Frankfurt(Main)Hbf", "Hanau Hbf", "Aschaffenburg Hbf", "Würzburg Hbf", "Fürth(Bay)Hbf", "Nürnberg Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "ICE", train_number: "100", platform: "Fern 6", time: "Fri Jul 19 2019 20:09:00 GMT+0000 (UTC)", stops: ["Siegburg/Bonn", "Köln Hbf", "Düsseldorf Hbf", "Duisburg Hbf", "Gelsenkirchen Hbf", "Dortmund Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "ICE", train_number: "221", platform: "Fern 5", time: "Fri Jul 19 2019 20:18:00 GMT+0000 (UTC)", stops: ["Frankfurt(Main)Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "ICE", train_number: "524", platform: "Fern 7", time: "Fri Jul 19 2019 20:25:00 GMT+0000 (UTC)", stops: ["Limburg Süd", "Montabaur", "Siegburg/Bonn", "Köln/Bonn Flughafen", "Köln Messe/Deutz Gl.11-12", "Düsseldorf Hbf", "Duisburg Hbf", "Oberhausen Hbf", "Gelsenkirchen Hbf", "Dortmund Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "35877", platform: "Regio 2", time: "Fri Jul 19 2019 20:58:00 GMT+0000 (UTC)", stops: ["Frankfurt am Main - Stadion", "Frankfurt-Niederrad", "Frankfurt Hbf (tief)", "Frankfurt(M)Taunusanlage", "Frankfurt(M)Hauptwache", "Frankfurt(M)Konstablerwache", "Frankfurt(M)Ostendstraße", "Frankfurt(M)Mühlberg", "Offenbach(Main) Kaiserlei", "Offenbach(Main) Ledermuseum", "Offenbach(Main) Marktplatz", "Offenbach(Main)Ost"] }, SearchSearchStationsTimetableNextDepatures { type_: "IC", train_number: "2315", platform: "Fern 4", time: "Fri Jul 19 2019 21:01:00 GMT+0000 (UTC)", stops: ["Frankfurt(Main)Hbf"] }] }, tracks: [SearchSearchStationsTracks { platform: "B01", number: "4", name: "Gleis 4", length: Some(430), height: 76 }, SearchSearchStationsTracks { platform: "B01", number: "5", name: "Gleis 5", length: Some(430), height: 76 }, SearchSearchStationsTracks { platform: "B02", number: "6", name: "Gleis 6", length: Some(430), height: 76 }, SearchSearchStationsTracks { platform: "B02", number: "7", name: "Gleis 7", length: Some(430), height: 76 }] }, SearchSearchStations { name: "Flughafen Leipzig/Halle", primary_eva_id: Some(8012183), has_local_public_transport: true, has_taxi_rank: true, has_stepless_access: "yes", has_wi_fi: false, picture: Some(SearchSearchStationsPicture { id: 8015, url: "https://fotos.railway-stations.org/fotos/de/8015.jpg", license: "CC BY-SA 4.0", photographer: SearchSearchStationsPicturePhotographer { name: "@tmmd", url: "https://www.euroreiseblog.de" } }), location: Some(SearchSearchStationsLocation { latitude: 51.423338, longitude: 12.223426 }), timetable: SearchSearchStationsTimetable { next_arrivals: [SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "37586", platform: "", time: "Fri Jul 19 2019 20:07:00 GMT+0000 (UTC)", stops: ["Altenburg", "Treben-Lehma", "Regis-Breitingen", "Deutzen", "Neukieritzsch", "Böhlen Werke", "Böhlen(Leipzig)", "Markkleeberg", "Markkleeberg Nord", "Leipzig-Connewitz", "Leipzig MDR", "Leipzig Bayerischer Bahnhof", "Leipzig Wilhelm-Leuschner-Platz", "Leipzig Markt", "Leipzig Hbf (tief)", "Leipzig Messe"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "37589", platform: "1", time: "Fri Jul 19 2019 20:24:00 GMT+0000 (UTC)", stops: ["Halle(Saale)Hbf"] }, SearchSearchStationsTimetableNextArrivals { type_: "IC", train_number: "2435", platform: "1", time: "Fri Jul 19 2019 20:30:00 GMT+0000 (UTC)", stops: ["Norddeich Mole", "Norddeich", "Norden", "Marienhafe", "Emden Hbf", "Leer(Ostfriesl)", "Augustfehn", "Westerstede-Ocholt", "Bad Zwischenahn", "Oldenburg(Oldb)", "Hude", "Delmenhorst", "Bremen Hbf", "Verden(Aller)", "Nienburg(Weser)", "Hannover Hbf", "Braunschweig Hbf", "Helmstedt", "Magdeburg Hbf", "Dessau Hbf", "Bitterfeld", "Halle(Saale)Hbf"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "37536", platform: "1", time: "Fri Jul 19 2019 20:38:00 GMT+0000 (UTC)", stops: ["Altenburg", "Böhlen(Leipzig)", "Markkleeberg", "Markkleeberg Nord", "Leipzig-Connewitz", "Leipzig MDR", "Leipzig Bayerischer Bahnhof", "Leipzig Wilhelm-Leuschner-Platz", "Leipzig Markt", "Leipzig Hbf (tief)", "Leipzig Messe"] }], next_depatures: [SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "37589", platform: "1", time: "Fri Jul 19 2019 20:25:00 GMT+0000 (UTC)", stops: ["Leipzig Messe", "Leipzig Hbf (tief)", "Leipzig Markt", "Leipzig Wilhelm-Leuschner-Platz", "Leipzig Bayerischer Bahnhof", "Leipzig MDR", "Leipzig-Connewitz"] }, SearchSearchStationsTimetableNextDepatures { type_: "IC", train_number: "2435", platform: "1", time: "Fri Jul 19 2019 20:32:00 GMT+0000 (UTC)", stops: ["Leipzig Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "37536", platform: "1", time: "Fri Jul 19 2019 20:38:00 GMT+0000 (UTC)", stops: ["Halle(Saale)Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "37591", platform: "2", time: "Fri Jul 19 2019 20:41:00 GMT+0000 (UTC)", stops: ["Leipzig Messe", "Leipzig Hbf (tief)", "Leipzig Markt", "Leipzig Wilhelm-Leuschner-Platz", "Leipzig Bayerischer Bahnhof", "Leipzig MDR", "Leipzig-Connewitz", "Markkleeberg Nord", "Markkleeberg", "Böhlen(Leipzig)", "Böhlen Werke", "Neukieritzsch", "Deutzen", "Regis-Breitingen", "Treben-Lehma", "Altenburg"] }] }, tracks: [SearchSearchStationsTracks { platform: "B01", number: "1", name: "Gleis 1", length: Some(405), height: 55 }, SearchSearchStationsTracks { platform: "B02", number: "2", name: "Gleis 2", length: Some(405), height: 55 }] }, SearchSearchStations { name: "Dresden Flughafen", primary_eva_id: Some(8011399), has_local_public_transport: true, has_taxi_rank: false, has_stepless_access: "yes", has_wi_fi: false, picture: None, location: Some(SearchSearchStationsLocation { latitude: 51.124665, longitude: 13.765993 }), timetable: SearchSearchStationsTimetable { next_arrivals: [SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "32772", platform: "2", time: "Fri Jul 19 2019 20:09:00 GMT+0000 (UTC)", stops: ["Dresden Hbf", "Dresden Freiberger Straße", "Dresden Mitte", "Dresden-Neustadt", "Dresden Industriegelände", "Dresden-Klotzsche", "Dresden Grenzstraße"] }, SearchSearchStationsTimetableNextArrivals { type_: "S", train_number: "32774", platform: "1", time: "Fri Jul 19 2019 20:39:00 GMT+0000 (UTC)", stops: ["Dresden Hbf", "Dresden Freiberger Straße", "Dresden Mitte", "Dresden-Neustadt", "Dresden Industriegelände", "Dresden-Klotzsche", "Dresden Grenzstraße"] }], next_depatures: [SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "32773", platform: "2", time: "Fri Jul 19 2019 20:18:00 GMT+0000 (UTC)", stops: ["Dresden Grenzstraße", "Dresden-Klotzsche", "Dresden Industriegelände", "Dresden-Neustadt", "Dresden Mitte", "Dresden Freiberger Straße", "Dresden Hbf"] }, SearchSearchStationsTimetableNextDepatures { type_: "S", train_number: "32775", platform: "1", time: "Fri Jul 19 2019 20:48:00 GMT+0000 (UTC)", stops: ["Dresden Grenzstraße", "Dresden-Klotzsche", "Dresden Industriegelände", "Dresden-Neustadt", "Dresden Mitte", "Dresden Freiberger Straße", "Dresden Hbf"] }] }, tracks: [SearchSearchStationsTracks { platform: "B01", number: "1", name: "Gleis 1", length: Some(140), height: 55 }, SearchSearchStationsTracks { platform: "B01", number: "2", name: "Gleis 2", length: Some(140), height: 55 }] }] } }), errors: None } +\ No newline at end of file diff --git a/src/api_provider.rs b/src/api_provider.rs @@ -0,0 +1,172 @@ +use juniper::{EmptyMutation, Value}; +use rocket::response::content; +use rocket::State; + +#[derive(juniper::GraphQLObject)] +struct TrainMovement { + movement_type: String, + train_number: String, + platform: String, + time: String, + stops: Vec<String>, +} + +#[derive(juniper::GraphQLObject)] +struct Timetables { + next_arrivals: Vec<TrainMovement>, + next_depatures: Vec<TrainMovement>, +} + +#[derive(juniper::GraphQLObject)] +struct Location { + latitude: f64, + longitude: f64, +} + +#[derive(juniper::GraphQLObject)] +#[graphql(description = "A Station in the Bahn Universe")] +struct Station { + name: String, + primary_eva_id: Option<i32>, + has_local_public_transport: bool, + has_taxi_rank: bool, + has_stepless_access: bool, + has_wifi: bool, + location: Option<Location>, + timetables: Timetables, +} + +#[derive(juniper::GraphQLObject)] +#[graphql(description = "A Space in the Space API")] +struct Space { + #[graphql(description = "The human readable name of a *Space")] + name: String, + #[graphql(description = "All Bahn Stations in a radius of 2000m")] + stations: Vec<Station>, +} + +struct Query; + +enum NotFoundErr { + NotFound, +} + +impl juniper::IntoFieldError for NotFoundErr { + fn into_field_error(self) -> juniper::FieldError { + match self { + NotFoundErr::NotFound => { + juniper::FieldError::new("The searched space does not exist", Value::null()) + } + } + } +} + +#[juniper::object] +impl Query { + fn apiVersion() -> &str { + "0.1.0" + } + + fn space(name: String) -> Result<Space, NotFoundErr> { + let searched_space_coordinates = crate::spaceapi::find_space(&name); + match searched_space_coordinates { + Ok(searched_space_coordinates_unpacked) => { + let stations = crate::bahnapi::nearby( + searched_space_coordinates_unpacked["lat"], + searched_space_coordinates_unpacked["lon"], + Some(2000), + Some(20), + ); + let mut stations_usable = Vec::new(); + + if let Ok(x) = stations { + let data = x.data.unwrap(); + let nearby_stations = data.nearby.stations; + for station in nearby_stations.into_iter() { + let primary_eva_id: Option<i32>; + if station.primary_eva_id.is_some() { + let primary_eva_id_raw: i32 = station.primary_eva_id.unwrap() as i32; + primary_eva_id = Some(primary_eva_id_raw); + } else { + primary_eva_id = None; + } + let has_stepless_access: bool; + if station.has_stepless_access == "yes" { + has_stepless_access = true + } else { + has_stepless_access = false + } + let location: Option<Location>; + if station.location.is_some() { + let location_bahn = station.location.unwrap(); + location = Some(Location { + latitude: location_bahn.latitude, + longitude: location_bahn.longitude, + }); + } else { + location = None; + } + let station_usable = Station { + name: station.name, + primary_eva_id, + has_local_public_transport: station.has_local_public_transport, + has_taxi_rank: station.has_taxi_rank, + has_stepless_access, + has_wifi: station.has_wi_fi, + location, + timetables: Timetables { + next_arrivals: vec![], + next_depatures: vec![], + }, + }; + stations_usable.push(station_usable); + } + } + let space = Space { + name, + stations: stations_usable, + }; + return Ok(space); + } + Err(e) => { + error!("{:?}", e); + } + } + Err(NotFoundErr::NotFound) + } +} + +// A root schema consists of a query and a mutation. +// Request queries can be executed against a RootNode. +type Schema = juniper::RootNode<'static, Query, EmptyMutation<()>>; + +#[rocket::get("/")] +fn graphiql() -> content::Html<String> { + juniper_rocket::graphiql_source("/graphql") +} + +#[rocket::get("/graphql?<request>")] +fn get_graphql_handler( + request: juniper_rocket::GraphQLRequest, + schema: State<Schema>, +) -> juniper_rocket::GraphQLResponse { + request.execute(&schema, &()) +} + +#[rocket::post("/graphql", data = "<request>")] +fn post_graphql_handler( + request: juniper_rocket::GraphQLRequest, + schema: State<Schema>, +) -> juniper_rocket::GraphQLResponse { + request.execute(&schema, &()) +} + +pub fn start_api() { + rocket::ignite() + .manage(Schema::new(Query, EmptyMutation::<()>::new())) + .mount( + "/", + rocket::routes![graphiql, get_graphql_handler, post_graphql_handler], + ) + .launch(); +} diff --git a/src/bahnapi.rs b/src/bahnapi.rs @@ -0,0 +1,76 @@ +use graphql_client::*; +use std::fs; + +#[derive(GraphQLQuery)] +#[graphql( + schema_path = "bahn_definitions/schema.graphql", + query_path = "bahn_definitions/search.graphql", + response_derives = "Debug" +)] +pub struct Search; + +#[derive(GraphQLQuery)] +#[graphql( + schema_path = "bahn_definitions/schema.graphql", + query_path = "bahn_definitions/nearby.graphql", + response_derives = "Debug" +)] +pub struct Nearby; + +pub fn search(search_term: String) -> Result<(), failure::Error> { + let q = Search::build_query(search::Variables { + search_term: Some(search_term), + }); + + let client = reqwest::Client::new(); + + let mut res = client + .post("https://api.deutschebahn.com/free1bahnql/v1/graphql") + .bearer_auth("6fc6827d4628e9568210eed4a22fa8b5") + .json(&q) + .send()?; + let response_body: Response<search::ResponseData> = res.json()?; + //println!("{:?}", response_body); + fs::write("./search.json", format!("{:?}", response_body)).expect("Unable to write file"); + if let Some(errors) = response_body.errors { + println!("there are errors:"); + + for error in &errors { + println!("{:?}", error); + } + } + Ok(()) +} + +pub fn nearby( + lat: f64, + long: f64, + radius: Option<i64>, + count: Option<i64>, +) -> Result<Response<nearby::ResponseData>, failure::Error> { + let q = Nearby::build_query(nearby::Variables { + latitude: lat, + longitude: long, + radius, + count, + }); + + let client = reqwest::Client::new(); + + let mut res = client + .post("https://api.deutschebahn.com/free1bahnql/v1/graphql") + .bearer_auth("6fc6827d4628e9568210eed4a22fa8b5") + .json(&q) + .send()?; + let response_body: Response<nearby::ResponseData> = res.json()?; + //println!("{:?}", response_body); + fs::write("./nearby.json", format!("{:?}", response_body)).expect("Unable to write file"); + if let Some(errors) = &response_body.errors { + println!("there are errors:"); + + for error in errors { + println!("{:?}", error); + } + } + Ok(response_body) +} diff --git a/src/main.rs b/src/main.rs @@ -0,0 +1,19 @@ +#![feature(decl_macro, proc_macro_hygiene)] + +#[macro_use] +extern crate log; +extern crate env_logger; + +mod api_provider; +mod bahnapi; +mod spaceapi; + +fn main() -> Result<(), failure::Error> { + //env_logger::init(); + //bahnapi::search("CBase".to_string()); + // 2000km is the default magic number for max travel from station to space + //bahnapi::nearby(54.303623,10.124862,Some(2000), Some(10)); + //println!("{:?}", spaceapi::get_spaces().unwrap()); + api_provider::start_api(); + Ok(()) +} diff --git a/src/spaceapi.rs b/src/spaceapi.rs @@ -0,0 +1,208 @@ +use reqwest::StatusCode; +use serde::*; +use serde_json::Value; +use std::collections::HashMap; +use std::fs; +use std::fs::File; +use std::path::Path; +use std::time::{Duration, SystemTime}; +use std::io::BufReader; + +fn get_spaces_web() -> Result<HashMap<String, HashMap<String, f64>>, failure::Error> { + let client = reqwest::Client::builder() + .gzip(true) + .timeout(Duration::from_secs(10)) + .build()?; + + let mut res = client.get("https://directory.spaceapi.io/").send()?; + + let json: Value = res.json()?; + + fs::create_dir_all("./tmp/")?; + let serialized = serde_json::to_string(&json).unwrap(); + fs::write("./tmp/spaces.json", serialized).expect("Unable to write file"); + + let mut spaces = HashMap::new(); + for (key, value) in json.as_object().unwrap().iter() { + let space: Result<HashMap<String, f64>, failure::Error> = get_space( + key.as_str().to_string(), + value.as_str().unwrap().to_string(), + ); + if space.is_ok() { + spaces.insert(key.to_string(), space.unwrap()); + } + } + + //println!("{:?}", json); + Ok(spaces) +} + +pub fn get_spaces() -> Result<HashMap<String, HashMap<String, f64>>, failure::Error> { + if Path::new("./tmp/spaces.json").exists() { + let cache_data = fs::metadata("./tmp/spaces.json")?; + + if let Ok(time) = cache_data.modified() { + let now = SystemTime::now(); + if now.duration_since(time).unwrap() >= Duration::from_secs(86400) { + return get_spaces_web(); + } else { + let cache_file = File::open(Path::new("./tmp/spaces.json"))?; + let reader = BufReader::new(cache_file); + let json: Value = serde_json::from_reader(reader)?; + + let mut spaces = HashMap::new(); + for (key, value) in json.as_object().unwrap().iter() { + info!("{}: {}", key, value); + info!("GetSpace"); + let space: Result<HashMap<String, f64>, failure::Error> = get_space( + key.as_str().to_string(), + value.as_str().unwrap().to_string(), + ); + if space.is_ok() { + spaces.insert(key.to_string(), space.unwrap()); + } + } + + //println!("{:?}", json); + return Ok(spaces); + } + } else { + return get_spaces_web(); + } + } else { + return get_spaces_web(); + } +} + +#[derive(Serialize, Deserialize)] +pub struct Location { + address: String, + lon: f64, + lat: f64, +} + +#[derive(Serialize, Deserialize)] +pub struct Space { + api: String, + space: String, + logo: String, + url: String, + location: Location, + contact: Value, + issue_report_channels: Vec<String>, + state: Value, + open: Option<bool>, +} + +fn get_space_web(name: String, url: String) -> Result<HashMap<String, f64>, failure::Error> { + let client = reqwest::Client::builder() + .gzip(true) + .timeout(Duration::from_secs(10)) + .build()?; + + let mut res = client.get(url.as_str()).send()?; + + if res.status() == StatusCode::OK { + let json: Space = res.json()?; + fs::create_dir_all("./tmp/spaces/")?; + let serialized = serde_json::to_string(&json).unwrap(); + let file_name_path = format!("./tmp/spaces/space_{}.json", name.replace("/", "_")); + fs::write(&file_name_path, serialized) + .expect(format!("Unable to write file: {:?}", file_name_path).as_str()); + + let mut map = HashMap::new(); + + map.insert("lat".to_string(), json.location.lat); + map.insert("lon".to_string(), json.location.lon); + //println!("{:?}", json); + return Ok(map); + } + Err(failure::err_msg("SPACE API DOWN")) +} + +pub fn get_space(name: String, url: String) -> Result<HashMap<String, f64>, failure::Error> { + let file_name_path = format!("./tmp/spaces/space_{}.json", name.replace("/", "_")); + let space_file = Path::new(&file_name_path); + if space_file.exists() { + info!("1"); + let cache_data = fs::metadata(&space_file)?; + + if let Ok(time) = cache_data.modified() { + let now = SystemTime::now(); + if now.duration_since(time).unwrap() >= Duration::from_secs(86400) { + return get_space_web(name, url); + } else { + info!("2"); + let cache_file = File::open(&space_file)?; + let reader = BufReader::new(cache_file); + let json: Space = serde_json::from_reader(reader)?; + + let mut map = HashMap::new(); + + map.insert("lat".to_string(), json.location.lat); + map.insert("lon".to_string(), json.location.lon); + //println!("{:?}", json); + return Ok(map); + } + } else { + Err(failure::err_msg("modified Date Missing")) + } + } else { + return get_space_web(name, url); + } +} + +pub fn find_space(name: &str) -> Result<HashMap<String, f64>, failure::Error> { + if Path::new("./tmp/spaces").exists() { + let file_name_path = format!("./tmp/spaces/space_{}.json", name.replace("/", "_")); + let space_file = Path::new(&file_name_path); + if space_file.exists() { + let cache_file = File::open(&space_file)?; + let reader = BufReader::new(cache_file); + let json: Space = serde_json::from_reader(reader)?; + + let mut map = HashMap::new(); + + map.insert("lat".to_string(), json.location.lat); + map.insert("lon".to_string(), json.location.lon); + //println!("{:?}", json); + return Ok(map); + } else { + let all_spaces = get_spaces(); + match all_spaces { + Ok(x) => { + let space: Option<HashMap<String, f64>> = + x.into_iter() + .find_map(|x| if x.0 == name { Some(x.1) } else { None }); + if space.is_some() { + Ok(space.unwrap()) + } else { + Err(failure::err_msg("Space not found")) + } + } + Err(e) => { + error!("{:?}", e); + return Err(e); + } + } + } + } else { + let all_spaces = get_spaces(); + match all_spaces { + Ok(x) => { + let space: Option<HashMap<String, f64>> = + x.into_iter() + .find_map(|x| if x.0 == name { Some(x.1) } else { None }); + if space.is_some() { + Ok(space.unwrap()) + } else { + Err(failure::err_msg("Space not found")) + } + } + Err(e) => { + error!("{:?}", e); + return Err(e); + } + } + } +}