Search code examples
phppack

php pack: problems with data types and verification of my results


I am PHP beginner and my task is to build commands which will later be sent over UDP to a device. Running: OSX, PHP 5.5.3.8 To create the binary data I am using "pack". Here is an example of my code:

<?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);
?>

the output in my terminal is:

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

I wonder about the number 25 for $in_2. If I assign 0x0031 to $in_2 the result is 49. Whats wrong here?

By the way: My final goal is to build binary commands which are exactly 12 Bytes in a scheme like this (decimal values as comments in each line):

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
}

The result in this case(hex) should look like: 25 00 00 00 04 03 06 FF 79 81 23 00

Thanks!


Solution

  • I came up with this, but it is not the best method to do it, proper bitwise operations would be faster.

    I'm using sprintf with the %x format specifier which converts the value to a hexadecimal value.

    Each conversion specification consists of a percent sign (%)

    You will see I use %02x and %04x

    • 0 - Left-pads the number with zeroes
    • 2 or 4 - Width, the minimum number of characters to be printed.
    • x - Specifier for hexadecimal, use X for uppercase.

    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;
    

    Output:

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

    Demo: https://eval.in/793695