VM暫存
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

1652 lines
54KB

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