| 
					
				 | 
			
			
				@@ -0,0 +1,277 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+package com.its.bis.service; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.its.app.utils.Elapsed; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.its.app.utils.SysUtils; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.its.app.utils.TimeUtils; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.its.bis.api.dto.AgipObeLoc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.its.bis.config.ServerConfig; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.its.bis.dto.*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.its.bis.entity.TbBisLinkTrafClct; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.its.bis.entity.TbBisVehLoc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.its.bis.process.DbmsData; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.its.bis.process.DbmsDataProcess; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.its.bis.process.DbmsDataType; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import lombok.extern.slf4j.Slf4j; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.slf4j.MDC; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.Map; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.concurrent.LinkedBlockingQueue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@Slf4j 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+public class BisAgipWorker implements Runnable { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private long avgTime = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private int idx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private int qSize; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final ServerConfig config; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final AppRepositoryService repoService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final DbmsDataProcess dbmsDataProcess; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final LinkedBlockingQueue<AgipObeLoc> DATA_QUEUE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public BisAgipWorker(int idx, int qSize, ServerConfig config, AppRepositoryService repoService, DbmsDataProcess dbmsDataProcess) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.idx = idx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.qSize = qSize; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.config = config; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.repoService = repoService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.dbmsDataProcess = dbmsDataProcess; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.DATA_QUEUE = new LinkedBlockingQueue<>(qSize); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected long calcProcessTime(long recvTime) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        long jobTime = System.nanoTime() - recvTime; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (this.avgTime == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.avgTime = jobTime; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.avgTime = (this.avgTime + jobTime) / 2L; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return this.avgTime; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *  작업큐에 데이터 추가 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public boolean add(AgipObeLoc obeLoc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        boolean offer = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //offer => full -> return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //add   => full -> wait 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            offer = this.DATA_QUEUE.offer(obeLoc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!offer) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                MDC.put("id", obeLoc.getDeviceId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                log.error("Packet Queue.offer: {}/{}, Queue Full: {} EA, {}, {}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        obeLoc.getDeviceId(), this.DATA_QUEUE.size(), this.qSize, TimeUtils.elapsedTime(obeLoc.getRcvNanoSeconds()), Thread.currentThread().getName()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                MDC.clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } catch (Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            MDC.put("id", obeLoc.getDeviceId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log.error("Packet Queue.offer: Exception: {}, {}, {}", obeLoc.getDeviceId(), Thread.currentThread().getName(), e.getMessage()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            MDC.clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return offer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public void process(AgipObeLoc obeLoc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        long curr = System.nanoTime(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 샘플데이터: latitude=36.56392018, longitude=128.74352336 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Location currLocation = Location.builder() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .mDistance(0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .mInitialBearing(0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .mFinalBearing(0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .mLatitude(obeLoc.getGnssInfo().getLongitude()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .mLongitude(obeLoc.getGnssInfo().getLatitude()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                .mLatitude(obeLoc.getGnssInfo().getLatitude()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                .mLongitude(obeLoc.getGnssInfo().getLongitude()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .build(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BisObe bisObe = this.repoService.getObeMap(obeLoc.getDeviceId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (bisObe == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            bisObe = BisObe.builder() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .deviceId(obeLoc.getDeviceId()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .carId(obeLoc.getCarId()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .carNumber(obeLoc.getCarNumber()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .location(currLocation) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .moveDist(0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .stNodeId(0L) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .edNodeId(0L) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .trvlHh(0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .stNodeTm(0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .edNodeTm(0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .build(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.repoService.putObeMap(bisObe); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            bisObe.setLocation(currLocation); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        bisObe.setHeight(obeLoc.getGnssInfo().getHeight()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        bisObe.setSpeed(obeLoc.getGnssInfo().getSpeed()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        bisObe.setAngle(obeLoc.getGnssInfo().getAngle()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * 최근접 통과노드정보를 구한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        NearNodeDto passNode = getNearNode(currLocation); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Long stNodeId = bisObe.getStNodeId(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Long edNodeId = bisObe.getEdNodeId(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Long passNodeId = passNode.getNodeId(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (passNodeId != 0L) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log.info("DEVICE ID: {}, 현재노드 통과: {}", bisObe.getDeviceId(), passNodeId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (stNodeId == 0L) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 시작노드가 없으면 시작노드 설정 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                bisObe.setStNodeId(passNodeId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                bisObe.setStNodeTm(System.currentTimeMillis()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                log.info("DEVICE ID: {}, 시작노드 통과: {}", bisObe.getDeviceId(), passNodeId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (!stNodeId.equals(passNodeId) && !edNodeId.equals(passNodeId)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 시작노드 값이 존재하면서 통과노드가 시작노드 및 종료노드와 같지 않으면 종료노드로 설정 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    log.info("DEVICE ID: {}, 종료노드 통과: {}", bisObe.getDeviceId(), passNodeId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 종료노드와 같지 않은 경우 종료노드에 도착한 것이므로 구간 소통정보를 생성하자.... 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    bisObe.setEdNodeId(passNodeId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    bisObe.setEdNodeTm(System.currentTimeMillis()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    int travelSec = (int) ((bisObe.getEdNodeTm() - bisObe.getStNodeTm()) / 1000); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (travelSec > (this.config.getMaxTrvlMin() * 60)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        // 구간 통과 시간이 설정한 값보다 크기 때문에 통행시간을 계산하지 않는다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        // 현재 통과 노드를 시작노드로 설정한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        log.warn("DEVICE ID: {}, 시작노드: {}, 종료노드: {}, 여행시간 오류: {} sec.", bisObe.getDeviceId(), bisObe.getStNodeId(), bisObe.getEdNodeId(), travelSec); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        bisObe.setStNodeId(bisObe.getEdNodeId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        bisObe.setStNodeTm(bisObe.getEdNodeTm()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        bisObe.setEdNodeId(0L); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        bisObe.setEdNodeTm(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        TbLinkDto link = this.repoService.getSectMap(bisObe.getStNodeId(), bisObe.getEdNodeId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (link == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            // 구간을 찾지 못하였음... 종료노드를 시작노드로 설정 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            log.warn("DEVICE ID: {}, 시작노드: {}, 종료노드: {}, 구간 맷칭 오류...", bisObe.getDeviceId(), bisObe.getStNodeId(), bisObe.getEdNodeId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            bisObe.setStNodeId(bisObe.getEdNodeId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            bisObe.setStNodeTm(bisObe.getEdNodeTm()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            bisObe.setEdNodeId(0L); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            bisObe.setEdNodeTm(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            // 구간을 통과하였으므로 구간교통정보를 생성한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            int speed = calcSpeed(link.getLinkLeng(), travelSec); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            log.warn("DEVICE ID: {}, 시작노드: {}, 종료노드: {}, 구간통과: {}, {} m, {} km/h, {} seconds.", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    bisObe.getDeviceId(), bisObe.getStNodeId(), bisObe.getEdNodeId(), link.getLinkId(), link.getLinkLeng(), speed, travelSec); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            TbBisLinkTrafClct bisLinkTrafClct = TbBisLinkTrafClct.builder() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    .CLCT_DT(SysUtils.getSysTime()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    .LINK_ID(link.getLinkId()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    .DEVICE_ID(bisObe.getDeviceId()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    .SPED(speed) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    .TRVL_HH(travelSec) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    .ST_NODE_ARR_DT(TimeUtils.millisToString(bisObe.getStNodeTm())) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    .ED_NODE_ARR_DT(TimeUtils.millisToString(bisObe.getEdNodeTm())) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    .build(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            this.dbmsDataProcess.add(new DbmsData(DbmsDataType.DBMS_DATA_CRT_BIS_LINK_TRAF_CLCT, false, bisLinkTrafClct)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            bisObe.setStNodeId(bisObe.getEdNodeId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            bisObe.setStNodeTm(bisObe.getEdNodeTm()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            bisObe.setEdNodeId(0L); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            bisObe.setEdNodeTm(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    log.info("DEVICE ID: {}, 시작노드: {}, 종료노드: {}, 통과노드: {}", bisObe.getDeviceId(), stNodeId, edNodeId, passNodeId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (stNodeId != 0 && edNodeId != 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 시작노드와 종료노드가 설정된 상태에서 이번에 아무런 노드정보가 없으므로 노드를 빠져 나온것이므로 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 종료노드를 시작노드로 설정하고 종료노드는 0으로 설정한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                log.info("DEVICE ID: {}, 시작노드: {}, 종료노드: {}, 통과노드: {}", bisObe.getDeviceId(), stNodeId, edNodeId, passNodeId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                bisObe.setStNodeId(edNodeId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                bisObe.setStNodeTm(System.currentTimeMillis()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 종료노드 초기화 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                bisObe.setEdNodeId(0L); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                bisObe.setEdNodeTm(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                log.info("DEVICE ID: {}, 시작노드: {}, 종료노드: {}, 통과노드: {}, 구간 운행 중...", bisObe.getDeviceId(), stNodeId, edNodeId, passNodeId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * 버스 현재위치 정보를 업데이트 한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        TbBisVehLoc bisVehLoc = TbBisVehLoc.builder() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .DEVICE_ID(bisObe.getDeviceId()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .CLCT_DT(SysUtils.getSysTime()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .LOC_TYPE(obeLoc.getGnssInfo().getType()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .SPEED(obeLoc.getGnssInfo().getSpeed()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .HEGT(obeLoc.getGnssInfo().getHeight()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .ANGLE(obeLoc.getGnssInfo().getAngle()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .LNG(obeLoc.getGnssInfo().getLongitude()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .LAT(obeLoc.getGnssInfo().getLatitude()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .PASS_NODE_ID(passNodeId) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .build(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.dbmsDataProcess.add(new DbmsData(DbmsDataType.DBMS_DATA_UPD_BIS_VEH_LOC, false, bisVehLoc)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public void report() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        long avgTime = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("Packet: Remain Q: {}, Average: {}, {}", this.DATA_QUEUE.size(), TimeUtils.elapsedTimeStr(avgTime), Thread.currentThread().getName()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public int calcSpeed(int distance, int seconds) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        int speed; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (distance <= 0 || seconds <= 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speed = (int)(((distance * 3.6) / (float)seconds) + 0.5); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return speed; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public NearNodeDto getNearNode(Location loc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Elapsed elapsed = new Elapsed(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //Location(mDistance=0.0, mInitialBearing=0.0, mFinalBearing=0.0, mLatitude=128.73881251, mLongitude=36.56128759) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        double maxDistance = this.config.getMaxDistance(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        NearNodeDto nearNode = NearNodeDto.builder().nodeId(0L).distance(maxDistance).build(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (Map.Entry<Long, TbNodeDto> e : this.repoService.getEntrySetNode()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            TbNodeDto node = e.getValue(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            double fDistance = (float) getDistance(loc.getMLatitude(), loc.getMLongitude(), node.getXCrdn(), node.getYCrdn()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (fDistance < maxDistance) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                maxDistance = fDistance; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                nearNode.setNodeId(node.getNodeId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                nearNode.setDistance(fDistance); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //log.info("{}", nearNode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("getNearNode: {} ms. {} m, {}", elapsed.milliSeconds(), maxDistance, nearNode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return nearNode; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public double getDistance(double lat1, double lon1, double lat2, double lon2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        double EARTH_RADIUS = 6371.0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        double dLat = Math.toRadians(lat2 - lat1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        double dLon = Math.toRadians(lon2 - lon1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        double a = Math.sin(dLat/2)* Math.sin(dLat/2)+ Math.cos(Math.toRadians(lat1))* Math.cos(Math.toRadians(lat2))* Math.sin(dLon/2)* Math.sin(dLon/2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return (EARTH_RADIUS * c * 1000);    // Distance in m 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public void run() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("{} Start. Q_SIZE: {}", Thread.currentThread().getName(), this.qSize); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        while (true) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                AgipObeLoc obeLoc = this.DATA_QUEUE.take(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (obeLoc != null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    process(obeLoc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    Thread.yield(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            catch (Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                log.error("Exception: {}", e.getMessage()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |