Device Control (Arm/Disarm)¶
This section describes how to control the radar, enable/disable tracking, change from indoor to outdoor etc., it is done over a REST HTTP Interface with JSON messages.
The base address is from UPnP the 'api' node of the descriptor:
HTTP GET¶
The root address returns the api version. As long as the major version does not change, backwards compatibility is available with the code you've written.
{"Version": "3.0.0"}
Setup¶
Returns a JSON object describing the current setup. Below is a description of all the properties included.
MeasurementMode¶
MeasurementMode | Description |
---|---|
Golf.Indoor | Indoor golf mode (short ball flight) |
Golf.Outdoor | Outdoor golf mode (full ball flight) |
IsMeasuring¶
True to enable measurements, false otherwise.
StartPosition¶
This position where the ball will be hit from (approximately).
This value is set through target selection
TargetPosition¶
To which point should the data received from the radar be oriented at? The value can be obtained by using the Camera API (see [Target selection]{.underline})
ExtrapolationHeight¶
The point vertically to where data is extrapolated if more ballflight than can be done physically is needed. Typically this doesn't need to be changed
LandingHeight¶
The height where LandingData (carry flat) is matched to. Typically this doesn't need to be changed
Conditions¶
Conditions describes external conditions. These conditions play an important part if the user wishes to normalize the strokes hit, or in indoor usage.
Normalization means that strokes that i.e. is hit with a range ball at a low temperature can be converted to a premium ball at 25 degrees celcius. This gives the player a fair indication of how the ball flies under 'normal' conditions. Or if you wish to add wind to the flight.
BallType¶
The ball can be set from a predefined list of balls, which all has their own characteristics.
Type | Description |
---|---|
Premium | Premium ball, Titleist Pro V1, Srixon Z-Star etc. |
PremiumHard | Similar ball speed (±2%), higher spin rate for longer clubs, similar (±5%) spinrate |
PremiumSoft | Similar ball speed (±2%), lower spin rate for longer clubs, similar (±5%) spinrate for |
LimitedDistanceHard | Ball speed lower by more than 2%, increased spin rate for wedges |
LimitedDistanceSoft | Ball speed lower by more than 2%, reduced spin rate for wedges |
Floater | Slightly higher ball speed, ball weighs only 40 g compared to normal 46 g |
Hard | Similar ball speed (±2%), higher spin rate for longer clubs, lower spinrate for wedges |
Medium | Similar ball speed (±2%), lower spin rate for wedges |
Soft | Similar ball speed (±2%), lower spin rate for both longer clubs and wedges |
ClubType¶
The club can be one from this predefined list of clubs:
Type | Description |
---|---|
Driver | Driver |
2Wood -- 9Wood | Fairway woods |
1Hybrid -- 9Hybrid | Hybrid clubs |
1Iron -- 9Iron | Irons |
PitchingWedge | Pitching Wedge (~47°) |
SandWedge | Sand Wedge (56°) |
LobWedge | Lob Wedge (60°) |
50Wedge (50/52/54/56/58/60) | Specially lofted Wedge |
Weather¶
The current weather conditions. This is used when indoor, simulation or when normalizing.
Temperature¶
Temperature in °C
Pressure¶
Air Pressure in hPa
Altitude¶
Height above sea level in m
Humidity¶
Relative humidity in percent (0.6 = 60%)
Latitude¶
Internal use
Longitude¶
Internal use
WindVelocity¶
The wind as a vector.
Example¶
{
"IsMeasuring": false,
"MeasurementMode": "Golf.Outdoor",
"StartPosition": {
"X": 2.8,
"Y": -0.14,
"Z": 0
},
"TargetPosition": {
"X": 300,
"Y": 0,
"Z": 0
},
"LandingHeight": 0,
"ExtrapolationHeight": 0,
"Conditions": {
"PlayerName": "Unknown",
"ClubType": "6Iron",
"BallType": "Premium",
"Weather": {
"Temperature": 25,
"Pressure": 1013.25,
"Altitude": 0,
"Humidity": 0.6,
"Latitude": 33,
"Longitude": 0,
"WindVelocity": {
"X": 0,
"Y": 0,
"Z": 0
}
}
}
}
Status¶
Returns a JSON object describing the current status of the device. It contains all of the values that are subject to change during operation.
Name | Type | Unit | Comments |
---|---|---|---|
SystemState | string | See SystemState | |
TrackerState | string | See TrackerState | |
Battery.State | string | Present, TemperatureCritical, TemperatureWarning, CommunicationError, Defective | |
Battery.PowerState | string | Charging,NotCharging, Discharging, Charged | |
Battery.RemainingCapacityPercent | int | ||
Gps.State | string | ||
Gps.Latitude | Double | ||
Gps.Longitude | Double | ||
Gps.Altitude | Double | ||
Gps.PDOP | |||
Gps.IsFixValid | Boolean | ||
Leveling.State | Level/Not Level/Leveling | ||
Leveling.VerticalAngle | Double | Radian | Positive value means tilted backwards |
Leveling.HorizontalAngle | Double | Radian | Positive value means tilted to the right |
{
"SystemState": "Active",
"TrackerState": null,
"Battery": {
"State": "Present",
"PowerState": "Charged",
"RemainingCapacityPercent": 100
},
"GPS": {
"State": "Error",
"Latitude": null,
"Longitude": null,
"Altitude": null,
"PDOP": null,
"IsFixValid": false
},
"Leveling": {
"State": "Level",
"HorizontalAngle": 0.000602138591938046,
"VerticalAngle": 0.11871729572065436
}
}
SystemInfo¶
Contains static information about the TrackMan
Name | Description |
---|---|
DeviceName | The name of the device. The value is also sent through upnp |
Model | Product name |
Type | Internal product type |
SerialNumber | Serial number |
SystemMode | Normal / Recovery |
SystemTime | ISO 8601 UTC |
{
"DeviceName": "TM4 1536-0001",
"Model": "TM4",
"Type": "TMA4A",
"SerialNumber": 15360001,
"SystemMode": "Normal",
"SystemTime": "2015-11-26T13:23:47Z",
}
LicenseStatus¶
The TrackMan license describes which features are enabled on the TrackMan.
This call provides the ability to check whether the device has a license for the modes the client intend to use.
Name | Description |
---|---|
Timestamp | ISO 8601 |
Signature | Base64 |
DeviceTimeValid | If the time on the device is valid |
FirmwareVersionValid | If the firmware is valid |
DeviceUsage | If usage of the TrackMan is allowed, and for how long |
HardwareMaintenance | How long and if the TrackMan is egible for hardware maintenance |
SoftwareMaintenance | How long and if the TrackMan is egible for software maintenance |
LicensedFeatures | |
LicensedMeasurementModes | Which measurement modes are allowed |
The example below is a TrackMan which works for both Indoor+Outdoor.
{
"Timestamp": "2013-02-28T14:57:55.8947821+00:00",
"Signature": "GnSP+SEuRcNYkoqpppDcP2K4wBctZyARS00fMQbjspCc9tMSrn4OlTyTwJ9q3pyQcMk9i0WWxGOWHQBfLIi5j8m+U5E6Z/UaqbJYXfP9tl6DdCMUWv4Z6J3QDsUfBLU9UWIMTZJji7GZld/R/uem3f/yS+259L6mw2v8NxXojtlNbaKUGYAJQHyYt+raqQ1hq9P2lSwenSy6ISqL68dGeFFWuVj2JTEsSlQp/cy6QfVd5IkcMYuEOiLmtuQceoSpKc74ZG+e9DIpih2abRC9tmmpw/E0otnBtb8kqmyLSzMou5//06A1+KOQorE9eQ+waG5JeUI/UEdKrLnya+EELg==",
"DeviceTimeValid": true,
"FirmwareVersionValid": true,
"DeviceUsage": {
"Valid": true,
"ExpirationDate": "2100-01-01"
},
"HardwareMaintenance": {
"Valid": true,
"ExpirationDate": "2100-01-01"
},
"SoftwareMaintenance": {
"Valid": true,
"ExpirationDate": "2100-01-01"
},
"LicensedFeatures": {
"Tps": {
"Valid": true
},
"TpsVideo": {
"Valid": true
},
"R&D": {
"Valid": true
}
},
"LicensedMeasurementModes": {
"Golf.Outdoor": {
"Valid": true
},
"Golf.Indoor": {
"Valid": true
},
}
}
FirmwareStatus¶
Contains information about the current firmware.
Name | Description |
---|---|
FirmwareInfo | Version and build date of the firmware |
RecoveryFirmwareInfo | Version and build date of the recovery firmware |
BootloaderInfo | Version and build date of the bootloader |
{
"FirmwareInfo": {
"Version": "2.0.10",
"Date": "2013-03-15"
},
"RecoveryFirmwareInfo": {
"Version": "0.1.14",
"Date": "2012-09-20"
},
"BootloaderInfo": {
"Version": null,
"Date": null
}
}
SessionStatus¶
Returns the current controller of the TrackMan. If no one is using the TrackMan, null is returned.
Name | Description |
---|---|
Operator | Name of the current user using the application |
IpAddress | Client IP |
Software | Name of the software / client device |
LoginTime | When did the user login |
LastSeenTime | When was the user last active (last answer to ping or sending a http post message) |
ClientId | The client id the client has set. This can be used to ensure that when a sessionclosed is broadcasted, the listener can match against its own clientid |
{
"Operator": "Andreas Willadsen",
"IpAddress": "172.30.20.143",
"Software": "Andreas' iPhone",
"LoginTime": "2013-03-19T07:56:13",
"LastSeenTime": "2013-03-19T07:56:30"
}
HTTP POST¶
Through POST-messages the client application has the ability to control the TrackMan.
In order to control the TrackMan, the application has to have a session id. How to obtain this is explained in the Login method.
All the methods below use the REST base address.
Login¶
To obtain control of the TrackMan, a login is required.
To get a session id, this method must be invoked with the following body:
{
"Username": "operator",
"Password": "",
"Operator": "<user_identifier>",
"Software": "<the_name_of_your_software>",
"Force": true/false,
"ClientId": "<an id of your choosing>",
}
If the username/password combination is valid, a session id in form of a GUID is returned: ie. "d94cefa2-4499-4587-a851-c31518366e70". If not, a HTTP 403 is returned.
If no one is logged in, the scenario plays out like this:
If someone is already logged in, read on.
Forced entry¶
If someone is using the TrackMan, it would be considered rude to just steal the control. Therefore, when logging in, set the force flag to false. If someone is using the TrackMan, a 403 return code is returned, and the message will contain 'An operator is already connected'.
Then the application should invoke SessionStatus to get information about who is currently controlling the TrackMan. This information can be presented to the user, which then can take the decision about whether to force login or not. If the user chooses to do so, invoke Login again with Force set to true.
The login flow in this scenario is described in the following diagram:
If the user does not wish to do so, the application could go into a 'viewer mode' where it only can display data being sent from the TrackMan. This is not uncommon if you have multiple clients connecting to the same TrackMan. Viewer mode is entered by just connecting to websocket and subscribe for messages.
Return value¶
Once logged in, the returned Session Id must be used to invoke the other POST endpoints by setting the message header 'Session-Id' to the value of the obtained session id.
If the login succeeds, a message is sent through websocket. See SessionOpened and SessionClosed for further information.
In order to match session id with a websocket connection, the session id must be included in the http request used to initialize the websocket connection.
This makes it possible for the trackman device to logout a user when the connection to that user is lost, and thereby freeing control of the trackman. If you do not send the session-id to associate the websocket with the login, the login is invalidated after 1min.
Logout¶
When the application is done using the TrackMan, please logout. This is done by posting an empty message to Logout, with the Session-Id header set.
Setup¶
When invoked, the Setup JSON message will be applied on the TrackMan.
This is where you set up the TrackMan for your current situation.
For convenience, just set the values that need to be changed. For example, if you wish to stop tracking:
{"IsMeasuring": false} //This will stop tracking
If the session id is valid and message is valid, HTTP 200 is returned, otherwise HTTP 403. If the the format of the message cannot be understood, HTTP 400 is returned. If an unexpected error occurs, HTTP 500 is returned.
See [Setup]{.underline} for information about which parameters can be set.
License¶
It is possible to update the license on the TrackMan. The license for the TrackMan is available at http://update.trackman.dk/api/license/99040003 (for a trackman with serial 99040003). That url will return a JSON document which can be uploaded to the TrackMan unit. It is done as you usually would by uploading a file by http post.