PHP CRC16物联网硬件通讯升级

通过清心醉

PHP CRC16物联网硬件通讯升级

<?php
class crc{

private $SerialNumber = 1; //自增加
private $SerialNumberXOR = 254; //自减少

function issleep($time = 1){
    sleep($time);
}

private $binFile = '';
private $getSocketData = ''; //获取的16进制数据
function setBinFile($str){
    $this->binFile .=$str;
}
function getBinFile($str){
    $this->binFile .=$str;
    //$this->getSocketData .=$str;
}

function CreateSetLogFile($file){
    $file = SET_FILE;
    if($this->binFile){
        $hexstr = str_replace(" ","",$this->binFile);
        $data = pack('H*', $hexstr);
        file_put_contents($file, $data, true);
    }

    //因为获取的是16进制 所以直接写入16进制文件
    $getfile = GET_FILE;
    if($this->getSocketData){
        //$hexstr = str_replace(" ","",$this->getSocketData);
        //$data = pack('H*', $hexstr);
        file_put_contents($getfile, $this->getSocketData, true);
    }
}

public $str = array();
function setlog($str){
    $this->str[] = $str;
    $str = $str."\r\n";
    echo iconv('utf-8','gbk//IGNORE',$str);
}

function chaString($string){
    $str = '';
    for($i=0;$i<strlen($string);$i++){
        $str .= $this->getByteData($i, $string);
    }
    return $str;
}

function getByteData($k,$str){
    if($k%2==0){
        return " ".$str[$k];
    } else {
        return $str[$k];
    }
}
//字符串转16进制
function strToHex($str){
    $hex="";
    for($i=0;$i<strlen($str);$i++)
        $hex.=dechex(ord($str[$i]));
        $hex=strtoupper($hex);
        return $hex;
}
//16进制转字符串
function hexToStr($hex){
    $str="";
    for($i=0;$i<strlen($hex)-1;$i+=2)
        $str.=chr(hexdec($hex[$i].$hex[$i+1]));
        return $str;
}

function crc16($string) {
    $crc = 0xA28C;
    for ($x = 0; $x < strlen ($string); $x+=2) {
        $sys = '';
        if(isset($string[$x]) && isset($string[$x+1])){
            $sys = $string[$x].$string[$x+1];
        } else {
            continue;
        }
        //echo "sys = ". $sys."\r\n";
        $sys = hexdec($sys);

        $crc  ^= $sys;
        for ($y = 0; $y < 8; $y++) {
            $lbs = $crc & 0x0001;
            $crc >>=1;
            if($lbs == 1){
                $crc ^= 0x8408;
            }
        }
    }
    $crc ^=0xFFFF;
    return $crc;
}


private function dechexSerialNumber(){
    $str = dechex($this->SerialNumber);
    $str = $this->setHeadZero($str);
    $this->SerialNumber++;
    return $str;
}
private function dechexSerialNumberXOR(){
    $str = dechex($this->SerialNumberXOR);
    $str = $this->setHeadZero($str);
    $this->SerialNumberXOR--;
    return $str;
}

//前补0
private function setHeadZero($str,$max = 2){
    $leng = strlen($str);
    for($i=$leng;$i<$max;$i++){
        $str = "0".$str;
    }
    return $str;
}
//后补0
private function setEndZero($str,$max = 4){
    $leng = strlen($str);
    for($i=$leng;$i<$max;$i++){
        $str = $str."0";
    }
    return $str;
}


public function getdata($packet){
    $data = array();
    $data[0] = '6D';
    $data[1] = 'AC';
    $data[2] = $this->dechexSerialNumber();
    $data[3] = $this->dechexSerialNumberXOR();
    $packetNum = count($packet); //Packet Length
    $packetNum = dechex($packetNum);
    $packetNum = $this->setHeadZero($packetNum,4); //因为高字节要在前,比如包长度=10 那么实际就是0010,高低位转换就是10 00
    //数据包长度高低位
    $data[4] = substr($packetNum, 2,2);
    $data[5] = substr($packetNum, 0,2);

    //指令开始 协议头
    $command = '';

    for($i=0;$i<count($data);$i++){
        $command = $command.$this->setHeadZero($data[$i])." ";
        //$crcString .= $this->setHeadZero($data[$i]);
    }
    $crcString = '';
    //指令内容体
    for($i=0;$i<count($packet);$i++){
        $command = $command.$this->setHeadZero($packet[$i])." ";
        $crcString .= $this->setHeadZero($packet[$i]);
    }
    $crc = '';
    $temp_crc = dechex($this->crc16($crcString));
    $sum = strlen($temp_crc);
    for($i=$sum;$i<4;$i++){
        $temp_crc = "0".$temp_crc;
    }
    $crc = $temp_crc;
    $crc1 = $this->setHeadZero(substr($crc,2,2));
    $crc2 = $this->setHeadZero(substr($crc, 0,2));
    $command = $command.$crc1. " ".$crc2;
    $commandArray = array();
    return $command;
}

private function heightlow($readInt){
    $byte1 = (($readInt & 0xff));
    $byte2 = (($readInt & 0xff00) >> 8);
    // 拼装成 "高字节在后,低字节在前"的格式
    $realint = ($byte1 & 0xff) << 0 | ($byte2 & 0xff) << 8;
    //echo $byte1." = ".$byte2."\r\n";
    return $realint;
}
//更新
public function getUpdatePacket(){
    $data[0] = 26; //command
    $data[1] = 11; //type
    //p2-p9
    for($i=2;$i<=9;$i++){
        $data[$i] = 00;
    }
    return $data;
}
//握手
public function getHandshake(){
    $data[0] = 20; //command
    $data[1] = 11; //type
    //p2-p9
    for($i=2;$i<=9;$i++){
        $data[$i] = 00;
    }
    return $data;
}

private $falshAddress = 64;
private $defaultFalshAddress = 64; //falsh默认的10进制地址

private function getFalshAddress($zizeng = true){
    $falshAddress = $this->falshAddress;
    if($zizeng == true){
        $this->falshAddress = $this->falshAddress+2;
    }
    return dechex($falshAddress);
}
//跳转到Application
public function runApp(){
    $data[0] = 21;
    $data[1] = 11;
    for($i=2;$i<=9;$i++){
        $data[$i] = 00;
    }
    return $data;
}

//校验falsh
public function checkFalsh($res){
    $data[0] = 25;
    $data[1] = 12; 
    //p2-p9
    for($i=2;$i<=9;$i++){
        $data[$i] = 00;
    }
    $data[3] = dechex($this->defaultFalshAddress);

    //大小 = 224*0x200;
    $data[10] = dechex($this->defaultFalshAddress);
    $data[11] = 56;
    $data[12] = 00;
    $data[13] = 00;
    //dechex(224*0x200);
    return $data;
}
//擦除
public function getRemove(){
    $data[0] = 24; //command
    $data[1] = 12; //type
    //p2-p9
    for($i=2;$i<=9;$i++){
        $data[$i] = 00;
    }
    $data[3] = $this->getFalshAddress(false);
    //大小 = 224*0x200;
    $data[10] = dechex($this->defaultFalshAddress);
    $data[11] = 56;
    $data[12] = 00;
    $data[13] = 00;
    //dechex(224*0x200);
    return $data;
}
//下载
public function getUpload($arr){
    $data[0] = 22; //command
    $data[1] = 12; //type
    //p2-p9
    for($i=2;$i<=9;$i++){
        $data[$i] = 00;
    }
    $data[3] = $this->getFalshAddress(); //dechex();
    $array = explode(" ",$arr);
    for($i=0;$i<count($array);$i++){
        if(!empty($array[$i])){
            $data[] = $array[$i];
        }
    }
    return $data;
}

}

使用方式:

$filename = “C:\crc\APP-2020-02-05.bin”;
$host = ‘192.168.1.122’;
$port = 502;
define(“SET_FILE”,’C:\crc\log.log’);
define(“GET_FILE”,’C:\crc\getlog.log’);

require_once ‘crc.php’;
$req = new crc();
$res = bin2hex(file_get_contents($filename));
if (!$res){
$req->setlog(“打开更新文件失败”);
return;
}
$req->setlog(“连接设备中…”);
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($sock, SOL_SOCKET, SO_SNDTIMEO,array(‘sec’ => 1, ‘usec’ => 1));
$result = @socket_connect($sock, $host, $port);
if($result == false){
$req->setlog(“设备连接失败”);
return false;
}

//发送数据
function send($sock,$packets,$crc){
$status = socket_last_error($sock);
if($status!=0){
return false;
}
//记录的数据为字符串,实际发送的时候 重新转换成16进制的数据格式
$t = $packets;
$packets = str_split(str_replace(‘ ‘, ”, $packets), 2); //chr(hexdec($packets));
$packet = null;
for($i=0;$isetBinFile($t);
$res = getrec($sock,$crc);
$crc->getBinFile(bin2hex($res));
$crc->setlog(“接收的16进制数据:”.bin2hex($res));
return true;
}

function getrec($socket,$crc){
$rec = null;
$time = time();
$crc->setlog(“接收数据”);
while (@socket_recv($socket, $rec, 4096, 0)) { //设置接收长度最大值缓冲区
if($time+10setlog(“接收数据超时”);
break;
}
return $rec;
}
return false;
}
//

$req->setlog(“设备连接成功”);
$req->setlog(“更新帧”);
$getUpdatePacket = $req->getUpdatePacket(); //更新的包
$packets = $req->getdata($getUpdatePacket);
$req->setlog($packets);
if(send($sock, $packets,$req) == false){
$req->setlog(“发送数据”.$packets.”失败”);
}
$req->issleep();
$req->setlog(“握手”);
$getHandshake = $req->getHandshake(); //更新的包
$packets = $req->getdata($getHandshake);
$req->setlog($packets);
if(send($sock, $packets,$req) == false){
$req->setlog(“发送数据”.$packets.”失败”);
}
$req->issleep();

$req->setlog(“擦除falsh”);
$getRemove = $req->getRemove();
$packets = $req->getdata($getRemove);
$req->setlog($packets);
if(send($sock, $packets,$req) == false){
$req->setlog(“发送数据”.$packets.”失败”);
}
$req->issleep();

$arr = array();
$head = 0;
$end = 1024;
$length = strlen($res);
while(true){
if($length<=0){ break; } $arr[] = substr($res, $head,$end); $head = ($head+1024); $length = ($length-1024); } for($i=0;$isetlog(“第”.($i+1).”次下载数据”);
$str = $req->chaString($arr[$i]);;
$getUpload = $req->getUpload($str);
$packets = $req->getdata($getUpload);
$req->setlog($packets);
if(send($sock, $packets,$req) == false){
$req->setlog(“发送数据”.$packets.”失败”);
}
$req->issleep();
}

$req->setlog(“校验falsh”);
$checkfalsh = $req->checkFalsh($res);
$packets = $req->getdata($checkfalsh);
$req->setlog($packets);
if(send($sock, $packets,$req) == false){
$req->setlog(“发送数据”.$packets.”失败”);
}
$req->issleep();

$req->setlog(“跳转到Application”);
$runApp = $req->runApp();
$packets = $req->getdata($runApp);
$req->setlog($packets);
if(send($sock, $packets,$req) == false){
$req->setlog(“发送数据”.$packets.”失败”);
}
$req->issleep();

$req->setlog(“执行完成”);
$req->setlog(“创建写入文件”);
$req->CreateSetLogFile(SET_FILE);

关于作者

清心醉 administrator

发表评论

如果喜欢作者的文章,您可以打赏给作者:

TRC20(虚拟货币):


ERC20(虚拟货币):


Bitcoin(BTC):