|
@@ -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();
|
|
|
}
|
|
|
|