Completed
Push — master ( 118bb3...d652ce )
by Yannick
29:38
created

SBS::cprN()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 2
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
class SBS {
3
    static $latlon = array();
4
    
5
    public function parse($buffer) {
6
	// Not yet finished, no CRC checks
7
	//echo $buffer."\n";
8
	$data = array();
9
	$typehex = substr($buffer,0,1);
10
	if ($typehex == '*' || $typehex == ':') $hex = substr($buffer,1,-1);
11
	elseif ($typehex == '@' || $typehex == '%') $hex = substr($buffer,13,-13);
12
	else $hex = substr($buffer,1,-1);
13
	$bin = gmp_strval( gmp_init($hex,16), 2);
14
	//if (strlen($hex) == 28 && $this->parityCheck($hex,$bin)) {
15
	if (strlen($hex) == 28) {
16
	    $df = intval(substr($bin,0,5),2);
17
	    //$ca = intval(substr($bin,5,3),2);
18
	    // Only support DF17 for now
19
	    //if ($df == 17 || ($df == 18 && ($ca == 0 || $ca == 1 || $ca == 6))) {
20
	    if (($df == 17 || $df == 18) && ($this->parityCheck($hex,$bin) || $typehex == '@')) {
21
		$icao = substr($hex,2,6);
22
		$data['hex'] = $icao;
23
		$tc = intval(substr($bin,32,5),2);
24
		if ($tc >= 1 && $tc <= 4) {
25
		    //callsign
26
		    $csbin = substr($bin,40,56);
27
		    $charset = str_split('#ABCDEFGHIJKLMNOPQRSTUVWXYZ#####_###############0123456789######');
28
		    $cs = '';
29
		    $cs .= $charset[intval(substr($csbin,0,6),2)];
30
		    $cs .= $charset[intval(substr($csbin,6,6),2)];
31
		    $cs .= $charset[intval(substr($csbin,12,6),2)];
32
		    $cs .= $charset[intval(substr($csbin,18,6),2)];
33
		    $cs .= $charset[intval(substr($csbin,24,6),2)];
34
		    $cs .= $charset[intval(substr($csbin,30,6),2)];
35
		    $cs .= $charset[intval(substr($csbin,36,6),2)];
36
		    $cs .= $charset[intval(substr($csbin,42,6),2)];
37
		    $cs = str_replace('_','',$cs);
38
		    $cs = str_replace('#','',$cs);
39
		    $callsign = $cs;
40
		    $data['ident'] = $callsign;
41
		} elseif ($tc >= 9 && $tc <= 18) {
42
		    // Check Q-bit
43
		    $q = substr($bin,47,1);
44
		    if ($q) {
45
			$n = intval(substr($bin,40,7).substr($bin,48,4),2);
46
			$alt = $n*25-1000;
47
			$data['altitude'] = $alt;
48
		    }
49
		    // Check odd/even flag
50
		    $oe = substr($bin,53,1);
51
		    //if ($oe) => odd else even
52
		    //  131072 is 2^17 since CPR latitude and longitude are encoded in 17 bits.
53
		    $cprlat = intval(substr($bin,54,17),2)/131072.0;
54
		    $cprlon = intval(substr($bin,71,17),2)/131072.0;
55
		    if ($oe == 0) $this::$latlon[$icao] = array('latitude' => $cprlat,'longitude' => $cprlon,'created' => time());
56
		    elseif (isset($this::$latlon[$icao]) && (time() - $this::$latlon[$icao]['created']) < 10) {
57
			$cprlat_odd = $cprlat;
58
			$cprlon_odd = $cprlon;
59
			$cprlat_even = $this::$latlon[$icao]['latitude'];
60
			$cprlon_even = $this::$latlon[$icao]['longitude'];
61
		    
62
			$j = 59*$cprlat_even-60*$cprlat_odd+0.5;
63
			$lat_even = (360.0/60)*($j%60+$cprlat_even);
64
			$lat_odd = (360.0/59)*($j%59+$cprlat_odd);
65
			if ($lat_even >= 270) $lat_even = $lat_even - 360;
66
			if ($lat_odd >= 270) $lat_odd = $lat_odd - 360;
67
			// check latitude zone
68
			if ($this->cprNL($lat_even) == $this->cprNL($lat_odd)) {
69
			    if ($this::$latlon[$icao]['created'] > time()) {
70
				$ni = $this->cprN($lat_even,0);
71
				$m = floor($cprlon_even*($this->cprNL($lat_even)-1) - $cprlon_odd * $this->cprNL($lat_even)+0.5);
72
				$lon = (360.0/$ni)*($m%$ni+$cprlon_even);
73
				$lat = $lat_even;
74
				if ($lon > 180) $lon = $lon -360;
75
				if ($lat > -91 && $lat < 91 && $lon > -181 && $lon < 181) {
76
				    //if ($globalDebug) echo 'cs : '.$cs.' - hex : '.$hex.' - lat : '.$lat.' - lon : '.$lon;
77
				    $data['latitude'] = $lat;
78
				    $data['longitude'] = $lon;
79
				}
80
			    } else {
81
				$ni = $this->cprN($lat_odd,1);
82
				$m = floor($cprlon_even*($this->cprNL($lat_odd)-1) - $cprlon_odd * $this->cprNL($lat_odd)+0.5);
83
				$lon = (360.0/$ni)*($m%$ni+$cprlon_odd);
84
				$lat = $lat_odd;
85
				if ($lon > 180) $lon = $lon -360;
86
				if ($lat > -91 && $lat < 91 && $lon > -181 && $lon < 181) {
87
				    //if ($globalDebug) echo 'icao : '.$icao.' - hex : '.$hex.' - lat : '.$lat.' - lon : '.$lon.' second'."\n";
88
				    $data['latitude'] = $lat;
89
				    $data['longitude'] = $lon;
90
				}
91
			    }
92
			} else echo "Not cprNL";
93
			unset($this::$latlon[$icao]);
94
		    }
95
		} elseif ($tc == 19) {
96
		    // speed & heading
97
		    $v_ew_dir = intval(substr($bin,45,1));
98
		    $v_ew = intval(substr($bin,46,10),2);
99
		    $v_ns_dir = intval(substr($bin,56,1));
100
		    $v_ns = intval(substr($bin,57,10),2);
101
		    if ($v_ew_dir) $v_ew = -1*$v_ew;
102
		    if ($v_ns_dir) $v_ns = -1*$v_ns;
103
		    $speed = sqrt($v_ns*$v_ns+$v_ew*$v_ew);
104
		    $heading = atan2($v_ew,$v_ns)*360.0/(2*pi());
105
		    if ($heading <0) $heading = $heading+360;
106
		    $data['speed'] = $speed;
107
		    $data['heading'] = $heading;
108
		}
109
	    }
110
	    if (isset($data)) {
111
		//print_r($data);
112
		return $data;
113
	    }
114
        }
115
    }
116
117
118
	public function cprNL($lat) {
119
	//Lookup table to convert the latitude to index.
120
	if ($lat < 0) $lat = -$lat;             // Table is simmetric about the equator.
121
	if ($lat < 10.47047130) return 59;
122
	if ($lat < 14.82817437) return 58;
123
	if ($lat < 18.18626357) return 57;
124
	if ($lat < 21.02939493) return 56;
125
	if ($lat < 23.54504487) return 55;
126
	if ($lat < 25.82924707) return 54;
127
	if ($lat < 27.93898710) return 53;
128
	if ($lat < 29.91135686) return 52;
129
	if ($lat < 31.77209708) return 51;
130
	if ($lat < 33.53993436) return 50;
131
	if ($lat < 35.22899598) return 49;
132
	if ($lat < 36.85025108) return 48;
133
	if ($lat < 38.41241892) return 47;
134
	if ($lat < 39.92256684) return 46;
135
	if ($lat < 41.38651832) return 45;
136
	if ($lat < 42.80914012) return 44;
137
	if ($lat < 44.19454951) return 43;
138
	if ($lat < 45.54626723) return 42;
139
	if ($lat < 46.86733252) return 41;
140
	if ($lat < 48.16039128) return 40;
141
	if ($lat < 49.42776439) return 39;
142
	if ($lat < 50.67150166) return 38;
143
	if ($lat < 51.89342469) return 37;
144
	if ($lat < 53.09516153) return 36;
145
	if ($lat < 54.27817472) return 35;
146
	if ($lat < 55.44378444) return 34;
147
	if ($lat < 56.59318756) return 33;
148
	if ($lat < 57.72747354) return 32;
149
	if ($lat < 58.84763776) return 31;
150
	if ($lat < 59.95459277) return 30;
151
	if ($lat < 61.04917774) return 29;
152
	if ($lat < 62.13216659) return 28;
153
	if ($lat < 63.20427479) return 27;
154
	if ($lat < 64.26616523) return 26;
155
	if ($lat < 65.31845310) return 25;
156
	if ($lat < 66.36171008) return 24;
157
	if ($lat < 67.39646774) return 23;
158
	if ($lat < 68.42322022) return 22;
159
	if ($lat < 69.44242631) return 21;
160
	if ($lat < 70.45451075) return 20;
161
	if ($lat < 71.45986473) return 19;
162
	if ($lat < 72.45884545) return 18;
163
	if ($lat < 73.45177442) return 17;
164
	if ($lat < 74.43893416) return 16;
165
	if ($lat < 75.42056257) return 15;
166
	if ($lat < 76.39684391) return 14;
167
	if ($lat < 77.36789461) return 13;
168
	if ($lat < 78.33374083) return 12;
169
	if ($lat < 79.29428225) return 11;
170
	if ($lat < 80.24923213) return 10;
171
	if ($lat < 81.19801349) return 9;
172
	if ($lat < 82.13956981) return 8;
173
	if ($lat < 83.07199445) return 7;
174
	if ($lat < 83.99173563) return 6;
175
	if ($lat < 84.89166191) return 5;
176
	if ($lat < 85.75541621) return 4;
177
	if ($lat < 86.53536998) return 3;
178
	if ($lat < 87.00000000) return 2;
179
	return 1;
180
    }
181
    
182
    public function cprN($lat,$isodd) {
183
	$nl = $this->cprNL($lat) - $isodd;
184
	if ($nl > 1) return $nl;
185
	else return 1;
186
    }
187
188
189
    function parityCheck($msg, $bin) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
190
$modes_checksum_table = array(
191
0x3935ea, 0x1c9af5, 0xf1b77e, 0x78dbbf, 0xc397db, 0x9e31e9, 0xb0e2f0, 0x587178,
192
0x2c38bc, 0x161c5e, 0x0b0e2f, 0xfa7d13, 0x82c48d, 0xbe9842, 0x5f4c21, 0xd05c14,
193
0x682e0a, 0x341705, 0xe5f186, 0x72f8c3, 0xc68665, 0x9cb936, 0x4e5c9b, 0xd8d449,
194
0x939020, 0x49c810, 0x24e408, 0x127204, 0x093902, 0x049c81, 0xfdb444, 0x7eda22,
195
0x3f6d11, 0xe04c8c, 0x702646, 0x381323, 0xe3f395, 0x8e03ce, 0x4701e7, 0xdc7af7,
196
0x91c77f, 0xb719bb, 0xa476d9, 0xadc168, 0x56e0b4, 0x2b705a, 0x15b82d, 0xf52612,
197
0x7a9309, 0xc2b380, 0x6159c0, 0x30ace0, 0x185670, 0x0c2b38, 0x06159c, 0x030ace,
198
0x018567, 0xff38b7, 0x80665f, 0xbfc92b, 0xa01e91, 0xaff54c, 0x57faa6, 0x2bfd53,
199
0xea04ad, 0x8af852, 0x457c29, 0xdd4410, 0x6ea208, 0x375104, 0x1ba882, 0x0dd441,
200
0xf91024, 0x7c8812, 0x3e4409, 0xe0d800, 0x706c00, 0x383600, 0x1c1b00, 0x0e0d80,
201
0x0706c0, 0x038360, 0x01c1b0, 0x00e0d8, 0x00706c, 0x003836, 0x001c1b, 0xfff409,
202
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
203
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
204
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000
205
);
206
207
	$crc = 0;
208
	$checksum = intval(substr($msg,22,6),16);
209
210
	for ($j = 0; $j < strlen($bin); $j++) {
211
	    if ($bin[$j]) $crc = $crc^intval($modes_checksum_table[$j],0);
212
	}
213
	if ($crc == $checksum) return true;
214
	else {
215
	    //echo "**** CRC ERROR ****\n";
216
	    return false;
217
	}
218
    }
219
    
220
    public function famaprs_to_basestation($data) {
221
	$result = array();
222
        if (isset($data['ident']) && $data['ident'] != '') {
223
	    $msg = array();
224
	    $msg['msg_type'] = 'MSG';
225
	    $msg['transmission_type'] = 1;
226
	    $msg['session_id'] = 5;
227
	    $msg['aircraftid'] = hexdec($data['address']);
228
	    $msg['hex'] = $data['address'];
229
	    $msg['flightid'] = hexdec($data['address']);
230
	    $msg['date_gen'] = date('Y/m/d',$data['timestamp']);
231
	    $msg['time_gen'] = date('H:i:s',$data['timestamp']).'.180';
232
	    $msg['date_log'] = date('Y/m/d',$data['timestamp']);
233
	    $msg['time_log'] = date('H:i:s',$data['timestamp']).'.180';
234
	    $msg['callsign'] = $data['ident'];
235
	    $msg['altitude'] = '';
236
	    $msg['speed'] = '';
237
	    $msg['track'] = '';
238
	    $msg['latitude'] = '';
239
	    $msg['longitude'] = '';
240
	    $msg['verticalrate'] = '';
241
	    $msg['squawk'] = '';
242
	    $msg['alert'] = '';
243
	    $msg['emergency'] = '';
244
	    $msg['SPI'] = '';
245
	    $msg['ground'] = '';
246
    	    $result[] = implode(',',$msg);
247
    	}
248
    	if (isset($data['latitude']) && $data['latitude'] != 0) {
249
	    $msg = array();
250
	    $msg['msg_type'] = 'MSG';
251
	    $msg['transmission_type'] = 2;
252
	    $msg['session_id'] = 5;
253
	    $msg['aircraftid'] = hexdec($data['address']);
254
	    $msg['hex'] = $data['address'];
255
	    $msg['flightid'] = hexdec($data['address']);
256
	    $msg['date_gen'] = date('Y/m/d',$data['timestamp']);
257
	    $msg['time_gen'] = date('H:i:s',$data['timestamp']).'.180';
258
	    $msg['date_log'] = date('Y/m/d',$data['timestamp']);
259
	    $msg['time_log'] = date('H:i:s',$data['timestamp']).'.180';
260
	    $msg['callsign'] = '';
261
	    if (isset($data['altitude'])) $msg['altitude'] = $data['altitude'];
262
	    else $msg['altitude'] = '';
263
	    $msg['speed'] = $data['speed'];
264
	    if (isset($data['heading'])) $msg['track'] = $data['heading'];
265
	    else $msg['track'] = '';
266
	    $msg['latitude'] = $data['latitude'];
267
	    $msg['longitude'] = $data['longitude'];
268
	    if (isset($data['verticalrate'])) $msg['verticalrate'] = $data['verticalrate'];
269
	    else $msg['verticalrate'] = '';
270
	    if (isset($data['squawk'])) $msg['squawk'] = $data['squawk'];
271
	    else $msg['squawk'] = 0;
272
	    $msg['alert'] = 0;
273
	    $msg['emergency'] = 0;
274
	    $msg['SPI'] = 0;
275
	    if (isset($data['ground'])) $msg['ground'] = 1;
276
	    else $msg['ground'] = 0;
277
    	    $result[] = implode(',',$msg);
278
        }
279
        return $result;
280
    }
281
}
282
?>
283