start("jsontext",10240,1); } protected function onAppLogin( $connection, $proto ){ //检查imei地址 if(!$proto->imei){ $this->respError($connection,'imei is empty ',$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); return; } if( $proto->addr ){ //设备序列号在控制台操作添加,会直接上报,2019年3月14日09:29:57 $addr = $proto->addr; }else{ $addr = MM('dpsb_device')->where(array('DeviceImei'=>$proto->imei))->getField('DeviceAddr'); } if(!$addr){ $device_id = saveDeviceInfo($proto); $this->respError($connection,'addr is empty ',$proto); return; }else{ //保存到设备表 $device_id = saveDeviceInfo($proto); } //通过登录验证,加入连接池 $connection->imei = $proto->imei; $connection->addr = $addr; $this->addToPool($addr,$connection); $this->logDebug('login success. should put into connection pool. imei = ' . $proto->imei); // 将数据更新到数据表中 //$device_id = saveDeviceInfo($proto->imei,$proto->versionName,$addr,$proto->iccid,$proto->cellphone); if(!$device_id){ $this->respError($connection,'device_id is empty ',$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); return; } /* if(!$proto->channel){ $this->respError($connection,'channeldata is empty ',$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); return; }*/ $errmsg = saveChannel($device_id,$proto->channel); if($errmsg){ $this->respError($connection,$errmsg,$proto,\Zndp\Api\ResponseCode::DEVICE_LOST_CONNECTION); return; } // 新增:保存通道组信息 2019年1月8日11:46:49 $result = saveChgroup($device_id,$proto->channel); if($result){ $this->respError($connection,$errmsg,$proto,\Zndp\Api\ResponseCode::DEVICE_LOST_CONNECTION); return; } // 以设备id-通道号为key,通道组号为值存入redis 2019年1月28日13:44:37 addChgroupToRedis($device_id,$proto->channel); $where = array('DeviceAddr'=>$addr); $field = "Mobiles,ExceptContent,SmsInterval,HighTemp,IsUseHT,LowTemp,IsUseLT,SoundLightAlarmInterval,SoundLightDuration,SeveralExceptions,WorkUnitName"; $result = M('dpsb_device')->where($where)->field($field)->find(); $name = $result['WorkUnitName']; unset($result['WorkUnitName']); if(!$result){ //设备不存在 json_fail('DeviceAddr not exists!'); } $arr = array( 'method' => $proto->method.'Resp', 'Addr' => $addr, 'WorkUnitName' => $name, 'timestamp'=>time(date('Y-m-d H:i:s')), 'alarm'=>$result, ); $connection->send($arr); } private function respError( $connection, $message, $proto, $data ){ //判断$proto是否为字符串 if(!is_string($proto)){ $protostr = json_encode($proto); }else{ $protostr = $proto; } log_error($message.' proto = '.$protostr); $array = array( 'success' => false, 'message' => $message, 'data' => $data, ); //判断是否存在method if($proto->method){ $array['method'] = $proto->method . 'Resp'; } $connection->send($array); $connection->close(); } protected function onApiSendControl( $connection, $proto ){ /*返回结果: 1.失败,手动控制命令发送失败,地址码未设置 2.失败,手动控制命令发送失败,手动控制命令格式错误 3.失败,手动控制命令发送失败,设备未在线 4.失败,手动控制命令发送失败,可能设备掉线 5.失败,手动控制命令发送成功,但是设备回应超时 6.失败,手动控制命令发送成功,但是设备回应格式错误 7.失败,手动控制命令发送成功,但是设备回应错误信息 8.成功 */ //检查addr if(!$proto->Addr){ $this->respError($connection,'失败,手动控制命令发送失败,地址码未设置',$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); return; } //给控制app终端发送手动控制信号,并等待回应 $arr = array( "method"=> $proto->method, "Addr"=>$proto->Addr, "channelNumber"=>$proto->channelNumber, "status"=>$proto->status ); $callback = function($errno,$resp) use ($connection){ if($errno == self::ERRNO_SUCCESS){ if(is_object($resp)){ $res = $connection->send($resp); $connection->close(); } else $this->respError($connection,'失败,手动控制命令发送成功,但是设备回应格式错误',$proto,\Zndp\Api\ResponseCode::OTHER_SERVER_ERROR); } else{ $this->respError($connection,'失败,手动控制命令发送失败,'.$this->getErrnoText($errno),$proto,\Zndp\Api\ResponseCode::OTHER_SERVER_ERROR); } }; $this->sendWait($proto->Addr,$arr,'appSendControlResp',$callback,10); } protected function onApiModifyAutoControlInfo( $connection, $proto ){ //检查addr是否为空 if(!$proto->Addr){ $this->respError($connection,'发送失败,地址码未设置',$proto,\Zndp\Api\ResponseCode::NOT_AUTH_DEVICE); return; } //检查channelNumber是否为空 if(!$proto->channelNumber){ $this->respError($connection,'发送失败,设备通道查询不到',$proto,\Zndp\Api\ResponseCode::DEVICE_LOST_CONNECTION); return; } //检查channelNumber是否存在 $device_id = MM('dpsb_device')->where(array('DeviceAddr'=>$proto->Addr))->getField('ID'); $cond = array( 'DeviceId'=>$device_id, 'ChNumber'=>$proto->channelNumber, ); $result = MM('dpsb_channel')->where($cond)->find(); if(!$result){ $this->respError($connection,'发送失败,设备通道未设置',$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); return; } //给app转发自动控制命令 $arr = array( 'method'=>$proto->method, 'Addr'=>$proto->Addr, 'channelNumber'=>$proto->channelNumber, 'man'=>$proto->man, 'refChannel'=>$proto->refChannel, 'TimeEn'=>$proto->TimeEn, 'UpperLimit_Value'=>$proto->UpperLimit_Value, 'UpperLimit_State'=>$proto->UpperLimit_State, 'LowerLimit_Value'=>$proto->LowerLimit_Value, 'LowerLimit_State'=>$proto->LowerLimit_State, 'OnTime1'=>$proto->OnTime1, 'OffTime1'=>$proto->OffTime1, 'OnTime2'=>$proto->OnTime2, 'OffTime2'=>$proto->OffTime2, 'OnTime3'=>$proto->OnTime3, 'OffTime3'=>$proto->OffTime3, 'OnTime4'=>$proto->OnTime4, 'OffTime4'=>$proto->OffTime4, 'OnTime5'=>$proto->OnTime5, 'OffTime5'=>$proto->OffTime5, 'IssueTime'=>(int)$proto->IssueTime, ); $callback = function($errno,$resp) use ($connection,$proto,$device_id){ if($errno == \Zndp\Api\ResponseCode::SEND_SUCCESS){ if(is_object($resp)){ $connection->send($resp); $this->saveModifyAutoData($device_id,$proto,\Zndp\Api\ResponseCode::SEND_SUCCESS); $connection->close(); } else{ $this->respError($connection,'失败,自动控制命令发送成功,但是设备回应格式错误',$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); $this->saveModifyAutoData($device_id,$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); } } else{ $this->respError($connection,'失败,自动控制命令发送失败,'.$this->getErrnoText($errno),$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); $this->saveModifyAutoData($device_id,$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); } }; $this->sendWait($proto->Addr,$arr,'appModifyAutoControlInfoResp',$callback,10); } private function saveModifyAutoData( $device_id, $proto, $connection, $msg ){ $where = array( 'DeviceId'=> $device_id, 'Channel'=>$proto->channelNumber, ); $res = MM('dpsb_policy')->where($where)->find(); if($res){ $saveData = array( 'Man'=> $proto->man, 'RefChannel'=> $proto->refChannel, 'IsTime'=> $proto->TimeEn, 'UpperLimitValue'=> $proto->UpperLimit_Value, 'UpperLimitState'=> $proto->UpperLimit_State, 'LowerLimitValue'=> $proto->LowerLimit_Value, 'LowerLimitState'=> $proto->LowerLimit_State, 'OnTime1'=> $proto->OnTime1, 'OffTime1'=> $proto->OffTime1, 'OnTime2'=> $proto->OnTime2, 'OffTime2'=> $proto->OffTime2, 'OnTime3'=> $proto->OnTime3, 'OffTime3'=> $proto->OffTime3, 'OnTime4'=> $proto->OnTime4, 'OffTime4'=> $proto->OffTime4, 'OnTime5'=> $proto->OnTime5, 'OffTime5'=> $proto->OffTime5, 'SendTime'=> date('Y-m-d H:i:s'), 'SendResult'=> $msg ); $result = MM('dpsb_policy')->createSave($where,$saveData); }else{ $addData = array( 'DeviceId'=> $device_id, 'Channel'=>$proto->channelNumber, 'Man'=> $proto->man, 'RefChannel'=> $proto->refChannel, 'IsTime'=> $proto->TimeEn, 'UpperLimitValue'=> $proto->UpperLimit_Value, 'UpperLimitState'=> $proto->UpperLimit_State, 'LowerLimitValue'=> $proto->LowerLimit_Value, 'LowerLimitState'=> $proto->LowerLimit_State, 'OnTime1'=> $proto->OnTime1, 'OffTime1'=> $proto->OffTime1, 'OnTime2'=> $proto->OnTime2, 'OffTime2'=> $proto->OffTime2, 'OnTime3'=> $proto->OnTime3, 'OffTime3'=> $proto->OffTime3, 'OnTime4'=> $proto->OnTime4, 'OffTime4'=> $proto->OffTime4, 'OnTime5'=> $proto->OnTime5, 'OffTime5'=> $proto->OffTime5, 'SendTime'=> date('Y-m-d H:i:s'), 'SendResult'=> $msg ); $result = MM('dpsb_policy')->createAdd($addData); } if(!$result){ $this->respError($connection,'channelNumber inexistence',$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); return; } } protected function onAppSendRealTimeDeviceData( $connection, $proto ){ //检查imei地址 if(!$proto->imei){ $this->respError($connection,'imei is empty ',$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); return; } if(!$connection->addr){ $this->respError($connection,'addr is empty ',$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); return; } //检查连接池中是否存在addr,不存在添加回去 if(!$this->getFromPool($connection->addr)){ $connection->imei = $proto->imei; $this->addToPool($connection->addr,$connection); $this->logDebug('pool loss,reattach pool,imei = ' . $proto->imei); //log_debug('Data abnormal'); echo 'Data abnormal'.PHP_EOL; } // 将数据更新到数据表中 /* $data = $proto->data; $fix_device_info = MM('dpsb_device')->where(array('DeviceImei'=>$proto->imei))->select(); $device_id = saveDeviceInfo($proto); //$device_id = saveDeviceInfo($proto->imei,$fix_device_info[0]['VersionName'],$connection->addr,$fix_device_info[0]['IccId'],$fix_device_info[0]['CellPhone']); */ $device_id = MM('dpsb_device')->where(array('DeviceImei'=>$proto->imei))->getField('ID'); if(!$device_id){ $this->respError($connection,'device_id is empty ',$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); return; } if(!$proto->data){ //$this->respError($connection,'data is empty ',$proto,\Zndp\Api\ResponseCode::NO_DATA); //log_debug('Data is empty'); echo 'Data is empty'.PHP_EOL; } if(!$proto->gathertime){ $this->respError($connection,'gathertime is empty ',$proto,\Zndp\Api\ResponseCode::NO_DATA); return; } $gathertime = date('Y-m-d H:i:s',$proto->gathertime); //检查数据是否无效 if(isDeviceDataInvalid($proto->data)){ //保存到无效数据表 $device_data = array(); $device_data['Addr'] = $connection->addr; $device_data['DeviceData'] = json_encode($proto->data); $device_data['GatherTime'] = $gathertime; $device_data['AddTime'] = date('Y-m-d H:i:s'); MM('dpsj_invalid')->createAdd($device_data); //$this->respError($connection,'data invelid',$proto,\Zndp\Api\ResponseCode::NO_DATA); //return; } //保存到通道表 $errmsg2 = saveToChannel($device_id,$proto->data,$gathertime); if($errmsg2){ $this->respError($connection,$errmsg2,$proto,\Zndp\Api\ResponseCode::DEVICE_OPRATE_DISALLOWED); return; } //保存数据到设备数据表 if(!$proto->Dedata){ //log_debug('Dedata is empty'); echo 'Dedata is empty'.PHP_EOL; //$this->respError($connection,'Dedata is empty ',$proto,\Zndp\Api\ResponseCode::NO_DATA); //return; } $dedata = $proto->Dedata; $errmsg1 = saveToDevice($device_id,$dedata,$gathertime); if($errmsg1){ $this->respError($connection,$errmsg1,$proto,\Zndp\Api\ResponseCode::DEVICE_OPRATE_DISALLOWED); return; } //保存到通道数据表 $errmsg3 = saveToChannelData($device_id,$proto->data,$gathertime); if($errmsg3){ $this->respError($connection,$errmsg3,$proto,\Zndp\Api\ResponseCode::DEVICE_OPRATE_DISALLOWED); return; } // 检查告警,并推送到Redis 2019年1月29日10:09:59 pushAlarmToRedis($device_id,$proto->data,$gathertime); // 推送数据到农科院 $res = send_nongke($connection->addr,$proto->data,$gathertime); //$res = send_single_nongke($connection->addr,$data,$gathertime); $arr = array( 'method' => $proto->method.'Resp', "success"=>true, "message"=>"ok", "addtime"=>time(), ); $connection->send($arr); } protected function onAppHeartbeat( $connection, $proto ){ //直接返回心跳 $arr = array( 'success'=>true ); $connection->send($arr); } protected function onAppSendControlResp( ){ } protected function onAppModifyAutoControlInfoResp( ){ } protected function onApiUploadDebug( $connection, $proto ){ if(!$proto->Addr){ $this->respError($connection,'失败,地址码未设置',$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); return; } //给控制app终端发送手动控制信号,并等待回应 $arr = array( "method"=> $proto->method, "Addr"=>$proto->Addr, ); $callback = function($errno,$resp) use ($connection){ if($errno == self::ERRNO_SUCCESS){ if(is_object($resp)){ $res = $connection->send($resp); $connection->close(); } else $this->respError($connection,'失败,调试不存在',$proto,\Zndp\Api\ResponseCode::OTHER_SERVER_ERROR); } else{ $this->respError($connection,'失败,调试发送失败'.$this->getErrnoText($errno),$proto,\Zndp\Api\ResponseCode::OTHER_SERVER_ERROR); } }; $this->sendWait($proto->Addr,$arr,'appUploadDebugResp',$callback,10); } protected function onAppUploadDebugResp( ){ } protected function onApiReboot( $connection, $proto ){ if(!$proto->Addr){ $this->respError($connection,'失败,地址码未设置',$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); return; } //给控制app终端发送手动控制信号,并等待回应 $arr = array( "method"=> $proto->method, "Addr"=>$proto->Addr, ); $callback = function($errno,$resp) use ($connection){ if($errno == self::ERRNO_SUCCESS){ if(is_object($resp)){ $res = $connection->send($resp); $connection->close(); } else $this->respError($connection,'失败,重启不存在',$proto,\Zndp\Api\ResponseCode::OTHER_SERVER_ERROR); } else{ $this->respError($connection,'失败,重启发送失败'.$this->getErrnoText($errno),$proto,\Zndp\Api\ResponseCode::OTHER_SERVER_ERROR); } }; $this->sendWait($proto->Addr,$arr,'appRebootResp',$callback,10); } protected function onApiUpgrade( $connection, $proto ){ if(!$proto->Addr){ $this->respError($connection,'失败,地址码未设置',$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); return; } //给控制app终端发送手动控制信号,并等待回应 $arr = array( "method"=> $proto->method, "Addr"=>$proto->Addr, ); $callback = function($errno,$resp) use ($connection){ if($errno == self::ERRNO_SUCCESS){ if(is_object($resp)){ $res = $connection->send($resp); $connection->close(); } else $this->respError($connection,'失败,升级不存在',$proto,\Zndp\Api\ResponseCode::OTHER_SERVER_ERROR); } else{ $this->respError($connection,'失败,升级发送失败'.$this->getErrnoText($errno),$proto,\Zndp\Api\ResponseCode::OTHER_SERVER_ERROR); } }; $this->sendWait($proto->Addr,$arr,'appUpgradeResp',$callback,10); } protected function onAppUpgradeResp( ){ } protected function onAppRebootResp( ){ } protected function onApiSysReboot( $connection, $proto ){ if(!$proto->Addr){ $this->respError($connection,'失败,地址码未设置',$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); return; } //给控制app终端发送手动控制信号,并等待回应 $arr = array( "method"=> $proto->method, "Addr"=>$proto->Addr, ); $callback = function($errno,$resp) use ($connection){ if($errno == self::ERRNO_SUCCESS){ if(is_object($resp)){ $res = $connection->send($resp); $connection->close(); } else $this->respError($connection,'失败,系统重启不存在',$proto,\Zndp\Api\ResponseCode::OTHER_SERVER_ERROR); } else{ $this->respError($connection,'失败,系统重启发送失败'.$this->getErrnoText($errno),$proto,\Zndp\Api\ResponseCode::OTHER_SERVER_ERROR); } }; $this->sendWait($proto->Addr,$arr,'appSysReboot',$callback,10); } public function onAppSysRebootResp( ){ } protected function onFarmlandNum( $connection, $proto ){ if( !$proto->addr ){ $this->respError($connection,'失败,设置大棚编号命令发送失败,地址码未设置',$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); return; } if( $proto->channelGroup === ''){ $this->respError($connection,'失败,设置大棚编号命令发送失败,通道组未设置',$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); return; } //给控制app终端发送大棚编号,并等待回应 $arr = array( "method" => $proto->method, "channelGroup" => (int)$proto->channelGroup, "number" => $proto->number ); $callback = function($errno,$resp) use ($connection){ if($errno == self::ERRNO_SUCCESS){ if(is_object($resp)){ $res = $connection->send($resp); $connection->close(); }else{ $this->respError($connection,'失败,设置大棚编号命令发送成功,但是设备回应格式错误',$proto,\Zndp\Api\ResponseCode::OTHER_SERVER_ERROR); } }else{ $this->respError($connection,'失败,设置大棚编号命令发送失败,'.$this->getErrnoText($errno),$proto,\Zndp\Api\ResponseCode::OTHER_SERVER_ERROR); } }; $this->sendWait($proto->addr,$arr,'farmlandNumResp',$callback,10); } protected function onFarmlandNumResp( $connection, $resp ){ //var_dump($connection); var_dump($resp); } protected function onControlFinish( $connection, $proto ){ /* { "method" : "controlFinish", "channelGroup" : 0, // 设备通道组 "channelNum" : 1, // 卷膜机左/右 "success" : true, // 操作成功,失败 "isman" : 0, // 操作类型:(自动-0,手动-1) "operatTime" : 1552353910, // 操作时间戳 "operat" : 1, // 当前操作,停止-0,打开-1,关闭-2,全打开-3,全关闭-4 } */ // 保存操作日志 // 获取设备id $where = array('DeviceAddr' => $connection->addr); $device_id = MM('dpsb_device')->where($where)->getField('ID'); if(!$device_id){ $this->respError($connection,'device_id is empty ',$proto,\Zndp\Api\ResponseCode::DEVICE_NOT_EXISTS); return; } // 获取大棚id $where = array('DeviceId'=>$device_id,'ChGroup'=>$proto->channelGroup); $farmland_id = MM('dpsb_chgroup')->where($where)->getField('FarmlandId'); // 操作描述 $control_status = array('自动控制','手动控制'); $operat_status = array('停止','打开','关闭','全打开','全关闭'); $operat_content = $control_status[$proto->isman] .'-'. $operat_status[$proto->operat]; $log_data = array( 'ID' => create_guid(), 'IsMan' => $proto->isman, 'AddTime' => date('Y-m-d H:i:s',$proto->operatTime), 'DeviceId' => $device_id, 'FarmlandId' => $farmland_id, 'ChannelNumber' => $proto->channelNum, 'LogContent' => $operat_content, 'OperResult' => $proto->success ? '成功':'失败', ); // 如果是控制台手动操作的,记录操作用户 if( $proto->userName ){ //获取UserId $where = array('UserName'=>$proto->userName); $log_data['UserId'] = MM('uc_user')->where($where)->getField('ID'); } $result = MM('dpsj_oplog')->createAdd($log_data); $arr = array( 'method' => $proto->method.'Resp', 'message' => $result ? 'success':'fail', 'success' => (bool)$result ); $connection->send($arr); } }