<?php
ini_set('date.timezone','Asia/Shanghai');
ini_set("display_errors","On");
error_reporting(E_ALL);
define('FACESYNC_COMMAND_NONE', 0);
define('FACESYNC_REQUEST_FACE_IDS', 1);
define('FACESYNC_RESPONSE_FACE_IDS', 2);
define('FACESYNC_REQUEST_FACE_FEATURES', 3);
define('FACESYNC_RESPONSE_FACE_FEATURES', 4);
define('FACESYNC_REQUEST_FAREWELL', 5);
define('FACESYNC_RESPONSE_FAREWELL', 6);
/*
注意:
//模擬數(shù)據(jù)庫存放三個人的數(shù)據(jù)
$test_feature_datas = array(
//張三
array(
//'u32Flag'=> 0,
'u32CheckSum'=> 0, //下面數(shù)據(jù)的校驗碼,主要用來判斷特征結構是否被更新,可以不計算
'u64FaceId'=> 11111111, //faceid
'u64PersonId'=> 11111111, //personid
'u32UpdateTime'=> 0, //修改時間,主要用來判斷特征結構是否被更新
//'u32FeatureCRC'=> 0, //特征校驗碼,可以不計算
'feature'=> '', //特征向量,填base64解碼后的二進制數(shù)據(jù),php的字符串直接可以存放二進制(不需要轉十六進制字符)
'info'=> array(
//'u32Permission'=> 0, //權限
'szName'=> '張三', //姓名
'szNric'=> '123', //證件
'szCardNum'=> '123', //卡號
//'u32VaildDateBegin'=> 0, //有效期開始時間
//'u32VaildDateEnd'=> 0, //有效期結束時間
//'_reserv'=> '' //保留
)
),
//李四
array(
//'u32Flag'=> 0,
'u32CheckSum'=> 0, //下面數(shù)據(jù)的校驗碼,主要用來判斷特征結構是否被更新,可以不計算
'u64FaceId'=> 22222222, //faceid
'u64PersonId'=> 22222222, //personid
'u32UpdateTime'=> 0, //修改時間,主要用來判斷特征結構是否被更新
//'u32FeatureCRC'=> 0, //特征校驗碼,可以不計算
'feature'=> '', //特征向量,填base64解碼后的二進制數(shù)據(jù),php的字符串直接可以存放二進制(不需要轉十六進制字符)
'info'=> array(
//'u32Permission'=> 0, //權限
'szName'=> '李四', //姓名
'szNric'=> '444', //證件
'szCardNum'=> '444', //卡號
//'u32VaildDateBegin'=> 0, //有效期開始時間
//'u32VaildDateEnd'=> 0, //有效期結束時間
//'_reserv'=> '' //保留
)
),
//陳五
array(
//'u32Flag'=> 0,
'u32CheckSum'=> 0, //下面數(shù)據(jù)的校驗碼,主要用來判斷特征結構是否被更新,可以不計算
'u64FaceId'=> 33333333, //faceid
'u64PersonId'=> 33333333, //personid
'u32UpdateTime'=> 0, //修改時間,主要用來判斷特征結構是否被更新
//'u32FeatureCRC'=> 0, //特征校驗碼,可以不計算
'feature'=> '', //特征向量,填base64解碼后的二進制數(shù)據(jù),php的字符串直接可以存放二進制(不需要轉十六進制字符)
'info'=> array(
//'u32Permission'=> 0, //權限
'szName'=> '陳五', //姓名
'szNric'=> '555', //證件
'szCardNum'=> '555', //卡號
//'u32VaildDateBegin'=> 0, //有效期開始時間
//'u32VaildDateEnd'=> 0, //有效期結束時間
//'_reserv'=> '' //保留
)
)
);
class FaceSyncSDK
{
//CRC32校驗算法 (要速度快請改查表法,網(wǎng)上沒有,我不舍得開源)
function CRC32_Calc($buf, $offset, $length, $seed=0xFFFFFFFF)
{
$polynomial = 0x04c11db7;
$crc = $seed;
for ($i = $offset; $i < $offset + $length; $i++) {
$c = ord($buf[$i]);
$crc ^= ($c << 24);
for ($j = 0; $j < 8; $j++) {
if ($crc & 0x80000000) {
$crc = (($crc << 1) & 0xffffffff) ^ $polynomial;
} else {
$crc = ($crc << 1) & 0xffffffff;
}
}
}
return $crc;
}
//FACE_ID_SET_T 轉 二進制
function pack_FACE_ID_SET_T($arr)
{
$bin = '';
$bin .= pack('Q', $arr['u64FaceId']);
$bin .= pack('L', $arr['u32UpdateTime']);
$bin .= pack('L', $arr['u32CheckSum']);
return $bin;
}
//二進制 轉 FACE_ID_SET_T
function unpack_FACE_ID_SET_T($bin, $offset = 64)
{
$format = 'Qu64FaceId/Lu32UpdateTime/Lu32CheckSum';
return unpack($format, $bin, $offset);
}
//FACE_SYNC_CMD_T 轉 二進制
function pack_FACE_SYNC_CMD_T($arr)
{
$bin = '';
$bin .= pack('L', isset($arr['checksum']) ? $arr['checksum'] : 0); //構造時可忽略參數(shù)
$bin .= pack('L', $arr['command']); //命令,必要的參數(shù)
$bin .= pack('L', isset($arr['groupnum']) ? $arr['groupnum'] : 0); //構造時可忽略參數(shù)
$bin .= pack('a20', isset($arr['serialnum']) ? $arr['serialnum'] : ''); //構造時可忽略參數(shù)
$bin .= pack('a24', isset($arr['_reserv']) ? $arr['_reserv'] : ''); //構造時可忽略參數(shù)
$bin .= pack('L', isset($arr['itemcount']) ? $arr['itemcount'] : 0); //構造時可忽略參數(shù)
$bin .= pack('L', isset($arr['itemsize']) ? $arr['itemsize'] : 0); //構造時可忽略參數(shù)
return $bin;
}
//二進制 轉 FACE_SYNC_CMD_T
function unpack_FACE_SYNC_CMD_T($bin, $offset = 0)
{
$format = 'Lchecksum/Lcommand/Lgroupnum/a20serialnum/a24_reserv/Litemcount/Litemsize';
return unpack($format, $bin, $offset);
}
//FACE_FEATURE_T 轉 二進制
function pack_FACE_FEATURE_T($arr)
{
$bin = '';
$bin .= pack('L', isset($arr['u32Flag']) ? $arr['u32Flag'] : 0);
$bin .= pack('L', isset($arr['u32CheckSum']) ? $arr['u32CheckSum'] : 0);
$bin .= pack('Q', $arr['u64FaceId']);
$bin .= pack('Q', $arr['u64PersonId']);
$bin .= pack('L', $arr['u32UpdateTime']);
$bin .= pack('L', isset($arr['u32FeatureCRC']) ? $arr['u32FeatureCRC'] : 0);
$bin .= pack('a2048', $arr['feature']);
//PERSON_INFO_T
$bin .= pack('L', isset($arr['info']['u32Permission']) ? $arr['info']['u32Permission'] : 0);
$bin .= pack('a32', isset($arr['info']['szName']) ? $arr['info']['szName'] : '');
$bin .= pack('a20', isset($arr['info']['szNric']) ? $arr['info']['szNric'] : '');
$bin .= pack('a24', isset($arr['info']['szCardNum']) ? $arr['info']['szCardNum'] : '');
$bin .= pack('L', isset($arr['info']['u32VaildDateBegin']) ? $arr['info']['u32VaildDateBegin'] : 0);
$bin .= pack('L', isset($arr['info']['u32VaildDateEnd']) ? $arr['info']['u32VaildDateEnd'] : 0);
$bin .= pack('a8', isset($arr['info']['_reserv']) ? $arr['info']['_reserv'] : '');
return $bin;
}
function parseCommand($inputstream)
{
$recvcmd = self::unpack_FACE_SYNC_CMD_T($inputstream, 0);
//printf("command = 0x%X, checksum = 0x%X\r\n", $recvcmd['command'], $recvcmd['checksum']);
$checksum = self::CRC32_Calc($inputstream, 4, strlen($inputstream)-4, 0xffffffff);
if($recvcmd['checksum'] != $checksum){
//printf("recv_checksum = 0x%X, calc_checksum = 0x%X\r\n", $recvcmd['checksum'], $checksum);
//if($_SERVER['REQUEST_METHOD'] != 'GET'){
return; //校驗碼錯誤返回
//}
}
if($recvcmd['command'] == FACESYNC_REQUEST_FACE_IDS){ //收到請求人臉列表命令
$checksum = 0xffffffff; //初始種子
$test_feature_datas = $GLOBALS['test_feature_datas']; //模擬讀取數(shù)據(jù)庫
$itemcount = count($test_feature_datas);
//生成協(xié)議頭
$sendcmd = array(
'command'=> FACESYNC_RESPONSE_FACE_IDS, //回復人臉列表命令
'itemsize'=> 16, // FACE_ID_SET_T占16字節(jié)
'itemcount'=> $itemcount
);
$cmddata = self::pack_FACE_SYNC_CMD_T($sendcmd);
$checksum = self::CRC32_Calc($cmddata, 4, 60, $checksum); //計算協(xié)議頭第4字節(jié)開始到末尾的校驗碼
//生成附加數(shù)據(jù)
$listdata = '';
foreach($test_feature_datas as $obj){
$face_id_set = self::pack_FACE_ID_SET_T($obj); //生成二進制列表項
$checksum = self::CRC32_Calc($face_id_set, 0, 16, $checksum); //累計校驗碼
$listdata .= $face_id_set; //二進制列表
}
$sendcmd['checksum'] = $checksum; //將最終數(shù)據(jù)包的校驗碼填入?yún)f(xié)議頭
$cmddata = self::pack_FACE_SYNC_CMD_T($sendcmd); //重新封包協(xié)議頭
//返回二進制流
header("Content-Type: application/octet-stream");
echo $cmddata; //發(fā)送協(xié)議頭
echo $listdata; //發(fā)送附加數(shù)據(jù)
//flush();
}else if($recvcmd['command'] == FACESYNC_REQUEST_FACE_FEATURES){ //收到請求人臉特征命令
$checksum = 0xffffffff; //初始種子
$test_feature_datas = $GLOBALS['test_feature_datas']; //模擬讀取數(shù)據(jù)庫
$itemcount = $recvcmd['itemcount'];
$faceids = unpack("Q{$itemcount}", $inputstream, 64); //解包收到的N個人臉I(yè)Ds //這里注意雙引號
//生成協(xié)議頭
$sendcmd = array(
'command'=> FACESYNC_RESPONSE_FACE_FEATURES, //回復人臉特征命令
'itemsize'=> 2176, // FACE_FEATURE_T占2176字節(jié)
'itemcount'=> $itemcount
);
$cmddata = self::pack_FACE_SYNC_CMD_T($sendcmd);
$checksum = self::CRC32_Calc($cmddata, 4, 60, $checksum); //計算協(xié)議頭第4字節(jié)開始到末尾的校驗碼
//生成附加數(shù)據(jù)
$listdata = '';
$face_feature_item = '';
//查找客戶端發(fā)來的faceid(s)對應的特征數(shù)據(jù)
$found = false;
foreach($faceids as $id){
foreach($test_feature_datas as $obj){
if($id == $obj['u64FaceId']){
$face_feature_item = self::pack_FACE_FEATURE_T($obj); //生成二進制列表項
$found = true;
break;
}
}
if(!$found){
$face_feature_item = pack('a2176', ''); //如果faceid剛好不存在則填充2176字節(jié)空白數(shù)據(jù)
}
$checksum = self::CRC32_Calc($face_feature_item, 0, 2176, $checksum); //累計校驗碼
$listdata .= $face_feature_item; //二進制列表
}
$sendcmd['checksum'] = $checksum; //將最終數(shù)據(jù)包的校驗碼填入?yún)f(xié)議頭
$cmddata = self::pack_FACE_SYNC_CMD_T($sendcmd); //重新封包協(xié)議頭
//返回二進制流
header("Content-Type: application/octet-stream");
echo $cmddata; //發(fā)送協(xié)議頭
echo $listdata; //發(fā)送附加數(shù)據(jù)
//flush();
}
}
}
//######### Main() ###########
//phpinfo();
//print_r($test_feature_datas);
$inputstream = '';
if($_SERVER['REQUEST_METHOD'] == 'GET')
$inputstream = pack("L16", 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); //GET測試返回人臉列表
else
$inputstream = file_get_contents('php://input'); //POST
$facesync = new FaceSyncSDK();
$facesync->parseCommand($inputstream);
?>
看手冊 http://wtbis.cn/doc/webman#/response 應該不難吧
應該是
reutrn response($cmddata.$listdata, 200, ['Content-Type'=>'application/octet-stream']);
public function hello(Request $request)
{
// 創(chuàng)建一個對象
$response = response();
// .... 業(yè)務邏輯省略
// 設置cookie
$response->cookie('foo', 'value');
// .... 業(yè)務邏輯省略
// 設置http頭
$response->header('Content-Type', 'application/json');
$response->withHeaders([
'X-Header-One' => 'Header Value 1',
'X-Header-Tow' => 'Header Value 2',
]);
// .... 業(yè)務邏輯省略
// 設置要返回的數(shù)據(jù)
$response->withBody('返回的數(shù)據(jù)');
return $response;
}