투케이2K

128. (TWOK/LOGIC) [Ios] NWConnection 사용해 Broker MQTT 특정 topic Subscribe 구독 및 QOS 설정 로직 본문

투케이2K 로직정리

128. (TWOK/LOGIC) [Ios] NWConnection 사용해 Broker MQTT 특정 topic Subscribe 구독 및 QOS 설정 로직

투케이2K 2024. 12. 3. 19:43

[로직 정리]

정리 로직 : Ios / 아이폰

상태 : [Ios] NWConnection 사용해 Broker MQTT 특정 topic Subscribe 구독 및 QOS 설정 로직

 

[설 명]

 

// --------------------------------------------------------------------------------------
[사전) 설정 및 정보 확인 사항]
// --------------------------------------------------------------------------------------

- Broker MQTT 통신을 수행하기 위한 IP , PORT 정보 확인 필요


- 사전) 위치 권한 설정 필요


- NWConnection 설명 :

  >> NWConnection 는 로컬 엔드포인트와 원격 엔드포인트 간의 양방향 데이터 연결 (TCP , UDP) 을 수행할 수 있습니다

  >> NWConnection 를 사용하기 위해서는 import Network 패키지 호출 정의가 필요합니다

  >> NWParameters 설정 가능 옵션 : 

   - tls
   - tcp
   - dtls
   - udp
   - quic
   - quicDatagram

  >> 참고 사이트 : https://developer.apple.com/documentation/network/nwconnection

// --------------------------------------------------------------------------------------






// --------------------------------------------------------------------------------------
[로직 설명]
// --------------------------------------------------------------------------------------

1. 애플리케이션 실행 및 MQTT 통신을 수행할 수 있는 화면 진입


2. MQTT 클래스 화면에서 lazy 선언으로 NWProtocolTCP.Options , NWParameters 옵션 설정 수행 

  >> TimeOut 설정으로 연결 대기 제한 시간 설정


3. IP , PORT 정보 사용해 NWConnection 객체 초기화 URL 지정 및 설정한 옵션 값 지정 수행 >> 연결 요청 실시

  >> nwConnection?.start(queue: .global())


4. 연결 완료 상태를 감지하기 위한 stateUpdateHandler 이벤트 감지 핸들러 등록 및 ready 준비 완료 상태 확인


5. stateUpdateHandler 핸들러에서 준비 완료 상태가 된 경우 MQTT 연결 옵션을 설정하기 위한 send 정보 전달 수행

    // ---------------------------------------------
    // [패킷 정보]
    // ---------------------------------------------
    var clientId = "twok01234567892k"
    // ---------------------------------------------
    var packet = [UInt8]()
    packet.append(0x10) // [CONNECT Control Packet type]
    let variableHeader: [UInt8] = [
        0x00, 0x04, // [Length of "MQTT 3.1.1"]
        0x4D, 0x51, 0x54, 0x54, // ["MQTT"] : "MQTT".utf8
        0x04,       // [Protocol Level (4 for MQTT 3.1.1)]
        0x02,       // [Connect Flags (Clean session)]
        0x00, 0xB4  // [Keep Alive (180 seconds)] : 클라이언트와 브로커간 연결 상태 유지 값 : Hex To Dec
    ]
    let clientIdBytes = Array(clientId.utf8) // [클라이언트 아이디]
    let payload = UInt16(clientIdBytes.count).bigEndianBytes + clientIdBytes
    let remainingLength = UInt8(variableHeader.count + payload.count)
    packet.append(remainingLength)
    packet.append(contentsOf: variableHeader)
    packet.append(contentsOf: payload)
    // ---------------------------------------------


6. 연결 요청 패킷 전달 후 error 없이 최종 성공 완료 된 경우 연결 완료 상태 Flag 플래그 값 True 변경 수행


7. 연결 완료 플래그 값 변경 후 실시간 메시지 수신 상태 감지를 위한 특정 토픽 (topic) Subscribe 구독 수행 send 메시지 전송

    // ---------------------------------------------
    // [패킷 정보]
    // ---------------------------------------------
    var topic = "twok"
    var qos = 0
    // ---------------------------------------------
    var packet = [UInt8]()
            
    // [Fixed Header] : [고정 헤더 영역]
    packet.append(0x82) // SUBSCRIBE control packet type

    // [Variable Header] : [가변 헤더 영역]
    let packetIdentifier: UInt16 = 1 // [Packet Identifier (고유 ID)]
    let packetIdentifierMSB = UInt8((packetIdentifier >> 8) & 0xFF)
    let packetIdentifierLSB = UInt8(packetIdentifier & 0xFF)
    var variableHeader: [UInt8] = [packetIdentifierMSB, packetIdentifierLSB]

    // [Payload] : [메시지 전송 페이로드]
    let topicBytes = self.encodeString(topic) // [Topic 이름 UTF-8 인코딩]
    let qosByte = qos // [QoS Level]
    var payload: [UInt8] = topicBytes + [qosByte]

    // [Remaining Length]
    let remainingLength = variableHeader.count + payload.count
    packet.append(contentsOf: self.encodeRemainingLength(remainingLength))

    // [Variable Header + Payload 추가]
    packet.append(contentsOf: variableHeader)
    packet.append(contentsOf: payload)
    // ---------------------------------------------


8. 정상적으로 특정 토픽 구독이 완료 된 경우 >> 실시간 메시지를 수신 받기 위한 receiveData 리시버 핸들러 등록 수행

    nwConnection?.receive(minimumIncompleteLength: 1, maximumLength: 1024, completion: { data, _, isComplete, error in
                    
        // ---------------------------------------------
        // MARK: [실시간 메시지 수신 확인]
        // ---------------------------------------------

        if let data = data, !data.isEmpty {
            let message = String(data: data, encoding: .utf8) ?? ""
            
            let emptyCheck = message.replaceAll(_string: " ", _replace: "")
            if C_Util().stringNotNull(str: emptyCheck) == true {
                
                // ---------------------------------------------
                // MARK: [데이터 패킷 파싱 수행 및 토픽 , 메시지 구분 수행]
                // ---------------------------------------------
                let bytes = [UInt8](data)

                // [PUBLISH 패킷인지 확인 (Packet Type: 0x3)]
                /*
                let packetType = bytes[0] >> 4
                if packetType == 3 {
                    handlePublishPacket(data: bytes)
                }
                // */
                
                // [Variable Header: Topic 이름 파싱]
                let topicLength = (UInt16(bytes[2]) << 8) | UInt16(bytes[3])
                let topicStartIndex = 4
                let topicEndIndex = topicStartIndex + Int(topicLength)
                let topic = String(bytes: bytes[topicStartIndex..<topicEndIndex], encoding: .utf8) ?? "Unknown Topic"

                // [Payload: 메시지 내용]
                let payloadStartIndex = topicEndIndex
                let payload = String(bytes: bytes[payloadStartIndex...], encoding: .utf8) ?? "Unknown Payload"
                
                
                // ---------------------------------------------
                // MARK: [로그 출력 수행]
                // ---------------------------------------------
                S_Log._W_(description: "[Ing] ---- [MQTT 실시간 메시지 수신 감지] ---- [Ing]", data: [
                    "TOTAL :: \(message)",
                    "TOPIC :: \(topic)",
                    "MSG :: \(payload)"
                ])
                
                
                // ---------------------------------------------
                // MARK: [로직 분기 처리]
                // ---------------------------------------------
                
            }
        }

        
        // ---------------------------------------------
        // MARK: [계속해서 실시간 메시지 수신 처리]
        // ---------------------------------------------
        if isComplete {
            C_Broker_Mqtt_NWConnection_Client_Module.RECEIVE_ERROR_LOG = "[Error] : Connection closed by Broker"
            
            S_Log._E_(description: "MQTT 실시간 메시지 수신 감지 에러", data: [
                "M_LOG :: \(C_Broker_Mqtt_NWConnection_Client_Module.RECEIVE_ERROR_LOG)"
            ])            
            
        } else if let error = error {
            C_Broker_Mqtt_NWConnection_Client_Module.RECEIVE_ERROR_LOG = "[Error] : let error catch"
            
            S_Log._E_(description: "MQTT 실시간 메시지 수신 감지 에러", data: [
                "M_LOG :: \(C_Broker_Mqtt_NWConnection_Client_Module.RECEIVE_ERROR_LOG)",
                "Description :: \(error)"
            ])
            
        } else {
            
            // ---------------------------------------------
            // [계속해서 데이터 수신]
            // ---------------------------------------------
            self.receiveData()
            
        }
    })

// --------------------------------------------------------------------------------------






// --------------------------------------------------------------------------------------
[참고 사이트]
// --------------------------------------------------------------------------------------

[Ios - NWConnection 설명 및 TCP IP 소켓 통신 연결 및 데이터 전송 방법]

https://blog.naver.com/kkh0977/223670153413


[Ios - NWConnection 사용해 TCP IP 소켓 통신 NWProtocolTCP.Options 옵션 설정 방법]

https://blog.naver.com/kkh0977/223672535940


[Ios - NWConnection 사용해 TCP IP 소켓 통신 연결 후 stateUpdateHandler 연결 상태 확인 방법]

https://blog.naver.com/kkh0977/223672601987


[Ios - NWConnection 사용해 Broker 브로커 MQTT 연결 방법]

https://blog.naver.com/kkh0977/223678381489


[Ios - NWConnection 사용해 Broker 브로커 MQTT 메시지 publish send 전송 방법]

https://blog.naver.com/kkh0977/223678384631


[Ios - NWConnection 사용해 Broker 브로커 MQTT 메시지 subscribe 구독 방법]

https://blog.naver.com/kkh0977/223678387123

// --------------------------------------------------------------------------------------

 

반응형
Comments