php对接电信平台,对接lot设备发送or接收数据(一)
代码备份录
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 协议》,转载必须注明作者和本文链接
请教一个问题 0xE803 低字节在前,高字节在后,他的结果应该是多少 :smile:
这驼峰+蛇形+帕斯卡的名称看起来就很厉害 😂
@crazy 设备版本型号不一样,接入文档也有所差异,,这样写直接能对上号 :joy:
@22 你参考下reverseChar 和 crc16 里面的写法。 或者问你硬件那边怎么接入