Exemple #1
0
        private void ParseHeader()
        {
            byte[] header = CopyOfRange(mData, mData.Length - BYTE_HEADER_SIZE, BYTE_HEADER_SIZE);

            byte[] osbyte = CopyOfRange(header, 6, 4);

            mSectionId = (int)(osbyte[3] & 0xFF);
            mOwnerId   = ByteConverter.ByteToInt(new byte[] { osbyte[0], osbyte[1], osbyte[2], (byte)0x00 });

            mNoteId = ByteConverter.ByteToInt(CopyOfRange(header, 10, 4));
            mPageId = ByteConverter.ByteToInt(CopyOfRange(header, 14, 4));

            mLineCount = ByteConverter.ByteToInt(CopyOfRange(header, 22, 4));
            mDataSize  = ByteConverter.ByteToInt(CopyOfRange(header, 26, 4));
            //this.headerCheckSum = header[BYTE_HEADER_SIZE-1];

            mBody = CopyOfRange(mData, 0, mData.Length - BYTE_HEADER_SIZE);

            if (mBody.Length != mDataSize)
            {
                throw new Exception("data size is invalid");
            }

            //System.Console.WriteLine( "[OfflineDataParser] noteId : " + noteId + ", pageId : " + pageId + ", lineCount : " + lineCount + ", fileSize : " + dataSize + "byte" );
        }
Exemple #2
0
        private void ParseDotPacket(Cmd cmd, Packet pk)
        {
            switch (cmd)
            {
            case Cmd.ONLINE_PEN_UPDOWN_EVENT:

                IsStartWithDown = pk.GetByte() == 0x00;

                mDotCount = 0;

                mTime = pk.GetLong();

                mPenTipType = pk.GetByte() == 0x00 ? PenTipType.Normal : PenTipType.Eraser;

                mPenTipColor = pk.GetInt();

                if (mPrevPacket != null && !IsStartWithDown)
                {
                    mPrevPacket.Reset();
                    previousDot = null;
                    ParseDot(mPrevPacket, DotTypes.PEN_UP);
                }

                break;

            case Cmd.ONLINE_PEN_DOT_EVENT:

                if (HoverMode && !IsStartWithDown)
                {
                    // 호버모드 처리
                    ParseDot(pk, DotTypes.PEN_HOVER);
                }
                else if (IsStartWithDown)
                {
                    ParseDot(pk, mDotCount == 0 ? DotTypes.PEN_DOWN : DotTypes.PEN_MOVE);
                }
                else
                {
                    //오류
                }

                mPrevPacket = pk;
                mDotCount++;

                break;

            case Cmd.ONLINE_PAPER_INFO_EVENT:

                byte[] rb = pk.GetBytes(4);

                mCurSection = (int)(rb[3] & 0xFF);
                mCurOwner   = ByteConverter.ByteToInt(new byte[] { rb[0], rb[1], rb[2], (byte)0x00 });
                mCurNote    = pk.GetInt();
                mCurPage    = pk.GetInt();

                break;
            }
        }
Exemple #3
0
        public OfflineDataSerializer(string filepath, int packetCount, bool isCompressed)
        {
            chunks = new Dictionary <int, byte[]>();

            string[] arr = filepath.Split('\\');

            int sectionOwner = int.Parse(arr[2]);

            byte[] bso = ByteConverter.IntToByte(sectionOwner);

            sectionId = (int)(bso[3] & 0xFF);
            ownerId   = ByteConverter.ByteToInt(new byte[] { bso[0], bso[1], bso[2], (byte)0x00 });

            noteId = int.Parse(arr[3]);
            pageId = int.Parse(arr[4]);

            mPacketCount = packetCount;
            IsCompressed = isCompressed;

            base.SetupFileSystem();
        }
        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;
            }
        }
Exemple #5
0
        private void ParseBody(int penMaxForce)
        {
            mDots.Clear();

            long penDownTime = 0, penUpTime = 0, prevTimestamp = 0;

            int dotTotalCount = 0, dotCount = 0;

            byte lineCheckSum = 0;

            int dotStartIndex = 0, dotSize = 0;

            byte[] lineColorBytes = new byte[4];

            int lineColor = 0x000000;

            // 현재 라인의 도트
            offlineDots = new List <Dot>();

            int i = 0;

            while (i < mBody.Length && mBody.Length > 0)
            {
                if (ByteConverter.SingleByteToInt(mBody[i]) == LINE_MARK_1 && ByteConverter.SingleByteToInt(mBody[i + 1]) == LINE_MARK_2)
                {
                    offlineDots = new List <Dot>();

                    penDownTime    = ByteConverter.ByteToLong(CopyOfRange(mBody, i + 2, 8));
                    penUpTime      = ByteConverter.ByteToLong(CopyOfRange(mBody, i + 10, 8));
                    dotTotalCount  = ByteConverter.ByteToInt(CopyOfRange(mBody, i + 18, 4));
                    lineColorBytes = CopyOfRange(mBody, i + 23, 4);

                    lineColor = ByteConverter.ByteToInt(new byte[] { lineColorBytes[2], lineColorBytes[1], lineColorBytes[0], (byte)0 });

                    //System.Console.WriteLine( "[OfflineDataParser] penDownTime : {0}, penUpTime : {1}, dotTotalCount : {2}, lineColor : {3}", penDownTime, penUpTime, dotTotalCount, lineColor );

                    lineCheckSum = mBody[i + 27];

                    i += BYTE_LINE_SIZE;

                    dotStartIndex = i;
                    dotSize       = 0;
                    dotCount      = 0;
                }
                else
                {
                    dotCount++;

                    // 스트로크 헤더에 정의된 도트갯수보다 넘어가면 LN이 나올때까지 한바이트씩 포인터를 이동한다.
                    if (dotCount > dotTotalCount)
                    {
                        i++;
                        continue;
                    }

                    long timeGap = ByteConverter.SingleByteToInt(mBody[i]);

                    short x = ByteConverter.ByteToShort(CopyOfRange(mBody, i + 1, 2));
                    short y = ByteConverter.ByteToShort(CopyOfRange(mBody, i + 3, 2));

                    int fx = ByteConverter.SingleByteToInt(mBody[i + 5]);
                    int fy = ByteConverter.SingleByteToInt(mBody[i + 6]);

                    int force = ByteConverter.SingleByteToInt(mBody[i + 7]);

                    int color = lineColor;

                    bool isPenUp = false;

                    long timestamp = -1L;

                    DotTypes dotType;

                    if (dotSize == 0)
                    {
                        dotType       = DotTypes.PEN_DOWN;
                        timestamp     = penDownTime + timeGap;
                        prevTimestamp = timestamp;
                    }
                    else if (dotTotalCount > dotCount)
                    {
                        dotType       = DotTypes.PEN_MOVE;
                        timestamp     = prevTimestamp + timeGap;
                        prevTimestamp = timestamp;
                    }
                    else
                    {
                        dotType   = DotTypes.PEN_UP;
                        timestamp = penUpTime;
                        isPenUp   = true;
                    }

                    Dot.Builder builder;
                    if (penMaxForce == 0)
                    {
                        builder = new Dot.Builder();
                    }
                    else
                    {
                        builder = new Dot.Builder(penMaxForce);
                    }
                    offlineFilterForPaper.Put(
                        builder
                        .section(mSectionId)
                        .owner(mOwnerId)
                        .note(mNoteId)
                        .page(mPageId)
                        .coord(x + fx * 0.01f, y + fy * 0.01f)
                        .force(force)
                        .color(color)
                        .timestamp(timestamp)
                        .dotType(dotType).Build(), null
                        );

                    dotSize += 8;

                    if (isPenUp)
                    {
                        byte dotCalcCs = CalcChecksum(CopyOfRange(mBody, dotStartIndex, dotSize));

                        if (dotCalcCs == lineCheckSum)
                        {
                            for (int j = 0; j < offlineDots.Count; j++)
                            {
                                mDots.Add(offlineDots[j]);
                            }
                        }
                        else
                        {
                            Debug.WriteLine("[OfflineDataParser] invalid CheckSum cs : " + lineCheckSum + ", calc : " + dotCalcCs);
                        }

                        offlineDots = new List <Dot>();
                    }

                    i += BYTE_DOT_SIZE;
                }
            }
        }
Exemple #6
0
        public void ParsePacket(Packet packet)
        {
            //Debug.WriteLine("[PenCommCore] ParsePacket : " + packet.Cmd);

            switch ((Cmd)packet.Cmd)
            {
            case Cmd.A_DotData:
            {
                long time  = packet.GetByteToInt();
                int  x     = packet.GetShort();
                int  y     = packet.GetShort();
                int  fx    = packet.GetByteToInt();
                int  fy    = packet.GetByteToInt();
                int  force = packet.GetByteToInt();

                long timeLong = mPrevDotTime + time;

                if (!IsStartWithDown || timeLong < 10000)
                {
                    Debug.WriteLine("[PenCommCore] this stroke start with middle dot.");
                    return;
                }

                if (IsPrevDotDown)
                {
                    // 펜업의 경우 시작 도트로 저장
                    IsPrevDotDown = false;
                    ProcessDot(mOwnerId, mSectionId, mNoteId, mPageId, timeLong, x, y, fx, fy, force, DotTypes.PEN_DOWN, mCurrentColor);
                }
                else
                {
                    // 펜업이 아닌 경우 미들 도트로 저장
                    ProcessDot(mOwnerId, mSectionId, mNoteId, mPageId, timeLong, x, y, fx, fy, force, DotTypes.PEN_MOVE, mCurrentColor);
                }

                mPrevDotTime = timeLong;
                mPrevPacket  = packet;
            }
            break;

            case Cmd.A_DotUpDownDataNew:
            case Cmd.A_DotUpDownData:
            {
                // TODO Check
                long updownTime = packet.GetLong();

                int updown = packet.GetByteToInt();

                byte[] cbyte = packet.GetBytes(3);

                mCurrentColor = ByteConverter.ByteToInt(new byte[] { cbyte[2], cbyte[1], cbyte[0], (byte)0 });

                if (updown == 0x00)
                {
                    // 펜 다운 일 경우 Start Dot의 timestamp 설정
                    mPrevDotTime    = updownTime;
                    IsPrevDotDown   = true;
                    IsStartWithDown = true;

                    //Callback.onUpDown(this, false);
                }
                else if (updown == 0x01)
                {
                    if (mPrevPacket != null)
                    {
                        mPrevPacket.Reset();

                        // 펜 업 일 경우 바로 이전 도트를 End Dot로 삽입
                        int time  = mPrevPacket.GetByteToInt();
                        int x     = mPrevPacket.GetShort();
                        int y     = mPrevPacket.GetShort();
                        int fx    = mPrevPacket.GetByteToInt();
                        int fy    = mPrevPacket.GetByteToInt();
                        int force = mPrevPacket.GetByteToInt();

                        ProcessDot(mOwnerId, mSectionId, mNoteId, mPageId, updownTime, x, y, fx, fy, force, DotTypes.PEN_UP, mCurrentColor);
                    }

                    //Callback.onUpDown(this, true);

                    IsStartWithDown = false;
                }

                mPrevPacket = null;
            }
            break;

            case Cmd.A_DotIDChange:

                byte[] rb = packet.GetBytes(4);

                mSectionId = (int)(rb[3] & 0xFF);
                mOwnerId   = ByteConverter.ByteToInt(new byte[] { rb[0], rb[1], rb[2], (byte)0x00 });
                mNoteId    = packet.GetInt();
                mPageId    = packet.GetInt();

                break;

            case Cmd.A_PenOnState:

                packet.Move(8);

                int STATUS = packet.GetByteToInt();

                int FORCE_MAX = packet.GetByteToInt();

                string SW_VER = packet.GetString(5);

                if (STATUS == 0x00)
                {
                    SendPenOnOffData();
                }
                else if (STATUS == 0x01)
                {
                    Reset();

                    SendPenOnOffData();
                    SendRTCData();

                    PenController.onConnected(new ConnectedEventArgs(SW_VER, FORCE_MAX));
                    PenMaxForce = FORCE_MAX;
                    mOfflineworker.PenMaxForce = FORCE_MAX;
                }

                break;

            case Cmd.A_RTCsetResponse:
                break;

            case Cmd.A_PenStatusResponse:

                if (!Authenticated)
                {
                    Authenticated = true;
                    PenController.onPenAuthenticated();
                }

                packet.Move(2);

                int  stat_timezone = packet.GetInt();
                long stat_timetick = packet.GetLong();
                int  stat_forcemax = packet.GetByteToInt();
                int  stat_battery  = packet.GetByteToInt();
                int  stat_usedmem  = packet.GetByteToInt();
                int  stat_pencolor = packet.GetInt();

                bool stat_autopower = packet.GetByteToInt() == 2 ? false : true;
                bool stat_accel     = packet.GetByteToInt() == 2 ? false : true;
                bool stat_hovermode = packet.GetByteToInt() == 2 ? false : true;
                bool stat_beep      = packet.GetByteToInt() == 2 ? false : true;

                short stat_autoshutdowntime = packet.GetShort();
                short stat_pensensitivity   = packet.GetShort();

                PenController.onReceivePenStatus(new PenStatusReceivedEventArgs(stat_timezone, stat_timetick, stat_forcemax, stat_battery, stat_usedmem, stat_pencolor, stat_autopower, stat_accel, stat_hovermode, stat_beep, stat_autoshutdowntime, stat_pensensitivity));
                break;

            // 오프라인 데이터 크기,갯수 전송
            case Cmd.A_OfflineDataInfo:

                mOfflineTotalFileCount = packet.GetInt();
                mOfflineTotalDataSize  = packet.GetInt();

                Debug.WriteLine("[PenCommCore] A_OfflineDataInfo : {0}, {1}", mOfflineTotalFileCount, mOfflineTotalDataSize);

                PenController.onStartOfflineDownload();

                IsStartOfflineTask = true;

                break;

            // 오프라인 전송 최종 결과 응답
            case Cmd.A_OfflineResultResponse:

                int result = packet.GetByteToInt();

                //System.Console.WriteLine( "[PenCommCore] A_OfflineDataResponse : {0}", result );

                IsStartOfflineTask = false;

                PenController.onFinishedOfflineDownload(new SimpleResultEventArgs(result == 0x00));

                mOfflineworker.onFinishDownload();

                break;

            // 오프라인 파일 정보
            case Cmd.A_OfflineFileInfo:

                mOfflineFileName    = packet.GetString(128);
                mOfflineFileSize    = packet.GetInt();
                mOfflinePacketCount = packet.GetShort();
                mOfflinePacketSize  = packet.GetShort();

                Debug.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 = packet.GetShort();

                // 체크섬 필드
                byte cs = packet.GetByte();

                // 체크섬 계산
                byte calcChecksum = packet.GetChecksum();

                // 오프라인 데이터
                byte[] data = packet.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, mOfflineTotalDataSize, mOfflineRcvDataSize);
                        }

                        mOfflineDataBuilder = null;
                    }
                    else
                    {
                        SendOfflineChunkResponse((short)index);
                    }

                    mOfflineRcvDataSize += data.Length;

                    // TODO Check
                    //if (mOfflineTotalDataSize > 0)
                    //{
                    //	Debug.WriteLine("[PenCommCore] mOfflineRcvDataSize : " + mOfflineRcvDataSize);

                    //	//Callback.onUpdateOfflineDownload(this, mOfflineTotalDataSize, mOfflineRcvDataSize);
                    //}
                }
                else
                {
                    Debug.WriteLine("[PenCommCore] offline data file verification failed ( index : " + index + " )");
                }

                break;

            case Cmd.A_UsingNoteNotifyResponse:
                PenController.onAvailableNoteAdded();
                break;

            case Cmd.A_OfflineNoteListResponse:
            {
                int status = packet.GetByteToInt();

                byte[] rxb = packet.GetBytes(4);

                int section = (int)(rxb[3] & 0xFF);

                int owner = ByteConverter.ByteToInt(new byte[] { rxb[0], rxb[1], rxb[2], (byte)0x00 });

                int noteCnt = packet.GetByteToInt();

                for (int i = 0; i < noteCnt; i++)
                {
                    int note = packet.GetInt();
                    mOfflineNotes.Add(new OfflineDataInfo(section, owner, note));
                }

                if (status == 0x01)
                {
                    OfflineDataInfo[] array = mOfflineNotes.ToArray();

                    PenController.onReceiveOfflineDataList(new OfflineDataListReceivedEventArgs(array));
                    mOfflineNotes.Clear();
                }
                else
                {
                    PenController.onReceiveOfflineDataList(new OfflineDataListReceivedEventArgs(new OfflineDataInfo[0]));
                }
            }
            break;

            case Cmd.A_OfflineDataRemoveResponse:
                //System.Console.WriteLine( "[PenCommCore] CMD.A_OfflineDataRemoveResponse" );
                break;

            case Cmd.A_PasswordRequest:
            {
                int countRetry = packet.GetByteToInt();
                int countReset = packet.GetByteToInt();

                Debug.WriteLine("[PenCommCore] A_PasswordRequest ( " + countRetry + " / " + countReset + " )");

                PenController.onPenPasswordRequest(new PasswordRequestedEventArgs(countRetry, countReset));
            }
            break;


            case Cmd.A_PasswordSetResponse:
            {
                int setResult = packet.GetByteToInt();

                //System.Console.WriteLine( "[PenCommCore] A_PasswordSetResponse => " + setResult );

                PenController.onPenPasswordSetupResponse(new SimpleResultEventArgs(setResult == 0x00));
            }
            break;

            case Cmd.A_PenSensitivityResponse:
            case Cmd.A_AutoShutdownTimeResponse:
            case Cmd.A_AutoPowerOnResponse:
            case Cmd.A_BeepSetResponse:
            case Cmd.A_PenColorSetResponse:
                ResPenSetup((Cmd)packet.Cmd, packet.GetByteToInt() == 0x01);
                break;

            case Cmd.A_PenSWUpgradeRequest:

                short idx = packet.GetShort();

                Debug.WriteLine("[PenCommCore] A_PenSWUpgradeRequest => " + idx);

                ResponseChunkRequest(idx);

                break;

            case Cmd.A_PenSWUpgradeStatus:
            {
                int upgStatus = packet.GetByteToInt();

                if (upgStatus == 0x02)
                {
                    return;
                }

                PenController.onReceiveFirmwareUpdateResult(new SimpleResultEventArgs(upgStatus == 0x01));
                mFwChunk = null;
            }
            break;
            }
        }
Exemple #7
0
        public void ParsePacket(Packet packet)
        {
            Cmd cmd = (Cmd)packet.Cmd;

            //Debug.Write("Cmd : {0}", cmd.ToString());

            switch (cmd)
            {
            case Cmd.VERSION_RESPONSE:
            {
                DeviceName      = packet.GetString(16);
                FirmwareVersion = packet.GetString(16);
                ProtocolVersion = packet.GetString(8);
                SubName         = packet.GetString(16);
                DeviceType      = packet.GetShort();
                MaxForce        = -1;
                MacAddress      = BitConverter.ToString(packet.GetBytes(6)).Replace("-", "");

                IsUploading = false;

                ReqPenStatus();
            }
            break;

                #region event
            case Cmd.SHUTDOWN_EVENT:
            {
                byte reason = packet.GetByte();
                Debug.Write(" => SHUTDOWN_EVENT : {0}", reason.ToString());
            }
            break;

            case Cmd.LOW_BATTERY_EVENT:
            {
                int battery = (int)(packet.GetByte() & 0xff);

                PenController.onReceiveBatteryAlarm(new BatteryAlarmReceivedEventArgs(battery));
            }
            break;

            case Cmd.ONLINE_PEN_UPDOWN_EVENT:
            case Cmd.ONLINE_PEN_DOT_EVENT:
            case Cmd.ONLINE_PAPER_INFO_EVENT:
            {
                ParseDotPacket(cmd, packet);
            }
            break;
                #endregion

                #region setting response
            case Cmd.SETTING_INFO_RESPONSE:
            {
                // 비밀번호 사용 여부
                bool lockyn = packet.GetByteToInt() == 1;

                // 비밀번호 입력 최대 시도 횟수
                int pwdMaxRetryCount = packet.GetByteToInt();

                // 비밀번호 입력 시도 횟수
                int pwdRetryCount = packet.GetByteToInt();

                // 1970년 1월 1일부터 millisecond tick
                long time = packet.GetLong();

                // 사용하지 않을때 자동으로 전원이 종료되는 시간 (단위:분)
                short autoPowerOffTime = packet.GetShort();

                // 최대 필압
                short maxForce = packet.GetShort();

                // 현재 메모리 사용량
                int usedStorage = packet.GetByteToInt();

                // 펜의 뚜껑을 닫아서 펜의 전원을 차단하는 기능 사용 여부
                bool penCapOff = packet.GetByteToInt() == 1;

                // 전원이 꺼진 펜에 필기를 시작하면 자동으로 펜의 켜지는 옵션 사용 여부
                bool autoPowerON = packet.GetByteToInt() == 1;

                // 사운드 사용여부
                bool beep = packet.GetByteToInt() == 1;

                // 호버기능 사용여부
                bool hover = packet.GetByteToInt() == 1;

                // 남은 배터리 수치
                int batteryLeft = packet.GetByteToInt();

                // 오프라인 데이터 저장 기능 사용 여부
                bool useOffline = packet.GetByteToInt() == 1;

                // 필압 단계 설정 (0~4) 0이 가장 민감
                short fsrStep = (short)packet.GetByteToInt();

                // 최초 연결시
                if (MaxForce == -1)
                {
                    MaxForce = maxForce;

                    var connectedEventArgs = new ConnectedEventArgs();

                    PenController.onConnected(new ConnectedEventArgs(MacAddress, DeviceName, FirmwareVersion, ProtocolVersion, SubName, MaxForce));
                    PenMaxForce = MaxForce;

                    if (lockyn)
                    {
                        // TODO 여기서 부터 시작
                        PenController.onPenPasswordRequest(new PasswordRequestedEventArgs(pwdRetryCount, pwdMaxRetryCount));
                    }
                    else
                    {
                        PenController.onPenAuthenticated();
                    }
                }
                else
                {
                    PenController.onReceivePenStatus(new PenStatusReceivedEventArgs(lockyn, pwdMaxRetryCount, pwdRetryCount, time, autoPowerOffTime, MaxForce, batteryLeft, usedStorage, useOffline, autoPowerON, penCapOff, hover, beep, fsrStep));
                }
            }
            break;

            case Cmd.SETTING_CHANGE_RESPONSE:
            {
                int inttype = packet.GetByteToInt();

                SettingType stype = (SettingType)inttype;

                bool result = packet.Result == 0x00;

                switch (stype)
                {
                case SettingType.AutoPowerOffTime:
                    PenController.onPenAutoShutdownTimeSetupResponse(new SimpleResultEventArgs(result));
                    break;

                case SettingType.AutoPowerOn:
                    PenController.onPenAutoPowerOnSetupResponse(new SimpleResultEventArgs(result));
                    break;

                case SettingType.Beep:
                    PenController.onPenBeepSetupResponse(new SimpleResultEventArgs(result));
                    break;

                case SettingType.Hover:
                    PenController.onPenHoverSetupResponse(new SimpleResultEventArgs(result));
                    break;

                case SettingType.LedColor:
                    PenController.onPenColorSetupResponse(new SimpleResultEventArgs(result));
                    break;

                case SettingType.OfflineData:
                    PenController.onPenOfflineDataSetupResponse(new SimpleResultEventArgs(result));
                    break;

                case SettingType.PenCapOff:
                    PenController.onPenCapPowerOnOffSetupResponse(new SimpleResultEventArgs(result));
                    break;

                case SettingType.Sensitivity:
                    PenController.onPenSensitivitySetupResponse(new SimpleResultEventArgs(result));
                    break;

                case SettingType.Timestamp:
                    PenController.onPenTimestampSetupResponse(new SimpleResultEventArgs(result));
                    break;
                }
            }
            break;
                #endregion

                #region password response
            case Cmd.PASSWORD_RESPONSE:
            {
                int status   = packet.GetByteToInt();
                int cntRetry = packet.GetByteToInt();
                int cntMax   = packet.GetByteToInt();

                if (status == 0)
                {
                    PenController.onPenPasswordRequest(new PasswordRequestedEventArgs(cntRetry, cntMax));
                }
                else
                {
                    PenController.onPenAuthenticated();
                }
            }
            break;

            case Cmd.PASSWORD_CHANGE_RESPONSE:
            {
                int cntRetry = packet.GetByteToInt();
                int cntMax   = packet.GetByteToInt();

                PenController.onPenPasswordSetupResponse(new SimpleResultEventArgs(packet.Result == 0x00));
            }
            break;
                #endregion

                #region offline response
            case Cmd.OFFLINE_NOTE_LIST_RESPONSE:
            {
                short length = packet.GetShort();

                List <OfflineDataInfo> result = new List <OfflineDataInfo>();

                for (int i = 0; i < length; i++)
                {
                    byte[] rb = packet.GetBytes(4);

                    int section = (int)(rb[3] & 0xFF);
                    int owner   = ByteConverter.ByteToInt(new byte[] { rb[0], rb[1], rb[2], (byte)0x00 });
                    int note    = packet.GetInt();

                    result.Add(new OfflineDataInfo(section, owner, note));
                }

                PenController.onReceiveOfflineDataList(new OfflineDataListReceivedEventArgs(result.ToArray()));
            }
            break;

            case Cmd.OFFLINE_PAGE_LIST_RESPONSE:
            {
                byte[] rb = packet.GetBytes(4);

                int section = (int)(rb[3] & 0xFF);
                int owner   = ByteConverter.ByteToInt(new byte[] { rb[0], rb[1], rb[2], (byte)0x00 });
                int note    = packet.GetInt();

                short length = packet.GetShort();

                int[] pages = new int[length];

                for (int i = 0; i < length; i++)
                {
                    pages[i] = packet.GetInt();
                }

                OfflineDataInfo info = new OfflineDataInfo(section, owner, note);

                PenController.onReceiveOfflineDataList(new OfflineDataListReceivedEventArgs(info));
            }
            break;

            case Cmd.OFFLINE_DATA_RESPONSE:
            {
                mTotalOfflineStroke    = packet.GetInt();
                mReceivedOfflineStroke = 0;
                mTotalOfflineDataSize  = packet.GetInt();

                bool isCompressed = packet.GetByte() == 1;

                PenController.onStartOfflineDownload();
            }
            break;

            case Cmd.OFFLINE_PACKET_REQUEST:
            {
                #region offline data parsing

                List <Stroke> result = new List <Stroke>();

                short packetId = packet.GetShort();

                bool isCompressed = packet.GetByte() == 1;

                short sizeBefore = packet.GetShort();

                short sizeAfter = packet.GetShort();

                short location = (short)(packet.GetByte() & 0xFF);

                byte[] rb = packet.GetBytes(4);

                int section = (int)(rb[3] & 0xFF);

                int owner = ByteConverter.ByteToInt(new byte[] { rb[0], rb[1], rb[2], (byte)0x00 });

                int note = packet.GetInt();

                short strCount = packet.GetShort();

                mReceivedOfflineStroke += strCount;

                Debug.WriteLine(" packetId : {0}, isCompressed : {1}, sizeBefore : {2}, sizeAfter : {3}, size : {4}", packetId, isCompressed, sizeBefore, sizeAfter, packet.Data.Length - 18);

                if (sizeAfter != (packet.Data.Length - 18))
                {
                    SendOfflinePacketResponse(packetId, false);
                    return;
                }

                byte[] oData = packet.GetBytes(sizeAfter);

                GZipStream gzipStream = new GZipStream(new System.IO.MemoryStream(oData), CompressionLevel.Fastest);

                byte[] strData = Ionic.Zlib.ZlibStream.UncompressBuffer(oData);

                if (strData.Length != sizeBefore)
                {
                    SendOfflinePacketResponse(packetId, false);
                    return;
                }

                ByteUtil butil = new ByteUtil(strData);

                for (int i = 0; i < strCount; i++)
                {
                    int pageId = butil.GetInt();

                    long timeStart = butil.GetLong();

                    long timeEnd = butil.GetLong();

                    int penTipType = (int)(butil.GetByte() & 0xFF);

                    int color = butil.GetInt();

                    short dotCount = butil.GetShort();

                    long time = timeStart;

                    //System.Console.WriteLine( "pageId : {0}, timeStart : {1}, timeEnd : {2}, penTipType : {3}, color : {4}, dotCount : {5}, time : {6},", pageId, timeStart, timeEnd, penTipType, color, dotCount, time );

                    Stroke stroke = new Stroke(section, owner, note, pageId);

                    for (int j = 0; j < dotCount; j++)
                    {
                        byte dotChecksum = butil.GetChecksum(15);

                        int timeadd = butil.GetByte();

                        time += timeadd;

                        int force = butil.GetShort();

                        int x = butil.GetShort();
                        int y = butil.GetShort();

                        int fx = butil.GetByte();
                        int fy = butil.GetByte();

                        int tx = butil.GetByte();
                        int ty = butil.GetByte();

                        int twist = butil.GetShort();

                        short reserved = butil.GetShort();

                        byte checksum = butil.GetByte();

                        //System.Console.WriteLine( "x : {0}, y : {1}, force : {2}, checksum : {3}, dotChecksum : {4}", tx, ty, twist, checksum, dotChecksum );

                        if (dotChecksum != checksum)
                        {
                            SendOfflinePacketResponse(packetId, false);
                            result.Clear();
                            return;
                        }

                        DotTypes dotType;

                        if (j == 0)
                        {
                            dotType = DotTypes.PEN_DOWN;
                        }
                        else if (j == dotCount - 1)
                        {
                            dotType = DotTypes.PEN_UP;
                        }
                        else
                        {
                            dotType = DotTypes.PEN_MOVE;
                        }

                        stroke.Add(MakeDot(PenMaxForce, owner, section, note, pageId, time, x, y, fx, fy, force, dotType, color));
                    }

                    result.Add(stroke);
                }

                SendOfflinePacketResponse(packetId);

                PenController.onReceiveOfflineStrokes(new OfflineStrokeReceivedEventArgs(mTotalOfflineStroke, mReceivedOfflineStroke, result.ToArray()));

                if (location == 2)
                {
                    PenController.onFinishedOfflineDownload(new SimpleResultEventArgs(true));
                }

                #endregion
            }
            break;

            case Cmd.OFFLINE_DATA_DELETE_RESPONSE:
            {
                PenController.onRemovedOfflineData(new SimpleResultEventArgs(packet.Result == 0x00));
            }
            break;
                #endregion

                #region firmware response
            case Cmd.FIRMWARE_UPLOAD_RESPONSE:
            {
                if (packet.Result != 0 || packet.GetByteToInt() != 0)
                {
                    IsUploading = false;
                    PenController.onReceiveFirmwareUpdateResult(new SimpleResultEventArgs(false));
                }
            }
            break;

            case Cmd.FIRMWARE_PACKET_REQUEST:
            {
                int status = packet.GetByteToInt();
                int offset = packet.GetInt();

                ResponseChunkRequest(offset, status != 3);
            }
            break;
                #endregion

            case Cmd.ONLINE_DATA_RESPONSE:
                break;



            default:
                break;
            }
        }