123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503 |
- <?php
- class RcgjfwXqIndexAction extends Action {
-
-
- public function index( ){
- if (!C('rcgjfw.人车标签_允许的最大时间差')){
- echo '常量【人车标签_允许的最大时间差】未定义'.PHP_EOL;
- return;
- }
- if (!C('rcgjfw.被盗告警_间隔时间')){
- echo '常量【被盗告警_间隔时间】未定义'.PHP_EOL;
- return;
- }
- if (!C('rcgjfw.车辆标签_rssi阀值')){
- echo '常量【车辆标签_rssi阀值】未定义'.PHP_EOL;
- return;
- }
- if (!C('rcgjfw.车主标签_rssi阀值')){
- echo '常量【车辆标签_rssi阀值】未定义'.PHP_EOL;
- return;
- }
- Vendor('Workerman352.Autoloader');
- $tcp_worker = new Workerman\Worker("tcp://0.0.0.0:20160");
- $tcp_worker->count = 1;
- $tcp_worker->onWorkerStart = function($worker){
-
- };
- $tcp_worker->onConnect = function($connection){
- $this->onConnect($connection);
- };
- $tcp_worker->onMessage = function($connection,$data){
- $this->onMessage($connection,$data);
- };
- $tcp_worker->onClose = function($connection){
- $this->onClose($connection);
- };
- //实例化信号处理类
- $this->rfid_proto = new Rlgs\Proto\RfidStation2();
-
- $this->rchy_alarm_list = Redis("rchy_alarm_list","queue");
- $this->redis_vsignal = Redis("rchy_vsignal_{no}","zset")->prefix('rchy_vsignal_');
- //$this->cache = \Rchy\Cache\RedisCache::getInstance();
-
- Workerman\Worker::runAll();//保持运行
-
- }
-
-
- private function onMessage( $connection, $data ){
- $connection->m_packet .= $data;
- }
-
-
- private function onConnect( $connection ){
- echo PHP_EOL . $connection->id . ' connected'. PHP_EOL;
- }
-
-
- private function onClose( $connection ){
- //记录数据包文本
- $packet_text = $this->rfid_proto->tcp_hex2str($connection->m_packet,true) ;
- //$this->rfid_proto->tcp_log($connection->id . ' closed ' . $packet_text);
- //echo 'packet_text => '.$packet_text.PHP_EOL;
- //解析消息体
- $packet = $this->rfid_proto->tcp_str2bin($packet_text);
- $result = $this->rfid_proto->tcp_unpack_msg($packet);
- if(! $result['Success'] ){
- echo 'unpack packet failed'.PHP_EOL;
- $this->rfid_proto->decode_error_log('unpack_fail','unpack packet failed ,result : '.json_encode($result));
- return;
- }
- //echo 'decode_data => '.json_encode($result).PHP_EOL;
- //记录基站数据包
- //$this->rfid_proto->decode_packet_log($result['StationCode'],$result['StationCode'].' => '.$packet_text);
- if (!$result['StationCode']){
- echo 'StationCode is empty!'.PHP_EOL;
- $this->rfid_proto->decode_error_log('unpack_fail','StationCode is empty! ');
- return false;
- }
-
- if (!$result['VehicleList']){
- echo 'VehicleList is empty!'.PHP_EOL;
- return ;
- }
-
- //检查是否有效基站
- $station_info = \Rchy\Cache\RedisCache::getStationInfo($result['StationCode']);
- if(!$station_info){
- $this->rfid_proto->decode_error_log('unpack_fail','getStationInfo failed ,StationCode : '.$result['StationCode']);
- return false;
- }
-
- //更新车主标签时间
- echo '======= updateRfidTime start ======='.$connection->id.PHP_EOL;
- $this->updateRfidTime($result);
- echo '======= updateRfidTime over ======='.$connection->id.PHP_EOL;
- //添加报警
- echo '======= addAlarm start ======='.$connection->id.PHP_EOL;
- $this->addAlarm($result);
- echo '======= addAlarm over ======='.$connection->id.PHP_EOL;
- /*
- //轨迹包redis主库
- $redis_raw_packet = Redis("fdqu_raw_packet","queue");
- $redis_raw_packet->push($packet_text);
-
- //数据解包
- $result = $this->unpackMsg($packet_text);
-
- //生成车辆轨迹日志
- $this->addTcpLog($result);
- */
- }
-
-
- private function addTcpLog( $result ){
- //一个基站一个日志文件
- $this->rfid_proto->station_route_log('tcp',$result);
- //一个车辆一个日志文件
- $this->rfid_proto->vehicle_route_log('tcp',$result);
-
- }
-
-
- private function unpackMsg( $packet_text ){
- $packet = $this->rfid_proto->tcp_str2bin($packet_text);
- if(!$packet){
- echo 'parse packet failed.'.PHP_EOL;
- $this->rfid_proto->tcp_error_log('parse_fail','parse packet failed ,packet_text : '.$packet_text);
- return false;
- }
- $result = $this->rfid_proto->tcp_unpack_msg($packet);
- if(! $result['Success'] ){
- echo 'unpack fail: ' . $result['Message'].PHP_EOL;
- $this->rfid_proto->tcp_error_log('unpack_fail',$result);
- return false;
- }
- return $result;
- }
-
-
- private function addAlarm( $result ){
- //获取当前所有车主rfid的rssi数据
- $chezhu_rfids = array();
- foreach ($result['VehicleList'] as $key => $row){
- $chezhu_info = \Rchy\Cache\RedisCache::getCheZhuInfo($row['VehicleNumber']);
- if(!$chezhu_info){
- continue;
- }
- $chezhu_rfids[$row['VehicleNumber']]['Rssi'] = $row['rssi'];
- $chezhu_rfids[$row['VehicleNumber']]['SignalCount'] = $row['SignalCount'];
- }
- //var_dump($result['VehicleList']);
- foreach ($result['VehicleList'] as $key => $row){
- $row['StationCode'] = $result['StationCode'];
- if (!$row['VehicleNumber']){
- echo 'VehicleNumber empty!'.PHP_EOL;
- continue;
- }
-
- //获取车辆信息
- $vehicle_info = \Rchy\Cache\RedisCache::getVehicleInfo($row['VehicleNumber']);
- //车辆不存在跳过
- if (!$vehicle_info){
- //echo 'vehicle not existed, vehilce_number = '.$row['VehicleNumber'].', rssi = '.$row['rssi'].PHP_EOL;
- continue;
- }
- //未绑定车主rfid跳过
- if (!$vehicle_info['CheZhuRfid']){
- echo 'vehicle not kaihu, vehilce_number: '.$row['VehicleNumber'].', rssi = '.$row['rssi'].PHP_EOL;
- continue;
- }
- echo 'VehicleNumber: '.$row['VehicleNumber'].',rssi = '.$row['rssi'].PHP_EOL;
-
-
- //车辆标签
- $vehicle_no = strtolower($row['VehicleNumber']);
- //末次信号(改用本地缓存了)
- //$last_signal_info = $this->redis_vsignal->table($vehicle_no)->max();
-
- //获取最近一段时间内所有rssi,求均值
- $avgRssi = $this->getAvgRssi($row);
- if($avgRssi === false){
- echo 'getAvgRssi failed! VehicleNumber = '.$row['VehicleNumber'].PHP_EOL;
- continue;
- }
- //车辆rssi信号弱的,过滤掉,防止收到车信号的时候,没有收到车主信号,从而误报
- if ($avgRssi > C('rcgjfw.车辆标签_rssi阀值')){
- echo 'avgRssi > '.C('rcgjfw.车辆标签_rssi阀值').', avgRssi = '.$avgRssi.', VehicleNumber = '.$row['VehicleNumber'].PHP_EOL;
- continue;
- }
-
- //有效信号加入到 rchy_vsignal_{no} 表
- $signal = array(
- 'StationCode' => $row['StationCode'],
- 'Rssi' => $row['rssi'],
- 'Timestamp' => $row['Timestamp']
- );
-
- //获取最近一次的信号信息
- $last_signal_info = S('last_signal_info'.$row['VehicleNumber']);
- //更新最近一次的信号信息
- S('last_signal_info'.$row['VehicleNumber'], $signal, 24*60*60);
-
- $alarm_info = array();
- $alarm_info['VehicleNumber'] = $row['VehicleNumber'];
- $alarm_info['AlarmTime'] = time();
- $alarm_info['OnlineTime'] = $row['OnlineTime'];
- $alarm_info['VehicleRssi'] = $row['rssi'];
- $alarm_info['VehicleSignalCount'] = $row['SignalCount'];
- $alarm_info['CheZhuRssi'] = $chezhu_rfids[$vehicle_info['CheZhuRfid']]['Rssi'];//车主或者授权车主信号强度,这里还需要完善
- $alarm_info['CheZhuSignalCount'] = $chezhu_rfids[$vehicle_info['CheZhuRfid']]['SignalCount'];
- $alarm_info['StationCode'] = $row['StationCode'];
- //检查车辆经过时,在限定的时间内,是否有接收到任一授权标签信号
- $is_stolen = $this->checkVehicleStatus($vehicle_info['CheZhuRfid'], $row);
- $cur_time = time();
- //检查是否被盗报警
- if ( $is_stolen ){
- $alarm_info['AlarmType'] = \Rchy\Enum\AlarmType::STOLEN;
- //上次被盗告警时间
- $latest_stolen_alarm_time = S('latest_stolen_alarm_time_'.$row['VehicleNumber']);
- //避免频繁告警检测
- if ($latest_stolen_alarm_time && $cur_time - $latest_stolen_alarm_time <= C('rcgjfw.被盗告警_间隔时间')){
- echo '车辆'.$row['VehicleNumber'].'刚被盗告警过,跳过告警! latest_stolen_alarm_time = '.$latest_stolen_alarm_time.', cur_time = '.$cur_time.PHP_EOL;
- return ;
- }
- echo 'VehicleNumber:'.$row['VehicleNumber'].', 告警类型: 被盗告警'.PHP_EOL;
-
- //更新本次被盗告警时间
- S('latest_stolen_alarm_time_'.$row['VehicleNumber'], $cur_time);
-
- }else{
-
- //上次告警时间
- $latest_pass_alarm_time = S('latest_pass_alarm_time_'.$row['VehicleNumber']);
- //避免频繁告警检测
- if ($latest_pass_alarm_time && $cur_time - $latest_pass_alarm_time <= C('rcgjfw.过车告警_间隔时间')){
- echo '车辆'.$row['VehicleNumber'].'刚过车告警过,跳过! 已过车告警'.$pass_alarm_count.'次, latest_pass_alarm_time = '.$latest_pass_alarm_time.', cur_time = '.$cur_time.PHP_EOL;
- return ;
- }
- $alarm_info['AlarmType'] = \Rchy\Enum\AlarmType::PASS;
- echo 'pass_alarm_count = '.$pass_alarm_count.', last_chezhu_signal_time = '.$last_signal_info['Timestamp'].', now = '.$row['Timestamp']. PHP_EOL;
- echo 'VehicleNumber:'.$row['VehicleNumber'].', 告警类型: 过车告警'.PHP_EOL;
- //记录本次过车告警时间
- S('latest_pass_alarm_time_'.$row['VehicleNumber'], $cur_time);
- }
- $this->rchy_alarm_list->push(json_encode($alarm_info));
- echo '添加告警成功, VehicleNumber:'.$row['VehicleNumber'].', AlarmType: '.$alarm_info['AlarmType'].PHP_EOL;
- //echo 'alarm_info: '.json_encode($alarm_info).PHP_EOL;
-
-
-
-
- }
- }
-
-
- private function updateRfidTime( $result ){
-
- foreach($result['VehicleList'] as $key => $row){
- $row['StationCode'] = $result['StationCode'];
- if(!$row['VehicleNumber']){
- //echo 'VehicleNumber not existed, VehicleNumber: '.$row['VehicleNumber'].PHP_EOL;
- continue;
- }
- //检查车主标签是否有效,无效跳过,有效的更新上报信息
- $vehicle_info = \Rchy\Cache\RedisCache::getCheZhuInfo($row['VehicleNumber']);
- if(!$vehicle_info){
- continue;
- }
- echo 'CheZhuRfid = '.$row['VehicleNumber'].', rssi = '.$row['rssi'].', time:'.date('Y-m-d H:i:s',$row['Timestamp']).PHP_EOL;
- //如果基站时间不准确,用服务器时间
- if($row['Timestamp'] < time()-3600){
- $row['Timestamp'] = time();
- }
- //获取最近一段时间内所有rssi,求均值
- $avgRssi = $this->getAvgRssi($row);
- if($avgRssi === false){
- echo 'getAvgRssi failed! CheZhuRfid = '.$row['VehicleNumber'].PHP_EOL;
- continue;
- }
- //检查车主标签rssi,过滤掉弱信号
- if ($avgRssi > C('rcgjfw.车主标签_rssi阀值')){
- echo 'avgRssi > '.C('rcgjfw.车主标签_rssi阀值').', avgRssi = '.$avgRssi.', CheZhuRfid = '.$row['VehicleNumber'].PHP_EOL;
- continue;
- }
- echo 'avgRssi = '.$avgRssi.', CheZhuRfid = '.$row['VehicleNumber'].PHP_EOL;
-
- $info = array(
- 'Timestamp' => $row['Timestamp'],
- 'StationCode' => $row['StationCode'],
- 'Rssi' => $row['rssi']
- );
- //更新车主RFID上报信息
- S('last_chezhu_rfid_'.$row['VehicleNumber'], $info, 60*60*24);
- //echo 'last_chezhu_rfid_'.$row['VehicleNumber'] .PHP_EOL;
- //var_dump(S('last_chezhu_rfid_'.$row['VehicleNumber']));
-
- //echo '更新车主标签上报信息成功,CheZhuRfid: '.$row['VehicleNumber'].', 上报时间:'.date('Y-m-d H:i:s',$row['Timestamp']).', rssi: '.$row['rssi'].PHP_EOL;
-
- }
- }
-
-
- private function checkVehicleStatus( $chezhu_rfid, $row ){
- if(!$chezhu_rfid){
- echo 'checkVehicleStatus failed, chezhu_rfid is empty!'.PHP_EOL;
- return false;
- }
- if(!$row){
- echo 'checkVehicleStatus failed, row is empty!'.PHP_EOL;
- return false;
- }
-
- //获取车辆已授权车主标签
- $all_rfids = \Rchy\Cache\RedisCache::getVehicleAuthors($row['VehicleNumber']);
- if(!$all_rfids){
- $all_rfids = array();
- }
- //加入车主标签
- if(!in_array($chezhu_rfid,$all_rfids)){
- array_push($all_rfids,$chezhu_rfid);
- }
-
- $is_stolen = true;
- foreach ($all_rfids as $rfid){
- //获取授权车主标签上报信息
- $last_rfid_info = S('last_chezhu_rfid_'.$rfid);
- //var_dump($last_rfid_info);
- $last_rfid_time = $last_rfid_info['Timestamp'];
- $rfid_pass_station = $last_rfid_info['StationCode'];
- echo 'chezhu_rfid = '.$rfid.', now = '.$row['Timestamp'].', last_rfid_time = '.$last_rfid_time.', rfid_pass_station = '. $rfid_pass_station . PHP_EOL;
- //车辆和授权车主同时出现在同一个小区门口,则认为是过车告警
- if ( $last_rfid_time && abs($row['Timestamp']-$last_rfid_time) < C('rcgjfw.人车标签_允许的最大时间差') && $rfid_pass_station == $row['StationCode']){
- $is_stolen = false;
- break;
- }
- }
- echo 'all_rfids:'.PHP_EOL;
- var_dump($all_rfids);
-
- return $is_stolen;
- }
-
-
- private function checkVehicleDirection( $vehicle_no, $now ){
- //开发中。。。
- return false;
- if(!$vehicle_no){
- echo 'checkVehicleDirection failed, vehicle_no is empty!'.PHP_EOL;
- return false;
- }
- if(!$now){
- echo 'checkVehicleDirection failed, now is empty!'.PHP_EOL;
- return false;
- }
- //获取最近一段时间内的信号
- $cond = array($now-60,$now);
- $signal_list = $this->redis_vsignal->table($vehicle_no)->where($cond)->select();
- //查询结果默认是按时间升序,这里翻转一下
- $signal_list = array_reverse($signal_list);
- if(!$signal_list){
- echo 'checkVehicleDirection failed,signal_list is empty!'.PHP_EOL;
- return false;
- }
-
- //最后一个信号点所在的基站
- $last_station = $signal_list[0]['StationCode'];
- if(!$last_station){
- echo 'checkVehicleDirection failed,last_station is empty!'.PHP_EOL;
- return false;
- }
- //获取一段时间内同一基站连续的几个信号强度点
- $rssi_list = array();
- foreach($signal_list as $key=>$row){
- $signal = json_decode($key,true);
- if(!$signal){
- echo 'json_decode error'.PHP_EOL;
- return false;
- }
- if($last_station != $signal['StationCode']){
- echo 'is not the last_station rssi,stop push! last_station = '.$last_station.', cur_station = '.$signal['StationCode'].PHP_EOL;
- break;
- }
- $rssi_list[] = $signal['rssi'];
- }
-
- if( count($rssi_list)<3 ){
- echo 'checkVehicleDirection failed,count($rssi_list)<3 !! count($rssi_list) = '.count($rssi_list).PHP_EOL;
- return false;
- }
-
- //<信号一直递增或者一直递减的,车辆方向暂时不好判断>
- //判断车辆rssi信号强度是否递减(此时,时间是降序)
- $is_rssi_decrease = $this->isRssiDecrease($rssi_list, count($rssi_list));
- if($is_rssi_decrease){
- echo '检测到车辆rssi信号强度递增,车辆正在靠近基站!StationCode = '.$last_station.PHP_EOL;
- return false;
- }
- //如果rssi先逐渐增强,后逐渐减弱,且峰值右侧第一个信号大于峰值左侧第一个信号,则认为是进入小区
-
- //如果rssi先逐渐增强,后逐渐减弱,且峰值右侧第一个信号小于峰值左侧第一个信号,则认为是走出小区
-
- echo '判断不出车辆运动方向!VehicleNumber = '. $vehicle_no .PHP_EOL;
- return false;
- }
-
-
- private function isRssiDecrease( $arr, $len ){
- if ($len == 1)
- return true;
-
- return ($arr[$len - 2] >= $arr[$len - 1]) && $this->isRssiDecrease($arr, $len-1);
- }
-
-
- private function isRssiDrab( $arr, $len ){
- if(!$arr){
- echo 'isRssiDrab failed, arr is empty!!'.PHP_EOL;
- return false;
- }
-
- if(!$len){
- echo 'isRssiDrab failed, len is empty!!'.PHP_EOL;
- return false;
- }
-
- if($this->isRssiIncrease($arr, $len)){
- echo 'rssi increase'.PHP_EOL;
- return true;
- }
-
- if($this->isRssiDecrease($arr, $len)){
- echo 'rssi decrease'.PHP_EOL;
- return true;
- }
-
- echo 'rssi is not drab '.PHP_EOL;
- return false;
- }
-
-
- private function isRssiIncrease( $arr, $len ){
- if ($len == 1)
- return true;
-
- return ($arr[$len - 2] <= $arr[$len - 1]) && $this->isRssiIncrease($arr, $len-1);
- }
-
-
- private function getAvgRssi( $data ){
- $rfid = $data['VehicleNumber'];
- if(!$rfid){
- echo 'getAvgRssi failed ,VehicleNumber not existed!'.PHP_EOL;
- return false;
- }
- $station_code = $data['StationCode'];
- if(!$station_code){
- echo 'getAvgRssi failed ,StationCode not existed!'.PHP_EOL;
- return false;
- }
-
- $key = $station_code.'_'.$rfid;
- //添加新车辆轨迹点
- $route_point = array('Rfid'=>$rfid,'Time'=>$data['Timestamp'],'Rssi'=>$data['rssi']);
- $signal_data = array(json_encode($route_point) => $data['Timestamp']);
- $this->redis_vsignal->table($key)->add($signal_data);
- //查询时间窗内,所有rssi
- $interval = C('rcgjfw.信号均值_采集时间窗');
- if(!$interval){
- $interval = 4;
- }
- $start = $data['Timestamp']-$interval;
- $where = array( $start,$data['Timestamp']);
- $list = $this->redis_vsignal->table($key)->where($where)->select();
-
- //计算平均值
- $sum = 0;
- $count = 0;
- $info = array();
- foreach($list as $signal => $time){
- $signal = json_decode($signal,true);
- $sum += $signal['Rssi'];
- $count++;
- $info[$time] = $signal['Rssi'];
- }
- echo 'key:'.$key.', rssi_pool:'.json_encode($info).PHP_EOL;
-
- if(!$count){
- echo 'getAvgRssi failed ,rssi_pool empty!'.PHP_EOL;
- return false;
- }
- $avgRssi = round($sum/$count);
- echo 'rfid: '.$rfid.', station_code: '.$station_code.', avgRssi = '.$avgRssi.PHP_EOL;
- return $avgRssi;
- }
-
- }
|