pangs 6 gadi atpakaļ
revīzija
50925d8d86

+ 30 - 0
.gitignore

@@ -0,0 +1,30 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+log/
+bin/
+*.class
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/

+ 30 - 0
application.dat

@@ -0,0 +1,30 @@
+{
+	"services" : [
+					{
+						"name" : "kakao",
+						"address" : "10.0.1.1",
+						"port":	2222, 
+						"events" : [
+									"msg_device_event",
+									"unsubscription"
+						          ] 
+					}, 
+					
+					{
+						"name" : "kt",
+						"address" : "10.0.1.1",
+						"port":	2224, 
+						"events" : [
+									"msg_device_event",
+									"msg_home_devices_status_event",
+									"msg_ararm_event",
+									"msg_visitor_event",
+									"msg_notice_event",
+									"msg_car_inout_event",
+									"msg_box_event",
+									"msg_energy_event",
+									"unsubscription"
+						          ] 
+					}
+				]
+}

BIN
bridge/lib/gson-2.8.5.jar


BIN
bridge/lib/logback-classic-1.0.7.jar


BIN
bridge/lib/logback-core-1.0.7.jar


BIN
bridge/lib/slf4j-api-1.6.6.jar


+ 30 - 0
bridge/src/com/icontrole/bridge/Main.java

@@ -0,0 +1,30 @@
+package com.icontrole.bridge;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.icontrole.bridge.wallpad.IMapMultiSocket;
+
+public class Main {
+	private static Logger logger = LoggerFactory.getLogger(Main.class);
+	public static void main(String[] args) {
+		
+		logger.info("*************************************************************************");
+    	logger.info("*                                                                       *");
+    	logger.info("*  *****   *         *******   *          **       *      *    *    *   *");
+    	logger.info("*  *       *            *      *          **       *      *    *    *   *");
+    	logger.info("*  *       ***         * *     *         *  *   ****      ******    *   *");
+    	logger.info("*  *       *          *   *    *        *    *     *      *    *  ***   *");
+    	logger.info("*  *****   *         *     *   *       *      *    *      *    *    *   *");
+    	logger.info("*       *                      *      *        *   *      ******    *   *");
+    	logger.info("*       *                                                               *");
+    	logger.info("*       *******                                                         *");
+    	logger.info("*                                                       BRIDGE BY PANGS *");
+    	logger.info("*************************************************************************");
+
+    	// ¼ÒÄÏ ¼­¹ö ½ÃÀÛ
+    	new IMapMultiSocket();
+	}
+
+}

+ 7 - 0
bridge/src/com/icontrole/bridge/common/COMMON_INFO.java

@@ -0,0 +1,7 @@
+package com.icontrole.bridge.common;
+
+public class COMMON_INFO {
+	public static final String LINUX_PROPERTIES_DIR = "/service/bridge/application.dat";
+	public static final String WINDOWS_PROPERTIES_DIR = "D:\\temp\\bridge_jar\\application.dat";
+	
+}

+ 67 - 0
bridge/src/com/icontrole/bridge/common/CommonUtil.java

@@ -0,0 +1,67 @@
+package com.icontrole.bridge.common;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+
+import com.google.gson.JsonIOException;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonSyntaxException;
+
+public class CommonUtil {
+	public static JsonObject getJsonObject(String str) {
+		JsonParser jsonParser = new JsonParser();
+		
+		JsonObject object = null;
+		try {
+			object = (JsonObject)jsonParser.parse(str);
+		} catch (JsonIOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} catch (JsonSyntaxException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} 
+		
+		return object;
+	}
+	
+	public static boolean isWindows() {
+		String OS = System.getProperty("os.name").toLowerCase();
+
+		if (OS.indexOf("win") >= 0) {
+			return true;
+		}
+		return false;
+	}
+	
+	public static String readFile(String filePath) {
+        BufferedReader br = null;
+        StringBuffer sb = new StringBuffer(); // Å×½ºÆ®¿ë º¯¼ö
+         try {
+            br = new BufferedReader(new FileReader(filePath));
+            String line = null;
+            
+            while ((line = br.readLine()) != null) {
+                //System.out.println(line);
+                sb.append(line);
+            }
+ 
+        } catch (IOException ioe) {
+            System.out.println(ioe.getMessage());
+        } finally {
+            try { 
+                if (br!=null) 
+                    br.close(); 
+            } catch (Exception e) {}
+        }
+         
+         return sb.toString();
+    }
+	
+	public static String getPropFileDir() {
+		return isWindows()?COMMON_INFO.WINDOWS_PROPERTIES_DIR:COMMON_INFO.LINUX_PROPERTIES_DIR;
+	}
+
+}

+ 55 - 0
bridge/src/com/icontrole/bridge/common/SERVER_INFO.java

@@ -0,0 +1,55 @@
+package com.icontrole.bridge.common;
+
+public class SERVER_INFO {
+	// 월패드에서 수신되는 데이터를 처리 하기 위한 소켓 포트
+	public static final int WalladReceivePort = 8098;
+	
+	public enum SERVICE_LIST{
+		KAKAO	("kakao", 	"10.0.1.1", 2222),
+		GOOGLE	("google", 	"10.0.1.1", 2223),
+		KT		("kt", 		"10.0.1.1", 2224),
+		LGUPLUS	("UPLUS", 	"10.0.1.1", 2225);
+		
+		private String serviceName;
+		private String address;
+		private int port;
+		
+		
+		private SERVICE_LIST(String serviceName, String address, int port) {
+			this.serviceName = serviceName;
+			this.address = address;
+			this.port = port;
+		}
+
+
+		public String getServiceName() {
+			return serviceName;
+		}
+
+
+		public void setServiceName(String serviceName) {
+			this.serviceName = serviceName;
+		}
+
+
+		public String getAddress() {
+			return address;
+		}
+
+
+		public void setAddress(String address) {
+			this.address = address;
+		}
+
+
+		public int getPort() {
+			return port;
+		}
+
+
+		public void setPort(int port) {
+			this.port = port;
+		}
+		
+	}
+}

+ 65 - 0
bridge/src/com/icontrole/bridge/dto/ServiceDetail.java

@@ -0,0 +1,65 @@
+package com.icontrole.bridge.dto;
+
+import java.util.Arrays;
+
+public class ServiceDetail {
+	private String name;
+	
+	private String address;
+	
+	private int port;
+	
+	private String[] events;
+
+	public ServiceDetail() {
+		super();
+		// TODO Auto-generated constructor stub
+	}
+
+	public ServiceDetail(String name, String address, int port, String[] events) {
+		super();
+		this.name = name;
+		this.address = address;
+		this.port = port;
+		this.events = events;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getAddress() {
+		return address;
+	}
+
+	public void setAddress(String address) {
+		this.address = address;
+	}
+
+	public int getPort() {
+		return port;
+	}
+
+	public void setPort(int port) {
+		this.port = port;
+	}
+
+	public String[] getEvents() {
+		return events;
+	}
+
+	public void setEvents(String[] events) {
+		this.events = events;
+	}
+
+	@Override
+	public String toString() {
+		return "ServiceDetail [name=" + name + ", address=" + address + ", port=" + port + ", events="
+				+ Arrays.toString(events) + "]";
+	}
+	
+}

+ 5 - 0
bridge/src/com/icontrole/bridge/socket/iMapRequestSync.java

@@ -0,0 +1,5 @@
+package com.icontrole.bridge.socket;
+
+public class iMapRequestSync {
+
+}

+ 56 - 0
bridge/src/com/icontrole/bridge/wallpad/IMapMultiSocket.java

@@ -0,0 +1,56 @@
+package com.icontrole.bridge.wallpad;
+
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.icontrole.bridge.common.SERVER_INFO;
+
+
+public class IMapMultiSocket{
+	private static final Logger logger = LoggerFactory.getLogger(IMapMultiSocket.class);
+
+	public IMapMultiSocket() {
+		logger.info("*************************************************************************");
+		logger.info("* Socket 다중 접속 서버 실행 .. ");
+		logger.info("* 서버 소켓 포트 : " + SERVER_INFO.WalladReceivePort);
+		logger.info("*************************************************************************");
+		
+		ServerSocket server = null;
+		long connectCount = 0;
+		try {
+			server = new ServerSocket(SERVER_INFO.WalladReceivePort);
+			
+			while(true) {
+				logger.info("[클라이언트의 접속을 기다리고 있습니다......]");
+				
+				Socket clientSocket = server.accept();
+				connectCount++;
+				
+				InetAddress ia = clientSocket.getInetAddress();
+				int port = clientSocket.getLocalPort();
+				
+				String ip = ia.getHostAddress();
+				
+				logger.info("* --> connectCount = [" + connectCount + "] -- 접속 포트 = [" + port + "] -- CLIENT IP = ["+ip+"]");
+				
+				if (connectCount > 2000000000) connectCount = 0;
+				
+				new MsgServerHandler(clientSocket).start();
+			}
+		}catch(Exception e) { 
+			logger.error("[IMapMultiSocket] - 메인 에러....    " + e.getMessage());
+			logger.error(e.getStackTrace().toString());
+		} finally {
+			try {
+				server.close();
+			}catch(Exception e) {
+				logger.error("무시.");
+			}
+		}
+		
+	}
+}

+ 62 - 0
bridge/src/com/icontrole/bridge/wallpad/MsgClientHandler.java

@@ -0,0 +1,62 @@
+package com.icontrole.bridge.wallpad;
+
+import java.io.DataOutputStream;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class MsgClientHandler{
+	private Logger logger = LoggerFactory.getLogger(MsgClientHandler.class);
+	
+	private String clientIP;
+	private int clientPort;
+	
+	public final int SOCKET_BUFFER_SIZE = 100;
+	int SOCKET_WAIT_TIME = 3000;
+	
+	public MsgClientHandler (String clientIP, int clientPort) {
+		this.clientIP = clientIP;
+		this.clientPort = clientPort;
+	} 
+	
+	public void doWork(String xmlStr) {
+		Socket danziSocket = null;
+		
+		try {
+			danziSocket = new Socket();
+			danziSocket.setSoLinger(true, 3000);
+			danziSocket.setSendBufferSize(SOCKET_BUFFER_SIZE * 1024);
+			danziSocket.setSoTimeout(SOCKET_WAIT_TIME);
+			
+			InetSocketAddress iSocAddr = new InetSocketAddress(clientIP, clientPort);
+			danziSocket.connect(iSocAddr, SOCKET_WAIT_TIME);
+			
+			DataOutputStream outStream = new DataOutputStream(danziSocket.getOutputStream());
+			String sendMsg = xmlStr + "\r\n";
+			byte[] outBF = sendMsg.getBytes("euc-kr");
+			
+			outStream.write(outBF);
+			outStream.flush();
+			
+			logger.info("***************************************************");
+			logger.info("   S E N D    T O " + clientPort + "  C O M P L I T E ! ! ! !  ");
+			logger.info("***************************************************");
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			logger.error("***************************************************");
+			logger.error("   F A I L   T O "+ clientPort + "   S E N D   E V E N T   ! ! ! !  ");
+			logger.error("***************************************************");
+			e.printStackTrace();
+		} finally {
+			try {
+				Thread.sleep(100);
+				danziSocket.close();
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+	}
+}

+ 169 - 0
bridge/src/com/icontrole/bridge/wallpad/MsgServerHandler.java

@@ -0,0 +1,169 @@
+package com.icontrole.bridge.wallpad;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.Socket;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.icontrole.bridge.common.CommonUtil;
+import com.icontrole.bridge.dto.ServiceDetail;
+
+public class MsgServerHandler extends Thread {
+	private final Logger logger = LoggerFactory.getLogger(MsgServerHandler.class);
+	
+	private Socket clientSocket;
+	private String rcvMsgStr;								//  입력 받은 XML String
+	
+	
+	private long lSocketConnectionPeriod = 0;
+	private int TIMEOUT_iMAP_WAIT = 3000; // iMAP 타임아웃
+	private int SOCKET_BUFFER_SIZE_READ = 50;
+	
+	public MsgServerHandler (Socket clientSocket) {
+		this.clientSocket = clientSocket;
+	}
+	
+	public void run() {
+		try {
+			InputStream is = clientSocket.getInputStream();
+			clientSocket.setSoLinger(true, 3000);
+			
+			BufferedReader br = new BufferedReader(new InputStreamReader(is, "euc-kr"));
+			rcvMsgStr = "";
+			
+			StringBuffer sbRcvMSG = new StringBuffer();
+			StringBuffer sbInBuffer = null;
+			
+			boolean rcvOK = false;
+			lSocketConnectionPeriod = System.currentTimeMillis() + TIMEOUT_iMAP_WAIT;
+			
+			while(System.currentTimeMillis() < lSocketConnectionPeriod) {
+				try {
+					if(br.ready()) {
+						try {
+							char[] readData = new char[SOCKET_BUFFER_SIZE_READ * 1024];
+							sbInBuffer = new StringBuffer();
+							
+							while(br.ready()) {
+								long charCnt = br.read(readData);
+								sbInBuffer.append(new String(readData, 0, (int)charCnt));
+							}
+							
+							if(sbInBuffer != null || sbInBuffer.toString().trim().length() > 0) 
+								sbRcvMSG.append(sbInBuffer.toString());
+							
+							if(0 < sbInBuffer.toString().indexOf("</imap>")) {
+								rcvOK = true;
+								logger.info("Client Message Receive DONE!!!");
+								break;
+							}
+						}catch(Exception e) {
+							logger.error("Message Read ERROR --> " + e.getMessage());
+							return;
+						}
+					}else {
+						Thread.sleep(100);
+					} 
+				}catch(Exception e) {
+					logger.error("Message Read Error 2 ...  --> " + e.getMessage());
+					clientSocket.close();
+					return;
+				}finally {
+					rcvMsgStr = sbRcvMSG.toString();
+				}
+			}
+			
+			if(!rcvOK) {
+				logger.error("FAIL...  iMap message is unacceptable!! : \n\r " + rcvMsgStr);
+				clientSocket.close();
+				return;
+			}
+			
+			logger.info(" :: >> " + rcvMsgStr);
+			
+			rcvMsgStr = rcvMsgStr.substring(rcvMsgStr.indexOf("<")); // 이 부분에 대한 예시 데이터가 있으면 이해하기 좋을거 같다. 테스트 하면서 뽑아내고 주석으로 잘아보자.
+																	 // 내가 생각하기엔 앞에 공백이 있을 경우? 혹은 다른 문자가 있을경우를 대비하기 위함이지 않을까 생각한다.
+			// 이벤트명 가져오기
+			String eventName = "";
+			try {
+				DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();						// XML 문서를 읽기 위한 Factory 객체 생성
+				DocumentBuilder builder = factory.newDocumentBuilder();										// Builder 객체 생성
+				InputStream istream = new ByteArrayInputStream(rcvMsgStr.getBytes("UTF-8"));
+				Document doc = builder.parse(istream);
+				
+				XPath xpath = XPathFactory.newInstance().newXPath();
+				Node iMap = (Node)xpath.evaluate("//imap/service", doc, XPathConstants.NODE);
+				
+				eventName = iMap.getAttributes().getNamedItem("name").getTextContent();
+			}catch(Exception e) {
+				logger.error("[ERROR] - XML 문서 읽는도중 에러 발생 -" + e.getMessage());
+				e.printStackTrace();
+			}
+			
+			
+			// 이벤트 명이 null 이거나 공란이면 종료.
+			if(eventName == null || eventName.trim().length() == 0) return;
+
+			boolean isContainCompany = true;	// <req_company>UPLUS</req_company> Element가 있는지 확인한다.
+												// 없으면 설정파일에 등록된 모든 서비스에 이벤트를 전송하고 있으면 해당 Element에 정의된 서비스에만 전송한다.
+			
+			String topStr = "";
+			String midStr  = "";
+			String reqStr = "";
+			String bottomStr = "";
+			
+			try {
+				topStr = rcvMsgStr.substring(0, rcvMsgStr.indexOf("<req_company>"));
+				midStr = rcvMsgStr.substring(rcvMsgStr.indexOf("<req_company>"), rcvMsgStr.indexOf("</req_company>"));
+				bottomStr = rcvMsgStr.substring(rcvMsgStr.indexOf("</req_company>"));
+
+				reqStr = midStr.substring(midStr.indexOf(">")+1);
+				topStr = rcvMsgStr.substring(0, rcvMsgStr.indexOf(reqStr));
+				
+			}catch(Exception e) {
+				isContainCompany = false;	
+			}
+			
+			// 서비스 목록 가져오기
+			String str = CommonUtil.readFile(CommonUtil.getPropFileDir());
+	    	JsonObject object = CommonUtil.getJsonObject(str);
+	    	JsonArray list = (JsonArray)object.get("services");
+	    	
+	    	for(int i=0; i < list.size(); i++) {
+	    		ServiceDetail service = new Gson().fromJson(list.get(i).toString(), ServiceDetail.class);
+	    		
+	    		if(isContainCompany && !reqStr.contains(service.getName()) ) continue;	// reqCompany 엘리먼트에 해당 서비스가 등록 돼 있지 않으면 이벤트 전송 X 
+	    		
+	    		for(String tmpEvent:service.getEvents()) {
+	    			if(!eventName.equals(tmpEvent)) continue;
+	    			StringBuffer sb = new StringBuffer();
+	    			
+	    			if(isContainCompany) rcvMsgStr = sb.append(topStr).append(service.getName()).append(bottomStr).toString();
+	    			
+	    			logger.info("최종 - \r\n" + rcvMsgStr);
+	    			new MsgClientHandler(service.getAddress(), service.getPort()).doWork(rcvMsgStr);	
+	    		}
+	    	}
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			logger.error("[ERROR] -" + e.getMessage());
+		}
+	}
+}

+ 33 - 0
bridge/src/main/resources/logback.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <appender name="dailyRollingFileAppender"
+              class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <append>true</append>
+        <prudent>true</prudent>
+
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>/service/log/Bridge_Log_%d{yyyy-MM-dd}.log</fileNamePattern>
+            <maxHistory>30</maxHistory>
+        </rollingPolicy>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>DEBUG</level>
+        </filter>
+
+        <encoder>
+            <pattern>[BRIDGE] %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{35} - %msg%n</pattern>
+        </encoder>
+    </appender>
+     
+	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    	<layout class="ch.qos.logback.classic.PatternLayout">
+      		<Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
+    	</layout>
+  </appender>
+  
+    <logger name="com.icontrols.bridge" level="DEBUG"></logger>
+
+    <root level="INFO">
+        <appender-ref ref="dailyRollingFileAppender" />
+        <appender-ref ref="STDOUT" />
+    </root>
+</configuration>