Ver código fonte

소스간결화 작업

pangs 6 anos atrás
pai
commit
f9af957159

+ 5 - 4
src/main/java/com/icontrols/kakao/common/THINGS_INFO.java

@@ -1,7 +1,8 @@
 package com.icontrols.kakao.common;
 
+import java.util.Arrays;
+
 import com.icontrols.kakao.common.utils.BeanUtils;
-import com.icontrols.kakao.repo.DonghoInfoRepository;
 import com.icontrols.kakao.repo.ThingsInfoRepository;
 
 public final class THINGS_INFO {
@@ -179,9 +180,7 @@ public final class THINGS_INFO {
 	}
 	
 	public static THINGS_INFO.THINGS getThingsType(String modelId){    
-		
 		ThingsInfoRepository repo = (ThingsInfoRepository)BeanUtils.getBean("thingsInfoRepository");
-		
 		THINGS_INFO.THINGS[] list = THINGS_INFO.THINGS.values();
 		
 		for(THINGS_INFO.THINGS things:list) {
@@ -193,6 +192,8 @@ public final class THINGS_INFO {
 		return null;
 	}
 	
-	
+	public static boolean isAvailableThings(String modelId) {
+		return Arrays.asList("livinglight", "light", "temper", "ventil", "gas").contains(modelId);
+	}
 	
 }

+ 33 - 0
src/main/java/com/icontrols/kakao/common/utils/NodeUtil.java

@@ -0,0 +1,33 @@
+package com.icontrols.kakao.common.utils;
+
+import java.util.AbstractList;
+import java.util.Collections;
+import java.util.List;
+import java.util.RandomAccess;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+// xml의 NodeList를 List형태로 변경하기 위한 클래스
+public class NodeUtil {
+	
+	public static List<Node> asList(NodeList n) {
+		return n.getLength()==0?Collections.<Node>emptyList(): new NodeListWrapper(n);
+	}
+	
+	static final class NodeListWrapper extends AbstractList<Node> implements RandomAccess {
+		private final NodeList list;
+		NodeListWrapper(NodeList l) {
+		
+			list=l;
+		}
+		
+		public Node get(int index) {
+			return list.item(index);
+		}
+		
+		public int size() {
+			return list.getLength();
+		}
+	}
+}

+ 8 - 13
src/main/java/com/icontrols/kakao/socket/wallpad/KakaoEventHandler.java

@@ -139,15 +139,12 @@ public class KakaoEventHandler {
 				}else {
 					retMap.put("message", "ID-["+tmpDonghoInfo.getId() + "]-이벤트 재전송 성공");
 				}
-				
 				break;
 			case KAKAO_RESULT.SUCCESS:
 				retMap.put("result", KAKAO_RESULT.SUCCESS);
 				retMap.put("message", "ID-["+donghoInfo.getId() + "]-이벤트 전송 성공!");	
 				break;
 			}
-			
-			
 		}catch(Exception e) {
 			retMap.put("result", KAKAO_RESULT.FAIL_INTERNAL);
 			
@@ -199,9 +196,9 @@ public class KakaoEventHandler {
 			
 			String url = SERVERINFO.isDev?SERVERINFO.SendDevEventURL + ":" + SERVERINFO.SendDevEventPort + "/events":SERVERINFO.SendKakaoEventURL + ":" + SERVERINFO.SendKakaoEventPort + "/events";
 
-			logger.info("SendStatusResult URL : " + url);
-			logger.info("SendStatusResult header : " + headers.toString());
-			logger.info("SendStatusResult return value : " + params.toString());
+			logger.debug("SendStatusResult URL : " + url);
+			logger.debug("SendStatusResult header : " + headers.toString());
+			logger.debug("SendStatusResult return value : " + params.toString());
 			
 			String answer = restTemplate.postForObject(url, entity, String.class);
 			
@@ -226,7 +223,7 @@ public class KakaoEventHandler {
 				retMap.put("result", KAKAO_RESULT.SUCCESS);
 			}
 		} catch (Exception e) {
-			logger.info("SendStatusResult Exception e :" + e.toString());
+			logger.error("SendStatusResult Exception e :" + e.toString());
 			retMap.put("result", KAKAO_RESULT.FAIL_INTERNAL);
 			retMap.put("message", e.getMessage());
 		}
@@ -264,10 +261,10 @@ public class KakaoEventHandler {
 		String url = SERVERINFO.isDev?SERVERINFO.SendDevEventURL + ":" + SERVERINFO.SendDevEventPort + "/events/token":SERVERINFO.SendKakaoEventURL + ":" + SERVERINFO.SendKakaoEventPort +"/events/token";
 //		String url = "https://kakaohome-api.i.kakao.com/events/token";
 		
-		logger.info("[TOKEN REFRESH REQUEST] URL : " + url);
-		logger.info("[TOKEN REFRESH REQUEST] header : " + headers.toString());
-		logger.info("[TOKEN REFRESH REQUEST] return value : " + entity.toString());
-		logger.info("[TOKEN parameter] --" +parameters.toString());
+		logger.debug("[TOKEN REFRESH REQUEST] URL : " + url);
+		logger.debug("[TOKEN REFRESH REQUEST] header : " + headers.toString());
+		logger.debug("[TOKEN REFRESH REQUEST] return value : " + entity.toString());
+		logger.debug("[TOKEN parameter] --" +parameters.toString());
 		URI uri = URI.create(url);
 		
 		CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
@@ -296,7 +293,6 @@ public class KakaoEventHandler {
 				
 				logger.info("****************************************************");
 				logger.info("토큰 리프레시 성공");
-				logger.info(donghoInfo.toString());
 				logger.info("****************************************************");
 				return donghoInfo;
 			}
@@ -306,7 +302,6 @@ public class KakaoEventHandler {
 			e.printStackTrace();
 		}
 		
-		
 		logger.error("****************************************************");
 		logger.error("토클 리프레시 실패");
 		logger.error("****************************************************");

+ 97 - 130
src/main/java/com/icontrols/kakao/socket/wallpad/KakaoMsgHandler.java

@@ -10,6 +10,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
 
 import javax.annotation.Resource;
 import javax.xml.xpath.XPath;
@@ -45,6 +46,7 @@ import com.icontrols.kakao.common.TYPE;
 import com.icontrols.kakao.common.TYPE.XML_LIGHT;
 import com.icontrols.kakao.common.utils.BeanUtils;
 import com.icontrols.kakao.common.utils.CommonUtil;
+import com.icontrols.kakao.common.utils.NodeUtil;
 import com.icontrols.kakao.config.AsyncConfig;
 import com.icontrols.kakao.entity.DonghoInfo;
 import com.icontrols.kakao.repo.DonghoInfoRepository;
@@ -165,57 +167,60 @@ public class KakaoMsgHandler {
 			Node dCount =  null;
 	        
 			NodeList devList = (NodeList)xpath.evaluate("//imap/service/devinfo", doc, XPathConstants.NODESET);
-			for(int i=0; i < devList.getLength(); i++) {
-				Node pNode = devList.item(i);
-				
-				String tmpModelId = pNode.getAttributes().getNamedItem("name").getTextContent();
-				int childCount = Integer.parseInt(pNode.getAttributes().getNamedItem("value").getTextContent());
-				
-				// 아직 카카오에서 electric과 batchlight는 지원하지 않는다.
-				// 나중에 지원하게 되면 그때 추가하면 된다.
-				if(tmpModelId.equalsIgnoreCase("electric") || tmpModelId.equalsIgnoreCase("batchlight")) continue;
-				
-				List<Map<String, Object>> childNodeInfoList = null;
-				
-				// subdevinfo 를 가지고 있는 THINGS일 경우는 subdevinfo 들을 다시 구해야 한다.
-				// 예를들어 light는 light01 ~ 05 등의 subdevinfo를 가진다.
-				if(tmpModelId.equalsIgnoreCase("light")) {
-					for(int j=1; j <= childCount; j++) {
-						String childName = j < 10 ? tmpModelId+"0"+j : tmpModelId+j;
-						Node childNode = (Node)xpath.evaluate("//imap/service/devinfo/*[@name='"+ childName +"']", doc, XPathConstants.NODE);
-						
-						childCount = Integer.parseInt(childNode.getAttributes().getNamedItem("value").getTextContent());
-						
-						NodeList childList = (NodeList)xpath.evaluate("//imap/service/devinfo/subdevinfo/*[@name='"+ childName +"']", doc, XPathConstants.NODESET);
-						childNodeInfoList = getChildDeviceInfo(childCount, childList);
-						
-						if(childNodeInfoList != null)
-							for(Map<String, Object> tMap : childNodeInfoList) body.putAll(tMap);
-					}
-					continue;
-				}
-				// 해당 THINGS의 자식노드 status 목록들을 조회한다.
-				NodeList childList = (NodeList)xpath.evaluate("//imap/service/devinfo/*[@name='"+ tmpModelId +"']", doc, XPathConstants.NODESET);
-				
-				
-				childNodeInfoList = getChildDeviceInfo(childCount, childList);
-				
-				if(childNodeInfoList != null)
-					for(Map<String, Object> tMap : childNodeInfoList) body.putAll(tMap);
-	        }
+			
+			
+			NodeUtil.asList(devList).stream()
+									.filter(pNode -> THINGS_INFO.isAvailableThings(pNode.getAttributes().getNamedItem("name").getTextContent()))
+									.forEach(pNode -> {
+										String tmpModelId = pNode.getAttributes().getNamedItem("name").getTextContent();
+										int childCount = Integer.parseInt(pNode.getAttributes().getNamedItem("value").getTextContent());
+										
+										List<Map<String, Object>> childNodeInfoList = null;
+										NodeList childList = null;
+										
+										try {
+											// subdevinfo 를 가지고 있는 THINGS일 경우는 subdevinfo 들을 다시 구해야 한다.
+											// 예를들어 light는 light01 ~ 05 등의 subdevinfo를 가진다.
+											if(tmpModelId.equalsIgnoreCase("light")) {
+												for(int j=1; j <= childCount; j++) {
+													String childName = j < 10 ? tmpModelId+"0"+j : tmpModelId+j;
+													Node childNode = (Node)xpath.evaluate("//imap/service/devinfo/*[@name='"+ childName +"']", doc, XPathConstants.NODE);
+													
+													childCount = Integer.parseInt(childNode.getAttributes().getNamedItem("value").getTextContent());
+													
+													childList = (NodeList)xpath.evaluate("//imap/service/devinfo/subdevinfo/*[@name='"+ childName +"']", doc, XPathConstants.NODESET);
+												}
+											}else {
+												childList = (NodeList)xpath.evaluate("//imap/service/devinfo/*[@name='"+ tmpModelId +"']", doc, XPathConstants.NODESET);
+											}
+											
+											childNodeInfoList = getChildDeviceInfo(childCount, childList);
+											
+											if(childNodeInfoList != null)
+												childNodeInfoList.forEach(tMap -> { body.putAll(tMap); });
+											
+										}catch(Exception e) {
+											retMap.put(KEY_INFO.HTTP_KEY_ERROR, KAKAO_RESULT.getErrorInfo(KAKAO_RESULT.FAIL_INTERNAL));
+											logger.error("[ERROR] at stream - " + e.getMessage());
+										}
+									});
+			
+			// elevator는 하드코딩.
+			// elevator가 존재해야 카카오홈 앱에서 엘리베이터를 제어할 수 있다.
+			Map<String, Object> eleMap = new HashMap<String, Object>();
+			eleMap.put("displayType", THINGS_INFO.THINGS.ELEVATOR.getKakaoDisplayName());
+			eleMap.putAll(getDeviceCapabilities(THINGS_INFO.THINGS.ELEVATOR.getThingsName()));
+			eleMap.put("endpointId", THINGS_INFO.THINGS.ELEVATOR.getKakaoDisplayName());
+			eleMap.put("name", THINGS_INFO.THINGS.ELEVATOR.getKakaoDisplayName());
+			eleMap.put("state", new HashMap<String, Object>());
+			
+			body.put(THINGS_INFO.THINGS.ELEVATOR.getKakaoDisplayName(), eleMap);
+			
 		}catch(Exception e) {
 			retMap.put(KEY_INFO.HTTP_KEY_ERROR, KAKAO_RESULT.getErrorInfo(KAKAO_RESULT.FAIL_INTERNAL));
 			logger.error("[ERROR] - " + e.getMessage());
 		}
-		// elevator는 하드코딩.
-		Map<String, Object> eleMap = new HashMap<String, Object>();
-		eleMap.put("displayType", THINGS_INFO.THINGS.ELEVATOR.getKakaoDisplayName());
-		eleMap.putAll(getDeviceCapabilities(THINGS_INFO.THINGS.ELEVATOR.getThingsName()));
-		eleMap.put("endpointId", THINGS_INFO.THINGS.ELEVATOR.getKakaoDisplayName());
-		eleMap.put("name", THINGS_INFO.THINGS.ELEVATOR.getKakaoDisplayName());
-		eleMap.put("state", new HashMap<String, Object>());
 		
-		body.put(THINGS_INFO.THINGS.ELEVATOR.getKakaoDisplayName(), eleMap);
 		retMap.put(KEY_INFO.HTTP_KEY_UNREACHABLEIDS, unreachableIds);
 		retMap.put(KEY_INFO.HTTP_KEY_BODY, body);
 		
@@ -272,32 +277,6 @@ public class KakaoMsgHandler {
 		return getStatusMap(endpointId, doc);
 	}
 	
-	public Map<String, Object> getDeviceStatus_bak(int dong, int ho, String endpointId){
-		Map<String, Object> retMap = new HashMap<String, Object>();
-		Document doc = null;
-
-		try {
-			String[] tmpSplit = endpointId.split("_");
-			
-			String modelId = tmpSplit[0];				// 기기 ID
-			int devNum = Integer.parseInt(tmpSplit[1]);	// 회로 번호
-			
-			doc = new WallpadMsgSender().remoteDeviceStatus(dong, ho, modelId, devNum);
-			
-			if(doc == null) {
-				retMap.put(KEY_INFO.HTTP_KEY_ERROR, KAKAO_RESULT.getErrorInfo(KAKAO_RESULT.FAIL_UNREACHABLE));
-				logger.error("[ERROR]-[Document is Null] - [" + dong + "-" + ho + "] ["+ modelId +"]");
-				return retMap;
-			}
-		}catch(Exception e) { 
-			retMap.put(KEY_INFO.HTTP_KEY_ERROR, KAKAO_RESULT.getErrorInfo(KAKAO_RESULT.FAIL_NONEXIST));
-			logger.error("[ERROR]-[(" + endpointId + ") - Non Exist]");
-			return retMap;
-		}
-		
-		return getStatusMap(endpointId, doc);
-	}
-	
 	/**
 	 * 월패드에 장치 제어 명령을 보내고 결과를 리턴한다.
 	 * @param dong
@@ -451,6 +430,41 @@ public class KakaoMsgHandler {
 	 */
 	public List<Map<String, Object>> getChildDeviceInfo(int childCount, NodeList childList){
 		List<Map<String, Object>> deviceList = new ArrayList<>();
+		try {
+			NodeUtil.asList(childList).forEach(cNode -> {
+				Map<String, Object> deviceMap = new HashMap<>();
+				
+				String cNodeName = cNode.getAttributes().getNamedItem("name").getTextContent();
+				String cNodeDevNum = cNode.getAttributes().getNamedItem("dev_num").getTextContent();
+				String status = cNode.getTextContent();
+				String endpointId = cNodeName+"_"+cNodeDevNum;
+				
+				String tmpModelId = cNodeName.equals("temper")?endpointId:cNodeName;
+				
+				THINGS_INFO.DEVICE_DETAIL detailDev = THINGS_INFO.getDeviceInfo(tmpModelId);
+				
+				Map<String, Object> deviceInfo =  new HashMap<String, Object>();
+				
+				deviceInfo.put(KEY_INFO.BODY_KEY_ENDPOINT_ID, endpointId);
+	    		deviceInfo.put(KEY_INFO.BODY_KEY_NAME, detailDev.getDisplayName()+cNodeDevNum);
+	    		deviceInfo.put(KEY_INFO.BODY_KEY_DISPLAY_TYPE, detailDev.getDisplayType());
+	    		
+	    		deviceInfo.putAll(getDeviceCapabilities(endpointId));
+	    		deviceInfo.put(KEY_INFO.BODY_KEY_STATE, setDeviceState(endpointId, status));
+	    		
+	    		deviceMap.put(endpointId, deviceInfo);
+	    		
+	    		deviceList.add(deviceMap);
+			});			
+		}catch(Exception e) {
+			return null;
+		}
+		
+		return deviceList;
+	}
+	
+	public List<Map<String, Object>> getChildDeviceInfo_bak(int childCount, NodeList childList){
+		List<Map<String, Object>> deviceList = new ArrayList<>();
 		
 		for(int j=0; j < childCount; j++) {
 			Map<String, Object> deviceMap = new HashMap<>();
@@ -470,8 +484,6 @@ public class KakaoMsgHandler {
 			
 			THINGS_INFO.DEVICE_DETAIL detailDev = THINGS_INFO.getDeviceInfo(tmpModelId);
 			
-//			THINGS_INFO.THINGS things = THINGS_INFO.getThingsType(cNodeName);
-			
 			Map<String, Object> deviceInfo =  new HashMap<String, Object>();
 			
 			deviceInfo.put(KEY_INFO.BODY_KEY_ENDPOINT_ID, endpointId);
@@ -490,51 +502,52 @@ public class KakaoMsgHandler {
 	
 	/**
 	 * 디바이스의 상태 명령어를 디바이스 종류에 맞게 생성한다.
+	 * 카카오에서 던져준 capability 값부터 유효성 검사를 한 뒤에 해당 capability와 맞는 속성인지도 확인해야 한다.
 	 * @param modelId
 	 * @param desired
 	 * @return
 	 */
 	
-	public static String setDeviceActionStr(String modelId, String actionName, Map<String, Object> desired) {
+	public static String setDeviceActionStr(String modelId, String capability, Map<String, Object> desired) {
 		StringBuffer sb = new StringBuffer();
 		
 		THINGS_INFO.THINGS things = THINGS_INFO.getThingsType(modelId);
 		try {
 			switch(things.getEndPoint()) {
 			case THINGS_INFO.THINGS_LIGHT:
-				if(actionName.equals("Power") && desired.containsKey("power")) {
+				if(capability.equals("Power") && desired.containsKey("power")) {
 					String tmpState = (String)desired.get("power");
 					if(tmpState.equals("on") || tmpState.equals("off")) sb.append(tmpState);
 				}
+				
 				break;
 				
 			case THINGS_INFO.THINGS_TEMPER:
-				if(actionName.equals("Power") && desired.containsKey("power")) {
+				if(capability.equals("Power") && desired.containsKey("power")) {
 					String tmpState = (String)desired.get("power");
 					if(tmpState.equals("on") || tmpState.equals("off")) sb.append(tmpState);
 				}
 					
-				if(actionName.equals("TemperatureSetpoint") && desired.containsKey("targetSetpoint")) {
+				if(capability.equals("TemperatureSetpoint") && desired.containsKey("targetSetpoint")) {
 					double tempPoint = (double)desired.get("targetSetpoint");
 					sb.append("on/").append(Double.toString(tempPoint));
 				}
-				
 				break;
 				
 			case THINGS_INFO.THINGS_GAS:
-				if(actionName.equals("Lock") && desired.containsKey("locked")){
+				if(capability.equals("Lock") && desired.containsKey("locked")){
 					if((boolean)desired.get("locked"))
 						sb.append("close");
 				}
 				break;
 				
 			case THINGS_INFO.THINGS_VENTIL:
-				if(actionName.equals("Power") && desired.containsKey("power")) {
+				if(capability.equals("Power") && desired.containsKey("power")) {
 					String tmpState = (String)desired.get("power");
 					if(tmpState.equals("on") || tmpState.equals("off")) sb.append(tmpState);
 				}
 				
-				if(actionName.equals("AirFlow") && desired.containsKey("fanSpeed")) {
+				if(capability.equals("AirFlow") && desired.containsKey("fanSpeed")) {
 					String tmpFanSpeed = (String)desired.get("fanSpeed");
 					
 					if(tmpFanSpeed.equals("low") || tmpFanSpeed.equals("middle") || tmpFanSpeed.equals("high"))
@@ -542,13 +555,13 @@ public class KakaoMsgHandler {
 				}
 				break;
 				
-			case THINGS_INFO.THINGS_ELECPLUG:
+			case THINGS_INFO.THINGS_ELECPLUG: // 지원하지 않음
 				if(desired.containsKey("power")) sb.append(desired.get("power"));
 				else if(desired.containsKey("mode")) sb.append(desired.get("mode"));
 				break;
 				
 			case THINGS_INFO.THINGS_ELEVATOR:
-				if(actionName.equals("ElevatorCall") && desired.containsKey("callDirection")) {
+				if(capability.equals("ElevatorCall") && desired.containsKey("callDirection")) {
 					if("down".equalsIgnoreCase((String)desired.get("callDirection"))) {
 						sb.append(desired.get("callDirection"));
 					}
@@ -558,52 +571,6 @@ public class KakaoMsgHandler {
 			
 		}
 		
-		logger.info("[---->>]" + sb.toString());
-		return sb.toString();
-	}
-	
-	public static String setDeviceActionStr_bak(String modelId, Map<String, Object> desired) {
-		StringBuffer sb = new StringBuffer();
-		
-		THINGS_INFO.THINGS things = THINGS_INFO.getThingsType(modelId);
-		
-		switch(things.getEndPoint()) {
-		case THINGS_INFO.THINGS_LIGHT:
-			sb.append(desired.get("power"));
-			break;
-			
-		case THINGS_INFO.THINGS_TEMPER:
-			if(desired.containsKey("power")) sb.append(desired.get("power"));
-			else if(desired.containsKey("targetSetpoint")) sb.append("on/").append(desired.get("targetSetpoint"));
-			
-			break;
-			
-		case THINGS_INFO.THINGS_GAS:
-			if(desired.containsKey("locked")){
-				if((boolean)desired.get("locked"))
-					sb.append("close");
-			}
-			break;
-			
-		case THINGS_INFO.THINGS_VENTIL:
-			if(desired.containsKey("power")) sb.append(desired.get("power"));
-			else if(desired.containsKey("fanSpeed")) sb.append("on/").append(desired.get("fanSpeed"));
-			break;
-			
-		case THINGS_INFO.THINGS_ELECPLUG:
-			if(desired.containsKey("power")) sb.append(desired.get("power"));
-			else if(desired.containsKey("mode")) sb.append(desired.get("mode"));
-			break;
-			
-		case THINGS_INFO.THINGS_ELEVATOR:
-			if(desired.containsKey("callDirection")) {
-				if("down".equalsIgnoreCase((String)desired.get("callDirection"))) {
-					sb.append(desired.get("callDirection"));
-				}
-			}
-		}
-		
-		logger.info("[---->>]" + sb.toString());
 		return sb.toString();
 	}
 	

+ 39 - 38
src/main/java/com/icontrols/kakao/socket/wallpad/ThreadServerHandler.java

@@ -179,7 +179,7 @@ public class ThreadServerHandler extends Thread {
 			try {
 				DonghoInfoRepository repo = (DonghoInfoRepository)BeanUtils.getBean("donghoInfoRepository");
 				KakaoMsgHandler kakaoMsgHandler = (KakaoMsgHandler)BeanUtils.getBean("kakaoMsgHandler");
-				KakaoEventHandler kakaoEventHandler = null;
+				
 				// 데이터 뽑아서 이통사 연동 서버에 전달한다.
 				String model_id, status;
 				int dev_num;
@@ -217,8 +217,6 @@ public class ThreadServerHandler extends Thread {
 				logger.info("[DeviceEventMsgHandler] - status   : " + status);
 
 				String endpointId = model_id + "_" + dev_num;
-				int int_dong = Integer.parseInt(dong);
-				int int_ho = Integer.parseInt(ho);
 				
 				Map <String, Object> body = new HashMap<String, Object>();
 				
@@ -229,54 +227,57 @@ public class ThreadServerHandler extends Thread {
 					//dong ho 가  같은 유저 모두 조회
 					
 					List<DonghoInfo> dList = repo.findByDongAndHo(dong, ho);
-					kakaoEventHandler = (KakaoEventHandler)BeanUtils.getBean("kakaoEventHandler");
+					KakaoEventHandler kakaoEventHandler = (KakaoEventHandler)BeanUtils.getBean("kakaoEventHandler");
 					
 					List<CompletableFuture<Map<String, Object>>> fList = new ArrayList<>();
 					
-					for(DonghoInfo donghoInfo:dList) {
-						// 삭제된 토큰은 이벤트 전송을 하지 않는다.
-						if(donghoInfo.getDeleteFlag().equals("Y")) continue;
-						body.put(endpointId, KakaoMsgHandler.setDeviceState(endpointId, status));
-						logger.debug("body --> " + body.toString());
-						
-						Map<String, Object> sendMap = kakaoMsgHandler.setKakaoEventMsg(donghoInfo, body);
-						logger.debug("sendMap --> " + sendMap.toString());
-						
-						while(true) {
-			    			if(asyncConfig.isEventTaskExecute()) {
-			    				fList.add(kakaoEventHandler.sendEventAsync(donghoInfo, sendMap));
-			    				break;
-			    			}
-			    			Thread.sleep(1000);
-			    		}
-					}
+					dList.stream().filter(donghoInfo -> donghoInfo.getDeleteFlag().equals("N"))
+									.forEach(donghoInfo -> { 
+										try {
+											body.put(endpointId, KakaoMsgHandler.setDeviceState(endpointId, status));
+											logger.debug("body --> " + body.toString());
+											
+											Map<String, Object> sendMap = kakaoMsgHandler.setKakaoEventMsg(donghoInfo, body);
+											logger.debug("sendMap --> " + sendMap.toString());
+											
+											while(true) {
+												if(asyncConfig.isEventTaskExecute()) {
+													fList.add(kakaoEventHandler.sendEventAsync(donghoInfo, sendMap));
+													break;
+												}
+												Thread.sleep(1000);
+											}
+										}catch(Exception e) {
+											logger.error("[ERROR - ASYNC EVENT SEND] - " + e.getMessage());
+											e.printStackTrace();
+										}
+									});
 					
 					CompletableFuture.allOf(fList.toArray(new CompletableFuture[fList.size()])).join();
 					
 					// 이벤트 전송이 실패했는지 성공했는지..
-					for(CompletableFuture<Map<String, Object>> future:fList) {
-						Map<String, Object> eventResult = future.get();
-						
-						int code = (int)eventResult.get("result");
-						String message = (String)eventResult.get("message");
-						
-						if(code == KAKAO_RESULT.SUCCESS) {
-							logger.info("[EVENT SUCCESS] - " + message);
-						} else {
-							logger.error("[EVENT ERROR] - " + message);
+					fList.stream().filter(future -> future != null).forEach(future -> { 
+						try {
+							Map<String, Object> eventResult = future.get();
+							
+							int code = (int)eventResult.get("result");
+							String message = (String)eventResult.get("message");
+							
+							if(code == KAKAO_RESULT.SUCCESS) {
+								logger.info("[EVENT SUCCESS] - " + message);
+							} else {
+								logger.error("[EVENT ERROR] - " + message);
+							}							
+						}catch(Exception e) {
+							logger.error("[ERROR - future get] - " + e.getMessage());
+							e.printStackTrace();
 						}
-					}
+					});
 				}
 			} catch (Exception e) {
 				logger.error("message : " + e);
 				e.printStackTrace();
-				
 			}
 		}
-
-		private String trimquotation(String sen) {
-			sen = sen.replaceAll("\"", "");
-			return sen.trim();
-		}
 	}
 }