VM暫存
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

Cars_model.php 54KB

8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650
  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] 擋重覆 20170912 前端不止一筆 opendoor 送來時, 只處理第一個 (限 2 sec 內)
  141. if($opendoor)
  142. {
  143. $skip_or_not = false;
  144. $new_cars_tmp = array
  145. (
  146. 'timestamp' => time(),
  147. 'sno_io' => $parms['sno'] . $parms['io'],
  148. 'lpr' => $parms['lpr']
  149. );
  150. $cars_tmp_arr = array();
  151. $cars_tmp_log_arr = $this->vars['mcache']->get(CARS_TMP_LOG);
  152. if(!empty($cars_tmp_log_arr))
  153. {
  154. foreach($cars_tmp_log_arr as $tmp)
  155. {
  156. if(isset($tmp['timestamp']) && $tmp['timestamp'] > time() - 2) // 時限內才判斷
  157. {
  158. array_push($cars_tmp_arr, $tmp);
  159. }
  160. }
  161. }
  162. // 判斷是否繼續
  163. foreach($cars_tmp_arr as $tmp)
  164. {
  165. if( $new_cars_tmp['lpr'] == $tmp['lpr'] &&
  166. $new_cars_tmp['sno_io'] == $tmp['sno_io'])
  167. {
  168. $skip_or_not = true;
  169. }
  170. }
  171. // 更新
  172. array_push($cars_tmp_arr, $new_cars_tmp);
  173. $this->vars['mcache']->set(CARS_TMP_LOG, $cars_tmp_arr);
  174. trigger_error(__FUNCTION__ . '..new ' . CARS_TMP_LOG . " |s:{$skip_or_not}|" . print_r($cars_tmp_arr, true));
  175. // 跳過
  176. if($skip_or_not)
  177. {
  178. trigger_error(__FUNCTION__ . '..skip..');
  179. // [msg] 0: 不處理
  180. $msg_id = 0;
  181. return $this->gen_return_msg($msg_id);
  182. }
  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. }