2017-05-10 4 views
3

Je suis débutant PHP et ma tâche est de construire des commandes qui seront ensuite envoyées via UDP à un périphérique. En cours d'exécution: OSX, PHP 5.5.3.8 Pour créer les données binaires, j'utilise "pack". Voici un exemple de mon code:php pack: problèmes avec les types de données et vérification de mes résultats

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

la sortie de mon terminal est:

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

Je me demande sur le numéro 25 pour in_2 $. Si j'assigne 0x0031 à $ in_2, le résultat est 49. Qu'est-ce qui ne va pas?

Par ailleurs: Mon objectif final est de construire des commandes binaires qui sont exactement 12 octets dans un système comme celui-ci (valeurs décimales sous forme de commentaires dans chaque ligne):

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 
} 

Le résultat dans ce cas (hex) devrait ressembler à: 25 00 00 00 04 03 06 FF 79 81 23 00

Merci!

+0

Ok Première chose résolu. PHP interprète les nombres avec des zéros en tête comme nombre octal. Donc $ a = 0123; est équivalent à 83 décimal Exemple trouvé ici: http://php.net/manual/de/language.types.integer.php – Stefatronik

+0

Pouvez-vous poster plus d'informations sur '' toggle_two_bytes'' – alistaircol

+0

Bien sûr.Bien que j'aie appris avec le bon modificateur 'v' dans pack() ce n'est plus nécessaire ... // bascule l'octet supérieur et inférieur d'une variable courte de deux octets function toggle_two_bytes ($ two_bytes) { $ two_bytes = $ two_bytes & 0xffff; // limite la taille à 2 octets $ high = ($ two_bytes << 8); // bit shift $ low = ($ two_bytes >> 8); $ ret = ($ haut | $ bas); // OU $ ret = $ ret & 0xffff; // limite (encore) à deux octets return ($ ret); } – Stefatronik

Répondre

1

Je suis arrivé avec cela, mais c'est pas la meilleure méthode pour le faire, les opérations au niveau du bit correct seraient plus rapides.

J'utilise sprintf avec le spécificateur de format %x qui convertit la valeur en une valeur hexadécimale.

Chaque spécification de conversion consiste en un signe pour cent (%)

Vous verrez que j'utilise %02x et %04x

  • 0 - gauche-tampons le nombre avec des zéros
  • 2 ou 4 - Largeur, le nombre minimum de caractères à imprimer.
  • - Spécificateur pour hexadécimal, utilisez X pour les majuscules.

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; 

Sortie:

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

Démo: https://eval.in/793695

+0

Merci pour votre inspiration. J'ai finalement obtenu le 'pack()' pour fonctionner. Le _magic_ est ici: 'return pack (" vvCCCCvv ", $ commande, $ status, $ type, $ ch, $ out_ch, $ preset, $ valeur, $ seq);' Pour voir mon résultat j'utilise 'bin2hex () 'sur la chaîne de la poubelle. À la votre! Stefan. – Stefatronik

+0

BTW J'ai vérifié la chaîne que j'ai envoyé via UDP avec wireshark- tout est parfait. – Stefatronik

0

Désolé pour ma mauvaise réponse formatée. Voici le code demandé:

// 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); 
} 

J'ai découvert que avec le pack ('v', ...) ce n'est pas plus nécessaire.