|
@@ -0,0 +1,362 @@
|
|
|
|
+<?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);
|
|
|
|
+}
|