diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4dbcb53
--- /dev/null
+++ b/README.md
@@ -0,0 +1,22 @@
+
+
+## Related
+
+- https://github.com/asplendidday/ACbus
+- https://github.com/feuerrot/aseag-python
+- https://github.com/RobertKrajewski/PyASEAG
+- https://github.com/RobinMeis/pyASEAG
+- https://github.com/lebu/ASEAG-Busabfahrten
+- https://git.rwth-aachen.de/markus.witt/aseag-cli
+- https://github.com/stklcode/juraclient
+- https://github.com/acmurmeltier69/Alexa-Busauskunft
+
+
+- http://content.tfl.gov.uk/tfl-live-bus-river-bus-arrivals-api-documentation.pdf
+
+
+# API Endpoints
+
+http://countdown.api.tfl.gov.uk
+http://ivu.aseag.de/interfaces/
+http://opendata.avv.de/current_GTFS/AVV_GTFS_mit_SPNV.zip
diff --git a/connectiq/.settings/IQ_IDE.prefs b/connectiq/.settings/IQ_IDE.prefs
new file mode 100644
index 0000000..10bb291
--- /dev/null
+++ b/connectiq/.settings/IQ_IDE.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+project_manifest=manifest.xml
diff --git a/connectiq/bin/ura-busstops-settings.json b/connectiq/bin/ura-busstops-settings.json
new file mode 100644
index 0000000..3221ce5
--- /dev/null
+++ b/connectiq/bin/ura-busstops-settings.json
@@ -0,0 +1 @@
+{"settings":[{"key":"api_url_index","valueType":"number","defaultValue":1,"configTitle":"ApiUrl","configPrompt":"ApiUrlPrompt","configHelpUrl":null,"configError":null,"configType":"list","configReadonly":false,"configRequired":false,"configOptions":[{"display":"ApiUrlLocalhost","value":0},{"display":"ApiUrlNulll","value":1}],"configMin":null,"configMax":null,"configMaxLength":null}],"languages":{"valyrian":{"ApiUrl":"API URL","ApiUrlNulll":"https://connectiq-ura.0l.de","ApiUrlLocalhost":"http://localhost:8080","AppName":"Bus Stops","ApiUrlPrompt":"API URL:"}}}
\ No newline at end of file
diff --git a/connectiq/manifest.xml b/connectiq/manifest.xml
index 646f7b4..3b9f280 100644
--- a/connectiq/manifest.xml
+++ b/connectiq/manifest.xml
@@ -1,16 +1,16 @@
-
-
+
-
-
-
+
-
+
+
+
-
-
-
+
+ deu
+ eng
+
diff --git a/connectiq/monkey.jungle b/connectiq/monkey.jungle
new file mode 100644
index 0000000..45c1bf8
--- /dev/null
+++ b/connectiq/monkey.jungle
@@ -0,0 +1,2 @@
+project.manifest = manifest.xml
+
diff --git a/connectiq/resources/drawables/ASEAG.svg b/connectiq/resources/drawables/ASEAG.svg
new file mode 100644
index 0000000..6f04314
--- /dev/null
+++ b/connectiq/resources/drawables/ASEAG.svg
@@ -0,0 +1,48 @@
+
+
+
+
diff --git a/connectiq/resources/drawables/bus_icon.png b/connectiq/resources/drawables/bus_icon.png
new file mode 100644
index 0000000..ec4260a
Binary files /dev/null and b/connectiq/resources/drawables/bus_icon.png differ
diff --git a/connectiq/resources/drawables/bus_stop_sign.png b/connectiq/resources/drawables/bus_stop_sign.png
new file mode 100644
index 0000000..44b9e37
Binary files /dev/null and b/connectiq/resources/drawables/bus_stop_sign.png differ
diff --git a/connectiq/resources/drawables/bus_stop_sign.svg b/connectiq/resources/drawables/bus_stop_sign.svg
new file mode 100644
index 0000000..fc78172
--- /dev/null
+++ b/connectiq/resources/drawables/bus_stop_sign.svg
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/connectiq/resources/drawables/drawables.xml b/connectiq/resources/drawables/drawables.xml
index d0de5d6..66f0bd4 100644
--- a/connectiq/resources/drawables/drawables.xml
+++ b/connectiq/resources/drawables/drawables.xml
@@ -1,3 +1,3 @@
-
+
\ No newline at end of file
diff --git a/connectiq/resources/drawables/launcher_icon.png b/connectiq/resources/drawables/launcher_icon.png
index d3594e7..28847fb 100644
Binary files a/connectiq/resources/drawables/launcher_icon.png and b/connectiq/resources/drawables/launcher_icon.png differ
diff --git a/connectiq/resources/porperties.xml b/connectiq/resources/porperties.xml
new file mode 100644
index 0000000..1316df4
--- /dev/null
+++ b/connectiq/resources/porperties.xml
@@ -0,0 +1,15 @@
+
+
+
+ 1
+
+
+
+
+
+ @Strings.ApiUrlLocalhost
+ @Strings.ApiUrlNulll
+
+
+
+
diff --git a/connectiq/resources/strings/strings.xml b/connectiq/resources/strings/strings.xml
index ec44fdc..88febd5 100644
--- a/connectiq/resources/strings/strings.xml
+++ b/connectiq/resources/strings/strings.xml
@@ -1,3 +1,7 @@
- ASEAG Fahrplan
+ Bus Stops
+ API URL
+ API URL:
+ http://localhost:8080
+ https://connectiq-ura.0l.de
\ No newline at end of file
diff --git a/connectiq/source/BusStopApp.mc b/connectiq/source/BusStopApp.mc
index df3e1cc..af55e85 100644
--- a/connectiq/source/BusStopApp.mc
+++ b/connectiq/source/BusStopApp.mc
@@ -1,54 +1,57 @@
-using Toybox.Application as App;
-using Toybox.Position as Position;
-using Toybox.Time as Time;
+using Toybox.Application;
+using Toybox.Position;
+using Toybox.Time;
+using Toybox.Sensor;
+using Toybox.System;
-class BusStopApp extends App.AppBase {
- var mView;
- var mDelegate;
+class BusStopApp extends Application.AppBase {
+ var view;
+ var delegate;
+ var position;
+ var sensors;
+ var api_url;
- function intialize() {
- AppBase.initialize();
- }
-
- //! onStart() is called on application start up
- function onStart() {
- Position.enableLocationEvents(Position.LOCATION_CONTINUOUS, method(:onPosition));
- }
-
- //! onStop() is called when your application is exiting
- function onStop() {
- Position.enableLocationEvents(Position.LOCATION_DISABLE, method(:onPosition));
+ var offset = 0;
+ var stopId = 0;
+
+ function initialize() {
+ Application.AppBase.initialize();
+
+ loadSettings();
}
- function fakePosition() {
- var pos = new Position.Info();
-
- pos.accuracy = 0;
- pos.altitude = 0;
- pos.heading = 0;
- pos.speed = 0;
- pos.when = Time.now();
- pos.position = new Position.Location({
- :latitude => 50.7855,
- :longitude => 6.0541,
- :format => :degrees
- });
-
- mView.setPosition(pos);
+ function onSettingsChanged() {
+ loadSettings();
+ }
+
+ function loadSettings() {
+ var api_url_index = 1; //getProperty("api_url_index");
+
+ switch (api_url_index) {
+ case 0:
+ api_url = "https://localhost:8080";
+ break;
+
+ case 1:
+ api_url = "https://connectiq-ura.0l.de";
+ break;
+ }
+
+ System.println(api_url);
}
- function onPosition(info) {
- positionView.setPosition(info);
+ function onStart(state) {
+ }
+
+ function onStop(state) {
}
//! Return the initial view of your application here
function getInitialView() {
- mView = new BusStopView();
- mDelegate = new BusStopDelegate();
+ view = new BusStopView(self);
+ delegate = new BusStopDelegate(self);
- fakePosition();
-
- return [ mView, mDelegate ];
+ return [ view, delegate ];
}
}
\ No newline at end of file
diff --git a/connectiq/source/BusStopDelegate.mc b/connectiq/source/BusStopDelegate.mc
index 6fd792e..d36ec75 100644
--- a/connectiq/source/BusStopDelegate.mc
+++ b/connectiq/source/BusStopDelegate.mc
@@ -1,10 +1,36 @@
-using Toybox.WatchUi as Ui;
-using Toybox.Graphics as Gfx;
-using Toybox.System as Sys;
+using Toybox.WatchUi;
-var last_key = null;
-
-class InputTestDelegate extends Ui.BehaviorDelegate {
+class BusStopDelegate extends WatchUi.BehaviorDelegate {
+ var app;
+ function initialize(a) {
+ WatchUi.BehaviorDelegate.initialize();
+
+ app = a;
+ }
+
+ function onNextPage() {
+ app.view.offset += 1;
+
+ WatchUi.requestUpdate();
+
+ return true;
+ }
+
+ function onPreviousPage() {
+ if (app.view.offset > 0) {
+ app.view.offset -= 1;
+
+ WatchUi.requestUpdate();
+ }
+
+ return true;
+ }
+ function onSelect() {
+ app.offset = 0;
+ WatchUi.pushView(new DepartureView(app), new DepartureDelegate(app), WatchUi.SLIDE_LEFT);
+
+ return true;
+ }
}
\ No newline at end of file
diff --git a/connectiq/source/BusStopView.mc b/connectiq/source/BusStopView.mc
index 18accd2..182de96 100644
--- a/connectiq/source/BusStopView.mc
+++ b/connectiq/source/BusStopView.mc
@@ -1,105 +1,205 @@
-using Toybox.WatchUi as Ui;
-using Toybox.Graphics as Gfx;
-using Toybox.System as Sys;
-using Toybox.Lang as Lang;
-using Toybox.Communications as Comm;
-using Toybox.System as Sys;
-using Toybox.Time as Time;
-using Toybox.Timer as Timer;
+using Toybox.WatchUi;
+using Toybox.Graphics;
+using Toybox.System;
+using Toybox.Lang;
+using Toybox.Communications;
+using Toybox.System;
-class BusStopView extends Ui.View {
- var schedule = null;
- var tmr;
+class CompassDrawable extends WatchUi.Drawable {
+
+ var bearing = 0;
+ var aWidth = 2;
+ var aLength = 6;
+ var aColor = Graphics.COLOR_RED;
+
+ function initialize(settings) {
+ WatchUi.Drawable.initialize(settings);
+
+ aWidth = settings[:aWidth];
+ aLength = settings[:aLength];
+ aColor = settings[:aColor];
+ }
+
+ function setBearing(b) {
+ bearing = Math.PI * (b - 90) / 180;
+ }
+
+ function draw(dc) {
+ var rPts = new[7];
+ var aPts = [
+ [-0.5*aLength, -0.5*aWidth],
+ [ 0.0, -0.5*aWidth],
+ [ 0.0, -1.0*aWidth],
+ [ 0.5*aLength, 0],
+ [ 0.0, 1.0*aWidth],
+ [ 0.0, 0.5*aWidth],
+ [-0.5*aLength, 0.5*aWidth]
+ ];
+
+ var s = Math.sin(bearing);
+ var c = Math.cos(bearing);
+
+ for (var i = 0; i < 7; i++) {
+ var p = aPts[i];
+ rPts[i] = [
+ locX + width * (p[0] * c - p[1] * s),
+ locY + height * (p[0] * s + p[1] * c)
+ ];
+ }
+
+ dc.setColor(aColor, Graphics.COLOR_TRANSPARENT);
+ dc.fillPolygon(rPts);
+ }
+}
+
+
+class BusStopView extends WatchUi.View {
+ var stops = null;
+ var app;
+ var compass;
+
+ var offset = 0;
+ var sensors;
+ var position;
- function intialize() {
- View.initialize();
- }
-
- //! Load your resources here
- function onLayout(dc) {
- }
-
- //! Called when this View is brought to the foreground. Restore
- //! the state of this View and prepare it to be shown. This includes
- //! loading resources into memory.
- function onShow() {
- tmr = new Timer.Timer();
- tmr.start(method(:redraw), 1000, true);
- }
-
- //! Called when this View is removed from the screen. Save the
- //! state of this View here. This includes freeing resources from
- //! memory.
- function onHide() {
- tmr.stop();
- }
-
- //! Update the view
- function onUpdate(dc) {
- var string;
-
- // Set background color
- dc.setColor( Gfx.COLOR_TRANSPARENT, Gfx.COLOR_BLACK );
- dc.clear();
- dc.setColor( Gfx.COLOR_WHITE, Gfx.COLOR_TRANSPARENT );
-
- if( schedule != null ) {
- var ts = new Time.Moment(schedule[1][4] / 1000);
- var duration = Time.now().subtract(ts);
- var ts_greg = Time.Gregorian.info(ts, Time.FORMAT_MEDIUM);
- var dur_greg = Time.Gregorian.info(new Time.Moment(duration.value()), Time.FORMAT_SHORT);
-
- /* Timezone offset */
- dur_greg.hour -= 2;
-
- var arr = Lang.format("$1$:$2$:$3$", [
- (ts_greg.hour - 2),
- (ts_greg.min).format("%02u"),
- (ts_greg.sec).format("%02u")
- ]);
-
- var due = "";
- if (dur_greg.hour > 0) {
- due += dur_greg.hour + " h ";
- }
- if (dur_greg.min > 0) {
- due += dur_greg.min + " min ";
- }
- if (dur_greg.sec > 0) {
- due += dur_greg.sec + " sec ";
- }
-
- dc.drawText( (dc.getWidth() / 2), (dc.getHeight() / 2) - 80, Gfx.FONT_LARGE, schedule[1][2], Gfx.TEXT_JUSTIFY_CENTER );
- dc.drawText( (dc.getWidth() / 2), (dc.getHeight() / 2) - 40, Gfx.FONT_SMALL, schedule[1][1], Gfx.TEXT_JUSTIFY_CENTER );
- dc.drawText( (dc.getWidth() / 2), (dc.getHeight() / 2) - 20, Gfx.FONT_SMALL, schedule[1][3], Gfx.TEXT_JUSTIFY_CENTER );
- dc.drawText( (dc.getWidth() / 2), (dc.getHeight() / 2) + 10, Gfx.FONT_SMALL, arr, Gfx.TEXT_JUSTIFY_CENTER );
- dc.drawText( (dc.getWidth() / 2), (dc.getHeight() / 2) + 40, Gfx.FONT_SMALL, due, Gfx.TEXT_JUSTIFY_CENTER );
- }
- else {
- dc.drawText( (dc.getWidth() / 2), (dc.getHeight() / 2), Gfx.FONT_SMALL, "No schedule avail", Gfx.TEXT_JUSTIFY_CENTER );
- }
- }
-
- function setPosition(info) {
- var url = "http://web.0l.de:8080/";
- var parameters = { "Circle" => info.position.toDegrees()[0] + "," +
- info.position.toDegrees()[1] + ",150",
- "ReturnList" => "StopPointName,DestinationName,LineName,EstimatedTime" };
- var options = { :method => Comm.HTTP_REQUEST_METHOD_GET };
+ function initialize(a) {
+ WatchUi.View.initialize();
- Comm.makeJsonRequest(url, parameters, options, method(:requestCompleted));
+ app = a;
+ }
+
+ function onLayout(dc) {
+ var compassX = dc.getWidth() / 2;
+ var compassY = dc.getHeight() / 2 - 60;
+
+ compass = new CompassDrawable({
+ :locX => compassX,
+ :locY => compassY,
+ :width => 11,
+ :height => 11,
+ :aWidth => 2,
+ :aLength => 6,
+ :aColor => Graphics.COLOR_DK_RED
+ });
+ }
+
+ function onShow() {
+ Position.enableLocationEvents(Position.LOCATION_CONTINUOUS, method(:onPosition));
+
+ Sensor.setEnabledSensors([Sensor.SENSOR_HEARTRATE]);
+ Sensor.enableSensorEvents(method(:onSensor));
+ }
+
+ function onHide() {
+ Position.enableLocationEvents(Position.LOCATION_DISABLE, method(:updateStops));
+ }
+
+ function onPosition(positionInfo) {
+ System.println("Position: " + positionInfo.position.toDegrees());
+
+ position = positionInfo;
+ updateStops();
+ }
+
+ function onSensor(sensorInfo) {
+ System.println("Heading: " + 180.0 * Math.PI / sensorInfo.heading);
+
+ sensors = sensorInfo;
+ requestUpdate();
+ }
+
+ function onUpdate(dc) {
+ // Set background color
+ dc.setColor(Graphics.COLOR_TRANSPARENT, Graphics.COLOR_BLACK);
+ dc.clear();
+
+ var midW = dc.getWidth() / 2;
+ var midH = dc.getHeight() / 2;
+ var top = Graphics.getFontAscent(Graphics.FONT_SMALL);
+
+ if (stops != null) {
+ if (stops.size() > 0) {
+ if (offset >= stops.size()) {
+ offset = stops.size() - 1;
+ }
+
+ var stop = stops[offset];
+
+ var dist = stop["dist"] < 1000
+ ? stop["dist"].format("%.0f") + " m"
+ : (stop["dist"] / 1000).format("%.1f") + " km";
+
+ var bearing = stop["bearing"].format("%.0f") + "° (" + stop["bearing_str"] + ")";
+
+ var y = midH;
+
+ var bDeg = stop["bearing"];
+ var hDeg = 180.0 * sensors.heading / Math.PI;
+
+ dc.setColor(Graphics.COLOR_RED, Graphics.COLOR_TRANSPARENT);
+ dc.setPenWidth(4);
+ dc.drawArc(midW, midH, midW-2, Graphics.ARC_CLOCKWISE, -bDeg+5+90, -bDeg-5+90);
+
+ dc.setColor(Graphics.COLOR_YELLOW, Graphics.COLOR_TRANSPARENT);
+ dc.setPenWidth(4);
+ dc.drawArc(midW, midH, midW-2, Graphics.ARC_CLOCKWISE, -hDeg+5, -hDeg-5);
+
+ compass.setBearing(bDeg);
+ compass.draw(dc);
+
+ dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_TRANSPARENT);
+ dc.drawText(midW, y, Graphics.FONT_MEDIUM, stop["name"], Graphics.TEXT_JUSTIFY_CENTER + Graphics.TEXT_JUSTIFY_VCENTER);
+
+ y += dc.getFontAscent(Graphics.FONT_SMALL) + dc.getFontDescent(Graphics.FONT_MEDIUM);
+
+ if (stop["indicator"].length() > 0) {
+ dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_TRANSPARENT);
+ dc.drawText(midW, y, Graphics.FONT_SMALL, stop["indicator"], Graphics.TEXT_JUSTIFY_CENTER + Graphics.TEXT_JUSTIFY_VCENTER);
+ }
+
+ y += dc.getFontAscent(Graphics.FONT_TINY) + dc.getFontDescent(Graphics.FONT_SMALL);
+
+ dc.setColor(Graphics.COLOR_LT_GRAY, Graphics.COLOR_TRANSPARENT);
+ dc.drawText(midW, y, Graphics.FONT_TINY, dist, Graphics.TEXT_JUSTIFY_CENTER);
+
+ y += dc.getFontAscent(Graphics.FONT_TINY) + dc.getFontDescent(Graphics.FONT_TINY);
+
+ dc.drawText(midW, y, Graphics.FONT_TINY, bearing, Graphics.TEXT_JUSTIFY_CENTER);
+
+ app.stopId = stop["id"];
+ }
+ else {
+ dc.drawText(midW, midH, Graphics.FONT_SMALL, "No stops found!", Graphics.TEXT_JUSTIFY_CENTER);
+ }
+ }
+ else {
+ dc.drawText(midW, midH, Graphics.FONT_SMALL, "Loading...", Graphics.TEXT_JUSTIFY_CENTER);
+ }
+ }
+
+ function updateStops() {
+ var degs = position.position.toDegrees();
+ var params = {
+ "latitude" => degs[0],
+ "longitude" => degs[1],
+ "distance" => 10000,
+ "limit" => 50
+ };
+
+ var options = {
+ :method => Communications.HTTP_REQUEST_METHOD_GET,
+ :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
+ };
+
+ Communications.makeWebRequest(app.api_url + "/stops", params, options, method(:requestCompleted));
}
function requestCompleted(responseCode, data) {
- Sys.println("Request completed: " + responseCode);
+ System.println("Request completed: " + responseCode);
if (responseCode == 200) {
- schedule = data;
- redraw();
+ stops = data;
+ WatchUi.requestUpdate();
}
}
-
- function redraw() {
- WatchUi.requestUpdate();
- }
}
diff --git a/connectiq/source/DepartureDelegate.mc b/connectiq/source/DepartureDelegate.mc
new file mode 100644
index 0000000..0dbf09a
--- /dev/null
+++ b/connectiq/source/DepartureDelegate.mc
@@ -0,0 +1,36 @@
+using Toybox.WatchUi;
+
+class DepartureDelegate extends WatchUi.BehaviorDelegate {
+ var app;
+
+ function initialize(a) {
+ WatchUi.BehaviorDelegate.initialize();
+
+ app = a;
+ }
+
+ function onNextPage() {
+ app.offset += 1;
+
+ WatchUi.requestUpdate();
+
+ return true;
+ }
+
+ function onPreviousPage() {
+ if (app.offset > 0) {
+ app.offset -= 1;
+
+ WatchUi.requestUpdate();
+ }
+
+ return true;
+ }
+
+ function onBack() {
+ app.offset = 0;
+ WatchUi.popView(WatchUi.SLIDE_RIGHT);
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/connectiq/source/DepartureView.mc b/connectiq/source/DepartureView.mc
new file mode 100644
index 0000000..f43cf82
--- /dev/null
+++ b/connectiq/source/DepartureView.mc
@@ -0,0 +1,84 @@
+using Toybox.WatchUi;
+using Toybox.Graphics;
+using Toybox.System;
+using Toybox.Communications;
+using Toybox.Timer;
+
+class DepartureView extends WatchUi.View {
+ var departures = null;
+ var tmr;
+ var app;
+
+ function initialize(a) {
+ WatchUi.View.initialize();
+
+ app = a;
+
+ updateDepartures();
+ }
+
+ function onLayout(dc) {
+
+ }
+
+ function onShow() {
+ tmr = new Timer.Timer();
+ tmr.start(method(:updateDepartures), 10000, true);
+ }
+
+
+ function onHide() {
+ tmr.stop();
+ }
+
+ function onUpdate(dc) {
+ dc.setColor(Graphics.COLOR_TRANSPARENT, Graphics.COLOR_BLACK);
+ dc.clear();
+ dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_TRANSPARENT);
+
+ var mid = dc.getWidth() / 2;
+ var top = Graphics.getFontAscent(Graphics.FONT_SMALL);
+
+ if (departures != null) {
+ if (departures.size() > 0) {
+ for (var i = app.offset; i < departures.size(); i++) {
+ var dep = departures[i];
+
+ dc.drawText(mid, top, Graphics.FONT_SMALL, dep["line"] + " " + dep["dest"], Graphics.TEXT_JUSTIFY_CENTER);
+ top += Graphics.getFontAscent(Graphics.FONT_TINY);
+ dc.drawText(mid, top, Graphics.FONT_XTINY, dep["delta_str"], Graphics.TEXT_JUSTIFY_CENTER);
+
+ top += Graphics.getFontHeight(Graphics.FONT_SMALL);
+ }
+ }
+ else {
+ dc.drawText( (dc.getWidth() / 2), (dc.getHeight() / 2), Graphics.FONT_SMALL, "No departures!", Graphics.TEXT_JUSTIFY_CENTER );
+ }
+ }
+ else {
+ dc.drawText( (dc.getWidth() / 2), (dc.getHeight() / 2), Graphics.FONT_SMALL, "Loading...", Graphics.TEXT_JUSTIFY_CENTER );
+ }
+ }
+
+ function updateDepartures() {
+ var parameters = {
+ "id" => app.stopId,
+ "limit" => 10
+ };
+ var options = {
+ :method => Communications.HTTP_REQUEST_METHOD_GET,
+ :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
+ };
+
+ Communications.makeWebRequest(app.api_url + "/departures", parameters, options, method(:requestCompleted));
+ }
+
+ function requestCompleted(responseCode, data) {
+ System.println("Request completed: " + responseCode);
+
+ if (responseCode == 200) {
+ departures = data;
+ WatchUi.requestUpdate();
+ }
+ }
+}
diff --git a/rev-eng/script.sh b/rev-eng/script.sh
new file mode 100644
index 0000000..54f45ec
--- /dev/null
+++ b/rev-eng/script.sh
@@ -0,0 +1,8 @@
+API_BASE="http://ivu.aseag.de/interfaces/ura"
+
+LOC="50.7802655,6.0752138,400"
+RL="StopPointName,StopID,StopPointState,StopPointIndicator,Latitude,Longitude,VisitNumber,TripID,VehicleID,LineID,LineName,DirectionID,DestinationName,DestinationText,EstimatedTime,BaseVersion"
+
+# curl "${API_BASE}/location?searchString=*&maxResults=10000" | jq .
+
+curl "${API_BASE}/instant_V1?Circle=${LOC}&StopPointState=0&ReturnList=${RL}"