🔎 유용한 정보
1. 강의 개요
이번 강의에서는 MQTT(Message Queuing Telemetry Transport) 프로토콜을 활용하여 IoT 애플리케이션을 제작합니다.
MQTT는 경량 메시징 프로토콜로, 제한된 네트워크 환경에서도 실시간 데이터 통신이 가능합니다.
IoT 장치 간 메시지를 송수신하며, Windows Forms 애플리케이션을 통해 데이터를 관리하고 실시간 업데이트하는 방법을 배웁니다.
2. 학습 목표
- MQTT 클라이언트를 사용하여 브로커와 통신 구현
- IoT 메시지를 발행(Publish) 및 구독(Subscribe)
- 실시간으로 수신된 데이터를 UI에 표시
- Mosquitto와 같은 MQTT 브로커를 활용
3. 기능 요구사항
필수 기능
1️⃣ 브로커 연결:
- MQTT 브로커에 연결 및 연결 해제
2️⃣ 메시지 발행(Publish):
- 특정 주제로 메시지를 발행
3️⃣ 메시지 구독(Subscribe):
- 구독한 주제의 메시지를 실시간으로 수신
4️⃣ UI 표시:
- 수신된 메시지를 ListBox에 표시
4. 실습: MQTT 클라이언트 애플리케이션 제작
1️⃣ 사전 준비
- MQTT 브로커 설치:
- Mosquitto MQTT 브로커를 설치하거나,
무료 클라우드 MQTT 서비스(HiveMQ, Eclipse Mosquitto)를 사용하세요.
- Mosquitto MQTT 브로커를 설치하거나,
- NuGet 패키지 설치:
- Visual Studio에서 MQTTnet 패키지를 설치합니다.
- MQTTnet은 .NET용 MQTT 클라이언트 라이브러리입니다.
2️⃣ 폼 구성
- 폼(Form) 이름: Form1
- 컨트롤 배치
컨트롤 타입 이름 위치 크기
TextBox | txtBrokerUrl | 폼 상단 왼쪽 | (300 x 30) |
Button | btnConnect | 폼 상단 중앙 | (100 x 30) |
TextBox | txtTopic | 폼 중앙 왼쪽 | (300 x 30) |
Button | btnSubscribe | 폼 중앙 오른쪽 | (100 x 30) |
TextBox | txtMessage | 폼 하단 왼쪽 | (300 x 30) |
Button | btnPublish | 폼 하단 오른쪽 | (100 x 30) |
ListBox | lstMessages | 폼 하단 전체 | (400 x 200) |
📌 폼 디자인 예시:
--------------------------------------------------
| [Broker URL: TextBox] [Connect 버튼] |
--------------------------------------------------
| [Topic: TextBox] [Subscribe 버튼] |
--------------------------------------------------
| [Message: TextBox] [Publish 버튼] |
--------------------------------------------------
| [ListBox - 메시지 표시] |
--------------------------------------------------
3️⃣ 코드 작성
(1) MQTT 클라이언트 구현
using System;
using System.Text;
using System.Windows.Forms;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Client.Options;
namespace WindowsFormsApp_MQTT
{
public partial class Form1 : Form
{
private IMqttClient _mqttClient;
public Form1()
{
InitializeComponent();
}
// MQTT 브로커 연결
private async void btnConnect_Click(object sender, EventArgs e)
{
string brokerUrl = txtBrokerUrl.Text.Trim();
if (string.IsNullOrEmpty(brokerUrl))
{
MessageBox.Show("브로커 URL을 입력하세요.", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
try
{
var mqttFactory = new MqttFactory();
_mqttClient = mqttFactory.CreateMqttClient();
var mqttOptions = new MqttClientOptionsBuilder()
.WithTcpServer(brokerUrl) // 브로커 URL 설정
.WithCleanSession()
.Build();
_mqttClient.UseConnectedHandler(e =>
{
Invoke(new Action(() => lstMessages.Items.Add("브로커에 연결되었습니다.")));
});
_mqttClient.UseDisconnectedHandler(e =>
{
Invoke(new Action(() => lstMessages.Items.Add("브로커 연결이 종료되었습니다.")));
});
_mqttClient.UseApplicationMessageReceivedHandler(e =>
{
string topic = e.ApplicationMessage.Topic;
string message = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
Invoke(new Action(() => lstMessages.Items.Add($"[{topic}] {message}")));
});
await _mqttClient.ConnectAsync(mqttOptions);
}
catch (Exception ex)
{
MessageBox.Show($"연결 실패: {ex.Message}", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
(2) 메시지 구독 및 발행
// MQTT 메시지 구독
private async void btnSubscribe_Click(object sender, EventArgs e)
{
string topic = txtTopic.Text.Trim();
if (string.IsNullOrEmpty(topic))
{
MessageBox.Show("구독할 주제를 입력하세요.", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (_mqttClient == null || !_mqttClient.IsConnected)
{
MessageBox.Show("브로커와 연결되지 않았습니다.", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
try
{
await _mqttClient.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic(topic).Build());
lstMessages.Items.Add($"구독 시작: {topic}");
}
catch (Exception ex)
{
MessageBox.Show($"구독 실패: {ex.Message}", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
// MQTT 메시지 발행
private async void btnPublish_Click(object sender, EventArgs e)
{
string topic = txtTopic.Text.Trim();
string message = txtMessage.Text.Trim();
if (string.IsNullOrEmpty(topic) || string.IsNullOrEmpty(message))
{
MessageBox.Show("주제와 메시지를 입력하세요.", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (_mqttClient == null || !_mqttClient.IsConnected)
{
MessageBox.Show("브로커와 연결되지 않았습니다.", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
try
{
var mqttMessage = new MqttApplicationMessageBuilder()
.WithTopic(topic)
.WithPayload(message)
.WithAtLeastOnceQoS()
.Build();
await _mqttClient.PublishAsync(mqttMessage);
lstMessages.Items.Add($"발행 완료: [{topic}] {message}");
}
catch (Exception ex)
{
MessageBox.Show($"발행 실패: {ex.Message}", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
(3) Designer 코드
private void InitializeComponent()
{
this.txtBrokerUrl = new TextBox();
this.btnConnect = new Button();
this.txtTopic = new TextBox();
this.btnSubscribe = new Button();
this.txtMessage = new TextBox();
this.btnPublish = new Button();
this.lstMessages = new ListBox();
// Broker URL TextBox 설정
this.txtBrokerUrl.Location = new System.Drawing.Point(10, 10);
this.txtBrokerUrl.Size = new System.Drawing.Size(300, 30);
// Connect Button 설정
this.btnConnect.Location = new System.Drawing.Point(320, 10);
this.btnConnect.Size = new System.Drawing.Size(100, 30);
this.btnConnect.Text = "Connect";
this.btnConnect.Click += new EventHandler(this.btnConnect_Click);
// Topic TextBox 설정
this.txtTopic.Location = new System.Drawing.Point(10, 50);
this.txtTopic.Size = new System.Drawing.Size(300, 30);
// Subscribe Button 설정
this.btnSubscribe.Location = new System.Drawing.Point(320, 50);
this.btnSubscribe.Size = new System.Drawing.Size(100, 30);
this.btnSubscribe.Text = "Subscribe";
this.btnSubscribe.Click += new EventHandler(this.btnSubscribe_Click);
// Message TextBox 설정
this.txtMessage.Location = new System.Drawing.Point(10, 90);
this.txtMessage.Size = new System.Drawing.Size(300, 30);
// Publish Button 설정
this.btnPublish.Location = new System.Drawing.Point(320, 90);
this.btnPublish.Size = new System.Drawing.Size(100, 30);
this.btnPublish.Text = "Publish";
this.btnPublish.Click += new EventHandler(this.btnPublish_Click);
// ListBox 설정
this.lstMessages.Location = new System.Drawing.Point(10, 130);
this.lstMessages.Size = new System.Drawing.Size(400, 200);
// Form 설정
this.ClientSize = new System.Drawing.Size(450, 350);
this.Controls.Add(this.txtBrokerUrl);
this.Controls.Add(this.btnConnect);
this.Controls.Add(this.txtTopic);
this.Controls.Add(this.btnSubscribe);
this.Controls.Add(this.txtMessage);
this.Controls.Add(this.btnPublish);
this.Controls.Add(this.lstMessages);
this.Text = "MQTT 클라이언트 애플리케이션";
}
4️⃣ 실행 결과
1️⃣ 브로커 연결
- 브로커 URL 입력 후 "Connect" 버튼 클릭 → 브로커 연결 성공
2️⃣ 메시지 구독
- 주제 입력 후 "Subscribe" 클릭 → 해당 주제의 메시지 수신
3️⃣ 메시지 발행
- 주제와 메시지 입력 후 "Publish" 클릭 → 메시지가 브로커를 통해 발행
5. 주요 개념 요약
- MQTTnet: .NET용 MQTT 클라이언트 라이브러리
- Subscribe: 특정 주제의 메시지를 수신
- Publish: 특정 주제에 메시지 전송
- QoS: 메시지 전달 품질 보장 수준
📌 #CSharp #WindowsForms #MQTT #IoT #실시간통신 #MQTTnet
'📁 [4] 개발자 정보 & 코드 노트 > C#' 카테고리의 다른 글
C# Windows Forms 강의 76편: CSV 데이터를 기반으로 한 데이터 분석 애플리케이션 (0) | 2025.04.20 |
---|---|
C# Windows Forms 강의 75편: 실시간 대시보드 - 센서 데이터를 활용한 시각화 (0) | 2025.04.19 |
C# Windows Forms 강의 73편: SignalR 클라이언트를 활용한 실시간 채팅 애플리케이션 제작 (0) | 2025.04.17 |
C# Windows Forms 강의 73편: SignalR 클라이언트를 활용한 실시간 채팅 애플리케이션 제작 (0) | 2025.04.16 |
C# Windows Forms 강의 72편: WebSocket을 활용한 실시간 양방향 통신 (0) | 2025.04.15 |
🔎 유용한 정보