Completed
Push — master ( dab432...128a26 )
by Yannick
35:16 queued 01:17
created

AIS::make_lonf()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 10
nc 2
nop 1
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/*
3
Copyright 2014 Aaron Gong Hsien-Joen <[email protected]>
4
5
Licensed under the Apache License, Version 2.0 (the "License");
6
you may not use this file except in compliance with the License.
7
You may obtain a copy of the License at
8
9
    http://www.apache.org/licenses/LICENSE-2.0
10
11
Unless required by applicable law or agreed to in writing, software
12
distributed under the License is distributed on an "AS IS" BASIS,
13
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
See the License for the specific language governing permissions and
15
limitations under the License.
16
*/
17
/*
18
Modified in 2017 by Ycarus <[email protected]>
19
Original version come from https://github.com/ais-one/phpais
20
*/
21
class AIS {
22
	protected $shiptype = array(0 => 'Not available (default)',
23
			20 => 'Wing in ground (WIG), all ships of this type',
24
			21 => 'Wing in ground (WIG), Hazardous category A',
25
			22 => 'Wing in ground (WIG), Hazardous category B',
26
			23 => 'Wing in ground (WIG), Hazardous category C',
27
			24 => 'Wing in ground (WIG), Hazardous category D',
28
			25 => 'Wing in ground (WIG), Reserved for future use',
29
			26 => 'Wing in ground (WIG), Reserved for future use',
30
			27 => 'Wing in ground (WIG), Reserved for future use',
31
			28 => 'Wing in ground (WIG), Reserved for future use',
32
			29 => 'Wing in ground (WIG), Reserved for future use',
33
			30 => 'Fishing',
34
			31 => 'Towing',
35
			32 => 'Towing: length exceeds 200m or breadth exceeds 25m',
36
			33 => 'Dredging or underwater ops',
37
			34 => 'Diving ops',
38
			35 => 'Military ops',
39
			36 => 'Sailing',
40
			37 => 'Pleasure Craft',
41
			38 => 'Reserved',
42
			39 => 'Reserved',
43
			40 => 'High speed craft (HSC), all ships of this type',
44
			41 => 'High speed craft (HSC), Hazardous category A',
45
			42 => 'High speed craft (HSC), Hazardous category B',
46
			43 => 'High speed craft (HSC), Hazardous category C',
47
			44 => 'High speed craft (HSC), Hazardous category D',
48
			45 => 'High speed craft (HSC), Reserved for future use',
49
			46 => 'High speed craft (HSC), Reserved for future use',
50
			47 => 'High speed craft (HSC), Reserved for future use',
51
			48 => 'High speed craft (HSC), Reserved for future use',
52
			49 => 'High speed craft (HSC), No additional information',
53
			50 => 'Pilot Vessel',
54
			51 => 'Search and Rescue vessel',
55
			52 => 'Tug',
56
			53 => 'Port Tender',
57
			54 => 'Anti-pollution equipment',
58
			55 => 'Law Enforcement',
59
			56 => 'Spare - Local Vessel',
60
			57 => 'Spare - Local Vessel',
61
			58 => 'Medical Transport',
62
			59 => 'Noncombatant ship according to RR Resolution No. 18',
63
			60 => 'Passenger, all ships of this type',
64
			61 => 'Passenger, Hazardous category A',
65
			62 => 'Passenger, Hazardous category B',
66
			63 => 'Passenger, Hazardous category C',
67
			64 => 'Passenger, Hazardous category D',
68
			65 => 'Passenger, Reserved for future use',
69
			66 => 'Passenger, Reserved for future use',
70
			67 => 'Passenger, Reserved for future use',
71
			68 => 'Passenger, Reserved for future use',
72
			69 => 'Passenger, No additional information',
73
			70 => 'Cargo, all ships of this type',
74
			71 => 'Cargo, Hazardous category A',
75
			72 => 'Cargo, Hazardous category B',
76
			73 => 'Cargo, Hazardous category C',
77
			74 => 'Cargo, Hazardous category D',
78
			75 => 'Cargo, Reserved for future use',
79
			76 => 'Cargo, Reserved for future use',
80
			77 => 'Cargo, Reserved for future use',
81
			78 => 'Cargo, Reserved for future use',
82
			79 => 'Cargo, No additional information',
83
			80 => 'Tanker, all ships of this type',
84
			81 => 'Tanker, Hazardous category A',
85
			82 => 'Tanker, Hazardous category B',
86
			83 => 'Tanker, Hazardous category C',
87
			84 => 'Tanker, Hazardous category D',
88
			85 => 'Tanker, Reserved for future use',
89
			86 => 'Tanker, Reserved for future use',
90
			87 => 'Tanker, Reserved for future use',
91
			88 => 'Tanker, Reserved for future use',
92
			89 => 'Tanker, No additional information',
93
			90 => 'Other Type, all ships of this type',
94
			91 => 'Other Type, Hazardous category A',
95
			92 => 'Other Type, Hazardous category B',
96
			93 => 'Other Type, Hazardous category C',
97
			94 => 'Other Type, Hazardous category D',
98
			95 => 'Other Type, Reserved for future use',
99
			96 => 'Other Type, Reserved for future use',
100
			97 => 'Other Type, Reserved for future use',
101
			98 => 'Other Type, Reserved for future use',
102
			99 => 'Other Type, no additional information');
103
104
105
106
107
108
109
110
/* AIS Decoding
111
- Receive and get ITU payload
112
- Organises the binary bits of the Payload into 6-bit strings,
113
- Converts the 6-bit strings into their representative "valid characters" – see IEC 61162-1, table 7,
114
- Assembles the valid characters into an encapsulation string, and
115
- Transfers the encapsulation string using the VDM sentence formatter.
116
*/
117
118
	private function make_latf($temp) { // unsigned long 
119
		$flat = 0.0; // float
0 ignored issues
show
Unused Code introduced by
$flat is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
120
		$temp = $temp & 0x07FFFFFF;
121
		if ($temp & 0x04000000) {
122
			$temp = $temp ^ 0x07FFFFFF;
123
			$temp += 1;
124
			$flat = (float)($temp / (60.0 * 10000.0));
125
			$flat *= -1.0;
126
		} else $flat = (float)($temp / (60.0 * 10000.0));
127
		return $flat; // float
128
	}
129
130
	private function make_lonf($temp) { // unsigned long
131
		$flon = 0.0; // float
0 ignored issues
show
Unused Code introduced by
$flon is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
132
		$temp = $temp & 0x0FFFFFFF;
133
		if ($temp & 0x08000000) {
134
			$temp = $temp ^ 0x0FFFFFFF;
135
			$temp += 1;
136
			$flon = (float)($temp / (60.0 * 10000.0));
137
			$flon *= -1.0;
138
		} else $flon = (float)($temp / (60.0 * 10000.0));
139
		return $flon;
140
	}
141
142
	private function ascii_2_dec($chr) {
143
		$dec=ord($chr);//get decimal ascii code
144
		$hex=dechex($dec);//convert decimal to hex
0 ignored issues
show
Unused Code introduced by
$hex is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
145
		return ($dec);
146
	}
147
	
148
    /*
149
    $ais_map64 = array(
150
       '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', // 48
151
       ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C',
152
       'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
153
       'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', // 87
154
       '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', // 96
155
       'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
156
       't', 'u', 'v', 'w' // 119
157
    ); // char 64
158
    */
159
	private function asciidec_2_8bit($ascii) {
160
		//only process in the following range: 48-87, 96-119
161
		if ($ascii < 48) { }
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
162
		else {
163
			if($ascii>119) { }
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
164
			else {
165
				if ($ascii>87 && $ascii<96) ;
166
				else {
167
					$ascii=$ascii+40;
168
					if ($ascii>128){
169
						$ascii=$ascii+32;
170
					} else {
171
						$ascii=$ascii+40;
172
					}
173
				}
174
			}
175
		}
176
		return ($ascii);
177
	}
178
179
	private function dec_2_6bit($dec) {
180
		$bin=decbin($dec);
181
		return(substr($bin, -6)); 
182
	}
183
184
	private function binchar($_str, $_start, $_size) {
185
		//  ' ' --- '?', // 0x20 - 0x3F
186
		//  '@' --- '_', // 0x40 - 0x5F
187
		$ais_chars = array(
188
		    '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
189
		    'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
190
		    'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']',
191
		    '^', '_', ' ', '!', '\"', '#', '$', '%', '&', '\'',
192
		    '(', ')', '*', '+', ',', '-', '.', '/', '0', '1',
193
		    '2', '3', '4', '5', '6', '7', '8', '9', ':', ';',
194
		    '<', '=', '>', '?'
195
		);
196
		// "
197
		$rv = '';
198
		if ($_size % 6 == 0) {
199
			$len = $_size / 6;
200
			for ($i=0; $i<$len; $i++) {
201
				$offset = $i * 6;
202
				$rv .= $ais_chars[ bindec(substr($_str,$_start + $offset,6)) ];
203
			}
204
		}
205
		return $rv;
206
	}
207
208
	// function for decoding the AIS Message ITU Payload
209
	private function decode_ais($_aisdata) {
210
		$ro = new stdClass(); // return object
211
		$ro->cls = 0; // AIS class undefined, also indicate unparsed msg
212
		$ro->name = '';
213
		$ro->status = '';
214
		$ro->callsign = '';
215
		$ro->imo = '';
216
		$ro->typeid = '';
217
		$ro->type = '';
218
		$ro->sog = -1.0;
219
		$ro->cog = 0.0;
220
		$ro->lon = 0.0;
221
		$ro->lat = 0.0;
222
		$ro->heading = '';
223
		$ro->destination = '';
224
		$ro->eta_month = '';
225
		$ro->eta_day = '';
226
		$ro->eta_hour = '';
227
		$ro->eta_minute = '';
228
		$ro->ts = time();
229
		$ro->id = bindec(substr($_aisdata,0,6));
230
		$ro->mmsi = bindec(substr($_aisdata,8,30));
231
		if ($ro->id >= 1 && $ro->id <= 3) {
232
			$ro->cog = bindec(substr($_aisdata,116,12))/10;
233
			$ro->sog = bindec(substr($_aisdata,50,10))/10;
234
			$ro->lon = $this->make_lonf(bindec(substr($_aisdata,61,28)));
235
			$ro->lat = $this->make_latf(bindec(substr($_aisdata,89,27)));
236
			$ro->cls = 1; // class A
237
		} else if ($ro->id == 4) {
238
			$ro->lon = $this->make_lonf(bindec(substr($_aisdata,79,28)));
239
			$ro->lat = $this->make_latf(bindec(substr($_aisdata,107,27)));
240
			$ro->cls = 1; // class A
241
		} else if ($ro->id == 5) {
242
			$ro->imo = bindec(substr($_aisdata,40,30));
243
			$ro->callsign = $this->binchar($_aisdata,70,42);
244
			$ro->name = $this->binchar($_aisdata,112,120);
245
			$ro->typeid = bindec(substr($_aisdata,232,8));
246
			$ro->type = $this->getShipType($ro->typeid);
247
			//$ro->to_bow = bindec(substr($_aisdata,240,9));
248
			//$ro->to_stern = bindec(substr($_aisdata,249,9));
249
			//$ro->to_port = bindec(substr($_aisdata,258,6));
250
			//$ro->to_starboard = bindec(substr($_aisdata,264,6));
251
			$ro->eta_month = bindec(substr($_aisdata,274,4));
252
			$ro->eta_day = bindec(substr($_aisdata,278,5));
253
			$ro->eta_hour = bindec(substr($_aisdata,283,5));
254
			$ro->eta_minute = bindec(substr($_aisdata,288,6));
255
			//$ro->draught = bindec(substr($_aisdata,294,8));
256
			$ro->destination = $this->binchar($_aisdata,302,120);
257
			$ro->cls = 1; // class A
258
		} else if ($ro->id == 9) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
259
			// Search and Rescue aircraft position report
260
		} else if ($ro->id == 18) {
261
			$ro->cog = bindec(substr($_aisdata,112,12))/10;
262
			$ro->sog = bindec(substr($_aisdata,46,10))/10;
263
			$ro->lon = $this->make_lonf(bindec(substr($_aisdata,57,28)));
264
			$ro->lat = $this->make_latf(bindec(substr($_aisdata,85,27)));
265
			$ro->heading = bindec(substr($_aisdata,124,9));
266
			if ($ro->heading == 511) $ro->heading = '';
267
			$ro->cls = 2; // class B
268
		} else if ($ro->id == 19) {
269
			$ro->cog = bindec(substr($_aisdata,112,12))/10;
270
			$ro->sog = bindec(substr($_aisdata,46,10))/10;
271
			$ro->lon = $this->make_lonf(bindec(substr($_aisdata,61,28)));
272
			$ro->lat = $this->make_latf(bindec(substr($_aisdata,89,27)));
273
			$ro->name = $this->binchar($_aisdata,143,120);
274
			$ro->cls = 2; // class B
275
			$ro->heading = bindec(substr($_aisdata,124,9));
276
			if ($ro->heading == 511) $ro->heading = '';
277
			$ro->typeid = bindec(substr($_aisdata,263,8));
278
			$ro->type = $this->getShipType($ro->typeid);
279
			//$ro->to_bow = bindec(substr($_aisdata,271,9));
280
			//$ro->to_stern = bindec(substr($_aisdata,280,9));
281
			//$ro->to_port = bindec(substr($_aisdata,289,6));
282
			//$ro->to_starboard = bindec(substr($_aisdata,295,6));
283
		} else if ($ro->id == 21) {
284
			$ro->lon = $this->make_lonf(bindec(substr($_aisdata,164,28)));
285
			$ro->lat = $this->make_latf(bindec(substr($_aisdata,192,27)));
286
			$ro->name = $this->binchar($_aisdata,43,120);
287
			//$ro->to_bow = bindec(substr($_aisdata,219,9));
288
			//$ro->to_stern = bindec(substr($_aisdata,228,9));
289
			//$ro->to_port = bindec(substr($_aisdata,237,6));
290
			//$ro->to_starboard = bindec(substr($_aisdata,243,6));
291
			$ro->cls = 2; // class B
292
		} else if ($ro->id == 24) {
293
			$pn = bindec(substr($_aisdata,38,2));
294
			if ($pn == 0) {
295
				$ro->name = $this->binchar($_aisdata,40,120);
296
			}
297
			$ro->typeid = bindec(substr($_aisdata,40,8));
298
			$ro->type = $this->getShipType($ro->typeid);
299
			$ro->callsign = $this->binchar($_aisdata,90,42);
300
			//$ro->to_bow = bindec(substr($_aisdata,132,9));
301
			//$ro->to_stern = bindec(substr($_aisdata,141,9));
302
			//$ro->to_port = bindec(substr($_aisdata,150,6));
303
			//$ro->to_starboard = bindec(substr($_aisdata,156,6));
304
			$ro->cls = 2; // class B
305
		} else if ($ro->id == 27) {
306
			$ro->cog = bindec(substr($_aisdata,85,9));
307
			if ($ro->cog == 511) $ro->cog = 0.0;
308
			$ro->sog = bindec(substr($_aisdata,79,6));
309
			if ($ro->sog == 63) $ro->sog = 0.0;
310
			$ro->lon = $this->make_lonf(bindec(substr($_aisdata,44,18))*10);
311
			$ro->lat = $this->make_latf(bindec(substr($_aisdata,62,17))*10);
312
			$ro->cls = 1; // class A
313
		
314
		}
315
		$ro->statusid = bindec(substr($_aisdata,38,4));
316
		$ro->status = $this->getStatus($ro->statusid);
317
		return $ro;
318
	}
319
320
	public function getStatus($statusid) {
321
		if ($statusid == 0) {
322
			return 'under way using engine';
323
		} elseif ($statusid == 1) {
324
			return 'at anchor';
325
		} elseif ($statusid == 2) {
326
			return 'not under command';
327
		} elseif ($statusid == 3) {
328
			return 'restricted maneuverability';
329
		} elseif ($statusid == 4) {
330
			return 'constrained by her draught';
331
		} elseif ($statusid == 5) {
332
			return 'moored';
333
		} elseif ($statusid == 6) {
334
			return 'aground';
335
		} elseif ($statusid == 7) {
336
			return 'engaged in fishing';
337
		} elseif ($statusid == 8) {
338
			return 'under way sailing';
339
		} elseif ($statusid == 9) {
340
			return 'reserved for future amendment of navigational status for ships carrying DG, HS, or MP, or IMO hazard or pollutant category C, high speed craft (HSC)';
341
		} elseif ($statusid == 10) {
342
			return 'reserved for future amendment of navigational status for ships carrying dangerous goods (DG), harmful substances (HS) or marine pollutants (MP), or IMO hazard or pollutant category A, wing in ground (WIG)';
343
		} elseif ($statusid == 11) {
344
			return 'power-driven vessel towing astern (regional use)';
345
		} elseif ($statusid == 12) {
346
			return 'power-driven vessel pushing ahead or towing alongside (regional use)';
347
		} elseif ($statusid == 13) {
348
			return 'reserved for future use';
349
		} elseif ($statusid == 14) {
350
			return 'AIS-SART (active), MOB-AIS, EPIRB-AIS';
351
		} elseif ($statusid == 15) {
352
			return 'undefined = default (also used by AIS-SART, MOB-AIS and EPIRB-AIS under test)';
353
		}
354
	}
355
	
356
	public function getShipType($code) {
357
		if (isset($this->shiptype[$code])) return $this->shiptype[$code];
358
		else return '';
359
	}
360
361
	public function getShipTypeID($type) {
362
		$typeid = array_search($type,$this->shiptype);
363
		if ($typeid !== FALSE) return $typeid;
364
		else return '';
365
	}
366
367
	public function process_ais_itu($_itu, $_len, $_filler, $aux /*, $ais_ch*/) {
0 ignored issues
show
Unused Code introduced by
The parameter $_len is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $_filler is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $aux is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
368
		global $port; // tcpip port...
369
		static $debug_counter = 0;
370
		$aisdata168='';//six bit array of ascii characters
371
		$ais_nmea_array = str_split($_itu); // convert to an array
372
		foreach ($ais_nmea_array as $value) {
373
			$dec = $this->ascii_2_dec($value);
374
			$bit8 = $this->asciidec_2_8bit($dec);
375
			$bit6 = $this->dec_2_6bit($bit8);
376
			//echo $value ."-" .$bit6 ."";
377
			$aisdata168 .=$bit6;
378
		}
379
		//echo $aisdata168 . "<br/>";
380
		//return $this->decode_ais($aisdata168, $aux);
381
		return $this->decode_ais($aisdata168);
382
	}
383
384
	// char* - AIS \r terminated string
385
	// TCP based streams which send messages in full can use this instead of calling process_ais_buf
386
	public function process_ais_raw($rawdata, $aux = '') { // return int
387
		static $num_seq; // 1 to 9
388
		static $seq; // 1 to 9
389
		static $pseq; // previous seq
390
		static $msg_sid = -1; // 0 to 9, indicate -1 at start state of device, do not process messages
391
		static $cmsg_sid; // current msg_sid
392
		static $itu; // buffer for ITU message
393
		//echo $rawdata."\n";
394
		$filler = 0; // fill bits (int)
395
		$chksum = 0;
396
		// raw data without the \n
397
		// calculate checksum after ! till *
398
		// assume 1st ! is valid
399
		// find * ensure that it is at correct position
400
		$end = strrpos ( $rawdata , '*' );
401
		if ($end === FALSE) return -1; // check for NULLS!!!
402
		$cs = substr( $rawdata, $end + 1 );
403
		if ( strlen($cs) != 2 ) return -1; // correct cs length
404
		$dcs = (int)hexdec( $cs );
405
		for ( $alias=1; $alias<$end; $alias++) $chksum ^= ord( $rawdata[$alias] ); // perform XOR for NMEA checksum
406
		if ( $chksum == $dcs ) { // NMEA checksum pass
407
			$pcs = explode(',', $rawdata);
408
			// !AI??? identifier
409
			if (!isset($pcs[1])) {
410
				echo "ERROR,INVALID_DATA ".time()." $rawdata\n";
411
				return -1;
412
			}
413
			$num_seq = (int)$pcs[1]; // number of sequences
414
			$seq = (int)$pcs[2]; // get sequence
415
			// get msg sequence id
416
			if ($pcs[3] == '') $msg_sid = -1; // non-multipart message, set to -1
417
			else $msg_sid = (int)$pcs[3]; // multipart message
418
			$ais_ch = $pcs[4]; // get AIS channel
0 ignored issues
show
Unused Code introduced by
$ais_ch is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
419
			// message sequence checking
420
			if ($num_seq < 1 || $num_seq > 9) {
421
				echo "ERROR,INVALID_NUMBER_OF_SEQUENCES ".time()." $rawdata\n";
422
				return -1;
423
			} else if ($seq < 1 || $seq > 9) { // invalid sequences number
424
				echo "ERROR,INVALID_SEQUENCES_NUMBER ".time()." $rawdata\n";
425
				return -1;
426
			} else if ($seq > $num_seq) {
427
				echo "ERROR,INVALID_SEQUENCE_NUMBER_OR_INVALID_NUMBER_OF_SEQUENCES ".time()." $rawdata\n";
428
				return -1;
429
			} else { // sequencing ok, handle single/multi-part messaging
430
				if ($seq == 1) { // always init to 0 at first sequence
431
					$filler = 0; // ?
432
					$itu = ""; // init message length
433
					$pseq = 0; // note previous sequence number
434
					$cmsg_sid = $msg_sid; // note msg_sid
435
				}
436
				if ($num_seq > 1) { // for multipart messages
437
					if ($cmsg_sid != $msg_sid // different msg_sid
438
					    || $msg_sid == -1 // invalid initial msg_sid
439
					    || ($seq - $pseq) != 1 // not insequence
440
					) {  // invalid for multipart message
441
						$msg_sid = -1;
442
						$cmsg_sid = -1;
443
						echo "ERROR,INVALID_MULTIPART_MESSAGE ".time()." $rawdata\n";
444
						return -1;
445
					} else {
446
						$pseq++;
447
					}
448
				}
449
				$itu = $itu.$pcs[5]; // get itu message
450
				$filler += (int)$pcs[6][0]; // get filler
451
				if ($num_seq == 1 // valid single message
452
				    || $num_seq == $pseq // valid multi-part message
453
				) {
454
					/*
455
					if ($num_seq != 1) { // test
456
						echo $rawdata;
457
					}
458
					*/
459
					return $this->process_ais_itu($itu, strlen($itu), $filler, $aux /*, $ais_ch*/);
460
				}
461
			} // end process raw AIS string (checksum passed)
462
		}
463
		return -1;
464
	}
465
466
	// incoming data from serial or IP comms
467
	public function process_ais_buf($ibuf) {
468
		static $cbuf = "";
469
		$cbuf = $cbuf.$ibuf;
470
		$last_pos = 0;
471
		$result = new stdClass();
472
		while ( ($start = strpos($cbuf,"VDM",$last_pos)) !== FALSE) {
473
		//while ( ($start = strpos($cbuf,"!AI",$last_pos)) !== FALSE) {
474
			//DEBUG echo $cbuf;
475
			if ( ($end = strpos($cbuf,"\r\n", $start)) !== FALSE) { //TBD need to trim?
476
				$tst = substr($cbuf, $start - 3, ($end - $start + 3));
477
				//DEBUG echo "[$start $end $tst]\n";
478
				$result = $this->process_ais_raw( $tst, "" );
479
				$last_pos = $end + 1;
480
			} else break;
481
		}
482
		if ($last_pos > 0) $cbuf = substr($cbuf, $last_pos); // move...
483
		if (strlen($cbuf) > 1024) $cbuf = ""; // prevent overflow simple mode...
484
		return $result;
485
	}
486
487
	// incoming data from serial or IP comms
488
	public function process_ais_line($cbuf) {
489
		$result = new stdClass();
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
490
		$start = strpos($cbuf,"VDM");
491
		$tst = substr($cbuf, $start - 3);
492
		$result = $this->process_ais_raw( $tst, "" );
493
		return $result;
494
	}
495
496
	/* AIS Encoding
497
	*/
498
	private function mk_ais_lat( $lat ) {
499
		//$lat = 1.2569;
500
		if ($lat<0.0) {
501
			$lat = -$lat;
502
			$neg=true;
503
		} else $neg=false;
504
		$latd = 0x00000000;
0 ignored issues
show
Unused Code introduced by
$latd is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
505
		$latd = intval ($lat * 600000.0);
506
		if ($neg==true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
507
			$latd = ~$latd;
508
			$latd+=1;
509
			$latd &= 0x07FFFFFF;
510
		}
511
		return $latd;
512
	}
513
514
	private function mk_ais_lon( $lon ) {
515
		//$lon = 103.851;
516
		if ($lon<0.0) {
517
			$lon = -$lon;
518
			$neg=true;
519
		} else $neg=false;
520
		$lond = 0x00000000;
0 ignored issues
show
Unused Code introduced by
$lond is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
521
		$lond = intval ($lon * 600000.0);
522
		if ($neg==true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
523
			$lond = ~$lond;
524
			$lond+=1;
525
			$lond &= 0x0FFFFFFF;
526
		}
527
		return $lond;
528
	}
529
530
	private function char2bin($name, $max_len) {
531
		$len = strlen($name);
532
		if ($len > $max_len) $name = substr($name,0,$max_len);
533
		if ($len < $max_len) $pad = str_repeat('0', ($max_len - $len) * 6);
534
		else $pad = '';
535
		$rv = '';
536
		$ais_chars = array(
537
		    '@'=>0, 'A'=>1, 'B'=>2, 'C'=>3, 'D'=>4, 'E'=>5, 'F'=>6, 'G'=>7, 'H'=>8, 'I'=>9,
538
		    'J'=>10, 'K'=>11, 'L'=>12, 'M'=>13, 'N'=>14, 'O'=>15, 'P'=>16, 'Q'=>17, 'R'=>18, 'S'=>19,
539
		    'T'=>20, 'U'=>21, 'V'=>22, 'W'=>23, 'X'=>24, 'Y'=>25, 'Z'=>26, '['=>27, '\\'=>28, ']'=>29,
540
		    '^'=>30, '_'=>31, ' '=>32, '!'=>33, '\"'=>34, '#'=>35, '$'=>36, '%'=>37, '&'=>38, '\''=>39,
541
		    '('=>40, ')'=>41, '*'=>42, '+'=>43, ','=>44, '-'=>45, '.'=>46, '/'=>47, '0'=>48, '1'=>49,
542
		    '2'=>50, '3'=>51, '4'=>52, '5'=>53, '6'=>54, '7'=>55, '8'=>56, '9'=>57, ':'=>58, ';'=>59,
543
		    '<'=>60, '='=>61, '>'=>62, '?'=>63
544
		);
545
		// "
546
		$_a = str_split($name);
547
		if ($_a) foreach ($_a as $_1) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $_a of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
548
			if (isset($ais_chars[$_1])) $dec = $ais_chars[$_1];
549
			else $dec = 0;
550
			$bin = str_pad(decbin( $dec ), 6, '0', STR_PAD_LEFT);
551
			$rv .= $bin;
552
			//echo "$_1 $dec ($bin)<br/>";
553
		}
554
		return $rv.$pad;
555
	}
556
557
	private function mk_ais($_enc, $_part=1,$_total=1,$_seq='',$_ch='A') {
558
		$len_bit = strlen($_enc);
559
		$rem6 = $len_bit % 6;
560
		$pad6_len = 0;
561
		if ($rem6) $pad6_len = 6 - $rem6;
562
		//echo  $pad6_len.'<br>';
563
		$_enc .= str_repeat("0", $pad6_len); // pad the text...
564
		$len_enc = strlen($_enc) / 6;
565
		//echo $_enc.' '.$len_enc.'<br/>';
566
		$itu = '';
567
		for ($i=0; $i<$len_enc; $i++) {
568
			$offset = $i * 6;
569
			$dec = bindec(substr($_enc,$offset,6));
570
			if ($dec < 40) $dec += 48;
571
			else $dec += 56;
572
			//echo chr($dec)." $dec<br/>";
573
			$itu .= chr($dec);
574
		}
575
		// add checksum
576
		$chksum = 0;
577
		$itu = "AIVDM,$_part,$_total,$_seq,$_ch,".$itu.",0";
578
		$len_itu = strlen($itu);
579
		for ($i=0; $i<$len_itu; $i++) {
580
			$chksum ^= ord( $itu[$i] );
581
		}
582
		$hex_arr = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
583
		$lsb = $chksum & 0x0F;
584
		if ($lsb >=0 && $lsb <= 15 ) $lsbc = $hex_arr[$lsb];
585
		else $lsbc = '0';
586
		$msb = (($chksum & 0xF0) >> 4) & 0x0F;
587
		if ($msb >=0 && $msb <= 15 ) $msbc = $hex_arr[$msb];
588
		else $msbc = '0';
589
		$itu = '!'.$itu."*{$msbc}{$lsbc}\r\n";
590
		return $itu;
591
	}
592
593
	public function parse($buffer) {
594
		$data = $this->process_ais_buf($buffer);
595
		if (!is_object($data)) return array();
596
		if ($data->lon != 0) $result['longitude'] = $data->lon;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$result was never initialized. Although not strictly required by PHP, it is generally a good practice to add $result = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
597
		if ($data->lat != 0) $result['latitude'] = $data->lat;
0 ignored issues
show
Bug introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
598
		$result['ident'] = trim($data->name);
599
		$result['timestamp'] = $data->ts;
600
		$result['mmsi'] = $data->mmsi;
601
		if ($data->sog != -1.0) $result['speed'] = $data->sog;
602
		if ($data->cog != 0) $result['heading'] = $data->cog;
603
		/*
604
		    $ro->cls = 0; // AIS class undefined, also indicate unparsed msg
605
		    $ro->id = bindec(substr($_aisdata,0,6));
606
		*/
607
		return $result;
608
	}
609
610
	public function mmsitype($mmsi) {
611
		if (strlen($mmsi) == 9) {
612
			if (substr($mmsi,0,3) == '974') return 'EPIRB (Emergency Position Indicating Radio Beacon) AIS';
613
			elseif (substr($mmsi,0,3) == '972') return 'MOB (Man Overboard) device';
614
			elseif (substr($mmsi,0,3) == '970') return 'AIS SART (Search and Rescue Transmitter)';
615
			elseif (substr($mmsi,0,3) == '111') return 'SAR (Search and Rescue) aircraft';
616
			elseif (substr($mmsi,0,2) == '98') return 'Auxiliary craft associated with a parent ship';
617
			elseif (substr($mmsi,0,2) == '99') return 'Aids to Navigation';
618
			elseif (substr($mmsi,0,2) == '00') return 'Coastal stations';
619
			elseif (substr($mmsi,0,1) == '0') return 'Group of ships';
620
			else return 'Ship';
621
		}
622
623
	
624
	}
625
626
	public function parse_line($buffer) {
627
		global $globalDebug;
628
		$result = array();
629
		$data = new stdClass();
0 ignored issues
show
Unused Code introduced by
$data is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
630
		$start = strpos($buffer,"VDM");
631
		$tst = substr($buffer, $start - 3);
632
		$data = $this->process_ais_raw( $tst, "" );
633
		if (!is_object($data)) {
634
			//if ($globalDebug) echo '==== Line format not supported : '.$buffer."\n";
635
			return array();
636
		}
637
		if ($data->lon != 0) $result['longitude'] = $data->lon;
638
		if ($data->lat != 0) $result['latitude'] = $data->lat;
639
		$result['ident'] = trim(str_replace('@','',$data->name));
640
		$result['timestamp'] = $data->ts;
641
		$result['mmsi'] = $data->mmsi;
642
		if (strlen($result['mmsi']) == 8 && substr($result['mmsi'],0,3) == '669') $result['mmsi'] = '3'.$result['mmsi'];
643
		$result['mmsi_type'] = $this->mmsitype($result['mmsi']);
644
		if ($data->sog != -1.0) $result['speed'] = $data->sog;
645
		if ($data->heading !== '') $result['heading'] = $data->heading;
646
		elseif ($data->cog != 0) $result['heading'] = $data->cog;
647
		if ($data->status != '') $result['status'] = $data->status;
648
		if ($data->statusid !== '') $result['statusid'] = $data->statusid;
649
		if ($data->type !== '') $result['type'] = $data->type;
650
		if ($data->typeid !== '') $result['typeid'] = $data->typeid;
651
		if ($data->imo !== '') $result['imo'] = $data->imo;
652
		if ($data->callsign !== '') $result['callsign'] = trim(str_replace('@','',$data->callsign));
653
		if (is_numeric($data->eta_month) && $data->eta_month != 0 && is_numeric($data->eta_day) && $data->eta_day != 0 && $data->eta_hour !== '' && $data->eta_minute !== '') {
654
			$eta_ts = strtotime(date('Y').'-'.sprintf("%02d",$data->eta_month).'-'.sprintf("%02d",$data->eta_day).' '.sprintf("%02d",$data->eta_hour).':'.sprintf("%02d",$data->eta_minute).':00');
655
			if ($eta_ts != '') $result['eta_ts'] = $eta_ts;
656
		} elseif (is_numeric($data->eta_hour) && is_numeric($data->eta_minute)) {
657
			$eta_ts = strtotime(date('Y-m-d').' '.sprintf("%02d",$data->eta_hour).':'.sprintf("%02d",$data->eta_minute).':00');
658
			if ($eta_ts != '') $result['eta_ts'] = $eta_ts;
659
		}
660
		if ($data->destination != '') {
661
			$dest = trim(str_replace('@','',$data->destination));
662
			if ($dest != '') $result['destination'] = $dest;
663
		}
664
		$result['all'] = (array) $data;
665
		/*
666
		    $ro->cls = 0; // AIS class undefined, also indicate unparsed msg
667
		    $ro->id = bindec(substr($_aisdata,0,6));
668
		*/
669
		return $result;
670
	}
671
	
672
	public function famaprs_to_ais($data) {
0 ignored issues
show
Unused Code introduced by
The parameter $data is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
673
		/*
674
		// In dev. Not yet finished.
675
		$result = array();
676
		$result['id'] = str_pad(decbin($data['id']),6,'0',STR_PAD_LEFT);
677
		$result['noidea'] = str_pad(decbin(0), 2, '0', STR_PAD_LEFT);
678
		$result['mmsi'] = str_pad(decbin($data['mmsi']),30,'0',STR_PAD_LEFT);
679
		//$result['noidea2'] = str_pad(decbin(0), 2, '0', STR_PAD_LEFT);
680
		$result['statusid'] = str_pad(decbin($data['status_id']),4,'0',STR_PAD_LEFT);
681
		//$result['statusid'] = str_pad(decbin($data['status_id']),2,'0',STR_PAD_LEFT);
682
		
683
		//$result['callsign'] = $this->char2bin($data['callsign'],20);
684
		if ($id >= 1 && $id <= 3) {
685
			$result['noidea2'] = str_pad(decbin(0), 8, '0', STR_PAD_LEFT);
686
			$result['sog'] = str_pad(decbin($data['speed']*10),10,'0',STR_PAD_LEFT);
687
			$result['longitude'] = str_pad(decbin($this->mk_ais_lon($data['longitude'])),28,'0',STR_PAD_LEFT);
688
			$result['latitude'] = str_pad(decbin($this->mk_ais_lat($data['latitude'])),27,'0',STR_PAD_LEFT);
689
			$result['cog'] = str_pad(decbin($data['heading']*10),12,'0',STR_PAD_LEFT);
690
		} else if ($id == 4) {
691
			//$ro->lon = $this->make_lonf(bindec(substr($_aisdata,79,28)));
692
			//$ro->lat = $this->make_latf(bindec(substr($_aisdata,107,27)));
693
			$result['longitude'] = str_pad(decbin($this->mk_ais_lon($data['longitude'])),28,'0',STR_PAD_LEFT);
694
			$result['latitude'] = str_pad(decbin($this->mk_ais_lat($data['latitude'])),27,'0',STR_PAD_LEFT);
695
		} else if ($id == 5) {
696
			$result['imo'] = str_pad(decbin($data['imo']),30,'0',STR_PAD_LEFT);
697
			$result['callsign'] = $this->char2bin($data['callsign'],42);
698
			$result['name'] = $this->char2bin($data['ident'],120);
699
			$ro->typeid = bindec(substr($_aisdata,232,8));
700
			$ro->type = $this->getShipType($ro->typeid);
701
			//$ro->to_bow = bindec(substr($_aisdata,240,9));
702
			//$ro->to_stern = bindec(substr($_aisdata,249,9));
703
			//$ro->to_port = bindec(substr($_aisdata,258,6));
704
			//$ro->to_starboard = bindec(substr($_aisdata,264,6));
705
			$ro->eta_month = bindec(substr($_aisdata,274,4));
706
			$ro->eta_day = bindec(substr($_aisdata,278,5));
707
			$ro->eta_hour = bindec(substr($_aisdata,283,5));
708
			$ro->eta_minute = bindec(substr($_aisdata,288,6));
709
			//$ro->draught = bindec(substr($_aisdata,294,8));
710
			$ro->destination = $this->binchar($_aisdata,302,120);
711
		} else if ($id == 9) {
712
			// Search and Rescue aircraft position report
713
		} else if ($id == 18) {
714
			$ro->sog = bindec(substr($_aisdata,46,10))/10;
715
			$ro->lon = $this->make_lonf(bindec(substr($_aisdata,57,28)));
716
			$ro->lat = $this->make_latf(bindec(substr($_aisdata,85,27)));
717
			$ro->cog = bindec(substr($_aisdata,112,12))/10;
718
			$ro->heading = bindec(substr($_aisdata,124,9));
719
			if ($ro->heading == 511) $ro->heading = '';
720
		} else if ($id == 19) {
721
			$ro->cog = bindec(substr($_aisdata,112,12))/10;
722
			$ro->sog = bindec(substr($_aisdata,46,10))/10;
723
			$ro->lon = str_pad($this->mk_ais_lon($data['longitude']),28,'0',STR_PAD_LEFT);
724
			$ro->lat = $this->mk_ais_lat(bindec(substr($_aisdata,89,27)));
725
			$ro->name = $this->binchar($_aisdata,143,120);
726
			$ro->cls = 2; // class B
727
			$ro->heading = bindec(substr($_aisdata,124,9));
728
			if ($ro->heading == 511) $ro->heading = '';
729
			$ro->typeid = bindec(substr($_aisdata,263,8));
730
			$ro->type = $this->getShipType($ro->typeid);
731
			//$ro->to_bow = bindec(substr($_aisdata,271,9));
732
			//$ro->to_stern = bindec(substr($_aisdata,280,9));
733
			//$ro->to_port = bindec(substr($_aisdata,289,6));
734
			//$ro->to_starboard = bindec(substr($_aisdata,295,6));
735
		} else if ($id == 21) {
736
			$ro->lon = $this->make_lonf(bindec(substr($_aisdata,164,28)));
737
			$ro->lat = $this->make_latf(bindec(substr($_aisdata,192,27)));
738
			$ro->name = $this->binchar($_aisdata,43,120);
739
			//$ro->to_bow = bindec(substr($_aisdata,219,9));
740
			//$ro->to_stern = bindec(substr($_aisdata,228,9));
741
			//$ro->to_port = bindec(substr($_aisdata,237,6));
742
			//$ro->to_starboard = bindec(substr($_aisdata,243,6));
743
		} else if ($id == 24) {
744
			$pn = bindec(substr($_aisdata,38,2));
745
			if ($pn == 0) {
746
				$ro->name = $this->binchar($_aisdata,40,120);
747
			}
748
			$ro->typeid = bindec(substr($_aisdata,40,8));
749
			$ro->type = $this->getShipType($ro->typeid);
750
			$ro->callsign = $this->binchar($_aisdata,90,42);
751
			//$ro->to_bow = bindec(substr($_aisdata,132,9));
752
			//$ro->to_stern = bindec(substr($_aisdata,141,9));
753
			//$ro->to_port = bindec(substr($_aisdata,150,6));
754
			//$ro->to_starboard = bindec(substr($_aisdata,156,6));
755
		} else if ($id == 27) {
756
			$ro->cog = bindec(substr($_aisdata,85,9));
757
			if ($ro->cog == 511) $ro->cog = 0.0;
758
			$ro->sog = bindec(substr($_aisdata,79,6));
759
			if ($ro->sog == 63) $ro->sog = 0.0;
760
			$ro->lon = $this->make_lonf(bindec(substr($_aisdata,44,18))*10);
761
			$ro->lat = $this->make_latf(bindec(substr($_aisdata,62,17))*10);
762
			$ro->cls = 1; // class A
763
		
764
		}
765
		$ro->statusid = bindec(substr($_aisdata,38,4));
766
		$ro->status = $this->getStatus($ro->statusid);
767
768
		return $this->mk_ais(implode('',$result));
769
		*/
770
	}
771
}
772