Merge branch 'master' into axel-usermanagement

This commit is contained in:
Axel Uhl committed 2014-10-29 12:52:12 +01:00
commit dd4a49bcec
5 files changed
+27 -10

No files matched your search

+16
View File
@@ -0,0 +1,16 @@
# Big Data - Amount of data processed by the SAP Sailing Analytics
Amount of data processed by the SAP Sailing Analytics during events.
## Kieler Woche 2014
- 13,836,495 GPS fixes with position, speed and course (996,227,640 bytes of memory)
- 6,617,218 wind measurements with position, speed, course and heading of the unit, and speed and direction of the wind (370,564,208 bytes of memory)
- 286,392 maneuvers analyzed (13,764,816 bytes or memory)
## 505 Worlds 2014
- 9,012,271 GPS fixes with position, speed and course (648,883,512 bytes of memory)
- 1,036,846 wind measurements with position, speed, course and heading of the unit, and speed and direction of the wind (58,063,376 bytes of memory)
- 205,532 maneuvers analyzed (9,865,536 bytes or memory)
+197
View File
@@ -0,0 +1,197 @@
# Tracking App API v1 Draft
## General
This is a design for the REST API to be used by the iOS and Android tracking apps.
## Event Data
### Path
http://sapsailing.com/b964b0
A shortened URL is used. This URL is embedded in the QR code. In case a user does not have a QR code, she can manually enter the URL into the app.
Note that a unique URL needs to be defined per competitor and event.
### Verb
GET
### Response
{
"serverUrl" : "http://ec2-54-171-89-140.eu-west-1.compute.amazonaws.com:8888"
"event" : {
"eventId" : "123",
"eventTitle" : "Kieler Woche",
"eventStartDate" : 1414414481000,
"eventEndDate" : 1414609200000,
"eventDays": [
{
"eventDayStart" : "1414414481000",
"eventDayEnd" : "1414436081000"
},
{
"eventDayStart" : "1414497600000",
"eventDayEnd" : "1414522800000"
},
{
"eventDayStart" : "1414584000000",
"eventDayEnd" : "1414609200000"
},
]
}
"competitor" : {
"competitorId" : "250cf8b51c773f3f8dc8b4be867a9a02",
"competitorName" : "Alster Segel Club",
"competitorProfileImageUrl" : "http://s3.amazonaws.com/sapsailing/profile_images/68053af2923e00204c3ca7c6a3150cf7.jpeg"
}
}
**serverUrl** This is the endpoint to be used for all following REST requests.
**eventDays** An event can be held for several days. This array contains all start and end times of an event day. This is used to remind a user to turn tracking on or off (in order to save battery).
### Push Notifications
Event data can be updated via push notifications. These are limited on iOS to 256 bytes (not characters). For this reason, on receiving a push notification, the app must GET the event data.
## Check-In
After the user has received the event data with the short URL, the smartphone is mapped to a competitor.
_Question: What should be done if a second device is mapped to competitor?_
### Path
/event/{event_id}/competitor/{competitor_id}/device
### Verb
POST
### Request
{
"deviceUdid" : "202cb962ac59075b964b07152d234b70",
"deviceType" : "ios",
"pushDeviceId" : "0f744707bebcf74f9b7c25d48e3358945f6aa01da5ddb387462c7eaf61bbad78"
}
**deviceUdid** A UDID generated by device, generated on first run.
**deviceType** Either `android` or `ios`. Needed for selecting correct push notification service.
**pushDeviceId** On Android the GCM regId, on iOS the APNS push token. This is needed for sending push notifications to the device.
## Upload Profile Image
An image can be uploaded per competitor and event.
### Path
/event/{event_id}/competitor/{competitor_id}/profile_image
### Verb
POST
### Request
Multipart upload with part `image` containing JPEG image 80%, max dimension 1200px.
### Response
{
"profileImageUrl" : "http://s3.amazonaws.com/sapsailing/profile_images/68053af2923e00204c3ca7c6a3150cf7.jpeg"
}
**profileImageUrl** URL of uploaded image.
## Tracking Status
As general information, the tracking status of the smartphone is sent.
### Path
/event/{event_id}/competitor/{competitor_id}/tracking_status
### Verb
POST
### Request
{
"timeStamp" : "14144158370000",
"status" : "start"
}
**status** Either `start` or `stop`.
## Send Location
The main data sent by the app.
### Path
/event/{event_id}/competitor/{competitor_id}/location
### Verb
POST
### Request
{
"timestamp" : "14144160080000",
"latitude" : "54.325246",
"longitude" : "10.148556",
"speed" : "3.61",
"course" : "258.11",
}
**speed** Speed over ground in meters per second.
**course** Heading in degrees.
### Web Sockets
Note that locations should be sent via web socket instead of HTTP POST in order to speed up communication. POST requests can be used as a fallback in case web sockets aren't available.
## Bulk Upload Locations
Locations should be sent live during an event. In case of missing network, locations are stored to the device and uploaded to the server later for analysis.
As this could be a lot of data, GZIP compression is a must. Bulk uploads should be chunked, e.g. per day or per 1,000 locations.
### Path
/event/{event_id}/competitor/{competitor_id}/location_bulk
### Verb
POST
### Request
{
"locations" : [
{
"timestamp" : "14144160080000",
"latitude" : "54.325246",
"longitude" : "10.148556",
"speed" : "3.61",
"course" : "258.11",
},
{
"timestamp" : "14144168490000",
"latitude" : "55.12456",
"longitude" : "8.03456",
"speed" : "5.1",
"course" : "14.2",
},
...
]
}
+313
View File
@@ -0,0 +1,313 @@
# Tracking App API
This document describes the API used by the tracking smartphone apps.
## Device Mapping
Following POST call maps smartphones to competitors.
### Verb
POST
### Path
/sailingserver/rc/racelog
?leaderboard=Guy%27s+Regatta
&raceColumn=M1
&fleet=Default
&clientuuid=92669a6c-72c9-46d2-a815-f51ff15a4369
#### Query Parameters
Query parameters are required and are encoded in QR code.
`clientuuid` ???
### Request Body
{
"timestamp": 1413460233257,
"id": "c72eabea-f456-4b29-9ba0-dadd06f5a179",
"passId": 0, ***IS THIS NEEDED?***
"fromMillis": 1413459900000,
"@class": "DeviceCompetitorMappingEvent",
"createdAt": 1413460233258,
"item": {
"id": "da815c7f-c935-44f5-b01d-20b750ce75ab",
"nationality": "", ***IS THIS NEEDED?***
"displayColor": null, ***IS THIS NEEDED?***
"idtype": "java.util.UUID",
"name": null, ***IS THIS NEEDED?***
"nationalityISO3": "", ***IS THIS NEEDED?***
"sailID": "", ***IS THIS NEEDED?***
"nationalityISO2": "" ***IS THIS NEEDED?***
},
"authorName": "Tracking App",
"competitors": [ ], ***IS THIS NEEDED?***
"device": {
"stringRepresentation": "147d8230-4db0-11e4-916c-0800200c9a66",
"id": "147d8230-4db0-11e4-916c-0800200c9a66",
"type": "smartphoneUUID"
},
"authorPriority": 0, ***IS THIS NEEDED?***
"toMillis": 1413460500000
}
### Response Body
[
{
"@class": "RaceLogStartProcedureChangedEvent",
"id": "1e76925c-6518-434c-8d43-f5abf97154bf",
"createdAt": 1413794205930,
"timestamp": 1413794205905,
"passId": 0,
"competitors": [],
"authorName": "Shore",
"authorPriority": 4,
"startProcedureType": "RRS26"
},
{
"@class": "RaceLogStartTimeEvent",
"id": "978701be-d087-4ac1-a263-db2d7059e5d8",
"createdAt": 1413794205931,
"timestamp": 1413794205905,
"passId": 0,
"competitors": [],
"authorName": "Shore",
"authorPriority": 4,
"nextStatus": "SCHEDULED",
"startTime": 1413794160000
},
{
"@class": "DenoteForTrackingEvent",
"id": "f332a53b-db8c-4e22-b250-042400e08c9a",
"createdAt": 1413460016871,
"timestamp": 1413460016869,
"passId": 0,
"competitors": [],
"authorName": "com.sap.sailing.server.RacingEventService",
"authorPriority": 1,
"raceName": "Guy's Regatta M1 Default",
"boatClass": "Small",
"raceId": "dee82eb7-4d0f-4d1b-b834-9d1faa6b2517"
},
{
"@class": "RegisterCompetitorEvent",
"id": "f381d118-3344-41d3-bd47-4a2beb206d30",
"createdAt": 1413460067296,
"timestamp": 1413460067294,
"passId": 0,
"competitors": [
{
"idtype": "java.util.UUID",
"id": "da815c7f-c935-44f5-b01d-20b750ce75ab",
"name": "Competitor A",
"displayColor": null,
"sailID": "A",
"nationality": "",
"nationalityISO2": "",
"nationalityISO3": ""
}
],
"authorName": "com.sap.sailing.server.RacingEventService",
"authorPriority": 1
},
{
"@class": "RegisterCompetitorEvent",
"id": "f7e6da48-d245-4615-8cbb-f7b4a96c7566",
"createdAt": 1413460067298,
"timestamp": 1413460067297,
"passId": 0,
"competitors": [
{
"idtype": "java.util.UUID",
"id": "9c09ad1a-e05c-45d2-8b08-b8a6f4b03004",
"name": "Competitor B",
"displayColor": null,
"sailID": "B",
"nationality": "",
"nationalityISO2": "",
"nationalityISO3": ""
}
],
"authorName": "com.sap.sailing.server.RacingEventService",
"authorPriority": 1
},
{
"@class": "DefineMarkEvent",
"id": "87b347c8-ad57-47ca-9b67-2fe01ac72e3f",
"createdAt": 1413461050887,
"timestamp": 1413461050886,
"passId": 0,
"competitors": [],
"authorName": "com.sap.sailing.server.RacingEventService",
"authorPriority": 1,
"mark": {
"@class": "Mark",
"name": "Buoy 1",
"id": "a8f20289-0246-438f-a4de-9bc1c30b9fc3",
"color": "",
"pattern": "",
"shape": "CONICAL",
"type": "BUOY"
}
},
{
"@class": "DefineMarkEvent",
"id": "d48d2e37-496b-48b8-8fb6-5233638c018b",
"createdAt": 1413461060946,
"timestamp": 1413461060946,
"passId": 0,
"competitors": [],
"authorName": "com.sap.sailing.server.RacingEventService",
"authorPriority": 1,
"mark": {
"@class": "Mark",
"name": "Buoy 2",
"id": "a8a84cf8-ad78-4db1-a593-91f43ced523a",
"color": "",
"pattern": "",
"shape": "CONICAL",
"type": "BUOY"
}
},
{
"@class": "RaceLogCourseDesignChangedEvent",
"id": "f4e0d5c6-494c-4492-a09d-1665baf385ca",
"createdAt": 1413461086484,
"timestamp": 1413461086483,
"passId": 0,
"competitors": [],
"authorName": "com.sap.sailing.server.RacingEventService",
"authorPriority": 1,
"courseDesign": {
"name": "Course for Guy's Regatta - M1 - Default",
"waypoints": [
{
"name": "Buoy 1",
"passingInstruction": "None",
"controlPoint": {
"@class": "Mark",
"name": "Buoy 1",
"id": "a8f20289-0246-438f-a4de-9bc1c30b9fc3",
"color": "",
"pattern": "",
"shape": "CONICAL",
"type": "BUOY"
}
},
{
"name": "Buoy 2",
"passingInstruction": "None",
"controlPoint": {
"@class": "Mark",
"name": "Buoy 2",
"id": "a8a84cf8-ad78-4db1-a593-91f43ced523a",
"color": "",
"pattern": "",
"shape": "CONICAL",
"type": "BUOY"
}
}
]
}
},
{
"@class": "DeviceCompetitorMappingEvent",
"id": "cf5995a4-6cca-4cca-a6cc-2357a32bb436",
"createdAt": 1413463043674,
"timestamp": 1413463043674,
"passId": 0,
"competitors": [],
"authorName": "Tracking App",
"authorPriority": 0,
"fromMillis": 1413461400000,
"toMillis": 1413464100000,
"item": {
"idtype": "java.util.UUID",
"id": "da815c7f-c935-44f5-b01d-20b750ce75ab",
"name": "Competitor A",
"displayColor": null,
"sailID": "A",
"nationality": "",
"nationalityISO2": "",
"nationalityISO3": ""
},
"device": {
"type": "smartphoneUUID",
"id": "147d8230-4db0-11e4-916c-0800200c9a66",
"stringRepresentation": "147d8230-4db0-11e4-916c-0800200c9a66"
}
},
{
"@class": "RevokeEvent",
"id": "481e710e-9f8d-4222-a4ae-ec4b15b7a8bd",
"createdAt": 1413793852767,
"timestamp": 1413793852767,
"passId": 0,
"competitors": [],
"authorName": "com.sap.sailing.server.RacingEventService",
"authorPriority": 0,
"revokedEventId": "f332a53b-db8c-4e22-b250-042400e08c9a"
},
{
"@class": "DenoteForTrackingEvent",
"id": "740701f2-639b-4bfb-8f72-06093b0ac1e8",
"createdAt": 1413793857143,
"timestamp": 1413793857143,
"passId": 0,
"competitors": [],
"authorName": "com.sap.sailing.server.RacingEventService",
"authorPriority": 0,
"raceName": "Guy's Regatta M1 Default",
"boatClass": "Small",
"raceId": "8fd69b14-f9bf-46bc-8bda-def5814d8758"
},
...
]
The response is a JSON array containing all events pertaining to leaderboard.
_Is that correct?_
**@class**
`RaceLogStartProcedureChangedEvent` ???
`RaceLogStartTimeEvent` ???
`DenoteForTrackingEvent` ???
`RegisterCompetitorEvent` Add new competitor.
`DefineMarkEvent` Add new mark (e.g. buoy).
`RaceLogCourseDesignChangedEvent` Called when defining course with marks.
`DeviceCompetitorMappingEvent` Triggered when device and competitor are mapped.
`RevokeEvent` Called e.g. when deleting a device / competitor mapping.
## GPSFix
### Verb
POST
### Path
/tracking/recordFixesFlatJson
### Body
{
"bearingDeg":48,
"timeMillis":1414504349713,
"speedMperS":0,
"lonDeg":9.9650613,
"deviceUuid":"147d8230-4db0-11e4-916c-0800200c9a66",
"latDeg":53.5510491
}
### Response
200