common.php 57 KB

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