123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- <?php
- $hexSerial = 0x6FFFFF;
- // 修复前先关闭设备上报
- $switch = sqlite("system_set")->where(["key"=>"light_state_switch"])->value("val");
- if(!$switch || $switch == "on"){
- // 先关闭
- $switchCmdStr = jsonCmdStr("LIGHT_STATE_SWITCH", ["state" => "off"]);
- $socket = sendSocketMsg($switchCmdStr, 0, 1, "LIGHT_STATE_SWITCH");
- $socketStatus = returnCmdDeal($socket, $switchCmdStr, function ($code,$msg) {
- writeLog("关闭网关设备信息上报失败,错误码:".$code."-错误消息:".$msg);
- });
- }
- // 修复zone的日程表
- $zoneList = sqlite("zones")->field("id,zone_title,holidays")->select();
- foreach ($zoneList as $zone){
- if (!$zone["holidays"]) continue;
- $holidaysList = json_decode($zone["holidays"], true);
- foreach ($holidaysList as $k => $v){
- // 开始修复
- $params = [];
- $params[] = replenStr(dechex($v["table_id"]), 4, 1);
- $start = $v["num"];
- if ($start >= 38) { // 特殊日
- $startDate = explode("-", $v["start_time"]);
- $params[] = $startDate[2] . $startDate[1];
- } else {
- $startDate = explode("-", $v["start_time"]);
- $endDate = explode("-", $v["end_time"]);
- $params[] = $startDate[2] . $startDate[1];
- $params[] = $endDate[2] . $endDate[1];
- }
- $loc = replenStr(dechex($start), 2);
- $socket = writeACTCmd(dechex($zone["id"] + 20480), $loc, "01", $params, "76");
- $socketStatus = returnCmdDeal($socket["result"], $socket["cmdStr"], function($code,$msg) use($zone) {
- writeLog("重写Zone:".$zone["zone_title"]."的日程失败,错误码:".$code."-错误消息:".$msg);
- });
- }
- }
- // 修复传感器群组的日程表
- $groupList = sqlite("groups")->field("id,group_title,holidays")->where(["type"=>["in",[3,4,5,6,8,9,12,13,14]]])->select();
- foreach ($groupList as $group){
- if (!$group["holidays"]) continue;
- $holidaysList = json_decode($group["holidays"], true);
- $gwid = sqlite("group_device")->where(["gid"=>$group["id"]])->value("gwid");
- if(!$gwid){
- writeLog("传感器群组:".$group["group_title"]."未找到网关id");
- continue;
- }
- $ip = sqlite("gateways")->where(["id"=>$gwid])->value("eth_ip");
- if(!$ip){
- writeLog("传感器群组:".$group["group_title"]."未找到对应的网关IP");
- continue;
- }
- foreach ($holidaysList as $k => $v){
- // 开始修复
- $params = [];
- $params[] = replenStr(dechex($v["table_id"]), 4, 1);
- $start = $v["num"];
- if ($start >= 38) { // 特殊日
- $startDate = explode("-", $v["start_time"]);
- $params[] = $startDate[2] . $startDate[1];
- } else {
- $startDate = explode("-", $v["start_time"]);
- $endDate = explode("-", $v["end_time"]);
- $params[] = $startDate[2] . $startDate[1];
- $params[] = $endDate[2] . $endDate[1];
- }
- $loc = replenStr(dechex($start), 2);
- $cmdStr = jsonCmdStr("SET_SENSOR_PERIOD", ["addr" => dechex($group["id"]), "byte7" => $loc, "byte8"=>"01", "ip"=>$ip, "param"=>implode("", $params)]);
- $res = sendSocketMsg($cmdStr, 0, 1, "SET_SENSOR_PERIOD");
- $socketStatus = returnCmdDeal($res, $cmdStr, function ($code,$msg) use ($group){
- writeLog("重写传感器群组:".$group["group_title"]."的日程失败,错误码:".$code."-错误消息:".$msg);
- });
- }
- }
- if(!$switch || $switch == "on"){
- // 原来是打开的重新打开
- $switchCmdStr = jsonCmdStr("LIGHT_STATE_SWITCH", ["state" => "on"]);
- $socket = sendSocketMsg($switchCmdStr, 0, 1, "LIGHT_STATE_SWITCH");
- $socketStatus = returnCmdDeal($socket, $switchCmdStr, function ($code,$msg) {
- writeLog("打开网关设备信息上报失败,错误码:".$code."-错误消息:".$msg);
- });
- }
- // 写入动作/配置等
- function writeACTCmd($addr="",$byte7,$byte8,$data=[], $byte4="71"){
- if(!$addr || !$byte7 || !$byte8) return false;
- $addr = swapHilo($addr);
- $serial = getSerial();
- $byte = [];
- $byte[0] = "E0";
- $byte[1] = $serial[0];
- $byte[2] = $serial[1];
- $byte[3] = $serial[2];
- $byte[4] = $byte4;
- $byte[5] = $addr["lbyte"];
- $byte[6] = $addr["hbyte"];
- $byte[7] = $byte7;
- $byte[8] = $byte8;
- if(!empty($data)){
- foreach ($data as $k => $v) {
- $byte[9+$k] = $v;
- }
- }
- $cmdStr = implode("",$byte);
- $crc = crc16($cmdStr);
- $cmdStr .= $crc;
- $result = sendSocketMsg($cmdStr);
- if(!$result){
- }
- return ["cmdStr"=>$cmdStr,"result"=>$result];
- }
- function sendSocketMsg($data,$hex=1,$back=1, $cmd=""){
- $host = "127.0.0.1";
- $port = "2347";
- $socket = socket_create(AF_INET,SOCK_STREAM,0);
- if ($socket < 0) return false;
- $result = @socket_connect($socket,$host,$port);
- if (!$result)return false;
- // 转成二级制流发送
- if(is_array($data)){ // 是数组,批量发送
- foreach ($data as $k => $v) {
- if($hex) $v = hex2bin(preg_replace("# #", "", $v));
- socket_write($socket,$v,strlen($v));
- }
- }else{
- if($hex) $data = hex2bin(preg_replace("# #", "", $data));
- $res = socket_write($socket,$data,strlen($data));
- }
- if($back!=0){
- do{
- $is_fail = false;
- $input = socket_read($socket, 1024);
- $is = json_decode($input, true);
- if($is && $cmd && $is["cmd"] != $cmd && $is["cmd"] != "GLOBAL"){
- $is_fail = true;
- }else if(strpos($input, $cmd)){
- break;
- }
- }while($is_fail);
- // $input = bin2hex($input); // 将2进制数据转换成16进制
- socket_close ($socket);
- return $input;
- }else{
- socket_close ($socket);
- return true;
- }
- }
- function crc16($str)
- {
- $string = pack("H*", $str);
- $crc = 0xFFFF;
- for ($x = 0; $x < strlen($string); $x++) {
- $crc = $crc ^ ord($string[$x]);
- for ($y = 0; $y < 8; $y++) {
- if (($crc & 0x0001) == 0x0001) {
- $crc = (($crc >> 1) ^ 0xA001);
- } else {
- $crc = $crc >> 1;
- }
- }
- }
- return crcSwapHilo($crc);
- }
- function crcSwapHilo($crc)
- {
- $hbyte = dechex(floor($crc / 256));
- $lbyte = dechex($crc % 256);
- if (strlen($hbyte) <= 1) $hbyte = "0" . $hbyte;
- if (strlen($lbyte) <= 1) $lbyte = "0" . $lbyte;
- return $lbyte . $hbyte;
- }
- function returnCmdDeal($returnCmd,$cmdStr, $failCall=null, $successCall=null){
- if(!$returnCmd){
- call_user_func($failCall, "00", "");
- return false;
- }
- /*
- * 过滤粘包
- * 防止出现:{"code":"00","cmd":"","data":[]}{"code":"01","cmd":"","data":[]}
- */
- if(!preg_match("/(\{.*\}\})/", $returnCmd, $matches) && !preg_match("/(\{.*\})/", $returnCmd, $matches)) return false;
- $data = json_decode($matches[1],true);
- if(is_null($data)){
- $successCall && call_user_func($successCall, true);
- return true;
- }
- if($data["cmd"] == "75"){
- $is = call_user_func($failCall, "00", "操作失败,网关ip:".$data["data"]);
- if($is === false) return false;
- }
- if($data["code"] == "40"){ // 网关不在线
- $is = call_user_func($failCall, $data["code"], "网关不在线");
- if($is === false) return false;
- }elseif($data["code"] == "0a"){ // 设备不在线
- $is = call_user_func($failCall, $data["code"], "设备不在线");
- if($is === false) return false;
- }elseif($data["code"] == "07") {
- $is = call_user_func($failCall, $data["code"], "设备超时");
- if($is === false) return false;
- }elseif($data["code"] == "08") {
- $is = call_user_func($failCall, $data["code"], "未设置meshId和密码");
- if($is === false) return false;
- }elseif($data["code"] == "09") {
- $is = call_user_func($failCall, $data["code"], "设备类型错误");
- if($is === false) return false;
- }elseif($data["code"] == "13") {
- $is = call_user_func($failCall, $data["code"], "操作无效,系统正在升级中");
- if($is === false) return false;
- }elseif($data["code"] == "02") {
- $is = call_user_func($failCall, $data["code"], "设备地址错误");
- if($is === false) return false;
- }elseif($data["code"] == "-1") {
- $is = call_user_func($failCall, $data["code"], "失败");
- if($is === false) return false;
- }elseif($data["code"] == "-2") {
- $is = call_user_func($failCall, $data["code"], "自动备份中,请勿操作");
- if($is === false) return false;
- }elseif($data["code"] == "-3") {
- $is = call_user_func($failCall, $data["code"], "预设导入中,请误操作");
- if($is === false) return false;
- }elseif($data["code"] == "-4") {
- $is = call_user_func($failCall, $data["code"], "正在恢复数据中,请误操作");
- if($is === false) return false;
- }elseif($data["code"] == "-5") {
- $is = call_user_func($failCall, $data["code"], "系统很拥挤");
- if($is === false) return false;
- }elseif($data["code"] == "-6") {
- $is = call_user_func($failCall, $data["code"], "mcu正在matching");
- if($is === false) return false;
- }elseif($data["code"] == "03") {
- $is = call_user_func($failCall, $data["code"], "数据地址错误");
- if($is === false) return false;
- }elseif($data["code"] == "05") {
- $is = call_user_func($failCall, $data["code"], "数据超出范围");
- if($is === false) return false;
- }elseif($data["code"] == "04") {
- $is = call_user_func($failCall, $data["code"], "数据长度错误");
- if($is === false) return false;
- }elseif($data["code"] == "0d") {
- $is = call_user_func($failCall, $data["code"], "mcu忙碌着");
- if($is === false) return false;
- }elseif($data["code"] == "00"){
- if(empty($data["data"])) {
- $successCall && call_user_func($successCall, true);
- return true;
- } else {
- $successCall &&call_user_func($successCall, $data["data"]);
- return $data["data"];
- }
- }elseif($data["code"] == "0b"){
- $is = call_user_func($failCall, $data["code"], "当前网关设备地址254个已用完");
- if($is === false) return false;
- }elseif($data["code"] == "01"){// 需要重发,重发次数5
- $count = 4;
- while ($count > 0) {
- $socket = sendSocketMsg($cmdStr);
- if(strcasecmp($socket,"FAD20001")==0){
- $count--;
- }elseif(strcasecmp($socket,"FAD20000")==0){
- return true;
- break;
- }else{
- $is = call_user_func($failCall, "0", "错误");
- if($is === false) return false;
- }
- }
- $is = call_user_func($failCall, "01", "重发次数超出");
- if($is === false) return false;
- }
- return false;
- }
- // 长度补充
- function replenStr($str, $len, $swap = 0, $replenField = "0")
- {
- $str = str_pad($str, $len, $replenField, STR_PAD_LEFT);
- if ($swap == 1) {
- // 交换高低位
- $lhbyte = swapHilo($str);
- $str = $lhbyte["lbyte"] . $lhbyte["hbyte"];
- }
- return $str;
- }
- // 交换高低位
- function swapHilo($num)
- {
- // 先转换为10进制数
- $num = hexdec($num);
- $hbyte = dechex(floor($num / 256));
- $lbyte = dechex($num % 256);
- if (strlen($hbyte) <= 1) $hbyte = "0" . $hbyte;
- if (strlen($lbyte) <= 1) $lbyte = "0" . $lbyte;
- return ["hbyte" => $hbyte, "lbyte" => $lbyte];
- }
- function jsonCmdStr($cmd = "", $data = [])
- {
- return json_encode(["cmd" => $cmd, "data" => $data]);
- }
- function getSerial()
- {
- global $hexSerial;
- $lowerLimit = 0x6FFFFF;
- $upperLimit = 0xAFFFFF;
- $hexSerial++;
- // 检查是否超出上限,如果超出则重新从下限开始
- if ($hexSerial > $upperLimit) {
- $hexSerial = $lowerLimit;
- }
- // 将整数转换为 24 位无符号整数的二进制表示
- $binaryData = pack('N', $hexSerial);
- // 取后 3 个字节(24 位)的数据
- $binaryData = substr($binaryData, 1);
- // 将二进制数据反转(高低位交换)
- $reversedData = strrev($binaryData);
- // 将反转后的二进制数据转换为十六进制字符串
- $hexSerialNumber = bin2hex($reversedData);
- return str_split($hexSerialNumber, 2);
- }
- function writeLog($msg){
- $dir = __DIR__ . "/../logs/patch/";
- // 日志目录不存在
- if(!file_exists($dir)) mkdir($dir, 0777, true);
- $filename = $dir ."rewriteTheSchedule.log";
- // 日志文件不存在
- if(!file_exists($filename)){
- file_put_contents($filename, "");
- chmod($filename, 0777);
- }
- // 写入日志
- file_put_contents($filename, $msg . "\n", FILE_APPEND);
- }
|