public void Disconnect()
        {
            try
            {
                UpdateConnectionStatus(NefitConnectionStatus.Disconnecting);
                if (_client == null)
                {
                    return;
                }

                lock (_lockObj)
                {
                    _client.OnReadXml  -= XmppRead;
                    _client.OnWriteXml -= XmppWrite;
                    _client.Close();
                    _client      = null;
                    _lastMessage = null;
                }
            }
            catch (Exception e)
            {
                ExceptionEvent?.Invoke(this, e);
            }
            finally
            {
                UpdateConnectionStatus(NefitConnectionStatus.Disconnected);
            }
        }
 NefitEasyClient(string serial, string accesskey, string password)
 {
     ConnectionStatus   = NefitConnectionStatus.Disconnected;
     _lockObj           = new object();
     _communicationLock = new object();
     _lastMessage       = null;
     _serial            = serial;
     _accessKey         = accesskey;
     _encryptionHelper  = new NefitEasyEncryption(accesskey, password);
 }
        T HttpGet <T>(string url)
        {
            lock (_communicationLock)
            {
                try
                {
                    if (_client == null)
                    {
                        return(default(T));
                    }

                    var request = new NefitEasyHttpRequest(url, _client.MyJID, $"{CRrcGatewayPrefix}{_serial}@{CHost}");
                    _client.Send(request.ToString());

                    HttpRequestEvent?.Invoke(this, $"HttpGet->request: {request}");
                    var timeout = CRequestTimeout;

                    while (timeout > 0)
                    {
                        lock (_lockObj)
                        {
                            if (_lastMessage != null)
                            {
                                var decrypted = _encryptionHelper.Decrypt(_lastMessage.Payload);
                                HttpRequestEvent?.Invoke(this, $"HttpGet->decrypted: {decrypted}");

                                NefitJson <T> obj;

                                if (TryParseJsonString(decrypted, out obj))
                                {
                                    if (ConnectionStatus != NefitConnectionStatus.Connected)
                                    {
                                        UpdateConnectionStatus(NefitConnectionStatus.Connected);
                                    }
                                    _lastMessage = null;
                                    return(obj.Value);
                                }

                                UpdateConnectionStatus(NefitConnectionStatus.InvalidPassword);
                                timeout = 0;
                            }
                        }
                        timeout -= CCheckInterval;
                        Thread.Sleep(CCheckInterval);
                    }
                }
                catch (Exception e)
                {
                    ExceptionEvent?.Invoke(this, e);
                }
                return(default(T));
            }
        }
        bool HttpPut(string url, string data)
        {
            lock (_communicationLock)
            {
                try
                {
                    if (_client == null)
                    {
                        return(false);
                    }

                    var request = new NefitEasyHttpRequest(url, _client.MyJID, $"{CRrcGatewayPrefix}{_serial}@{CHost}", _encryptionHelper.Encrypt(data));
                    _client.Send(request.ToString());

                    HttpRequestEvent?.Invoke(this, $"HttpPut: {request}");
                    var timeout = CRequestTimeout;

                    while (timeout > 0)
                    {
                        lock (_lockObj)
                        {
                            if (_lastMessage != null)
                            {
                                var result = _lastMessage.Code == (int)HttpStatusCode.OK || _lastMessage.Code == (int)HttpStatusCode.NoContent;
                                if (result && ConnectionStatus != NefitConnectionStatus.Connected)
                                {
                                    UpdateConnectionStatus(NefitConnectionStatus.Connected);
                                }

                                _lastMessage = null;
                                return(result);
                            }
                        }
                        timeout -= CCheckInterval;
                        Thread.Sleep(CCheckInterval);
                    }
                }
                catch (Exception e)
                {
                    ExceptionEvent?.Invoke(this, e);
                }
                return(false);
            }
        }
        void XmppRead(object sender, string xml)
        {
            XmlDocument doc;

            if (TryParseXml(xml, out doc))
            {
                XmlReadEvent?.Invoke(this, doc);

                if (doc.DocumentElement == null)
                {
                    return;
                }

                if (doc.DocumentElement.Name.Equals(nameof(DocumentElement.Message), StringComparison.InvariantCultureIgnoreCase))
                {
                    var header = new NefitEasyHttpResponse(doc.InnerText);
                    lock (_lockObj)
                    {
                        _lastMessage = header;
                    }
                }
                else if (doc.DocumentElement.Name.Equals(nameof(DocumentElement.Presence), StringComparison.InvariantCultureIgnoreCase))
                {
                    UpdateConnectionStatus(NefitConnectionStatus.AuthenticationTest);
                }
                else if (doc.DocumentElement.Name.Equals(nameof(DocumentElement.Failure), StringComparison.InvariantCultureIgnoreCase) &&
                         doc.ChildNodes.Cast <XmlNode>().FirstOrDefault()?.FirstChild.Name == "not-authorized")
                {
                    UpdateConnectionStatus(NefitConnectionStatus.InvalidSerialAccessKey);
                }
            }
            else
            {
                UpdateConnectionStatus(NefitConnectionStatus.Authenticating);
            }
        }