common.php 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453
  1. <?php
  2. // 应用公共文件
  3. use think\facade\Env;
  4. use think\facade\Db;
  5. use Aliyun\OTS\Consts\OperationTypeConst;
  6. use Aliyun\OTS\Consts\PrimaryKeyTypeConst;
  7. use Aliyun\OTS\Consts\RowExistenceExpectationConst;
  8. use Aliyun\OTS\OTSClient;
  9. use PDO;
  10. /**
  11. * 查询Gps股轨迹 表格存储
  12. */
  13. function queryTableStoreGpsRoute($options){
  14. if(!isset($options['device_number']) && $options['device_number'] !=''){
  15. return array('success'=>false,'message'=>'缺少设备号');
  16. }
  17. $device_number=$options['device_number'];
  18. if(!isset($options['start_time']) && $options['start_time']>0){
  19. return array('success'=>false,'message'=>'缺少起始时间');
  20. }
  21. $start_time=$options['start_time'];
  22. if(!isset($options['end_time']) && $options['end_time']>0){
  23. $end_time=time();
  24. }else{
  25. $end_time=$options['end_time'];
  26. }
  27. if(!isset($options['table_name']) && !$options['table_name']){
  28. return array('success'=>false,'message'=>'缺少表名参数');
  29. }
  30. $table_name=$options['table_name'];
  31. $table_config=Db::table('sys_config')->where('type','table_store')->column('fieldValue','field');
  32. if(!isset($table_config['EndPoint']) || !isset($table_config['AccessKeyID']) || !isset($table_config['AccessKeySecret']) || !isset($table_config['InstanceName'])){
  33. return array('success'=>false,'message'=>'未配置表格存储');
  34. }
  35. $otsClient = new OTSClient (array (
  36. 'EndPoint' => $table_config['EndPoint'],
  37. 'AccessKeyID' => $table_config['AccessKeyID'],
  38. 'AccessKeySecret' => $table_config['AccessKeySecret'],
  39. 'InstanceName' => $table_config['InstanceName'],
  40. ));
  41. $otsClient->getClientConfig()->debugLogHandler = null;
  42. $otsClient->getClientConfig()->errorLogHandler = null;
  43. // var_dump($otsClient);
  44. ini_set('memory_limit', '512M');
  45. $startPK = array (
  46. array('DeviceNumber',$device_number),
  47. array('Timestamp', $start_time)
  48. // array('Timestamp', 1620885120)
  49. );
  50. $endPK = array (
  51. array('DeviceNumber', $device_number),
  52. array('Timestamp', $end_time)
  53. // array('Timestamp', 1620885441)
  54. );
  55. if(isset($options['limit']) && $options['limit']>0){
  56. $limit = $options['limit'];
  57. }else{
  58. $limit = 5500;
  59. }
  60. $rows=[];
  61. while (! empty ($startPK) && $limit > 0) {
  62. $request = array (
  63. 'table_name' => $table_name,
  64. 'max_versions' => 1,
  65. 'direction' => 'BACKWARD', // 方向可以为 FORWARD 或者 BACKWARD
  66. 'inclusive_start_primary_key' => $endPK, // 开始主键
  67. 'exclusive_end_primary_key' => $startPK, // 结束主键
  68. 'limit' => $limit
  69. );
  70. $response = [];
  71. try {
  72. $response = $otsClient->getRange($request);
  73. } catch (\Exception $e) {
  74. var_dump($e->getMessage());
  75. }
  76. if (!isset($response['rows'])){
  77. return CatchResponse::success([]);
  78. }
  79. foreach ($response['rows'] as $rowData) {
  80. // $str=($limit-4000)/2000;
  81. $item=[];
  82. foreach($rowData['primary_key'] as $keyItem){
  83. $item[$keyItem[0]]=$keyItem[1];
  84. }
  85. foreach($rowData['attribute_columns'] as $colItem){
  86. $item[$colItem[0]]=$colItem[1];
  87. }
  88. $item['PassTime']=date('Y-m-d H:i:s',$item['Timestamp']);
  89. $rows[]=$item;
  90. $limit --;
  91. // 处理每一行数据
  92. }
  93. $startPK = $response['next_start_primary_key'];
  94. // 如果 next_start_primary_key 不为空并且 limit > 0 则循环继续
  95. }
  96. // if(!$rows){
  97. // return array('success'=>true,'message'=>'查询成功','data'=>[]);
  98. // }
  99. // $arr= [];
  100. // foreach($rows as $k=> $v){
  101. // // if( !isset($v['Latitude']) || !isset($v['Longitude']) || $v['Latitude']<0.065 || $v['Longitude']<0.065){
  102. // // continue;
  103. // // }
  104. // array_push($arr, $rows[$k]);
  105. // }
  106. return array('success'=>true,'message'=>'查询成功','data'=>$rows);
  107. }
  108. /**
  109. * 添加轨迹到表格存储
  110. * @param $data 存储数据
  111. * @param $options 配置信息
  112. */
  113. function addGpsRouteToTs($data,$options){
  114. if(!isset($options['table_name']) && !$options['table_name']){
  115. return array('success'=>false,'message'=>'缺少表名参数');
  116. }
  117. // 判断主键字段是否存在
  118. if(!isset($options['primary_key']) || !$options['primary_key']){
  119. return array('success'=>false,'message'=>'primary_key not exists');
  120. }
  121. $primary_keys = explode(',',$options['primary_key']);
  122. if(empty($primary_keys)){
  123. return array('success'=>false,'message'=>'primary_key format error,right format is a String like:"Key1,Key2"');
  124. }
  125. $table_name=$options['table_name'];
  126. $table_config=Db::table('sys_config')->where('type','table_store')->column('fieldValue','field');
  127. if(!isset($table_config['EndPoint']) || !isset($table_config['AccessKeyID']) || !isset($table_config['AccessKeySecret']) || !isset($table_config['InstanceName'])){
  128. return array('success'=>false,'message'=>'未配置表格存储');
  129. }
  130. $otsClient = new OTSClient (array (
  131. 'EndPoint' => $table_config['EndPoint'],
  132. 'AccessKeyID' => $table_config['AccessKeyID'],
  133. 'AccessKeySecret' => $table_config['AccessKeySecret'],
  134. 'InstanceName' => $table_config['InstanceName'],
  135. ));
  136. //
  137. $otsClient->getClientConfig()->debugLogHandler = null; //关闭日志函数打印
  138. $otsClient->getClientConfig()->errorLogHandler = null;
  139. $rows=array();
  140. foreach($data as $value){
  141. $fullKey = true; // 主键齐全
  142. $primary_info = array(); // 主键信息
  143. $attribute_info=array();
  144. // 跳过主键不全的数据
  145. foreach($primary_keys as $key){
  146. if(!$value[$key]){
  147. $fullKey = false;
  148. break;
  149. }
  150. // $primary_info[$key] = $value[$key];
  151. $primary_info[] = [$key,$value[$key]];
  152. unset($value[$key]);
  153. }
  154. if(!$fullKey){
  155. continue;
  156. }
  157. //转换多余参数 键值对格式
  158. foreach($value as $key=>$val){
  159. $attribute_info[]=[$key,$val];
  160. }
  161. $row= array ( // 第一行
  162. 'operation_type' => OperationTypeConst::CONST_PUT, //操作是PUT
  163. 'condition' => RowExistenceExpectationConst::CONST_IGNORE,
  164. 'primary_key' => $primary_info,
  165. 'attribute_columns' => $attribute_info
  166. );
  167. $rows[]=$row;
  168. }
  169. $request = array (
  170. 'tables' => array (
  171. array (
  172. 'table_name' => $table_name,
  173. 'rows' =>$rows,
  174. )
  175. )
  176. );
  177. // $response =[];
  178. $response = $otsClient->batchWriteRow($request);
  179. $res=processWriteError($response);
  180. return $res;
  181. }
  182. /**
  183. * 判断服务器返回是否有错误
  184. */
  185. function processWriteError($response){
  186. $hasError = 0;
  187. foreach ($response['tables'] as $tableData) {
  188. // 处理这个表下的PutRow返回的结果
  189. $putRows = $tableData['rows'];
  190. foreach ($putRows as $rowData) {
  191. if ($rowData['is_ok']) {
  192. continue;
  193. } else {
  194. $hasError++;
  195. debug_log('addGpsToTsError',$tableData['table_name'].' error_code: '.$rowData['error']['code'].' message: '.$rowData['error']['message']);
  196. //print "Error: {$rowData['error']['code']} {$rowData['error']['message']}\n";
  197. }
  198. }
  199. }
  200. if($hasError > 0){
  201. return array('success'=>false);
  202. }else{
  203. return array('success'=>true);
  204. }
  205. }
  206. /**
  207. * 检测是否进出围栏
  208. * @param $info 定位信息
  209. * @param $device_info 设备信息
  210. */
  211. function checkIsCrollFence($info, $device_info){
  212. $log_filename = 'pushFenceMsgToYys';
  213. $app_id = Env::get('wechat.wechat_appid');
  214. $appsecret =Env::get('wechat.wechat_appsecret');
  215. $template_id = Env::get('wechat.wx_fence_template_id');
  216. if (!$app_id || !$appsecret) {
  217. debug_log($log_filename,'WECHAT_APPID and WECHAT_APPSECRET required');
  218. return array('success'=>false,'message'=>'WECHAT_APPID and WECHAT_APPSECRET required');
  219. }
  220. if (!$info['Longitude'] || !$info['Latitude']) {
  221. debug_log($log_filename,$info['DeviceId'] .' location incomplete');
  222. return array('success'=>false,'message'=>$info['DeviceId'] .' location incomplete');
  223. }
  224. //设备未绑定车辆不检测
  225. if (!$device_info['bind_id']) {
  226. debug_log('pushFenceMsgToYys',$info['DeviceId'].' has not bind any vehicle');
  227. return array('success'=>false,'message'=>$info['DeviceId'].' has not bind any vehicle');
  228. }
  229. $vehicle_info=Db::table('vehicles')->where('id',$device_info['bind_id'])->find();
  230. if(!$vehicle_info || !$vehicle_info['user_id']){
  231. debug_log('pushFenceMsgToYys',$vehicle_info['id'].' vehicle has not bind any user');
  232. return array('success'=>false,'message'=>$vehicle_info['id'].' vehicle has not bind any user');
  233. }
  234. // 是否跨越围栏
  235. $is_cross = false;
  236. $fence_model = Db::table('fences');
  237. $user_model = Db::table('users');
  238. $alarm_report_model = Db::table('alarm_report');
  239. // $wx_tmp = new \Jiaruan\WxTmp();
  240. $wx_tmp = new \Jiaruan\WxTmp();
  241. $time = date('H:i:s'); // 当前时间
  242. // 保存到 alarm_report 表中
  243. $user_info=Db::table('users')->where(array('id'=>$vehicle_info['user_id']))->find();
  244. $fence_alarm_data = array(
  245. 'device_number' => $device_info['imei'],
  246. 'alarm_time' => date('Y-m-d H:i:s',$info['DeviceTime']),
  247. 'creator_id' => $device_info['creator_id'],
  248. 'created_at' => null,
  249. 'longitude' => $info['Longitude'],
  250. 'latitude' => $info['Latitude'],
  251. 'is_sent' => 1,//默认1 需要推送
  252. 'fence_id' => null,
  253. 'alarm_type' => null, // 进围栏-fence_in,出围栏-fence_out
  254. );
  255. $lnglat = [ // 基站坐标
  256. 'lng' => $info['Longitude'],
  257. 'lat' => $info['Latitude'],
  258. ];
  259. // 查出所有平台围栏
  260. $level_str = Db::table('departments')->where(array('id'=>$device_info['department_id']))->value('level');
  261. $levelArr=explode('-',$level_str);
  262. array_push($levelArr,$device_info['department_id']);
  263. $where=[
  264. ['departments', 'in', $levelArr],
  265. ['fence_type', '=', 0],
  266. ];
  267. $fence_list = $fence_model->where($where)->select();
  268. // var_dump($fence_list);
  269. foreach ($fence_list as $fence) {
  270. $check_in = false; // 检查进围栏
  271. $check_out = false;// 检查出围栏
  272. $need_sent_alarm=false;
  273. if ( ($fence['is_check_in']!=0) && !empty($fence['in_fence_time_area'])) {
  274. $check_in = true;
  275. }
  276. if ( ($fence['is_check_out']!=0) && !empty($fence['out_fence_time_area'])) {
  277. $check_out = true;
  278. }
  279. // 没有开启进出检测的跳过
  280. if (!$check_in && !$check_out) {
  281. continue;
  282. }
  283. // 没有设置部门和推送用户的跳过
  284. if (empty($fence['departments']) || empty($fence['push_users'])) {
  285. continue;
  286. }
  287. $cond=[
  288. ['id', 'in',json_decode($fence['push_users'], true)],
  289. ];
  290. $push_users = $user_model->where($cond)->column('realname','wx_open_id');//第二个字段为索引
  291. if (empty($push_users)) {
  292. continue;
  293. }
  294. $content = ''; // 推送内容
  295. // 围栏形状数据为空跳过
  296. $fence_info = json_decode($fence['fence_info'], true);
  297. if (empty($fence_info)) {
  298. continue;
  299. }
  300. // 在检查时间内,根据围栏形状和基站位置判断是否在围栏内
  301. $is_in_fence = isCrossFence($fence['fence_shape'], $fence_info, $lnglat);
  302. $fence_alarm_data['fence_id'] = $fence['id'];
  303. // 进围栏
  304. $sent_interval=$fence['sent_interval'];
  305. $check_cond=[
  306. ['device_number', '=',$fence_alarm_data['device_number']],
  307. ['fence_id', '=',$fence_alarm_data['fence_id']],
  308. ['created_at', '>',time()-$sent_interval],
  309. ];
  310. if ($check_in && $is_in_fence) {
  311. $res = bmap_geocoding($info['Latitude'],$info['Longitude']);
  312. if($res['success']){
  313. $fence_alarm_data['address'] = $res['address'];
  314. }else{
  315. $fence_alarm_data['address'] = $info['Longitude'].','.$info['Latitude'];
  316. }
  317. // 检查是否在推送时间段
  318. $time_area = json_decode($fence['in_fence_time_area'], true);
  319. foreach ($time_area as $area) {
  320. if ($time < $area[0] || $time > $area[1]) {
  321. continue;
  322. }
  323. $is_cross = true;
  324. $need_sent_alarm=true;
  325. break;
  326. }
  327. if($need_sent_alarm){
  328. // 添加到上报记录表
  329. $fence_alarm_data['alarm_type'] = 'fence_in';
  330. $fence_alarm_data['created_at'] = time();
  331. // $check_cond['alarm_type']='fence_in';
  332. // $check_cond['is_sent']=1;
  333. $check_cond[]=['alarm_type','=','fence_in'];
  334. $check_cond[]=['is_sent','=','1'];
  335. //检测是否需要推送
  336. if(Db::table('alarm_report')->where($check_cond)->count()){
  337. $fence_alarm_data['is_sent']=0;
  338. $alarm_report_model->save($fence_alarm_data);
  339. debug_log($log_filename,'add alarm record failed,Msg:fence_in 围栏推送间隔未达到 device:'.$fence_alarm_data['device_number'].' fence_id:'.$fence_alarm_data['fence_id']);
  340. continue;
  341. }
  342. $insertId = $alarm_report_model->insertGetId($fence_alarm_data);
  343. //保存告警记录
  344. // saveAlarmRecords($fence_alarm_data);
  345. // 推送内容
  346. $content = "检测到有设备在{$fence_alarm_data['alarm_time']}进入围栏({$fence['name']})范围,当前位于{$fence_alarm_data['address']}";
  347. if (!$insertId) {
  348. debug_log($log_filename,'add alarm record failed,SQL:'.$alarm_report_model->getLastSql());
  349. }
  350. }
  351. } else if ($check_out && !$is_in_fence) { // 出围栏
  352. $res = bmap_geocoding($info['Latitude'],$info['Longitude']);
  353. if($res['success']){
  354. $fence_alarm_data['address'] = $res['address'];
  355. }else{
  356. $fence_alarm_data['address'] = $info['Longitude'].','.$info['Latitude'];
  357. }
  358. // 检查是否在推送时间段
  359. $time_area = json_decode($fence['out_fence_time_area'], true);
  360. foreach ($time_area as $area) {
  361. if ($time < $area[0] || $time > $area[1]) {
  362. continue;
  363. }
  364. $is_cross = true;
  365. $need_sent_alarm=true;
  366. }
  367. if($need_sent_alarm){
  368. // 添加到上报记录表
  369. $fence_alarm_data['alarm_type'] = 'fence_out';
  370. $fence_alarm_data['created_at'] = time();
  371. $check_cond[]=['alarm_type','=','fence_out'];
  372. $check_cond[]=['is_sent','=','1'];
  373. // $check_cond['alarm_type']='fence_out';
  374. // $check_cond['is_sent']=1;
  375. //检测是否需要推送
  376. if(Db::table('alarm_report')->where($check_cond)->count()){
  377. $fence_alarm_data['is_sent']=0;
  378. $alarm_report_model->save($fence_alarm_data);
  379. debug_log($log_filename,'add alarm record failed,Msg:fence_in 围栏推送间隔未达到 device:'.$fence_alarm_data['device_number'].' fence_id:'.$fence_alarm_data['fence_id']);
  380. continue;
  381. }
  382. $insertId = $alarm_report_model->insertGetId($fence_alarm_data);
  383. //保存告警记录
  384. // saveAlarmRecords($fence_alarm_data);
  385. // 推送内容
  386. $content = "检测到有设备在{$fence_alarm_data['alarm_time']}离开围栏({$fence['name']})范围,当前位于{$fence_alarm_data['address']}";
  387. if (!$insertId) {
  388. debug_log($log_filename,'add alarm record failed,SQL:'.$alarm_report_model->getLastSql());
  389. }
  390. }
  391. }
  392. // 不存在推送内容说明未跨越围栏,跳过
  393. if (!$content) {
  394. continue;
  395. }
  396. $wx_push_data = [
  397. 'template_id' => $template_id,
  398. 'data' => [
  399. 'first' => [ 'value' => $content, 'color' => '#173177' ],
  400. 'keyword1' => [ 'value' => $info['DeviceId'], 'color' => '#173177' ],
  401. 'keyword2' => [ 'value' => $user_info['realname'], 'color' => '#173177' ],
  402. 'keyword3' => [ 'value' => $fence['name'], 'color' => '#173177' ],
  403. 'keyword4' => [ 'value' => date('Y-m-d H:i:s',$info['DeviceTime']), 'color' => '#173177' ],
  404. 'remark' => [ 'value' => '', 'color' => '#173177' ],
  405. ],
  406. ];
  407. // 开始推送
  408. foreach ($push_users as $push_key=>$push_value) {
  409. if(!$push_key){
  410. continue;
  411. }
  412. $wx_push_data['touser'] = $push_key;
  413. // 开始推送
  414. $res='待完成';
  415. // $res = $wx_tmp->sendMessage($wx_push_data);
  416. $res= $wx_tmp->sendMessage($wx_push_data);
  417. $push_res_data = array(
  418. 'username'=>$push_value,
  419. 'device_number'=> $device_info['imei'],
  420. 'result'=> json_encode($res),
  421. 'created_at'=>time(),
  422. 'alarm_id'=>$insertId,
  423. 'alarm_type'=>$fence_alarm_data['alarm_type'],
  424. 'creator_id'=>$fence_alarm_data['creator_id']
  425. );
  426. Db::table('wx_push_result_log')->save($push_res_data);
  427. }
  428. }
  429. return array('success'=>true,'message'=>'围栏检测完成,结果:'.$is_cross);
  430. }
  431. /**
  432. * 是否跨越围栏
  433. * @param $shape 围栏类型
  434. * @param $fence_info 围栏信息
  435. * @param $lnglat 当前位置
  436. */
  437. function isCrossFence($shape,$fence_info,$lnglat){
  438. $is_cross = false;
  439. if ($shape == 'circle') {
  440. // 计算基站位置到圆形围栏中心点的距离
  441. $len = \algorithm\Geometry::distanceBetween2BdPoints($fence_info['center'], $lnglat); // 单位:km
  442. // 小于圆形围栏半径
  443. if ($len * 1000 < $fence_info['radius']) {
  444. $is_cross = true;
  445. }
  446. } else if ($shape == 'polygon') {
  447. // 判断是否在多边形范围内
  448. $isIn =\algorithm\Geometry::isInPolygon($fence_info, $lnglat);
  449. if ($isIn) {
  450. $is_cross = true;
  451. }
  452. }
  453. return $is_cross;
  454. }
  455. /**
  456. * 百度经纬度解析
  457. * @param $lat
  458. * @param $lng
  459. */
  460. function bmap_geocoding($lat,$lng){
  461. /*
  462. http://lbsyun.baidu.com/index.php?title=uri/api/web
  463. */
  464. $addr = json_decode(file_get_contents("http://api.map.baidu.com/geocoder?location={$lat},{$lng}&coord_type=wgs84&output=json&ak=2Gk7v8Gcb6PkgDZytoqsfdxuTGrQgfgB"), true);
  465. if($addr['status']=='OK'){
  466. $address=$addr['result']['formatted_address'];
  467. return array('success'=>true,'address'=>$address);
  468. }else{
  469. return array('success'=>false,'address'=>'');
  470. }
  471. }
  472. /**
  473. * debug日志
  474. */
  475. function debug_log($filename,$data){
  476. if(Env::get('APP_DEBUG')){
  477. $file = runtime_path() . '/log/'.date("Y-m-d", time()) ."/".$filename.".log";
  478. $folder=dirname($file);
  479. if (!is_dir($folder)){
  480. mkdir($folder,0777,true);
  481. }
  482. if(is_array($data)){
  483. $data = json_encode($data);
  484. }
  485. file_put_contents($file, '[' . date('Y-m-d H:i:s') . ']' . $data . PHP_EOL,FILE_APPEND);
  486. }
  487. }
  488. /**
  489. * api日志
  490. */
  491. function api_log($filename,$data){
  492. $file = runtime_path() . '/log/'.date("Ymd", time()) ."/".$filename.".log";
  493. $folder=dirname($file);
  494. if (!is_dir($folder)){
  495. mkdir($folder,0777,true);
  496. }
  497. if(is_array($data)){
  498. $data = json_encode($data);
  499. }
  500. file_put_contents($file, '[' . date('Y-m-d H:i:s') . ']' . $data . PHP_EOL,FILE_APPEND);
  501. }
  502. /**
  503.  *postt请求
  504. */
  505. function curl_http_post($data,$url,$ssl){
  506. $curl = curl_init();
  507. curl_setopt($curl,CURLOPT_URL,$url);
  508. if($ssl){
  509. curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,0);
  510. curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,1);
  511. curl_setopt($curl,CURLOPT_SSLVERSION,3);
  512. }
  513. // curl_setopt($curl,CURLOPT_USERAGENT,$_SERVER["HTTP_USER_AGENT"]);
  514. curl_setopt($curl,CURLOPT_AUTOREFERER,1);
  515. curl_setopt($curl,CURLOPT_POST,1);
  516. curl_setopt($curl,CURLOPT_POSTFIELDS,$data);
  517. curl_setopt($curl,CURLOPT_TIMEOUT,30);
  518. curl_setopt($curl,CURLOPT_HEADER,0);
  519. curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
  520. $tmpInfo = curl_exec($curl);
  521. if(curl_errno($curl)){
  522. dump(curl_error($curl));
  523. return false;
  524. }
  525. curl_close($curl);
  526. return $tmpInfo;
  527. }
  528. /**
  529. * 短信发送
  530. */
  531. function send_sms_with_config( $mobile, $content, $sms_config, $info ){
  532. $config = array();
  533. /*url示例
  534. $url="https://$this->ServerIP:$this->ServerPort/$this->SoftVersion/Accounts/$this->AccountSid/SMS/TemplateSMS?sig=$sig";
  535. */
  536. //沙盒环境(应用开发调试):sandboxapp.cloopen.com
  537. //生产环境(应用上线使用):app.cloopen.com
  538. $serverIP = 'app.cloopen.com';
  539. //sdk版本号
  540. $softVersion = '2013-12-26';
  541. //请求端口,一般为8883
  542. $serverPort='8883';
  543. //主账号,对应开官网发者主账号下的 ACCOUNT SID
  544. $accountSid= $sms_config['accountSid'];
  545. //$accountSid="8aaf0708754a3ef201755a063f070592";
  546. $config['accountSid']= $accountSid;
  547. //密钥
  548. $config['accountToken'] = $sms_config['accountToken'];
  549. //$config['accountToken'] = "324fb91d40cf472580dc8dc4d9a3e0d5";
  550. //应用Id,在官网应用列表中点击应用,对应应用详情中的APP ID
  551. $config['appId'] = $sms_config['appId'];
  552. //$config['appId'] = "8aaf070875774c6d0175910e26fc0bf9";
  553. //时间戳
  554. $batch = date("YmdHis");
  555. //验证信息编码
  556. $config['authen'] = base64_encode($accountSid . ":" . $batch);
  557. //加密REST API验证参数
  558. $sig = strtoupper(md5($accountSid . $config['accountToken'] . $batch));
  559. //拼接url
  560. $config['api_send_url'] = "https://$serverIP:$serverPort/$softVersion/Accounts/$accountSid/SMS/TemplateSMS?sig=".$sig;
  561. $postArr = array (
  562. 'to'=>$mobile,
  563. 'templateId' => $content['tplno'],
  564. 'appId'=>$config['appId'],
  565. 'datas'=>$content['tpldata'],
  566. );
  567. $postArr = json_encode($postArr);
  568. $authen = $config['authen'];
  569. $header = array("Accept:application/json","Content-Type:application/json;charset=utf-8","Authorization:$authen");
  570. $url = $config['api_send_url'];
  571. //$result = $this->curlPost( $url , $postArr, $header);
  572. //初始化curl
  573. $ch = curl_init();
  574. //参数设置
  575. $res= curl_setopt ($ch, CURLOPT_URL,$url);
  576. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  577. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  578. curl_setopt ($ch, CURLOPT_HEADER, 0);
  579. curl_setopt($ch, CURLOPT_POST, 1);
  580. curl_setopt($ch, CURLOPT_POSTFIELDS, $postArr);
  581. curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
  582. curl_setopt($ch,CURLOPT_HTTPHEADER,$header);
  583. $result = curl_exec ($ch);
  584. curl_close($ch);
  585. $result = json_decode($result,true);
  586. //var_dump($result);
  587. $data=array(
  588. 'recipient'=>$mobile,
  589. 'content'=>$content['info'],
  590. // 'type'=>'sms',
  591. 'created_at'=>time(),
  592. 'creator_id'=>0,
  593. // 'sent_time'=>time(),
  594. );
  595. if($result['statusCode']==='000000'){
  596. $data['sent_result']='发送成功';
  597. $res = Db::name('sms_send_log')->insert($data);
  598. return array('success'=>true,'message'=>'发送成功');
  599. }else{
  600. $data['sent_result']=json_encode($result,JSON_UNESCAPED_UNICODE);
  601. $res = Db::name('sms_send_log')->insert($data);
  602. return array('success'=>false,'errorCode'=>$result['statusCode'],'message'=>$result['statusMsg'],'data'=>$data);
  603. }
  604. }
  605. /**
  606. * 获取短信配置
  607. */
  608. function get_sms_config( $type ){
  609. $key="wxt_sms_send_config_".$type;
  610. $sms_cache_config =S($key);
  611. $sms_config=array();
  612. if(!$sms_cache_config){
  613. $config_id=Db::name('sms_config')->where(array('name'=>$type,'pid'=>'0'))->getField('id');
  614. if(!$config_id){
  615. return array('result'=>'fail','message'=>'未配置'.$type);
  616. }
  617. $config_list=Db::name('sms_config')->where(array('pid'=>$config_id))->select();
  618. if(!$config_list){
  619. return array('result'=>'fail','message'=>'未配置参数'.$type);
  620. }
  621. foreach($config_list as $val){
  622. $sms_config[$val['key']]=$val['value'];
  623. }
  624. S($key,json_encode($sms_config),60);
  625. }else{
  626. $sms_config=json_decode($sms_cache_config,true);
  627. }
  628. return $sms_config;
  629. }
  630. /**
  631. * 请求wifi定位信息
  632. */
  633. function requestWifiLBS($routeInfo){
  634. if(Env::get('map.wifiwayz')){
  635. return requestWifiLBS_wayz($routeInfo);
  636. }
  637. if(!$routeInfo){
  638. return array(
  639. 'success' => false,
  640. 'msg' => '空数据'
  641. );
  642. }
  643. if(!isset( $routeInfo['WifiMacs']) ){
  644. return array(
  645. 'success' => false,
  646. 'msg' => '无wifi信息'
  647. );
  648. }
  649. api_log('gaode_wifi_lbs',$routeInfo['WifiMacs']);
  650. $WifiMacs = $routeInfo['WifiMacs'];
  651. $userKey = '';
  652. if(!$userKey){
  653. $userKey = 'f107b0b3a513e6e37c6fb0424bed6633';
  654. }
  655. $t1=microtime(true);
  656. //$url = 'http://api.cellocation.com:81/loc/?wl=' . $WifiMacs .'&output=json&coord=gcj02';
  657. $url = 'http://apilocate.amap.com/position?accesstype=1&imei=' . $routeInfo['DeviceNumber'] . '&macs=' . $WifiMacs . '&key=' . $userKey;
  658. $curl = curl_init($url);
  659. curl_setopt($curl, CURLOPT_TIMEOUT, 1);
  660. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  661. $response = curl_exec($curl);
  662. if (curl_errno($curl)) {
  663. $errmsg = curl_error($curl);
  664. curl_close($curl);
  665. return array(
  666. 'success' => false,
  667. 'msg' => $errmsg
  668. );
  669. }
  670. curl_close($curl);
  671. api_log('gaode_wifi_lbs',$routeInfo['DeviceNumber']."返回结果".$response);
  672. $response = json_decode($response, true);
  673. if($response['info'] != 'OK' || count($response['result']) < 2 ){
  674. return array(
  675. 'success' => false,
  676. 'msg' => $response['info']
  677. );
  678. }
  679. $result = $response['result'];
  680. $location = $response['result']['location'];
  681. $location = explode(',', $location);
  682. $lngLat = \algorithm\Geometry::convertGcj02ToBd09($location[1],$location[0]);
  683. $response = array(
  684. 'lon' => $lngLat['lng'],
  685. 'lat' => $lngLat['lat'],
  686. 'address' => $result['desc']
  687. );
  688. $t2=microtime(true);
  689. api_log('gaode_wifi_lbs','t3:---'. ($t2-$t1));
  690. return array(
  691. 'success' => true,
  692. 'data' => $response
  693. );
  694. }
  695. /**
  696. * 请求wifi定位信息(WAYZ融合定位)
  697. */
  698. function requestWifiLBS_wayz($routeInfo){
  699. if(!$routeInfo){
  700. return array(
  701. 'success' => false,
  702. 'msg' => '空数据'
  703. );
  704. }
  705. if(!isset( $routeInfo['WifiMacs']) ){
  706. return array(
  707. 'success' => false,
  708. 'msg' => '无wifi信息'
  709. );
  710. }
  711. api_log('wayz_wifi_lbs',$routeInfo['WifiMacs']);
  712. //当前毫秒时间戳
  713. list($msec, $sec) = explode(' ', microtime());
  714. $msectime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
  715. //鉴权方式 采用 access_key 的方式,在 URL 的 Query Param 中添加 access_key。
  716. $access_key = 'VOiuxRnGhlJsAzVzhaU2Hen24zvwuWck';
  717. //处理WiFi信息
  718. $WifiMacs = $routeInfo['WifiMacs'];
  719. $WifiMacs = explode('|',$WifiMacs);
  720. $wifis = [];
  721. $countWifi=count($WifiMacs);
  722. $isFilter=Env::get('map.isfilter',false);
  723. $filterSignal=Env::get('map.signal',80);//过滤信号强度
  724. $filterTotal=Env::get('map.mactotal',10);;//wifi个数大于次数才开始过滤
  725. $total=0;//wifimacs上报 默认按强度排序 可直接计算不过滤前$filterTotal个
  726. foreach($WifiMacs as $v){
  727. $total++;
  728. $w = explode(',',$v);
  729. $wifi = array(
  730. "timestamp"=> intval($msectime),
  731. "signalStrength"=> abs($w[1]),
  732. "macAddress"=> $w[0],
  733. //"ssid"=> "AiMap",
  734. //"frequency"=> 0,
  735. //"channel"=> 0,
  736. //"connected"=> true
  737. );
  738. //判断是否需要过滤
  739. if( $isFilter && ($total>$filterTotal) && ($wifi['signalStrength'] > $filterSignal )){
  740. continue;
  741. }
  742. array_push($wifis,$wifi);
  743. }
  744. $asset = array(
  745. "id"=>date('YmdHis'),
  746. "manufacturer"=>"hzrl",
  747. "model"=>"校园卡",
  748. "imeiMd5"=> md5($routeInfo['DeviceNumber']),
  749. "macAddress"=>$routeInfo['DeviceNumber'],
  750. "serialNumber"=> "",
  751. "uniqueId"=> $routeInfo['DeviceNumber'],
  752. /*"os"=>array(
  753. "type"=> "",
  754. "version"=> ""
  755. )*/
  756. );
  757. $url = "https://api.newayz.com/location/hub/v1/track_points?access_key=".$access_key."&field_masks=location.position,location.address,location.place";
  758. //var_dump($url);
  759. //发送数据data
  760. $data = array(
  761. 'timestamp'=>intval($msectime),
  762. 'id'=>date('YmdHis'),
  763. 'asset'=>$asset,
  764. 'location'=>array(
  765. "wifis"=>$wifis
  766. )
  767. );
  768. $data = json_encode( $data );
  769. $curl = curl_init();
  770. curl_setopt($curl, CURLOPT_URL, $url);
  771. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  772. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
  773. curl_setopt($curl, CURLOPT_POST, 1);
  774. curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
  775. curl_setopt($curl, CURLOPT_HEADER, 0);
  776. curl_setopt($curl, CURLOPT_HTTPHEADER,
  777. array(
  778. 'Content-Type: application/json; charset=utf-8',
  779. 'Content-Length:' . strlen($data)
  780. )
  781. );
  782. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  783. $response = curl_exec($curl);
  784. $errorno = curl_errno($curl);
  785. if ($errorno) {
  786. return array('success' => false, 'data' => $errorno);
  787. }
  788. api_log('wayz_wifi_lbs',$routeInfo['DeviceNumber']."返回结果".$response);
  789. curl_close($curl);
  790. $response = json_decode($response, true);
  791. if(isset($response['code'])){
  792. return array(
  793. 'success' => false,
  794. 'msg' => $response['message']
  795. );
  796. }
  797. $location = $response['location'];
  798. $position = $location['position'];
  799. $point = $position['point'];
  800. $lngLat = \algorithm\Geometry::convertGcj02ToBd09($point['latitude'],$point['longitude']);
  801. $response = array(
  802. 'lon' => $lngLat['lng'],
  803. 'lat' => $lngLat['lat'],
  804. 'address' => $location['address']['name']
  805. );
  806. //echo '--------way end---------';
  807. return array(
  808. 'success' => true,
  809. 'data' => $response
  810. );
  811. }
  812. /**
  813. * 请求wifi定位信息(高德批量)
  814. */
  815. function requestWifiLBS_gaode_batch($routeArr){
  816. if(!$routeArr){
  817. return array(
  818. 'success' => false,
  819. 'msg' => '空数据'
  820. );
  821. }
  822. $mh = curl_multi_init();
  823. $curlArray = array();
  824. $t1=microtime(true);
  825. foreach($routeArr as $key=>$routeInfo){
  826. if(!isset( $routeInfo['WifiMacs'])){
  827. continue;
  828. }
  829. $WifiMacs = $routeInfo['WifiMacs'];
  830. $userKey = 'f107b0b3a513e6e37c6fb0424bed6633';
  831. $ch = curl_init();
  832. $url = 'http://apilocate.amap.com/position?accesstype=1&imei=' . $routeInfo['DeviceNumber'] . '&macs=' . $WifiMacs . '&key=' . $userKey;
  833. curl_setopt($ch, CURLOPT_URL, $url);
  834. curl_setopt($ch, CURLOPT_TIMEOUT, 3);
  835. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  836. curl_multi_add_handle($mh, $ch);
  837. $curlArray[$key] = $ch;
  838. }
  839. // echo count($curlArray);
  840. //api_log('gaode_wifi_lbs','count:--'. (count($curlArray)));
  841. $running = NULL;
  842. do {
  843. // usleep(10000);
  844. curl_multi_exec($mh,$running);
  845. } while($running > 0);
  846. $response_data=array();
  847. $success=0;
  848. $fail=0;
  849. foreach($curlArray as $key => $info) {
  850. // $res[$key] = curl_multi_getcontent($curlArray[$key]);
  851. $result = curl_multi_getcontent($curlArray[$key]);
  852. $response = json_decode($result,true);
  853. if($response['info'] != 'OK' || count($response['result']) < 2 ){
  854. $fail++;
  855. $item=array(
  856. 'success' => false,
  857. 'msg' => '定位信息解析失败'
  858. );
  859. }else{
  860. $success++;
  861. $result = $response['result'];
  862. $location = $result['location'];
  863. $location = explode(',', $location);
  864. $lngLat = \algorithm\Geometry::convertGcj02ToBd09($location[1],$location[0]);
  865. $address = array(
  866. 'lon' => $lngLat['lng'],
  867. 'lat' => $lngLat['lat'],
  868. 'address' => $result['desc']
  869. );
  870. $item=array(
  871. 'success' => true,
  872. 'data' => $address
  873. );
  874. }
  875. $response_data[$key]=$item;
  876. }
  877. // api_log('gaode_wifi_lbs','result:---success:--'.$success.'--fail:--'. $fail);
  878. foreach($curlArray as $key => $info){
  879. curl_multi_remove_handle($mh, $curlArray[$key]);
  880. }
  881. curl_multi_close($mh);
  882. // $t3=microtime(true);
  883. // api_log('gaode_wifi_lbs','t3:---'. ($t3-$t1));
  884. // echo 't3:---'. ($t3-$t2).PHP_EOL;
  885. return $response_data;
  886. }
  887. /**
  888. * 批量请求wifi定位信息(WAYZ融合定位)
  889. */
  890. function requestWifiLBS_wayz_batch($routeArr){
  891. if(!$routeArr){
  892. return array(
  893. 'success' => false,
  894. 'msg' => '空数据'
  895. );
  896. }
  897. //当前毫秒时间戳
  898. list($msec, $sec) = explode(' ', microtime());
  899. $msectime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
  900. //鉴权方式 采用 access_key 的方式,在 URL 的 Query Param 中添加 access_key。
  901. $access_key = 'VOiuxRnGhlJsAzVzhaU2Hen24zvwuWck';
  902. $post_data=array();
  903. $batch_keys=array();
  904. $isFilter=Env::get('map.isfilter',true);//
  905. $filterSignal=Env::get('map.signal',85);//过滤信号强度
  906. $filterTotal=Env::get('map.mactotal',5);;//wifi个数大于次数才开始过滤
  907. foreach($routeArr as $k=>$routeInfo){
  908. $asset = array(
  909. "id"=>date('YmdHis'),
  910. "manufacturer"=>"hzrl",
  911. "model"=>"校园卡",
  912. "imeiMd5"=> md5($routeInfo['DeviceNumber']),
  913. "macAddress"=>$routeInfo['DeviceNumber'],
  914. "serialNumber"=> "",
  915. "uniqueId"=> $routeInfo['DeviceNumber'],
  916. /*"os"=>array(
  917. "type"=> "",
  918. "version"=> ""
  919. )*/
  920. );
  921. //处理WiFi信息
  922. $WifiMacs = $routeInfo['WifiMacs'];
  923. $WifiMacs = explode('|',$WifiMacs);
  924. $wifis = [];
  925. $countWifi=count($WifiMacs);
  926. $total=0;//wifimacs上报 默认按强度排序 可直接计算不过滤前$filterTotal个
  927. foreach($WifiMacs as $v){
  928. $total++;
  929. $w = explode(',',$v);
  930. $wifi = array(
  931. "timestamp"=> intval($msectime),
  932. "signalStrength"=> abs($w[1]),
  933. "macAddress"=> $w[0],
  934. );
  935. //判断是否需要过滤
  936. if( $isFilter && ($total>$filterTotal) && ($wifi['signalStrength'] > $filterSignal )){
  937. continue;
  938. }
  939. array_push($wifis,$wifi);
  940. }
  941. if(count($wifis)<=3){
  942. continue;
  943. }
  944. $data = array(
  945. 'timestamp'=>intval($msectime),
  946. 'id'=>date('YmdHis'),
  947. 'asset'=>$asset,
  948. 'location'=>array(
  949. "wifis"=>$wifis
  950. )
  951. );
  952. //$post_data[$k]=$data;
  953. array_push($post_data,$data);
  954. array_push($batch_keys,$k);
  955. }
  956. // var_dump($batch_keys);
  957. $url = "https://api.newayz.com/location/hub/v1/track_points?batch=true&access_key=".$access_key."&field_masks=location.position,location.address,location.place";
  958. //var_dump($url);
  959. //发送数据data
  960. $post_data = json_encode( $post_data );
  961. $curl = curl_init();
  962. curl_setopt($curl, CURLOPT_URL, $url);
  963. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  964. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
  965. curl_setopt($curl, CURLOPT_POST, 1);
  966. curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
  967. curl_setopt($curl, CURLOPT_HEADER, 0);
  968. curl_setopt($curl, CURLOPT_HTTPHEADER,
  969. array(
  970. 'Content-Type: application/json; charset=utf-8',
  971. 'Content-Length:' . strlen($post_data)
  972. )
  973. );
  974. // curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept-Encoding: gzip, deflate'));
  975. // curl_setopt($curl, CURLOPT_ENCODING, "gzip");
  976. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  977. $response = curl_exec($curl);
  978. $errorno = curl_errno($curl);
  979. if ($errorno) {
  980. return array('success' => false, 'data' => $errorno);
  981. }
  982. // api_log('wayz_wifi_lbs',$routeInfo['DeviceNumber']."返回结果".$response);
  983. curl_close($curl);
  984. if(count($batch_keys)==1){
  985. $response = [json_decode($response, true)];
  986. }else{
  987. $response = json_decode($response, true);
  988. }
  989. $response_data=array();
  990. foreach($response as $key=>$value){
  991. // api_log('wayz_wifi_lbs',"返回结果".$key);
  992. $response_key=$batch_keys[$key];
  993. // api_log('wayz_wifi_lbs_batch',$routeArr[$response_key]['DeviceNumber'].' macs: '.$routeArr[$response_key]['WifiMacs']);
  994. // api_log('wayz_wifi_lbs_batch',$routeArr[$response_key]['DeviceNumber']." 返回结果: ".json_encode($value,JSON_UNESCAPED_UNICODE));
  995. $item=[];
  996. // var_dump($value);
  997. if(!isset($value['location']) ){
  998. $item=array(
  999. 'success' => false,
  1000. 'msg' => '定位信息解析失败'
  1001. );
  1002. }else{
  1003. $location = $value['location'];
  1004. if(!isset($location['position']) ){
  1005. $item=array(
  1006. 'success' => false,
  1007. 'msg' =>'定位信息解析失败'
  1008. );
  1009. }else{
  1010. $position = $location['position'];
  1011. $point = $position['point'];
  1012. $lngLat = \algorithm\Geometry::convertGcj02ToBd09($point['latitude'],$point['longitude']);
  1013. $address = array(
  1014. 'lon' => $lngLat['lng'],
  1015. 'lat' => $lngLat['lat'],
  1016. // 'address' => $location['address']['name']
  1017. );
  1018. if(isset($location['address']['name'])){
  1019. $address['address']=$location['address']['name'];
  1020. }
  1021. $item=array(
  1022. 'success' => true,
  1023. 'data' => $address
  1024. );
  1025. }
  1026. }
  1027. $response_data[$response_key]=$item;
  1028. }
  1029. return $response_data;
  1030. }
  1031. /**
  1032. * 百度地图过滤异常点
  1033. * @time 2021年05月18日 10:15
  1034. * @param Request $request
  1035. */
  1036. function bmapFilterOutliers($rows){
  1037. if(!$rows){
  1038. return array();
  1039. }
  1040. $response_data=[];
  1041. $point1=[];
  1042. $speedArr=[];
  1043. $timestamp=0;
  1044. for($i=0;$i<count($rows);$i++){
  1045. if($i==0){
  1046. //当前最新的一个定位保留
  1047. $timestamp=$rows[$i]['Timestamp'];
  1048. array_push($response_data, $rows[$i]);
  1049. $point1=['lng'=>$rows[$i]['Longitude'],'lat'=>$rows[$i]['Latitude']];
  1050. continue;
  1051. }
  1052. $point2=['lng'=>$rows[$i]['Longitude'],'lat'=>$rows[$i]['Latitude']];
  1053. $distance=\algorithm\Geometry::distanceBetween2BdPoints($point1,$point2);//单位km
  1054. $time=($timestamp-$rows[$i]['Timestamp'])/3600;//单位h
  1055. $speed=$distance/$time;//计算速度 超过130的默认为异常点
  1056. $speedArr[]=$speed;
  1057. if($rows[$i]['SignalType']=='WiFi'){
  1058. $length=count($speedArr);
  1059. if($length>=5){
  1060. $filterSpeed=($speedArr[$length-1]+$speedArr[$length-2]+$speedArr[$length-3]+$speedArr[$length-4]+$speedArr[$length-5])/5*1.5;//超过平均速度 1.5倍
  1061. }else{
  1062. $filterSpeed=50;
  1063. }
  1064. if($filterSpeed<10){
  1065. $filterSpeed=10;
  1066. }
  1067. if($speed<$filterSpeed){
  1068. $timestamp=$rows[$i]['Timestamp'];
  1069. $point1=$point2;
  1070. array_push($response_data, $rows[$i]);
  1071. }else{
  1072. array_pop($speedArr);//去除无效速度
  1073. }
  1074. }else{
  1075. $timestamp=$rows[$i]['Timestamp'];
  1076. $point1=$point2;
  1077. //只有wifi点需要过滤 gps点不过滤
  1078. array_push($response_data, $rows[$i]);
  1079. }
  1080. }
  1081. return bmapReverseFilterOutliers($response_data);
  1082. }
  1083. /**
  1084. * 百度地图过滤异常点
  1085. * @time 2021年05月18日 10:15
  1086. * @param Request $request
  1087. */
  1088. function bmapReverseFilterOutliers($rows){
  1089. if(!$rows){
  1090. return array();
  1091. }
  1092. $response_data=[];
  1093. $point1=[];
  1094. $speedArr=[];
  1095. $timestamp=0;
  1096. for($i=count($rows)-1;$i>=0;$i--){
  1097. if($i==count($rows)-1){
  1098. //当前最新的一个定位保留
  1099. array_push($response_data, $rows[$i]);
  1100. $timestamp=$rows[$i]['Timestamp'];
  1101. $point1=['lng'=>$rows[$i]['Longitude'],'lat'=>$rows[$i]['Latitude']];
  1102. continue;
  1103. }
  1104. $point2=['lng'=>$rows[$i]['Longitude'],'lat'=>$rows[$i]['Latitude']];
  1105. $distance=\algorithm\Geometry::distanceBetween2BdPoints($point1,$point2);//单位km
  1106. $time=($rows[$i]['Timestamp']-$timestamp)/3600;//单位h
  1107. $speed=$distance/$time;//计算速度 超过130的默认为异常点
  1108. $speedArr[]=$speed;
  1109. if($rows[$i]['SignalType']=='WiFi'){
  1110. $length=count($speedArr);
  1111. if($length>=5){
  1112. $filterSpeed=($speedArr[$length-1]+$speedArr[$length-2]+$speedArr[$length-3]+$speedArr[$length-4]+$speedArr[$length-5])/5*1.5;//超过平均速度 1.5倍
  1113. }else{
  1114. $filterSpeed=50;
  1115. }
  1116. // test_log('filt_map','['.$rows[$i]['PassTime'].'] filterSpeed: '. $filterSpeed.'speed: '. $speed.' time: '. $time);
  1117. // if($filterSpeed>50){
  1118. // $filterSpeed=50;
  1119. // }
  1120. if($filterSpeed<10){
  1121. $filterSpeed=10;
  1122. }
  1123. if($speed<$filterSpeed){
  1124. $point1=$point2;
  1125. $timestamp=$rows[$i]['Timestamp'];
  1126. array_push($response_data, $rows[$i]);
  1127. }else{
  1128. array_pop($speedArr);//去除无效速度
  1129. }
  1130. }else{
  1131. $point1=$point2;
  1132. $timestamp=$rows[$i]['Timestamp'];
  1133. //只有wifi点需要过滤 gps点不过滤
  1134. array_push($response_data, $rows[$i]);
  1135. }
  1136. }
  1137. $res_data=[];
  1138. for($i=count($response_data)-1;$i>=0;$i--){
  1139. array_push($res_data, $response_data[$i]);
  1140. }
  1141. return $res_data;
  1142. }
  1143. /**
  1144. * 查询oracle数据库 select
  1145. * @time 2021年05月18日 10:15
  1146. * @param Request $request
  1147. */
  1148. function queryOracleSelect($tableName,$cond,$field='*'){
  1149. $conn = null;
  1150. if(!isset($cond['page'])){
  1151. $cond['page']=1;
  1152. }
  1153. if(!isset($cond['limit'])){
  1154. $cond['limit']=10;
  1155. }
  1156. $host= Env::get('oracle.hostname', '127.0.0.1');
  1157. $port= Env::get('oracle.hostport', '1521');
  1158. $instance_name= Env::get('oracle.instance', 'ORCL');
  1159. $username= Env::get('oracle.username', 'root');
  1160. $password= Env::get('oracle.password', 'root');
  1161. // $conn = oci_connect('用户名', '密码', '远程数据库名(eg.//192.168.1.133/orcl)');
  1162. $conn = oci_connect($username, $password, $host.':'.$port.'/'. $instance_name,'AL32UTF8');
  1163. if (!$conn) {
  1164. $e = oci_error();
  1165. trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
  1166. }
  1167. $start=($cond['page']-1)*$cond['limit'];
  1168. $end=$cond['page']*$cond['limit'];
  1169. $whereStr=buildQueryCond2($cond);
  1170. // $sql = 'SELECT * FROM ( SELECT '.$field.',ROWNUM RN FROM (SELECT * FROM '.$tableName.' '.$whereStr.' ORDER BY ID DESC) a WHERE ROWNUM <='.$end.' ) WHERE RN >='. $start;
  1171. $sql='SELECT * FROM ( SELECT '.$field.',ROWNUM RN FROM '.$tableName.' WHERE ROWNUM <='.$end.' '.$whereStr.' ) WHERE RN >'. $start;
  1172. // var_dump($sql);
  1173. // 查询并渲染
  1174. $stid = oci_parse($conn, $sql);
  1175. $r = oci_execute($stid);
  1176. $rows=[];
  1177. while($row = oci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_NULLS)) {
  1178. $rows[]=$row;
  1179. }
  1180. oci_free_statement($stid);
  1181. return $rows;
  1182. // $conn = new PDO("oci:dbname=//".$host.":".$port."/".$instance_name,$username,$password);// PDO方式
  1183. // $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  1184. // $start=($cond['page']-1)*$cond['limit'];
  1185. // $end=$cond['page']*$cond['limit'];
  1186. // $whereStr=buildQueryCond($cond);
  1187. // // SELECT * FROM ( SELECT a.*,to_char(a.UPDATE_DATE,'yyyy-mm-dd hh24:mi:ss') UPDATE_TIME,ROWNUM RN FROM (SELECT * FROM DSSC2.ADM_DEV ORDER BY ID DESC) a WHERE ROWNUM <=10 ) WHERE RN >=0
  1188. // $sql = 'SELECT * FROM ( SELECT '.$field.',ROWNUM RN FROM (SELECT * FROM '.$tableName.' '.$whereStr.' ORDER BY ID DESC) a WHERE ROWNUM <='.$end.' ) WHERE RN >='. $start;
  1189. // // var_dump($sql);
  1190. // $res = $conn -> query($sql);
  1191. // $rows = $res -> fetchAll(PDO::FETCH_ASSOC);
  1192. // if ($conn){
  1193. // $conn = null;
  1194. // }
  1195. // $rows=[];
  1196. }
  1197. /**
  1198. * 查询oracle数据库 count
  1199. * @time 2021年05月18日 10:15
  1200. * @param Request $request
  1201. */
  1202. function queryOracleFind($tableName,$cond){
  1203. $conn = null;
  1204. if(!$cond){
  1205. return [];
  1206. }
  1207. $host= Env::get('oracle.hostname', '127.0.0.1');
  1208. $port= Env::get('oracle.hostport', '1521');
  1209. $instance_name= Env::get('oracle.instance', 'ORCL');
  1210. $username= Env::get('oracle.username', 'root');
  1211. $password= Env::get('oracle.password', 'root');
  1212. $conn = new PDO("oci:dbname=//".$host.":".$port."/".$instance_name,$username,$password);// PDO方式
  1213. $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  1214. $sql='SELECT * FROM '.$tableName.' WHERE ';
  1215. foreach($cond as $key=>$val){
  1216. $sql .=$key.' '.$val[0].' '.$val[1];
  1217. }
  1218. $res= $conn -> query($sql)->fetch(PDO::FETCH_ASSOC);
  1219. if ($conn){
  1220. $conn = null;
  1221. }
  1222. // $response=[];
  1223. return $res;
  1224. }
  1225. /**
  1226. * 查询oracle数据库 count
  1227. * @time 2021年05月18日 10:15
  1228. * @param Request $request
  1229. */
  1230. function queryOracleCount($tableName,$cond){
  1231. $conn = null;
  1232. $host= Env::get('oracle.hostname', '127.0.0.1');
  1233. $port= Env::get('oracle.hostport', '1521');
  1234. $instance_name= Env::get('oracle.instance', 'ORCL');
  1235. $username= Env::get('oracle.username', 'root');
  1236. $password= Env::get('oracle.password', 'root');
  1237. $conn = new PDO("oci:dbname=//".$host.":".$port."/".$instance_name,$username,$password);// PDO方式
  1238. $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  1239. // var_dump($cond);
  1240. $whereStr=buildQueryCond($cond);
  1241. $countQuery='SELECT count(*) as count FROM '.$tableName.' '.$whereStr;
  1242. // var_dump($countQuery);
  1243. // return 1111;
  1244. $countRes= $conn -> query($countQuery)->fetch(PDO::FETCH_ASSOC);
  1245. if ($conn){
  1246. $conn = null;
  1247. }
  1248. return (int)$countRes['COUNT'];
  1249. }
  1250. function buildQueryCond($cond){
  1251. $whereStr='';
  1252. foreach($cond as $key=>$val){
  1253. if( $key!='page' && $key!='limit' && $val[1]!=''){
  1254. if($key=='_string'){
  1255. if($whereStr==''){
  1256. $whereStr .='WHERE '.$val;
  1257. }else{
  1258. $whereStr .=' AND '.$val;
  1259. }
  1260. continue;
  1261. }
  1262. if($val[0]=='like'){
  1263. if($whereStr==''){
  1264. $whereStr .='WHERE '.$key.' '.$val[0].' \'%'.$val[1].'%\'';
  1265. }else{
  1266. $whereStr .=' AND '.$key.' '.$val[0].' \'%'.$val[1].'%\'';
  1267. }
  1268. }else if($val[0]=='timeRange'){
  1269. if($whereStr==''){
  1270. $whereStr .='WHERE '.$key.' >= to_date(\''.$val[1].'\', \'yyyy-mm-dd hh24:mi:ss\') AND '.$key.' <= to_date(\''.$val[2].'\', \'yyyy-mm-dd hh24:mi:ss\')';
  1271. }else{
  1272. $whereStr .=' AND '.$key.' >= to_date(\''.$val[1].'\', \'yyyy-mm-dd hh24:mi:ss\') AND '.$key.' <= to_date(\''.$val[2].'\', \'yyyy-mm-dd hh24:mi:ss\')';
  1273. }
  1274. }else{
  1275. if($whereStr==''){
  1276. $whereStr .='WHERE '.$key.' '.$val[0].' \''.$val[1].'\'';
  1277. }else{
  1278. $whereStr .=' AND '.$key.' '.$val[0].' \''.$val[1].'\'';
  1279. }
  1280. }
  1281. }
  1282. }
  1283. return $whereStr;
  1284. }
  1285. function buildQueryCond2($cond){
  1286. $whereStr='';
  1287. foreach($cond as $key=>$val){
  1288. if( $key!='page' && $key!='limit' && $val[1]!=''){
  1289. if($key=='_string'){
  1290. $whereStr .=' AND '.$val;
  1291. continue;
  1292. }
  1293. if($val[0]=='like'){
  1294. $whereStr .=' AND '.$key.' '.$val[0].' \'%'.$val[1].'%\'';
  1295. }else if($val[0]=='timeRange'){
  1296. $whereStr .=' AND '.$key.' >= to_date(\''.$val[1].'\', \'yyyy-mm-dd hh24:mi:ss\') AND '.$key.' <= to_date(\''.$val[2].'\', \'yyyy-mm-dd hh24:mi:ss\')';
  1297. }else{
  1298. $whereStr .=' AND '.$key.' '.$val[0].' \''.$val[1].'\'';
  1299. }
  1300. }
  1301. }
  1302. return $whereStr;
  1303. }
  1304. function getOracleConnect(){
  1305. $host= Env::get('oracle.hostname', '127.0.0.1');
  1306. $port= Env::get('oracle.hostport', '1521');
  1307. $instance_name= Env::get('oracle.instance', 'ORCL');
  1308. $username= Env::get('oracle.username', 'root');
  1309. $password= Env::get('oracle.password', 'root');
  1310. $conn = oci_connect($username, $password, $host.':'.$port.'/'. $instance_name,'AL32UTF8');
  1311. if (!$conn) {
  1312. $e = oci_error();
  1313. trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
  1314. }
  1315. return $conn;
  1316. }