2017-05-10 4 views
3

Ich bin PHP-Anfänger und meine Aufgabe ist es, Befehle zu erstellen, die später über UDP an ein Gerät gesendet werden. Running: OSX, PHP 5.5.3.8 Um die Binärdaten zu erstellen, verwende ich "pack". Hier ist ein Beispiel von meinem Code:PHP-Pack: Probleme mit Datentypen und Verifikation meiner Ergebnisse

<?php 
$in_1 = 0x3100; 
$in_2 = 0031; 
echo "Inputs: " . $in_1 . "\t" . $in_2; 
$bin = pack("v*", $in_1, $in_2); 
echo "\nlength: ". strlen($bin); 
printf ("\npacked result: %x \n",$bin); 
printf("HEX result %h\n", $bin); 
file_put_contents("ausgabe.log", $bin, FILE_APPEND); 
?> 

der Ausgang in meinem Terminal ist:

Inputs: 12544 25 
length: 4 
packed result: 0 
HEX result 

Ich frage mich, über die Zahl 25 für $ in_2. Wenn ich 0x0031 $ in_2 zuweisen, ist das Ergebnis 49. Was ist hier falsch?

By the way: Mein Endziel ist Binärbefehlen zu bauen, die wie folgt aus (Dezimalwerte als Kommentare in jeder Zeile) genau 12 Bytes in einem Schema sind:

function set_routing_item ($in_ch, $out_ch, $on_off, $seq) 
{ 
    $command = toggle_two_bytes(37); // 37 --> 0x2500 
    $status = 0x0000;     // 0 --> 0x0000 
    $pos = 4;       // 4= route item 
    $channel_1 = $in_ch;    // 3 
    $channel_2 = $out_ch;    // 6 
    $preset_no = 0xff;     // 255 
    $value = $on_off;     // 33145 
    $seq = $seq;      // 35 
    // implement building of command using pack here 
} 

Das Ergebnis in diesem Fall (hex) sollte wie folgt aussehen: 25 00 00 00 04 03 06 FF 79 81 23 00

Vielen Dank!

+0

Ok Das erste, was gelöst. PHP interpretiert Zahlen mit führenden Nullen als Oktalzahl. Also $ a = 0123; entspricht 83 dezimal Beispiel hier gefunden: http://php.net/manual/de/language.types.integer.php – Stefatronik

+0

Können Sie weitere Informationen über '' toggle_zwei_bytes'' – alistaircol

+0

Natürlich.Obwohl ich mit dem richtigen Modifizierer 'v' in pack() gelernt habe, ist dies nicht mehr notwendig ... // Toggle höher und niedriger Byte einer Zwei-Byte-Short-Variable Funktion toggle_two_bytes ($ two_bytes) { $ two_bytes = $ zwei_bytes & 0xffff; // limit size auf 2 Bytes $ high = ($ two_bytes << 8); // Bitverschiebung $ low = ($ two_bytes >> 8); $ ret = ($ hoch | $ niedrig); // ODER $ ret = $ ret & 0xffff; // Begrenzung (wieder) auf zwei Bytes return ($ ret); } – Stefatronik

Antwort

1

Ich kam mit diesem, aber es ist nicht die beste Methode, um es zu tun, richtig bitweise Operationen wäre schneller.

Ich verwende sprintf mit dem Formatbezeichner %x, der den Wert in einen hexadezimalen Wert konvertiert.

Jede Umwandlung Angabe eines Prozentzeichen besteht (%)

Sie werden sehen, ich %02x und %04x

  • 0 - Links Pads die Zahl mit Nullen
  • 2 oder 4 - Breite, die minimale Anzahl der zu druckenden Zeichen.
  • x - Spezifizierer für Hexadezimal, verwenden Sie X für Großbuchstaben.

Code:

<?php 
function toggle_two_bytes ($two_bytes) 
{ 
    $two_bytes = $two_bytes & 0xffff; // limit size to 2 Bytes 
    $high = ($two_bytes << 8);   // bit shift 
    $low = ($two_bytes >> 8); 
    $ret = ($high | $low);    // OR 
    $ret = $ret & 0xffff;    // limit (again) to two bytes 
    return ($ret); 
} 


function set_routing_item ($in_ch, $out_ch, $on_off, $seq) 
{ 
    $str = ''; 
    $command = toggle_two_bytes(37); 
    $str .= sprintf('%04X', $command); 

    $status = 0x0000; 
    $str .= sprintf('%04X', $status); 

    $pos = 4; 
    $str .= sprintf('%02X', $pos); 

    $str .= sprintf('%02X', $in_ch); 

    $str .= sprintf('%02X', $out_ch); 

    $preset_no = 0xFF; 
    $str .= sprintf('%02X', $preset_no); 

    $value = toggle_two_bytes($on_off); 
    $str .= sprintf('%04X', $value); 

    $seq = toggle_two_bytes($seq); 
    $str .= sprintf('%04X', $seq); 

    for ($i = 0; $i < strlen($str) - 1; $i += 2) { 
     echo $str[$i] . $str[$i+1] . ' '; 
    } 
} 

echo set_routing_item(3, 6, 33145, 35) . PHP_EOL; 

Ausgang:

25 00 00 00 04 03 06 FF 79 81 23 00 

Demo: https://eval.in/793695

+0

Vielen Dank für Ihre Inspiration. Ich habe endlich die 'pack()' zum arbeiten bekommen. Die _magic_ ist hier: 'return pack (" vvCCCCvv ", $ Befehl, $ Status, $ Typ, $ ch, $ out_ch, $ Voreinstellung, $ Wert, $ seq);' Um mein Ergebnis zu sehen benutze ich 'bin2hex () 'auf der Bin-Zeichenfolge. Prost! Stefan. – Stefatronik

+0

BTW Ich überprüfte die Zeichenfolge, die ich über UDP mit Wireshark gesendet habe - alles ist perfekt. – Stefatronik

0

Entschuldigung für meine schlecht formatierte Antwort. Hier ist der angeforderte Code:

// toggle higher and lower byte of a two-byte short variable 
function toggle_two_bytes ($two_bytes)` 

{ 
    $two_bytes = $two_bytes & 0xffff; // limit size to 2 Bytes 
    $high = ($two_bytes << 8);   // bit shift 
    $low = ($two_bytes >> 8); 
    $ret = ($high | $low);    // OR 
    $ret = $ret & 0xffff;    // limit (again) to two bytes 
    return ($ret); 
} 

Ich fand heraus, dass mit Pack ('v', ...) dies nicht mehr notwendig ist.