| 
					
				 | 
			
			
				@@ -0,0 +1,680 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+package com.icontrols.kakao.socket.wallpad; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.net.URI; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.text.SimpleDateFormat; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.ArrayList; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.Base64; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.Date; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.HashMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.List; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.Map; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.UUID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.concurrent.CompletableFuture; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import javax.annotation.Resource; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import javax.xml.xpath.XPath; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import javax.xml.xpath.XPathConstants; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import javax.xml.xpath.XPathExpressionException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import javax.xml.xpath.XPathFactory; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.apache.http.conn.ssl.NoopHostnameVerifier; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.apache.http.impl.client.CloseableHttpClient; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.apache.http.impl.client.HttpClients; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.slf4j.Logger; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.slf4j.LoggerFactory; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.beans.factory.annotation.Autowired; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.http.HttpEntity; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.http.HttpHeaders; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.http.MediaType; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.http.ResponseEntity; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.stereotype.Service; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.util.LinkedMultiValueMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.util.MultiValueMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.web.client.RestTemplate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.w3c.dom.Document; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.w3c.dom.Node; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.w3c.dom.NodeList; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.icontrols.kakao.common.ERROR_INFO; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.icontrols.kakao.common.KAKAO_RESULT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.icontrols.kakao.common.KEY_INFO; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.icontrols.kakao.common.SERVERINFO; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.icontrols.kakao.common.THINGS_INFO; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+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.config.AsyncConfig; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.icontrols.kakao.entity.DonghoInfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.icontrols.kakao.repo.DonghoInfoRepository; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.icontrols.kakao.socket.utils.IPGenerator; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.icontrols.kakao.socket.utils.SSLClient; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.icontrols.kakao.socket.utils.XMLConstants.REMOTE_KIND; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.icontrols.kakao.socket.utils.XMLGenerator; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@Service("kakaoMsgHandler") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+public class KakaoMsgHandler { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private final static Logger logger = LoggerFactory.getLogger(KakaoMsgHandler.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	@Resource(name="asyncConfig") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private AsyncConfig asyncConfig; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	@Resource(name="wallpadMsgSender") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	WallpadMsgSender wallpadMsgSender; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	@Autowired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	DonghoInfoRepository donghoRepo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private static final int REPORTSTATE_REQUEST_FIRST = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private static final int REPORTSTATE_REQUEST_RETRY = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 카카오 전용 인증 프로세스 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 월패드에 인증번호를 노출시키는 메시지를 전송한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param param 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public Map<String, Object> doAuthProcess(Map<String, Object> param){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Map<String, Object> retMap = new HashMap<String, Object>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			int dong = Integer.parseInt((String)param.get("dong")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			int ho = Integer.parseInt((String)param.get("ho")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String code = (String)param.get("code"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String targetIP = IPGenerator.getIPFromDongHo(dong, ho); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String twinid = UUID.randomUUID().toString(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String alias = "Kakao"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			StringBuffer sb = new StringBuffer(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			sb.append(XMLGenerator.MakeXMLHeaderForNotice(REMOTE_KIND.remote_register_new_device_auth_number.getContents())) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			.append("      <home_info dong=\"").append(dong).append("\" ho=\"").append(ho).append("\" ip=\"").append(targetIP).append("\" type=\"main\"/>\r\n") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			.append("      <device_info alias=\"").append(alias).append("\" twinid=\"").append(twinid).append("\" auth_number=\"" + code + "\" />\r\n") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			.append(XMLGenerator.MakeXMLTail()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			logger.info(sb.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			SSLClient.sendToWallpad(targetIP, sb.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			retMap.put("result", ERROR_INFO.CODE.SUCCESS.getContents()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			retMap.put("resultCode", ERROR_INFO.CODE.SUCCESS.getmIdx()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}catch(Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			retMap.put("result", ERROR_INFO.CODE.FAIL_999.getContents()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			retMap.put("resultCode", ERROR_INFO.CODE.FAIL_999.getmIdx()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			e.printStackTrace(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return retMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 기기 구독 / 해제 에 대한 메시지를 월패드에 전송한다.  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 기기 구독이 돼 있지 않으면 이벤트를 받지 못한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param param 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public Map<String, Object> subscriptionProcess(Map<String, Object> param) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Map<String, Object> retMap = new HashMap<String, Object>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Document doc = new WallpadMsgSender().remoteDeviceSubscription(param); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if(doc == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				logger.error("[subscriptionProcess ERROR] - Document null"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				retMap.put(KEY_INFO.HTTP_KEY_ERROR, KAKAO_RESULT.getErrorInfo(KAKAO_RESULT.FAIL_UNREACHABLE)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return retMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			retMap.put("result", "success"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}catch(Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			logger.error("[subscriptionProcess ERROR] - " + e.getStackTrace()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			retMap.put(KEY_INFO.HTTP_KEY_ERROR, KAKAO_RESULT.getErrorInfo(KAKAO_RESULT.FAIL_INTERNAL)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return retMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 월패드와 연결된 기기들의 전체 상태를 월패드에 요청하고 응답 받는다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 지원 기기가 추가되면 해당 부분은 수정이 필요하다.  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 자식 노드로 subdevinfo가 있는 기기들을 잘 확인해야 한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param dong 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param ho 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public Map<String, Object> getDevicesStatusList(int dong, int ho) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Map<String, Object> retMap = new HashMap<String, Object>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Map<String, Object> body = new HashMap<String, Object>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		List<String> unreachableIds = new ArrayList<String>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Document doc = new WallpadMsgSender().remoteDeviceStatusList(dong, ho); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			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 + "]"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return retMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			XPath xpath = XPathFactory.newInstance().newXPath(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Node iMap = (Node)xpath.evaluate("//imap/service", doc, XPathConstants.NODE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String xmlResult = iMap.getAttributes().getNamedItem("result").getTextContent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			logger.debug("[KakaoMsgHandler - getDeviceList] - xmlResult -> " + xmlResult); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if(!xmlResult.equalsIgnoreCase("ok")) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				retMap.put(KEY_INFO.HTTP_KEY_ERROR, KAKAO_RESULT.getErrorInfo(KAKAO_RESULT.FAIL_UNREACHABLE)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				logger.error("[KakaoMsgHandler - getDeviceList] xmlResult not ok"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return retMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// 월패드와 연결된 상위 THINGS 갯수 확인 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			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); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}catch(Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			retMap.put(KEY_INFO.HTTP_KEY_ERROR, KAKAO_RESULT.getErrorInfo(KAKAO_RESULT.FAIL_INTERNAL)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			logger.error("[ERROR] - " + e.getMessage()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}finally { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			retMap.put(KEY_INFO.HTTP_KEY_UNREACHABLEIDS, unreachableIds); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			retMap.put(KEY_INFO.HTTP_KEY_BODY, body); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return retMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 동 호 정보 EndpointID 로 월패드에 상태 조회 메세지를 전송하고 결과를 반환 받는다.  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param dong 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param ho 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param endpointId 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public Map<String, Object> getDeviceStatus(int dong, int ho, String endpointId){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Map<String, Object> retMap = new HashMap<String, Object>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		String[] tmpSplit = endpointId.split("_"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		String modelId = tmpSplit[0];				// 기기 ID 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		int devNum = Integer.parseInt(tmpSplit[1]);	// 회로 번호 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Document 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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return getStatusMap(endpointId, doc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 월패드에 장치 제어 명령을 보내고 결과를 리턴한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param dong 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param ho 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param endpointId 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param actionName 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param desired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public Map<String, Object> sendDeviceAction(int dong, int ho, String endpointId, String actionName, Map<String, Object> desired){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Map<String, Object> retMap = new HashMap<String, Object>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		String[] tmpSplit = endpointId.split("_"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		String modelId = tmpSplit[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		int devNum = tmpSplit.length == 1?1:Integer.parseInt(tmpSplit[1]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		THINGS_INFO.THINGS things = THINGS_INFO.getThingsType(endpointId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if(things == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			retMap.put(KEY_INFO.HTTP_KEY_ERROR, KAKAO_RESULT.getErrorInfo(KAKAO_RESULT.FAIL_INVALID_REQ)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return retMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		String action = KakaoMsgHandler.setDeviceActionStr(modelId, desired); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if(action.length() == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			retMap.put(KEY_INFO.HTTP_KEY_ERROR, KAKAO_RESULT.getErrorInfo(KAKAO_RESULT.FAIL_INVALID_REQ)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return retMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Document doc = new WallpadMsgSender().remoteDeviceControl( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+																dong,  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+																ho,  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+																modelId,  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+																devNum,  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+																action 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+															); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if(doc == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			retMap.put(KEY_INFO.HTTP_KEY_ERROR, KAKAO_RESULT.getErrorInfo(KAKAO_RESULT.FAIL_UNREACHABLE)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return retMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return getStatusMap(endpointId, doc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 상태조회 요청 메세지에 대한 응답 메세지를 파싱하여 카카오 형식으로 변환한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param endpointId 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param doc 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public static Map<String, Object> getStatusMap(String endpointId, Document doc){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Map<String, Object> retMap = new HashMap<String, Object>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		XPath xpath = XPathFactory.newInstance().newXPath(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Node iMap = (Node) xpath.evaluate("//imap/service", doc, XPathConstants.NODE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String xmlResult = iMap.getAttributes().getNamedItem("result").getTextContent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if(!xmlResult.equalsIgnoreCase("ok")) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				retMap.put(KEY_INFO.HTTP_KEY_ERROR, KAKAO_RESULT.getErrorInfo(KAKAO_RESULT.FAIL_INVALID_REQ));  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				logger.error("[ERROR]-[xmlResult is not ok"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return retMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String status = (String) xpath.evaluate("//imap/service/status", doc, XPathConstants.STRING); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Map<String, Object> state = setDeviceState(endpointId, status); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			retMap.put(endpointId, state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} catch (XPathExpressionException e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			retMap.put(KEY_INFO.HTTP_KEY_ERROR, KAKAO_RESULT.getErrorInfo(KAKAO_RESULT.FAIL_INTERNAL)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			e.printStackTrace(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return retMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 상태 변경 이벤트 발생시 이벤트 결과를 카카오 이벤트 서버에 전송한다.  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 전송시 토큰이 만료 되면 [sendKakaoTokenRefresh] method를 호출하여 토큰을 갱신한뒤 다시 재시도 한다.  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param dong 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param ho 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param params 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param reqType 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public void SendStatusResult(int dong, int ho, Map<String, Object> params, int reqType) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if(params == null) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// 먼저 이벤트 전송전 인증 토큰이 만료 됐는지 확인한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// 인증 토큰이 만료 됐으면 인증토큰을 재생성 한뒤 이벤트를 전송한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// reqType이 REPORTSTATE_REQUEST_FIRST 이면 이벤트 전송을 한번도 하지 않은 경우 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// reqType이 REPORTSTATE_REQUEST_RETRY 이면 이벤트 전송 후 인증토큰 만료 에러 때문에 인증토큰 갱신하고 재전송하는 경우 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			DonghoInfoRepository repo = (DonghoInfoRepository)BeanUtils.getBean("donghoInfoRepository"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			List<DonghoInfo> dList = repo.findByDongAndHo(Integer.toString(dong), Integer.toString(ho)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if(dList.size() != 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				logger.error("[" + dong + "/"+ ho +"]-유저정보 없음- 이벤트 전송 불가."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String tokenStartTime = dList.get(0).getKakaoTokenCreateTime(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String tokenExpiresTime = dList.get(0).getKakaoTokenExpireTime(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String currentTime = CommonUtil.getStrTypeCurTime(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			int result = CommonUtil.compareStringTypeTime(currentTime, tokenExpiresTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// 현재 시간이 토큰 만료시간보다 크다면 토큰이 만료 됐다는 뜻. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// 카카오 이벤트 서버에서 토큰을 갱신 받은 뒤 이벤트를 전송해야 한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if(result < 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				sendKakaoTokenRefresh(dong, ho, params); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String authorization = SERVERINFO.KAKAO_EVENT_CLIENT_ID+":"+SERVERINFO.KAKAO_EVENT_CLIENT_SECRET; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String encoding = Base64.getEncoder().encodeToString(authorization.getBytes()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).build(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			requestFactory.setHttpClient(httpClient); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			requestFactory.setConnectTimeout(3000); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			RestTemplate restTemplate = new RestTemplate(requestFactory); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			HttpHeaders headers = new HttpHeaders(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			headers.setContentType(MediaType.APPLICATION_JSON); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			headers.set("Authorization", "Basic " + encoding); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// 제어기기 별로 상태 이벤트 구분하여 처리하도록 해야 한다 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			HttpEntity<Object> entity = new HttpEntity<Object>(params, headers); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String url = SERVERINFO.SendDevEventURL + ":" + SERVERINFO.SendDevEventPort + "/events"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			logger.info("SendStatusResult URL : " + url); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			logger.info("SendStatusResult header : " + headers.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			logger.info("SendStatusResult return value : " + params.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String answer = restTemplate.postForObject(url, entity, String.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			logger.info("SendStatusResult answer :" + answer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// 결과에 error가 있으면 error에 맞게 대응해줘야 한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Map<String, Object> retMap = CommonUtil.jsonToMap(answer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if(retMap.containsKey(KEY_INFO.HTTP_KEY_ERROR)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				//error 결과가 -201 이면 인증토큰이 만료 됐다는 뜻 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Map<String, Object> errMap = (Map<String, Object>)retMap.get(KEY_INFO.HTTP_KEY_ERROR); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				int errorCode = Integer.parseInt((String)errMap.get(KEY_INFO.ERROR_KEY_CODE)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				String message = (String)errMap.get(KEY_INFO.ERROR_KEY_MESSAGE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				logger.info("[KAKAO - ERROR] - [ CODE ] - " + errorCode + " || [message] - " + message ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				// 인증토큰 만료 에러 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if(reqType == REPORTSTATE_REQUEST_FIRST && errorCode == KAKAO_RESULT.CODE.FAIL_EXPIREDTOKEN.getResultCode()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					// 인증토큰 갱신 요청 보내기  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					sendKakaoTokenRefresh(dong, ho, params); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				logger.info("EVENT SEND SUCCESS -- " + params.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} catch (Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			logger.info("SendStatusResult Exception e :" + e.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 이벤트 전송시 토큰이 만료되면 해당 메서드가 호출된다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 이벤트 토큰 만료시 카카오 이벤트 토큰 서버에 토큰 갱신 요청을 보낸다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 토큰이 갱신 되면 이벤트 전송을 시도한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param dong 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param ho 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param params 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public boolean sendKakaoTokenRefresh(int dong, int ho, Map<String, Object> params){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		DonghoInfoRepository repo = (DonghoInfoRepository)BeanUtils.getBean("donghoInfoRepository"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		List<DonghoInfo> dList = repo.findByDongAndHo(Integer.toString(dong), Integer.toString(ho)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if(dList.size() != 1) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		DonghoInfo donghoInfo = dList.get(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		String refreshToken = donghoInfo.getKakaoRefreshToken(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		String authorization = SERVERINFO.KAKAO_EVENT_CLIENT_ID+":"+SERVERINFO.KAKAO_EVENT_CLIENT_SECRET; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		String encoding = Base64.getEncoder().encodeToString(authorization.getBytes()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		HttpHeaders headers = new HttpHeaders(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		headers.add("Authorization", "Basic " + encoding); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		parameters.add("grant_type", "refresh_token"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		parameters.add("refresh_token", refreshToken); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(parameters, headers); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		String url = SERVERINFO.SendDevEventURL + ":" + SERVERINFO.SendDevEventPort + "/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()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		URI uri = URI.create(url); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).build(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		requestFactory.setHttpClient(httpClient); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		requestFactory.setConnectTimeout(3000); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		RestTemplate restTemplate = new RestTemplate(requestFactory); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		String answer = restTemplate.postForObject(url, entity, String.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		logger.debug("[TOKEN REFRESH REQUEST] = " + answer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Map<String, Object> retMap = CommonUtil.jsonToMap(answer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if(retMap.containsKey(KEY_INFO.HTTP_KEY_ACCESS_TOKEN) && retMap.containsKey(KEY_INFO.HTTP_KEY_REFRESH_TOKEN) && retMap.containsKey(KEY_INFO.HTTP_KEY_EXPIRES_IN)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			donghoInfo.setKakaoAccessToken((String)retMap.get(KEY_INFO.HTTP_KEY_ACCESS_TOKEN)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			donghoInfo.setKakaoRefreshToken((String)retMap.get(KEY_INFO.HTTP_KEY_REFRESH_TOKEN)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			donghoInfo.setKakaoExpiresTime(Integer.toString((int)retMap.get(KEY_INFO.HTTP_KEY_EXPIRES_IN))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			donghoInfo.setKakaoTokenCreateTime(CommonUtil.getStrTypeCurTime()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			donghoInfo.setKakaoTokenExpireTime(CommonUtil.getStrTypeCurTimeAfterSec(Integer.parseInt(donghoInfo.getKakaoExpiresTime()))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			repo.save(donghoInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			SendStatusResult(dong, ho, params, REPORTSTATE_REQUEST_FIRST); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			logger.error("****************************************************"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			logger.error("토클 리프레시 실패"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			logger.error("****************************************************"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 이벤트 발생시 카카오에 전송하는 Body를 반환한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param dong 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param ho 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param body 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @throws Exception 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public Map<String, Object> setKakaoEventMsg(int dong, int ho, Map<String, Object> body) throws Exception{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Map<String, Object> retMap = new HashMap<String, Object>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		List<String> unreachableIds = new ArrayList<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		DonghoInfoRepository repo = (DonghoInfoRepository)BeanUtils.getBean("donghoInfoRepository"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		List<DonghoInfo> dList = repo.findByDongAndHo(Integer.toString(dong), Integer.toString(ho)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if(dList.size() != 1) return null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		retMap.put(KEY_INFO.HTTP_KEY_ID, UUID.randomUUID().toString());  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		retMap.put(KEY_INFO.HTTP_KEY_TYPE, TYPE.REQ_TYPE.REPORTSTATE.getTypeName()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		retMap.put(KEY_INFO.HTTP_KEY_AUTHORIZATION, dList.get(0).getKakaoAccessToken()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		retMap.put(KEY_INFO.HTTP_KEY_VERSION, "1"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		retMap.put(KEY_INFO.HTTP_KEY_UNREACHABLEIDS, unreachableIds); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		retMap.put(KEY_INFO.HTTP_KEY_BODY, body); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return retMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 지원하는 기기들의 Capability 를 카카오 형식에 맞게 추출한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 기기가 추가되게 되면 목록을 수정해야한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param modelId 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public static Map<String, Object> getDeviceCapabilities(String modelId){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		THINGS_INFO.THINGS things = THINGS_INFO.getThingsType(modelId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		String jsonString = ""; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		switch(things.getEndPoint()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case THINGS_INFO.THINGS_LIGHT: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			jsonString = THINGS_INFO.THINGS_CAPABILITY.LIGHT.getCapJsonStr(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case THINGS_INFO.THINGS_TEMPER: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			jsonString = THINGS_INFO.THINGS_CAPABILITY.TEMPER.getCapJsonStr(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case THINGS_INFO.THINGS_GAS: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			jsonString = THINGS_INFO.THINGS_CAPABILITY.GAS.getCapJsonStr(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case THINGS_INFO.THINGS_VENTIL: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			jsonString = THINGS_INFO.THINGS_CAPABILITY.VENTIL.getCapJsonStr(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case THINGS_INFO.THINGS_ELECPLUG: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Map<String, Object> capabilities = CommonUtil.jsonToMap(jsonString); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return capabilities; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * Document에서 추출한 Device의 자식 노드들을 추출한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param childCount 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param childList 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public List<Map<String, Object>> getChildDeviceInfo(int childCount, NodeList childList){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		List<Map<String, Object>> deviceList = new ArrayList<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for(int j=0; j < childCount; j++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Map<String, Object> deviceMap = new HashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Node cNode = childList.item(j); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if(cNode == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				logger.error("cNode is null"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String cNodeName = cNode.getAttributes().getNamedItem("name").getTextContent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String cNodeDevNum = cNode.getAttributes().getNamedItem("dev_num").getTextContent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String status = cNode.getTextContent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			String endpointId = cNodeName+"_"+cNodeDevNum; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			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); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    		deviceInfo.put(KEY_INFO.BODY_KEY_NAME, cNodeName.toUpperCase() + " " + cNodeDevNum); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    		deviceInfo.put(KEY_INFO.BODY_KEY_DISPLAY_TYPE, things.getKakaoDisplayName()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    		deviceInfo.putAll(getDeviceCapabilities(endpointId)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    		deviceInfo.put(KEY_INFO.BODY_KEY_STATE, setDeviceState(endpointId, status)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    		deviceMap.put(endpointId, deviceInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    		deviceList.add(deviceMap); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return deviceList; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 디바이스의 상태 명령어를 디바이스 종류에 맞게 생성한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param modelId 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param desired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public static String setDeviceActionStr(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(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 상태조회 이후 월패드에서 받은 상태 값을 디바이스의 속성에 맞게 파싱하고  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * Map에 <"속성명", "상태값"> 형태로 담아준다.  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param modelId 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param status 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public static Map<String, Object> setDeviceState(String modelId, String status){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Map<String,Object> state = new HashMap<String, Object>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		THINGS_INFO.THINGS things = THINGS_INFO.getThingsType(modelId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		String[] splitStr = status.split("\\/"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		switch(things.getEndPoint()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case THINGS_INFO.THINGS_LIGHT: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			state.put("power", status); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case THINGS_INFO.THINGS_TEMPER: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			state.put("power", splitStr[0]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			state.put("targetSetpoint", Double.parseDouble(splitStr[1])); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			state.put("currentTemperature", Double.parseDouble(splitStr[2])); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case THINGS_INFO.THINGS_GAS: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if(status.equalsIgnoreCase("close")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				state.put("locked", true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				state.put("locked", false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case THINGS_INFO.THINGS_VENTIL: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			state.put("power", splitStr[0]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if(splitStr[0].equalsIgnoreCase("on")) state.put("fanSpeed", splitStr[1]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case THINGS_INFO.THINGS_ELEVATOR: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			state.put("callDirection", "down"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return state; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |