public static byte[] BuildOkreply(UInt32 kcid, Protocol.CommandType commandType)
        {
            // serialize to byte array for transmission via TCP/IP:
            MemoryStream ms = new MemoryStream();

            MsgPack.Packer packer = MsgPack.Packer.Create(ms);
            packer.PackMapHeader(3);

            //kcid, commandtype, OK

            // KCID
            packer.Pack((byte)Protocol.Parameter.KCID);
            packer.Pack((kcid));

            // Command ID
            packer.Pack((byte)Protocol.Parameter.CommandType);
            packer.Pack((byte)commandType);

            // KCResultCode
            packer.Pack((byte)Protocol.Parameter.Result_Code);
            packer.Pack((byte)Protocol.ReturnValues.OK);

            return(ms.ToArray());
        }
        private void ReturnOk(Protocol.CommandType commandType)
        {
            var data = ServerProtocol.BuildOkreply(_kcid, commandType);

            Send(data);
        }
        private void HandleReceiveBuffer2(Socket socket)
        {
            // TODO - Refactor HandleReceiveBuffer2

            // 1: best-case scenario: er staat een geheel bericht in buffer
            // 2: meerdere berichten in buffer
            // 3: deelbericht in buffer
            // 4: kapotte buffer

            //System.Diagnostics.Debug.Print(DateTime.Now.ToString("HH:mm:ss.fffff") + ":HandleReceiveBuffer2:" + _receiveBuffer.Length);

            var msgs = Protocol.ParseBuffer(ref _receiveBuffer);

            if (msgs == null)
            {
                return;
            }



            foreach (MsgPack.MessagePackObject msg in msgs)
            {
                //if (OnMessage != null)
                //{
                //    OnMessage(this, new KeyConductorRawCommandEventArgs(msg)); // this is the raw message from the KeyConductorLite
                //}

                // handle the message
                // first key/pair = KCID
                // second key/pair = CommandType
                // rest is based on commandtype

                var dicMessage = msg.AsDictionary();

                // Generic parameters
                string kcid = "000000000000"; // default kcid
                Protocol.CommandType  commandType = Protocol.CommandType.Undefined;
                Protocol.ReturnValues returnValue = Protocol.ReturnValues.Undefined;
                string paramData = "";

                // Specific parameters
                byte position = 0;
                //Protocol.Capabilities capabilities = Protocol.Capabilities.None;
                Protocol.EventType eventType = Protocol.EventType.Undefined;

                Protocol.FileName fileName = Protocol.FileName.Undefined;
                uint   fileChecksum        = 0;
                byte[] fileContents        = new byte[] { };

                foreach (var dc in dicMessage)
                {
                    if ((byte)dc.Key == (byte)Protocol.Parameter.KCID) // always first parameter
                    {
                        kcid = Convert.ToString((UInt32)dc.Value, 16);
                    }
                    else if ((byte)dc.Key == (byte)Protocol.Parameter.CommandType) // always second parameter
                    {
                        commandType = (Protocol.CommandType)(byte) dc.Value;

                        switch (commandType)
                        {
                        case Protocol.CommandType.GetInfo:
                            OnLogMessage?.Invoke(this, new LogMessageEventArgs("GetInfo request"));
                            ReturnInfo();
                            break;

                        case Protocol.CommandType.PutFile:
                        case Protocol.CommandType.RemoteRelease:
                        case Protocol.CommandType.SetDateTime:
                        case Protocol.CommandType.RemoteReturn:
                            OnLogMessage?.Invoke(this, new LogMessageEventArgs(string.Format("Command:{0} request", commandType)));
                            ReturnOk(commandType);
                            break;
                        }
                    }
                    else if ((byte)dc.Key == (byte)Protocol.Parameter.Position)
                    {
                        position = (byte)dc.Value;
                    }
                    else // rest of the parameters depends on type of command/event
                    {
                        switch (commandType)
                        {
                        case Protocol.CommandType.GetFile:
                        {
                            if ((byte)dc.Key == (byte)Protocol.Parameter.FileName)
                            {
                                fileName = (Protocol.FileName)(byte) dc.Value;

                                OnLogMessage?.Invoke(this, new LogMessageEventArgs(string.Format("Command:GetFile {0} request", fileName)));
                                ReturnDummyFile(fileName);
                            }
                        }
                        break;


                        case Protocol.CommandType.OnEvent:
                        {
                            if ((byte)dc.Key == (byte)Protocol.Parameter.EventType)
                            {
                                eventType = (Protocol.EventType)(byte) dc.Value;
                            }

                            else if ((byte)dc.Key == (byte)Protocol.Parameter.EventData)
                            {
                                // depends on eventType
                                switch (eventType)
                                {
                                // Standalone events:

                                case Protocol.EventType.RemoteAuthentication:
                                {
                                    //case Protocol.EventType.KeyBoardPress: // ter simulatie

                                    string userCode = "0000";
                                    string pinCode  = "0000";
                                    string userData = "";

                                    // bytes[0] + bytes[1]: userCode of pinCode
                                    // bytes[2] + bytes[3]: pinCode
                                    // bytes[rest]: userData (optional)
                                    paramData = BitConverter.ToString((byte[])dc.Value).Replace("-", "");

                                    // Note that both UserCode and Pincode are byte-rotated; 1234 -> 3412

                                    if (paramData.Length == 4)
                                    {
                                        pinCode = paramData.Substring(2, 2) + paramData.Substring(0, 2);
                                    }
                                    else if (paramData.Length >= 8)
                                    {
                                        userCode = paramData.Substring(2, 2) + paramData.Substring(0, 2);
                                        pinCode  = paramData.Substring(6, 2) + paramData.Substring(4, 2);
                                    }

                                    if (paramData.Length > 8)
                                    {
                                        for (int i = 8; i < paramData.Length; i++)
                                        {
                                            userData += (char)paramData[i];                 // Convert.ToString(paramData[i], 10);
                                        }
                                    }

                                    var evtArg = new RemoteAuthenticationEventArgs(kcid, userCode, pinCode, userData);
                                    OnRemoteAuthentication?.Invoke(this, evtArg);
                                }
                                break;

                                case Protocol.EventType.Login:
                                case Protocol.EventType.Logout:
                                {
                                    string userCode = "0000";
                                    string pinCode  = "0000";
                                    string userData = "";

                                    // bytes[0] + bytes[1]: userCode of pinCode
                                    // bytes[2] + bytes[3]: pinCode
                                    // bytes[rest]: userData (optional)

                                    byte[] tmpAuthData = (byte[])dc.Value;


                                    paramData = BitConverter.ToString(tmpAuthData).Replace("-", "");

                                    // Note that both UserCode and Pincode are NOT byte-rotated


                                    if (paramData.Length == 4)
                                    {
                                        pinCode = paramData.Substring(0, 4);
                                    }
                                    else if (paramData.Length >= 8)
                                    {
                                        userCode = paramData.Substring(0, 4);
                                        pinCode  = paramData.Substring(4, 4);
                                    }

                                    if (paramData.Length > 8)
                                    {
                                        for (int i = 8; i < paramData.Length; i++)
                                        {
                                            userData += (char)paramData[i];                 // Convert.ToString(paramData[i], 10);
                                        }
                                    }

                                    var evtArg = new OnEventUserEventArgs(kcid, userCode, pinCode, userData);
                                    if (eventType == Protocol.EventType.Login)
                                    {
                                        OnEventLogin?.Invoke(this, evtArg);
                                    }
                                    else
                                    {
                                        OnEventLogout?.Invoke(this, evtArg);
                                    }
                                }
                                break;

                                case Protocol.EventType.DoorOpen:
                                case Protocol.EventType.DoorClosed:
                                {
                                    string userCode = "0000";

                                    // bytes[0] + bytes[1]: userCode of pinCode

                                    paramData = BitConverter.ToString((byte[])dc.Value).Replace("-", "");

                                    // Note that both UserCode and Pincode are NOT byte-rotated

                                    if (paramData.Length == 4)
                                    {
                                        userCode = paramData;
                                    }

                                    var evtArg = new OnEventDoorEventArgs(kcid, userCode, 0x00);
                                    if (eventType == Protocol.EventType.DoorOpen)
                                    {
                                        OnEventDoorOpen?.Invoke(this, evtArg);
                                    }
                                    else
                                    {
                                        OnEventDoorClosed?.Invoke(this, evtArg);
                                    }
                                }
                                break;

                                case Protocol.EventType.KeyReturned:
                                case Protocol.EventType.KeyPicked:
                                {
                                    string userCode = "0000";
                                    ushort slot     = 0;

                                    // bytes[0] + bytes[1]: userCode
                                    // V2: bytes[2]: slot
                                    // V3: bytes[2] + bytes[3]: slot (ushort)

                                    byte[] data = (byte[])dc.Value;
                                    paramData = BitConverter.ToString(data).Replace("-", "");

                                    // Note that both UserCode and Pincode are byte-rotated; 1234 -> 3412

                                    userCode = paramData.Substring(2, 2) + paramData.Substring(0, 2);

                                    if (data.Length == 3)
                                    {
                                        // Firmware 2
                                        slot = data[2];
                                    }
                                    else if (data.Length == 4)
                                    {
                                        // Firmware 3
                                        slot = (ushort)(data[2] * 256 + data[3]);
                                    }

                                    var evtArg = new OnEventKeyEventArgs(kcid, userCode, slot);
                                    if (eventType == Protocol.EventType.KeyReturned)
                                    {
                                        OnEventKeyReturned?.Invoke(this, evtArg);
                                    }
                                    else
                                    {
                                        OnEventKeyPicked?.Invoke(this, evtArg);
                                    }
                                }
                                break;

                                case Protocol.EventType.Timeout:
                                case Protocol.EventType.Warning:
                                case Protocol.EventType.ExternalAlarm:
                                case Protocol.EventType.ExternalAlarmCleared:
                                case Protocol.EventType.Startup:
                                case Protocol.EventType.MainsVoltageLost:
                                case Protocol.EventType.MainsVoltageConnected:
                                {
                                    string userCode = "0000";

                                    // bytes[0] + bytes[1]: userCode
                                    byte[] data = (byte[])dc.Value;
                                    paramData = BitConverter.ToString(data).Replace("-", "");

                                    // Note that both UserCode is NOT byte-rotated
                                    userCode = paramData;

                                    var evtArg = new OnEventWarningEventArgs(kcid, userCode, eventType);

                                    switch (eventType)
                                    {
                                    case Protocol.EventType.Warning:
                                        OnEventWarning?.Invoke(this, evtArg);
                                        break;

                                    case Protocol.EventType.Timeout:
                                        OnEventTimeout?.Invoke(this, evtArg);
                                        break;

                                    case Protocol.EventType.ExternalAlarm:
                                        OnEventAlarm?.Invoke(this, evtArg);
                                        break;

                                    case Protocol.EventType.ExternalAlarmCleared:
                                        OnEventAlarmCleared?.Invoke(this, evtArg);
                                        break;

                                    case Protocol.EventType.Startup:
                                        OnEventStartUp?.Invoke(this, evtArg);
                                        break;

                                    case Protocol.EventType.MainsVoltageLost:
                                        OnEventMainsVoltageLost?.Invoke(this, evtArg);
                                        break;

                                    case Protocol.EventType.MainsVoltageConnected:
                                        OnEventMainsVoltageConnected?.Invoke(this, evtArg);
                                        break;
                                    }
                                }
                                break;
                                }
                            }
                            else if ((byte)dc.Key == (byte)Protocol.Parameter.Result_Code)         // n-th parameter
                            {
                                // dit komt niet voor bij events !!
                            }
                        }
                        break;

                        default:
                        {
                            if ((byte)dc.Key == (byte)Protocol.Parameter.Result_Code)         // n-th parameter
                            {
                                returnValue = (Protocol.ReturnValues)(byte) dc.Value;

                                var evtArg = new KeyConductorBaseReplyEventArgs(kcid, commandType, returnValue);

                                OnCommand?.Invoke(this, evtArg);

                                // raise event for individual functions
                                switch (commandType)
                                {
                                case Protocol.CommandType.Unknown:
                                    OnUnknownCommand?.Invoke(this, evtArg);
                                    break;

                                case Protocol.CommandType.PutFile:
                                    OnPutFile?.Invoke(this, evtArg);
                                    break;

                                case Protocol.CommandType.SetDateTime:
                                    OnSetDateTime?.Invoke(this, evtArg);
                                    break;

                                case Protocol.CommandType.RemoteRelease:
                                    OnRemoteRelease?.Invoke(this, evtArg);
                                    break;

                                case Protocol.CommandType.RemoteReturn:
                                    OnRemoteReturn?.Invoke(this, evtArg);
                                    break;

                                case Protocol.CommandType.RemoteReboot:
                                    OnRemoteReboot?.Invoke(this, evtArg);
                                    break;
                                }
                            }         // if parameter = resultcode
                        }
                        break;
                        } // /Switch commandType
                    }     //Else parameter
                }         // foreach dc in dicMessage
            }             // foreach msg in msgs
        }                 // /HandleReceiveBuffer