| 1 | [![Build Status](https://travis-ci.org/ibnfirnas/erlang-x_plane_data.svg?branch=master)](https://travis-ci.org/ibnfirnas/erlang-x_plane_data) |
| 2 | |
| 3 | X-Plane UDP data parser |
| 4 | ======================= |
| 5 | |
| 6 | ![Data output in the cockpit](screenshot.png) |
| 7 | |
| 8 | Examples |
| 9 | -------- |
| 10 | |
| 11 | ### Receive data packet |
| 12 | |
| 13 | ```erlang |
| 14 | {ok, Socket} = gen_udp:open(Port, [binary, {active, false}]), |
| 15 | {ok, {_, _, <<XPlaneDataPacket/binary>>}} = gen_udp:recv(Socket, 0), |
| 16 | ``` |
| 17 | |
| 18 | ### Parse data packet |
| 19 | |
| 20 | ```erlang |
| 21 | {ok, {64=Index, GroupsRaw}=DataRaw} = x_plane_data_raw:of_bin(XPlaneDataPacket), |
| 22 | ``` |
| 23 | |
| 24 | ### Access parsed data |
| 25 | |
| 26 | #### Raw |
| 27 | |
| 28 | At this stage, only the structure of the packet was parsed. No attempt at |
| 29 | interpreting the values have been made: |
| 30 | |
| 31 | ```erlang |
| 32 | % Speeds are in group 3 |
| 33 | {3, Speeds} = lists:keyfind(3, 1, GroupsRaw), |
| 34 | { VindKias |
| 35 | , VindKeas |
| 36 | , VtrueKtas |
| 37 | , VtrueKtgs |
| 38 | , _ |
| 39 | , VindMph |
| 40 | , VtrueMphas |
| 41 | , VtrueMphgs |
| 42 | } = Speeds, |
| 43 | |
| 44 | % Pitch roll and headings values are in group 17 |
| 45 | {17, PitchRollHeadings} = lists:keyfind(17, 1, GroupsRaw), |
| 46 | { PitchDeg |
| 47 | , RollDeg |
| 48 | , HdingTrue |
| 49 | , HdingMag |
| 50 | , _ |
| 51 | , _ |
| 52 | , _ |
| 53 | , _ |
| 54 | } = PitchRollHeadings, |
| 55 | ``` |
| 56 | |
| 57 | #### Named |
| 58 | |
| 59 | Here we identify what each of the numbered groups mean in a given X-Plane |
| 60 | version. Right now only X-Plane 10 (packet index 64) is supported and I only |
| 61 | identified 3 groups so far: |
| 62 | |
| 63 | | packet index | group index | group name | |
| 64 | |--------------|-------------|----------------------| |
| 65 | | 64 | 3 | `speeds` | |
| 66 | | 64 | 17 | `pitch_roll_heading` | |
| 67 | | 64 | 20 | `lat_lon_alt` | |
| 68 | |
| 69 | Unidentified groups (with index other than what is listed above) will be |
| 70 | absent from the list of named groups (think of `x_plane_data_named:of_raw/1` as |
| 71 | a filter), so you'll have to access their raw version, if needed. |
| 72 | |
| 73 | ##### Identify |
| 74 | ```erlang |
| 75 | {ok, {x_plane_data_v10, GroupsNamed}} = x_plane_data_named:of_raw(DataRaw), |
| 76 | ``` |
| 77 | |
| 78 | ##### Access |
| 79 | ```erlang |
| 80 | -include_lib("x_plane_data/include/x_plane_data_group_speeds.hrl"). |
| 81 | {speeds, #x_plane_data_group_speeds |
| 82 | { vind_kias = VindKias |
| 83 | , vind_keas = VindKeas |
| 84 | , vtrue_ktas = VtrueKtas |
| 85 | , vtrue_ktgs = VtrueKtgs |
| 86 | , vind_mph = VindMph |
| 87 | , vtrue_mphas = VtrueMphas |
| 88 | , vtrue_mphgs = VtrueMphgs |
| 89 | } |
| 90 | } = lists:keyfind(speeds, 1, GroupsNamed), |
| 91 | |
| 92 | ... |
| 93 | |
| 94 | -include_lib("x_plane_data/include/x_plane_data_group_pitch_roll_heading.hrl"). |
| 95 | {pitch_roll_heading, #x_plane_data_group_pitch_roll_heading |
| 96 | { pitch_deg = PitchDeg |
| 97 | , roll_deg = RollDeg |
| 98 | , hding_true = HdingTrue |
| 99 | , hding_mag = HdingMag |
| 100 | } |
| 101 | } = lists:keyfind(pitch_roll_heading, 1, GroupsNamed), |
| 102 | |
| 103 | ... |
| 104 | |
| 105 | -include_lib("x_plane_data/include/x_plane_data_group_lat_lon_alt.hrl"). |
| 106 | {lat_lon_alt, #x_plane_data_group_lat_lon_alt |
| 107 | { lat_deg = LatDeg |
| 108 | , lon_deg = LonDeg |
| 109 | , alt_ftmsl = AltFtmsl |
| 110 | , alt_ftagl = AltFtagl |
| 111 | , on_runwy = OnRunwy |
| 112 | , alt_ind = AltInd |
| 113 | , lat_south = LatSouth |
| 114 | , lon_west = LonWest |
| 115 | } |
| 116 | } = lists:keyfind(lat_lon_alt, 1, GroupsNamed), |
| 117 | ``` |
| 118 | |
| 119 | Packet structure |
| 120 | ---------------- |
| 121 | |
| 122 | ```erlang |
| 123 | <<"DATA", PacketIndex:8/integer, Groups/binary>>, |
| 124 | << GroupIndex:32/little-integer |
| 125 | , GroupValue1:32/little-float |
| 126 | , GroupValue2:32/little-float |
| 127 | , GroupValue3:32/little-float |
| 128 | , GroupValue4:32/little-float |
| 129 | , GroupValue5:32/little-float |
| 130 | , GroupValue6:32/little-float |
| 131 | , GroupValue7:32/little-float |
| 132 | , GroupValue8:32/little-float |
| 133 | , GroupsRest/binary |
| 134 | >> = Groups, |
| 135 | ``` |
| 136 | |
| 137 | Where `PacketIndex` indicates something like a schema version, i.e. what each |
| 138 | of the numbered groups means. For example, in X-Plane 10, packet index is 64 |
| 139 | (character `"@"`) and group 3 contains speed data, in which the 8 group values |
| 140 | are: |
| 141 | |
| 142 | | Location | Label | Description | |
| 143 | |----------|---------------|-------------| |
| 144 | | 1 | `vind_kias` | Velocity indicated, in knots indicated airspeed. | |
| 145 | | 2 | `vind_keas` | Velocity indicated, in knots equivalent airspeed (the calibrated airspeed corrected for adiabatic compressible flow at the craft's current altitude). | |
| 146 | | 3 | `vtrue_ktas` | Velocity true (the speed of the craft relative to undisturbed air), in knots true airspeed. | |
| 147 | | 4 | `vtrue_ktgs` | Velocity true, in knots true ground speed. | |
| 148 | | 5 | | Unused. Contains a dummy value. | |
| 149 | | 6 | `vind_mph` | Velocity indicated, in miles per hour. | |
| 150 | | 7 | `vtrue_mphas` | Velocity true, in miles per hour airspeed. | |
| 151 | | 8 | `vtrue_mphgs` | Velocity true, in miles per hour ground speed. | |
| 152 | |
| 153 | |
| 154 | References |
| 155 | ---------- |
| 156 | |
| 157 | - `X-Plane_10_manual.pdf` (distributed with X-Plane 10) |
| 158 | - http://b58.svglobe.com/data.html |
| 159 | - http://www.nuclearprojects.com/xplane/xplaneref.html |