VM暫存
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

1778 líneas
59KB

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