VM暫存
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

1670 строки
58KB

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