 enum MQTTClientState {
     case ConnectionClosed
     case Initializing
+    case Connected
     case DecodingHeader
     case DecodingLength
     case DecodingData
     case ConnectionError
 }
 
-protocol LightMQTTDelegate {
+protocol LightMQTTDelegate: class {
     func didReceiveMessage(topic: String, message: String)
 }
 
+let MQTT_BUFFER_SIZE: Int = 4096
+
 final class LightMQTT: NSObject, NSStreamDelegate {
-
-    let MQTT_BUFFER_SIZE: Int = 4096
-    let MQTT_KEEPALIVE: UInt8 = 10
 
     private var clientState = MQTTClientState.ConnectionClosed
 


    private var topicLength: Int?

    private var keepAliveTimer: NSTimer?

    var delegate: LightMQTTDelegate?

    // MARK: - Keep alive timer

    func beginKeepAliveTimer() {
        keepAliveTimer?.invalidate()
        keepAliveTimer = NSTimer.scheduledTimerWithTimeInterval(
            Double(MQTT_KEEPALIVE) / 2.0,
            target: self,
            selector: "ping",
            userInfo: nil,
            repeats: true)
    }

    func endKeepAliveTimer() {
        keepAliveTimer?.invalidate()
        keepAliveTimer = nil
    }

    // MARK: - Socket connection

    func connectSocket(host: String, port: Int) {
        NSStream.getStreamsToHostWithName(host, port: port, inputStream: &inputStream, outputStream: &outputStream)

        inputStream?.delegate = self
        outputStream?.delegate = self

        inputStream?.open()
        outputStream?.open()

        inputStream?.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
        outputStream?.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
    }

    func disconnectSocket() {
        keepAliveTimer?.invalidate()
        keepAliveTimer = nil

        inputStream?.removeFromRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
        outputStream?.removeFromRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)

        inputStream?.close()
        outputStream?.close()

        inputStream?.delegate = nil
        outputStream?.delegate = nil

        inputStream = nil;
        outputStream = nil;
    }

    // MARK: - MQTT messages

    func connect() {
        let baseIntA = Int(arc4random() % 65535)
        let baseIntB = Int(arc4random() % 65535)
        let clientId = "clientid_" + String(format: "%04X%04X", baseIntA, baseIntB)

        let connectBytes: [UInt8] = [
            0x10,                               // FIXED BYTE 1   1 = CONNECT, 0 = DUP QoS RETAIN, not used in CONNECT
            UInt8(clientId.utf8.count + 12),    // FIXED BYTE 2   remaining length, client id length + 12
            0x00,                               // VARIA BYTE 1   length MSB
            0x04,                               // VARIA BYTE 2   length LSB is 4
            0x4d,                               // VARIA BYTE 3   M

            0x54,                               // VARIA BYTE 6   T
            0x04,                               // VARIA BYTE 7   Version = 4
            0x02,                               // VARIA BYTE 8   Username Password RETAIN QoS Will Clean flags
            keepAliveInterval.highByte,         // VARIA BYTE 9   Keep Alive MSB
            keepAliveInterval.lowByte,          // VARIA BYTE 10  Keep Alive LSB
            UInt16(client.utf8.count).highByte, // VARIA BYTE 11  client id length MSB
            UInt16(client.utf8.count).lowByte   // VARIA BYTE 12  client id length LSB
        ]

        let messageBytes = connectBytes + [UInt8](client.utf8)
        outputStream?.write(messageBytes, maxLength: messageBytes.count)

        clientState = MQTTClientState.Initializing
    }

    private func mqttSubscribe(topic: String) {
        messageId += 1

        let subscribeBytes: [UInt8] = [
            0x82,                               // FIXED BYTE 1   8 = SUBSCRIBE, 2 = DUP QoS RETAIN
            UInt8(topic.utf8.count + 5),        // FIXED BYTE 2   remaining length, msg id + topic length + topic
            messageId.highByte,                 // VARIA BYTE 1   message id MSB
            messageId.lowByte,                  // VARIA BYTE 2   message id LSB
            UInt16(topic.utf8.count).highByte,  // VARIA BYTE 3   topic length MSB
            UInt16(topic.utf8.count).lowByte    // VARIA BYTE 4   topic length LSB
        ]

        let requestedQosByte: [UInt8] = [
            0x00                                // Requested QoS
        ]

        let messageBytes = subscribeBytes + [UInt8](topic.utf8) + requestedQosByte
        outputStream?.write(messageBytes, maxLength: messageBytes.count)
    }

    private func mqttUnsubscribe(topic: String) {
        messageId += 1

        let unsubscribeBytes: [UInt8] = [
            0xa2,                               // FIXED BYTE 1   a = UNSUBSCRIBE, 2 = DUP QoS RETAIN
            UInt8(topic.utf8.count + 4),        // FIXED BYTE 2   remaining length, topic id length + 4
            messageId.highByte,                 // VARIA BYTE 1   message id MSB
            messageId.lowByte,                  // VARIA BYTE 2   message id LSB
            UInt16(topic.utf8.count).highByte,  // VARIA BYTE 3   topic length MSB
            UInt16(topic.utf8.count).lowByte    // VARIA BYTE 4   topic length LSB
        ]

        let messageBytes = unsubscribeBytes + [UInt8](topic.utf8)
        outputStream?.write(messageBytes, maxLength: messageBytes.count)
    }

    dynamic private func mqttPing() {
        let messageBytes: [UInt8] = [
            0xc0,                               // FIXED BYTE 1   c = PINGREQ, 0 = DUP QoS RETAIN (not used)
            0x00                                // FIXED BYTE 2   remaining length = 0
