程式碼備份錄
1、大端模式單通道(10位編碼版)
2、crc16位校驗
3、16進位制轉float
直接上程式碼
trait tcp_V1_3Traits{
/***
* 16進位制轉float
* @param $strHex
* @return float|int
*/
public function hexTo32Float($strHex) {
$v = hexdec($strHex);
$x = ($v & ((1 << 23) - 1)) + (1 << 23) * ($v >> 31 | 1);
$exp = ($v >> 23 & 0xFF) - 127;
return $x * pow(2, $exp - 23);
}
/**
* 將一個字元按位元位進行反轉 eg: 65 (01000001) --> 130(10000010)
* @param $char
* @return string $char
*/
private function reverseChar($char) {
$byte = ord($char);
$tmp = 0;
for ($i = 0; $i < 8; ++$i) {
if ($byte & (1 << $i)) {
$tmp |= (1 << (7 - $i));
}
}
return chr($tmp);
}
/**
* 將一個位元組流按位元位反轉 eg: 'AB'(01000001 01000010) --> '\x42\x82'(01000010 10000010)
* @param $str
* @return mixed
*/
private function reverseString($str) {
$m = 0;
$n = strlen($str) - 1;
while ($m <= $n) {
if ($m == $n) {
$str{$m} = $this->reverseChar($str{$m});
break;
}
$ord1 = $this->reverseChar($str{$m});
$ord2 = $this->reverseChar($str{$n});
$str{$m} = $ord2;
$str{$n} = $ord1;
$m++;
$n--;
}
return $str;
}
/**
* @param string $str 待校驗字串
* @param int $polynomial 二項式
* @param int $initValue 初始值
* @param int $xOrValue 輸出結果前異或的值
* @param bool $inputReverse 輸入字串是否每個位元組按位元位反轉
* @param bool $outputReverse 輸出是否整體按位元位反轉
* @return int
*/
public function crc16($str, $polynomial, $initValue, $xOrValue, $inputReverse = false, $outputReverse = false) {
$crc = $initValue;
for ($i = 0; $i < strlen($str); $i++) {
if ($inputReverse) {
// 輸入資料每個位元組按位元位逆轉
$c = ord($this->reverseChar($str{$i}));
} else {
$c = ord($str{$i});
}
$crc ^= ($c << 8);
for ($j = 0; $j < 8; ++$j) {
if ($crc & 0x8000) {
$crc = (($crc << 1) & 0xffff) ^ $polynomial;
} else {
$crc = ($crc << 1) & 0xffff;
}
}
}
if ($outputReverse) {
// 把低地址存低位,即採用小端法將整數轉換為字串
$ret = pack('cc', $crc & 0xff, ($crc >> 8) & 0xff);
// 輸出結果按位元位逆轉整個字串
$ret = $this->reverseString($ret);
// 再把結果按小端法重新轉換成整數
$arr = unpack('vshort', $ret);
$crc = $arr['short'];
}
return $crc ^ $xOrValue;
}
}
使用方式
$crc = $this->crc16(hex2bin("你要檢驗的值"), 0x8005, 0xffff, 0, true, true);
// 將你要檢驗的值去和資料返回的crc進行校驗,來確保資料沒有被篡改
關於本次使用的crc模式【CRC-16/MODBUS】
CRC-16/CCITT:除數選定為 0x1021,初始值為0,最終結果輸出前異或0,輸入的每個位元組按位元位反轉,結果在最終異或前按位元位反轉
CRC-16/MODBUS:除數選定為 0x8005,初始值為 0xffff,最終結果輸出前異或0, 輸入的每個位元組按位元位反轉,結果在最終異或前按位元位反轉。
心得記錄
以往都是做api介面,這是第一次使用php除錯物聯網的裝置,裡面資料互動都是採用16進位制進行換算
比如對方文件寫的1個位元組,實際上對應的是兩位長度的字串01 ; 反向傳送資料需要用函式補齊位數 如你要傳送已知1個位元組的01,要使用 sprintf("%02s", 1) 去拼接資料得到01
暫時先寫到這吧,tcp模式給裝置傳送接收資料等下一回附上
本作品採用《CC 協議》,轉載必須註明作者和本文連結