VM暫存
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1625 lines
53KB

  1. <?php
  2. /*
  3. file: cars_model.php
  4. */
  5. require_once(ALTOB_SYNC_FILE) ;
  6. define('CARS_TMP_LOG', 'cars_tmp_log'); // 暫存進出車號
  7. class Cars_model extends CI_Model
  8. {
  9. var $vars = array();
  10. var $io_name = array('I' => '車入', 'O' => '車出', 'MI' => '機入', 'MO' => '機出', 'FI' => '樓入', 'FO' => '樓出');
  11. var $now_str;
  12. function __construct()
  13. {
  14. parent::__construct();
  15. $this->load->database();
  16. $this->now_str = date('Y-m-d H:i:s');
  17. }
  18. public function init($vars)
  19. {
  20. $this->vars = $vars;
  21. }
  22. // 產生回傳訊息
  23. function gen_return_msg($msg_id, $open_or_not=false)
  24. {
  25. $open_id = $open_or_not ? 1 : 0;
  26. return $open_id . ',' . str_pad($msg_id, 5, '0', STR_PAD_LEFT);
  27. }
  28. // 特殊方式進出註記
  29. public function ipcam_meta($parms)
  30. {
  31. trigger_error(__FUNCTION__ . '|特殊註記:' . print_r($parms, true));
  32. if($parms['token'] != 1)
  33. {
  34. trigger_error(__FUNCTION__ . '|未定義|' . print_r($parms, true));
  35. return false;
  36. }
  37. // 讀取最近一筆入場資料
  38. $rows_cario = $this->db->select('cario_no, obj_id, in_time, out_before_time')
  39. ->from('cario')
  40. ->where(array(
  41. 'station_no' => $parms['sno'],
  42. 'obj_id' => $parms['lpr'],
  43. 'err' => 0
  44. ))
  45. ->order_by('cario_no', 'desc')
  46. ->limit(1)
  47. ->get()
  48. ->row_array();
  49. if (!isset($rows_cario['cario_no']))
  50. {
  51. trigger_error(__FUNCTION__ . '|查無入場記錄|' . print_r($parms, true));
  52. return false;
  53. }
  54. // 更新入場記錄
  55. $data = array('ticket_type' => 3);
  56. $this->db->update('cario', $data, array('cario_no' => $rows_cario['cario_no']));
  57. trigger_error(__FUNCTION__ . '|悠遊卡,更新入場記錄|');
  58. $affect_rows = $this->db->affected_rows();
  59. if ($affect_rows > 0)
  60. {
  61. // 傳送更新記錄
  62. $sync_agent = new AltobSyncAgent();
  63. $sync_agent->init($parms['sno'], $this->now_str);
  64. $sync_agent->cario_no = $rows_cario['cario_no']; // 進出編號
  65. $sync_result = $sync_agent->sync_st_io_meta($data);
  66. trigger_error( __FUNCTION__ . "..sync_st_io_meta.." . $sync_result);
  67. }
  68. }
  69. // 車輛進出傳入車牌號碼 (2016/07/27)
  70. public function opendoor_lprio($parms)
  71. {
  72. $parms['lpr'] = urldecode($parms['lpr']);
  73. $rows = array();
  74. // $parms['ts'] = date('Y-m-d H:i:s', $parms['ts']);
  75. trigger_error(__FUNCTION__ . '|車牌傳入:' . print_r($parms, true));
  76. if ($parms['etag'] != 'NONE')
  77. {
  78. if ($parms['lpr'] != 'NONE')
  79. {
  80. // do nothing
  81. }
  82. else // 車辨失敗但有eTag, 查詢是否有車號
  83. {
  84. //$parms['lpr'] = $this->etag2lpr_2($parms['etag']); // 2017/01/10 預設都不用 ETAG 找車牌
  85. }
  86. }
  87. $rows = $this->get_member($parms['lpr']);
  88. return $this->save_db_io($parms, $rows, true);
  89. }
  90. // 車輛進出傳入車牌號碼
  91. public function lprio($parms)
  92. {
  93. //$parms['lpr'] = urldecode($parms['lpr']);
  94. $rows = array();
  95. // $parms['ts'] = date('Y-m-d H:i:s', $parms['ts']);
  96. trigger_error('車牌傳入:' . print_r($parms, true));
  97. if ($parms['etag'] != 'NONE')
  98. {
  99. if ($parms['lpr'] != 'NONE')
  100. {
  101. // 有車牌有eTag, 檢查資料庫是否double驗證
  102. //get_headers("http://192.168.10.201/cars.html/check_lpr_etag/{$parms['lpr']}/{$parms['etag']}");
  103. get_headers("http://localhost/cars.html/check_lpr_etag/{$parms['lpr']}/{$parms['etag']}"); // update 2016/07/26
  104. }
  105. else // 車辨失敗但有eTag, 查詢是否有車號
  106. {
  107. // $parms['lpr'] = $this->etag2lpr_2($parms['etag']); // 2017/01/10 預設都不用 ETAG 找車牌
  108. }
  109. }
  110. $rows = $this->get_member($parms['lpr']);
  111. return $this->save_db_io($parms, $rows);
  112. }
  113. // 入出口異動cario
  114. public function save_db_io($parms, $rows, $opendoor=false)
  115. {
  116. $msg_id = 0; // 訊息代碼
  117. if (!empty($rows['lpr_correct'])) $parms['lpr'] = $rows['lpr_correct'];
  118. // [START] 擋重覆 20170912 前端不止一筆 opendoor 送來時, 只處理第一個 (限 2 sec 內)
  119. if($opendoor)
  120. {
  121. $skip_or_not = false;
  122. $new_cars_tmp = array
  123. (
  124. 'timestamp' => time(),
  125. 'sno_io' => $parms['sno'] . $parms['io'],
  126. 'lpr' => $parms['lpr']
  127. );
  128. $cars_tmp_arr = array();
  129. $cars_tmp_log_arr = $this->vars['mcache']->get(CARS_TMP_LOG);
  130. if(!empty($cars_tmp_log_arr))
  131. {
  132. foreach($cars_tmp_log_arr as $tmp)
  133. {
  134. if(isset($tmp['timestamp']) && $tmp['timestamp'] > time() - 2) // 時限內才判斷
  135. {
  136. array_push($cars_tmp_arr, $tmp);
  137. }
  138. }
  139. }
  140. // 判斷是否繼續
  141. foreach($cars_tmp_arr as $tmp)
  142. {
  143. if( $new_cars_tmp['lpr'] == $tmp['lpr'] &&
  144. $new_cars_tmp['sno_io'] == $tmp['sno_io'])
  145. {
  146. $skip_or_not = true;
  147. }
  148. }
  149. // 更新
  150. array_push($cars_tmp_arr, $new_cars_tmp);
  151. $this->vars['mcache']->set(CARS_TMP_LOG, $cars_tmp_arr);
  152. trigger_error(__FUNCTION__ . '..new ' . CARS_TMP_LOG . " |s:{$skip_or_not}|" . print_r($cars_tmp_arr, true));
  153. // 跳過
  154. if($skip_or_not)
  155. {
  156. trigger_error(__FUNCTION__ . '..skip..');
  157. // [msg] 0: 不處理
  158. $msg_id = 0;
  159. return $this->gen_return_msg($msg_id);
  160. }
  161. }
  162. // [END] 擋重覆
  163. // 車辨失敗, 結束
  164. if ($parms['lpr'] == 'NONE')
  165. {
  166. if($opendoor)
  167. {
  168. // [msg] 1: 車辨失敗
  169. $msg_id = 1;
  170. $this->mq_send(MQ_TOPIC_ALTOB, MQ_ALTOB_MSG.",{$msg_id},{$parms['ivsno']}".MQ_ALTOB_MSG_END_TAG);
  171. return $this->gen_return_msg($msg_id);
  172. }
  173. else
  174. {
  175. if(substr($parms['io'], -strlen('I')) === 'I')
  176. {
  177. $data = array
  178. (
  179. 'station_no' => $parms['sno'],
  180. 'obj_type' => 1,
  181. 'obj_id' => $parms['lpr'],
  182. 'etag' => $parms['etag'] == 'NONE' ? '' : $parms['etag'],
  183. 'in_out' => $parms['io'],
  184. 'member_no' => 0,
  185. 'finished' => 0,
  186. 'in_time' => $this->now_str,
  187. 'in_lane' => $parms['ivsno'],
  188. 'in_pic_name' => empty($parms['pic_name']) ? '' : $parms['pic_name'],
  189. 'out_before_time' => date("Y-m-d H:i:s"),
  190. 'ticket_no' => $this->gen_pass_code()
  191. );
  192. $this->db->insert('cario', $data);
  193. trigger_error("[車辨失敗] 新增入場資料:".print_r($parms, true));
  194. }
  195. }
  196. return false;
  197. }
  198. $msg = $rows['member_no'] != 0 ? "{$parms['lpr']}." : $parms['lpr']; // 月租車號加.符號
  199. // 月租鎖車, 結束
  200. if ((substr($parms['io'], -strlen('O')) === 'O') && $rows['member_no'] != 0 && !empty($rows['locked']) && $rows['locked'] == 1)
  201. {
  202. if($opendoor)
  203. {
  204. // [msg] 2: 已鎖車
  205. $msg_id = 2;
  206. $this->mq_send(MQ_TOPIC_ALTOB, MQ_ALTOB_MSG.",{$msg_id},{$parms['ivsno']},{$parms['lpr']}".MQ_ALTOB_MSG_END_TAG);
  207. return $this->gen_return_msg($msg_id);
  208. }
  209. return false;
  210. }
  211. // 取得會員資訊
  212. $parms['member_no'] = $rows['member_no'];
  213. switch($parms['io'])
  214. {
  215. case 'CI':
  216. case 'MI':
  217. if($opendoor)
  218. {
  219. // 空車位導引
  220. $pks_arr = $this->get_valid_seat();
  221. if ($pks_arr['result']['location_no'] != 0)
  222. {
  223. $pks_loc_name = $pks_arr['loc_name'];
  224. $pks_loc_no = $pks_arr['result']['location_no'];
  225. $pks_floors = $pks_arr['floors'];
  226. }
  227. else
  228. {
  229. $pks_loc_name = 0;
  230. $pks_loc_no = 0;
  231. $pks_floors = 0;
  232. }
  233. // 訊息
  234. if ($rows['member_no'] == 0)
  235. {
  236. $ck = md5($parms['lpr']);
  237. $jdata = file_get_contents("http://localhost/allpa_service.html/get_allpa_valid_user/{$parms['lpr']}/{$ck}");
  238. $results = json_decode($jdata, true);
  239. if($results['result_code'] == 0)
  240. {
  241. // [msg] 3: 歐pa卡, 開門
  242. $msg_id = 3;
  243. // 會員開門
  244. $this->member_opendoors($parms);
  245. }
  246. else
  247. {
  248. // [msg] 11: 臨停車, 開門
  249. $msg_id = 11;
  250. // 臨停開門
  251. $this->temp_opendoors($parms);
  252. }
  253. }
  254. else
  255. {
  256. // [msg] 4: 會員, 開門
  257. $msg_id = 4;
  258. // 會員開門
  259. $this->member_opendoors($parms);
  260. }
  261. // 字幕
  262. $this->mq_send(MQ_TOPIC_ALTOB, MQ_ALTOB_MSG.",{$msg_id},{$parms['ivsno']},{$parms['lpr']},{$pks_floors},{$pks_loc_no}".MQ_ALTOB_MSG_END_TAG);
  263. // 產生回傳
  264. return $this->gen_return_msg($msg_id, true);
  265. }
  266. else
  267. // 資料流
  268. {
  269. if ($parms['lpr'] != 'NONE')
  270. {
  271. $data = array
  272. (
  273. 'err' => 1,
  274. 'finished' => 1
  275. );
  276. // 原有歷史記錄, 設定錯誤碼為1(入場不應該有歷史記錄)
  277. $this->db->update('cario', $data, array('obj_id' => $parms['lpr'], 'finished' => 0, 'err' => 0, 'obj_type' => 1));
  278. $affect_rows = $this->db->affected_rows();
  279. if ($affect_rows > 0)
  280. {
  281. trigger_error("err://入場郤已有歷史進場記錄[{$affect_rows}]筆,已設成錯誤並結清記錄".print_r($parms, true));
  282. }
  283. }
  284. $data = array
  285. (
  286. 'station_no' => $parms['sno'],
  287. 'obj_type' => 1,
  288. 'obj_id' => $parms['lpr'],
  289. 'etag' => $parms['etag'] == 'NONE' ? '' : $parms['etag'],
  290. 'in_out' => $parms['io'],
  291. 'member_no' => $rows['member_no'],
  292. 'finished' => 0,
  293. 'in_time' => $this->now_str,
  294. 'in_lane' => $parms['ivsno'],
  295. 'in_pic_name' => empty($parms['pic_name']) ? '' : $parms['pic_name'],
  296. 'out_before_time' => date("Y-m-d H:i:s"),
  297. //'out_before_time' => date('Y-m-d H:i:s', strtotime(" + 15 minutes")), // 15分鐘內, 可直接離場
  298. 'ticket_no' => $this->gen_pass_code()
  299. );
  300. $this->db->insert('cario', $data);
  301. trigger_error("新增入場資料:".print_r($parms, true));
  302. // 傳送進場記錄
  303. $sync_agent = new AltobSyncAgent();
  304. $sync_agent->init($parms['sno'], $this->now_str);
  305. $sync_agent->cario_no = $this->db->insert_id(); // 進出編號
  306. $sync_agent->member_no = $rows['member_no']; // 會員編號
  307. $sync_result = $sync_agent->sync_st_in($parms);
  308. trigger_error( "..sync_st_in.." . $sync_result);
  309. }
  310. return true;
  311. break;
  312. // 出場
  313. case 'CO':
  314. case 'MO':
  315. // 讀取最近一筆入場資料
  316. $rows_cario = $this->db
  317. ->select('cario_no, payed, in_time, pay_time, out_before_time')
  318. ->from('cario')
  319. //->where(array('in_out' => 'CI', 'obj_id' => $parms['lpr'], 'finished' => 0, 'err' => 0))
  320. ->where(array('obj_id' => $parms['lpr'], 'err' => 0))
  321. ->order_by('cario_no', 'desc')
  322. ->limit(1)
  323. ->get()
  324. ->row_array();
  325. trigger_error("opendoor={$opendoor}| 出場讀到資料:{$rows['member_no']}|".time().'|'.print_r($rows_cario, true));
  326. if (!empty($rows_cario['cario_no'])) // 在限時內可出場
  327. {
  328. $co_time_minutes = floor((strtotime($this->now_str) - strtotime($rows_cario['in_time'])) / 60); // 停車時數 (分鐘)
  329. // 合規定者開門放行
  330. switch(true)
  331. {
  332. case $rows['member_no'] != 0:
  333. // CO.A.1 會員車
  334. // 判斷時段租是否超時 (超過 12 小時)
  335. if($rows['park_time'] != 'RE' && $co_time_minutes > 720)
  336. {
  337. if($opendoor)
  338. {
  339. // [msg] 16: 時段租超時字幕
  340. $msg_id = 16;
  341. // 字幕
  342. $this->mq_send(MQ_TOPIC_ALTOB, MQ_ALTOB_MSG.",{$msg_id},{$parms['ivsno']},{$parms['lpr']}".MQ_ALTOB_MSG_END_TAG);
  343. // 產生回傳
  344. return $this->gen_return_msg($msg_id);
  345. }
  346. else
  347. {
  348. $data = array
  349. (
  350. 'out_time' => $this->now_str,
  351. 'out_lane' => $parms['ivsno'],
  352. 'minutes' => $co_time_minutes,
  353. 'out_pic_name' => $parms['pic_name']
  354. );
  355. $this->db->update('cario', $data, array('cario_no' => $rows_cario['cario_no'])); // 記錄出場
  356. trigger_error("{$parms['lpr']}|時段租超時" . print_r($rows_cario, true));
  357. // 傳送離場記錄
  358. $sync_agent = new AltobSyncAgent();
  359. $sync_agent->init($parms['sno'], $this->now_str);
  360. $sync_agent->cario_no = $rows_cario['cario_no']; // 進出編號
  361. $sync_agent->member_no = $rows['member_no']; // 會員編號
  362. $sync_agent->in_time = $rows_cario['in_time']; // 入場時間
  363. $sync_result = $sync_agent->sync_st_out($parms);
  364. trigger_error( "..sync_st_out.." . $sync_result);
  365. }
  366. return true;
  367. }
  368. if($opendoor)
  369. {
  370. // [msg] 5: 會員離場開門
  371. $msg_id = 5;
  372. // 會員開門
  373. $this->member_opendoors($parms);
  374. // 字幕
  375. $this->mq_send(MQ_TOPIC_ALTOB, MQ_ALTOB_MSG.",{$msg_id},{$parms['ivsno']},{$parms['lpr']}".MQ_ALTOB_MSG_END_TAG);
  376. // 產生回傳
  377. return $this->gen_return_msg($msg_id, true);
  378. }
  379. else
  380. {
  381. $data = array
  382. (
  383. 'in_out' => $parms['io'],
  384. 'finished' => 1,
  385. 'out_time' => $this->now_str,
  386. 'out_lane' => $parms['ivsno'],
  387. 'minutes' => $co_time_minutes,
  388. 'out_pic_name' => $parms['pic_name']
  389. );
  390. $this->db->update('cario', $data, array('cario_no' => $rows_cario['cario_no']));
  391. trigger_error('會員車離場:' . print_r($rows, true));
  392. // 傳送離場記錄
  393. $sync_agent = new AltobSyncAgent();
  394. $sync_agent->init($parms['sno'], $this->now_str);
  395. $sync_agent->cario_no = $rows_cario['cario_no']; // 進出編號
  396. $sync_agent->member_no = $rows['member_no']; // 會員編號
  397. $sync_agent->in_time = $rows_cario['in_time']; // 入場時間
  398. $sync_agent->finished = 1; // 已離場
  399. $sync_result = $sync_agent->sync_st_out($parms);
  400. trigger_error( "..sync_st_out.." . $sync_result);
  401. }
  402. return true;
  403. break;
  404. case strtotime($rows_cario['out_before_time']) >= time():
  405. if ($rows_cario['payed'])
  406. {
  407. // CO.B.1 臨停車已付款
  408. if($opendoor)
  409. {
  410. // [msg] 6: 臨停車已付款
  411. $msg_id = 6;
  412. // 臨停開門
  413. $this->temp_opendoors($parms);
  414. // 字幕
  415. $this->mq_send(MQ_TOPIC_ALTOB, MQ_ALTOB_MSG.",{$msg_id},{$parms['ivsno']},{$parms['lpr']}".MQ_ALTOB_MSG_END_TAG);
  416. // 產生回傳
  417. return $this->gen_return_msg($msg_id, true);
  418. }
  419. else
  420. {
  421. $data = array
  422. (
  423. 'in_out' => $parms['io'],
  424. 'finished' => 1,
  425. 'out_time' => $this->now_str,
  426. 'out_lane' => $parms['ivsno'],
  427. 'minutes' => $co_time_minutes,
  428. 'out_pic_name' => $parms['pic_name']
  429. );
  430. $this->db->update('cario', $data, array('cario_no' => $rows_cario['cario_no']));
  431. trigger_error('臨停車已付款:' . print_r($rows, true));
  432. // 傳送離場記錄
  433. $sync_agent = new AltobSyncAgent();
  434. $sync_agent->init($parms['sno'], $this->now_str);
  435. $sync_agent->cario_no = $rows_cario['cario_no']; // 進出編號
  436. $sync_agent->in_time = $rows_cario['in_time']; // 入場時間
  437. $sync_agent->finished = 1; // 已離場
  438. $sync_result = $sync_agent->sync_st_out($parms);
  439. trigger_error( "..sync_st_out.." . $sync_result);
  440. }
  441. return true;
  442. }
  443. else
  444. {
  445. // CO.B.2 臨停車未付款
  446. if($opendoor)
  447. {
  448. // [msg] 8: 臨停車未付款
  449. $msg_id = 8;
  450. // 字幕
  451. $this->mq_send(MQ_TOPIC_ALTOB, MQ_ALTOB_MSG.",{$msg_id},{$parms['ivsno']},{$parms['lpr']}".MQ_ALTOB_MSG_END_TAG);
  452. // 產生回傳
  453. return $this->gen_return_msg($msg_id);
  454. }
  455. else
  456. {
  457. // TODO: 歐pa卡離場記錄和臨停未付款一樣, 待更正
  458. $data = array
  459. (
  460. 'out_time' => $this->now_str,
  461. 'out_lane' => $parms['ivsno'],
  462. 'minutes' => $co_time_minutes,
  463. 'out_pic_name' => $parms['pic_name']
  464. );
  465. $this->db->update('cario', $data, array('cario_no' => $rows_cario['cario_no'])); // 記錄出場
  466. trigger_error('臨停未付款:' . print_r($rows, true));
  467. // 傳送離場記錄
  468. $sync_agent = new AltobSyncAgent();
  469. $sync_agent->init($parms['sno'], $this->now_str);
  470. $sync_agent->cario_no = $rows_cario['cario_no']; // 進出編號
  471. $sync_agent->in_time = $rows_cario['in_time']; // 入場時間
  472. $sync_result = $sync_agent->sync_st_out($parms);
  473. trigger_error( "..sync_st_out.." . $sync_result);
  474. // [mitac] 要求 mitac 扣款 START
  475. $this->call_mitac_pay($parms['lpr'], $parms['ivsno'], $rows_cario);
  476. // [mitac] 要求 mitac 扣款 END
  477. }
  478. return true;
  479. }
  480. break;
  481. default:
  482. // CO.C.1 其它付款方式
  483. if($opendoor)
  484. {
  485. $in_time = strtotime($rows_cario['out_before_time']);
  486. $ck = md5($in_time. $parms['lpr'] . $parms['sno']);
  487. //$jdata = file_get_contents("http://localhost/allpa_service.html/allpa_go/{$in_time}/{$parms['lpr']}/{$parms['sno']}/{$ck}");
  488. $jdata = file_get_contents("http://localhost/allpa_service.html/allpa_go_remote/{$in_time}/{$parms['lpr']}/{$parms['sno']}/{$ck}");
  489. trigger_error("allpa回傳:{$jdata}|{$in_time}/{$parms['lpr']}/{$parms['sno']}/{$ck}");
  490. $results = json_decode($jdata, true);
  491. if (isset($results['result_code'])) // 歐pa卡, 點數足夠扣
  492. {
  493. if($results['result_code'] == 0)
  494. {
  495. // [msg] 7: 歐pa卡付款
  496. $msg_id = 7;
  497. // 臨停開門
  498. $this->temp_opendoors($parms);
  499. // 歐pa卡, 字幕
  500. $this->mq_send(MQ_TOPIC_ALTOB, MQ_ALTOB_MSG.",{$msg_id},{$parms['ivsno']},{$parms['lpr']},{$results['amt']}".MQ_ALTOB_MSG_END_TAG);
  501. $data = array(
  502. 'out_before_time' => date('Y-m-d H:i:s', strtotime(" + 15 minutes")),
  503. 'pay_time' => $this->now_str,
  504. 'pay_type' => 9, // 歐pa卡
  505. 'payed' => 1
  506. );
  507. $this->db->update('cario', $data, array('cario_no' => $rows_cario['cario_no'])); // 記錄出場
  508. // 產生回傳
  509. return $this->gen_return_msg($msg_id, true);
  510. }
  511. else if ($results['result_code'] == 12) // 歐pa卡, 餘額不足
  512. {
  513. // [msg] 12: 歐pa卡, 餘額不足
  514. $msg_id = 12;
  515. }
  516. else if ($results['result_code'] == 11) // 歐pa卡, 查無會員
  517. {
  518. // [msg] 9: 其它付款方式
  519. $msg_id = 9;
  520. }
  521. else
  522. {
  523. // [msg] 9: 其它付款方式
  524. $msg_id = 9;
  525. }
  526. }
  527. else
  528. {
  529. // [msg] 9: 其它付款方式
  530. $msg_id = 9;
  531. }
  532. // 字幕
  533. $this->mq_send(MQ_TOPIC_ALTOB, MQ_ALTOB_MSG.",{$msg_id},{$parms['ivsno']},{$parms['lpr']}".MQ_ALTOB_MSG_END_TAG);
  534. // 產生回傳
  535. return $this->gen_return_msg($msg_id);
  536. }
  537. else
  538. {
  539. $data = array
  540. (
  541. 'out_time' => $this->now_str,
  542. 'out_lane' => $parms['ivsno'],
  543. 'minutes' => $co_time_minutes,
  544. 'out_pic_name' => $parms['pic_name']
  545. );
  546. $this->db->update('cario', $data, array('cario_no' => $rows_cario['cario_no'])); // 記錄出場
  547. trigger_error("{$parms['lpr']}|其它付款方式:" . print_r($rows_cario, true));
  548. // 傳送離場記錄
  549. $sync_agent = new AltobSyncAgent();
  550. $sync_agent->init($parms['sno'], $this->now_str);
  551. $sync_agent->cario_no = $rows_cario['cario_no']; // 進出編號
  552. $sync_agent->in_time = $rows_cario['in_time']; // 入場時間
  553. $sync_result = $sync_agent->sync_st_out($parms);
  554. trigger_error( "..sync_st_out.." . $sync_result);
  555. // [mitac] 要求 mitac 扣款 START
  556. $this->call_mitac_pay($parms['lpr'], $parms['ivsno'], $rows_cario);
  557. // [mitac] 要求 mitac 扣款 END
  558. }
  559. return true;
  560. break;
  561. }
  562. }
  563. else if ($rows['member_no'] != 0)
  564. {
  565. // CO.Z.1 月租車無入場資料
  566. if($opendoor)
  567. {
  568. // [msg] 10: 月租車無入場資料
  569. $msg_id = 10;
  570. // 會員開門
  571. $this->member_opendoors($parms);
  572. // 會員字幕
  573. $this->mq_send(MQ_TOPIC_ALTOB, MQ_ALTOB_MSG.",{$msg_id},{$parms['ivsno']},{$parms['lpr']}".MQ_ALTOB_MSG_END_TAG);
  574. // 產生回傳
  575. return $this->gen_return_msg($msg_id, true);
  576. }
  577. else
  578. {
  579. trigger_error('月租車無入場資料:' . print_r($rows, true));
  580. // 傳送離場記錄
  581. $sync_agent = new AltobSyncAgent();
  582. $sync_agent->init($parms['sno'], $this->now_str);
  583. $sync_agent->member_no = $rows['member_no']; // 會員編號
  584. $sync_agent->finished = 1; // 已離場
  585. $sync_result = $sync_agent->sync_st_out($parms);
  586. trigger_error( "..sync_st_out.." . $sync_result);
  587. }
  588. return true;
  589. }
  590. else
  591. {
  592. // CO.Z.Z 無入場資料
  593. if($opendoor)
  594. {
  595. // [msg] 13: 無入場資料
  596. $msg_id = 13;
  597. $this->mq_send(MQ_TOPIC_ALTOB, MQ_ALTOB_MSG.",{$msg_id},{$parms['ivsno']},{$parms['lpr']}".MQ_ALTOB_MSG_END_TAG);
  598. // 產生回傳
  599. return $this->gen_return_msg($msg_id);
  600. }
  601. else
  602. {
  603. trigger_error('無入場資料:' . print_r($rows, true));
  604. // 傳送離場記錄
  605. $sync_agent = new AltobSyncAgent();
  606. $sync_agent->init($parms['sno'], $this->now_str);
  607. $sync_result = $sync_agent->sync_st_out($parms);
  608. trigger_error( "..sync_st_out.." . $sync_result);
  609. }
  610. return true;
  611. }
  612. break;
  613. }
  614. }
  615. // 檢查是否合法會員或VIP資料
  616. public function get_member($lpr)
  617. {
  618. $where_arr = array
  619. (
  620. 'c.lpr' => $lpr,
  621. 'c.start_time <=' => $this->now_str,
  622. 'c.end_time >=' => $this->now_str
  623. );
  624. $sql = "select
  625. c.lpr_correct,
  626. c.member_no,
  627. m.member_name,
  628. m.member_type,
  629. m.locked,
  630. m.remarks,
  631. m.park_time,
  632. m.suspended,
  633. m.valid_time,
  634. c.etag,
  635. c.start_time,
  636. c.end_time
  637. from member_car c, members m
  638. where c.member_no = m.member_no
  639. and c.start_time <= '{$this->now_str}'
  640. and c.end_time >= '{$this->now_str}'
  641. and c.lpr = '{$lpr}'
  642. limit 1";
  643. $rows = $this->db->query($sql)->row_array();
  644. // 新增 park_time_check 2016/11/11
  645. $park_time_check = 0;
  646. if (!empty($rows['lpr_correct']))
  647. {
  648. $park_time = $rows['park_time'];
  649. $pt_arr = $this->vars['mcache']->get('pt');
  650. if(empty($pt_arr) || empty($park_time))
  651. {
  652. // ERROR: 無法驗証時段, 跳過時段限制判斷
  653. trigger_error("[ERROR] mcache.pt is empty !!");
  654. $park_time_check = 1;
  655. }
  656. else
  657. {
  658. $now_time = substr($this->now_str, 11); // 日期字串只取最後時間字串(13:25:32)
  659. $week_no = date('w',strtotime($this->now_str)); // 取星期幾
  660. $park_time_array = explode(',', $park_time); // 用 , 格開
  661. foreach($park_time_array as $idx => $park_time_value)
  662. {
  663. foreach($pt_arr[$park_time_value]['timex'] as $idx => $pt_rows)
  664. {
  665. if ($week_no >= $pt_rows['w_start'] &&
  666. $week_no <= $pt_rows['w_end'] &&
  667. $now_time >= $pt_rows['time_start'] &&
  668. $now_time <= $pt_rows['time_end'])
  669. {
  670. $park_time_check = 2;
  671. trigger_error("時段代碼:{$park_time_value} 星期:{$week_no}");
  672. break;
  673. }
  674. }
  675. }
  676. }
  677. }
  678. if (empty($rows['lpr_correct'])) // A. 非月租車
  679. {
  680. $rows = array
  681. (
  682. 'lpr_correct' => '',
  683. 'member_no' => 0,
  684. 'member_name' => '',
  685. 'member_type' => 9,
  686. 'etag' => '',
  687. 'start_time' => '',
  688. 'end_time' => '',
  689. );
  690. }
  691. else if(empty($park_time_check)) // B. 月租車, 時段無效
  692. {
  693. trigger_error("無效的時段!! " . print_r($rows, true));
  694. $rows = array
  695. (
  696. 'lpr_correct' => '',
  697. 'member_no' => 0,
  698. 'member_name' => '',
  699. 'member_type' => 9,
  700. 'etag' => '',
  701. 'start_time' => '',
  702. 'end_time' => '',
  703. );
  704. }
  705. else if(!empty($rows['suspended'])) // C. 月租車, 停權中
  706. {
  707. trigger_error("停權中!! " . print_r($rows, true));
  708. $rows = array
  709. (
  710. 'lpr_correct' => '',
  711. 'member_no' => 0,
  712. 'member_name' => '',
  713. 'member_type' => 9,
  714. 'etag' => '',
  715. 'start_time' => '',
  716. 'end_time' => '',
  717. );
  718. }
  719. else if(!empty($rows['valid_time']) && $rows['valid_time'] < $this->now_str) // D. 月租車, 已無效 (審核未通過)
  720. {
  721. trigger_error("已無效!! " . print_r($rows, true));
  722. $rows = array
  723. (
  724. 'lpr_correct' => '',
  725. 'member_no' => 0,
  726. 'member_name' => '',
  727. 'member_type' => 9,
  728. 'etag' => '',
  729. 'start_time' => '',
  730. 'end_time' => '',
  731. );
  732. }
  733. trigger_error('讀取會員:' . print_r($rows, true) . ", park_time_check: {$park_time_check}");
  734. /*
  735. // 20171025 強制先不導入會員
  736. $rows = array
  737. (
  738. 'lpr_correct' => '',
  739. 'member_no' => 0,
  740. 'member_name' => '',
  741. 'member_type' => 9,
  742. 'etag' => '',
  743. 'start_time' => '',
  744. 'end_time' => '',
  745. );
  746. trigger_error(__FUNCTION__ . '..force not found..');
  747. */
  748. return $rows;
  749. }
  750. /*
  751. // 開門 (月租)
  752. public function member_opendoors($parms)
  753. {
  754. $this->mq_send(MQ_TOPIC_OPEN_DOOR, "DO{$parms['ivsno']},OPEN,{$parms['lpr']}");
  755. return true;
  756. }
  757. // 開門 (臨停)
  758. public function temp_opendoors($parms)
  759. {
  760. $this->mq_send(MQ_TOPIC_OPEN_DOOR, "DO{$parms['ivsno']},TICKET,{$parms['lpr']}");
  761. return true;
  762. }
  763. */
  764. // 用eTag讀出車號
  765. public function etag2lpr_2($etag)
  766. {
  767. // 用讀取eTag記錄(有double驗證過)
  768. $rows = $this->db->select('lpr')
  769. ->from('etag_lpr')
  770. ->where(array('etag' => $etag, 'confirms >' => 0))
  771. ->limit(1)
  772. ->get()
  773. ->row_array();
  774. // 讀出eTag資料
  775. if (!empty($rows['lpr']))
  776. {
  777. trigger_error("+++車牌NONE,以eTag讀入車牌:{$etag}|{$rows['lpr']}");
  778. return $rows['lpr'];
  779. }
  780. return 'NONE';
  781. }
  782. // 有車牌與eTag, 檢查資料庫 (2017/03/22 new)
  783. public function check_lpr_etag($lpr, $etag)
  784. {
  785. $ETAG_LOG_TITLE = 'etag://';
  786. $ETAG_WARMIN_TITLE = 'etag-warning://';
  787. trigger_error($ETAG_LOG_TITLE. "輸入: {$lpr},{$etag}");
  788. // 手動值上下限
  789. $max_admin_confirms_value = 99;
  790. $min_admin_confirms_value = 50;
  791. // 自動值上下限
  792. $max_system_confirms_value = 33;
  793. $min_system_confirms_value = 0;
  794. // 判斷對應加權
  795. $etag_confirms_bias_plus = 11; // etag 找 車牌, 對上一次可扺 11次
  796. $etag_confirms_bias_minus = -1;
  797. $lpr_confirms_bias_plus = 3; // 車牌 找 etag, 對上一次可扺 3次
  798. $lpr_confirms_bias_minus = -1;
  799. // eTag 找 車牌
  800. $lpr_info_from_etag = $this->db->select('lpr, confirms')
  801. ->from('etag_lpr')
  802. ->where(array('etag' => $etag))
  803. ->limit(1)
  804. ->get()
  805. ->row_array();
  806. if (!empty($lpr_info_from_etag['lpr']))
  807. {
  808. // B. etag 有找到 車牌
  809. if ($lpr_info_from_etag['lpr'] == $lpr)
  810. {
  811. // B.1. etag 有找到 車牌, 且 車牌 相符, confirms 上升
  812. $confirms_bias = $etag_confirms_bias_plus;
  813. }
  814. else
  815. {
  816. // B.2. etag 有找到 車牌, 但 車牌 不符, confirms 下降
  817. $confirms_bias = $etag_confirms_bias_minus;
  818. trigger_error($ETAG_WARMIN_TITLE . "etag 找 lpr | lpr error : {$lpr},{$etag} | query:" . print_r($lpr_info_from_etag, true));
  819. }
  820. $next_confirms_value = $lpr_info_from_etag['confirms'] + $confirms_bias;
  821. trigger_error($ETAG_LOG_TITLE . "etag 找 lpr | {$lpr},{$etag}, next_confirms: {$next_confirms_value}, bias:{$confirms_bias}");
  822. // 更新 confirms 資訊
  823. if($next_confirms_value > $max_admin_confirms_value)
  824. {
  825. // B.3.0 confirms 超過 max_admin_confirms_value, skip
  826. //trigger_error($ETAG_LOG_TITLE . "etag 找 lpr | {$lpr},{$etag} next_confirms_value > max_admin_confirms_value : {$max_admin_confirms_value}");
  827. }
  828. else if ($next_confirms_value >= $min_admin_confirms_value)
  829. {
  830. // B.3.1 人工確認過的記錄, 誤判多次後會停留在 min_admin_confirms_value, 或加到 max_admin_confirms_value
  831. $this->db->where('etag', $etag)->update('etag_lpr', array('confirms' => $next_confirms_value));
  832. }
  833. else if ($next_confirms_value > $max_system_confirms_value)
  834. {
  835. // B.3.2 confirms 超過 max_system_confirms_value, skip
  836. //trigger_error($ETAG_LOG_TITLE . "etag 找 lpr | {$lpr},{$etag} next_confirms_value > max_system_confirms_value : {$max_system_confirms_value}");
  837. }
  838. else if ($next_confirms_value <= $max_system_confirms_value && $next_confirms_value >= $min_system_confirms_value)
  839. {
  840. // B.3.3 confirms 不到 max_system_confirms_value 為系統生成記錄, 誤判多次後 confirms 會扣到 min_system_confirms_value
  841. $this->db->where('etag', $etag)->update('etag_lpr', array('confirms' => $next_confirms_value));
  842. }
  843. else
  844. {
  845. // B.3.4 若低於 min_system_confirms_value,刪除
  846. $this->db->delete('etag_lpr', array('etag' => $etag));
  847. trigger_error($ETAG_LOG_TITLE . "etag 找 lpr | etag confirms fail and removed : {$lpr_info_from_etag['lpr']}, {$etag}");
  848. trigger_error($ETAG_WARMIN_TITLE . "etag 找 lpr | etag confirms fail and removed : {$lpr_info_from_etag['lpr']}, {$etag}");
  849. }
  850. }
  851. else
  852. {
  853. // 車牌 找 etag
  854. $etag_info_form_lpr = $this->db->select('etag, confirms, member_no')
  855. ->from('etag_lpr')
  856. ->where(array('lpr' => $lpr))
  857. ->limit(1)
  858. ->get()
  859. ->row_array();
  860. if (!empty($etag_info_form_lpr['etag']))
  861. {
  862. // A. 車牌 有找到 etag
  863. if ($etag_info_form_lpr['etag'] == $etag)
  864. {
  865. // A.1. 車牌 有找到 etag, 且 etag 相符, confirms 上升
  866. $confirms_bias = $lpr_confirms_bias_plus;
  867. // 若尚未登記為會員
  868. if(empty($etag_info_form_lpr['member_no']))
  869. {
  870. // 檢查是否會員
  871. $member_info_from_lpr = $this->db->select('member_no, member_name')
  872. ->from('members')
  873. ->where(array('lpr' => $lpr))
  874. ->limit(1)
  875. ->get()
  876. ->row_array();
  877. // 確認為會員, 建立 eTag 資訊
  878. if (!empty($member_info_from_lpr['member_no']))
  879. {
  880. $data['member_no'] = $member_info_from_lpr['member_no'];
  881. $data['member_name'] = $member_info_from_lpr['member_name'];
  882. $this->db->where('member_no', $member_info_from_lpr['member_no'])->update('member_car', array('etag' => $etag));
  883. $this->db->where('member_no', $member_info_from_lpr['member_no'])->update('members', array('etag' => $etag));
  884. // 更新 etag_lpr
  885. $this->db->where('etag', $etag)->update('etag_lpr', $data);
  886. }
  887. }
  888. }
  889. else
  890. {
  891. // A.2. 車牌 有找到 etag, 但 etag 不符, confirms 下降
  892. $confirms_bias = $lpr_confirms_bias_minus;
  893. trigger_error($ETAG_WARMIN_TITLE . "lpr 找 etag | etag error : {$lpr},{$etag} | query:" . print_r($etag_info_form_lpr, true));
  894. }
  895. $next_confirms_value = $lpr_info_from_etag['confirms'] + $confirms_bias;
  896. trigger_error($ETAG_LOG_TITLE . "lpr 找 etag | {$lpr},{$etag}, next_confirms: {$next_confirms_value}, bias:{$confirms_bias}");
  897. // 更新 confirms 資訊
  898. if($next_confirms_value > $max_admin_confirms_value)
  899. {
  900. // A.3.0 confirms 超過 max_admin_confirms_value, skip
  901. //trigger_error($ETAG_LOG_TITLE . "lpr 找 etag | {$lpr},{$etag} next_confirms_value > max_admin_confirms_value : {$max_admin_confirms_value}");
  902. }
  903. else if ($next_confirms_value >= $min_admin_confirms_value)
  904. {
  905. // A.3.1 人工確認過的記錄, 誤判多次後會停留在 min_admin_confirms_value, 或加到 max_admin_confirms_value
  906. $this->db->where('lpr', $lpr)->update('etag_lpr', array('confirms' => $next_confirms_value));
  907. }
  908. else if ($next_confirms_value > $max_system_confirms_value)
  909. {
  910. // A.3.2 confirms 超過 max_system_confirms_value, skip
  911. //trigger_error($ETAG_LOG_TITLE . "lpr 找 etag | {$lpr},{$etag} next_confirms_value > max_system_confirms_value : {$max_system_confirms_value}");
  912. }
  913. else if ($next_confirms_value <= $max_system_confirms_value && $next_confirms_value >= $min_system_confirms_value)
  914. {
  915. // A.3.3 confirms 不到 max_system_confirms_value 為系統生成記錄, 誤判多次後 confirms 會扣到 min_system_confirms_value
  916. $this->db->where('lpr', $lpr)->update('etag_lpr', array('confirms' => $next_confirms_value));
  917. }
  918. else
  919. {
  920. // A.3.4 若低於 min_system_confirms_value,刪除
  921. $this->db->delete('etag_lpr', array('lpr' => $lpr));
  922. trigger_error($ETAG_LOG_TITLE . "lpr 找 etag | lpr confirms fail and removed : {$lpr}, {$etag_info_form_lpr['etag']}");
  923. trigger_error($ETAG_WARMIN_TITLE . "lpr 找 etag | lpr confirms fail and removed : {$lpr}, {$etag_info_form_lpr['etag']}");
  924. }
  925. }
  926. else
  927. {
  928. // C. 車牌 與 etag 都找不到記錄
  929. $data = array
  930. (
  931. 'lpr' => $lpr,
  932. 'lpr_correct' => $lpr,
  933. 'etag' => $etag
  934. );
  935. // 檢查是否會員
  936. $member_info_from_lpr = $this->db->select('member_no, member_name')
  937. ->from('members')
  938. ->where(array('lpr' => $lpr))
  939. ->limit(1)
  940. ->get()
  941. ->row_array();
  942. // 會員者, 將eTag update回去
  943. if (!empty($member_info_from_lpr['member_no']))
  944. {
  945. $data['member_no'] = $member_info_from_lpr['member_no'];
  946. $data['member_name'] = $member_info_from_lpr['member_name'];
  947. $this->db->where('member_no', $member_info_from_lpr['member_no'])->update('member_car', array('etag' => $etag));
  948. $this->db->where('member_no', $member_info_from_lpr['member_no'])->update('members', array('etag' => $etag));
  949. }
  950. // 建立第一筆記錄
  951. $this->db->insert('etag_lpr', $data);
  952. $etag_lpr_seqno = $this->db->insert_id();
  953. trigger_error($ETAG_LOG_TITLE . "create | insert seqno = {$etag_lpr_seqno}". print_r($data, true));
  954. }
  955. }
  956. }
  957. /*
  958. // 有車牌與eTag, 檢查資料庫
  959. public function check_lpr_etag($lpr, $etag)
  960. {
  961. // 用讀取eTag記錄(有double驗證過)
  962. $rows = $this->db->select('etag, confirms')
  963. ->from('etag_lpr')
  964. ->where(array('lpr' => $lpr))
  965. ->limit(1)
  966. ->get()
  967. ->row_array();
  968. // 讀出eTag資料
  969. if (!empty($rows['etag']))
  970. {
  971. // 車牌與eTag皆相符, 檢查是否confirms欄位若為0, 設成1(double驗證)
  972. if ($rows['etag'] == $etag)
  973. {
  974. if ($rows['confirms'] == 0) $this->db->where('lpr', $lpr)->update('etag_lpr', array('confirms' => 1));
  975. }
  976. else // eTag不相符
  977. {
  978. if ($rows['confirms'] == 1)
  979. {
  980. $this->db->where('lpr', $lpr)->update('etag_lpr', array('confirms' => 0));
  981. }
  982. else // 原confirms為0者, 刪除之
  983. {
  984. $this->db->delete('etag_lpr', array('lpr' => $lpr));
  985. }
  986. }
  987. }
  988. else // 無資料, 新增一筆
  989. {
  990. // 再檢查一次是否有eTag ?
  991. $rows_etag = $this->db->select('lpr, confirms')
  992. ->from('etag_lpr')
  993. ->where(array('etag' => $etag))
  994. ->limit(1)
  995. ->get()
  996. ->row_array();
  997. if (empty($rows_etag['lpr'])) // 無資料
  998. {
  999. $data = array
  1000. (
  1001. 'lpr' => $lpr,
  1002. 'lpr_correct' => $lpr,
  1003. 'etag' => $etag
  1004. );
  1005. // 檢查是否會員
  1006. $rows_members = $this->db->select('member_no, member_name')
  1007. ->from('members')
  1008. ->where(array('lpr' => $lpr))
  1009. ->limit(1)
  1010. ->get()
  1011. ->row_array();
  1012. // 會員者, 將eTag update回去
  1013. if (!empty($rows_members['member_no']))
  1014. {
  1015. $data['member_no'] = $rows_members['member_no'];
  1016. $data['member_name'] = $rows_members['member_name'];
  1017. $this->db->where('member_no', $rows_members['member_no'])->update('member_car', array('etag' => $etag));
  1018. $this->db->where('member_no', $rows_members['member_no'])->update('members', array('etag' => $etag));
  1019. }
  1020. $this->db->insert('etag_lpr', $data);
  1021. }
  1022. else
  1023. {
  1024. if ($rows_etag['confirms'] == 1)
  1025. {
  1026. $this->db->where('etag', $etag)->update('etag_lpr', array('confirms' => 0));
  1027. }
  1028. else // 原confirms為0者, 刪除之
  1029. {
  1030. $this->db->delete('etag_lpr', array('etag' => $etag));
  1031. }
  1032. }
  1033. }
  1034. }
  1035. */
  1036. // 送出至message queue(目前用mqtt)
  1037. public function mq_send($topic, $msg)
  1038. {
  1039. $this->vars['mqtt']->publish($topic, $msg, 0);
  1040. trigger_error("mqtt:{$topic}|{$msg}");
  1041. usleep(100000); // delay 0.1 sec (避免漏訊號)
  1042. }
  1043. // 產生 CK
  1044. public function gen_opendoor_ck($parms, $function_name)
  1045. {
  1046. return md5($parms['ivsno']. 'alt' . date('dmh') . 'o' . $parms['lpr'] . 'b' . $function_name);
  1047. }
  1048. // 開門 (月租)
  1049. public function member_opendoors($parms)
  1050. {
  1051. //$this->mq_send_opendoor(MQ_TOPIC_OPEN_DOOR, "DO{$parms['ivsno']},OPEN,{$parms['lpr']}");
  1052. $ck = $this->gen_opendoor_ck($parms, __FUNCTION__);
  1053. get_headers("http://localhost/cars.html/" . __FUNCTION__ . "/{$parms['ivsno']}/{$parms['lpr']}/{$ck}");
  1054. return true;
  1055. }
  1056. // 開門 (臨停)
  1057. public function temp_opendoors($parms)
  1058. {
  1059. //$this->mq_send_opendoor(MQ_TOPIC_OPEN_DOOR, "DO{$parms['ivsno']},TICKET,{$parms['lpr']}");
  1060. $ck = $this->gen_opendoor_ck($parms, __FUNCTION__);
  1061. get_headers("http://localhost/cars.html/" . __FUNCTION__ ."/{$parms['ivsno']}/{$parms['lpr']}/{$ck}");
  1062. return true;
  1063. }
  1064. // 開門 (月租)
  1065. public function do_member_opendoor($parms)
  1066. {
  1067. if($parms['ck'] != $this->gen_opendoor_ck($parms, 'member_opendoors'))
  1068. {
  1069. return 'ck_error'; // 中斷
  1070. }
  1071. $this->mq_send(MQ_TOPIC_OPEN_DOOR, "DO{$parms['ivsno']},OPEN,{$parms['lpr']}");
  1072. return 'ok';
  1073. }
  1074. // 開門 (臨停)
  1075. public function do_temp_opendoor($parms)
  1076. {
  1077. if($parms['ck'] != $this->gen_opendoor_ck($parms, 'temp_opendoors'))
  1078. {
  1079. return 'ck_error'; // 中斷
  1080. }
  1081. $this->mq_send(MQ_TOPIC_OPEN_DOOR, "DO{$parms['ivsno']},TICKET,{$parms['lpr']}");
  1082. return 'ok';
  1083. }
  1084. // 指派車位
  1085. // http://203.75.167.89/parkingquery.html/get_valid_seat
  1086. // 註記現在時間, 並保留10分鐘
  1087. public function get_valid_seat()
  1088. {
  1089. $data = array();
  1090. //$data['result']['location_no'] = '0';
  1091. //$data['result_code'] = 'FAIL';
  1092. //return $data;
  1093. // 撈 roger db
  1094. /*
  1095. $sql = "
  1096. SELECT ParkingNum AS pksno FROM table_carpark
  1097. WHERE LPR = '' AND DisableSeat = 0 AND
  1098. (SELECT COUNT(*) FROM table_carpark WHERE LPR = '' AND DisableSeat = 0) <= 10
  1099. ORDER BY RAND() LIMIT 1 FOR UPDATE;
  1100. ";
  1101. $dsn_old_db = $this->load->database('old_db', true);
  1102. // 2016/12/14 roger_db 掛了的可能
  1103. if ($dsn_old_db->initialize())
  1104. {
  1105. $retults = $dsn_old_db->query($sql)->result_array();
  1106. }
  1107. if(!empty($retults[0]))
  1108. {
  1109. $data['result']['location_no'] = substr($retults[0]['pksno'], 1);
  1110. $data['result_code'] = 'OK';
  1111. $data['loc_name'] = 'B'.substr($retults[0]['pksno'], 0, 1);
  1112. $data['floors'] = 'B'.substr($retults[0]['pksno'], 0, 1);
  1113. }
  1114. else
  1115. {
  1116. $data['result']['location_no'] = '0';
  1117. $data['result_code'] = 'FAIL';
  1118. }
  1119. */
  1120. $this->db->trans_start();
  1121. $sql = "select pksno from pks where status = 'VA' and prioritys != 0 and (book_time is null or book_time <= now()) order by prioritys asc limit 1 for update;";
  1122. $rows = $this->db->query($sql)->row_array();
  1123. if (!empty($rows['pksno']))
  1124. {
  1125. $data['result']['location_no'] = substr($rows['pksno'], -3);
  1126. $data['result_code'] = 'OK';
  1127. $sql = "update pks set book_time = addtime(now(), '00:10:00') where pksno = {$rows['pksno']};";
  1128. $this->db->query($sql);
  1129. $sql = "select g.group_name, g.floors from pks_groups g, pks_group_member m where m.pksno = {$rows['pksno']} and g.group_id = m.group_id and g.group_type = 1 limit 1";
  1130. $rows = $this->db->query($sql)->row_array();
  1131. $data['loc_name'] = $rows['group_name'];
  1132. $data['floors'] = $rows['floors'];
  1133. }
  1134. else
  1135. {
  1136. $data['result']['location_no'] = '0';
  1137. $data['result_code'] = 'FAIL';
  1138. }
  1139. $this->db->trans_complete();
  1140. return $data;
  1141. }
  1142. // 取得出入口 888 資訊
  1143. public function get_888_info($parms)
  1144. {
  1145. $data = array();
  1146. $sql = "select availables as availables, tot as tot from pks_groups where group_id = 'C888' and station_no = {$parms['sno']}";
  1147. $rows = $this->db->query($sql)->row_array();
  1148. if (!empty($rows) && array_key_exists('availables', $rows))
  1149. {
  1150. $data['result_code'] = 'OK';
  1151. $data['availables'] = $rows['availables'];
  1152. $data['tot'] = $rows['tot'];
  1153. }
  1154. else
  1155. {
  1156. trigger_error(__FUNCTION__ . "..not found..".print_r($parms, true));
  1157. $data['result_code'] = 'FAIL';
  1158. $data['availables'] = 9999; // 如果拿不到就忽略這個流程
  1159. $data['tot'] = 0;
  1160. }
  1161. return $data;
  1162. }
  1163. // ===============================================
  1164. // acer cmd
  1165. // ===============================================
  1166. // 產生通行碼
  1167. function gen_pass_code()
  1168. {
  1169. return rand(100000,999999);
  1170. }
  1171. // 呼叫acer
  1172. function call_acer($cmd, $parms)
  1173. {
  1174. return false; // 尚未啟用
  1175. try{
  1176. $ch = curl_init();
  1177. curl_setopt($ch, CURLOPT_URL, 'http://localhost/acer_service.html/cmd_'. $cmd);
  1178. curl_setopt($ch, CURLOPT_HEADER, FALSE);
  1179. curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  1180. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  1181. curl_setopt($ch, CURLOPT_POST, TRUE);
  1182. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT ,3);
  1183. curl_setopt($ch, CURLOPT_TIMEOUT, 3); //timeout in seconds
  1184. curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($parms));
  1185. $data = curl_exec($ch);
  1186. if(curl_errno($ch))
  1187. {
  1188. trigger_error(__FUNCTION__ . ', curl error: '. curl_error($ch));
  1189. }
  1190. curl_close($ch);
  1191. trigger_error(__FUNCTION__ . '..'. $data);
  1192. }catch (Exception $e){
  1193. trigger_error(__FUNCTION__ . 'error:'.$e->getMessage());
  1194. }
  1195. }
  1196. // ===============================================
  1197. // mitac cmd
  1198. // ===============================================
  1199. // 檢查指定時間是否介於停車時段區間
  1200. function check_park_time($park_time, $target_time)
  1201. {
  1202. $pt_arr = $this->vars['mcache']->get('pt');
  1203. $now_time = substr($target_time, 11); // 日期字串只取最後時間字串(13:25:32)
  1204. $week_no = date('w',strtotime($target_time)); // 取星期幾
  1205. $park_time_array = explode(',', $park_time); // 用 , 格開
  1206. foreach($park_time_array as $idx => $park_time_value)
  1207. {
  1208. foreach($pt_arr[$park_time_value]['timex'] as $idx => $pt_rows)
  1209. {
  1210. if ($week_no >= $pt_rows['w_start'] &&
  1211. $week_no <= $pt_rows['w_end'] &&
  1212. $now_time >= $pt_rows['time_start'] &&
  1213. $now_time <= $pt_rows['time_end'])
  1214. {
  1215. return true;
  1216. }
  1217. }
  1218. }
  1219. return false;
  1220. }
  1221. // 取得會員時段區間起點
  1222. function gen_park_time_first($park_time, $target_time)
  1223. {
  1224. $pt_arr = $this->vars['mcache']->get('pt');
  1225. $now_time = substr($target_time, 11); // 日期字串只取最後時間字串(13:25:32)
  1226. $week_no = date('w',strtotime($target_time)); // 取星期幾
  1227. $park_time_array = explode(',', $park_time); // 用 , 格開
  1228. $week_no_first = 0;
  1229. $time_end_first = '';
  1230. foreach($park_time_array as $idx => $park_time_value)
  1231. {
  1232. foreach($pt_arr[$park_time_value]['timex'] as $idx => $pt_rows)
  1233. {
  1234. if ($week_no >= $pt_rows['w_start'] &&
  1235. $week_no <= $pt_rows['w_end'] &&
  1236. $now_time >= $pt_rows['time_start'] &&
  1237. $now_time <= $pt_rows['time_end'])
  1238. {
  1239. $week_no_first = $pt_rows['w_start'];
  1240. $time_end_first = $pt_rows['time_start'];
  1241. trigger_error(__FUNCTION__ . "|$park_time, $target_time | $week_no_first, $time_end_first");
  1242. break;
  1243. }
  1244. }
  1245. }
  1246. $day_offset = $week_no - $week_no_first;
  1247. if($day_offset < 0)
  1248. {
  1249. trigger_error(__FUNCTION__ . '..error..offset..' . $day_offset);
  1250. $day_offset = 0;
  1251. }
  1252. return date('Y-m-d', strtotime("-$day_offset day", strtotime($target_time))). " $time_end_first";
  1253. }
  1254. // 取得會員時段區間終點
  1255. function gen_park_time_last($park_time, $target_time)
  1256. {
  1257. $pt_arr = $this->vars['mcache']->get('pt');
  1258. $now_time = substr($target_time, 11); // 日期字串只取最後時間字串(13:25:32)
  1259. $week_no = date('w',strtotime($target_time)); // 取星期幾
  1260. $park_time_array = explode(',', $park_time); // 用 , 格開
  1261. $week_no_last = 0;
  1262. $time_end_last = '';
  1263. foreach($park_time_array as $idx => $park_time_value)
  1264. {
  1265. foreach($pt_arr[$park_time_value]['timex'] as $idx => $pt_rows)
  1266. {
  1267. if ($week_no >= $pt_rows['w_start'] &&
  1268. $week_no <= $pt_rows['w_end'] &&
  1269. $now_time >= $pt_rows['time_start'] &&
  1270. $now_time <= $pt_rows['time_end'])
  1271. {
  1272. $week_no_last = $pt_rows['w_end'];
  1273. $time_end_last = $pt_rows['time_end'];
  1274. trigger_error(__FUNCTION__ . "|$park_time, $target_time | $week_no_last, $time_end_last");
  1275. break;
  1276. }
  1277. }
  1278. }
  1279. $day_offset = $week_no_last - $week_no;
  1280. if($day_offset < 0)
  1281. {
  1282. trigger_error(__FUNCTION__ . '..error..offset..' . $day_offset);
  1283. $day_offset = 0;
  1284. }
  1285. return date('Y-m-d', strtotime("+$day_offset day", strtotime($target_time))). " $time_end_last";
  1286. }
  1287. // 取得會員身份減免後的費用起算時間
  1288. function check_member_state($lpr, $in_time, $out_time)
  1289. {
  1290. // 檢查月租身份修正
  1291. $member_info = $this->get_member($lpr, false);
  1292. if ($member_info['member_no'] == 0)
  1293. {
  1294. // 查無會員身份
  1295. $member_state = 0;
  1296. $new_in_time = $in_time;
  1297. $new_out_time = $out_time;
  1298. }
  1299. else
  1300. {
  1301. $park_time = $member_info['park_time'];
  1302. $pt_arr = $this->vars['mcache']->get('pt');
  1303. if(empty($pt_arr) || empty($park_time))
  1304. {
  1305. // ERROR: 無法驗証時段, 跳過時段限制判斷
  1306. $member_state = 1;
  1307. $new_in_time = $in_time;
  1308. $new_out_time = $out_time;
  1309. }
  1310. else
  1311. {
  1312. $in_time_in_park_time = $this->check_park_time($park_time, $in_time);
  1313. $out_time_in_park_time = $this->check_park_time($park_time, $out_time);
  1314. trigger_error(__FUNCTION__ . "|$lpr, $in_time, $out_time|..check_park_time: {$in_time_in_park_time}, {$out_time_in_park_time}..");
  1315. if($in_time_in_park_time && $out_time_in_park_time)
  1316. {
  1317. // 進出時間都在會員區間內: 費用起算時間改為出場時間
  1318. $member_state = 2;
  1319. $new_in_time = $out_time;
  1320. $new_out_time = $out_time;
  1321. }
  1322. else if($in_time_in_park_time)
  1323. {
  1324. // 入場時間在會員區間內: 費用起算時間改為, 會員時段區間終點
  1325. $member_state = 3;
  1326. $new_in_time = $this->gen_park_time_last($park_time, $in_time);
  1327. $new_out_time = $out_time;
  1328. if(strtotime($new_in_time) > strtotime($out_time))
  1329. {
  1330. trigger_error(__FUNCTION__ . "|$lpr, $in_time, $out_time|new_in_time error >> out_time..");
  1331. $new_in_time = $out_time;
  1332. }
  1333. }
  1334. else if($out_time_in_park_time)
  1335. {
  1336. // 出場時間在會員區間內: 費用起算時間改為, 會員時段區間起點
  1337. $member_state = 4;
  1338. $new_in_time = $in_time;
  1339. $new_out_time = $this->gen_park_time_first($park_time, $out_time);
  1340. if(strtotime($in_time) > strtotime($new_out_time))
  1341. {
  1342. trigger_error(__FUNCTION__ . "|$lpr, $in_time, $out_time|new_in_time error >> out_time..");
  1343. $new_out_time = $out_time;
  1344. }
  1345. }
  1346. }
  1347. }
  1348. $member_result = array('state' => $member_state, 'in_time' => $new_in_time, 'out_time' => $new_out_time);
  1349. trigger_error(__FUNCTION__ . "|$lpr, $in_time, $out_time|..". print_r($member_result, true));
  1350. return $member_result;
  1351. }
  1352. // 要求 mitac 扣款
  1353. function call_mitac_pay($lpr, $ivsno, $rows_cario)
  1354. {
  1355. $function_name = 'parking_fee_altob';
  1356. $seqno = $rows_cario['cario_no'];
  1357. $in_time = $rows_cario['out_before_time'];
  1358. $out_time = $this->now_str;
  1359. $gate_id = 1; // 20171124 改為強制 1//$ivsno;
  1360. // 確認會員身份
  1361. $member_result = $this->check_member_state($lpr, $in_time, $out_time);
  1362. switch($member_result['state'])
  1363. {
  1364. case 0:
  1365. trigger_error(__FUNCTION__ . '|非會員|');
  1366. break;
  1367. case 1:
  1368. trigger_error(__FUNCTION__ . '|無法驗証時段|skip MITAC|'. print_r($member_result, true));
  1369. return false; // 跳過 mitac
  1370. break;
  1371. case 2:
  1372. trigger_error(__FUNCTION__ . '|進出時間都在會員區間內|skip MITAC|'. print_r($member_result, true));
  1373. return false; // 跳過 mitac
  1374. break;
  1375. case 3:
  1376. trigger_error(__FUNCTION__ . '|入場時間在會員區間內|'. print_r($member_result, true));
  1377. $in_time = $member_result['in_time'];
  1378. break;
  1379. case 4:
  1380. trigger_error(__FUNCTION__ . '|出場時間在會員區間內|'. print_r($member_result, true));
  1381. $out_time = $member_result['out_time'];
  1382. break;
  1383. default:
  1384. trigger_error(__FUNCTION__ . '|未定義|'. print_r($member_result, true));
  1385. break;
  1386. }
  1387. // 通訊內容
  1388. $parms = array(
  1389. 'seqno' => $seqno,
  1390. 'lpr' => $lpr,
  1391. 'in_time' => $in_time,
  1392. 'out_time' => $out_time,
  1393. 'gate_id' => $gate_id);
  1394. // 超過一天就擋掉
  1395. if(strtotime($parms['out_time']) - strtotime($parms['in_time']) > 86400)
  1396. {
  1397. trigger_error(__FUNCTION__ . '|超過計費時限|skip MITAC|'. print_r($parms, true));
  1398. return false; // 跳過 mitac
  1399. }
  1400. // 驗証碼
  1401. $parms['ck'] = md5($parms['seqno']. 'a' . date('dmh') . 'l' . $parms['lpr'] . 't'. $parms['in_time']. 'o'. $parms['out_time'] . 'b'. $parms['gate_id'] . $function_name);
  1402. // 呼叫
  1403. try{
  1404. $ch = curl_init();
  1405. curl_setopt($ch, CURLOPT_URL, "http://localhost/mitac_service.html/{$function_name}");
  1406. curl_setopt($ch, CURLOPT_HEADER, FALSE);
  1407. curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  1408. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  1409. curl_setopt($ch, CURLOPT_POST, TRUE);
  1410. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT ,3);
  1411. curl_setopt($ch, CURLOPT_TIMEOUT, 3); //timeout in seconds
  1412. curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($parms));
  1413. $data = curl_exec($ch);
  1414. if(curl_errno($ch))
  1415. {
  1416. trigger_error(__FUNCTION__ . ', curl error: '. curl_error($ch));
  1417. }
  1418. curl_close($ch);
  1419. trigger_error(__FUNCTION__ . '..'. $data);
  1420. }catch (Exception $e){
  1421. trigger_error(__FUNCTION__ . 'error:'.$e->getMessage());
  1422. }
  1423. }
  1424. }