shjung 3 éve
szülő
commit
9531212b93
28 módosított fájl, 1143 hozzáadás és 259 törlés
  1. 17 4
      src/main/java/com/beanit/asn1dsrc/enums/eAuthInfo.java
  2. 18 2
      src/main/java/com/beanit/asn1dsrc/util/DsrcAsn1Utils.java
  3. 8 8
      src/main/java/com/its/dsrc/DsrcCommServerApplication.java
  4. 2 2
      src/main/java/com/its/dsrc/config/RunningConfig.java
  5. 44 1
      src/main/java/com/its/dsrc/entity/TbRseCtlr.java
  6. 8 0
      src/main/java/com/its/dsrc/scheduler/SchedulerTask.java
  7. 16 0
      src/main/java/com/its/dsrc/service/RseCtlrService.java
  8. 17 10
      src/main/java/com/its/dsrc/ui/CtlrSttsTableCellRenderer.java
  9. 49 26
      src/main/java/com/its/dsrc/ui/CtlrSttsTableModel.java
  10. 21 12
      src/main/java/com/its/dsrc/ui/MainUI.java
  11. 5 4
      src/main/java/com/its/dsrc/xnettcp/dsrc/codec/DsrcTcpServerDecoder.java
  12. 2 2
      src/main/java/com/its/dsrc/xnettcp/dsrc/codec/DsrcTcpServerEncoder.java
  13. 3 0
      src/main/java/com/its/dsrc/xnettcp/dsrc/handler/DsrcAsn1ServerIdleStateConnectionHandler.java
  14. 0 5
      src/main/java/com/its/dsrc/xnettcp/dsrc/handler/DsrcAsn1ServerLoginInboundHandler.java
  15. 2 2
      src/main/java/com/its/dsrc/xnettcp/dsrc/handler/DsrcAsn1ServerPacketInboundHandler.java
  16. 12 3
      src/main/java/com/its/dsrc/xnettcp/dsrc/process/TcpServerDataProcess.java
  17. 1 1
      src/main/java/com/its/dsrc/xnettcp/dsrc/process/TcpServerDataTask.java
  18. 66 6
      src/main/java/com/its/dsrc/xnettcp/dsrc/process/response/AcceptResponse.java
  19. 39 3
      src/main/java/com/its/dsrc/xnettcp/dsrc/process/response/FredResponse.java
  20. 13 1
      src/main/java/com/its/dsrc/xnettcp/dsrc/process/response/InitiateResponse.java
  21. 3 3
      src/main/java/com/its/dsrc/xnettcp/dsrc/process/response/PublicationResponse.java
  22. 120 118
      src/main/java/com/its/dsrc/xnettcp/dsrc/process/service/ControlDeviceService.java
  23. 288 22
      src/main/java/com/its/dsrc/xnettcp/dsrc/process/service/LoginDeviceService.java
  24. 44 2
      src/main/java/com/its/dsrc/xnettcp/dsrc/process/service/impl/SubscriptionRegisterService.java
  25. 2 2
      src/main/java/com/its/dsrc/xnettcp/dsrc/process/service/impl/SubscriptionSingleService.java
  26. 2 2
      src/main/resources/application.yml
  27. 1 1
      src/main/resources/mybatis/mapper/RseObuClctMapper.xml
  28. 340 17
      src/test/java/com/its/app/DsrcCommServerApplicationTests.java

+ 17 - 4
src/main/java/com/beanit/asn1dsrc/enums/eAuthInfo.java

@@ -5,6 +5,19 @@ import java.util.Map;
 
 public enum eAuthInfo {
 
+//    AI_Null        (0x00, "AI_Null"),               /* NULL */
+//    AI_Initiate    (0x01, "AI_Initiate"),           /* 초기 통신연결을 위한 개시 요청 데이터 패킷 */
+//    AI_Login       (0x02, "AI_Login"),              /* 서버에 접속하기 위한 클라이언트의 로그인 데이터 패킷 */
+//    AI_FrED        (0x03, "AI_FrED"),               /* 서버와 클라이언트의 연결을 유지하기 위한 확인 데이터 패킷 */
+//    AI_Terminate   (0x04, "AI_Terminate"),          /* 연결을 종료하고자 할 때, 서버에서 클라이언트에 요청하는 데이터 패킷 */
+//    AI_Logout      (0x05, "AI_Logout"),             /* 접속을 종료하기 위한 클라이언트의 로그아웃 데이터 패킷 */
+//    AI_Subscription(0x06, "AI_Subscription"),       /* 클라이언트가 서버에 정보를 요청할 경우 송신하는 데이터 패킷 */
+//    AI_Publication (0x07, "AI_Publication"),        /* 클라이언트가 요청한 정보를 제공하기 위한 데이터 패킷 - 요청에 대한 정보공개*/
+//    AI_TransferDone(0x08, "AI_TransferDone"),       /* 클라이언트가 요청한 정보를 파일형태로 제공하기 위한 데이터 패킷 */
+//    AI_Accept      (0x09, "AI_Accept"),             /* 클라이언트의 요청에 대한 수용 */
+//    AI_Reject      (0x0A, "AI_Reject"),             /* 클라이언트의 요청에 대한 거부 */
+//    AI_NonCryptObu (0x21, "AI_NonCryptObu"),
+//    AI_Multimedia  (0x22, "AI_Multimedia");
     AI_Null        (0x00, "AI_Null"),               /* NULL */
     AI_Initiate    (0x01, "AI_Initiate"),           /* 초기 통신연결을 위한 개시 요청 데이터 패킷 */
     AI_Login       (0x02, "AI_Login"),              /* 서버에 접속하기 위한 클라이언트의 로그인 데이터 패킷 */
@@ -12,10 +25,10 @@ public enum eAuthInfo {
     AI_Terminate   (0x04, "AI_Terminate"),          /* 연결을 종료하고자 할 때, 서버에서 클라이언트에 요청하는 데이터 패킷 */
     AI_Logout      (0x05, "AI_Logout"),             /* 접속을 종료하기 위한 클라이언트의 로그아웃 데이터 패킷 */
     AI_Subscription(0x06, "AI_Subscription"),       /* 클라이언트가 서버에 정보를 요청할 경우 송신하는 데이터 패킷 */
-    AI_Publication (0x07, "AI_Publication"),        /* 클라이언트가 요청한 정보를 제공하기 위한 데이터 패킷 - 요청에 대한 정보공개*/
-    AI_TransferDone(0x08, "AI_TransferDone"),       /* 클라이언트가 요청한 정보를 파일형태로 제공하기 위한 데이터 패킷 */
-    AI_Accept      (0x09, "AI_Accept"),             /* 클라이언트의 요청에 대한 수용 */
-    AI_Reject      (0x0A, "AI_Reject"),             /* 클라이언트의 요청에 대한 거부 */
+    AI_Publication (0x40, "AI_Publication"),        /* 클라이언트가 요청한 정보를 제공하기 위한 데이터 패킷 - 요청에 대한 정보공개*/
+    AI_TransferDone(0x07, "AI_TransferDone"),       /* 클라이언트가 요청한 정보를 파일형태로 제공하기 위한 데이터 패킷 */
+    AI_Accept      (0x08, "AI_Accept"),             /* 클라이언트의 요청에 대한 수용 */
+    AI_Reject      (0x09, "AI_Reject"),             /* 클라이언트의 요청에 대한 거부 */
     AI_NonCryptObu (0x21, "AI_NonCryptObu"),
     AI_Multimedia  (0x22, "AI_Multimedia");
 

+ 18 - 2
src/main/java/com/beanit/asn1dsrc/util/DsrcAsn1Utils.java

@@ -40,24 +40,40 @@ public final class DsrcAsn1Utils {
     }
     public static Time getRegisterStartTime() {
         Time tm = new Time();
+        Time.TimeSecondFractions tmSecond = new Time.TimeSecondFractions();
+        tmSecond.setDeciSeconds(new BerInteger(0));
 
-        tm.setTimeYearQty(new BerInteger(2021));
+        Time.TimeTimezone tmZone = new Time.TimeTimezone();
+        tmZone.setTimezoneHourQty(new BerInteger(9));
+        tmZone.setTimeMinuteQty(new BerInteger(0));
+
+        tm.setTimeYearQty(new BerInteger(2022));
         tm.setTimeMonthQty(new BerInteger(1));
         tm.setTimeDayQty(new BerInteger(1));
         tm.setTimeHourQty(new BerInteger(0));
         tm.setTimeMinuteQty(new BerInteger(0));
         tm.setTimeSecondQty(new BerInteger(0));
+        tm.setTimeSecondFractions(tmSecond);
+        tm.setTimeTimezone(tmZone);
         return tm;
     }
     public static Time getRegisterEndTime() {
         Time tm = new Time();
+        Time.TimeSecondFractions tmSecond = new Time.TimeSecondFractions();
+        tmSecond.setDeciSeconds(new BerInteger(0));
+
+        Time.TimeTimezone tmZone = new Time.TimeTimezone();
+        tmZone.setTimezoneHourQty(new BerInteger(9));
+        tmZone.setTimeMinuteQty(new BerInteger(0));
 
-        tm.setTimeYearQty(new BerInteger(2040));
+        tm.setTimeYearQty(new BerInteger(2099));
         tm.setTimeMonthQty(new BerInteger(12));
         tm.setTimeDayQty(new BerInteger(31));
         tm.setTimeHourQty(new BerInteger(0));
         tm.setTimeMinuteQty(new BerInteger(0));
         tm.setTimeSecondQty(new BerInteger(0));
+        tm.setTimeSecondFractions(tmSecond);
+        tm.setTimeTimezone(tmZone);
         return tm;
     }
 

+ 8 - 8
src/main/java/com/its/dsrc/DsrcCommServerApplication.java

@@ -113,7 +113,7 @@ public class DsrcCommServerApplication implements CommandLineRunner, Application
                     }
                 });
                 frame.pack();
-                frame.setBounds(100, 100, 1000, 800);
+                frame.setBounds(100, 100, 800, 920);
                 frame.setLocationRelativeTo(null);
                 frame.setVisible(true);
 
@@ -163,21 +163,21 @@ public class DsrcCommServerApplication implements CommandLineRunner, Application
         MultimediaService multimediaService = (MultimediaService)AppUtils.getBean(MultimediaService.class);
         multimediaService.loadMaster();
 
-        DsrcTcpCommServerService dsrcTcpCommServerService = (DsrcTcpCommServerService)AppUtils.getBean(DsrcTcpCommServerService.class);
-        dsrcTcpCommServerService.run();
-
-        CenterTcpServerService centerService = (CenterTcpServerService)AppUtils.getBean(CenterTcpServerService.class);
-        centerService.run();
-
         // schedule enable
         applicationConfig.setStartSchedule(true);
 
         if (OS.isWindows()) {
             MainUI UI = MainUI.getInstance();
             if (UI != null) {
-                UI.LoadControllerInfo();
+                UI.loadControllerInfo();
             }
         }
+
+        DsrcTcpCommServerService dsrcTcpCommServerService = (DsrcTcpCommServerService)AppUtils.getBean(DsrcTcpCommServerService.class);
+        dsrcTcpCommServerService.run();
+
+        CenterTcpServerService centerService = (CenterTcpServerService)AppUtils.getBean(CenterTcpServerService.class);
+        centerService.run();
     }
 
     public void terminateApplication() {

+ 2 - 2
src/main/java/com/its/dsrc/config/RunningConfig.java

@@ -28,8 +28,8 @@ public class RunningConfig {
     private boolean dumpSend = true;
 
     private String serverDomainName = "GJATMSSERVER";
-    private String serverAuthUser = "test1";
-    private String serverAuthPassword = "test1";
+    private String serverAuthUser = "PTATMS";
+    private String serverAuthPassword = "PTATMS";
     private String serverSenderText = "DSRC Center Unit";
 
     private boolean publicationMultimedia = false;

+ 44 - 1
src/main/java/com/its/dsrc/entity/TbRseCtlr.java

@@ -10,6 +10,7 @@ import com.beanit.asn1dsrc.util.DsrcAsn1Sequence;
 import com.its.app.utils.SysUtils;
 import com.its.dsrc.vo.NET;
 import com.its.dsrc.xnettcp.dsrc.handler.DsrcAsn1ServerIdleStateConnectionHandler;
+import com.its.dsrc.xnettcp.dsrc.process.response.FredResponse;
 import com.its.dsrc.xnettcp.dsrc.process.service.ControlDeviceService;
 import com.its.dsrc.xnettcp.dsrc.task.DsrcAsn1TimeoutTask;
 import io.netty.channel.Channel;
@@ -21,6 +22,7 @@ import lombok.extern.slf4j.Slf4j;
 
 import java.net.InetSocketAddress;
 import java.nio.ByteBuffer;
+import java.text.SimpleDateFormat;
 import java.util.Map;
 import java.util.Timer;
 import java.util.TimerTask;
@@ -69,6 +71,8 @@ public class TbRseCtlr {
 	private int connectCount;
 	private String connectTm;
 	private String disConnectTm;
+	private long lastRecvTime;
+
 	public Integer getId() {
 		return Integer.parseInt(this.RSE_CTLR_NMBR);
 	}
@@ -85,9 +89,21 @@ public class TbRseCtlr {
 		this.connectCount = 0;
 		this.connectTm = "";
 		this.disConnectTm = "";
+		this.lastRecvTime = 0;
 
 		initNet();
 	}
+	public void setLastRecvTime() {
+		this.lastRecvTime = System.currentTimeMillis();
+//		MainUI mainUI = MainUI.getInstance();
+//		if (mainUI != null) {
+//			mainUI.updateCtlrStts(this);
+//		}
+	}
+	public String getLastRecvTimeFmt() {
+		SimpleDateFormat sdfDate = new SimpleDateFormat("MM-dd HH:mm:ss");
+		return sdfDate.format(lastRecvTime);
+	}
 
 	public String getID() {
 		return this.RSE_CTLR_NMBR;
@@ -138,7 +154,18 @@ public class TbRseCtlr {
 		}
 		this.registeredCommandsTimer.clear();
 
-		this.netState = com.its.dsrc.vo.NET.LOGINED;
+		this.netState = NET.LOGINED;
+		setConnectTm();
+	}
+	public synchronized void channelLoginInit() {
+		this.registeredCommands.clear();
+		for (Map.Entry<Long, Timer> e : this.registeredCommandsTimer.entrySet()) {
+			Timer task = e.getValue();
+			task.cancel();
+		}
+		this.registeredCommandsTimer.clear();
+
+		this.netState = NET.LOGINED;
 		setConnectTm();
 	}
 
@@ -203,6 +230,7 @@ public class TbRseCtlr {
 		eControlDeviceId controlDeviceId = eControlDeviceId.getByValue(devcType);
 		eControlCommand commandType = eControlCommand.getByValue(cntlType);
 		if (controlDeviceId == null || commandType == null) {
+			log.error("Reset Request: control type missMatched: [{}], {}, {}", this, controlDeviceId, commandType);
 			return 2;
 		}
 
@@ -302,4 +330,19 @@ public class TbRseCtlr {
 		return c2c;
 	}
 
+	public synchronized boolean sendFrED() {
+		if (getChannel() == null || getNetState() == NET.CLOSED) {
+			log.error("sendFrED Request: channel not connected: [{}]", this);
+			return false;
+		}
+		return FredResponse.sendFrED(this, getChannel());
+	}
+
+	public int getManufacturerid() {
+		return 0;
+	}
+
+	public int getIndividualid() {
+		return 0;
+	}
 }

+ 8 - 0
src/main/java/com/its/dsrc/scheduler/SchedulerTask.java

@@ -102,4 +102,12 @@ public class SchedulerTask {
         log.info("schedule5M..: ..end. {} ms. {}", elapsed.milliSeconds(), Thread.currentThread().getName());
     }
 
+    @Scheduled(cron = "0/10 * * * * *")  // 10초 주기 작업 실행
+    public void scheduleFrED() {
+        if (!this.applicationConfig.isStartSchedule()) {
+            return;
+        }
+//        this.rseCtlrService.monitoringSession();
+    }
+
 }

+ 16 - 0
src/main/java/com/its/dsrc/service/RseCtlrService.java

@@ -142,4 +142,20 @@ public class RseCtlrService {
         log.info("RseCtlrService.updateCtlrStts: total {}, normal {}, error {}", normal + error, normal, error);
     }
 
+    public void monitoringSession() {
+        long currMilliSeconds = System.currentTimeMillis();
+        for (Map.Entry<String, TbRseCtlr> e : AppRepository.getInstance().getCtlrMap().entrySet()) {
+            TbRseCtlr obj = e.getValue();
+            if (obj.getNetState() >= NET.LOGIN_REQ && obj.getChannel() != null) {
+                // 주차정보시스템 통신정상
+                long recvTimout = currMilliSeconds - obj.getLastRecvTime();
+                if (recvTimout > 15*1000) {
+                    log.error("Idle timeout: {}, ipAddr={}, Idle={} sec.", obj.getID(), obj.getRSE_ID(), (int)(recvTimout/1000L));
+                    obj.setLastRecvTime();
+                    obj.sendFrED();
+                }
+
+            }
+        }
+    }
 }

+ 17 - 10
src/main/java/com/its/dsrc/ui/CtlrSttsTableCellRenderer.java

@@ -12,22 +12,29 @@ public class CtlrSttsTableCellRenderer extends DefaultTableCellRenderer {
         String commStts = table.getModel().getValueAt(row, 6).toString();
         if (commStts.equals("Connect")) {
             cell.setBackground(new Color(255, 255, 255, 255));
-            if (column == 7) {
-                String door = table.getModel().getValueAt(row, 7).toString();
+//            if (column == 7) {
+//                String door = table.getModel().getValueAt(row, 7).toString();
+//                if (door.equals("열림")) {
+//                    cell.setBackground(new Color(255, 0, 0, 176));
+//                    cell.setForeground(new Color(255, 255, 255, 255));
+//                }
+//            }
+            if (column == 8) {
+                String door = table.getModel().getValueAt(row, 8).toString();
                 if (door.equals("열림")) {
                     cell.setBackground(new Color(255, 0, 0, 176));
                     cell.setForeground(new Color(255, 255, 255, 255));
                 }
             }
-            if (column == 8) {
-                String fan = table.getModel().getValueAt(row, 8).toString();
-                if (fan.equals("가동")) {
-                    cell.setBackground(new Color(255, 213, 0, 250));
-                    cell.setForeground(new Color(0, 0, 0, 255));
+            if (column == 9) {
+                String door = table.getModel().getValueAt(row, 9).toString();
+                if (door.equals("열림")) {
+                    cell.setBackground(new Color(255, 0, 0, 176));
+                    cell.setForeground(new Color(255, 255, 255, 255));
                 }
             }
-            if (column == 9) {
-                String heater = table.getModel().getValueAt(row, 9).toString();
+            if (column == 10) {
+                String heater = table.getModel().getValueAt(row, 10).toString();
                 if (heater.equals("가동")) {
                     cell.setBackground(new Color(255, 213, 0, 250));
                     cell.setForeground(new Color(0, 0, 0, 255));
@@ -35,7 +42,7 @@ public class CtlrSttsTableCellRenderer extends DefaultTableCellRenderer {
             }
             if (column == 11) {
                 String video = table.getModel().getValueAt(row, 11).toString();
-                if (video.equals("이상")) {
+                if (video.equals("가동")) {
                     cell.setBackground(new Color(255, 213, 0, 250));
                     cell.setForeground(new Color(0, 0, 0, 255));
                 }

+ 49 - 26
src/main/java/com/its/dsrc/ui/CtlrSttsTableModel.java

@@ -22,11 +22,11 @@ public class CtlrSttsTableModel extends AbstractTableModel {
             "IP",
             "PORT",
             "연결상태",
-            "장치상태",
-            "ATN-1",
-            "ATN-2",
-            "ATN-3",
-            "ATN-4",
+            "온도",
+            "앞문",
+            "뒷문",
+            "",
+            "히터",
             "연결 시각",
             "연결종료 시각"
     };
@@ -89,24 +89,47 @@ public class CtlrSttsTableModel extends AbstractTableModel {
 
             int netState = info.getNetState();
             TbRseCtlrStts stts = info.getStts();
-            String devStts = "-";
-            String antena1 = "-";
-            String antena2 = "-";
-            String antena3 = "-";
-            String antena4 = "-";
+            String temper = "-";
+            String fDoor = "-";
+            String bDoor = "-";
+            String fan = "-";
+            String hetr = "-";
+            String rtu = "-";
             if ("CMS0".equals(stts.getCMNC_STTS_CD())) {
-               switch(Integer.parseInt(stts.getCNTL_DEVC_STTS())) {
-                   case 0: devStts = "정상"; break;
-                   case 1: devStts = "문열림"; break;
-                   case 2: devStts = "팬동작"; break;
-                   case 3: devStts = "온도이상"; break;
-                   case 4: devStts = "정보없음"; break;
-                   default: devStts = stts.getCNTL_DEVC_STTS(); break;
+//               switch(Integer.parseInt(stts.getCNTL_DEVC_STTS())) {
+//                   case 0: devStts = "정상"; break;
+//                   case 1: devStts = "문열림"; break;
+//                   case 2: devStts = "팬동작"; break;
+//                   case 3: devStts = "온도이상"; break;
+//                   case 4: devStts = "정보없음"; break;
+//                   default: devStts = stts.getCNTL_DEVC_STTS(); break;
+//                }
+                temper = String.valueOf(stts.getCBOX_TMPR());
+                if ("CDS0".equals(stts.getFRONT_DOOR_STTS_CD())) {
+                    fDoor = "닫힘";
+                } else if ("CDS1".equals(stts.getFRONT_DOOR_STTS_CD())) {
+                    fDoor = "열림";
+                }
+                if ("CDS0".equals(stts.getBACK_DOOR_STTS_CD())) {
+                    bDoor = "닫힘";
+                } else if ("CDS1".equals(stts.getBACK_DOOR_STTS_CD())) {
+                    bDoor = "열림";
+                }
+                if ("PAS0".equals(stts.getFAN_STTS_CD())) {
+                    fan = "가동";
+                } else if ("PAS1".equals(stts.getFAN_STTS_CD())) {
+                    fan = "중지";
+                }
+                if ("HTS0".equals(stts.getHETR_STTS_CD())) {
+                    hetr = "가동";
+                } else if ("HTS1".equals(stts.getHETR_STTS_CD())) {
+                    hetr = "중지";
+                }
+                if ("RTU1".equals(stts.getRTU_STTS_CD())) {
+                    rtu = "정상";
+                } else if ("VDI1".equals(stts.getRTU_STTS_CD())) {
+                    rtu = "이상";
                 }
-                antena1 = stts.getATN_1_STTS();
-                antena2 = stts.getATN_2_STTS();
-                antena3 = stts.getATN_3_STTS();
-                antena4 = stts.getATN_4_STTS();
             }
             switch (columnIndex) {
                 case 0:
@@ -130,11 +153,11 @@ public class CtlrSttsTableModel extends AbstractTableModel {
                 case 6:
                     returnValue = netStateStr[netState];
                     break;
-                case  7: returnValue = devStts; break;
-                case  8: returnValue = antena1; break;
-                case  9: returnValue = antena2; break;
-                case 10: returnValue = antena3; break;
-                case 11: returnValue = antena4; break;
+                case  7: returnValue = temper; break;
+                case  8: returnValue = fDoor; break;
+                case  9: returnValue = bDoor; break;
+                case 10: returnValue = fan; break;
+                case 11: returnValue = hetr; break;
                 case 12:
                     returnValue = info.getConnectTm();
                     break;

+ 21 - 12
src/main/java/com/its/dsrc/ui/MainUI.java

@@ -280,19 +280,19 @@ public class MainUI {
 
         TableColumnModel getColumnModel = tblCtlrList.getColumnModel();
         getColumnModel.getColumn(0).setPreferredWidth(30);  //  "S",
-        getColumnModel.getColumn(1).setPreferredWidth(60);  //  "번호",
-        getColumnModel.getColumn(2).setPreferredWidth(140);  //  "시설물ID",
-        getColumnModel.getColumn(3).setPreferredWidth(210); //  "명칭",
-        getColumnModel.getColumn(4).setPreferredWidth(120); //  "IP",
+        getColumnModel.getColumn(1).setPreferredWidth(50);  //  "번호",
+        getColumnModel.getColumn(2).setPreferredWidth(120);  //  "시설물ID",
+        getColumnModel.getColumn(3).setPreferredWidth(180); //  "명칭",
+        getColumnModel.getColumn(4).setPreferredWidth(100); //  "IP",
         //getColumnModel.getColumn(5).setPreferredWidth(0);  //  "PORT",
         getColumnModel.getColumn(6).setPreferredWidth(70);  //  "연결상태",
-        getColumnModel.getColumn(7).setPreferredWidth(80); //  "장치상태",
-        getColumnModel.getColumn(8).setPreferredWidth(50);  //  "안테나1",
-        getColumnModel.getColumn(9).setPreferredWidth(50);  //  "안테나2",
-        getColumnModel.getColumn(10).setPreferredWidth(50); //  "안테나3",
-        getColumnModel.getColumn(11).setPreferredWidth(50); //  "안테나4",
-        getColumnModel.getColumn(12).setPreferredWidth(130);
-        getColumnModel.getColumn(13).setPreferredWidth(130);
+//        getColumnModel.getColumn(7).setPreferredWidth(50); //  "장치상태",
+//        getColumnModel.getColumn(8).setPreferredWidth(50);  //  "안테나1",
+//        getColumnModel.getColumn(9).setPreferredWidth(50);  //  "안테나2",
+//        getColumnModel.getColumn(10).setPreferredWidth(50); //  "안테나3",
+//        getColumnModel.getColumn(11).setPreferredWidth(50); //  "안테나4",
+        getColumnModel.getColumn(12).setPreferredWidth(150);
+        getColumnModel.getColumn(13).setPreferredWidth(150);
 
         getColumnModel.getColumn(0).setMaxWidth(30);
         getColumnModel.getColumn(0).setMinWidth(30);
@@ -303,6 +303,13 @@ public class MainUI {
         getColumnModel.getColumn(5).setWidth(0);
         getColumnModel.getColumn(5).setResizable(false);
 
+        for (int ii = 7; ii <= 11; ii++) {
+            getColumnModel.getColumn(ii).setMinWidth(0);
+            getColumnModel.getColumn(ii).setMaxWidth(0);
+            getColumnModel.getColumn(ii).setWidth(0);
+            getColumnModel.getColumn(ii).setResizable(false);
+        }
+
         Color color = UIManager.getColor("Table.gridColor");
         MatteBorder border = new MatteBorder(1, 1, 0, 0, color);
         tblCtlrList.setBorder(border);
@@ -338,7 +345,8 @@ public class MainUI {
         }
     }
 
-    public void LoadControllerInfo() {
+    public void loadControllerInfo() {
+        log.info("loadControllerInfo: start. {} EA.", AppRepository.getInstance().getCtlrMap().size());
         SortedMap<Integer, TbRseCtlr> ctlrMap = new TreeMap<>();
         for (Map.Entry<String, TbRseCtlr> e : AppRepository.getInstance().getCtlrMap().entrySet()) {
             TbRseCtlr obj = e.getValue();
@@ -349,6 +357,7 @@ public class MainUI {
         List<TbRseCtlr> ctlrList = new ArrayList<TbRseCtlr>(ctlrMap.values());
         initTblListUI(ctlrList);
         updateCommSttsTotal();
+        log.info("loadControllerInfo: ..end. {} EA.", ctlrList.size());
     }
 
     public void updateCtlrStts(TbRseCtlr obj) {

+ 5 - 4
src/main/java/com/its/dsrc/xnettcp/dsrc/codec/DsrcTcpServerDecoder.java

@@ -84,9 +84,9 @@ public class DsrcTcpServerDecoder extends ByteToMessageDecoder {
                 }
 
                 if (pktLength > readableBytes) {
-                        log.warn("RECV: Decoder: {}. [pktLength > readableBytes]", ipAddress);
-                        log.warn("RECV: Decoder: {}. [Readable:{}, RIDX:{}-WIDX:{}]. Packet Remain.", ipAddress, readableBytes, byteBuf.readerIndex(), byteBuf.writerIndex());
-                        break;
+                    log.warn("RECV: Decoder: {}. [pktLength > readableBytes]", ipAddress);
+                    log.warn("RECV: Decoder: {}. [Readable:{}, RIDX:{}-WIDX:{}]. Packet Remain.", ipAddress, readableBytes, byteBuf.readerIndex(), byteBuf.writerIndex());
+                    break;
                 }
 
                 // 패킷 읽은 만큼 이동
@@ -98,7 +98,8 @@ public class DsrcTcpServerDecoder extends ByteToMessageDecoder {
                 C2CAuthenticatedMessage c2c = new C2CAuthenticatedMessage();
                 authLength = c2c.decode(new ByteArrayInputStream(berOctetString.value, 0, berOctetString.value.length));
                 //log.info("RECV: Decoder: {}. ASN1 PACKET: {} Bytes, decodeLength: {} Bytes", ipAddress, pktLength, authLength);
-                log.info("RECV: Decoder: {}, C2CAuth: {}", ipAddress, c2c);
+                //log.info("RECV: Decoder: {}, C2CAuth: {}", ipAddress, c2c);
+                obj.setLastRecvTime();
                 list.add(c2c);
 
                 readableBytes = byteBuf.readableBytes();

+ 2 - 2
src/main/java/com/its/dsrc/xnettcp/dsrc/codec/DsrcTcpServerEncoder.java

@@ -75,8 +75,8 @@ public class DsrcTcpServerEncoder extends MessageToByteEncoder<Object> {
 
                 int encodeLength = dataPkt.encode(pktBuff);
                 byteBuf.writeBytes(pktBuff.getArray());
-                log.info("SEND: Encoder: {}. ASN1 PACKET: {} Bytes, encodeLength: {} Bytes", ipAddress, length, encodeLength);
-                log.debug("SEND: Encoder: {}, C2CAuth: {}", ipAddress, c2c.toString());
+                //log.info("SEND: Encoder: {}. ASN1 PACKET: {} Bytes, encodeLength: {} Bytes", ipAddress, length, encodeLength);
+                //log.info("SEND: Encoder: {}, C2CAuth: {}", ipAddress, c2c);
                 if (this.runningConfig.isDumpSend()) {
                     byte[] debugBytes = new byte[byteBuf.readableBytes()];
                     byteBuf.getBytes(byteBuf.readerIndex(), debugBytes);

+ 3 - 0
src/main/java/com/its/dsrc/xnettcp/dsrc/handler/DsrcAsn1ServerIdleStateConnectionHandler.java

@@ -2,6 +2,7 @@ package com.its.dsrc.xnettcp.dsrc.handler;
 
 import com.beanit.asn1dsrc.util.DsrcAsn1Utils;
 import com.its.app.utils.NettyUtils;
+import com.its.app.utils.SysUtils;
 import com.its.dsrc.config.RunningConfig;
 import com.its.dsrc.entity.TbRseCtlr;
 import com.its.dsrc.global.AppRepository;
@@ -109,8 +110,10 @@ public class DsrcAsn1ServerIdleStateConnectionHandler extends ChannelDuplexHandl
             ctx.channel().pipeline().remove(this);                              // First packet recv/send timeout handler(dsrcAsn1ServerConnectionHandler)
 
             obj.setNetState(NET.LOGIN_REQ);
+            obj.setConnectTm(SysUtils.getSysTimeStr());
             obj.setChannel(ctx.channel());
             obj.setHeaderOptions(DsrcAsn1Utils.getDefaultOptions());
+            obj.setLastRecvTime();
 
             MDC.remove(obj.getLogKey());
             MDC.clear();

+ 0 - 5
src/main/java/com/its/dsrc/xnettcp/dsrc/handler/DsrcAsn1ServerLoginInboundHandler.java

@@ -29,11 +29,6 @@ public class DsrcAsn1ServerLoginInboundHandler extends ChannelInboundHandlerAdap
     private final DbmsDataProcess dbmsDataProcess;
     private final RunningConfig runningConfig;
 
-//    public DsrcAsn1ServerLoginInboundHandler() {
-//        super();
-//        this.config = (DsrcConfig) AppUtils.getBean(DsrcConfig.class);
-//    }
-
     @Override
     public void channelActive(ChannelHandlerContext ctx) throws Exception {
         super.channelActive(ctx);

+ 2 - 2
src/main/java/com/its/dsrc/xnettcp/dsrc/handler/DsrcAsn1ServerPacketInboundHandler.java

@@ -24,8 +24,8 @@ public class DsrcAsn1ServerPacketInboundHandler extends ChannelInboundHandlerAda
             log.error("{} | Received Data is not C2CAuthenticatedMessage", NettyUtils.getRemoteAddress(ctx.channel()));
             return;
         }
-        C2CAuthenticatedMessage c2c = (C2CAuthenticatedMessage)msg;
-        log.info("DsrcAsn1ServerPacketHandler: channelRead: {}, {}", NettyUtils.getRemoteAddress(ctx.channel()), c2c);
+//        C2CAuthenticatedMessage c2c = (C2CAuthenticatedMessage)msg;
+//        log.info("DsrcAsn1ServerPacketHandler: channelRead: {}, {}", NettyUtils.getRemoteAddress(ctx.channel()), c2c);
         this.tcpServerDataProcess.add(new TcpServerData(TcpServerData.DATA_TYPE_PACKET, null, ctx, msg));
     }
 }

+ 12 - 3
src/main/java/com/its/dsrc/xnettcp/dsrc/process/TcpServerDataProcess.java

@@ -1,6 +1,7 @@
 package com.its.dsrc.xnettcp.dsrc.process;
 
 import com.beanit.asn1dsrc.dsrc.C2CAuthenticatedMessage;
+import com.beanit.asn1dsrc.dsrc.PDUs;
 import com.beanit.asn1dsrc.enums.eAuthInfo;
 import com.its.app.AppUtils;
 import com.its.app.utils.NettyUtils;
@@ -70,10 +71,10 @@ public class TcpServerDataProcess {
         try {
             ChannelHandlerContext ctx = data.getCtx();
             Channel channel = ctx.channel();
-            //String tcpAddress = NettyUtils.getTcpAddress(channel);    // local/remote address 를 폼함한 문자열
             String ipAddress = NettyUtils.getRemoteIpAddress(channel);
             TbRseCtlr obj = AppRepository.getInstance().getCtlrIpMap().get(ipAddress);;
             C2CAuthenticatedMessage c2c = (C2CAuthenticatedMessage)data.getData();
+            PDUs pdus = c2c.getPdu();
 
             if (obj == null || channel == null || c2c == null) {
                 log.error("TcpServerDataProcess.process: {}, data null. controller: {}, channel: {}, c2c: {{}", ipAddress, obj, channel, c2c);
@@ -83,13 +84,21 @@ public class TcpServerDataProcess {
             MDC.put("id", obj.getLogKey());
             eAuthInfo cmd = eAuthInfo.getByValue(c2c.getDatexAuthenticationInfoText().value[0]);
 
-            log.info("TcpServerDataProcess.process: {}, {}, ThreadId: {}", ipAddress, cmd.toString(), Thread.currentThread().getId());
+            //log.info("TcpServerDataProcess.process: {}, {}, ThreadId: {}", ipAddress, cmd.toString(), Thread.currentThread().getId());
 
             DsrcAsn1Response response = null;
             switch (cmd) {
                 case AI_Initiate    :   //(0x01, "AI_Initiate"),           /* 초기 통신연결을 위한 개시 요청 데이터 패킷 */
                     // 서버모드 처리내용 없음(평택 서버인데 클라이언트가 서버로 동작 => 로그인 요청해야함)
-                    response = new InitiateResponse(obj, ctx, c2c);
+                    if (pdus.getDatexInitiateNull() != null) {
+                        response = new InitiateResponse(obj, ctx, c2c);
+                    }
+                    else if (pdus.getSubscription() != null) {
+                        response = new SubscriptionResponse(obj, ctx, c2c);
+                    }
+                    else if (pdus.getPublication() != null) {
+                        response = new PublicationResponse(obj, ctx, c2c);
+                    }
                     break;
                 case AI_Login       :   //(0x02, "AI_Login"),              /* 서버에 접속하기 위한 클라이언트의 로그인 데이터 패킷 */
                     response = new LoginResponse(obj, ctx, c2c);

+ 1 - 1
src/main/java/com/its/dsrc/xnettcp/dsrc/process/TcpServerDataTask.java

@@ -8,7 +8,7 @@ import org.springframework.stereotype.Service;
 @Service
 public class TcpServerDataTask {
 
-    @Async("appJobExecutor")
+    @Async("workDataExecutor")
     public void run(TcpServerDataProcess serverDataProcess, TcpServerData serverData) {
 
         serverDataProcess.process(serverData);

+ 66 - 6
src/main/java/com/its/dsrc/xnettcp/dsrc/process/response/AcceptResponse.java

@@ -8,8 +8,13 @@ import com.its.app.utils.NettyUtils;
 import com.its.dsrc.config.RunningConfig;
 import com.its.dsrc.dao.mapper.RseCtlrMapper;
 import com.its.dsrc.entity.TbRseCtlr;
+import com.its.dsrc.entity.TbRseCtlrCnncHs;
 import com.its.dsrc.entity.TbRseCtrlHs;
+import com.its.dsrc.process.DbmsData;
 import com.its.dsrc.process.DbmsDataProcess;
+import com.its.dsrc.process.DbmsDataType;
+import com.its.dsrc.vo.NET;
+import com.its.dsrc.xnettcp.dsrc.process.service.LoginDeviceService;
 import io.netty.channel.ChannelHandlerContext;
 import lombok.extern.slf4j.Slf4j;
 
@@ -30,7 +35,7 @@ public class AcceptResponse implements DsrcAsn1Response {
     @Override
     public boolean response(RunningConfig runningConfig) {
         String ipAddress = NettyUtils.getRemoteIpAddress(this.ctx.channel());
-        log.debug("AcceptResponse.response: {}", ipAddress);
+        log.info("AcceptResponse.response: {}", ipAddress);
 
         PDUs pdus = this.c2c.getPdu();
         Accept accept = pdus.getAccept();
@@ -45,7 +50,8 @@ public class AcceptResponse implements DsrcAsn1Response {
         Accept.DatexAcceptType acceptType = accept.getDatexAcceptType();
         if (acceptType.getLogIn() != null) {
             // Login = 1, 여기는 들어오지 않는다.
-            log.info("AcceptResponse.response: {}. Login: {} {}", ipAddress, dataPacketNmbr, acceptPacketNmbr);
+            log.info("AcceptResponse.response: {}. Login: {}, {}", ipAddress, dataPacketNmbr, acceptPacketNmbr);
+            loginAccept(runningConfig);
         }
         else if (acceptType.getSingleSubscription() != null) {
             // SingleSubscription = 2
@@ -53,7 +59,7 @@ public class AcceptResponse implements DsrcAsn1Response {
             // 제어명령에 대한 응답, 제어목록에서 삭제하고 이력으로 저장한다.
             this.obj.removeRegisteredCommands(acceptPacketNmbr, true);
             command = this.obj.getUserCommands(acceptPacketNmbr);
-            log.info("AcceptResponse.response: {}. SingleSubscription: {} {}", ipAddress, dataPacketNmbr, acceptPacketNmbr);
+            log.info("AcceptResponse.response: {}. SingleSubscription: {}, {}", ipAddress, dataPacketNmbr, acceptPacketNmbr);
         }
         else if (acceptType.getPublication() != null) {
             // SingleSubscription = 2
@@ -61,17 +67,33 @@ public class AcceptResponse implements DsrcAsn1Response {
             // 제어명령에 대한 응답, 제어목록에서 삭제하고 이력으로 저장한다.
             this.obj.removeRegisteredCommands(acceptPacketNmbr, true);
             command = this.obj.getUserCommands(acceptPacketNmbr);
-            log.info("AcceptResponse.response: {}. Publication: {} {}", ipAddress, dataPacketNmbr, acceptPacketNmbr);
+            log.info("AcceptResponse.response: {}. Publication: {}, {}", ipAddress, dataPacketNmbr, acceptPacketNmbr);
         }
         else if (acceptType.getRegisteredSubscription() != null) {
             // RegisteredSubscription = 4
             // 요청에 대한 응답, 제어목록에서 삭제한다.
+            // 상태정보요청: 269677936
+            if (269677936 == acceptType.getRegisteredSubscription().longValue()) {
+                if (acceptPacketNmbr == 1) {
+                    /**
+                     * requestObuGatherInfo 에 대한 Accept 응답
+                     */
+                    LoginDeviceService.getInstance().requestObuStatusInfo(this.obj, this.ctx.channel());
+                }
+                else if (acceptPacketNmbr == 2) {
+                    /**
+                     * requestObuStatusInfo 에 대한 Accept 응답
+                     */
+                    //LoginDeviceService.getInstance().requestObuStatusInfo(this.obj, this.ctx.channel());
+                }
+                //log.info("AcceptResponse.response: {}. 상태정보요청응답: {}, {}", ipAddress, dataPacketNmbr, acceptPacketNmbr);
+            }
             this.obj.removeRegisteredCommands(acceptPacketNmbr, true);
-            log.info("AcceptResponse.response: {}. RegisteredSubscription: {} {}", ipAddress, dataPacketNmbr, acceptPacketNmbr);
+            log.info("AcceptResponse.response: {}. RegisteredSubscription: {}, {}, {}", ipAddress, dataPacketNmbr, acceptPacketNmbr, acceptType.getRegisteredSubscription().longValue());
         }
 
         if (command != null) {
-            log.info("AcceptResponse.response: {}. Accept User Command: {} {}", ipAddress, dataPacketNmbr, acceptPacketNmbr);
+            log.info("AcceptResponse.response: {}. Accept User Command: {}, {}", ipAddress, dataPacketNmbr, acceptPacketNmbr);
             this.obj.removeUserCommands(acceptPacketNmbr);
             // TODO: 제어명령 성공 전송(성공)
             command.setRspsType("0");  // 명령 성공으로 설정
@@ -80,4 +102,42 @@ public class AcceptResponse implements DsrcAsn1Response {
         }
         return true;
     }
+
+    /**
+     * 클라이언트 모드 동작시 로그인 요청에 대한 응답으로 로그인 처리
+     * @param runningConfig
+     */
+    private void loginAccept(RunningConfig runningConfig) {
+        if (this.obj.getNetState() > NET.LOGIN_REQ && this.obj.getChannel() != null) {
+            log.warn("AcceptResponse.loginAccept: {}, already login. older channel will be closed.", this.obj.getMcuID());
+            this.obj.setDupLogin(true);
+            this.obj.setDupChannel(this.obj.getChannel());
+//            DsrcAsn1ServerIdleStatePacketHandler.disconnectChannel(this.obj, this.obj.getDupChannel());
+        }
+
+        this.obj.channelLoginInit();
+
+        TbRseCtlrCnncHs voLog = new TbRseCtlrCnncHs();
+        voLog.setRSE_CTLR_NMBR(this.obj.getID());
+        voLog.setLOG_ADDRESS(this.obj.getRSE_CTLR_IP());
+        voLog.setLoginInfo(c2c);
+        voLog.setLOG_ID(this.obj.getMcuID());
+        voLog.setLOG_TYPE(Integer.toString(TbRseCtlrCnncHs.LOG_TYPE_LOGIN));
+        this.obj.setLOG_ID(voLog.getLOG_ID());
+        if (this.obj.isDupLogin()) {
+            // 중복 접속(이미 통신중인 세션이 존재함)
+            voLog.setLOG_TYPE(Integer.toString(TbRseCtlrCnncHs.LOG_TYPE_DUP_LOGIN));
+        }
+        this.dbmsDataProcess.add(new DbmsData(DbmsDataType.DBMS_DATA_LOG_HS, false, voLog));
+
+        this.obj.getSeq().resetValue();
+        //this.obj.setLogin(login);
+        // 로그인이 성공하면 제어기에 정보를 요청한다.
+        log.info("AcceptResponse.loginAccept: {}, Request Subscriptions", obj.getMcuID());
+
+        /**
+         * OBU Gather Info request
+         */
+        LoginDeviceService.getInstance().requestObuGatherInfo(this.obj, this.ctx.channel());
+    }
 }

+ 39 - 3
src/main/java/com/its/dsrc/xnettcp/dsrc/process/response/FredResponse.java

@@ -3,16 +3,20 @@ package com.its.dsrc.xnettcp.dsrc.process.response;
 import com.beanit.asn1bean.ber.types.BerInteger;
 import com.beanit.asn1bean.ber.types.BerOctetString;
 import com.beanit.asn1dsrc.dsrc.C2CAuthenticatedMessage;
+import com.beanit.asn1dsrc.dsrc.FrED;
 import com.beanit.asn1dsrc.dsrc.PDUs;
 import com.beanit.asn1dsrc.enums.eAuthInfo;
 import com.beanit.asn1dsrc.util.DsrcAsn1Utils;
 import com.its.app.utils.NettyUtils;
 import com.its.dsrc.config.RunningConfig;
 import com.its.dsrc.entity.TbRseCtlr;
+import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelHandlerContext;
 import lombok.extern.slf4j.Slf4j;
 
+import java.math.BigInteger;
+
 @Slf4j
 public class FredResponse implements DsrcAsn1Response {
     private TbRseCtlr obj;
@@ -41,13 +45,45 @@ public class FredResponse implements DsrcAsn1Response {
         resC2c.setOptions(DsrcAsn1Utils.getDefaultOptions());
         resC2c.setPdu(pdus);
 
-        ChannelFuture f = this.ctx.channel().writeAndFlush(resC2c);
+        /**
+         * TODO: 클라이언트 모드로 동작시 FrED를 다시 전송하지 않는다.
+         */
+//        ChannelFuture f = this.ctx.channel().writeAndFlush(resC2c);
+//        f.awaitUninterruptibly();
+//        if (f.isDone() || f.isSuccess()) {
+//            log.info("FredResponse.response: {}, Send OK", ipAddress);
+//        } else {
+//            log.error("FredResponse.response: {}, Send Failed", ipAddress);
+//        }
+        return true;
+    }
+
+    public static boolean sendFrED(TbRseCtlr obj, Channel channel) {
+        String ipAddress = NettyUtils.getRemoteIpAddress(channel);
+        log.debug("FredResponse.sendFrED: {}", ipAddress);
+
+        // 세션 연결 유지를 위해 Fred 메시지 전송
+        PDUs pdus = new PDUs();
+        FrED fred = new FrED(new BigInteger(String.valueOf(9871)));
+        pdus.setFred(fred);
+
+        byte[] auth = { (byte) eAuthInfo.AI_FrED.getValue() };
+        C2CAuthenticatedMessage resC2c = new C2CAuthenticatedMessage();
+        resC2c.setDatexDataPacketNumber(new BerInteger(obj.getSeq().nextValue()));
+        resC2c.setDatexDataPacketPriorityNumber(new BerInteger(1));
+        resC2c.setDatexAuthenticationInfoText(new BerOctetString(auth));
+        //resC2c.setOptions(DsrcAsn1Utils.swapHeaderOptions(this.obj.getHeaderOptions()));
+        resC2c.setOptions(DsrcAsn1Utils.getDefaultOptions());
+        resC2c.setPdu(pdus);
+
+        ChannelFuture f = channel.writeAndFlush(resC2c);
         f.awaitUninterruptibly();
         if (f.isDone() || f.isSuccess()) {
-            log.info("FredResponse.response: {}, Send OK", ipAddress);
+            log.info("FredResponse.sendFrED: {}, Send OK", ipAddress);
         } else {
-            log.error("FredResponse.response: {}, Send Failed", ipAddress);
+            log.error("FredResponse.sendFrED: {}, Send Failed", ipAddress);
         }
         return true;
     }
+
 }

+ 13 - 1
src/main/java/com/its/dsrc/xnettcp/dsrc/process/response/InitiateResponse.java

@@ -1,6 +1,8 @@
 package com.its.dsrc.xnettcp.dsrc.process.response;
 
 import com.beanit.asn1dsrc.dsrc.C2CAuthenticatedMessage;
+import com.beanit.asn1dsrc.dsrc.Initiate;
+import com.beanit.asn1dsrc.dsrc.PDUs;
 import com.its.app.utils.NettyUtils;
 import com.its.dsrc.config.RunningConfig;
 import com.its.dsrc.entity.TbRseCtlr;
@@ -26,6 +28,16 @@ public class InitiateResponse implements DsrcAsn1Response {
         String ipAddress = NettyUtils.getRemoteIpAddress(this.ctx.channel());
         log.info("InitiateResponse.response: {}", ipAddress);
 
-        return LoginDeviceService.getInstance().requestLogin(obj, this.ctx.channel(), runningConfig);
+        PDUs pdus = this.c2c.getPdu();
+        Initiate initiate = pdus.getDatexInitiateNull();
+        if (initiate != null) {
+            /**
+             * Login 요청에 대한 응답을 처리함
+             */
+            return LoginDeviceService.getInstance().requestLogin(obj, this.ctx.channel(), runningConfig);
+        }
+
+        return true;
     }
+
 }

+ 3 - 3
src/main/java/com/its/dsrc/xnettcp/dsrc/process/response/PublicationResponse.java

@@ -45,7 +45,7 @@ public class PublicationResponse implements DsrcAsn1Response {
         PublishFormat publishFormat = publication.getDatexPublishFormat();
         if (publishFormat.getDatexPublishData() != null) {
             List<PublicationData> list = publishFormat.getDatexPublishData().getPublicationData();
-            log.info("PublicationResponse.response: {}. Publication PublishData. size: {} EA", ipAddress, list.size());
+            //log.info("PublicationResponse.response: {}. Publication PublishData. size: {} EA", ipAddress, list.size());
             for (PublicationData data : list) {
                 if (data.getDatexPublishType().getDatexPublishData() != null) {
                     try {
@@ -61,7 +61,7 @@ public class PublicationResponse implements DsrcAsn1Response {
         }
 
         if (guaranteed) {
-            log.info("PublicationResponse.response: {}. guaranteed: true", ipAddress);
+            //log.info("PublicationResponse.response: {}. guaranteed: true", ipAddress);
             C2CAuthenticatedMessage resC2c = DsrcAsn1Accept.makeC2CAuthenticatedMessage(this.obj, this.ctx.channel(), this.c2c);
             if (resC2c != null) {
                 ChannelFuture f = this.ctx.channel().writeAndFlush(resC2c);
@@ -108,7 +108,7 @@ public class PublicationResponse implements DsrcAsn1Response {
             obuInfos.decode(berInputStream);
             List<OBUGatherInfo> list = obuInfos.getOBUGatherInfo();
             //TODO: OBU Gather Info
-            log.info("PublicationResponse.responsePublicationData: DSRC OBU Traffic, OBU: {} EA", list.size());
+            log.info("PublicationResponse.responsePublicationData: {}, DSRC OBU Traffic, OBU: {} EA", this.obj.getMcuID(), list.size());
             OBUGatherInfoService.getInstance().decoding_OBUGatherInfo(this.obj, list);
         }
         else {

+ 120 - 118
src/main/java/com/its/dsrc/xnettcp/dsrc/process/service/ControlDeviceService.java

@@ -373,8 +373,8 @@ public class ControlDeviceService {
                     decisionInfo.setUpdateNo(new BerInteger(updateNo));
                     decisionInfo.setGenerationTime(new BerGeneralizedTime(SysUtils.getSysTime()));                   // 주5) generationTime : 해당 정보의 생성 일자 시간
                     BeaconID beaconID = new BeaconID();
-                    beaconID.setManufacturerid(new BerInteger(obj.getMNFC_CMPY_CD()));
-                    beaconID.setIndividualid(new BerInteger(Long.parseLong(obj.getRSE_ID())));
+                    beaconID.setManufacturerid(new BerInteger(obj.getManufacturerid()));
+                    beaconID.setIndividualid(new BerInteger(obj.getIndividualid()));
                     decisionInfo.setTargetBeaconID(beaconID);
                     decisionInfo.setInCommingDirectionEnterBaseInfo(null);
                     List<TbRseOffrDrct> list = AppRepository.getInstance().getRseOffrDrctList(obj.getRSE_ID());
@@ -389,8 +389,8 @@ public class ControlDeviceService {
                             BeaconID beaconID1 = new BeaconID();
                             TbRseCtlr rseObj = AppRepository.getInstance().getCtlrMap().get(vo.getPRE_RSE_CTLR_NMBR());
                             if (rseObj != null) {
-                                beaconID1.setManufacturerid(new BerInteger(rseObj.getMNFC_CMPY_CD()));
-                                beaconID1.setIndividualid(new BerInteger(Long.parseLong(rseObj.getRSE_ID())));
+                                beaconID1.setManufacturerid(new BerInteger(rseObj.getManufacturerid()));
+                                beaconID1.setIndividualid(new BerInteger(rseObj.getIndividualid()));
                                 directionBeaconInfo.getPreviousBeaconID().getBeaconID().add(beaconID1);
                                 beacons.getDirectionBeaconInfo().add(directionBeaconInfo);
                             }
@@ -591,8 +591,10 @@ public class ControlDeviceService {
                     infoRequest.setQueryType(new BerEnum(request.getValue()));
                     if (request.getValue() == eControlRequest.Request_TrafficInfo.getValue()) {
                         BeaconID beaconID = new BeaconID();
-                        beaconID.setIndividualid(new BerInteger(Long.valueOf(obj.getID()).longValue()));
-                        beaconID.setManufacturerid(new BerInteger(Long.valueOf(obj.getMNFC_CMPY_CD()).longValue()));
+                        beaconID.setManufacturerid(new BerInteger(obj.getManufacturerid()));
+                        beaconID.setIndividualid(new BerInteger(obj.getIndividualid()));
+//                        beaconID.setIndividualid(new BerInteger(Long.valueOf(obj.getID()).longValue()));
+//                        beaconID.setManufacturerid(new BerInteger(Long.valueOf(obj.getMNFC_CMPY_CD()).longValue()));
                         //infoRequest.setRoadStationID(new BerOctetString(obj.getROAD_SPOT_ID().getBytes()));
                         infoRequest.setBeaconID(beaconID);
                     }
@@ -660,118 +662,118 @@ public class ControlDeviceService {
         return endApplicationMessage;
     }
 
-    public ControlDeviceList controlDevice_BasicBaseInfo(TbRseCtlr obj, eControlRequest type) {
-        // ControlDevice.vpbd-ControlID  : 기초정보(0x02)
-        //
-        // BasicBaseInfo.roadStationID   : 주1) 사업자 정의 ID. MCU ID임
-        // BasicBaseInfo.roadStationType : 주2) 제어부 위치 정보
-        //                                      101 고속국도
-        //                                      102 도시고속국도
-        //                                      103 일반국도
-        //                                      104 특별․광역시도
-        //                                      105 국가지원지방도
-        //                                      106 지방도
-        //                                      107 시․군도
-        //                                      108 기타
-        // BasicBaseInfo.dataOfNonCryptoObuList	DataOfNonCryptoObu
-        //주3) infoID
-        //1 : DataOfCollectionPointInfo (가상 수집지점 정보)
-        //2 : DirectionDecisionInfo (방향 판단 정보)
-        //3 : DataOfNonCryptoObu (비 암호화 단말기 정보)
-
-        ControlDeviceList controlDeviceList = null;
-        ControlDevice device = null;
-        BasicBaseInfo info = null;
-        byte[] controlId = { (byte)eControlDevice.Control_BasicInfo.getValue() };
-        String roadStationId = obj.getRSE_MCU_ID();//obj.getROAD_SPOT_ID();
-        if (roadStationId == null || roadStationId.equals("")) {
-            return null;
-        }
-
-        try {
-            int updateNo = 0;
-            byte[] operCode = { 0x00 };  // 0x00(추가), 0x01(삭제)
-            switch(type) {
-                case Request_BasicInfo:
-                case Request_BasicInfo_Collect:
-                case Request_BasicInfo_Direction:
-                    info = new BasicBaseInfo();
-                    info.setRoadStationID(new BerOctetString(roadStationId.getBytes()));
-                    info.setRoadStationType(new BerInteger(104));   //시․군도
-                    BasicBaseInfo.DataOfDirectionDecisionInfoList data = new BasicBaseInfo.DataOfDirectionDecisionInfoList();
-                    DirectionDecisionInfo decisionInfo = new DirectionDecisionInfo();
-                    decisionInfo.setInfoID(new BerInteger(eControlRequest.Request_BasicInfo_Direction.getValue()));
-                    decisionInfo.setUpdateNo(new BerInteger(updateNo));
-                    decisionInfo.setGenerationTime(new BerGeneralizedTime(SysUtils.getSysTime()));                   // 주5) generationTime : 해당 정보의 생성 일자 시간
-                    BeaconID beaconID = new BeaconID();
-                    beaconID.setManufacturerid(new BerInteger(Long.valueOf(obj.getMNFC_CMPY_CD()).longValue()));
-                    beaconID.setIndividualid(new BerInteger(Long.valueOf(obj.getRSE_ID()).longValue()));
-                    decisionInfo.setTargetBeaconID(beaconID);
-                    decisionInfo.setInCommingDirectionEnterBaseInfo(null);
-                    List<TbRseOffrDrct> list = AppRepository.getInstance().getRseOffrDrctList(obj.getRSE_ID());
-                    if (list == null || list.size() == 0) {
-                        decisionInfo.setInCommingDirectionBeaconInfo(null);
-                    }
-                    else {
-                        DirectionDecisionInfo.InCommingDirectionBeaconInfo beacons = new DirectionDecisionInfo.InCommingDirectionBeaconInfo();
-                        for (TbRseOffrDrct vo : list) {
-                            DirectionBeaconInfo directionBeaconInfo = new DirectionBeaconInfo();
-                            directionBeaconInfo.setDirectionInfo(new BerInteger(Long.valueOf(vo.getOBU_ENTR_DRCT_NMBR()).longValue()));
-                            BeaconID beaconID1 = new BeaconID();
-                            TbRseCtlr rseObj = AppRepository.getInstance().getCtlrMap().get(vo.getPRE_RSE_CTLR_NMBR());
-                            if (rseObj != null) {
-                                beaconID1.setIndividualid(new BerInteger(Long.valueOf(rseObj.getRSE_ID()).longValue()));
-                                beaconID1.setManufacturerid(new BerInteger(Long.valueOf(rseObj.getMNFC_CMPY_CD()).longValue()));
-                                directionBeaconInfo.getPreviousBeaconID().getBeaconID().add(beaconID1);
-                                beacons.getDirectionBeaconInfo().add(directionBeaconInfo);
-                            }
-                        }
-                        decisionInfo.setInCommingDirectionBeaconInfo(beacons);
-                    }
-                    data.getDirectionDecisionInfo().add(decisionInfo);
-                    info.setDataOfDirectionDecisionInfoList(data);
-                    break;
-                case Request_BasicInfo_NonCrypt:    // 최초 로그인 후 NonCryptObu 정보 요청
-                    DataOfNonCryptoObu dataObu = new DataOfNonCryptoObu();
-                    DataOfNonCryptoObu.CryptObuList obuList = new DataOfNonCryptoObu.CryptObuList();
-
-                    for (TbRseObuNonCrypt vo : AppRepository.getInstance().rseObuNonCryptList) {
-                        CryptObu obu = new CryptObu();
-                        obu.setOperCode(new BerOctetString(operCode));  // 주7) operCode : 비암호 단말기 리스트의 추가삭제 정보
-                        // 0x00 : 추가 , 0x01: 삭제
-                        obu.setObuID(new BerOctetString(vo.getOBU_ID().getBytes()));
-                        obuList.getCryptObu().add(obu);
-                    }
-                    dataObu.setInfoID(new BerInteger(eControlRequest.Request_BasicInfo_NonCrypt.getValue()));   // 주3) infoID
-                    //    1 : DataOfCollectionPointInfo (가상 수집지점 정보)
-                    //    2 : DirectionDecisionInfo (방향 판단 정보)
-                    //    3 : DataOfNonCryptoObu (비 암호화 단말기 정보)
-                    dataObu.setUpdateNo(new BerInteger(updateNo));                                                // 주4) updateNo : 해당정보의 변경이력 번호
-                    dataObu.setGenerationTime(new BerGeneralizedTime(SysUtils.getSysTime()));                   // 주5) generationTime : 해당 정보의 생성 일자 시간
-                    dataObu.setCryptObuList(obuList);
-
-                    info = new BasicBaseInfo();
-                    info.setRoadStationID(new BerOctetString(roadStationId.getBytes()));
-                    info.setRoadStationType(new BerInteger(107));   //시․군도
-                    info.setDataOfNonCryptoObuList(dataObu);
-                    break;
-            }
-
-            if (info != null) {
-                ReverseByteArrayOutputStream msgBuff = new ReverseByteArrayOutputStream(1024);
-                info.encode(msgBuff);
-                device = new ControlDevice();
-                device.setVpbdControlID(new BerOctetString(controlId));
-                device.setVpbdControlDeviceData(new BerOctetString(msgBuff.getArray()));
-            }
-        }
-        catch(Exception e) {
-            log.error("ControlDeviceService.makeControlDevice_BasicBaseInfo: {}, eControlType: {}, Exception: {}", obj.getID(), type, e);
-            return null;
-        }
-        //log.debug("ControlDeviceService.makeControlDevice_BasicBaseInfo: {}, eControlType: {}, ControlDevice: {}", obj.getID(), type, device);
-        return controlDeviceList;
-    }
+//    public ControlDeviceList controlDevice_BasicBaseInfo(TbRseCtlr obj, eControlRequest type) {
+//        // ControlDevice.vpbd-ControlID  : 기초정보(0x02)
+//        //
+//        // BasicBaseInfo.roadStationID   : 주1) 사업자 정의 ID. MCU ID임
+//        // BasicBaseInfo.roadStationType : 주2) 제어부 위치 정보
+//        //                                      101 고속국도
+//        //                                      102 도시고속국도
+//        //                                      103 일반국도
+//        //                                      104 특별․광역시도
+//        //                                      105 국가지원지방도
+//        //                                      106 지방도
+//        //                                      107 시․군도
+//        //                                      108 기타
+//        // BasicBaseInfo.dataOfNonCryptoObuList	DataOfNonCryptoObu
+//        //주3) infoID
+//        //1 : DataOfCollectionPointInfo (가상 수집지점 정보)
+//        //2 : DirectionDecisionInfo (방향 판단 정보)
+//        //3 : DataOfNonCryptoObu (비 암호화 단말기 정보)
+//
+//        ControlDeviceList controlDeviceList = null;
+//        ControlDevice device = null;
+//        BasicBaseInfo info = null;
+//        byte[] controlId = { (byte)eControlDevice.Control_BasicInfo.getValue() };
+//        String roadStationId = obj.getRSE_MCU_ID();//obj.getROAD_SPOT_ID();
+//        if (roadStationId == null || roadStationId.equals("")) {
+//            return null;
+//        }
+//
+//        try {
+//            int updateNo = 0;
+//            byte[] operCode = { 0x00 };  // 0x00(추가), 0x01(삭제)
+//            switch(type) {
+//                case Request_BasicInfo:
+//                case Request_BasicInfo_Collect:
+//                case Request_BasicInfo_Direction:
+//                    info = new BasicBaseInfo();
+//                    info.setRoadStationID(new BerOctetString(roadStationId.getBytes()));
+//                    info.setRoadStationType(new BerInteger(104));   //시․군도
+//                    BasicBaseInfo.DataOfDirectionDecisionInfoList data = new BasicBaseInfo.DataOfDirectionDecisionInfoList();
+//                    DirectionDecisionInfo decisionInfo = new DirectionDecisionInfo();
+//                    decisionInfo.setInfoID(new BerInteger(eControlRequest.Request_BasicInfo_Direction.getValue()));
+//                    decisionInfo.setUpdateNo(new BerInteger(updateNo));
+//                    decisionInfo.setGenerationTime(new BerGeneralizedTime(SysUtils.getSysTime()));                   // 주5) generationTime : 해당 정보의 생성 일자 시간
+//                    BeaconID beaconID = new BeaconID();
+//                    beaconID.setManufacturerid(new BerInteger(Long.valueOf(obj.getMNFC_CMPY_CD()).longValue()));
+//                    beaconID.setIndividualid(new BerInteger(Long.valueOf(obj.getRSE_ID()).longValue()));
+//                    decisionInfo.setTargetBeaconID(beaconID);
+//                    decisionInfo.setInCommingDirectionEnterBaseInfo(null);
+//                    List<TbRseOffrDrct> list = AppRepository.getInstance().getRseOffrDrctList(obj.getRSE_ID());
+//                    if (list == null || list.size() == 0) {
+//                        decisionInfo.setInCommingDirectionBeaconInfo(null);
+//                    }
+//                    else {
+//                        DirectionDecisionInfo.InCommingDirectionBeaconInfo beacons = new DirectionDecisionInfo.InCommingDirectionBeaconInfo();
+//                        for (TbRseOffrDrct vo : list) {
+//                            DirectionBeaconInfo directionBeaconInfo = new DirectionBeaconInfo();
+//                            directionBeaconInfo.setDirectionInfo(new BerInteger(Long.valueOf(vo.getOBU_ENTR_DRCT_NMBR()).longValue()));
+//                            BeaconID beaconID1 = new BeaconID();
+//                            TbRseCtlr rseObj = AppRepository.getInstance().getCtlrMap().get(vo.getPRE_RSE_CTLR_NMBR());
+//                            if (rseObj != null) {
+//                                beaconID1.setIndividualid(new BerInteger(Long.valueOf(rseObj.getRSE_ID()).longValue()));
+//                                beaconID1.setManufacturerid(new BerInteger(Long.valueOf(rseObj.getMNFC_CMPY_CD()).longValue()));
+//                                directionBeaconInfo.getPreviousBeaconID().getBeaconID().add(beaconID1);
+//                                beacons.getDirectionBeaconInfo().add(directionBeaconInfo);
+//                            }
+//                        }
+//                        decisionInfo.setInCommingDirectionBeaconInfo(beacons);
+//                    }
+//                    data.getDirectionDecisionInfo().add(decisionInfo);
+//                    info.setDataOfDirectionDecisionInfoList(data);
+//                    break;
+//                case Request_BasicInfo_NonCrypt:    // 최초 로그인 후 NonCryptObu 정보 요청
+//                    DataOfNonCryptoObu dataObu = new DataOfNonCryptoObu();
+//                    DataOfNonCryptoObu.CryptObuList obuList = new DataOfNonCryptoObu.CryptObuList();
+//
+//                    for (TbRseObuNonCrypt vo : AppRepository.getInstance().rseObuNonCryptList) {
+//                        CryptObu obu = new CryptObu();
+//                        obu.setOperCode(new BerOctetString(operCode));  // 주7) operCode : 비암호 단말기 리스트의 추가삭제 정보
+//                        // 0x00 : 추가 , 0x01: 삭제
+//                        obu.setObuID(new BerOctetString(vo.getOBU_ID().getBytes()));
+//                        obuList.getCryptObu().add(obu);
+//                    }
+//                    dataObu.setInfoID(new BerInteger(eControlRequest.Request_BasicInfo_NonCrypt.getValue()));   // 주3) infoID
+//                    //    1 : DataOfCollectionPointInfo (가상 수집지점 정보)
+//                    //    2 : DirectionDecisionInfo (방향 판단 정보)
+//                    //    3 : DataOfNonCryptoObu (비 암호화 단말기 정보)
+//                    dataObu.setUpdateNo(new BerInteger(updateNo));                                                // 주4) updateNo : 해당정보의 변경이력 번호
+//                    dataObu.setGenerationTime(new BerGeneralizedTime(SysUtils.getSysTime()));                   // 주5) generationTime : 해당 정보의 생성 일자 시간
+//                    dataObu.setCryptObuList(obuList);
+//
+//                    info = new BasicBaseInfo();
+//                    info.setRoadStationID(new BerOctetString(roadStationId.getBytes()));
+//                    info.setRoadStationType(new BerInteger(107));   //시․군도
+//                    info.setDataOfNonCryptoObuList(dataObu);
+//                    break;
+//            }
+//
+//            if (info != null) {
+//                ReverseByteArrayOutputStream msgBuff = new ReverseByteArrayOutputStream(1024);
+//                info.encode(msgBuff);
+//                device = new ControlDevice();
+//                device.setVpbdControlID(new BerOctetString(controlId));
+//                device.setVpbdControlDeviceData(new BerOctetString(msgBuff.getArray()));
+//            }
+//        }
+//        catch(Exception e) {
+//            log.error("ControlDeviceService.makeControlDevice_BasicBaseInfo: {}, eControlType: {}, Exception: {}", obj.getID(), type, e);
+//            return null;
+//        }
+//        //log.debug("ControlDeviceService.makeControlDevice_BasicBaseInfo: {}, eControlType: {}, ControlDevice: {}", obj.getID(), type, device);
+//        return controlDeviceList;
+//    }
 
     public boolean sendTerminate(TbRseCtlr obj, Channel channel, int reason)
     {

+ 288 - 22
src/main/java/com/its/dsrc/xnettcp/dsrc/process/service/LoginDeviceService.java

@@ -17,6 +17,7 @@ import io.netty.channel.ChannelFuture;
 import lombok.extern.slf4j.Slf4j;
 
 import java.math.BigInteger;
+import java.util.Calendar;
 
 @Slf4j
 public class LoginDeviceService {
@@ -41,25 +42,28 @@ public class LoginDeviceService {
 
         // OBU Non Crypt 데이터 요청 Subscription
         if (isObuNonCrypt) {
-            requestPublicationNonCryptObu(obj, channel);
+            log.info("initLoginDevice.isObuNonCrypt. {}, {}, {}", obj.getRSE_CTLR_NMBR(), obj.getRSE_CTLR_IP(), obj.getRSE_MCU_ID());
+            //requestPublicationNonCryptObu(obj, channel);
         }
 
         // DSRC 상태정보 요청 Subscription
         if (isDsrcStatus) {
-            requestSubscriptions(obj, channel, subscriptionStatusCycle, 1);
+            log.info("initLoginDevice.isDsrcStatus. {}, {}, {}", obj.getRSE_CTLR_NMBR(), obj.getRSE_CTLR_IP(), obj.getRSE_MCU_ID());
+            //requestSubscriptions(obj, channel, subscriptionStatusCycle, 1);
         }
 
         // OBU 교통정보 요청 Subscription
         if (isTraffic) {
+            log.info("initLoginDevice.isTraffic. {}, {}, {}", obj.getRSE_CTLR_NMBR(), obj.getRSE_CTLR_IP(), obj.getRSE_MCU_ID());
             requestSubscriptions(obj, channel, 0, 2);
         }
 
         // DSRC Antenna enable Publication
-        if (antennaCnt > 0) {
-            for (int antennaId = 1; antennaId <= antennaCnt; antennaId++) {
-                requestSubscriptionDeviceCommand(obj, channel, antennaId, eControlCommand.ControlCommand_Wireless_Start.getValue());
-            }
-        }
+//        if (antennaCnt > 0) {
+//            for (int antennaId = 1; antennaId <= antennaCnt; antennaId++) {
+//                requestSubscriptionDeviceCommand(obj, channel, antennaId, eControlCommand.ControlCommand_Wireless_Start.getValue());
+//            }
+//        }
         return true;
     }
 
@@ -80,6 +84,17 @@ public class LoginDeviceService {
         log.info("LoginDeviceService.requestSubscriptions: {}, {}, registeredUpdateDelayQty: {}, subscriptionsType: {}", obj.getID(), obj.getRSE_ID(), registeredUpdateDelayQty, subscriptionsType);
 
         int[] messageId = {1, 0, 15784, 4, 0, 7};
+//        pObject->numids = 6;
+//        pObject->subid[0] = 1;
+//        pObject->subid[1] = 0;
+//        pObject->subid[2] = 15784;
+//        switch (id)
+//        {
+//            case itMultimediaData: pObject->subid[3] = 5; pObject->subid[4] = 0; pObject->subid[5] = 1; break;
+//            case itControlDevice: pObject->subid[3] = 4; pObject->subid[4] = 0; pObject->subid[5] = 7; break;
+//            case itObuGatherInfo: pObject->subid[3] = 8; pObject->subid[4] = 0; pObject->subid[5] = 8; break;
+//            default: break;
+//        }
         int subscribeSerialNbr = obj.getSeq().nextValue();
 
         try {
@@ -131,7 +146,8 @@ public class LoginDeviceService {
             subscriptionData.setDatexSubscribeStatusCd(new BerEnum(0));         // 0: New, 1: Update
             subscriptionData.setDatexSubscribeMode(subscriptionMode);
             subscriptionData.setDatexSubscribePublishFormatCd(new BerEnum(3));  // 0: other, 1: ftp, 2: tftp, 3: dataPacket
-            subscriptionData.setDatexSubscriptionPriorityNbr(new BerInteger(1));
+            //subscriptionData.setDatexSubscriptionPriorityNbr(new BerInteger(1));
+            subscriptionData.setDatexSubscriptionPriorityNbr(new BerInteger(10));
             subscriptionData.setDatexSubscribeGuaranteeBool(new BerBoolean(true));
             subscriptionData.setDatexSubscribePdu(endApplicationMessage);
 
@@ -285,47 +301,297 @@ public class LoginDeviceService {
         return true;
     }
 
+    /**
+     * 클라이언트 모드로 동작시 Initiate 수신시 로그인 정보를 전송한다.
+     * @param obj
+     * @param channel
+     * @param runningConfig
+     * @return
+     */
     public boolean requestLogin(TbRseCtlr obj, Channel channel, RunningConfig runningConfig) {
 
-        log.info("LoginResponse.requestLogin");
+        log.info("LoginResponse.requestLogin: {}, {}, {}", obj.getRSE_CTLR_NMBR(), obj.getRSE_CTLR_IP(), obj.getRSE_MCU_ID());
+
+        int dataPacketNumber = 0;           //obj.getSeq().nextValue()
+        int dataPacketPriorityNumber = 0;
+        String serverDomainName = runningConfig.getServerDomainName();
+        String destinationTxt = obj.getRSE_MCU_ID();
+        String loginUserNameTxt = "";
+        String loginPasswordTxt = "";
 
         Login login = new Login();
-        login.setDatexSenderTxt(new BerUTF8String(runningConfig.getServerDomainName()));
-        login.setDatexDestinationTxt(new BerUTF8String(runningConfig.getServerDomainName()));
-        login.setDatexLoginUserNameTxt(new BerUTF8String(runningConfig.getServerAuthUser()));
-        login.setDatexLoginPasswordTxt(new BerUTF8String(runningConfig.getServerAuthPassword()));
+        login.setDatexSenderTxt(new BerUTF8String(serverDomainName));
+        login.setDatexDestinationTxt(new BerUTF8String(destinationTxt));
+        login.setDatexLoginUserNameTxt(new BerUTF8String(loginUserNameTxt));
+        login.setDatexLoginPasswordTxt(new BerUTF8String(loginPasswordTxt));
         login.setDatexLoginHeartbeatDurationMaxQty(new BerInteger(120));
-        login.setDatexLoginResponseTimeOutQty(new BerInteger(5));
+        login.setDatexLoginResponseTimeOutQty(new BerInteger(30));
         login.setDatexLoginInitiatorCd(new BerEnum(1));
         login.setDatexLoginDatagramSizeQty(new BerInteger(2048));
-        int[] encodingRules = {2, 1, 1};
+        int[] encodingRules = {2, 1};
         Login.DatexLoginEncodingRulesId loginEncodingRulesId = new Login.DatexLoginEncodingRulesId();
         loginEncodingRulesId.getBerObjectIdentifier().add(new BerObjectIdentifier(encodingRules));
         login.setDatexLoginEncodingRulesId(loginEncodingRulesId);
 
-
         byte[] auth = {(byte) eAuthInfo.AI_Login.getValue() };
         PDUs loginPdu = new PDUs();
         loginPdu.setLogin(login);
 
-        HeaderOptions headerOptions = DsrcAsn1Utils.getDefaultOptions();
+        HeaderOptions headerOptions = new HeaderOptions();
+        Time tm = new Time();
+        Time.TimeSecondFractions tmFac = new Time.TimeSecondFractions();
+        Time.TimeTimezone        tmZon = new Time.TimeTimezone();
+        Calendar currTm = Calendar.getInstance();
+        tm.setTimeYearQty(new BerInteger(currTm.get(Calendar.YEAR)));
+        tm.setTimeMonthQty(new BerInteger(currTm.get(Calendar.MONTH)+1));
+        tm.setTimeDayQty(new BerInteger(currTm.get(Calendar.DATE)));
+        tm.setTimeHourQty(new BerInteger(currTm.get(Calendar.HOUR_OF_DAY)));
+        tm.setTimeMinuteQty(new BerInteger(currTm.get(Calendar.MINUTE)));
+        tm.setTimeSecondQty(new BerInteger(currTm.get(Calendar.SECOND)));
+        tmFac.setMilliseconds(new BerInteger(currTm.get(Calendar.MILLISECOND)));
+        tm.setTimeSecondFractions(tmFac);
+        headerOptions.setDatexDataPacketTime(tm);
+
         C2CAuthenticatedMessage c2c = new C2CAuthenticatedMessage();
         c2c.setDatexAuthenticationInfoText(new BerOctetString(auth));
-        c2c.setDatexDataPacketNumber(new BerInteger(obj.getSeq().nextValue()));
-        c2c.setDatexDataPacketPriorityNumber(new BerInteger(1));
+        c2c.setDatexDataPacketNumber(new BerInteger(dataPacketNumber));
+        c2c.setDatexDataPacketPriorityNumber(new BerInteger(dataPacketPriorityNumber));
         c2c.setOptions(headerOptions);
         c2c.setPdu(loginPdu);
 
-        obj.setHeaderOptions(DsrcAsn1Utils.swapHeaderOptions(headerOptions));
-
         ChannelFuture f = channel.writeAndFlush(c2c);
         f.awaitUninterruptibly();
         if (f.isDone() || f.isSuccess()) {
-            log.info("LoginDeviceService.requestLogin: {}, {}, send ok", obj.getID(), obj.getRSE_ID());
+            obj.setHeaderOptions(DsrcAsn1Utils.swapHeaderOptions(headerOptions));
+            obj.setLogin(login);
+            log.info("LoginResponse.requestLogin: {}, {}, {}, send ok.", obj.getRSE_CTLR_NMBR(), obj.getRSE_CTLR_IP(), obj.getRSE_MCU_ID());
         } else {
             log.error("LoginDeviceService.requestLogin: {}, {}, send failed.", obj.getID(), obj.getRSE_ID());
         }
         return true;
     }
 
+//    public boolean requestLogin2(TbRseCtlr obj, Channel channel, RunningConfig runningConfig) {
+//
+//        log.info("LoginResponse.requestLogin: {}, {}, {}", obj.getRSE_CTLR_NMBR(), obj.getRSE_CTLR_IP(), obj.getRSE_MCU_ID());
+//
+//        int dataPacketNumber = 0;           //obj.getSeq().nextValue()
+//        int dataPacketPriorityNumber = 0;
+//
+//        Login login = new Login();
+//        login.setDatexSenderTxt(new BerUTF8String(runningConfig.getServerDomainName()));
+//        login.setDatexDestinationTxt(new BerUTF8String(obj.getRSE_MCU_ID()));
+//        login.setDatexLoginUserNameTxt(new BerUTF8String(runningConfig.getServerAuthUser()));
+//        login.setDatexLoginPasswordTxt(new BerUTF8String(runningConfig.getServerAuthPassword()));
+//        login.setDatexLoginHeartbeatDurationMaxQty(new BerInteger(120));
+//        login.setDatexLoginResponseTimeOutQty(new BerInteger(30));
+//        login.setDatexLoginInitiatorCd(new BerEnum(1));
+//        login.setDatexLoginDatagramSizeQty(new BerInteger(2048));
+//        int[] encodingRules = {2, 1, 1};
+//        Login.DatexLoginEncodingRulesId loginEncodingRulesId = new Login.DatexLoginEncodingRulesId();
+//        loginEncodingRulesId.getBerObjectIdentifier().add(new BerObjectIdentifier(encodingRules));
+//        login.setDatexLoginEncodingRulesId(loginEncodingRulesId);
+//
+//        byte[] auth = {(byte) eAuthInfo.AI_Login.getValue() };
+//        PDUs loginPdu = new PDUs();
+//        loginPdu.setLogin(login);
+//
+//        HeaderOptions headerOptions = DsrcAsn1Utils.getDefaultOptions();
+//        C2CAuthenticatedMessage c2c = new C2CAuthenticatedMessage();
+//        c2c.setDatexAuthenticationInfoText(new BerOctetString(auth));
+//        c2c.setDatexDataPacketNumber(new BerInteger(dataPacketNumber));
+//        c2c.setDatexDataPacketPriorityNumber(new BerInteger(dataPacketPriorityNumber));
+//        c2c.setOptions(headerOptions);
+//        c2c.setPdu(loginPdu);
+//
+//        ChannelFuture f = channel.writeAndFlush(c2c);
+//        f.awaitUninterruptibly();
+//        if (f.isDone() || f.isSuccess()) {
+//            obj.setHeaderOptions(DsrcAsn1Utils.swapHeaderOptions(headerOptions));
+//            obj.setLogin(login);
+//            log.info("LoginResponse.requestLogin: {}, {}, {}, send ok.", obj.getRSE_CTLR_NMBR(), obj.getRSE_CTLR_IP(), obj.getRSE_MCU_ID());
+//        } else {
+//            log.error("LoginDeviceService.requestLogin: {}, {}, send failed.", obj.getID(), obj.getRSE_ID());
+//        }
+//        return true;
+//    }
+
+    /**
+     * OBU 수집 정보 요청 등록(이벤트 방식)
+     * @param obj
+     * @param channel
+     * @return
+     */
+    public boolean requestObuGatherInfo(TbRseCtlr obj, Channel channel) {
+
+        log.info("LoginDeviceService.requestObuGatherInfo: {}, {}", obj.getID(), obj.getRSE_ID());
+
+        int[] messageId = {1, 0, 15784, 8, 0, 8};
+        int dataPacketNumber = 1;           //obj.getSeq().nextValue()
+        int dataPacketPriorityNumber = 0;
+        int datexSubscriptionPriorityNbr = 10;
+        int subscribeSerialNbr = 0;
+        try {
+            byte[] obuIdNumber = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+            byte[] vehicleType = {0};
+            byte[] obuType = {0};
+            byte[] generationDate = {0,0,0,0};
+            byte[] generationTime = {0,0,0};
+
+            OBUGatherInfoList lists = new OBUGatherInfoList();
+            OBUGatherInfo gatherInfo = new OBUGatherInfo();
+            gatherInfo.setObuIdNumber(new BerOctetString(obuIdNumber));
+            BeaconID beaconID = new BeaconID();
+            beaconID.setManufacturerid(new BerInteger(obj.getManufacturerid()));
+            beaconID.setIndividualid(new BerInteger(obj.getIndividualid()));
+            gatherInfo.setRseIDNumber(beaconID);
+            gatherInfo.setVehicleType(new BerOctetString(vehicleType));
+            gatherInfo.setObuType(new BerOctetString(obuType));
+            gatherInfo.setGenerationDate(new BerOctetString(generationDate));
+            gatherInfo.setGenerationTime(new BerOctetString(generationTime));
+            lists.getOBUGatherInfo().add(gatherInfo);
+
+            byte[] controlId = { (byte)4 };
+            ReverseByteArrayOutputStream msgBuff = new ReverseByteArrayOutputStream(1024);
+            lists.encode(msgBuff);
+            ControlDevice controlDevice = new ControlDevice();
+            controlDevice.setVpbdControlID(new BerOctetString(controlId));
+            controlDevice.setVpbdControlDeviceData(new BerOctetString(msgBuff.getArray()));
+
+            Registered registered = new Registered();
+            Registered.Continuous continuous = new Registered.Continuous();
+            SubscriptionMode subscriptionMode = new SubscriptionMode();
+
+            continuous.setDatexRegisteredUpdateDelayQty(new BerInteger(0));
+            continuous.setDatexRegisteredStartTime(DsrcAsn1Utils.getRegisterStartTime());
+            continuous.setDatexRegisteredEndTime(DsrcAsn1Utils.getRegisterEndTime());
+            registered.setContinuous(continuous);
+            subscriptionMode.setEventDriven(registered);
+
+            // EndApplicationMessage set
+            EndApplicationMessage endApplicationMessage =  new EndApplicationMessage();
+            endApplicationMessage.setEndApplicationMessageId(new BerObjectIdentifier(messageId));
+            endApplicationMessage.setEndApplicationMessageMsg(new BerAny(msgBuff.getArray()));
+
+            SubscriptionData subscriptionData = new SubscriptionData();
+            subscriptionData.setDatexSubscribePersistentBool(new BerBoolean(false));
+            subscriptionData.setDatexSubscribeStatusCd(new BerEnum(0));         // 0: New, 1: Update
+            subscriptionData.setDatexSubscribeMode(subscriptionMode);
+            subscriptionData.setDatexSubscribePublishFormatCd(new BerEnum(3));  // 0: other, 1: ftp, 2: tftp, 3: dataPacket
+            subscriptionData.setDatexSubscriptionPriorityNbr(new BerInteger(datexSubscriptionPriorityNbr));
+            subscriptionData.setDatexSubscribeGuaranteeBool(new BerBoolean(true));
+            subscriptionData.setDatexSubscribePdu(endApplicationMessage);
+
+            SubscriptionType subscriptionType = new SubscriptionType();
+            subscriptionType.setSubscription(subscriptionData);
+
+            Subscription subscription = new Subscription();
+            //subscription.setDatexSubscribeSerialNbr(new BerInteger(subscribeSerialNbr));
+            subscription.setDatexSubscribeSerialNbr(new BerInteger(subscribeSerialNbr));
+            subscription.setDatexSubscribeType(subscriptionType);
+
+            PDUs pdus = new PDUs();
+            pdus.setSubscription(subscription);
+            byte[] auth = { (byte) eAuthInfo.AI_Subscription.getValue() };
+            C2CAuthenticatedMessage c2c = new C2CAuthenticatedMessage();
+            c2c.setDatexAuthenticationInfoText(new BerOctetString(auth));
+            c2c.setDatexDataPacketNumber(new BerInteger(dataPacketNumber));
+            c2c.setDatexDataPacketPriorityNumber(new BerInteger(dataPacketPriorityNumber));
+            c2c.setOptions(new HeaderOptions());
+            c2c.setPdu(pdus);
+
+            ChannelFuture f = channel.writeAndFlush(c2c);
+            f.awaitUninterruptibly();
+            if (f.isDone() || f.isSuccess()) {
+                log.info("LoginDeviceService.requestObuGatherInfo: {}, {}, send ok", obj.getID(), obj.getRSE_ID());
+            }
+            else {
+                log.error("LoginDeviceService.requestObuGatherInfo: {}, {}, send failed.", obj.getID(), obj.getRSE_ID());
+            }
+        }
+        catch(Exception e) {
+            log.error("LoginDeviceService.requestObuGatherInfo: {}, {}, Exception: {}", obj.getID(), obj.getRSE_ID(), e.toString());
+        }
+        return true;
+    }
+
+    public boolean requestObuStatusInfo(TbRseCtlr obj, Channel channel) {
+
+        int updateDelayQty = 30;
+        String ipAddress = NettyUtils.getRemoteIpAddress(channel);
+        log.info("LoginDeviceService.requestObuStatusInfo: {}, {}, {}", obj.getID(), obj.getMcuID(), updateDelayQty);
+
+        int[] messageId = {1, 0, 15784, 4, 0, 7};
+        int dataPacketNumber = 2;           //obj.getSeq().nextValue()
+        int dataPacketPriorityNumber = 0;
+        int datexSubscriptionPriorityNbr = 10;
+        int subscribeSerialNbr = 1;
+        try {
+            byte[] controlId = {3};
+            byte[] controlData = {};
+            ControlDevice controlDevice = new ControlDevice();
+            controlDevice.setVpbdControlID(new BerOctetString(controlId));
+            controlDevice.setVpbdControlDeviceData(new BerOctetString(controlData));
+            Registered registered = new Registered();
+            Registered.Continuous continuous = new Registered.Continuous();
+            SubscriptionMode subscriptionMode = new SubscriptionMode();
+
+            continuous.setDatexRegisteredUpdateDelayQty(new BerInteger(updateDelayQty));
+            continuous.setDatexRegisteredStartTime(DsrcAsn1Utils.getRegisterStartTime());
+            continuous.setDatexRegisteredEndTime(DsrcAsn1Utils.getRegisterEndTime());
+            registered.setContinuous(continuous);
+            subscriptionMode.setPeriodic(registered);
+
+            // ControlDeviceList set
+            ReverseByteArrayOutputStream msgBuff = new ReverseByteArrayOutputStream(1024);
+            ControlDeviceList controlDeviceList = new ControlDeviceList();
+            controlDeviceList.getControlDevice().add(controlDevice);
+            controlDeviceList.encode(msgBuff);
+
+            // EndApplicationMessage set
+            EndApplicationMessage endApplicationMessage =  new EndApplicationMessage();
+            endApplicationMessage.setEndApplicationMessageId(new BerObjectIdentifier(messageId));
+            endApplicationMessage.setEndApplicationMessageMsg(new BerAny(msgBuff.getArray()));
+
+            SubscriptionData subscriptionData = new SubscriptionData();
+            subscriptionData.setDatexSubscribePersistentBool(new BerBoolean(false));
+            subscriptionData.setDatexSubscribeStatusCd(new BerEnum(0));         // 0: New, 1: Update
+            subscriptionData.setDatexSubscribeMode(subscriptionMode);
+            subscriptionData.setDatexSubscribePublishFormatCd(new BerEnum(3));  // 0: other, 1: ftp, 2: tftp, 3: dataPacket
+            subscriptionData.setDatexSubscriptionPriorityNbr(new BerInteger(datexSubscriptionPriorityNbr));
+            subscriptionData.setDatexSubscribeGuaranteeBool(new BerBoolean(true));
+            subscriptionData.setDatexSubscribePdu(endApplicationMessage);
+
+            SubscriptionType subscriptionType = new SubscriptionType();
+            subscriptionType.setSubscription(subscriptionData);
+
+            Subscription subscription = new Subscription();
+            subscription.setDatexSubscribeSerialNbr(new BerInteger(subscribeSerialNbr));
+            subscription.setDatexSubscribeType(subscriptionType);
+
+            PDUs pdus = new PDUs();
+            pdus.setSubscription(subscription);
+            byte[] auth = { (byte) eAuthInfo.AI_Subscription.getValue() };
+            C2CAuthenticatedMessage c2c = new C2CAuthenticatedMessage();
+            c2c.setDatexAuthenticationInfoText(new BerOctetString(auth));
+            c2c.setDatexDataPacketNumber(new BerInteger(dataPacketNumber));
+            c2c.setDatexDataPacketPriorityNumber(new BerInteger(dataPacketPriorityNumber));
+            c2c.setOptions(new HeaderOptions());
+            c2c.setPdu(pdus);
+
+            ChannelFuture f = channel.writeAndFlush(c2c);
+            f.awaitUninterruptibly();
+            if (f.isDone() || f.isSuccess()) {
+                log.info("LoginDeviceService.requestObuStatusInfo: {}, {}, {}, send ok", obj.getID(), obj.getMcuID(), updateDelayQty);
+            }
+            else {
+                log.error("LoginDeviceService.requestObuStatusInfo: {}, {}, {}, send failed.", obj.getID(), obj.getMcuID(), updateDelayQty);
+            }
+        }
+        catch(Exception e) {
+            log.error("LoginDeviceService.requestObuStatusInfo: {}, {}, {}, Exception: {}", obj.getID(), obj.getMcuID(), updateDelayQty, e);
+        }
+        return true;
+    }
+
 }

+ 44 - 2
src/main/java/com/its/dsrc/xnettcp/dsrc/process/service/impl/SubscriptionRegisterService.java

@@ -5,6 +5,7 @@ import com.beanit.asn1dsrc.enums.eControlDevice;
 import com.beanit.asn1dsrc.enums.eObjectId;
 import com.its.app.utils.NettyUtils;
 import com.its.dsrc.entity.TbRseCtlr;
+import com.its.dsrc.xnettcp.dsrc.process.service.ControlDeviceService;
 import com.its.dsrc.xnettcp.dsrc.process.service.SubscriptionService;
 import io.netty.channel.Channel;
 import lombok.extern.slf4j.Slf4j;
@@ -35,7 +36,11 @@ public class SubscriptionRegisterService implements SubscriptionService {
          *  SubscriptionResponse 에서 호출
          */
         String ipAddress = NettyUtils.getRemoteIpAddress(channel);
-        log.info("SubscriptionRegisterService.response: {}. ObjectId: {}", ipAddress, objectId);
+        //log.info("SubscriptionRegisterService.response: {}. ObjectId: {}", ipAddress, objectId);
+
+        if (objectId == eObjectId.OBJ_MultiMediaData.getValue()) {
+            return multiMediaDataResponse(obj, channel, objectId, subscription);
+        }
 
         if (objectId != eObjectId.OBJ_ControlDevice.getValue()) {
             log.error("SubscriptionRegisterService.response: {}, Unknown ObjectId: {}, Subscription: {}", ipAddress, objectId, subscription.toString());
@@ -73,12 +78,13 @@ public class SubscriptionRegisterService implements SubscriptionService {
                             case Control_BasicInfo:      //(0x02, "Control_BasicInfo"),
                                 break;
                             case Control_StatusRequest:  //(0x03, "Control_StatusRequest"),
+                                ControlDeviceService.getInstance().decoding_ControlDevice_Status_ITTelecom(obj, controlDevice);
                                 break;
                             case Control_InfoRequest:    //(0x04, "Control_InfoRequest"),
                                 DSRCTrafficInfoRequest dsrcTrafficInfoRequest = new DSRCTrafficInfoRequest();
                                 ByteArrayInputStream deviceStream = new ByteArrayInputStream(controlDevice.getVpbdControlDeviceData().value);
                                 dsrcTrafficInfoRequest.decode(deviceStream);
-                                //log.info("SubscriptionRegisterService.response: {}", dsrcTrafficInfoRequest.toString());
+                                log.info("SubscriptionRegisterService.response: {}", dsrcTrafficInfoRequest.toString());
                                 break;
                             case Control_EnterDirInfo:   //(0x05, "Control_EnterDirInfo"),
                                 break;
@@ -94,4 +100,40 @@ public class SubscriptionRegisterService implements SubscriptionService {
         }
         return true;
     }
+
+    private boolean multiMediaDataResponse(TbRseCtlr obj, Channel channel, int objectId, Subscription subscription) {
+        String ipAddress = NettyUtils.getRemoteIpAddress(channel);
+        if (objectId != eObjectId.OBJ_MultiMediaData.getValue()) {
+            log.error("SubscriptionRegisterService.multiMediaDataResponse: {}, OBJ_MultiMediaData ObjectId: {}, Subscription: {}", ipAddress, objectId, subscription.toString());
+            return false;
+        }
+        try {
+            Registered registered = null;
+            int subscribeSerialNbr = subscription.getDatexSubscribeSerialNbr().value.intValue();
+            SubscriptionData subscriptionData = subscription.getDatexSubscribeType().getSubscription();
+
+            if (subscriptionData.getDatexSubscribeMode().getEventDriven() != null) {
+                registered = subscriptionData.getDatexSubscribeMode().getEventDriven();
+                //log.info("SubscriptionRegisterService.multiMediaDataResponse: {}. EventDriven. subscribeSerialNbr: {}", ipAddress, subscribeSerialNbr);
+            }
+            else if (subscriptionData.getDatexSubscribeMode().getPeriodic() != null) {
+                registered = subscriptionData.getDatexSubscribeMode().getPeriodic();
+                //log.info("SubscriptionRegisterService.multiMediaDataResponse: {}. Periodic. subscribeSerialNbr: {}", ipAddress, subscribeSerialNbr);
+            }
+
+            if (registered != null) {
+//                ByteArrayInputStream berInputStream = new ByteArrayInputStream(subscriptionData.getDatexSubscribePdu().getEndApplicationMessageMsg().value);
+//                MultiMediaDataList dataOrg = new MultiMediaDataList();
+//                dataOrg.decode(berInputStream);
+//                List<MultiMediaData> dataLists = dataOrg.getMultiMediaData();
+//                for (MultiMediaData media : dataLists) {
+//                    log.info("{}", media);
+//                }
+            }
+        }
+        catch(Exception e) {
+            log.error("SubscriptionRegisterService.multiMediaDataResponse: {}, Exception: {}", ipAddress, e.toString());
+        }
+        return true;
+    }
 }

+ 2 - 2
src/main/java/com/its/dsrc/xnettcp/dsrc/process/service/impl/SubscriptionSingleService.java

@@ -122,13 +122,13 @@ public class SubscriptionSingleService implements SubscriptionService {
         c2c.setOptions(DsrcAsn1Utils.swapHeaderOptions(obj.getHeaderOptions()));
         c2c.setPdu(pdus);
 
-        log.info("SubscriptionSingleService: {}, C2CAuth: {}", obj.getID(), c2c.toString());
+        log.info("SubscriptionSingleService: {}, C2CAuth: {}", obj.getID(), c2c);
 
         ChannelFuture f = channel.writeAndFlush(c2c);
         if (f.isSuccess()) {
             obj.putRegisteredCommands(c2c);
         } else {
-            log.error("{}. SubscriptionSingleService: {}, Exception: {}", obj.getID(), c2c.toString());
+            log.error("SubscriptionSingleService: {}, Exception: {}", obj.getID(), c2c);
         }
 
         if (isMultimedia) {

+ 2 - 2
src/main/resources/application.yml

@@ -16,7 +16,7 @@ running:
   server-auth-password: PTATMS
   server-sender-text: DSRC Center Unit
   publication-multimedia: false
-  publication-non-crypt-obu: true
+  publication-non-crypt-obu: false
   publication-antenna: 1
   subscription-status: true
   subscription-status-cycle: 30
@@ -42,7 +42,7 @@ spring:
   application:
     name: dsrc-comm-server
   profiles:
-    active: dev
+    active: prod
   main:
     #web-application-type: none
     log-startup-info: true

+ 1 - 1
src/main/resources/mybatis/mapper/RseObuClctMapper.xml

@@ -45,7 +45,7 @@
                    CTYP,
                    OBU_KIND )
            VALUES (
-                   M.ID,
+                   M.RSE_CTLR_NMBR,
                    M.CLCT_DT,
                    M.OBU_IDNT_NMBR,
                    M.CTYP,

+ 340 - 17
src/test/java/com/its/app/DsrcCommServerApplicationTests.java

@@ -1,36 +1,46 @@
 package com.its.app;
 
-import com.beanit.asn1bean.ber.types.BerEnum;
-import com.beanit.asn1bean.ber.types.BerInteger;
-import com.beanit.asn1bean.ber.types.BerObjectIdentifier;
-import com.beanit.asn1bean.ber.types.BerOctetString;
+import com.beanit.asn1bean.ber.ReverseByteArrayOutputStream;
+import com.beanit.asn1bean.ber.types.*;
 import com.beanit.asn1bean.ber.types.string.BerUTF8String;
-import com.beanit.asn1dsrc.dsrc.C2CAuthenticatedMessage;
-import com.beanit.asn1dsrc.dsrc.Login;
-import com.beanit.asn1dsrc.dsrc.PDUs;
+import com.beanit.asn1dsrc.dsrc.*;
 import com.beanit.asn1dsrc.enums.eAuthInfo;
 import com.beanit.asn1dsrc.util.DsrcAsn1Utils;
+import com.its.app.utils.ByteUtils;
+import com.its.app.utils.SysUtils;
 import com.its.dsrc.DsrcCommServerApplication;
+import com.its.dsrc.entity.TbRseCtlr;
+import com.its.dsrc.global.AppRepository;
 import lombok.extern.slf4j.Slf4j;
 import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.context.SpringBootTest;
 
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+
 @Slf4j
 @SpringBootTest(classes = DsrcCommServerApplication.class)
 public class DsrcCommServerApplicationTests {
 
     @Test
-    void test1() {
+    void requestLogin() {
+        int dataPacketNumber = 0;           //obj.getSeq().nextValue()
+        int dataPacketPriorityNumber = 0;
+
         Login login = new Login();
-        login.setDatexSenderTxt(new BerUTF8String("GJATMSSERVER"));
-        login.setDatexDestinationTxt(new BerUTF8String("GJATMSSERVER"));
-        login.setDatexLoginUserNameTxt(new BerUTF8String("PTATMS"));
-        login.setDatexLoginPasswordTxt(new BerUTF8String("PTATMS"));
+        login.setDatexSenderTxt(new BerUTF8String("PTATMSSERVER"));
+        login.setDatexDestinationTxt(new BerUTF8String("PTMCU00000001"));
+//        login.setDatexLoginUserNameTxt(new BerUTF8String(runningConfig.getServerAuthUser()));
+//        login.setDatexLoginPasswordTxt(new BerUTF8String(runningConfig.getServerAuthPassword()));
+        login.setDatexLoginUserNameTxt(new BerUTF8String(""));
+        login.setDatexLoginPasswordTxt(new BerUTF8String(""));
         login.setDatexLoginHeartbeatDurationMaxQty(new BerInteger(120));
-        login.setDatexLoginResponseTimeOutQty(new BerInteger(5));
+        login.setDatexLoginResponseTimeOutQty(new BerInteger(30));
         login.setDatexLoginInitiatorCd(new BerEnum(1));
         login.setDatexLoginDatagramSizeQty(new BerInteger(2048));
-        int[] encodingRules = {2, 1, 1};
+        int[] encodingRules = {2, 1};
         Login.DatexLoginEncodingRulesId loginEncodingRulesId = new Login.DatexLoginEncodingRulesId();
         loginEncodingRulesId.getBerObjectIdentifier().add(new BerObjectIdentifier(encodingRules));
         login.setDatexLoginEncodingRulesId(loginEncodingRulesId);
@@ -39,13 +49,326 @@ public class DsrcCommServerApplicationTests {
         PDUs loginPdu = new PDUs();
         loginPdu.setLogin(login);
 
+        HeaderOptions headerOptions = new HeaderOptions();
+        Time tm = new Time();
+        Time.TimeSecondFractions tmFac = new Time.TimeSecondFractions();
+        Time.TimeTimezone        tmZon = new Time.TimeTimezone();
+        Calendar currTm = Calendar.getInstance();
+        tm.setTimeYearQty(new BerInteger(currTm.get(Calendar.YEAR)));
+        tm.setTimeMonthQty(new BerInteger(currTm.get(Calendar.MONTH)+1));
+        tm.setTimeDayQty(new BerInteger(currTm.get(Calendar.DATE)));
+        tm.setTimeHourQty(new BerInteger(currTm.get(Calendar.HOUR_OF_DAY)));
+        tm.setTimeMinuteQty(new BerInteger(currTm.get(Calendar.MINUTE)));
+        tm.setTimeSecondQty(new BerInteger(currTm.get(Calendar.SECOND)));
+        tmFac.setMilliseconds(new BerInteger(currTm.get(Calendar.MILLISECOND)));
+        tm.setTimeSecondFractions(tmFac);
+        headerOptions.setDatexDataPacketTime(tm);
+
         C2CAuthenticatedMessage c2c = new C2CAuthenticatedMessage();
         c2c.setDatexAuthenticationInfoText(new BerOctetString(auth));
-        c2c.setDatexDataPacketNumber(new BerInteger(1234));
-        c2c.setDatexDataPacketPriorityNumber(new BerInteger(1));
-        c2c.setOptions(DsrcAsn1Utils.getDefaultOptions());
+        c2c.setDatexDataPacketNumber(new BerInteger(dataPacketNumber));
+        c2c.setDatexDataPacketPriorityNumber(new BerInteger(dataPacketPriorityNumber));
+        c2c.setOptions(headerOptions);
         c2c.setPdu(loginPdu);
 
         log.error("{}", c2c);
     }
+
+    @Test
+    void requestObuStatusInfo() {
+        // 상태정보 요청
+        int updateDelayQty = 30;
+
+        int[] messageId = {1, 0, 15784, 4, 0, 7};
+        int subscribeSerialNbr = 22;
+
+        try {
+            byte[] controlId = {3};
+            byte[] controlData = {};
+            ControlDevice controlDevice = new ControlDevice();
+            controlDevice.setVpbdControlID(new BerOctetString(controlId));
+            controlDevice.setVpbdControlDeviceData(new BerOctetString(controlData));
+            Registered registered = new Registered();
+            Registered.Continuous continuous = new Registered.Continuous();
+            SubscriptionMode subscriptionMode = new SubscriptionMode();
+
+            continuous.setDatexRegisteredUpdateDelayQty(new BerInteger(updateDelayQty));
+            continuous.setDatexRegisteredStartTime(DsrcAsn1Utils.getRegisterStartTime());
+            continuous.setDatexRegisteredEndTime(DsrcAsn1Utils.getRegisterEndTime());
+            registered.setContinuous(continuous);
+            subscriptionMode.setPeriodic(registered);
+
+            // ControlDeviceList set
+            ReverseByteArrayOutputStream msgBuff = new ReverseByteArrayOutputStream(1024);
+            ControlDeviceList controlDeviceList = new ControlDeviceList();
+            controlDeviceList.getControlDevice().add(controlDevice);
+            controlDeviceList.encode(msgBuff);
+
+            // EndApplicationMessage set
+            EndApplicationMessage endApplicationMessage =  new EndApplicationMessage();
+            endApplicationMessage.setEndApplicationMessageId(new BerObjectIdentifier(messageId));
+            endApplicationMessage.setEndApplicationMessageMsg(new BerAny(msgBuff.getArray()));
+
+            SubscriptionData subscriptionData = new SubscriptionData();
+            subscriptionData.setDatexSubscribePersistentBool(new BerBoolean(false));
+            subscriptionData.setDatexSubscribeStatusCd(new BerEnum(0));         // 0: New, 1: Update
+            subscriptionData.setDatexSubscribeMode(subscriptionMode);
+            subscriptionData.setDatexSubscribePublishFormatCd(new BerEnum(3));  // 0: other, 1: ftp, 2: tftp, 3: dataPacket
+            //subscriptionData.setDatexSubscriptionPriorityNbr(new BerInteger(1));
+            subscriptionData.setDatexSubscriptionPriorityNbr(new BerInteger(10));
+            subscriptionData.setDatexSubscribeGuaranteeBool(new BerBoolean(true));
+            subscriptionData.setDatexSubscribePdu(endApplicationMessage);
+
+            SubscriptionType subscriptionType = new SubscriptionType();
+            subscriptionType.setSubscription(subscriptionData);
+
+            Subscription subscription = new Subscription();
+            subscription.setDatexSubscribeSerialNbr(new BerInteger(subscribeSerialNbr));
+            subscription.setDatexSubscribeType(subscriptionType);
+
+            PDUs pdus = new PDUs();
+            pdus.setSubscription(subscription);
+            byte[] auth = { (byte) eAuthInfo.AI_Subscription.getValue() };
+            C2CAuthenticatedMessage c2c = new C2CAuthenticatedMessage();
+            c2c.setDatexAuthenticationInfoText(new BerOctetString(auth));
+            c2c.setDatexDataPacketNumber(new BerInteger(subscribeSerialNbr));
+            c2c.setDatexDataPacketPriorityNumber(new BerInteger(1));
+            //c2c.setOptions(DsrcAsn1Utils.getDefaultOptions());
+            c2c.setOptions(new HeaderOptions());
+
+            c2c.setPdu(pdus);
+
+            log.info("{}", c2c);
+        }
+        catch(Exception e) {
+            log.error("LoginDeviceService.requestObuStatusInfo: {}, Exception: {}", updateDelayQty, e);
+        }
+    }
+
+    @Test
+    void requestObuGatherInfo() {
+        int[] messageId = {1, 0, 15784, 8, 0, 8};
+        TbRseCtlr obj = AppRepository.getInstance().getCtlrMap().get("1001");
+        log.error("{}", obj);
+        int subscribeSerialNbr = 0;
+        int dataPacketNumber = 1;           //obj.getSeq().nextValue()
+        int dataPacketPriorityNumber = 0;
+        int datexSubscriptionPriorityNbr = 10;
+        try {
+            // OBU 교통정보 요청
+            byte[] obuIdNumber = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+            byte[] vehicleType = {0};
+            byte[] obuType = {0};
+            byte[] generationDate = {0,0,0,0};
+            byte[] generationTime = {0,0,0};
+
+            OBUGatherInfoList lists = new OBUGatherInfoList();
+            OBUGatherInfo gatherInfo = new OBUGatherInfo();
+            gatherInfo.setObuIdNumber(new BerOctetString(obuIdNumber));
+            BeaconID beaconID = new BeaconID();
+            beaconID.setManufacturerid(new BerInteger(obj.getManufacturerid()));
+            beaconID.setIndividualid(new BerInteger(obj.getIndividualid()));
+            gatherInfo.setRseIDNumber(beaconID);
+            gatherInfo.setVehicleType(new BerOctetString(vehicleType));
+            gatherInfo.setObuType(new BerOctetString(obuType));
+            gatherInfo.setGenerationDate(new BerOctetString(generationDate));
+            gatherInfo.setGenerationTime(new BerOctetString(generationTime));
+            lists.getOBUGatherInfo().add(gatherInfo);
+
+            byte[] controlId = { (byte)4 };
+            ReverseByteArrayOutputStream msgBuff = new ReverseByteArrayOutputStream(1024);
+            lists.encode(msgBuff);
+            ControlDevice controlDevice = new ControlDevice();
+            controlDevice.setVpbdControlID(new BerOctetString(controlId));
+            controlDevice.setVpbdControlDeviceData(new BerOctetString(msgBuff.getArray()));
+
+            Registered registered = new Registered();
+            Registered.Continuous continuous = new Registered.Continuous();
+            SubscriptionMode subscriptionMode = new SubscriptionMode();
+
+            continuous.setDatexRegisteredUpdateDelayQty(new BerInteger(0));
+            continuous.setDatexRegisteredStartTime(DsrcAsn1Utils.getRegisterStartTime());
+            continuous.setDatexRegisteredEndTime(DsrcAsn1Utils.getRegisterEndTime());
+            registered.setContinuous(continuous);
+            subscriptionMode.setEventDriven(registered);
+
+            // EndApplicationMessage set
+            EndApplicationMessage endApplicationMessage =  new EndApplicationMessage();
+            endApplicationMessage.setEndApplicationMessageId(new BerObjectIdentifier(messageId));
+            endApplicationMessage.setEndApplicationMessageMsg(new BerAny(msgBuff.getArray()));
+
+            SubscriptionData subscriptionData = new SubscriptionData();
+            subscriptionData.setDatexSubscribePersistentBool(new BerBoolean(false));
+            subscriptionData.setDatexSubscribeStatusCd(new BerEnum(0));         // 0: New, 1: Update
+            subscriptionData.setDatexSubscribeMode(subscriptionMode);
+            subscriptionData.setDatexSubscribePublishFormatCd(new BerEnum(3));  // 0: other, 1: ftp, 2: tftp, 3: dataPacket
+            //subscriptionData.setDatexSubscriptionPriorityNbr(new BerInteger(1));
+            subscriptionData.setDatexSubscriptionPriorityNbr(new BerInteger(datexSubscriptionPriorityNbr));
+            subscriptionData.setDatexSubscribeGuaranteeBool(new BerBoolean(true));
+            subscriptionData.setDatexSubscribePdu(endApplicationMessage);
+
+            SubscriptionType subscriptionType = new SubscriptionType();
+            subscriptionType.setSubscription(subscriptionData);
+
+            Subscription subscription = new Subscription();
+            //subscription.setDatexSubscribeSerialNbr(new BerInteger(subscribeSerialNbr));
+            subscription.setDatexSubscribeSerialNbr(new BerInteger(subscribeSerialNbr));
+            subscription.setDatexSubscribeType(subscriptionType);
+
+            PDUs pdus = new PDUs();
+            pdus.setSubscription(subscription);
+            byte[] auth = { (byte) eAuthInfo.AI_Subscription.getValue() };
+            C2CAuthenticatedMessage c2c = new C2CAuthenticatedMessage();
+            c2c.setDatexAuthenticationInfoText(new BerOctetString(auth));
+            c2c.setDatexDataPacketNumber(new BerInteger(dataPacketNumber));
+            c2c.setDatexDataPacketPriorityNumber(new BerInteger(dataPacketPriorityNumber));
+            c2c.setOptions(new HeaderOptions());
+            c2c.setPdu(pdus);
+
+            log.info("{}", c2c);
+        }
+        catch(Exception e) {
+            log.error("LoginDeviceService.requestObuGatherInfo: {}, {}, Exception: {}", obj.getID(), obj.getRSE_ID(), e.toString());
+        }
+    }
+
+    @Test
+    void packetEncoding() {
+        TbRseCtlr obj = AppRepository.getInstance().getCtlrMap().get("1001");
+        List<String> lists = new ArrayList<>();
+//        lists.add("3068800101815f305d800102810100820100a31ba719800207e681010c82010983010a84011f85010fa6048202013aa435a133800c474a41544d53534552564552810d50544d4355303030303030303182008300a40306015185013c86011e870101880202408202e773");
+//        lists.add("3081ce8001018181c43081c1800106810101820100a300a481b3a581b0800100a181aaa081a7800100810100a24ba149a047800100a120800207e681010c82010983010a84011f85010fa603800100a706800109810100a2208002083381010c82010983010a84011f85010fa603800100a70680010981010083010384010a8501ffa649800628fb28080008a13f303d303b80200000000000000000000000000000000000000000000000000000000000000000a10680010081010082010083010084040000000085030000008202694d");
+//        lists.add("30819480010181818a308187800106810102820100a300a47aa578800101a173a071800100810100a24ba249a04780011ea120800207e681010c82010983010a84011f85010fa603800100a706800109810100a2208002083381010c82010983010a84011f85010fa603800100a70680010981010083010384010a8501ffa613800628fb28040007a1093007300580010381008202842f");
+//        lists.add("302180010181183016800108810103820100a300a409a807800108a102810082028dc0");
+//        lists.add("3082012b800101818201203082011c800106810104820100a300a482010da5820109800102a1820102a081ff800100810100a24ba249a04780011ea120800207e681010c82010983010a84011f85010fa603800100a706800109810100a2208002083381010c82010983010a84011f85010fa603800100a70680010981010083010384010a8501ffa681a0800628fb28040007a1819530819230818f800102818189308186800d50544d43553030303030303031810166a3723070800102810101820e3230323231323039313033313135a30a80020105810401101001a44c3011800101a10c300a800201058104011010053011800102a10c300a800201058104011010023011800102a10c300a800201058104011010033011800103a10c300a80020105810401101023820279e1");
+//        lists.add("303c80010181333031800140810105820100a300a424a6228001ffa11da01b3019800101810100820100a30ea10c800628fb28050001a10230008202e944");    // error
+//        lists.add("302180010181183016800108810106820100a300a409a807800105a102830082027dff");
+//        lists.add("302180010181183016800108810107820100a300a409a807800106a10283008202edea");
+//        lists.add("302180010181183016800108810108820100a300a409a807800107a10283008202dee2");
+//        lists.add("302180010181183016800108810109820100a300a409a807800108a102830082024fe7");
+//        lists.add("30218001018118301680010881010a820100a300a409a807800109a102830082027f2a");
+//        lists.add("30218001018118301680010881010b820100a300a409a80780010aa10283008202ef3f");
+//        lists.add("30218001018118301680010881010c820100a300a409a80780010ba102830082021eb0");
+//        lists.add("30218001018118301680010881010d820100a300a409a80780010ca102830082024e54");
+//        lists.add("30218001018118301680010881010e820100a300a409a80780010da102830082027e99");
+//        lists.add("30218001018118301680010881010f820100a300a409a80780010ea10283008202ee8c");
+//        lists.add("302180010181183016800108810110820100a300a409a80780010fa102830082021889");
+//        lists.add("302180010181183016800108810111820100a300a409a807800110a102830082024a4d");
+//        lists.add("302180010181183016800108810112820100a300a409a807800111a102830082027a80");
+//        lists.add("302180010181183016800108810113820100a300a409a807800112a10283008202ea95");
+//        lists.add("302180010181183016800108810114820100a300a409a807800113a102830082021b1a");
+//        lists.add("302180010181183016800108810115820100a300a409a807800114a102830082024bfe");
+//        lists.add("302180010181183016800108810116820100a300a409a807800115a102830082027b33");
+//        lists.add("302180010181183016800108810117820100a300a409a807800116a10283008202eb26");
+//        lists.add("302180010181183016800108810118820100a300a409a807800117a10283008202d82e");
+//        lists.add("302180010181183016800108810119820100a300a409a807800118a10283008202492b");
+//        lists.add("30218001018118301680010881011a820100a300a409a807800119a1028300820279e6");
+//        lists.add("30218001018118301680010881011b820100a300a409a80780011aa10283008202e9f3");
+//        lists.add("30218001018118301680010881011c820100a300a409a80780011ba10283008202187c");
+//        lists.add("3081c98001018181bf3081bc80014081011d820100a300a481aea681ab8001ffa181a5a081a230819f800101810101820100a38193a18190800628fb28050001a181853081823043800101810e3230323231323039313033323135a200830101a4298027534bebb7b0ec9584ed8c8ced8ab8ec959eec82bceab1b0eba6ac2035ebb68420ec868cec9a942e303b800102810e3230323231323039313033323135a200830101a421801feab5b0ebacb8eab590ec82bceab1b0eba6ac2032ebb68420ec868cec9a942e820269f5");
+//        lists.add("30218001018118301680010881011e820100a300a409a80780011da102830082027855");
+//        lists.add("3037800101812e302c80010181010182010aa300a41fa01d800d50544d43553030303030303032810c505441544d535345525645528202ea54");
+//        lists.add("3023800101811a301880010881010082010aa300a40ba809800102a10480025101820205e0");
+//        lists.add("3025800101811c301a80010881010182010aa300a40da80b800102a10682041012f5708202f990");
+        lists.add("3081a780010181819d30819a80010181010882010aa300a4818ca58189800101a18183a08180800100810100a229a227a02580013ca120800207e681010c82010983010e840121850108a603820100a70680010981010083010384010a8501ffa644800628fb28050001a13a3038303680016f81056655335f62a2150c01410c01350c016d0c014f0c016b0c014d0c0170830108a410a10e80010081075fa80468cf411682008202375d");
+//        lists.add("3025800101811c301a80010881010282010aa300a40da80b800102a10682041012f5708202caa3");
+//        lists.add("3025800101811c301a80010881010382010aa300a40da80b800102a10682041012f57082021bb3");
+//        lists.add("30218001018118301680010881010482010aa300a409a807800102a10283008202d7e1");
+//        lists.add("307d8001018174307280010181010582010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80203461396336343931626130336133356666643135613064633735356237363832a10a8002010581040110100282010183010184042022120985031433088202a22a");
+//        lists.add("307d8001018174307280010181010682010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80203237313130643834623235383062633535376231656432663036666263323065a10a80020105810401101002820101830101840420221209850314330882023b86");
+//        lists.add("307d8001018174307280010181010782010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80203963636634346535376362336566373835363333306639663234663861633365a10a80020105810401101002820101830101840420221209850314330882022aa5");
+//        lists.add("307d8001018174307280010181010882010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80203835303535376531623661393933306366376566336639643962356135353836a10a800201058104011010028201068301018404202212098503143308820282db");
+//        lists.add("307d8001018174307280010181010982010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80206535343832626230656330653239656263333561626264646433616662303566a10a80020105810401101002820103830101840420221209850314330882021b5a");
+//        lists.add("307d8001018174307280010181010a82010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80203964303462373136636266383634663661623366366639353130653831653135a10a8002010581040110100282010383010184042022120985031433088202ab27");
+//        lists.add("307d8001018174307280010181010b82010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80203564363233666334663261383838363530346437323537393933613564306230a10a80020105810401101002820101830101840420221209850314330982025341");
+//        lists.add("307d8001018174307280010181010c82010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80206265623031363838383532326361356265393337313834393461643563326338a10a80020105810401101002820101830101840420221209850314330982024957");
+//        lists.add("307d8001018174307280010181010d82010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80203664333861636435616438633262373137646436616261616363636537666130a10a8002010581040110100282010183010184042022120985031433098202bbb2");
+//        lists.add("307d8001018174307280010181010e82010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80203930653435373432303865643062613739366630363233626431333035636231a10a80020105810401101002820101830101840420221209850314331182029d41");
+//        lists.add("307d8001018174307280010181010f82010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80203432666331333237383736666461376435343763666564316230616637306534a10a8002010581040110100282010183010184042022120985031433118202ffa9");
+//        lists.add("307d8001018174307280010181011082010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80203037333037366463316663316138356135656439303763613533303161646339a10a8002010581040110100282010183010184042022120985031433128202ce89");
+//        lists.add("307d8001018174307280010181011182010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80206135623563333135643961616438643761613336313733623464373230376433a10a80020105810401101002820101830101840420221209850314331382029fc8");
+//        lists.add("307d8001018174307280010181011282010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80203661393531616434346336366533616130636363316166656135643138623561a10a80020105810401101002820101830101840420221209850314331682025e6d");
+//        lists.add("307d8001018174307280010181011382010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80206664383162626533336337633830653136373331633461346263626665333863a10a80020105810401101002820101830101840420221209850314332282023249");
+//        lists.add("307d8001018174307280010181011482010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80206266303633306166326262363438323961376661363533396237626535353235a10a800201058104011010028201018301018404202212098503143325820270d7");
+//        lists.add("307d8001018174307280010181011582010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80203562343731356562333264303432636336643262343534656564363666623666a10a8002010581040110100282010183010184042022120985031433268202f8ac");
+//        lists.add("307d8001018174307280010181011682010aa300a465a6638001ffa15ea05c305a8001648101648201ffa34fa14d800628fb28080008a1433041303f80206462393331613834326164646265653336303439363939323566343332316266a10a80020105810401101002820101830101840420221209850314333882023396");
+//        lists.add("30798001018170306e80010181011782010aa300a461a65f8001ffa15aa05830568001648101648201ffa34ba149800628fb28040007a13f303d303b80010381363034800d474a4d4355303030303030303281040a0a010ca31d301ba00a8002010581040110100281010082040185c80a83010184016682021eaa");
+
+        for (String data : lists) {
+            byte[] inBytes = ByteUtils.hexToByteArray(data);
+            DatexDataPacket datexDataPacket = new DatexDataPacket();
+            try {
+                datexDataPacket.decode(new ByteArrayInputStream(inBytes, 0, inBytes.length));
+                BerOctetString berOctetString = datexDataPacket.getDatexData();
+                C2CAuthenticatedMessage c2c = new C2CAuthenticatedMessage();
+                c2c.decode(new ByteArrayInputStream(berOctetString.value, 0, berOctetString.value.length));
+                log.info("{}", c2c);
+
+                String ipAddress = "127.0.0.1";
+                Subscription subscription = c2c.getPdu().getSubscription();
+                if (subscription != null) {
+                    Registered registered = null;
+                    int subscribeSerialNbr = subscription.getDatexSubscribeSerialNbr().value.intValue();
+                    SubscriptionData subscriptionData = subscription.getDatexSubscribeType().getSubscription();
+
+                    if (subscriptionData.getDatexSubscribeMode().getEventDriven() != null) {
+                        registered = subscriptionData.getDatexSubscribeMode().getEventDriven();
+                        log.info("SubscriptionRegisterService.response: {}. EventDriven. subscribeSerialNbr: {}", ipAddress, subscribeSerialNbr);
+                    }
+                    else if (subscriptionData.getDatexSubscribeMode().getPeriodic() != null) {
+                        registered = subscriptionData.getDatexSubscribeMode().getPeriodic();
+                        log.info("SubscriptionRegisterService.response: {}. Periodic. subscribeSerialNbr: {}", ipAddress, subscribeSerialNbr);
+                    }
+                    int objectId = DsrcAsn1Utils.getObjectId(subscriptionData.getDatexSubscribePdu().getEndApplicationMessageId().value);
+                    log.error("{}", objectId);
+                    log.error("{}", SysUtils.byteArrayToHex(subscriptionData.getDatexSubscribePdu().getEndApplicationMessageMsg().value));
+
+                    if (registered != null) {
+                        //log.error("{}", registered);
+                        ByteArrayInputStream berInputStream = new ByteArrayInputStream(subscriptionData.getDatexSubscribePdu().getEndApplicationMessageMsg().value);
+                        MultiMediaDataList dataOrg = new MultiMediaDataList();
+                        dataOrg.decode(berInputStream);
+
+//                        ControlDeviceList devices = new ControlDeviceList();
+//                        ControlDevice device = new ControlDevice();
+                        log.info("xxxxxxxxxxxxxxxxxxxxx");
+                        //device.decode(berInputStream);
+                        log.info("{}", dataOrg);
+                        List<MultiMediaData> dataLists = dataOrg.getMultiMediaData();
+                        for (MultiMediaData media : dataLists) {
+                            log.error("{}", media);
+                        }
+//                        for (ControlDevice controlDevice : list) {
+//                            if (controlDevice.getVpbdControlDeviceData() != null) {
+//                                eControlDevice e = eControlDevice.getByValue(controlDevice.getVpbdControlID().value[0]);
+//                                log.info("SubscriptionRegisterService.response: {}", e.toString());
+//                                switch(e) {
+//                                    case Control_Command:        //(0x01, "Control_Command"),
+//                                        break;
+//                                    case Control_BasicInfo:      //(0x02, "Control_BasicInfo"),
+//                                        break;
+//                                    case Control_StatusRequest:  //(0x03, "Control_StatusRequest"),
+//                                        ControlDeviceService.getInstance().decoding_ControlDevice_Status_ITTelecom(obj, controlDevice);
+//                                        break;
+//                                    case Control_InfoRequest:    //(0x04, "Control_InfoRequest"),
+//                                        DSRCTrafficInfoRequest dsrcTrafficInfoRequest = new DSRCTrafficInfoRequest();
+//                                        ByteArrayInputStream deviceStream = new ByteArrayInputStream(controlDevice.getVpbdControlDeviceData().value);
+//                                        dsrcTrafficInfoRequest.decode(deviceStream);
+//                                        //log.info("SubscriptionRegisterService.response: {}", dsrcTrafficInfoRequest.toString());
+//                                        break;
+//                                    case Control_EnterDirInfo:   //(0x05, "Control_EnterDirInfo"),
+//                                        break;
+//                                    case Control_DisconnectInfo: //(0x06, "Control_DisconnectInfo");
+//                                        break;
+//                                }
+//                            }
+//                        }
+                    }
+                }
+
+            } catch (Exception e) {
+                log.error("Exception: {}, {}", e, data);
+            }
+        }
+    }
 }