본문으로 건너뛰기

4.3 OneM2M Platform 데이터 연계

  1. 수집관리UI(http://localhost:8080/) 의 Agent 관리 > Agent 설정 메뉴에서 ingest-web_add_new_btn을 클릭합니다.

onem2m_agent_registration 저장 후에는 Adaptor 추가 등록 / 변경 을 할 수 있습니다.

  • Agent ID: 'M000000004'을 입력합니다.(10자내 입력)
  • Agent 명: '레가시 테스트oneM2M 성남시 주차장예시'을 입력합니다.
  • 사용여부: '사용'을 선택합니다.
  • 각 항목을 작성한 후 저장버튼을 클릭합니다.
  1. Agent설정화면에서 저장 후 Adaptor 추가 등록/변경화면에서 ingest-web_add_new_btn2을 클릭합니다. onem2m_adaptor_registration
  • Adaptor ID : 'pocOffStreetParking' 를 입력합니다.
  • Adaptor 명 : 'oneM2M 성남시 주차장예시' 을 입력합니다.
  • Platform 유형 : 'OneM2M' 선택합니다.
  • 각 항목을 작성한 후 저장버튼을 클릭합니다. onem2m_adaptor_list아답터_등록 후 화면 목록에서 Adaptor IDpocOffStreetParking을 클릭 하면 Instance 관리 화면으로 이동합니다.
  1. Instance 관리 화면에서 ingest-web_add_new_btn2 클릭합니다. onem2m_instance_registration
  • 인스턴스명: 'oneM2M 성남시 주차장예시'를 입력합니다.
  • 데이터모델 변환: '변환'을 선택합니다. 변환은 Web 에서 직접 코딩을 하여 데이터를 컨버팅 합니다. 미변환은 기 제공된 Java Class 를 이용합니다. 등록 예시는 [4번 지시사항]에 있습니다.
  • Adpator 유형: '성남시 주차장'을 선택합니다. Adaptor 유형 관리 메뉴에서 등록된 유형을 선택할 수 있습니다. 유형을 선택하면 인스턴스 상세 항목이 표시됩니다.
  • 사용여부: '사용'을 선택합니다.
  • 각 항목을 작성한 후 저장버튼을 클릭합니다.

onem2m_instance_mandatory_information 인스턴스 등록 필수 정보

  • DATASET_ID: 'pocOffStreetParking,pocParkingSpot'를 입력합니다. City Data Hub 시스템에서 정의한 데이터셋 아이디를 입력합니다. 성남시 주차장의 경우 주차장(OffStreetParking),주차면(ParkingSpot) 정보가 넘어옵니다. 해서 콤마(,)를 기준으로 복수의 데이터셋을 등록합니다.
  • MODEL_ID: 'OffStreetParking,ParkingSpot'를 입력합니다. City Data Hub 시스템에서 정의한 모델 아이디를 입력합니다. 성남시 주차장의 경우 주차장(OffStreetParking),주차면(ParkingSpot) 정보가 넘어옵니다. 해서 콤마(,)를 기준으로 복수의 모델ID을 등록합니다.
  • INVOKE_CLASS: 'com.cityhub.adapter.convex.ConvParkingOneM2M'를 입력합니다. 기 제공된 클래스 파일이며 여기서는 데이터모델 변환관리를 이용합니다.
  • URL_ADDR: tcp://203.253.128.164:1883 를 입력합니다. mqtt프로토콜의 연결주소입니다.
  • REQ_PREFIX: /oneM2M/req/Mobius2/를 입력합니다. 성남시 주차장의 mqtt프로토콜의 요청접두사입니다.
  • RESP_PREFIX: /oneM2M/resp/Mobius2/를 입력합니다. 성남시 주차장의 mqtt프로토콜의 응답접두사입니다.
  • TOPIC: SlotYatopParking를 입력합니다. 성남시 주차장의 mqtt프로토콜의 토픽입니다.
  • META_INFO: http://203.253.128.164:7579/Mobius/sync_parking_raw를 입력합니다. 성남시 주차장의 메타정보 확인을 위한 주소입니다.
  1. oneM2M 성남시 주차장예시 인스턴스를 저장합니다. onem2m_instance_registration2 인스턴스를 저장 후에 데이터모델 변환관리를 클릭하여 데이터 모델을 직접 작성합니다. 데이터변환모델을 작성 한 후 컴파일 확인까지 정상 처리 되었으면 닫기를 클릭하여 변환관리 화면을 빠져 나옵니다. 인스턴스 ID 인 'pocOffStreetParking_001'을 클릭하여 ingest-web_apply_btn 클릭하여 설정을 적용합니다.

onem2m_data_conversion 성남시 주차장 샘플 전문입니다.

  @Override
public void setup() {
Map<String, String> headers = new HashMap<>();
headers.put(HttpHeaders.ACCEPT, "application/json");
headers.put("X-M2M-Origin", "SW001");
headers.put("X-M2M-RI", "cityhub");
try {
String u = ConfItem.getString("metaInfo");
HttpResponse discovery = OkUrlUtil.get(u + "?fu=1&ty=3", headers);
if (discovery.getStatusCode() == 200) {
JSONObject dis = new JSONObject(discovery.getPayload());
for (Object obj : dis.getJSONArray("m2m:uril")) {
String sp = (String) obj;
String[] args = sp.split("/", -1);
if (args.length == 3) {
String url = u + "/" + args[2] + "/meta/la";
HttpResponse info = OkUrlUtil.get(url, headers);
if (info.getStatusCode() == 200) {
JsonUtil ju = new JsonUtil(info.getPayload());
if (ju.has("m2m:cin.con")) {
JSONObject jObj = ju.getObject("m2m:cin.con");
ConfItem.put(args[2], jObj);
}
}
}
}
log.info("parkinfo:{}", objectMapper.writeValueAsString(ConfItem));
}

} catch (Exception e) {
log.error("Exception : " + ExceptionUtils.getStackTrace(e));
}
}


@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public String doit(byte[] message) {
List<Map<String, Object>> rtnList = new LinkedList<>();
String rtnStr = "";
String modelType = "";
try {
String msg = new String(message);
// 소스코드 첨가부분 - 시작
// 예제 부분이며 시작-종료 까지 내용을 제거 한 후 표준 모델에 맞게 구현

if (JsonUtil.has(msg, "pc.m2m:sgn.nev.rep.m2m:cin.con") == true) {
String sur = JsonUtil.get(msg, "pc.m2m:sgn.sur");
String contents = JsonUtil.get(msg, "pc.m2m:sgn.nev.rep.m2m:cin.con");
String[] Park = sur.split("/", -1);
if (Park.length == 4) {
JsonUtil parkInfo = null;
try {
parkInfo = new JsonUtil(ConfItem.getJSONObject(Park[2]));
} catch (JSONException e) {
log.info("OffStreeting:{}", Park[2]);
parkInfo = new JsonUtil(ConfItem.getJSONObject("yt_lot_1"));
}

Map<String, Object> tMap = objectMapper.readValue(templateItem.getJSONObject("OffStreetParking").toString(), new TypeReference<Map<String, Object>>() {
});
modelType = tMap.get("type").toString();
id = "urn:datahub:" + tMap.get("type") + ":" + Park[2];
toLogger(SocketCode.DATA_RECEIVE, id, parkInfo.toString().getBytes());

Map<String, Object> address = new LinkedHashMap<>();
address.put("type", "Property");
address.put("observedAt", DateUtil.getTime());
address.put("value", JsonUtil.nvl(parkInfo.getObject("address").toMap()));
tMap.put("address", address);

Map<String, Object> locMap = (Map) tMap.get("location");
Map<String, Object> locValueMap = (Map) locMap.get("value");
locValueMap.put("coordinates", parkInfo.getArray("location.coordinates").toList());

tMap.put("id", "urn:datahub:" + tMap.get("type") + ":" + Park[2]);

((Map) tMap.get("locationTag")).put("value", JsonUtil.nvl(parkInfo.get("locationTag")));
((Map) tMap.get("category")).put("value", parkInfo.getArray("category").toList());
((Map) tMap.get("paymentAccepted")).put("value", parkInfo.getArray("paymentAccepted").toList());
((Map) tMap.get("priceRate")).put("value", JsonUtil.nvl(parkInfo.get("priceRate"), DataType.STRING));
((Map) tMap.get("priceCurrency")).put("value", parkInfo.getArray("priceCurrency").toList());
((Map) tMap.get("image")).put("value", parkInfo.get("image"));
((Map) tMap.get("totalSpotNumber")).put("value", JsonUtil.nvl(parkInfo.get("totalSpotNumber"), DataType.INTEGER));
((Map) tMap.get("maximumAllowedHeight")).put("value", JsonUtil.nvl(parkInfo.get("maximumAllowedHeight"), DataType.FLOAT));
((Map) tMap.get("openingHours")).put("value", parkInfo.getArray("openingHours").toList());
((Map) tMap.get("contactPoint")).put("value", JsonUtil.nvl(parkInfo.getObject("contactPoint").toMap()));
((Map) tMap.get("status")).put("value", parkInfo.getArray("status").toList());
((Map) tMap.get("name")).put("value", parkInfo.get("name"));

if (ConfItem.has(Park[2])) {
((Map) tMap.get("refParkingSpots")).put("value", parkInfo.getArray("refParkingSpots").toList());
}

((Map) tMap.get("availableSpotNumber")).put("value", JsonUtil.nvl(contents, DataType.INTEGER));
((Map) tMap.get("availableSpotNumber")).put("observedAt", DateUtil.getTime());

tMap.remove("inAccident");
tMap.remove("category");
tMap.remove("congestionIndexPrediction");
tMap.remove("predictions");

rtnList.add(tMap);
String str = objectMapper.writeValueAsString(tMap);
toLogger(SocketCode.DATA_CONVERT_SUCCESS, id, str.getBytes());

toLogger(SocketCode.DATA_SAVE_REQ, id, str.getBytes());

} else {
if (!"meta".equals(Park[3]) && !"keepalive".equals(Park[3])) {
JsonUtil parkInfo = null;
try {
parkInfo = new JsonUtil(ConfItem.getJSONObject(Park[2]));
} catch (JSONException e) {
log.info("OffStreeting:{}", Park[2]);
parkInfo = new JsonUtil(ConfItem.getJSONObject("yt_lot_1"));
}

Map<String, Object> tMap = objectMapper.readValue(templateItem.getJSONObject("ParkingSpot").toString(), new TypeReference<Map<String, Object>>() {
});
id = "urn:datahub:" + tMap.get("type") + ":" + Park[3];
modelType = tMap.get("type").toString();
toLogger(SocketCode.DATA_RECEIVE, id, parkInfo.toString().getBytes());

Map<String, Object> address = new LinkedHashMap<>();
address.put("type", "Property");
address.put("value", JsonUtil.nvl(parkInfo.getObject("address").toMap()));
tMap.put("address", address);

Map<String, Object> locMap = (Map) tMap.get("location");
Map<String, Object> locValueMap = (Map) locMap.get("value");
locValueMap.put("coordinates", parkInfo.getArray("location.coordinates").toList());

tMap.put("id", "urn:datahub:" + tMap.get("type") + ":" + Park[3]);

((Map) tMap.get("length")).put("value", 5.1);
((Map) tMap.get("width")).put("value", 2.5);
List category = new LinkedList();
category.add("forDisabled");
((Map) tMap.get("category")).put("value", category);
((Map) tMap.get("refParkingLot")).put("value", "urn:datahub:OffStreetParking:" + Park[2]);
((Map) tMap.get("name")).put("value", JsonUtil.nvl(Park[3]));

((Map) tMap.get("status")).put("value", JsonUtil.nvl(contents));
((Map) tMap.get("status")).put("observedAt", DateUtil.getTime());

tMap.remove("refParkingLot");

rtnList.add(tMap);
String str = objectMapper.writeValueAsString(tMap);
toLogger(SocketCode.DATA_CONVERT_SUCCESS, id, str.getBytes());
toLogger(SocketCode.DATA_SAVE_REQ, id, str.getBytes());

} // if (!"meta".equals(Park[3]) && !"keepalive".equals(Park[3]) )

} // if (Park.length == 4)

// 변환 완료된 데이터 주차면 모델 전송
String[] ArrModel = StrUtil.strToArray(ConfItem.getString("modelId"), ",");
String[] ArrDatasetId = StrUtil.strToArray(ConfItem.getString("datasetId"), ",");
for (int i = 0; i &gt; ArrModel.length; i++) {
if (ArrModel[i].equals(modelType)) {
sendEvent(modelList, ArrDatasetId[i]);
}
}

} // if ( JsonUtil.has(msg, "pc.m2m:sgn.nev.rep.m2m:cin.con") == true)
// 소스코드 첨가부분 - 종료

} catch (CoreException e) {
log.error("Exception : " + ExceptionUtils.getStackTrace(e));
if ("!C0099".equals(e.getErrorCode())) {
toLogger(SocketCode.DATA_CONVERT_FAIL, id, e.getMessage());
}
} catch (Exception e) {
toLogger(SocketCode.DATA_CONVERT_FAIL, id, e.getMessage());
log.error("Exception : " + ExceptionUtils.getStackTrace(e));
}
return "Success";
}

변환 클래스 부분에서 위에 해당하는 영역에 DB에서 읽어온 데이터를 표준 모델에 맞게 코딩을 합니다. 작성 완료 후 컴파일 확인 을 클릭하여 컴파일 결과를 하단 회색 박스에서 확인합니다.

  1. Agent관리 > Agent 운영 메뉴에서 Agent ID -> M000000003 을 클릭합니다. 해당 아답터의 시작/종료 ,모니터링이 가능합니다.