Notice
Recent Posts
Recent Comments
Link
투케이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
// --------------------------------------------------------------------------------------
반응형
'투케이2K 로직정리' 카테고리의 다른 글
Comments