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模式给设备发送接收数据等下一回附上

更多crc使用参考这

本作品采用《CC 协议》,转载必须注明作者和本文链接
朝着梦,踏平坎坷
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 6

请教一个问题 0xE803 低字节在前,高字节在后,他的结果应该是多少 :smile:

3年前 评论
wavebossy6666 (楼主) 2年前

file 接下来不知道该怎么算了。。

3年前 评论
tcp_V1_3Traits

这驼峰+蛇形+帕斯卡的名称看起来就很厉害 😂

3年前 评论

@crazy 设备版本型号不一样,接入文档也有所差异,,这样写直接能对上号 :joy:

3年前 评论

@22 你参考下reverseChar 和 crc16 里面的写法。 或者问你硬件那边怎么接入

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!