이번 장에서는 X-PUSH 메시지를 수신할 클라이언트(넥사크로플랫폼17.1 애플리케이션)를 개발하는 방법을 설명합니다. X-PUSH 클라이언트는 넥사크로 애플리케이션으로 구성할 수 있습니다. 그러므로 X-PUSH 클라이언트를 개발하기 위해서는 넥사크로 애플리케이션 개발에 대한 지식이 필요합니다.
이 문서에서는 넥사크로 애플리케이션 개발에 대해 설명은 하지 않으며 X-PUSH 서버와 관련된 특이 사항만 설명합니다. 애플리케이션 개발과 관련된 상세한 내용은 넥사크로플랫폼 매뉴얼을 참조하십시오.
nexacro17.1 클라이언트 개발
X-PUSH 클라이언트는 넥사크로 애플리케이션으로 개발할 수 있습니다. 기본적으로 X-PUSH 서버를 통해 메시지를 수신하려면 X-PUSH 프로토콜 어댑터가 추가되어야 하며, 오브젝트를 통해 구성할 수 있습니다.
- X-PUSH 프로토콜 어댑터
넥사크로플랫폼에는 X-PUSH 프로토콜 어댑터가 기본 패키지에 포함되어 있습니다.
xpush 2.8 상위 버전에 대한 모든 기능은, 넥사크로 17.1부터 지원하며 넥사크로 17에서는 일부 기능이 동작하지 않습니다.
넥사크로 프로젝트에 X-PUSH 오브젝트 추가
프로젝트에 X-Push 오브젝트를 추가하려면 아래 순서를 따라갑니다.
프로젝트 익스플로러(Project explorer) 원도우에서 "TypeDefinition"-"Objects" 선택 후 마우스 오른쪽 버튼을 클릭하여 "Edit" 를 선택합니다.
+ 버튼을 눌러 Push.json 파일을 선택 후 열기를 클릭합니다.
Objects에 + 버튼을 선택하고 nexacro.XPush를 선택한 뒤 OK버튼을 클릭합니다.
추가한 X-PUSH 오브젝트가 정상적으로 등록되었는지 확인합니다.
프로토콜 어댑터 속성
다음 속성값을 변경할 수 있습니다.
속성 | 형식 | 기본값 | 설명 |
---|---|---|---|
ControlRetry | number | 5 | Command() 메소드를 호출하여 X-PUSH 서버에 커맨드를 전송할 수 있습니다. "AddF"와 "DelF" 커맨드를 요청했을 때 에러가 발생하면 지정한 값만큼 재시도합니다. |
Debug | boolean | false | 넥사크로 스튜디오 output 윈도우에 Push 메시지를 보여줄지 여부(true/false)를 결정합니다. |
IPList | string | 없음 | 하나 이상의 X-PUSH 서버를 등록합니다. 어댑터는 등록된 서버 중 무작위로 선택해서 연결을 시도합니다. 접속 시도한 서버와 연결이 되지 않으면 실패한 서버를 제외한 서버 중에서 다시 무작위로 선택하여 연결을 시도합니다 다음과 같은 형식으로 서버를 등록합니다. [X-PUSH 서버의 IP : 포트],… 예) "192.168.1.1:50001,192.168.1.2:50001" |
KeepAliveTime | number | 30 (초) | X-PUSH 서버와 연결을 유지하기 위해서는 일정 간격으로 메시지를 X-PUSH 서버에 전송해야 합니다. 그 시간 간격을 초 단위로 설정 할 수 있습니다. |
KeepTimeOut | number | 60 (초) | 연결 유지를 위해 X-PUSH 서버에 보낸 메시지의 응답을 기다리는 시간을 설정합니다. |
LayoutURL | string | 없음 | 메시지 레이아웃 정의 파일의 경로를 설정합니다. 이 속성값은 반드시 설정하셔야 합니다. 경로를 설정할 때 다음과 같은 방법을 허용합니다. • 다음과 같은 앨리어스를 사용할 수 있습니다. %System%, %ProgramFiles%, %Tobe%, %Windows% %Component%, %USERAPP% • AppGroup을 사용할 수 있습니다. 그러므로 AppGroup 의 cache 기능을 사용할 수 있습니다. {AppGroup}::file • URL을 지원합니다. protocol://host/file protocol://host:port/file protocol://file … (현재 "file", "http", "https" 프로토콜만 사용할 수 있습니다) |
projectID | string | 없음 | X-PUSH 서버와 통신할 때 사용할 프로젝트 이름을 설정합니다. |
protocolversion | number | 2 | X-PUSH 서버와 통신 시 사용할 Protocol의 버전을 설정합니다. 2.8 version 이상: 3 2.6 version 이하: 2 |
Retry | number | 레지스트리에 설정된 값 | X-PUSH 서버 연결시에 재접속 횟수를 설정합니다. 아답터는 X-PUSH 서버와 접속에 실패하면 이 값만큼 연결을 시도합니다. 설정하지 않는 경우 레지스트리에 설정된 값을 사용합니다. |
SessionID | string | 없음 | X-PUSH 서버에 연결 시 사용할 SessionID를 설정합니다. CyPushAdp.Connect() 메소드를 호출할 때 SessionID를 설정하지 않으면 속성값에 지정한 값을 사용합니다. X-PUSH 서버가 Authenticator에게 인증을 요청하면 전달하는 두 개의 값이 바로 UserID와 SessinID입니다. |
TimeOut | number | 레지스터리에 설정된 값 | X-PUSH 서버와 통신시 TimeOut 값을 설정합니다. 설정하지 않는 경우 레지스트리에 설정된 값을 사용합니다. |
UserID | string | 없음 | X-PUSH 서버에 연결 시 사용할 UserID를 설정합니다. CyPushAdp.Connect() 메소드를 호출할 때 UserID를 설정하지 않으면 지정된 속성값을 사용합니다. |
프로토콜 어댑터 이벤트 속성
xpush 어댑터로부터 발생된 이벤트를 정의할 수 있습니다.
onerror | xpush 서버에 요청된 작업이 실패했을 때 발생되는 이벤트 |
onkeepalive | xpush 서버와 연결을 유지하기 위해 일정 간격 패킷을 주고 받았을 때 발생하는 이벤트 |
onsuccess | xpush 서버에 요청된 작업이 성공했을 때 발생되는 이벤트 |
예제
기능 예제 애플리케이션
위치: %XPUSH_HOME%/sample/nexacro_client
예제 애플리케이션의 프로젝트 파일은 %XPUSH_HOME%\sample\nexacro_client\xpushSample.xadl 입니다. 이 파일을 넥사크로 스튜디오에서 오픈합니다.
넥사크로 스튜디오 메뉴에서 [File > Open > Project] 항목을 클릭합니다.
예제 프로젝트인xpushSample.xprj 파일을 선택합니다.
Project Explorer 창에서 Base 밑에 sample01_functional을 더블클릭합니다.
아래에서는 예제에서 사용한 기능 및 코드에 대해 설명합니다.
set_projectid, set_protocolversion
project_id 정보를 설정합니다.
this.XPush00.set_projectid("PRO#1");
x-push와 통신할 프로토콜 버전을 설정합니다.
this.XPush00.set_protocolversion('3');
connection
X-PUSH 서버와 접속을 합니다.
{ var value = this.IpPort.value; this.XPush00.set_iplist(value); this.XPush00.connect("user00","pw"); }
| |
sUserID | 유저 아이디 |
sPassword | 유저 패스워드 |
subscribe
X-PUSH 서버에 Topic Type 및 Topic Id 등록합니다.
{ var ret = this.XPush00.subscribe(this.topicTYPE.value, this.topicID.value, this, this.dsMessage, "append", "fn_PushCallback_Test_Data"); } /* * 콜백 함수( 메시지 수신 ) */ this.fn_PushCallback_Test_Data = function (Row, ChangeColumn, AllColumns, Type, ActionType, MessageId) { trace("fn_PushCallback - NOTI\n" + " - ActionType : " + ActionType + "\n" + " - Row : " + Row + "\n" + " - MessageId : " + MessageId + "\n" ); trace(this.dsMessage.saveXML() ); /* * 일반 메시지 수신 */ if (ActionType == "PUSH") { trace(this.dsMessage.getColumn(0, "NOTI_00")); trace(this.dsMessage.getColumn(0, "NOTI_01")); trace(this.dsMessage.getColumn(Row, "NOTI_02")); trace(this.dsMessage.getColumn(Row, "NOTI_03")); } /* * 신뢰성 메시지 수신 */ if (ActionType == "RELI") { trace(this.dsMessage.getColumn(0, "NOTI_00")); trace(this.dsMessage.getColumn(0, "NOTI_01")); trace(this.dsMessage.getColumn(0, "NOTI_22")); } }
| |
sMessageType | Topic Type |
sMessageId | Topic Id |
this | 현재 form |
this.dsOperation | DataSet |
"update" | 수신한 메시지를 데이터셋에 반영하는 방식 |
"fn_PushCallback_Test_Data" | 콜백 함수 X-PUSH 메시지 수신 ActionType으로 일반메시지(PUSH), 신뢰성 메시지(RELI) 구분 |
미수신 메시지 개수 조회
X-PUSH 서버에 미수신 메시지 개수를 요청합니다.
this.btnReqd_onclick = function(obj:Button, e:nexacro.ClickEventInfo)
{
this.XPush00.requestMessageCount("NOTI", "ALL");
}
| |
"NOTI" | Topic Type |
"ALL" | Topic Id |
성공 실패 | 성공 : onsuccess 에서 확인 (action==10) 실패: onerror 에서 확인(action==10) |
미수신 메시지 요청
X-PUSH 서버에 미수신 메시지를 요청합니다.
this.btnReqd_onclick = function(obj:Button, e:nexacro.ClickEventInfo)
{
this.XPush00.requestMessage("NOTI", "ALL");
}
| |
"NOTI" | Topic Type |
"ALL" | Topic Id |
성공 실패 | 성공 : onsuccess 에서 확인 (reason == 6) 실패 : onerror 에서 확인(errorcode == -902) |
수신 확인 메시지 전송
X-PUSH 서버로부터 신뢰성 메시지를 받으면 수신확인 메시지를 X-PUSH 에 전송합니다.
this.fn_PushCallback_Test_Data = function(Row, ChangeColumn, AllColumn, Type, ActionType, MessageId)
{
AddLog("get push data. reliable message = " + "[ActionType:" + ActionType + "] " + this.dsMessage.getColumn(0, "Title"));
if (ActionType == "RELI") {
alert(this.dsMessage.getColumn(0, "Title"));
this.XPush00.sendResponse(MessageId);
}
}
| |
MessageId | 수신한 신뢰성 메시지의 ID |
성공 실패 | 성공 : onsuccess 에서 확인 (reason == 5) 실패 : onerror 에서 확인(errorcode == -901) |
유저 등록
데이터베이스에 유저정보(T_TOPIC Table)를 추가한다. 인증(AUTH)을 한 다음에 유저 등록(ADUI)를 해야합니다.
this.XPush00.registerTopic("NOTI", "ALL");
this.XPush00.registerTopic("NOTI", "ALL"); | |
"NOTI" | Topic Type |
"ALL" | Topic Id |
성공 실패 | 성공 : onsuccess 에서 확인 (action == 8) 실패 : onerror 에서 확인(action == 8) |
유저 삭제
데이터베이스에 유저정보(T_TOPIC Table)를 삭제합니다.
this.XPush00.unregisterTopic("NOTI", "ALL");
this.XPush00.unregisterTopic("NOTI", "ALL"); | |
"NOTI" | Topic Type |
"ALL" | Topic Id |
성공 실패 | 성공 : onsuccess 에서 확인 (action == 9) 실패 : onerror 에서 확인(action == 9) |
성공/실패 이벤트 처리
onerror
this.XPush00_onerror = function(obj:XPush, e:XPushErrorEventInfo) { this.fn_setMsg("XPush00_onerror Event\n" + " - eventid: " + e.eventid + "\n" + " - action: " + e.action + "\n" + " - statuscode: " + e.statuscode + "\n" + " - errormsg: " + e.errormsg + "\n" + " - serverip: " + e.serverip + "\n" + " - serverport: " + e.serverport + "\n" + " - e.message: " + e.message + "\n" + " - e.command : " + e.command ); if (e.command != null) { this.fn_setMsg("e.command != null\n" + " - e.command.check : " + e.command.check + "\n" + " - e.command.row : " + e.command.row + "\n" + " - e.command.type : " + e.command.type + "\n" + " - e.command.useactiveformcallback : " + e.command.useactiveformcallback + "\n" + " - e.command.actiontype : " + e.command.actiontype + "\n" + " - e.command.callback : " + e.command.callback + "\n" + " - e.command.messagekey : " + e.command.messagekey + "\n" + " - e.command.messagetype : " + e.command.messagetype + "\n" + " - e.command.objdataset : " + e.command.objdataset + "\n" + " - e.command.objform : " + e.command.objform); } if (e.message != null) { this.fn_setMsg("e.message != null\n" + " - e.message.messagetype: " + e.message.messagetype + "\n" + " - e.message.messagekey: " + e.message.messagekey + "\n" + " - e.message.messageid: " + e.message.messageid + "\n" + " - e.message.devicetoken: " + e.message.devicetoken); } this.fn_setMsg("e.returnvalue : " + e.returnvalue); }
| |
e.action | XPushAction.AUTH (0) - connect() XPushAction.BYEC (1) - disconnect() XPushAction.ADDF (2) - subscribe() XPushAction.DELF (3) - unsubscribe() XPushAction.REQD (4) - requestMessage() XPushAction.RECT (5) - sendResponse() XPushAction.RGST (6) - reqisterDevice() XPushAction.UNRG (7) - unreqisterDevice() XPushAction.ADUI (8) - reqisterUser() XPushAction.UNUI (9) - unreqisterUser() XPushAction.MSGC (10) - requestMessageCount() |
e.statuscode | -100 - Push 서버가 “Byec”를 보냈거나 서버와의 규약에 따라 종료되었습니다. -101 - 타임아웃 처리되었습니다. -200 - Command Auth Error. 현재 선택된 IP에 대해인증에 오류가 발생하였습니다. -201 - iplist 속성에 등록되어 있는 Push 서버로의 접속이 모두 실패했습니다. -202 - 데이터 전송 채널 인증(authentication)에 오류가 발생하였습니다. -300 - 서버로의 접속에 실패했습니다. -301 - 패킷 전송(send/recv) 오류가 발생하였습니다. -401 - X-PUSH 서버와 접속해제(disconnect) 요청을 실패했습니다. -501 - X-PUSH 서버로부터 메시지 수신중단(suspend) 요청을 실패했습니다. -601 - X-PUSH 서버로부터 메시지 수신 재시작(resume) 요청을 실패했습니다. -701 - X-PUSH 서버로 topic 등록/등록해제 요청을 실패했습니다. -801 - 메시지 포맷 버전 정보가 일치하지 않습니다. -901 - 신뢰성 메시지에 대한 수신응답 전송에 실패했습니다. -902 - 미수신 메시지 요청을 실패했습니다. -1001 - X-PUSH 서버로 모바일 DeviceToken 정보 등록요청을 실패했습니다. -1002 - X-PUSH 서버로 유저 topic 정보 등록요청(reqisterUser)이 실패했습니다. -1003 - X-PUSH 서버로 유저 topic 정보 등록해제(unregisterUser)요청이 실패했습니다. -1004 - 미수신 메시지 정보요청을 실패했습니다. -1072 - 디바이스 등록(RGST)시 중복된 경우 발생합니다. -1092 - 메시지 토픽 등록(ADUI)시 중복된 경우 발생합니다. |
onsuccess
this.XPush00_onsuccess = function(obj:XPush, e:XPushEventInfo) { alert("XPush00_onsuccess Event\n" + " - eventid: " + e.eventid + "\n" + " - statuscode: " + e.statuscode + "\n" + " - errormsg: " + e.errormsg + "\n" + " - reason: " + e.reason + "\n" + " - action: " + e.action + "\n" + " - serverip: " + e.serverip + "\n" + " - serverport: " + e.serverport + "\n" + " - e.message: " + e.message + "\n" + " - e.command : " + e.command + "\n" + " - e.returnvalue : " + e.returnvalue); if (e.command != null) { alert("e.command != null\n" + " - e.command.check : " + e.command.check + "\n" + " - e.command.row : " + e.command.row + "\n" + " - e.command.type : " + e.command.type + "\n" + " - e.command.useactiveformcallback : " + e.command.useactiveformcallback + "\n" + " - e.command.actiontype : " + e.command.actiontype + "\n" + " - e.command.callback : " + e.command.callback + "\n" + " - e.command.messagekey : " + e.command.messagekey + "\n" + " - e.command.messagetype : " + e.command.messagetype + "\n" + " - e.command.objdataset : " + e.command.objdataset + "\n" + " - e.command.objform : " + e.command.objform); } if (e.message != null) { alert("e.message != null\n" + " - e.message.messagetype: " + e.message.messagetype + "\n" + " - e.message.messagekey: " + e.message.messagekey + "\n" + " - e.message.messageid: " + e.message.messageid + "\n" + " - e.message.returnvalue: " + e.message.returnvalue + "\n" + " - e.message.devicetoken: " + e.message.devicetoken); if(e.message.returnvalue != undefined || e.message.returnvalue != null) { var returnvalue = e.message.returnvalue; for(var i = 0; i < returnvalue.length; i++) { alert("index:" + i + " : " + returnvalue[i].topictype + " : " + returnvalue[i].topicid + " : " + returnvalue[i].count); } } } }
| |
e.action | XPushAction.AUTH (0) - connect() XPushAction.BYEC (1) - disconnect() XPushAction.ADDF (2) - subscribe() XPushAction.DELF (3) - unsubscribe() XPushAction.REQD (4) - requestMessage() XPushAction.RECT (5) - sendResponse() XPushAction.RGST (6) - registerDevice() XPushAction.UNRG (7) - unregisterDevice() XPushAction.ADUI (8) - registerTopic() XPushAction.UNUI (9) - unregisterTopic() XPushAction.MSGC (10) - requestMessageCount() |