├── .gitignore
├── Cartfile
├── Cartfile.private
├── Cartfile.resolved
├── DemoPayload.md
├── ICEInformation.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcshareddata
│ │ └── ICEInformation.xcscmblueprint
│ └── xcuserdata
│ │ └── lukaslaschmidt.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── xcshareddata
│ └── xcschemes
│ │ └── ICEOnboardAPI.xcscheme
└── xcuserdata
│ ├── lukaslaschmidt.xcuserdatad
│ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes
│ │ ├── ICEInformation.xcscheme
│ │ ├── ICEOnboardWidget.xcscheme
│ │ ├── NextStopNotification.xcscheme
│ │ └── xcschememanagement.plist
│ └── lukasschmidt.xcuserdatad
│ ├── xcdebugger
│ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes
│ ├── ICEInformation.xcscheme
│ └── xcschememanagement.plist
├── ICEInformation
├── AppDelegate.swift
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── BuyableCell.swift
├── ConnectingTrainViewController.swift
├── Info.plist
├── ServiceViewController.swift
├── StationOverviewViewController.swift
├── StationViewController.swift
└── TrainStationCell.swift
├── ICEInformationiOS
├── Buyable+JSONSerialization.swift
├── Buyable.swift
├── ErrorType.swift
├── FakeICENetworkAccess.swift
├── FirstClassDeliverOffers+JSONSerialization.swift
├── FirstClassDeliverOffers.swift
├── ICEInformationiOS.h
├── ICEStatus+JSONSerialization.swift
├── ICEStatus.swift
├── ICETrip+JSONSerialization.swift
├── ICETrip.swift
├── Info.plist
├── Location+CLLocation.swift
├── Location+JSONSerialization.swift
├── Location.swift
├── Station+JSONSerialization.swift
├── Station+MKAnnotation.swift
├── Station.swift
├── StationSchedule+JSONSerialization.swift
├── Stop+JSONSerialization.swift
├── Stop.swift
├── Track+JSONSerialization.swift
├── Track.swift
├── TrainConnection+JSONSerialization.swift
├── TrainConnection.swift
├── TrainConnections+JSONSerialization.swift
├── TrainOnBoardAPI.swift
└── Trip+MKAnnotations.swift
├── ICEInformationiOSTests
├── ICEInformationiOSTests.swift
├── Info.plist
└── TestData.swift
├── ICEOnboardWidget
├── Base.lproj
│ └── MainInterface.storyboard
├── Info.plist
└── TodayViewController.swift
├── LICENSE
├── NextStopNotification
├── Base.lproj
│ └── MainInterface.storyboard
├── Info.plist
└── NotificationViewController.swift
├── README.md
└── Screenshot.png
/.gitignore:
--------------------------------------------------------------------------------
1 | Carthage/*
2 |
--------------------------------------------------------------------------------
/Cartfile:
--------------------------------------------------------------------------------
1 | github "matthewcheok/JSONCodable" == 3.0.1
2 | github "dbsystel/DBNetworkStack" == 0.6.0
3 |
--------------------------------------------------------------------------------
/Cartfile.private:
--------------------------------------------------------------------------------
1 | github "lightsprint09/Sourcing" ~> 2.0
--------------------------------------------------------------------------------
/Cartfile.resolved:
--------------------------------------------------------------------------------
1 | github "dbsystel/DBNetworkStack" "0.6.0"
2 | github "lightsprint09/Sourcing" "2.2"
3 | github "matthewcheok/JSONCodable" "3.0.1"
4 |
--------------------------------------------------------------------------------
/DemoPayload.md:
--------------------------------------------------------------------------------
1 | http://ice.portal2/jetty/api/v1/tripInfo
2 | ```json
3 | "actualPosition" : 173933,
4 | "tripDate" : "2015-12-10",
5 | "trainType" : "ICE",
6 | "distanceFromLastStop" : 45828,
7 | "totalDistance" : 475988,
8 | "stops" : [
9 | {
10 | "station" : {
11 | "evaNr" : "8500010_00",
12 | "name" : "Basel SBB",
13 | "geocoordinates" : {
14 | "longitude" : 7.589169,
15 | "latitude" : 47.547077
16 | }
17 | },
18 | "info" : {
19 | "status" : 0,
20 | "passed" : true,
21 | "distance" : 0,
22 | "distanceFromStart" : 0
23 | },
24 | "track" : {
25 | "scheduled" : "12",
26 | "actual" : ""
27 | },
28 | "timetable" : {
29 | "actualDepartureTime" : 1449742380000,
30 | "departureDelay" : "",
31 | "actualArrivalTime" : null,
32 | "scheduledArrivalTime" : null,
33 | "arrivalDelay" : "",
34 | "scheduledDepartureTime" : 1449742380000
35 | }
36 | },
37 | {
38 | "station" : {
39 | "evaNr" : "8000026_00",
40 | "name" : "Basel Bad Bf",
41 | "geocoordinates" : {
42 | "longitude" : 7.607805,
43 | "latitude" : 47.567288
44 | }
45 | },
46 | "info" : {
47 | "status" : 0,
48 | "passed" : true,
49 | "distance" : 2648,
50 | "distanceFromStart" : 2648
51 | },
52 | "track" : {
53 | "scheduled" : "4",
54 | "actual" : ""
55 | },
56 | "timetable" : {
57 | "actualDepartureTime" : 1449742980000,
58 | "departureDelay" : "",
59 | "actualArrivalTime" : 1449742800000,
60 | "scheduledArrivalTime" : 1449742740000,
61 | "arrivalDelay" : "+1",
62 | "scheduledDepartureTime" : 1449742980000
63 | }
64 | },
65 | {
66 | "station" : {
67 | "evaNr" : "8000107_00",
68 | "name" : "Freiburg(Breisgau) Hbf",
69 | "geocoordinates" : {
70 | "longitude" : 7.84117,
71 | "latitude" : 47.997697
72 | }
73 | },
74 | "info" : {
75 | "status" : 0,
76 | "passed" : true,
77 | "distance" : 50951,
78 | "distanceFromStart" : 53599
79 | },
80 | "track" : {
81 | "scheduled" : "1",
82 | "actual" : ""
83 | },
84 | "timetable" : {
85 | "actualDepartureTime" : 1449745080000,
86 | "departureDelay" : "+1",
87 | "actualArrivalTime" : 1449744900000,
88 | "scheduledArrivalTime" : 1449744900000,
89 | "arrivalDelay" : "",
90 | "scheduledDepartureTime" : 1449745020000
91 | }
92 | },
93 | {
94 | "station" : {
95 | "evaNr" : "8000290_00",
96 | "name" : "Offenburg",
97 | "geocoordinates" : {
98 | "longitude" : 7.946723,
99 | "latitude" : 48.476475
100 | }
101 | },
102 | "info" : {
103 | "status" : 0,
104 | "passed" : true,
105 | "distance" : 53824,
106 | "distanceFromStart" : 107423
107 | },
108 | "track" : {
109 | "scheduled" : "3",
110 | "actual" : ""
111 | },
112 | "timetable" : {
113 | "actualDepartureTime" : 1449747060000,
114 | "departureDelay" : "+1",
115 | "actualArrivalTime" : 1449746880000,
116 | "scheduledArrivalTime" : 1449746880000,
117 | "arrivalDelay" : "",
118 | "scheduledDepartureTime" : 1449747000000
119 | }
120 | },
121 | {
122 | "station" : {
123 | "evaNr" : "8000191_00",
124 | "name" : "Karlsruhe Hbf",
125 | "geocoordinates" : {
126 | "longitude" : 8.402181000000001,
127 | "latitude" : 48.993515
128 | }
129 | },
130 | "info" : {
131 | "status" : 0,
132 | "passed" : true,
133 | "distance" : 66510,
134 | "distanceFromStart" : 173933
135 | },
136 | "track" : {
137 | "scheduled" : "3",
138 | "actual" : "4"
139 | },
140 | "timetable" : {
141 | "actualDepartureTime" : 1449748980000,
142 | "departureDelay" : "+3",
143 | "actualArrivalTime" : 1449748800000,
144 | "scheduledArrivalTime" : 1449748680000,
145 | "arrivalDelay" : "+2",
146 | "scheduledDepartureTime" : 1449748800000
147 | }
148 | },
149 | {
150 | "station" : {
151 | "evaNr" : "8000244_00",
152 | "name" : "Mannheim Hbf",
153 | "geocoordinates" : {
154 | "longitude" : 8.468921,
155 | "latitude" : 49.479354
156 | }
157 | },
158 | "info" : {
159 | "status" : 0,
160 | "passed" : false,
161 | "distance" : 54255,
162 | "distanceFromStart" : 228188
163 | },
164 | "track" : {
165 | "scheduled" : "3",
166 | "actual" : ""
167 | },
168 | "timetable" : {
169 | "actualDepartureTime" : 1449750960000,
170 | "departureDelay" : "",
171 | "actualArrivalTime" : 1449750420000,
172 | "scheduledArrivalTime" : 1449750180000,
173 | "arrivalDelay" : "+4",
174 | "scheduledDepartureTime" : 1449750960000
175 | }
176 | },
177 | {
178 | "station" : {
179 | "evaNr" : "8070003_00",
180 | "name" : "Frankfurt(M) Flughafen Fernbf",
181 | "geocoordinates" : {
182 | "longitude" : 8.570185,
183 | "latitude" : 50.053167
184 | }
185 | },
186 | "info" : {
187 | "status" : 0,
188 | "passed" : false,
189 | "distance" : 64236,
190 | "distanceFromStart" : 292424
191 | },
192 | "track" : {
193 | "scheduled" : "Fern 6",
194 | "actual" : ""
195 | },
196 | "timetable" : {
197 | "actualDepartureTime" : 1449752940000,
198 | "departureDelay" : "",
199 | "actualArrivalTime" : 1449752760000,
200 | "scheduledArrivalTime" : 1449752760000,
201 | "arrivalDelay" : "",
202 | "scheduledDepartureTime" : 1449752940000
203 | }
204 | },
205 | {
206 | "station" : {
207 | "evaNr" : "8005556_00",
208 | "name" : "Siegburg\/Bonn",
209 | "geocoordinates" : {
210 | "longitude" : 7.203026,
211 | "latitude" : 50.793915
212 | }
213 | },
214 | "info" : {
215 | "status" : 0,
216 | "passed" : false,
217 | "distance" : 127174,
218 | "distanceFromStart" : 419598
219 | },
220 | "track" : {
221 | "scheduled" : "3",
222 | "actual" : ""
223 | },
224 | "timetable" : {
225 | "actualDepartureTime" : 1449755340000,
226 | "departureDelay" : "",
227 | "actualArrivalTime" : 1449755220000,
228 | "scheduledArrivalTime" : 1449755220000,
229 | "arrivalDelay" : "",
230 | "scheduledDepartureTime" : 1449755340000
231 | }
232 | },
233 | {
234 | "station" : {
235 | "evaNr" : "8073368_00",
236 | "name" : "Köln Messe\/Deutz Gl.11-12",
237 | "geocoordinates" : {
238 | "longitude" : 6.974067,
239 | "latitude" : 50.941721
240 | }
241 | },
242 | "info" : {
243 | "status" : 0,
244 | "passed" : false,
245 | "distance" : 22991,
246 | "distanceFromStart" : 442589
247 | },
248 | "track" : {
249 | "scheduled" : "12",
250 | "actual" : ""
251 | },
252 | "timetable" : {
253 | "actualDepartureTime" : 1449756360000,
254 | "departureDelay" : "",
255 | "actualArrivalTime" : 1449756180000,
256 | "scheduledArrivalTime" : 1449756180000,
257 | "arrivalDelay" : "",
258 | "scheduledDepartureTime" : 1449756360000
259 | }
260 | },
261 | {
262 | "station" : {
263 | "evaNr" : "8000085_00",
264 | "name" : "Düsseldorf Hbf",
265 | "geocoordinates" : {
266 | "longitude" : 6.794319,
267 | "latitude" : 51.219962
268 | }
269 | },
270 | "info" : {
271 | "status" : 0,
272 | "passed" : false,
273 | "distance" : 33399,
274 | "distanceFromStart" : 475988
275 | },
276 | "track" : {
277 | "scheduled" : "17",
278 | "actual" : ""
279 | },
280 | "timetable" : {
281 | "actualDepartureTime" : null,
282 | "departureDelay" : "",
283 | "actualArrivalTime" : 1449757620000,
284 | "scheduledArrivalTime" : 1449757620000,
285 | "arrivalDelay" : "",
286 | "scheduledDepartureTime" : null
287 | }
288 | }
289 | ],
290 | "stopInfo" : {
291 | "actualLast" : "8000191_00",
292 | "actualLastStarted" : "8000244",
293 | "actualNext" : "8000244_00",
294 | "finalStationName" : "Düsseldorf Hbf",
295 | "scheduledNext" : "8000244_00",
296 | "finalStationEvaNr" : "8000085_00"
297 | },
298 | "vzn" : "108"
299 | }
300 | ```
301 |
302 |
303 |
304 | http://ice.portal2/jetty/api/v1/status
305 | ```json
306 | {
307 | "serverTime" : 1449749986439,
308 | "speed" : 221.8000030517578,
309 | "latitude" : 49.404305,
310 | "connection" : true,
311 | "servicelevel" : "SERVICE",
312 | "longitude" : 8.547148
313 | }
314 | ```
315 |
316 | https://portal.imice.de/api1/rs/tripInfo/connection/8000244_00
317 |
318 | https://portal.imice.de/api1/rs/pois/map/50.105662/8.658493/3921.9763328765366
319 |
320 | https://portal.imice.de/api1/rs/pages/1259002220/775
321 |
322 |
--------------------------------------------------------------------------------
/ICEInformation.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ICEInformation.xcodeproj/project.xcworkspace/xcshareddata/ICEInformation.xcscmblueprint:
--------------------------------------------------------------------------------
1 | {
2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "08E1C23069954CB7B944845CD25D0DCF5E5B7F92",
3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
4 |
5 | },
6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
7 | "CA88B9C3A61C2C61F61FB87727D4B32C7135B85F" : 9223372036854775807,
8 | "08E1C23069954CB7B944845CD25D0DCF5E5B7F92" : 9223372036854775807
9 | },
10 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "2D4E3032-EB56-4E80-BED8-759E96ABA2B2",
11 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
12 | "CA88B9C3A61C2C61F61FB87727D4B32C7135B85F" : "DBNetworkStackSourcing\/",
13 | "08E1C23069954CB7B944845CD25D0DCF5E5B7F92" : "InTrain-ICE-API\/"
14 | },
15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "ICEInformation",
16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204,
17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "ICEInformation.xcodeproj",
18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
19 | {
20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/lightsprint09\/InTrain-ICE-API.git",
21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "08E1C23069954CB7B944845CD25D0DCF5E5B7F92"
23 | },
24 | {
25 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/dbsystel\/DBNetworkStack-Sourcing.git",
26 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "CA88B9C3A61C2C61F61FB87727D4B32C7135B85F"
28 | }
29 | ]
30 | }
--------------------------------------------------------------------------------
/ICEInformation.xcodeproj/project.xcworkspace/xcuserdata/lukaslaschmidt.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightsprint09/ICEOnboardAPI/05ebda2d3719e3f2d8305784d6ca0a1470494965/ICEInformation.xcodeproj/project.xcworkspace/xcuserdata/lukaslaschmidt.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/ICEInformation.xcodeproj/xcshareddata/xcschemes/ICEOnboardAPI.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
70 |
71 |
72 |
73 |
75 |
76 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/ICEInformation.xcodeproj/xcuserdata/lukaslaschmidt.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
20 |
21 |
22 |
24 |
36 |
37 |
38 |
40 |
52 |
53 |
67 |
68 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/ICEInformation.xcodeproj/xcuserdata/lukaslaschmidt.xcuserdatad/xcschemes/ICEInformation.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/ICEInformation.xcodeproj/xcuserdata/lukaslaschmidt.xcuserdatad/xcschemes/ICEOnboardWidget.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
10 |
16 |
22 |
23 |
24 |
30 |
36 |
37 |
38 |
39 |
40 |
45 |
46 |
47 |
48 |
54 |
55 |
56 |
57 |
58 |
59 |
70 |
72 |
78 |
79 |
80 |
81 |
82 |
83 |
90 |
92 |
98 |
99 |
100 |
101 |
103 |
104 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/ICEInformation.xcodeproj/xcuserdata/lukaslaschmidt.xcuserdatad/xcschemes/NextStopNotification.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
10 |
16 |
22 |
23 |
24 |
30 |
36 |
37 |
38 |
39 |
40 |
45 |
46 |
47 |
48 |
54 |
55 |
56 |
57 |
58 |
59 |
70 |
72 |
78 |
79 |
80 |
81 |
82 |
83 |
90 |
92 |
98 |
99 |
100 |
101 |
103 |
104 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/ICEInformation.xcodeproj/xcuserdata/lukaslaschmidt.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | ICEInformation.xcscheme
8 |
9 | orderHint
10 | 1
11 |
12 | ICEOnboardAPI.xcscheme_^#shared#^_
13 |
14 | orderHint
15 | 0
16 |
17 | ICEOnboardWidget.xcscheme
18 |
19 | orderHint
20 | 2
21 |
22 | NextStopNotification.xcscheme
23 |
24 | orderHint
25 | 3
26 |
27 |
28 | SuppressBuildableAutocreation
29 |
30 | 9431F9B81C19935000860884
31 |
32 | primary
33 |
34 |
35 | 943FF82A1C2D63AF009E7C5F
36 |
37 | primary
38 |
39 |
40 | 943FF8331C2D63AF009E7C5F
41 |
42 | primary
43 |
44 |
45 | C6A2A4D91E9792FD00B55A0F
46 |
47 | primary
48 |
49 |
50 | C6CF23631EADFFBD00580862
51 |
52 | primary
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/ICEInformation.xcodeproj/xcuserdata/lukasschmidt.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/ICEInformation.xcodeproj/xcuserdata/lukasschmidt.xcuserdatad/xcschemes/ICEInformation.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
43 |
49 |
50 |
51 |
53 |
59 |
60 |
61 |
62 |
63 |
69 |
70 |
71 |
72 |
73 |
74 |
84 |
86 |
92 |
93 |
94 |
95 |
96 |
97 |
103 |
105 |
111 |
112 |
113 |
114 |
116 |
117 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/ICEInformation.xcodeproj/xcuserdata/lukasschmidt.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | ICEInformation.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 | ICEInformationiOS.xcscheme_^#shared#^_
13 |
14 | orderHint
15 | 1
16 |
17 |
18 | SuppressBuildableAutocreation
19 |
20 | 9431F9B81C19935000860884
21 |
22 | primary
23 |
24 |
25 | 9431F9CC1C19935000860884
26 |
27 | primary
28 |
29 |
30 | 9431F9D71C19935000860884
31 |
32 | primary
33 |
34 |
35 | 943FF82A1C2D63AF009E7C5F
36 |
37 | primary
38 |
39 |
40 | 943FF8331C2D63AF009E7C5F
41 |
42 | primary
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/ICEInformation/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // ICEInformation
4 | //
5 | // Created by Lukas Schmidt on 10.12.15.
6 | // Copyright © 2015 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
18 |
19 | if let localNotificationInfo = launchOptions?[.remoteNotification] as? UILocalNotification {
20 | if let something = localNotificationInfo.userInfo!["evaId"] as? [String: Any] {
21 | print(something)
22 | }
23 |
24 |
25 | }
26 |
27 | return true
28 | }
29 |
30 | func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
31 | if let something = userInfo["evaId"] as? [String: Any] {
32 | print(something)
33 | }
34 | }
35 |
36 | func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
37 | print(notification.userInfo)
38 | if let something = notification.userInfo?["evaId"] as? [String: Any] {
39 | print(something)
40 | }
41 | }
42 |
43 | }
44 |
45 |
--------------------------------------------------------------------------------
/ICEInformation/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/ICEInformation/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/ICEInformation/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
124 |
130 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
203 |
209 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
290 |
291 |
292 |
293 |
299 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
321 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
341 |
342 |
343 |
344 |
350 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
423 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
--------------------------------------------------------------------------------
/ICEInformation/BuyableCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 |
23 | import Foundation
24 | import Sourcing
25 | import ICEOnboardAPI
26 |
27 | class BuyableCell: UITableViewCell {
28 | @IBOutlet weak var titleLabel: UILabel!
29 | @IBOutlet weak var priceLabel: UILabel!
30 | @IBOutlet weak var descriptionLabel: UILabel!
31 |
32 | }
33 |
34 | extension BuyableCell: CellIdentifierProviding {}
35 | extension BuyableCell: ConfigurableCell {
36 | func configure(with buyable: Buyable) {
37 | titleLabel.text = buyable.title
38 | priceLabel.text = buyable.price
39 | descriptionLabel.text = buyable.description
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/ICEInformation/ConnectingTrainViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 | //
23 | // ConnectingTrainViewController.swift
24 | // ICEInformation
25 | //
26 | // Created by Lukas Schmidt on 05.04.17.
27 | //
28 |
29 | import UIKit
30 | import DBNetworkStack
31 | import ICEOnboardAPI
32 |
33 | let dateFormatter: DateFormatter = {
34 | let formatter = DateFormatter()
35 | formatter.dateFormat = "HH:mm"
36 |
37 | return formatter
38 | }()
39 |
40 |
41 | class ConnectingTrainViewController: UITableViewController {
42 | var station: Station!
43 | var connections: TrainConnections?
44 | let networkService = NetworkService(networkAccess: URLSession(configuration: .default))
45 | let trainOnBoardAPI = TrainOnBoardAPI()
46 |
47 | override func viewDidLoad() {
48 | networkService.request(trainOnBoardAPI.connectionTrains(at: station), onCompletion: { connections in
49 | self.connections = connections
50 | self.tableView.reloadData()
51 | }, onError: { error in
52 |
53 | })
54 | }
55 |
56 | override func numberOfSections(in tableView: UITableView) -> Int {
57 | return 1
58 | }
59 |
60 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
61 | return connections?.connections.count ?? 0
62 | }
63 |
64 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
65 | let cell = tableView.dequeueReusableCell(withIdentifier: "TrainConnectionCell", for: indexPath)
66 | if let connection = connections?.connections[indexPath.row] {
67 | cell.textLabel?.text = "\(dateFormatter.string(from: connection.schedule.departureTime)) \(connection.trainType) \(connection.trainNumber) nach \(connection.destination.name)"
68 | cell.detailTextLabel?.text = connection.track?.actualTrack ?? connection.track?.scheduledTrack
69 | }
70 |
71 | return cell
72 | }
73 |
74 | override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
75 | return "Anschlusszüge"
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/ICEInformation/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 | NSAppTransportSecurity
47 |
48 | NSAllowsArbitraryLoads
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/ICEInformation/ServiceViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 |
23 | import UIKit
24 | import DBNetworkStack
25 | import ICEOnboardAPI
26 | import Sourcing
27 |
28 |
29 | class ServiceViewController: UITableViewController {
30 |
31 | let networkService = NetworkService(networkAccess: URLSession(configuration: .default))
32 | var dataSource: TableViewDataSource!
33 | var dataProvider: ArrayDataProvider!
34 | let trainOnBoardAPI = TrainOnBoardAPI()
35 |
36 | override func viewDidLoad() {
37 | tableView.estimatedRowHeight = 55
38 | tableView.rowHeight = UITableViewAutomaticDimension
39 | let firstClassOffers = trainOnBoardAPI.firstClassOffers()
40 | let cell = CellConfiguration()
41 | dataProvider = ArrayDataProvider(rows: [])
42 | dataSource = TableViewDataSource(tableView: tableView, dataProvider: dataProvider, cell: cell)
43 | networkService.request(firstClassOffers, onCompletion: {[weak self] offers in
44 | self?.dataProvider.reconfigure(with: offers.food)
45 | }, onError: { err in
46 | print(err)
47 | })
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/ICEInformation/StationOverviewViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StationOverviewViewController.swift
3 | // ICEInformation
4 | //
5 | // Created by Lukas Schmidt on 15.01.16.
6 | // Copyright © 2016 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import MapKit
11 | import ICEOnboardAPI
12 | import DBNetworkStack
13 | import Sourcing
14 | import NotificationCenter
15 | import UserNotifications
16 |
17 |
18 | class StationOverviewViewController: UIViewController {
19 | @IBOutlet weak var speedLabel: UILabel!
20 | @IBOutlet weak var mapView: MKMapView!
21 | @IBOutlet weak var tableView: UITableView!
22 | var trip: ICETrip?
23 |
24 | var dataProvider: ArrayDataProvider!
25 | var dataSource: TableViewDataSource!
26 | let trainOnBoardAPI = TrainOnBoardAPI()
27 | let networkService = NetworkService(networkAccess: URLSession(configuration: .default))
28 |
29 | override func viewDidLoad() {
30 | setupDataSource()
31 | fetchData()
32 | fetchStatus()
33 | NCWidgetController().setHasContent(true, forWidgetWithBundleIdentifier: "de.freiraum.ICEInformation.ICEOnboardWidget")
34 | Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(StationOverviewViewController.fetchData), userInfo: nil, repeats: true)
35 | Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(StationOverviewViewController.fetchStatus), userInfo: nil, repeats: true)
36 | }
37 |
38 | func setupDataSource() {
39 | dataProvider = ArrayDataProvider(rows: [])
40 | dataSource = TableViewDataSource(tableView: tableView, dataProvider: dataProvider, cell: CellConfiguration())
41 | }
42 |
43 | func fetchStatus() {
44 | networkService.request(trainOnBoardAPI.status(), onCompletion: didSuceedStatusLoad, onError: { error in
45 | print(error)
46 | })
47 | }
48 |
49 | func fetchData() {
50 | networkService.request(trainOnBoardAPI.trip(), onCompletion: didSuceedTripLoad, onError: { error in
51 | print(error)
52 | })
53 | }
54 |
55 | func didSuceedStatusLoad(_ iceStatus: ICEStatus) {
56 | speedLabel.text = "\(iceStatus.speed)km/h"
57 | }
58 |
59 | func didSuceedTripLoad(_ iceTrip: ICETrip) {
60 | title = iceTrip.trainName
61 | mapView.addAnnotations(iceTrip.mapAnnotations)
62 | trip = iceTrip
63 | dataProvider.headerTitles = ["Vergangene Halte", "Kommende Halte"]
64 | dataProvider.reconfigure(with: [iceTrip.passedStops, iceTrip.commingStops])
65 | guard let nextStop = iceTrip.nextStop, let indexPath = dataProvider.indexPath(for: nextStop) else {
66 | return
67 | }
68 | tableView.scrollToRow(at: indexPath, at: .top, animated: true)
69 | if #available(iOS 10.0, *) {
70 | scheduleNotification(at: nextStop)
71 | } else {
72 | // Fallback on earlier versions
73 | }
74 | }
75 |
76 | func registerNotifications() {
77 |
78 | }
79 | var registerdNextStop: Stop?
80 | @available(iOS 10.0, *)
81 | func scheduleNotification(at nextStop: Stop) {
82 | guard registerdNextStop != nextStop else {
83 | return
84 | }
85 | registerdNextStop = nextStop
86 | UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) {(accepted, error) in
87 | if !accepted {
88 | print("Notification access denied.")
89 | }
90 | }
91 | let category = UNNotificationCategory(identifier: "NextStop", actions: [], intentIdentifiers: [], options: .customDismissAction)
92 | UNUserNotificationCenter.current().setNotificationCategories([category])
93 | let calendar = Calendar(identifier: .gregorian)
94 | let date = Date().addingTimeInterval(60)
95 | let components = calendar.dateComponents(in: .current, from: date)
96 | let newComponents = DateComponents(calendar: calendar, timeZone: .current, month: components.month, day: components.day, hour: components.hour, minute: components.minute, second: components.second)
97 | let trigger = UNCalendarNotificationTrigger(dateMatching: newComponents, repeats: false)
98 | let content = UNMutableNotificationContent()
99 | content.title = "Nächster Halt"
100 | content.body = "Um \(dateFormatter.string(from: nextStop.schduledTimes.arrivalTime.addingTimeInterval(nextStop.schduledTimes.arrivalDelay ?? 0))) erreichen wir \(nextStop.station.name)."
101 |
102 | content.categoryIdentifier = "NextStop"
103 |
104 | content.sound = UNNotificationSound.default()
105 | let request = UNNotificationRequest(identifier: "textNotification", content: content, trigger: trigger)
106 | networkService.request(trainOnBoardAPI.connectionTrains(at: nextStop.station), onCompletion: { connections in
107 | content.userInfo = ["evaId": try! nextStop.station.toJSON(), "payload": try! connections.toJSON()]
108 | UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
109 | UNUserNotificationCenter.current().add(request) {(error) in
110 | if let error = error {
111 | print("Uh oh! We had an error: \(error)")
112 | }
113 | }
114 | }, onError: {_ in })
115 |
116 | }
117 |
118 |
119 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
120 | if let stationViewController = segue.destination as? StationViewController {
121 | stationViewController.stop = dataSource.selectedObject
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/ICEInformation/StationViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StationViewController.swift
3 | // ICEInformation
4 | //
5 | // Created by Lukas Schmidt on 15.01.16.
6 | // Copyright © 2016 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import ICEOnboardAPI
11 | import MapKit
12 |
13 | extension UIColor {
14 | static let delayedRed = UIColor(red: 178 / 255, green: 42 / 255, blue: 34 / 255, alpha: 1)
15 |
16 | static let inTimeGreen = UIColor(red: 93 / 255, green: 179 / 255, blue: 113 / 255, alpha: 1)
17 | }
18 |
19 | class StationViewController: UIViewController {
20 | var stop: Stop!
21 |
22 | @IBOutlet weak var mapView: MKMapView!
23 | @IBOutlet weak var trackLabel: UILabel!
24 | @IBOutlet weak var arrivalLabel: UILabel!
25 | @IBOutlet weak var arrivalDelayLabel: UILabel!
26 | @IBOutlet weak var depatureLabel: UILabel!
27 | @IBOutlet weak var departureDelayLabel: UILabel!
28 |
29 | override func viewDidLoad() {
30 | let dateFormatter = DateFormatter()
31 | dateFormatter.dateFormat = "HH:mm"
32 | if let mapAnotation = stop.station.mapAnnotation, let location = stop.station.location {
33 | mapView.addAnnotation(mapAnotation)
34 | let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
35 | let region = MKCoordinateRegion(center: location.locationCoordinate, span: span)
36 | mapView.setRegion(region, animated: true)
37 | }
38 |
39 | title = stop.station.name
40 |
41 | trackLabel.text = stop.track?.scheduledTrack
42 | arrivalLabel.text = dateFormatter.string(from: stop.schduledTimes.arrivalTime)
43 | depatureLabel.text = dateFormatter.string(from: stop.schduledTimes.departureTime)
44 | setDelayTimeAt(lable: arrivalDelayLabel, delay: stop.schduledTimes.arrivalDelay)
45 | setDelayTimeAt(lable: departureDelayLabel, delay: stop.schduledTimes.depatureDelay)
46 | }
47 |
48 | func setDelayTimeAt(lable : UILabel, delay: TimeInterval?) {
49 | let delay = stop.schduledTimes.arrivalDelay ?? 0
50 | lable.text = "+\(Int(delay / 60))"
51 | lable.textColor = delay >= 5 ? .delayedRed : .inTimeGreen
52 | }
53 |
54 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
55 | if let connectionTrainsViewController = segue.destination as? ConnectingTrainViewController {
56 | connectionTrainsViewController.station = stop.station
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/ICEInformation/TrainStationCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TrainStationCell.swift
3 | // ICEInformation
4 | //
5 | // Created by Lukas Schmidt on 15.01.16.
6 | // Copyright © 2016 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import ICEOnboardAPI
11 | import Sourcing
12 |
13 | class TrainStationCell: UITableViewCell, ConfigurableCell {
14 | @IBOutlet weak var stationNameLabel: UILabel!
15 | @IBOutlet weak var delayLabel: UILabel!
16 | @IBOutlet weak var arrivalTimeLabel: UILabel!
17 |
18 | static let dateFormatter: DateFormatter = {
19 | let dateFormatter = DateFormatter()
20 | dateFormatter.dateFormat = "HH:mm"
21 |
22 | return dateFormatter
23 | }()
24 |
25 | func configure(with stop: Stop) {
26 | stationNameLabel.text = stop.station.name
27 | let delay = stop.schduledTimes.arrivalDelay ?? 0
28 | delayLabel.text = "+\(Int(delay / 60))"
29 | delayLabel.textColor = delay >= 5 ? .delayedRed : .inTimeGreen
30 | arrivalTimeLabel.text = TrainStationCell.dateFormatter.string(from: stop.schduledTimes.arrivalTime)
31 | }
32 | }
33 |
34 | extension TrainStationCell: CellIdentifierProviding {}
35 |
--------------------------------------------------------------------------------
/ICEInformationiOS/Buyable+JSONSerialization.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 |
23 | import Foundation
24 | import JSONCodable
25 |
26 | extension Buyable: JSONDecodable {
27 | public init(object: JSONObject) throws {
28 | let decoder = JSONDecoder(object: object)
29 | price = try decoder.decode("priceEUR")
30 | title = try decoder.decode("title")
31 | let text: String? = try decoder.decode("text")
32 | description = text?.replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil)
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/ICEInformationiOS/Buyable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 |
23 | import Foundation
24 |
25 | public struct Buyable {
26 | public let title: String
27 | public let description: String?
28 | public let price: String
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/ICEInformationiOS/ErrorType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ErrorType.swift
3 | // ICEInformation
4 | //
5 | // Created by Lukas Schmidt on 28.12.15.
6 | // Copyright © 2015 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public enum ICEErrorType: Error {
12 | case wrongWifi
13 | case parse
14 | case network
15 | }
16 |
--------------------------------------------------------------------------------
/ICEInformationiOS/FakeICENetworkAccess.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 | //
23 | // FakeICENetworkAccess.swift
24 | // ICEInformation
25 | //
26 | // Created by Lukas Schmidt on 07.04.17.
27 | //
28 |
29 | import Foundation
30 | import DBNetworkStack
31 |
32 | let statusPayload = "{\"serverTime\":1449749986439,\"speed\":221.8000030517578,\"latitude\":49.404305,\"connection\":true,\"servicelevel\":\"SERVICE\",\"longitude\":8.547148}".data(using: .utf8)
33 |
34 | let tripInfoPayload = "{\"serverTime\":1449749986439,\"speed\":221.8000030517578,\"latitude\":49.404305,\"connection\":true,\"servicelevel\":\"SERVICE\",\"longitude\":8.547148}".data(using: .utf8)
35 |
36 | public class FakeICENetworkAccess: NetworkAccessProviding {
37 |
38 | public init() {}
39 |
40 | public func load(request: URLRequest, callback: @escaping (Data?, HTTPURLResponse?, Error?) -> Void) -> NetworkTaskRepresenting {
41 | guard let urlString = request.url?.absoluteString else {
42 | callback(nil, nil, nil)
43 | return NetworkTaskMock()
44 | }
45 | if urlString.contains("status") {
46 | callback(statusPayload, nil, nil)
47 | } else if urlString.contains("tripInfo") && !urlString.contains("connections") {
48 |
49 | }
50 | else {
51 | callback(nil, nil, nil)
52 | }
53 | return NetworkTaskMock()
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/ICEInformationiOS/FirstClassDeliverOffers+JSONSerialization.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 |
23 | import Foundation
24 | import JSONCodable
25 |
26 | extension FirstClassDeliverOffers: JSONDecodable {
27 | public init(object: JSONObject) throws {
28 | let decoder = JSONDecoder(object: object)
29 | food = try decoder.decode("articlesNested[0].items")
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ICEInformationiOS/FirstClassDeliverOffers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 |
23 | import Foundation
24 |
25 | public struct FirstClassDeliverOffers {
26 | public let food: [Buyable]
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/ICEInformationiOS/ICEInformationiOS.h:
--------------------------------------------------------------------------------
1 | //
2 | // ICEInformationiOS.h
3 | // ICEInformationiOS
4 | //
5 | // Created by Lukas Schmidt on 25.12.15.
6 | // Copyright © 2015 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for ICEInformationiOS.
12 | FOUNDATION_EXPORT double ICEInformationiOSVersionNumber;
13 |
14 | //! Project version string for ICEInformationiOS.
15 | FOUNDATION_EXPORT const unsigned char ICEInformationiOSVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/ICEInformationiOS/ICEStatus+JSONSerialization.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 | //
23 | // ICEStatus+JSONSerialization.swift
24 | // ICEInformation
25 | //
26 | // Created by Lukas Schmidt on 05.04.17.
27 | //
28 |
29 | import Foundation
30 | import JSONCodable
31 |
32 | extension ICEStatus: JSONDecodable {
33 | public init(object: JSONObject) throws {
34 | let decoder = JSONDecoder(object: object)
35 | speed = try decoder.decode("speed")
36 | location = try Location(object: object)
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/ICEInformationiOS/ICEStatus.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ICEStatus.swift
3 | // ICEInformation
4 | //
5 | // Created by Lukas Schmidt on 25.12.15.
6 | // Copyright © 2015 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public struct ICEStatus {
12 | public let location: Location
13 | public let speed: Float
14 | }
--------------------------------------------------------------------------------
/ICEInformationiOS/ICETrip+JSONSerialization.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 | //
23 | // ICETrip+JSONSerialization.swift
24 | // ICEInformation
25 | //
26 | // Created by Lukas Schmidt on 05.04.17.
27 | //
28 |
29 | import Foundation
30 | import JSONCodable
31 |
32 | extension ICETrip: JSONDecodable {
33 | public init(object: JSONObject) throws {
34 | let decoder = JSONDecoder(object: object)
35 | self.trainType = try decoder.decode("trainType")
36 | self.trainNumber = try decoder.decode("vzn")
37 | self.stops = try decoder.decode("stops")
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/ICEInformationiOS/ICETrip.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ICETripInformation.swift
3 | // ICEInformation
4 | //
5 | // Created by Lukas Schmidt on 25.12.15.
6 | // Copyright © 2015 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public struct ICETrip {
12 | public let trainType: String
13 | public let trainNumber: String
14 | public let stops: Array
15 |
16 | public var from: Stop {
17 | return stops.first!
18 | }
19 |
20 | public var to: Stop {
21 | return stops.last!
22 | }
23 |
24 | public var trainName: String {
25 | return trainType + " " + trainNumber
26 | }
27 |
28 | public var passedStops: [Stop] {
29 | return stops.filter { $0.passed }
30 | }
31 |
32 | public var commingStops: [Stop] {
33 | return stops.filter { !$0.passed }
34 | }
35 |
36 | public var nextStop: Stop? {
37 | return commingStops.first
38 | }
39 |
40 | public init(trainNumber: String, stops: [Stop], trainType: String) {
41 | if stops.count < 2 {
42 | fatalError("A trip must have at least 2 stops")
43 | }
44 | self.trainNumber = trainNumber
45 | self.stops = stops
46 | self.trainType = trainType
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/ICEInformationiOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ICEInformationiOS/Location+CLLocation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Location+CLLocation.swift
3 | // ICEInformation
4 | //
5 | // Created by Lukas Schmidt on 26.12.15.
6 | // Copyright © 2015 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import CoreLocation
11 |
12 | public extension Location {
13 | public var locationCoordinate: CLLocationCoordinate2D {
14 | return CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
15 | }
16 | }
--------------------------------------------------------------------------------
/ICEInformationiOS/Location+JSONSerialization.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 | //
23 | // Location+JSONSerialization.swift
24 | // ICEInformation
25 | //
26 | // Created by Lukas Schmidt on 05.04.17.
27 | //
28 |
29 | import Foundation
30 | import JSONCodable
31 |
32 | extension Location: JSONDecodable, JSONEncodable {
33 | public init(object: JSONObject) throws {
34 | let decoder = JSONDecoder(object: object)
35 | latitude = try decoder.decode("latitude")
36 | longitude = try decoder.decode("longitude")
37 | }
38 |
39 | public func toJSON() throws -> Any {
40 | return try JSONEncoder.create({ (encoder) -> Void in
41 | try encoder.encode(latitude, key: "latitude")
42 | try encoder.encode(longitude, key: "longitude")
43 | })
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/ICEInformationiOS/Location.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Location.swift
3 | // ICEInformation
4 | //
5 | // Created by Lukas Schmidt on 08.01.16.
6 | // Copyright © 2016 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public struct Location {
12 | public let latitude: Double
13 | public let longitude: Double
14 | }
15 |
--------------------------------------------------------------------------------
/ICEInformationiOS/Station+JSONSerialization.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 | //
23 | // Station+JSONSerialization.swift
24 | // ICEInformation
25 | //
26 | // Created by Lukas Schmidt on 05.04.17.
27 | //
28 |
29 | import Foundation
30 | import JSONCodable
31 |
32 | extension Station: JSONDecodable, JSONEncodable {
33 | public init(object: JSONObject) throws {
34 | let decoder = JSONDecoder(object: object)
35 | location = try decoder.decode("geocoordinates")
36 | evaId = try decoder.decode("evaNr")
37 | name = try decoder.decode("name")
38 | }
39 |
40 | public func toJSON() throws -> Any {
41 | return try JSONEncoder.create({ (encoder) -> Void in
42 | try encoder.encode(location, key: "geocoordinates")
43 | try encoder.encode(evaId, key: "evaNr")
44 | try encoder.encode(name, key: "name")
45 | })
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/ICEInformationiOS/Station+MKAnnotation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Station+MKAnotation.swift
3 | // ICEInformation
4 | //
5 | // Created by Lukas Schmidt on 15.01.16.
6 | // Copyright © 2016 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | import MapKit
10 |
11 | extension Station {
12 | public var mapAnnotation: MKPointAnnotation? {
13 | guard let locationCoordinate = location?.locationCoordinate else {
14 | return nil
15 | }
16 | let dropPin = MKPointAnnotation()
17 | dropPin.coordinate = locationCoordinate
18 | dropPin.title = name
19 |
20 | return dropPin
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/ICEInformationiOS/Station.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Station.swift
3 | // ICEInformation
4 | //
5 | // Created by Lukas Schmidt on 26.12.15.
6 | // Copyright © 2015 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public struct StationSchedule{
12 | public let arrivalTime: Date
13 | public let departureTime: Date
14 |
15 | public let arrivalDelay: TimeInterval?
16 | public let depatureDelay: TimeInterval?
17 | }
18 |
19 | public struct Station {
20 | public let evaId: String
21 | public let name: String
22 | public let location: Location?
23 | }
24 |
--------------------------------------------------------------------------------
/ICEInformationiOS/StationSchedule+JSONSerialization.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 | //
23 | // StationSchedule+JSONSerialization.swift
24 | // ICEInformation
25 | //
26 | // Created by Lukas Schmidt on 05.04.17.
27 | //
28 |
29 | import Foundation
30 | import JSONCodable
31 |
32 | extension StationSchedule: JSONDecodable, JSONEncodable {
33 | public init(object: JSONObject) throws {
34 | let decoder = JSONDecoder(object: object)
35 | let scheduledArrivalTime: Double? = try decoder.decode("scheduledArrivalTime")
36 | let scheduledDepartureTime: Double? = try decoder.decode("scheduledDepartureTime")
37 |
38 | arrivalTime = Date(timeIntervalSince1970: (scheduledArrivalTime ?? scheduledDepartureTime!) * 0.001)
39 | departureTime = Date(timeIntervalSince1970: (scheduledDepartureTime ?? scheduledArrivalTime!) * 0.001)
40 |
41 | arrivalDelay = extractDelay(try decoder.decode("arrivalDelay"))
42 | depatureDelay = extractDelay(try decoder.decode("departureDelay"))
43 | }
44 |
45 | public func toJSON() throws -> Any {
46 | return try JSONEncoder.create({ (encoder) -> Void in
47 | try encoder.encode(arrivalTime.timeIntervalSinceReferenceDate, key: "scheduledArrivalTime")
48 | try encoder.encode(departureTime.timeIntervalSinceReferenceDate, key: "scheduledArrivalTime")
49 | try encoder.encode(arrivalDelay, key: "arrivalDelay")
50 | try encoder.encode(depatureDelay, key: "depatureDelay")
51 | })
52 | }
53 | }
54 |
55 |
56 | func extractDelay(_ delay:String?) -> TimeInterval? {
57 | guard let delay = delay,
58 | let delayTime = Double(delay.replacingOccurrences(of: "+", with: "")) else { return nil }
59 | return delayTime * 60
60 | }
61 |
--------------------------------------------------------------------------------
/ICEInformationiOS/Stop+JSONSerialization.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 | //
23 | // Stop+JSONSerialization.swift
24 | // ICEInformation
25 | //
26 | // Created by Lukas Schmidt on 05.04.17.
27 | //
28 |
29 | import Foundation
30 | import JSONCodable
31 |
32 | extension Stop: JSONDecodable {
33 | public init(object: JSONObject) throws {
34 | let decoder = JSONDecoder(object: object)
35 | station = try decoder.decode("station")
36 | schduledTimes = try decoder.decode("timetable")
37 | track = try decoder.decode("track")
38 | passed = try decoder.decode("info.passed")
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/ICEInformationiOS/Stop.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 | //
23 | // Stop.swift
24 | // ICEInformation
25 | //
26 | // Created by Lukas Schmidt on 05.04.17.
27 | //
28 |
29 | import Foundation
30 |
31 | public struct Stop {
32 | public let station: Station
33 | public let passed: Bool
34 | public let schduledTimes: StationSchedule
35 | public let track: Track?
36 | }
37 |
38 | extension Stop: Equatable { }
39 |
40 | public func ==(lhs: Stop, rhs: Stop) -> Bool {
41 | return lhs.station.evaId == rhs.station.evaId
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/ICEInformationiOS/Track+JSONSerialization.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 | //
23 | // Track+JSONSerialization.swift
24 | // ICEInformation
25 | //
26 | // Created by Lukas Schmidt on 05.04.17.
27 | //
28 |
29 | import Foundation
30 | import JSONCodable
31 |
32 | extension Track: JSONDecodable, JSONEncodable {
33 | public init(object: JSONObject) throws {
34 | let decoder = JSONDecoder(object: object)
35 | scheduledTrack = try decoder.decode("scheduled")
36 | actualTrack = try decoder.decode("actual")
37 | }
38 |
39 | public func toJSON() throws -> Any {
40 | return try JSONEncoder.create({ (encoder) -> Void in
41 | try encoder.encode(scheduledTrack, key: "scheduled")
42 | try encoder.encode(actualTrack, key: "actual")
43 | })
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/ICEInformationiOS/Track.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 | //
23 | // Track.swift
24 | // ICEInformation
25 | //
26 | // Created by Lukas Schmidt on 05.04.17.
27 | //
28 |
29 | import Foundation
30 |
31 | public struct Track {
32 | public let actualTrack: String?
33 | public let scheduledTrack: String?
34 | }
35 |
--------------------------------------------------------------------------------
/ICEInformationiOS/TrainConnection+JSONSerialization.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 | //
23 | // TrainConnection+JSONSerialization.swift
24 | // ICEInformation
25 | //
26 | // Created by Lukas Schmidt on 05.04.17.
27 | //
28 |
29 | import Foundation
30 | import JSONCodable
31 |
32 | extension TrainConnection: JSONDecodable, JSONEncodable {
33 | public init(object: JSONObject) throws {
34 | let decoder = JSONDecoder(object: object)
35 | trainType = try decoder.decode("trainType")
36 | vzn = try decoder.decode("vzn")
37 | let lineName: String? = try decoder.decode("lineName")
38 | trainNumber = (try decoder.decode("trainNumber") as String?) ?? lineName ?? ""
39 | schedule = try decoder.decode("timetable")
40 | track = try decoder.decode("track")
41 | destination = try decoder.decode("station")
42 | }
43 |
44 | public func toJSON() throws -> Any {
45 | return try JSONEncoder.create({ (encoder) -> Void in
46 | try encoder.encode(trainType, key: "trainType")
47 | try encoder.encode(vzn, key: "vzn")
48 | try encoder.encode(trainNumber, key: "trainNumber")
49 | try encoder.encode(schedule, key: "timetable")
50 | try encoder.encode(track, key: "track")
51 | try encoder.encode(destination, key: "destination")
52 | })
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/ICEInformationiOS/TrainConnection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 | //
23 | // TrainConnection.swift
24 | // ICEInformation
25 | //
26 | // Created by Lukas Schmidt on 05.04.17.
27 | //
28 |
29 | import Foundation
30 |
31 | public struct TrainConnections {
32 | public let connections: [TrainConnection]
33 | }
34 |
35 |
36 |
37 | public struct TrainConnection {
38 | public let trainType: String
39 | public let vzn: String
40 | public let trainNumber: String
41 | public let schedule: StationSchedule
42 | public let track: Track?
43 | public let destination: Station
44 | }
45 |
--------------------------------------------------------------------------------
/ICEInformationiOS/TrainConnections+JSONSerialization.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 Lukas Schmidt.
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | // and/or sell copies of the Software, and to permit persons to whom the
9 | // Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 | //
22 | //
23 | // TrainConnections+JSONSerialization.swift
24 | // ICEInformation
25 | //
26 | // Created by Lukas Schmidt on 05.04.17.
27 | //
28 |
29 | import Foundation
30 | import JSONCodable
31 |
32 | extension TrainConnections: JSONDecodable, JSONEncodable {
33 | public init(object: JSONObject) throws {
34 | let decoder = JSONDecoder(object: object)
35 | connections = try decoder.decode("connections")
36 | }
37 |
38 | public func toJSON() throws -> Any {
39 | return try JSONEncoder.create({ (encoder) -> Void in
40 | try encoder.encode(connections, key: "connections")
41 | })
42 |
43 | }
44 | }
45 |
46 |
47 |
--------------------------------------------------------------------------------
/ICEInformationiOS/TrainOnBoardAPI.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ICEStatusURLRessources.swift
3 | // ICEInformation
4 | //
5 | // Created by Lukas Schmidt on 26.12.15.
6 | // Copyright © 2015 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import DBNetworkStack
11 |
12 | let baseURLPortal = URL(string: "https://portal.imice.de/api1/rs/")!
13 |
14 | extension ICEStatus: JSONMappable { }
15 | extension ICETrip: JSONMappable { }
16 | extension TrainConnections: JSONMappable { }
17 | extension FirstClassDeliverOffers: JSONMappable { }
18 |
19 | public final class TrainOnBoardAPI {
20 |
21 | private let baseURL: URL
22 |
23 | public init(baseURL: URL = baseURLPortal) {
24 | self.baseURL = baseURL
25 | }
26 |
27 | public func status() -> Resource {
28 | let request = URLRequest(path: "status", baseURL: baseURL)
29 |
30 | return Resource(resource: JSONResource(request: request))
31 | }
32 |
33 | public func trip() -> Resource {
34 | let request = URLRequest(path: "tripInfo", baseURL: baseURL)
35 |
36 | return Resource(resource: JSONResource(request: request))
37 | }
38 |
39 | public func connectionTrains(at station: Station) -> Resource {
40 | return connectionTrains(for: station.evaId)
41 | }
42 |
43 | public func connectionTrains(for evaId: String) -> Resource {
44 | let request = URLRequest(path: "tripInfo/connection/\(evaId)", baseURL: baseURL)
45 |
46 | return Resource(resource: JSONResource(request: request))
47 | }
48 |
49 | public func firstClassOffers() -> Resource {
50 | let request = URLRequest(path: "filterTop/1259026820/0", baseURL: baseURL)
51 |
52 | return Resource(resource: JSONResource(request: request))
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/ICEInformationiOS/Trip+MKAnnotations.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Trip+MKAnnotations.swift
3 | // ICEInformation
4 | //
5 | // Created by Lukas Schmidt on 15.01.16.
6 | // Copyright © 2016 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | import MapKit
10 |
11 | extension ICETrip {
12 | public var mapAnnotations: [MKPointAnnotation] {
13 | return stops.map { $0.station.mapAnnotation }.flatMap { $0 }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/ICEInformationiOSTests/ICEInformationiOSTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ICEInformationiOSTests.swift
3 | // ICEInformationiOSTests
4 | //
5 | // Created by Lukas Schmidt on 25.12.15.
6 | // Copyright © 2015 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import ICEOnboardAPI
11 |
12 | class ICEInformationiOSTests: XCTestCase {
13 |
14 | func testParseICEStatus() {
15 | let data = statusDataString.data(using: String.Encoding.utf8)!
16 | guard let json = try! JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any] else {
17 | XCTFail()
18 | return
19 | }
20 |
21 | let iceStatus = try! ICEStatus(object: json)
22 | XCTAssertEqual(iceStatus.location.latitude, 49.404305)
23 | XCTAssertEqual(iceStatus.location.longitude, 8.547148)
24 | XCTAssertEqual(iceStatus.speed, 221.8000030517578)
25 | }
26 |
27 | func testParseICETripInformation() {
28 | let data = tripInforationDataString.data(using: .utf8)!
29 | guard let json = try! JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any] else {
30 | XCTFail()
31 | return
32 | }
33 | let tripInfo = try! ICETrip(object: json)
34 | XCTAssertEqual(tripInfo.trainNumber, "108")
35 | XCTAssertEqual(tripInfo.trainType, "ICE")
36 | XCTAssertEqual(tripInfo.stops.count, 10)
37 | if let firstStop = tripInfo.stops.first {
38 | XCTAssertEqual(firstStop.track, "12")
39 | XCTAssertEqual(firstStop.name, "Basel SBB")
40 | XCTAssertEqual(firstStop.evaNr, "8500010_00")
41 | XCTAssertEqual(firstStop.location.longitude, 7.589169)
42 | XCTAssertEqual(firstStop.location.latitude, 47.547077)
43 | XCTAssertEqual(firstStop.schduledTimes.departureTime, Date(timeIntervalSince1970: 1449742380000 * 0.001))
44 | }
45 | let freiburg = tripInfo.stops[2]
46 | XCTAssertEqual(freiburg.schduledTimes.depatureDelay, 60)
47 | XCTAssertTrue(freiburg.passed)
48 | XCTAssertEqual(freiburg.track, "1")
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/ICEInformationiOSTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/ICEInformationiOSTests/TestData.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TestData.swift
3 | // ICEInformation
4 | //
5 | // Created by Lukas Schmidt on 26.12.15.
6 | // Copyright © 2015 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | let statusDataString = "{\"connection\":true,\"servicelevel\":\"SERVICE\",\"speed\":221.8000030517578,\"longitude\":8.547148,\"latitude\":49.404305,\"serverTime\":1449749986439}"
12 |
13 | let tripInforationDataString = "{\"tripDate\":\"2015-12-10\",\"trainType\":\"ICE\",\"vzn\":\"108\",\"actualPosition\":173933,\"distanceFromLastStop\":45828,\"totalDistance\":475988,\"stopInfo\":{\"scheduledNext\":\"8000244_00\",\"actualNext\":\"8000244_00\",\"actualLast\":\"8000191_00\",\"actualLastStarted\":\"8000244\",\"finalStationName\":\"Düsseldorf Hbf\",\"finalStationEvaNr\":\"8000085_00\"},\"stops\":[{\"station\":{\"evaNr\":\"8500010_00\",\"name\":\"Basel SBB\",\"geocoordinates\":{\"latitude\":47.547077,\"longitude\":7.589169}},\"timetable\":{\"scheduledArrivalTime\":null,\"actualArrivalTime\":null,\"arrivalDelay\":\"\",\"scheduledDepartureTime\":1449742380000,\"actualDepartureTime\":1449742380000,\"departureDelay\":\"\"},\"track\":{\"scheduled\":\"12\",\"actual\":\"\"},\"info\":{\"status\":0,\"passed\":true,\"distance\":0,\"distanceFromStart\":0}},{\"station\":{\"evaNr\":\"8000026_00\",\"name\":\"Basel Bad Bf\",\"geocoordinates\":{\"latitude\":47.567288,\"longitude\":7.607805}},\"timetable\":{\"scheduledArrivalTime\":1449742740000,\"actualArrivalTime\":1449742800000,\"arrivalDelay\":\"+1\",\"scheduledDepartureTime\":1449742980000,\"actualDepartureTime\":1449742980000,\"departureDelay\":\"\"},\"track\":{\"scheduled\":\"4\",\"actual\":\"\"},\"info\":{\"status\":0,\"passed\":true,\"distance\":2648,\"distanceFromStart\":2648}},{\"station\":{\"evaNr\":\"8000107_00\",\"name\":\"Freiburg(Breisgau) Hbf\",\"geocoordinates\":{\"latitude\":47.997697,\"longitude\":7.84117}},\"timetable\":{\"scheduledArrivalTime\":1449744900000,\"actualArrivalTime\":1449744900000,\"arrivalDelay\":\"\",\"scheduledDepartureTime\":1449745020000,\"actualDepartureTime\":1449745080000,\"departureDelay\":\"+1\"},\"track\":{\"scheduled\":\"1\",\"actual\":\"\"},\"info\":{\"status\":0,\"passed\":true,\"distance\":50951,\"distanceFromStart\":53599}},{\"station\":{\"evaNr\":\"8000290_00\",\"name\":\"Offenburg\",\"geocoordinates\":{\"latitude\":48.476475,\"longitude\":7.946723}},\"timetable\":{\"scheduledArrivalTime\":1449746880000,\"actualArrivalTime\":1449746880000,\"arrivalDelay\":\"\",\"scheduledDepartureTime\":1449747000000,\"actualDepartureTime\":1449747060000,\"departureDelay\":\"+1\"},\"track\":{\"scheduled\":\"3\",\"actual\":\"\"},\"info\":{\"status\":0,\"passed\":true,\"distance\":53824,\"distanceFromStart\":107423}},{\"station\":{\"evaNr\":\"8000191_00\",\"name\":\"Karlsruhe Hbf\",\"geocoordinates\":{\"latitude\":48.993515,\"longitude\":8.402181}},\"timetable\":{\"scheduledArrivalTime\":1449748680000,\"actualArrivalTime\":1449748800000,\"arrivalDelay\":\"+2\",\"scheduledDepartureTime\":1449748800000,\"actualDepartureTime\":1449748980000,\"departureDelay\":\"+3\"},\"track\":{\"scheduled\":\"3\",\"actual\":\"4\"},\"info\":{\"status\":0,\"passed\":true,\"distance\":66510,\"distanceFromStart\":173933}},{\"station\":{\"evaNr\":\"8000244_00\",\"name\":\"Mannheim Hbf\",\"geocoordinates\":{\"latitude\":49.479354,\"longitude\":8.468921}},\"timetable\":{\"scheduledArrivalTime\":1449750180000,\"actualArrivalTime\":1449750420000,\"arrivalDelay\":\"+4\",\"scheduledDepartureTime\":1449750960000,\"actualDepartureTime\":1449750960000,\"departureDelay\":\"\"},\"track\":{\"scheduled\":\"3\",\"actual\":\"\"},\"info\":{\"status\":0,\"passed\":false,\"distance\":54255,\"distanceFromStart\":228188}},{\"station\":{\"evaNr\":\"8070003_00\",\"name\":\"Frankfurt(M) Flughafen Fernbf\",\"geocoordinates\":{\"latitude\":50.053167,\"longitude\":8.570185}},\"timetable\":{\"scheduledArrivalTime\":1449752760000,\"actualArrivalTime\":1449752760000,\"arrivalDelay\":\"\",\"scheduledDepartureTime\":1449752940000,\"actualDepartureTime\":1449752940000,\"departureDelay\":\"\"},\"track\":{\"scheduled\":\"Fern 6\",\"actual\":\"\"},\"info\":{\"status\":0,\"passed\":false,\"distance\":64236,\"distanceFromStart\":292424}},{\"station\":{\"evaNr\":\"8005556_00\",\"name\":\"Siegburg/Bonn\",\"geocoordinates\":{\"latitude\":50.793915,\"longitude\":7.203026}},\"timetable\":{\"scheduledArrivalTime\":1449755220000,\"actualArrivalTime\":1449755220000,\"arrivalDelay\":\"\",\"scheduledDepartureTime\":1449755340000,\"actualDepartureTime\":1449755340000,\"departureDelay\":\"\"},\"track\":{\"scheduled\":\"3\",\"actual\":\"\"},\"info\":{\"status\":0,\"passed\":false,\"distance\":127174,\"distanceFromStart\":419598}},{\"station\":{\"evaNr\":\"8073368_00\",\"name\":\"Köln Messe/Deutz Gl.11-12\",\"geocoordinates\":{\"latitude\":50.941721,\"longitude\":6.974067}},\"timetable\":{\"scheduledArrivalTime\":1449756180000,\"actualArrivalTime\":1449756180000,\"arrivalDelay\":\"\",\"scheduledDepartureTime\":1449756360000,\"actualDepartureTime\":1449756360000,\"departureDelay\":\"\"},\"track\":{\"scheduled\":\"12\",\"actual\":\"\"},\"info\":{\"status\":0,\"passed\":false,\"distance\":22991,\"distanceFromStart\":442589}},{\"station\":{\"evaNr\":\"8000085_00\",\"name\":\"Düsseldorf Hbf\",\"geocoordinates\":{\"latitude\":51.219962,\"longitude\":6.794319}},\"timetable\":{\"scheduledArrivalTime\":1449757620000,\"actualArrivalTime\":1449757620000,\"arrivalDelay\":\"\",\"scheduledDepartureTime\":null,\"actualDepartureTime\":null,\"departureDelay\":\"\"},\"track\":{\"scheduled\":\"17\",\"actual\":\"\"},\"info\":{\"status\":0,\"passed\":false,\"distance\":33399,\"distanceFromStart\":475988}}]}"
--------------------------------------------------------------------------------
/ICEOnboardWidget/Base.lproj/MainInterface.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
34 |
35 |
36 |
37 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
55 |
61 |
62 |
63 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/ICEOnboardWidget/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ICEOnboardWidget
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | XPC!
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | NSExtension
24 |
25 | NSExtensionMainStoryboard
26 | MainInterface
27 | NSExtensionPointIdentifier
28 | com.apple.widget-extension
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/ICEOnboardWidget/TodayViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TodayViewController.swift
3 | // ICEOnboardWidget
4 | //
5 | // Created by Lukas Schmidt on 07.04.17.
6 | // Copyright © 2017 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import NotificationCenter
11 | import DBNetworkStack
12 | import ICEOnboardAPI
13 |
14 |
15 | class TodayViewController: UIViewController, NCWidgetProviding {
16 | @IBOutlet weak var speedLabel: UILabel!
17 | @IBOutlet weak var destinationLabel: UILabel!
18 | @IBOutlet weak var nextStopArrivalLabel: UILabel!
19 | @IBOutlet weak var nextStopStationNameLabel: UILabel!
20 | @IBOutlet weak var nextStopPlatformLabel: UILabel!
21 |
22 | let widgetController: NCWidgetController? = nil
23 | let widgetBundleIDentifier = "de.freiraum.ICEInformation.ICEOnboardWidget"
24 | let trainOnBoardAPI = TrainOnBoardAPI()
25 |
26 | let networkService: NetworkServiceProviding = NetworkService(networkAccess: URLSession(configuration: .default))
27 | var timer: Timer?
28 |
29 | static let dateFormatter: DateFormatter = {
30 | let dateFormatter = DateFormatter()
31 | dateFormatter.dateFormat = "HH:mm"
32 |
33 | return dateFormatter
34 | }()
35 |
36 | override func viewDidLoad() {
37 | super.viewDidLoad()
38 |
39 | networkService.request(trainOnBoardAPI.trip(), onCompletion: { trip in
40 | self.setICETripUI(trip: trip)
41 |
42 | self.widgetController?.setHasContent(true, forWidgetWithBundleIdentifier: self.widgetBundleIDentifier)
43 |
44 | }, onError: { err in
45 | self.widgetController?.setHasContent(false, forWidgetWithBundleIdentifier: self.widgetBundleIDentifier)
46 | print(err)
47 |
48 | })
49 | }
50 |
51 | func setICETripUI(trip: ICETrip) {
52 | destinationLabel.text = "\(trip.trainName) nach \(trip.to.station.name)"
53 | let nextStop = trip.commingStops.first
54 | let arrivaleDate = nextStop?.schduledTimes.arrivalTime
55 | nextStopArrivalLabel.text = arrivaleDate.map { TodayViewController.dateFormatter.string(from: $0)}.map { $0 + (nextStop?.schduledTimes.depatureDelay.map {" +\(Int($0 / 60))" } ?? "") }
56 | nextStopStationNameLabel.text = nextStop?.station.name
57 | nextStopPlatformLabel.text = (nextStop?.track?.actualTrack ?? nextStop?.track?.scheduledTrack).map { "Gleis " + $0 }
58 | }
59 |
60 | func reloadInformation(onCompletion doneCallback: @escaping (Bool) -> Void) {
61 | networkService.request(trainOnBoardAPI.status(), onCompletion: { status in
62 | self.speedLabel.text = "\(Int(status.speed)) km/h"
63 | doneCallback(true)
64 | }, onError: { err in
65 | print(err)
66 | doneCallback(false)
67 | })
68 |
69 | networkService.request(trainOnBoardAPI.trip(), onCompletion: { trip in
70 | self.setICETripUI(trip: trip)
71 |
72 | self.widgetController?.setHasContent(true, forWidgetWithBundleIdentifier: self.widgetBundleIDentifier)
73 | doneCallback(true)
74 |
75 | }, onError: { err in
76 | self.widgetController?.setHasContent(false, forWidgetWithBundleIdentifier: self.widgetBundleIDentifier)
77 | print(err)
78 | doneCallback(false)
79 | })
80 | }
81 |
82 | @IBAction func didTapNextStation(_ sender: Any) {
83 | //extensionContext?.open(<#T##URL: URL##URL#>, completionHandler: nil)
84 | }
85 |
86 | func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) {
87 | print("widget perform update")
88 |
89 | timer = Timer(timeInterval: 5, repeats: true, block: { timer in
90 | self.reloadInformation(onCompletion: { success in
91 | if success {
92 | completionHandler(.newData)
93 | } else {
94 | completionHandler(.failed)
95 | }
96 | })
97 | })
98 | RunLoop.main.add(timer!, forMode: .commonModes)
99 | }
100 |
101 | override func viewDidAppear(_ animated: Bool) {
102 |
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Lukas Schmidt
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/NextStopNotification/Base.lproj/MainInterface.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
37 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
60 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
89 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/NextStopNotification/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | NextStopNotification
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | XPC!
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | NSExtension
24 |
25 | NSExtensionAttributes
26 |
27 | UNNotificationExtensionCategory
28 | NextStop
29 | UNNotificationExtensionInitialContentSizeRatio
30 | 1
31 |
32 | NSExtensionMainStoryboard
33 | MainInterface
34 | NSExtensionPointIdentifier
35 | com.apple.usernotifications.content-extension
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/NextStopNotification/NotificationViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotificationViewController.swift
3 | // NextStopNotification
4 | //
5 | // Created by Lukas Schmidt on 24.04.17.
6 | // Copyright © 2017 Lukas Schmidt. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import UserNotifications
11 | import UserNotificationsUI
12 | import DBNetworkStack
13 | import ICEOnboardAPI
14 | import JSONCodable
15 |
16 | class NotificationViewController: UIViewController, UNNotificationContentExtension {
17 |
18 | @IBOutlet var label: UILabel?
19 | let networkService: NetworkServiceProviding = NetworkService(networkAccess: URLSession(configuration: .default))
20 |
21 | override func viewDidLoad() {
22 | super.viewDidLoad()
23 | // Do any required interface initialization here.
24 | }
25 |
26 | func didReceive(_ notification: UNNotification) {
27 | print("hallo")
28 | guard let object = notification.request.content.userInfo["payload"] as? [String: Any] else { return }
29 | let connection = try! TrainConnections(object: object)
30 | label?.text = connection.connections.first?.destination.name
31 |
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Unoffical InTrain ICE API
2 |
3 |
4 | This is the reverse engineered API for the ICE-Portal running in most of the ICE trains in Germany. This is only a Demo. Do not use it in production. This API is not offical!
5 |
6 | ## Usage
7 | Use the unfinisehd iOS framework or run the demo app. Carthage may work as well. The API is only available on InTrain-WiFi.
8 |
9 | ## REST-API
10 | If you are only interestst in the REST-API, look at [this document](https://github.com/lightsprint09/InTrain-ICE-API/blob/master/DemoPayload.md) to find URLs and example payloads.
11 |
12 | ##Contibution
13 | If you want to improve this even further make a Pull Request. It would be nice to write tests as well.
14 |
--------------------------------------------------------------------------------
/Screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightsprint09/ICEOnboardAPI/05ebda2d3719e3f2d8305784d6ca0a1470494965/Screenshot.png
--------------------------------------------------------------------------------