private void ParsePacket(IPacket pk) { switch ((Cmd)pk.Cmd) { case Cmd.A_DotData: { long time = pk.GetByteToInt(); int x = pk.GetShort(); int y = pk.GetShort(); int fx = pk.GetByteToInt(); int fy = pk.GetByteToInt(); int force = pk.GetByteToInt(); long timeLong = mPrevDotTime + time; Dot.Builder builder = new Dot.Builder(MaxForce); builder.owner(mOwnerId) .section(mSectionId) .note(mNoteId) .page(mPageId) .timestamp(timeLong) .coord(x, fx, y, fy) .force(force) .color(mCurrentColor); if (!IsStartWithDown) { if (!IsStartWithPaperInfo) { //펜 다운 없이 페이퍼 정보 없고 무브가 오는 현상(다운 - 무브 - 업 - 다운X - 무브) Callback.onErrorDetected(this, ErrorType.MissingPenDown, -1, null, null); } else { //펜 다운 없이 페이퍼 정보 있고 무브가 오는 현상(다운 - 무브 - 업 - 다운X - 무브) builder.dotType(DotTypes.PEN_ERROR); var errorDot = builder.Build(); Callback.onErrorDetected(this, ErrorType.MissingPenDown, -1, errorDot, null); IsStartWithDown = true; builder.timestamp(Time.GetUtcTimeStamp()); } } if (!IsStartWithDown) { if (!IsStartWithPaperInfo) { //펜 다운 없이 페이퍼 정보 없고 무브가 오는 현상(다운 - 무브 - 업 - 다운X - 무브) Callback.onErrorDetected(this, ErrorType.MissingPenDown, -1, null, null); } else { timeLong = Time.GetUtcTimeStamp(); PenDownTime = timeLong; //펜 다운 없이 페이퍼 정보 있고 무브가 오는 현상(다운 - 무브 - 업 - 다운X - 무브) builder.dotType(DotTypes.PEN_ERROR); var errorDot = builder.Build(); Callback.onErrorDetected(this, ErrorType.MissingPenDown, PenDownTime, errorDot, null); IsStartWithDown = true; builder.timestamp(timeLong); } } if (timeLong < 10000) { // 타임스템프가 10000보다 작을 경우 도트 필터링 builder.dotType(DotTypes.PEN_ERROR); var errorDot = builder.Build(); Callback.onErrorDetected(this, ErrorType.InvalidTime, PenDownTime, errorDot, null); } Dot dot = null; if (IsStartWithDown && IsStartWithPaperInfo && IsBeforePaperInfo) { // 펜다운의 경우 시작 도트로 저장 dot = builder.timestamp(PenDownTime).dotType(DotTypes.PEN_DOWN).Build(); } else if (IsStartWithDown && IsStartWithPaperInfo && !IsBeforePaperInfo && IsBeforeMiddle) { // 펜다운이 아닌 경우 미들 도트로 저장 dot = builder.dotType(DotTypes.PEN_MOVE).Build(); } else if (IsStartWithDown && !IsStartWithPaperInfo) { //펜 다운 이후 페이지 체인지 없이 도트가 들어왔을 경우 Callback.onErrorDetected(this, ErrorType.MissingPageChange, PenDownTime, null, null); } if (dot != null) { ProcessDot(dot); } mPrevDot = dot; mPrevDotTime = timeLong; IsBeforeMiddle = true; IsBeforePaperInfo = false; } break; case Cmd.A_DotUpDownDataNew: case Cmd.A_DotUpDownData: { long updownTime = pk.GetLong(); int updown = pk.GetByteToInt(); byte[] cbyte = pk.GetBytes(3); mCurrentColor = ByteConverter.ByteToInt(new byte[] { cbyte[2], cbyte[1], cbyte[0], (byte)0xFF }); if (updown == 0x00) { // 펜 다운 일 경우 Start Dot의 timestamp 설정 mPrevDotTime = updownTime; //IsPrevDotDown = true; if (IsBeforeMiddle && mPrevDot != null) { // 펜업이 넘어오지 않는 경우 //var errorDot = mPrevDot.Clone(); //errorDot.DotType = DotTypes.PEN_ERROR; //Callback.onErrorDetected(this, ErrorType.MissingPenUp, PenDownTime, errorDot, null); MakeUpDot(); } IsStartWithDown = true; PenDownTime = updownTime; //Callback.onUpDown( this, false ); } else if (updown == 0x01) { mPrevDotTime = -1; if (IsStartWithDown && IsBeforeMiddle && mPrevDot != null) { MakeUpDot(false); } else if (!IsStartWithDown && !IsBeforeMiddle) { Callback.onErrorDetected(this, ErrorType.MissingPenDownPenMove, PenDownTime, null, null); } else if (!IsBeforeMiddle) { // 무브없이 다운-업만 들어올 경우 UP dot을 보내지 않음 Callback.onErrorDetected(this, ErrorType.MissingPenMove, PenDownTime, null, null); } IsStartWithDown = false; PenDownTime = -1; } IsBeforeMiddle = false; IsStartWithPaperInfo = false; mPrevDot = null; } break; case Cmd.A_DotIDChange: if (IsStartWithDown && IsBeforeMiddle && mPrevDot != null) { MakeUpDot(false); } byte[] rb = pk.GetBytes(4); mSectionId = (int)(rb[3] & 0xFF); mOwnerId = ByteConverter.ByteToInt(new byte[] { rb[0], rb[1], rb[2], (byte)0x00 }); mNoteId = pk.GetInt(); mPageId = pk.GetInt(); //IsPrevDotDown = true; IsBeforePaperInfo = true; IsStartWithPaperInfo = true; break; case Cmd.A_PenOnState: pk.Move(8); int STATUS = pk.GetByteToInt(); int FORCE_MAX = pk.GetByteToInt(); MaxForce = (short)FORCE_MAX; string SW_VER = pk.GetString(5); if (STATUS == 0x00) { SendPenOnOffData(); Clean(); } else if (STATUS == 0x01) { Reset(); SendPenOnOffData(); SendRTCData(); needToInputDefaultPassword = true; mOfflineworker.PenMaxForce = FORCE_MAX; Callback.onConnected(this, FORCE_MAX, SW_VER); } break; case Cmd.A_RTCsetResponse: break; case Cmd.A_PenStatusResponse: if (!Authenticated) { Authenticated = true; needToInputDefaultPassword = false; Callback.onPenAuthenticated(this); } pk.Move(2); int stat_timezone = pk.GetInt(); long stat_timetick = pk.GetLong(); int stat_forcemax = pk.GetByteToInt(); int stat_battery = pk.GetByteToInt(); int stat_usedmem = pk.GetByteToInt(); int stat_pencolor = pk.GetInt(); bool stat_autopower = pk.GetByteToInt() == 2 ? false : true; bool stat_accel = pk.GetByteToInt() == 2 ? false : true; bool stat_hovermode = pk.GetByteToInt() == 2 ? false : true; bool stat_beep = pk.GetByteToInt() == 2 ? false : true; short stat_autoshutdowntime = pk.GetShort(); short stat_pensensitivity = pk.GetShort(); string model_name = string.Empty; if (pk.CheckMoreData()) { int model_name_length = pk.GetByte(); model_name = pk.GetString(model_name_length); } Callback.onReceivedPenStatus(this, stat_timezone, stat_timetick, stat_forcemax, stat_battery, stat_usedmem, stat_pencolor, stat_autopower, stat_accel, stat_hovermode, stat_beep, stat_autoshutdowntime, stat_pensensitivity, model_name); break; // 오프라인 데이터 크기,갯수 전송 case Cmd.A_OfflineDataInfo: mOfflineTotalFileCount = pk.GetInt(); mOfflineTotalDataSize = pk.GetInt(); System.Console.WriteLine("[PenCommCore] A_OfflineDataInfo : {0}, {1}", mOfflineTotalFileCount, mOfflineTotalDataSize); Callback.onStartOfflineDownload(this); IsStartOfflineTask = true; break; // 오프라인 전송 최종 결과 응답 case Cmd.A_OfflineResultResponse: int result = pk.GetByteToInt(); //System.Console.WriteLine( "[PenCommCore] A_OfflineDataResponse : {0}", result ); IsStartOfflineTask = false; Callback.onFinishedOfflineDownload(this, result == 0x00 ? false : true); mOfflineworker.onFinishDownload(); mOfflineRcvDataSize = 0; break; // 오프라인 파일 정보 case Cmd.A_OfflineFileInfo: mOfflineFileName = pk.GetString(128); mOfflineFileSize = pk.GetInt(); mOfflinePacketCount = pk.GetShort(); mOfflinePacketSize = pk.GetShort(); System.Console.WriteLine("[PenCommCore] offline file transfer is started ( name : " + mOfflineFileName + ", size : " + mOfflineFileSize + ", packet_qty : " + mOfflinePacketCount + ", packet_size : " + mOfflinePacketSize + " )"); mOfflineDataBuilder = null; mOfflineDataBuilder = new OfflineDataSerializer(mOfflineFileName, mOfflinePacketCount, mOfflineFileName.Contains(".zip") ? true : false); SendOfflineInfoResponse(); break; // 오프라인 파일 조각 전송 case Cmd.A_OfflineChunk: int index = pk.GetShort(); // 체크섬 필드 byte cs = pk.GetByte(); // 체크섬 계산 byte calcChecksum = pk.GetChecksum(); // 오프라인 데이터 byte[] data = pk.GetBytes(); // 체크섬이 틀리거나, 카운트, 사이즈 정보가 맞지 않으면 버린다. if (cs == calcChecksum && mOfflinePacketCount > index && mOfflinePacketSize >= data.Length) { mOfflineDataBuilder.Put(data, index); // 만약 Chunk를 다 받았다면 offline data를 처리한다. if (mOfflinePacketCount == mOfflineDataBuilder.chunks.Count) { string output = mOfflineDataBuilder.MakeFile(); if (output != null) { SendOfflineChunkResponse((short)index); mOfflineworker.onCreateFile(mOfflineDataBuilder.sectionId, mOfflineDataBuilder.ownerId, mOfflineDataBuilder.noteId, output); } mOfflineDataBuilder = null; } else { SendOfflineChunkResponse((short)index); } mOfflineRcvDataSize += data.Length; if (mOfflineTotalDataSize > 0) { System.Console.WriteLine("[PenCommCore] mOfflineRcvDataSize : " + mOfflineRcvDataSize); Callback.onUpdateOfflineDownload(this, mOfflineTotalDataSize, mOfflineRcvDataSize); } } else { System.Console.WriteLine("[PenCommCore] offline data file verification failed ( index : " + index + " )"); } break; case Cmd.A_UsingNoteNotifyResponse: { bool accepted = pk.GetByteToInt() == 0x01; Callback.onAvailableNoteAccepted(this, accepted); } break; case Cmd.A_OfflineNoteListResponse: { int status = pk.GetByteToInt(); byte[] rxb = pk.GetBytes(4); int section = (int)(rxb[3] & 0xFF); int owner = ByteConverter.ByteToInt(new byte[] { rxb[0], rxb[1], rxb[2], (byte)0x00 }); int noteCnt = pk.GetByteToInt(); for (int i = 0; i < noteCnt; i++) { int note = pk.GetInt(); mOfflineNotes.Add(new OfflineDataInfo(section, owner, note)); } if (status == 0x01) { OfflineDataInfo[] array = mOfflineNotes.ToArray(); Callback.onOfflineDataList(this, array); mOfflineNotes.Clear(); } else { Callback.onOfflineDataList(this, new OfflineDataInfo[0]); } } break; case Cmd.A_OfflineDataRemoveResponse: //System.Console.WriteLine( "[PenCommCore] CMD.A_OfflineDataRemoveResponse" ); break; case Cmd.A_PasswordRequest: { int countRetry = pk.GetByteToInt(); int countReset = pk.GetByteToInt(); System.Console.WriteLine("[PenCommCore] A_PasswordRequest ( " + countRetry + " / " + countReset + " )"); if (needToInputDefaultPassword) { _ReqInputPassword(DEFAULT_PASSWORD); needToInputDefaultPassword = false; } else { Callback.onPenPasswordRequest(this, countRetry, countReset); } } break; case Cmd.A_PasswordSetResponse: { int setResult = pk.GetByteToInt(); //System.Console.WriteLine( "[PenCommCore] A_PasswordSetResponse => " + setResult ); if (setResult == 0x00) { needToInputDefaultPassword = true; } Callback.onPenPasswordSetUpResponse(this, setResult == 0x00 ? true : false); } break; case Cmd.A_PenSensitivityResponse: case Cmd.A_AutoShutdownTimeResponse: case Cmd.A_AutoPowerOnResponse: case Cmd.A_BeepSetResponse: case Cmd.A_PenColorSetResponse: case Cmd.A_HoverOnOffResponse: ResPenSetup((Cmd)pk.Cmd, pk.GetByteToInt() == 0x01); break; case Cmd.A_PenSWUpgradeRequest: short idx = pk.GetShort(); ResponseChunkRequest(idx); break; case Cmd.A_PenSWUpgradeStatus: { int upgStatus = pk.GetByteToInt(); if (upgStatus == 0x02) { return; } Callback.onReceivedFirmwareUpdateResult(this, upgStatus == 0x01); mFwChunk = null; } break; } }