MQTT EXPLORER로 가상 데이터 뿌리기
MainWindow.xaml
<mah:MetroWindow x:Class="FakeIotDevice.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:local="clr-namespace:FakeIotDevice"
mc:Ignorable="d"
Title="Fake IOT Device" Height="500" Width="580" MinHeight="400" MinWidth="500" Closing="MetroWindow_Closing"
Loaded="MetroWindow_Loaded">
<mah:MetroWindow.IconTemplate>
<DataTemplate>
<iconPacks:PackIconSimpleIcons Kind="EclipseMosquitto" Foreground="White"
Margin="5,7,0,0" Width="24"/>
</DataTemplate>
</mah:MetroWindow.IconTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Label Content="MQTT Broker IP Address" VerticalAlignment="Center"/>
<TextBox x:Name="TxtMqttBrokerIp" Width="250" Margin="5" VerticalAlignment="Center"
mah:TextBoxHelper.Watermark="브로커 아이피를 입력하세요"/>
<Button x:Name="BtnConnect" Content="Connect" Margin="5"
Style="{StaticResource MahApps.Styles.Button.Square.Accent}" Click="BtnConnect_Click"/>
</StackPanel>
<RichTextBox Grid.Row="1" x:Name="RtbLog" Margin="10" VerticalScrollBarVisibility="Visible">
<RichTextBox.Resources>
<Style TargetType="{x:Type Paragraph}">
<Setter Property="Margin" Value="0"/>
</Style>
</RichTextBox.Resources>
</RichTextBox>
</Grid>
</mah:MetroWindow>
MainWindow.xaml.cs
using System.Windows;
using MahApps.Metro.Controls;
using Newtonsoft.Json;
using MahApps.Metro.Controls.Dialogs;
using Bogus;
using FakeIotDevice.Models;
using uPLibrary.Networking.M2Mqtt;
using System.Threading;
using System.Diagnostics;
using System.Text;
using System;
using System.Windows.Documents;
namespace FakeIotDevice
{
public partial class MainWindow : MetroWindow
{
Faker<SensorInfo> FakeHomeSensor { get;set; } = null;
MqttClient Client { get; set; }
Thread MqttThread { get; set; }
public MainWindow()
{
InitializeComponent();
InitFakeData();
}
private void InitFakeData()
{
var Rooms = new[] { "Bed", "Bath", "Living", "Dining" };
FakeHomeSensor = new Faker<SensorInfo>()
.RuleFor(s => s.Home_Id, "D101H703")
.RuleFor(s => s.Room_Name, f => f.PickRandom(Rooms))
.RuleFor(s => s.Sensing_DateTime, f => f.Date.Past(0))
.RuleFor(s => s.Temp, f => f.Random.Float(20.0f, 30.0f))
.RuleFor(s => s.Humid, f => f.Random.Float(40.0f, 64.0f));
}
private async void BtnConnect_Click(object sender, RoutedEventArgs e)
{
if(string.IsNullOrEmpty(TxtMqttBrokerIp.Text))
{
await this.ShowMessageAsync("오류", "브로커 아이피를 입력하세요");
return;
}
ConnectMqttBroker();
StartPublish();
}
private void StartPublish()
{
MqttThread = new Thread(() =>
{
while (true)
{
SensorInfo Info = FakeHomeSensor.Generate();
Debug.WriteLine($"{Info.Home_Id} / {Info.Room_Name} / {Info.Sensing_DateTime} / {Info.Temp}");
var jsonValue = JsonConvert.SerializeObject(Info, Formatting.Indented);
Client.Publish("SmartHome/IotData/", Encoding.Default.GetBytes(jsonValue));
this.Invoke(new Action(delegate ()
{
RtbLog.AppendText($"{jsonValue}\n");
RtbLog.ScrollToEnd();
}));
Thread.Sleep(1000);
}
});
MqttThread.Start();
}
private void ConnectMqttBroker()
{
Client = new MqttClient(TxtMqttBrokerIp.Text);
Client.Connect("SmartHomeDev");
}
private void MetroWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (Client != null && Client.IsConnected == true)
{
Client.Disconnect();
}
if(MqttThread!=null)
{
MqttThread.Abort();
}
}
private void MetroWindow_Loaded(object sender, RoutedEventArgs e)
{
TxtMqttBrokerIp.Focus();
}
}
}
Main 화면 디자인
MainWindow.xaml
<mah:MetroWindow x:Class="SmartHomeMonitoringApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SmartHomeMonitoringApp"
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
mc:Ignorable="d"
Title="Smart Monitoring system" Height="450" Width="800"
Loaded="MetroWindow_Loaded" FontFamily="NanumGothic">
<mah:MetroWindow.IconTemplate>
<DataTemplate>
<iconPacks:PackIconSimpleIcons Kind="HomeAssistant" Width="24" Margin="5,7,0,0" Foreground="White"/>
</DataTemplate>
</mah:MetroWindow.IconTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<Menu IsMainMenu="True" Style="{StaticResource MahApps.Styles.Menu}">
<MenuItem Header="파일">
<MenuItem.Icon>
<iconPacks:PackIconJamIcons Kind="FileF"/>
</MenuItem.Icon>
<MenuItem x:Name="MnuStartSubscribe" Header="시작">
<MenuItem.Icon>
<iconPacks:PackIconJamIcons Kind="PlayCircleF"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="MnuStopSubscribe" Header="중지">
<MenuItem.Icon>
<iconPacks:PackIconBootstrapIcons Kind="PauseCircleFill"/>
</MenuItem.Icon>
</MenuItem>
<Separator/>
<MenuItem x:Name="MnuExitProgram" Header="끝내기" Click="MnuExitProgram_Click">
<MenuItem.Icon>
<iconPacks:PackIconMaterialDesign Kind="ExitToApp"/>
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="화면">
<MenuItem.Icon>
<iconPacks:PackIconJamIcons Kind="ScreenF"/>
</MenuItem.Icon>
<MenuItem x:Name="MnuDataBaseMon" Header="DB모니터링">
<MenuItem.Icon>
<iconPacks:PackIconOcticons Kind="Database"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="MnuRealTimeMon" Header="실시간모니터링">
<MenuItem.Icon>
<iconPacks:PackIconMaterial Kind="GaugeLow"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="MnuVisualization" Header="시각화">
<MenuItem.Icon>
<iconPacks:PackIconMaterial Kind="ChartMultiline"/>
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="디자인">
<MenuItem.Icon>
<iconPacks:PackIconRemixIcon Kind="Brush2Fill"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="도움말">
<MenuItem.Icon>
<iconPacks:PackIconMaterial Kind="HelpBox"/>
</MenuItem.Icon>
<MenuItem x:Name="MnuAbout" Header="이 프로그램">
<MenuItem.Icon>
<iconPacks:PackIconBoxIcons Kind="SolidInfoCircle"/>
</MenuItem.Icon>
</MenuItem>
</MenuItem>
</Menu>
<ToolBarTray>
<ToolBar Style="{StaticResource MahApps.Styles.ToolBar}">
<Button x:Name="BtnStartSubscribe" ToolTip="구독 시작">
<iconPacks:PackIconJamIcons Kind="PlayCircleF"/>
</Button>
<Button x:Name="BtnStopSubscribe" ToolTip="구독 중지">
<iconPacks:PackIconBootstrapIcons Kind="PauseCircleFill"/>
</Button>
<Separator/>
<Button x:Name="BtnExitProgram" ToolTip="프로그램 끝내기">
<iconPacks:PackIconForkAwesome Kind="SignOut"/>
</Button>
</ToolBar>
</ToolBarTray>
</StackPanel>
<Grid Grid.Row="1">
<ContentControl x:Name="ActiveItem" Background="Gainsboro"/>
</Grid>
<StatusBar Grid.Row="2">
<StatusBarItem>SmartHome Solution</StatusBarItem>
<Separator Style="{StaticResource MahApps.Styles.Separator.StatusBar}"/>
<StatusBarItem>선택화면 :</StatusBarItem>
<StatusBarItem x:Name="StsSelScreen"></StatusBarItem>
</StatusBar>
</Grid>
</mah:MetroWindow>
실행화면