Json Properties
Abstract
Beginning with the developer version 3.1 and the indroduction of the advanced internal web server, the access to internal properties via web services have been introduced. The properties are represented as JSON. This Article contains the format description of JSON properties.
Example
This is an example of the /sim/time subtree:
{
"path": "/sim/time",
"name": "time",
"type": "-",
"index": 0,
"nChildren": 12,
"children": [{
"path": "/sim/time/cur-time-override",
"name": "cur-time-override",
"value": "0",
"type": "long",
"index": 0,
"nChildren": 0
}, {
"path": "/sim/time/delta-sec",
"name": "delta-sec",
"value": "0.01666666667",
"type": "double",
"index": 0,
"nChildren": 0
}, {
"path": "/sim/time/warp",
"name": "warp",
"value": "-28320",
"type": "int",
"index": 0,
"nChildren": 0
}, {
"path": "/sim/time/warp-delta",
"name": "warp-delta",
"value": "0",
"type": "int",
"index": 0,
"nChildren": 0
}, {
"path": "/sim/time/delta-realtime-sec",
"name": "delta-realtime-sec",
"value": "0.01666666667",
"type": "double",
"index": 0,
"nChildren": 0
}, {
"path": "/sim/time/local-offset",
"name": "local-offset",
"value": "3600",
"type": "int",
"index": 0,
"nChildren": 0
}, {
"path": "/sim/time/utc",
"name": "utc",
"type": "-",
"index": 0,
"nChildren": 8
}, {
"path": "/sim/time/real",
"name": "real",
"type": "-",
"index": 0,
"nChildren": 7
}, {
"path": "/sim/time/elapsed-sec",
"name": "elapsed-sec",
"value": "7072.525",
"type": "double",
"index": 0,
"nChildren": 0
}, {
"path": "/sim/time/gmt",
"name": "gmt",
"value": "2014-03-27T13:25:10",
"type": "string",
"index": 0,
"nChildren": 0
}, {
"path": "/sim/time/gmt-string",
"name": "gmt-string",
"value": "13:25:10",
"type": "string",
"index": 0,
"nChildren": 0
}, {
"path": "/sim/time/sun-angle-rad",
"name": "sun-angle-rad",
"value": "0.9883239645",
"type": "double",
"index": 0,
"nChildren": 0
}]
}
Definitions
- JavaScript Object Notation (JSON), and the terms object, name, value, array, and number, are defined in IETF RTC 4627.
- The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in IETF RFC 2119.
Property Objects
A Property Object always consist of a single object. This object represents a single property node or a complete (sub) tree of nodes.
- Each object must have a member with the name path. The members value is a string naming the absolute path of the node in the property tree. Example: /engines/engine[1]
- Each object must have a member with the name name. The members value is a string that determines the name of the node. Example: engine
- Each object may have a member with the name value. The members value contains the property nodes value. The current server implementation returns property node values by using the getStringValue() function.
- Each object must have a member with the name type. The members value must be on of "-" (for no type), "alias", "bool", "int", "long", "float", "double", "string", "unspecified", "extended", "vec3d" or "vec4d".
- Each object may have a member with the name index. The members value determines the index of the node in the parents node. Example: For a node /engines/engine[1] this would be 1. A missing index attribute results in an index of 0 (zero).
- Each object may have a member with the name ts. The members value represents the time when the server read node from the property tree. This is the time of /sim/time/elapsed-sec.
- Each object may have a member with the name nChildren. The members value determines the number of children under this node. It is optional to actually display the children itself within the JSON object.
- Each object may have a member with the name children. The members value is an array of JSON Property Objects.
Accessing the Property Tree
The web service
A simple web service provides read-only access to the property tree. This web service can be reached at the URL http://localhost:port/json where port is the portnumber provided to the -httpd= startup option. Path elements following that URL are interpreted as a property path, so http://localhost:port/json/sim/time returnes the JSON representation of the property node /sim/time and its immediate children (see example above). The service understands the following request parameters:
- i - if the request parameter i is set to 'y', the output will be indented to make it more readable by humans. If the parameter is missing or assigned any other value, the output will be compressed.
- t - if the request parameter t is set to 'y', the returned properties will be time stamped with the value of simulation time
- d - the recursion depth of the resulting tree. The default and minimum depth is implemented as 1 resulting in the node itself and - if existing - the immediate children of the node. A value of 2 would return the node itself, it's children and their children. A very high value combined with a request for the root node returns a complete dump of the property tree (use this with caution!)
The /PropertyListener websocket
The property change listener websocket also sends property objects as change events for the subscribed nodes. The following is a simple HTML page that shows its usage:
<!-- Sample on how to use a websocket PropertyListener. -->
<!-- Extracted from code in Phi. -->
<!-- FlightGear must be started with HTTP server enabled on port 5701. -->
<!DOCTYPE html>
<html>
<body>GMT time in Flightgear: <input type="text" id="myText" value="">
<p>Click the button to launch the property listener for property /sim/time/gmt.</p>
<button onclick="myFunction()">Launch</button>
<script>
function myFunction() {
var textfield = document.getElementById("myText");
var ws = new WebSocket('ws://localhost:5701/PropertyListener')
console.log('web socket readyState is ' + ws.readyState)
ws.onopen = function (ev) {
console.log('onopen')
ws.send(JSON.stringify({
command: 'addListener',
node: 'sim/time/gmt'
}))
}
ws.onmessage = function (ev) {
try {
var data = JSON.parse(ev.data)
textfield.value = data.value
} catch (e) {
console.log('Exception in onmessage:' + e)
}
}
ws.onclose = function (ev) {
var msg = 'Lost connection to FlightGear.'
alert(msg)
}
ws.onerror = function (ev) {
var msg = 'Error communicating with FlightGear.'
alert(msg)
}
}
</script>
</body>
</html>
Pitfalls
- calling http://localhost:port/json results in a 404 (Not found) error. Use http://localhost:port/json/ to access the root node.
- asking for a nonexistant node returns an empty object {}