Lhtlv.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. <?php
  2. namespace Workerman\Protocols;
  3. class Lhtlv {
  4. public static function input( $buffer, $connection ){
  5. if (strlen($buffer) < 4) {
  6. return 0;
  7. }
  8. $unpack_data = unpack('C1magic/C1method/n1length', $buffer);
  9. return $unpack_data['length'] + 6;
  10. }
  11. private static function bin2str( $hex, $space ){
  12. $data = unpack("C*chars",$hex);
  13. $bin = '';
  14. foreach($data as $key=>$value){
  15. $bin .= sprintf('%02X',$value);
  16. if($space)
  17. $bin .= ' ';
  18. }
  19. return trim($bin);
  20. }
  21. private static function packValue( $value ){
  22. if($value['cmd'] == 0x02){
  23. return pack('C1',$value['result']);
  24. }
  25. elseif($value['cmd'] == 0x04){
  26. return pack('C1',$value['result']);
  27. }
  28. elseif($value['cmd'] == 0x09){
  29. return pack('C1n1',$value['type'],$value['data']);
  30. }
  31. elseif($value['cmd'] == 0x01 || $value['cmd'] == 0xBC){
  32. return pack('H*', $value['data']);
  33. }
  34. else{
  35. return false;
  36. }
  37. }
  38. private static function unpackValue( $cmd, $value, $length ){
  39. if($cmd == 0x01){ //设备注册
  40. if($length == 6)
  41. return array('uid' => self::bin2str($value,false) );
  42. else
  43. return null;
  44. }
  45. elseif($cmd == 0x05){ //设备心跳
  46. return null;
  47. }
  48. elseif($cmd == 0x07){ //上报IMSI
  49. if($length == 21){
  50. return array(
  51. 'uid' => self::bin2str(substr($value,0,6),false) ,
  52. 'imsi' => substr($value,6,15)
  53. );
  54. }
  55. else
  56. return null;
  57. }
  58. elseif($cmd == 0x08){ //设备响应
  59. if($length == 2){
  60. return array(
  61. 'type' => Ord(substr($value,0,1)) ,
  62. 'result' => Ord(substr($value,1,1))
  63. );
  64. }
  65. else
  66. return null;
  67. }
  68. elseif($cmd == 0xbc){ //上报标签
  69. if($length >= 14){
  70. //解析设置的时间间隔,设置的设备数量
  71. $setting = unpack('n1maxtime/n1maxlabels', substr($value,10,4));
  72. //解析车辆信息
  73. $count = ($length - 14)/14;
  74. $labels = array();
  75. for($i=0;$i<$count;$i++){
  76. //解析RFID
  77. $j = 14+$i*14;
  78. $rfid = self::bin2str(substr($value,$j,6),false);
  79. $j += 6;
  80. //解析SSD信号强度
  81. $ssd = Ord(substr($value,$j,1));
  82. //解析时间
  83. $year1 = Ord(substr($value,$j+1,1));
  84. $year2 = Ord(substr($value,$j+2,1));
  85. $month = Ord(substr($value,$j+3,1));
  86. $day = Ord(substr($value,$j+4,1));
  87. $hour = Ord(substr($value,$j+5,1));
  88. $minute = Ord(substr($value,$j+6,1));
  89. $second = Ord(substr($value,$j+7,1));
  90. $hour = sprintf('%02d',$hour);
  91. $minute = sprintf('%02d',$minute);
  92. $second = sprintf('%02d',$second);
  93. $time = date('Y-m-d').' '.$hour.':'.$minute.':'.$second;
  94. if(strtotime($time) > time()){
  95. $time = date('Y-m-d H:i:s',strtotime('-1 day',strtotime($time)));
  96. }
  97. $info = array(
  98. 'rfid' => $rfid,
  99. 'ssd' => $ssd,
  100. 'time' => $time
  101. );
  102. array_push($labels,$info);
  103. }
  104. return array(
  105. 'maxtime' => $setting['maxtime'],
  106. 'maxlabels' => $setting['maxlabels'],
  107. 'labels' => $labels
  108. );
  109. }
  110. else
  111. return null;
  112. }
  113. elseif($cmd == 0xbd){ //上报报警
  114. if($length == 1)
  115. return array('v' => self::bin2str($value) );
  116. else
  117. return null;
  118. }
  119. return $value;
  120. }
  121. public static function decode( $buffer ){
  122. //解码头部数据
  123. $unpack_head = unpack('C1magic/C1cmd/n1length', $buffer);
  124. $unpack_head['method'] = sprintf("method%'04x",$unpack_head['cmd']);
  125. //判断头部引导符
  126. if( $unpack_head['magic'] != 0xEC )
  127. return null;
  128. //判断最后结尾符
  129. if( Ord(substr($buffer,-1)) != 0x68 )
  130. return null;
  131. //判断签名是否正确
  132. //如果长度等于0则没有值数据
  133. if($unpack_head['length'] == 0)
  134. return $unpack_head;
  135. //解码值数据
  136. $value = substr($buffer,4,$unpack_head['length']);
  137. $unpack_value = self::unpackValue($unpack_head['cmd'],$value,$unpack_head['length']);
  138. if(!$unpack_value)
  139. return null;
  140. //头部+值一起返回
  141. return array_merge($unpack_head,$unpack_value);
  142. }
  143. public static function encode( $value ){
  144. $pack_value = self::packValue($value);
  145. $length = strlen($pack_value);
  146. $sign = $value['cmd'] + $length;
  147. for($i=0;$i<strlen($pack_value);$i++){
  148. $sign += Ord($pack_value[$i]);
  149. }
  150. $buf = pack('C1C1n1', 0xEC,$value['cmd'],$length) . $pack_value .pack('C1', $sign). pack('C1', 0x68);
  151. return $buf;
  152. }
  153. private static function str2bin( $text ){
  154. if (!is_string($text))
  155. return null;
  156. $arr = explode(' ',$text);
  157. $bin = '';
  158. foreach($arr as $hex){
  159. if(strlen($hex) == 2){
  160. $bin .= chr( hexdec($hex) );
  161. }
  162. }
  163. return $bin;
  164. }
  165. }