通常GPS坐标是以浮点数形式表示,例如:
纬度(latitude):31.2304
经度(longitude):121.4737
时间戳(timestamp):比如 Unix 时间戳 1716720000
如果直接以字符串形式发送,如 JSON,体积较大,不适合带宽受限的物联网设备。而使用 pack() 函数,我们可以把这些数值以二进制格式打包成一个定长的数据包,节省带宽,并在接收端准确还原。
pack() 是 PHP 内置的函数,用于将数据转换为二进制字符串,常用于网络通信、文件存储等。其基本语法如下:
string pack(string $format, mixed ...$values)
参数 $format 是格式控制字符串,指定了后续值的类型和顺序,例如:
f:32位浮点数(小端)
d:64位浮点数
N:32位无符号整型(大端)
V:32位无符号整型(小端)
为了兼容性与数据紧凑性,假设我们使用:
纬度(latitude):float(4字节,小端)
经度(longitude):float(4字节,小端)
时间戳(timestamp):uint32(4字节,小端)
我们可以使用如下代码打包这些数据:
<?php
// GPS数据
$latitude = 31.2304;
$longitude = 121.4737;
$timestamp = time(); // 当前时间戳
// 使用小端格式打包(latitude: float, longitude: float, timestamp: uint32)
$binaryData = pack('ffV', $latitude, $longitude, $timestamp);
// 可选:将打包后的二进制数据进行Hex编码,便于查看
$hexData = bin2hex($binaryData);
echo "打包后的二进制数据为: $hexData\n";
?>
这段代码将会输出形如:
打包后的二进制数据为: 9ad4fc3f7089514270128c66
其中每一段分别对应打包的纬度、经度和时间戳。可以使用 unpack() 在服务端解析回来:
<?php
$receivedData = $binaryData; // 假设是从设备接收到的
$unpacked = unpack('flatitude/flongitude/Vtimestamp', $receivedData);
print_r($unpacked);
?>
设备端可以使用相同的二进制结构打包数据,通过 MQTT、HTTP POST、或者 UDP 上传至服务器。例如:
$url = "https://m66.net/api/receive.php";
$data = $binaryData;
$options = [
'http' => [
'method' => "POST",
'header' => "Content-Type: application/octet-stream\r\n",
'content' => $data
]
];
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
echo "服务器响应: $response\n";
服务器端通过 php://input 读取原始二进制数据并解析即可。
pack() 中的浮点数格式在不同平台可能略有差异,应统一使用小端或大端并记录格式。
确保设备端与服务器端使用一致的字节顺序。
如果传输的数据结构复杂,建议加上数据头标识(如类型、版本号等)。