| 1 | -module(x_plane_datum). |
| 2 | |
| 3 | -include("x_plane_datum_defaults.hrl"). |
| 4 | -include("include/x_plane_data.hrl"). |
| 5 | |
| 6 | -export_type( |
| 7 | [ t/0 |
| 8 | , label/0 |
| 9 | , anonymous/0 |
| 10 | , identified/0 |
| 11 | , parsing_error/0 |
| 12 | ]). |
| 13 | |
| 14 | -export( |
| 15 | [ of_bin/1 % Use default max index |
| 16 | , of_bin/2 % Specify max index |
| 17 | ]). |
| 18 | |
| 19 | -type parsing_error() :: |
| 20 | {block_structure_invalid, binary()} |
| 21 | | {block_index_byte_out_of_range, anonymous()} |
| 22 | . |
| 23 | |
| 24 | -type anonymous() :: |
| 25 | { non_neg_integer() |
| 26 | , float() |
| 27 | , float() |
| 28 | , float() |
| 29 | , float() |
| 30 | , float() |
| 31 | , float() |
| 32 | , float() |
| 33 | , float() |
| 34 | }. |
| 35 | |
| 36 | -type label() :: |
| 37 | speeds |
| 38 | | pitch_roll_heading |
| 39 | | lat_lon_alt |
| 40 | . |
| 41 | |
| 42 | -type identified() :: |
| 43 | #x_plane_datum_speeds{} |
| 44 | | #x_plane_datum_pitch_roll_heading{} |
| 45 | | #x_plane_datum_lat_lon_alt{} |
| 46 | . |
| 47 | |
| 48 | -type t() :: |
| 49 | {non_neg_integer() , anonymous()} |
| 50 | | {label() , identified()} |
| 51 | . |
| 52 | |
| 53 | -spec of_bin(binary()) -> |
| 54 | hope_result:t(t(), parsing_error()). |
| 55 | of_bin(<<Block/binary>>) -> |
| 56 | of_bin(Block, ?DEFAULT_MAX_INDEX). |
| 57 | |
| 58 | -spec of_bin(binary(), non_neg_integer()) -> |
| 59 | hope_result:t(t(), parsing_error()). |
| 60 | of_bin(<<Block/binary>>, MaxIndex) -> |
| 61 | case anonymous_of_bin(Block, MaxIndex) |
| 62 | of {ok, Anonymous} -> |
| 63 | IdentifiedOrIndexed = identify_or_index(Anonymous), |
| 64 | {ok, IdentifiedOrIndexed} |
| 65 | ; {error, _}=Error -> |
| 66 | Error |
| 67 | end. |
| 68 | |
| 69 | -spec anonymous_of_bin(binary(), non_neg_integer()) -> |
| 70 | hope_result:t(anonymous(), parsing_error()). |
| 71 | anonymous_of_bin( |
| 72 | << Index:32/little-integer |
| 73 | , V1:32/little-float |
| 74 | , V2:32/little-float |
| 75 | , V3:32/little-float |
| 76 | , V4:32/little-float |
| 77 | , V5:32/little-float |
| 78 | , V6:32/little-float |
| 79 | , V7:32/little-float |
| 80 | , V8:32/little-float |
| 81 | >>, |
| 82 | MaxIndex |
| 83 | ) -> |
| 84 | Anonymous = {Index, V1, V2, V3, V4, V5, V6, V7, V8}, |
| 85 | if Index > 0 andalso Index =< MaxIndex -> |
| 86 | {ok, Anonymous} |
| 87 | ; true -> |
| 88 | {error, {block_index_byte_out_of_range, Anonymous}} |
| 89 | end; |
| 90 | anonymous_of_bin(<<Block/binary>>, _) -> |
| 91 | % This case shouldn't be possible with a correct packet length, but we want |
| 92 | % to allow for possibility of using this module independently of it's |
| 93 | % parent, data module. |
| 94 | {error, {block_structure_invalid, Block}}. |
| 95 | |
| 96 | -spec identify_or_index(anonymous()) -> |
| 97 | t(). |
| 98 | identify_or_index({3, V1, V2, V3, V4, _, V6, V7, V8}) -> |
| 99 | Datum = |
| 100 | #x_plane_datum_speeds |
| 101 | { vind_kias = V1 |
| 102 | , vind_keas = V2 |
| 103 | , vtrue_ktas = V3 |
| 104 | , vtrue_ktgs = V4 |
| 105 | |
| 106 | , vind_mph = V6 |
| 107 | , vtrue_mphas = V7 |
| 108 | , vtrue_mphgs = V8 |
| 109 | }, |
| 110 | {speeds, Datum}; |
| 111 | identify_or_index({17, V1, V2, V3, V4, _, _, _, _}) -> |
| 112 | Datum = |
| 113 | #x_plane_datum_pitch_roll_heading |
| 114 | { pitch_deg = V1 |
| 115 | , roll_deg = V2 |
| 116 | , hding_true = V3 |
| 117 | , hding_mag = V4 |
| 118 | }, |
| 119 | {pitch_roll_heading, Datum}; |
| 120 | identify_or_index({20, V1, V2, V3, V4, V5, V6, V7, V8}) -> |
| 121 | Datum = |
| 122 | #x_plane_datum_lat_lon_alt |
| 123 | { lat_deg = V1 |
| 124 | , lon_deg = V2 |
| 125 | , alt_ftmsl = V3 |
| 126 | , alt_ftagl = V4 |
| 127 | , on_runwy = V5 |
| 128 | , alt_ind = V6 |
| 129 | , lat_south = V7 |
| 130 | , lon_west = V8 |
| 131 | }, |
| 132 | {lat_lon_alt, Datum}; |
| 133 | identify_or_index({Index, _, _, _, _, _, _, _, _}=Anonymous) -> |
| 134 | {Index, Anonymous}. |