2

PHP で UDP 経由でデータを受信して​​います。PHPでbin2hex関数を介してバッファを渡した後、Raw Data以下の例に示すように似たものになります

ここに私のPHPコードがあります:

$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($socket, "0.0.0.0" , 20500);

$from = '';
$port = 0;
socket_recvfrom($socket, $buf, 512, 0, $from, $port);

$file = 'testudp.txt';
// Open the file to get existing content
$current = file_get_contents($file);
// Append a new log line(s) to file
$current .= "New Connection " . date('Y-m-d H:i:s') . " \n" . bin2hex($buf) . "\n";
// Write the contents back to the file
file_put_contents($file, $current);
echo "Received connection from remote address $from and remote port $port" . PHP_EOL;

その結果、次のような結果になり83 05 01 02 03 04 05 01 01 01 02 00 01 4F B4 64 88 4F B4 64 88 13 BF 71 A8 BA 18 A5 06 00 00 1333 00 00 00 00 11 11 02 ... ますが、スペースはありません。

データの例と変換先: 変換は最初の 9 バイトの後にのみ開始され、次にアドレス 2 が開始され、2 が再びスキップされることに注意してください

Raw Data:
 83 05 01 02 03 04 05 01 01 01 02 00 01 4F B4 64 88 4F B4 64
 88 13 BF 71 A8 BA 18 A5 06 00 00 1333 00 00 00 00 11 11 02 
 33 44 44 55 55 66 77 88 99 10 11 ?? 00 ?? 

Decoded:
  -------Message Header--------
  01           Service Type, for this message 1 = Acknowledged Request
  02           Message Type, for this message 2 = Event Report
  -------Event Report----------
  4FB46488     Update Time (5/17/12 @ 2:38pm)
  4FB46488     Time of Fix (5/17/12 @ 2:38pm)
  13BF71A8     Latitude (33.1313576)
  BA18A506     Longitude (-117.2790010)
  00001333     Altitude
  00000000     Speed
  1111         Heading
  02           Satellites
  33           Fix Status
  4444         Carrier
  5555         RSSI
  66           Comm State
  77           HDOP
  88           Inputs
  99           Unit Status
  10           Event Index
  11           Event Code
  ??           Accums (# of 4-byte Accum List values)
  00           Spare
  ??           Accum List (Varies depending on the # of Accums reporting)

私は ascii への 16 進数のさまざまなデコーダーを試しました。また、PHP で unpack() を試しましたが、まったく役に立ちませんでした。
PHP を介してデータを例に似たものに変換するにはどうすればよいでしょうか? つまり、人間が読める形式BA18A506に対応するデータ (フォーマットされていないかどうかに関係なく) をどのように私に与えるのでしょうか?Longitude (-117.2790010)

編集: ドキュメントはNote that all bytes in multi-byte fields are transmitted in Net Endian format (Big Endian) where the most significant bits are transmitted first. For example, for a 32-bit field, bits 31-24 are transmitted first, 16-23 second, 8-15 third and 0-7 last 、それがまったく役立つかどうかを指定します。

4

1 に答える 1

2

バイナリデータの substr() ごとに unpack() または unpack() を実行すると、最終的に目的の場所に到達するはずです。しかし、HamZa が言及しているように、それがどのような形式であるかを知る必要があります...

$test = "\x06\xA5\x18\xBA";
var_dump(unpack('l',$test));

結果:

-1172790010

を追加するだけです。正しい場所に

最初の部分を解凍するサンプル コード (必要に応じて拡張/修正)

ファイルではなくバッファーに受信するようにコードを変更します。 socket_recv($socket, $buf, 512, 0);

次に、バッファー $buf を使用できます (今のところ、提供されたサンプル データを入力します)。

// Now we use some test data
$buf = "\x83\x05\x01\x02\x03\x04\x05\x01\x01\x01\x02\x00\x01\x4F\xB4\x64\x88\x4F\xB4\x64\x88\x13\xBF\x71\xA8\xBA\x18\xA5\x06\x00\x00\x13\x33\x00\x00\x00\x00\x11\x11\x02\x33\x44\x44\x55\x55\x66\x77\x88\x99\x10\x11";

// field definition
$fields = array();
$fields['header'] = array(9, 'c*');
$fields['serviceType'] = array(1, 'c');
$fields['messageType'] = array(1, 'c');
$fields['skip'] = array(2, 'c');
$fields['updateTime'] = array(4, 'l');
$fields['fixTime'] = array(4, 'l');
$fields['longitude'] = array(4, 'l');
$fields['latitude'] = array(4, 'l');
$fields['altitude'] = array(4, 'l');
$fields['speed'] = array(4, 'l');
// etc.

$values = array();
$start = 0;
foreach($fields as $type=>$setting) {
    list($len, $format) = $setting;
    $values[$type] = unpack($format, strrev(substr($buf, $start, $len)));
    $start += $len;
}

var_dump($values);

次のような出力が得られます:

["serviceType"]=>
array(1) {
  [1]=>
  int(1)
}
["messageType"]=>
array(1) {
  [1]=>
  int(2)
}
["skip"]=>
array(1) {
  [1]=>
  int(1)
}
["updateTime"]=>
array(1) {
  [1]=>
  int(1337222280)
}
["fixTime"]=>
array(1) {
  [1]=>
  int(1337222280)
}
["longitude"]=>
array(1) {
  [1]=>
  int(331313576)
}
["latitude"]=>
array(1) {
  [1]=>
  int(-1172790010)
}
["altitude"]=>
array(1) {
  [1]=>
  int(4915)
}
["speed"]=>
array(1) {
  [1]=>
  int(0)
}

実際の経度と緯度を取得するには、緯度と経度を 10000000 (10M) で割るだけです。

于 2013-10-25T14:13:12.350 に答える