기본 콘텐츠로 건너뛰기

스마트팜 시스템 설계 및 구현: Arduino, SignalR, .NET MAUI 연동 가이드

 



스마트팜 시스템의 설계부터 구현까지 바로 적용할 수 있도록 구성한 예제입니다. 이 예제는 Arduino(ESP8266)에서 온도/습도 센서(DHT22)와 기타 센서 데이터를 읽어 .NET 백엔드로 전송하고, 백엔드에서는 SignalR Hub를 통해 .NET MAUI 클라이언트에 실시간 데이터를 전달하는 전체 흐름을 포함합니다.


1. 시스템 아키텍처 개요

  • Arduino (ESP8266)
    • 센서 연결: DHT22(온도, 습도) 및 필요에 따라 다른 센서를 연결
    • 데이터 전송: WiFi를 통해 HTTP POST로 센서 데이터를 .NET 백엔드 서버에 전송
  • .NET 백엔드 (ASP.NET Core + SignalR)
    • SignalR Hub: /farmHub 엔드포인트에서 클라이언트와 실시간 통신
    • API 엔드포인트: /api/sensor에서 Arduino가 전송한 센서 데이터를 수신 후, 연결된 모든 클라이언트에 브로드캐스트
  • .NET MAUI 클라이언트
    • UI 구성: 센서 데이터를 실시간으로 표시하는 간단한 UI
    • SignalR 클라이언트: 백엔드 SignalR Hub에 연결하여 데이터 수신

2. 구현 단계

2.1. .NET 백엔드 (ASP.NET Core + SignalR)

프로젝트 생성 및 코드 구성

  1. Visual Studio에서 ASP.NET Core Web API 프로젝트를 생성합니다.
  2. NuGet 패키지 추가:
    • Microsoft.AspNetCore.SignalR
    • (필요 시) Microsoft.AspNetCore.SignalR.Core

Startup.cs (또는 Program.cs – .NET 6 이상)

아래 예제는 Startup.cs를 사용하는 형태이며, .NET 6 이상은 Program.cs로 통합할 수 있습니다.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
using System.IO;
using System.Threading.Tasks;

namespace SmartFarmBackend
{
    // SignalR Hub 정의
    public class FarmHub : Hub
    {
        // 추가적인 Hub 메서드 구현 가능
    }

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSignalR();
            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                // SignalR Hub 엔드포인트
                endpoints.MapHub<FarmHub>("/farmHub");

                // Arduino 센서 데이터 수신 API
                endpoints.MapPost("/api/sensor", async context =>
                {
                    using var reader = new StreamReader(context.Request.Body);
                    var sensorData = await reader.ReadToEndAsync();

                    // 연결된 모든 클라이언트에 센서 데이터 브로드캐스트
                    var hubContext = context.RequestServices.GetService<IHubContext<FarmHub>>();
                    await hubContext.Clients.All.SendAsync("ReceiveSensorData", sensorData);

                    context.Response.StatusCode = 200;
                    await context.Response.WriteAsync("Data received");
                });
            });
        }
    }
}

실행:
이 프로젝트를 실행한 후, SignalR Hub는 https://[서버주소]/farmHub로, 센서 데이터 API는 https://[서버주소]/api/sensor로 접근할 수 있습니다.


2.2. .NET MAUI 클라이언트

프로젝트 생성 및 SignalR 클라이언트 구현

  1. Visual Studio에서 .NET MAUI 프로젝트를 생성합니다.
  2. NuGet 패키지 추가:
    • Microsoft.AspNetCore.SignalR.Client

MainPage.xaml

    
        
        
    

MainPage.xaml.cs

using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Maui.Controls;
using System;
using System.Threading.Tasks;

namespace SmartFarmMauiApp
{
    public partial class MainPage : ContentPage
    {
        HubConnection hubConnection;

        public MainPage()
        {
            InitializeComponent();
            InitializeSignalR();
        }

        async void InitializeSignalR()
        {
            // 백엔드 서버 주소를 실제 서버 주소로 변경하세요.
            hubConnection = new HubConnectionBuilder()
                .WithUrl("https://yourserveraddress/farmHub")
                .Build();

            // SignalR Hub에서 데이터 수신 시 처리
            hubConnection.On<string>("ReceiveSensorData", (data) =>
            {
                MainThread.BeginInvokeOnMainThread(() =>
                {
                    SensorDataLabel.Text = data;
                });
            });

            await ConnectToHub();
        }

        async Task ConnectToHub()
        {
            try
            {
                await hubConnection.StartAsync();
            }
            catch (Exception ex)
            {
                // 연결 실패 시 로깅 또는 재시도 로직 추가 가능
                Console.WriteLine($"SignalR 연결 실패: {ex.Message}");
            }
        }
    }
}

실행:
MAUI 앱을 실행하면 백엔드 SignalR Hub에 연결되어 Arduino에서 전송하는 센서 데이터를 실시간으로 표시합니다.


2.3. Arduino (ESP8266 + DHT22)

Arduino IDE 설정 및 라이브러리 설치

  1. 라이브러리 설치:
  2. 하드웨어 연결:
    • DHT22 센서를 ESP8266의 디지털 핀(예: D4)에 연결합니다.
    • 필요에 따라 추가 센서를 연결합니다.

Arduino 코드 예제

아래 코드는 DHT22 센서를 사용하여 온도/습도 데이터를 읽고, 주기적으로 .NET 백엔드의 /api/sensor 엔드포인트로 전송합니다.

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <DHT.h>

// DHT 센서 설정 (DHT22 사용)
#define DHTPIN D4          // 연결 핀 (필요에 따라 변경)
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

// WiFi 설정
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";

// 백엔드 서버 URL (IP 또는 도메인, 포트 포함)
const char* serverUrl = "http://yourserveraddress/api/sensor";

void setup() {
  Serial.begin(115200);
  delay(10);

  // DHT 센서 초기화
  dht.begin();

  // WiFi 연결
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected");
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    http.begin(serverUrl);
    http.addHeader("Content-Type", "text/plain");

    // 온도와 습도 읽기
    float temperature = dht.readTemperature();
    float humidity = dht.readHumidity();

    // 센서 읽기 실패 시 처리
    if (isnan(temperature) || isnan(humidity)) {
      Serial.println("DHT 센서 읽기 실패!");
      delay(2000);
      return;
    }

    // 추가 센서 데이터가 있을 경우 문자열에 포함 가능
    String sensorData = "Temperature:" + String(temperature) + ";Humidity:" + String(humidity);
    
    // 예시로 추가 센서: 토양 수분 값 (가상 값 사용)
    // int soilMoisture = analogRead(A0);
    // sensorData += ";Soil:" + String(soilMoisture);

    int httpResponseCode = http.POST(sensorData);

    if (httpResponseCode > 0) {
      Serial.printf("HTTP Response code: %d\n", httpResponseCode);
    } else {
      Serial.printf("Error code: %d\n", httpResponseCode);
    }

    http.end();
  } else {
    Serial.println("WiFi Disconnected");
  }

  // 5초마다 데이터 전송 (필요 시 간격 조정)
  delay(5000);
}

실행:

  • Arduino 보드를 업로드하고, WiFi 연결 정보를 실제 네트워크에 맞게 수정합니다.
  • 코드 실행 후, 센서 데이터가 주기적으로 백엔드 API로 전송됩니다.

3. 전체 데이터 흐름

  1. Arduino (ESP8266):
    • DHT22 센서에서 온도와 습도를 읽어 문자열 형식으로 구성
    • HTTP POST 요청을 통해 /api/sensor 엔드포인트로 전송
  2. .NET 백엔드:
    • /api/sensor 엔드포인트에서 데이터를 수신
    • SignalR Hub(/farmHub)를 통해 모든 연결된 클라이언트에 데이터 브로드캐스트
  3. .NET MAUI 클라이언트:
    • SignalR 클라이언트가 백엔드에 연결되어 실시간 센서 데이터를 수신
    • UI 라벨에 데이터를 업데이트하여 사용자에게 표시

4. 배포 및 적용 팁

  • 보안:
    • 운영 환경에서는 HTTPS 사용 및 인증/암호화 적용
    • API 엔드포인트에 토큰 인증이나 IP 화이트리스트 적용 고려
  • 에러 핸들링:
    • 각 컴포넌트에서 예외 처리 및 로깅을 추가하여 문제 상황을 추적
    • Arduino의 경우, WiFi 재연결 로직 추가 가능
  • 확장성:
    • 센서 종류가 늘어나면, API에서 JSON 형식으로 데이터를 전송하여 확장성을 고려
    • 백엔드에서는 센서별 데이터를 분리하여 저장하거나 분석하는 기능 추가
  • 테스트:
    • 각 부분을 독립적으로 테스트한 후 전체 시스템 통합 테스트를 진행
    • MAUI 앱의 경우, 실제 디바이스나 에뮬레이터에서 테스트

댓글

이 블로그의 인기 게시물

실버테크(Silver-Tech)

고령화 시대의 새로운 혁신, 실버테크(Silver Tech) 1. 실버테크란 무엇인가? 현대 사회는 빠른 속도로 고령화되고 있으며, 이에 따라 노년층을 위한 기술과 서비스가 더욱 중요해지고 있습니다. **실버테크(Silver Tech)**는 노년층의 삶의 질을 향상시키기 위해 개발된 기술과 서비스를 의미합니다. 건강 관리, 안전, 생활 편의성, 사회적 연결 등을 지원하는 다양한 혁신적인 기술이 포함됩니다. 2. 실버테크의 주요 분야 1) 헬스케어 및 원격 의료 스마트워치나 피트니스 트래커를 활용한  건강 모니터링 온라인 진료를 통해 병원 방문 없이 상담이 가능한  원격 의료 서비스 건강 상태를 분석하고 관리해주는  AI 기반 건강 관리 시스템 2) 스마트홈 및 생활 보조 기술 음성 인식으로 조작이 가능한  스마트 가전 낙상 감지 및 응급 호출 기능이 포함된  스마트 센서 노년층을 위한  자동화된 조명, 난방 시스템 3) 커뮤니케이션 및 소셜 기술 사용하기 쉬운 UI를 적용한  실버폰 및 태블릿 가족 및 친구와 소통을 쉽게 해주는  화상 통화 및 메시징 앱 노인 대상의  디지털 리터러시 교육 프로그램 4) 여가 및 엔터테인먼트 노년층을 위한  VR(가상현실) 체험 프로그램 온라인으로 제공되는  문화, 교육 콘텐츠 손쉽게 즐길 수 있는  전용 게임 및 앱 5) 이동성 및 모빌리티 솔루션 편리한 이동을 돕는  전동 휠체어 및 스쿠터 실시간 위치 추적이 가능한  스마트 네비게이션 시스템 고령자를 위한  자율주행 차량 및 호출 서비스 3. 실버테크가 가져오는 변화 - 삶의 질 향상 기술의 발전으로 인해 노년층이 더욱 독립적으로 생활할 수 있도록 도와주며, 건강하고 편리한 삶을 지원합니다. - 사회적 고립 해소 화상 통화, 소셜 네트워크, 온라인 커뮤니티 등을 통해 사회적 관계를 유지할 수 있도록 돕습니다. - 경제적 기회 창출 실버테크 산...

로또 번호 생성기

키움증권 Open API를 활용하여 갭 매매 전략 구현- C#

  1. 갭 매매 전략이란? 갭 매매란 주가가 전일 종가 대비 큰 폭으로 상승(갭업)하거나 하락(갭다운)하여 개장할 때, 발생한 갭의 움직임을 활용하여 수익을 내는 전략입니다. 이번에 소개할 전략은 다음 조건에 해당하는 종목을 대상으로 합니다. 조건검색 : 전일 대비 오늘 시가가 5% 이상 갭업으로 시작한 종목 전략 실행 : 개장 후 30분 이내에 주가가 전일 종가 수준까지 회귀하면 매수 진입 후, 갭이 완전히 메워질 때 매도합니다. 손절매 : 진입 가격에서 갭 상승분의 50% 하락 시 손절 익절매 : 갭 상승분의 50% 이상 추가 상승 시 익절합니다. 2. 구현 환경 및 준비사항 키움증권 API+ 설치 (영웅문 API) Visual Studio Community Edition (C#) 키움증권 계좌 (모의투자 계좌 추천) 3. C# 코드 전체 구현 (주석 포함) 다음 코드에는 갭 매매 전략, 주문 실행, 체결 확인 및 정정 주문까지 포함되어 있습니다. using System; using System.Collections.Generic; using AxKHOpenAPILib; public class GapTrading { private AxKHOpenAPI axKHOpenAPI; private string accountNumber; // 매수 후 체결된 정보를 저장할 Dictionary (종목코드, (체결가격, 체결수량)) private Dictionary< string , ( int price, int qty)> positions = new Dictionary< string , ( int , int )>(); public GapTradingStrategy (AxKHOpenAPI api, string accountNo) { axKHOpenAPI = api; accountNumber = accountNo; ...

Log4Net vs. Serilog 비교

🔍 Log4Net vs. Serilog 간단 비교 기준Log4NetSerilog 성능 중간 (충분하지만, 최신 라이브러리보단 느림) 빠르고 효율적 설정 방식 XML 기반 (전통적) JSON 기반 (모던함) 구조적 로깅 미지원 (기본 텍스트 로그) 강력한 구조적 로깅 지원 ASP.NET Core 통합 가능하지만 설정이 좀 복잡 간단하고 직관적 Sink(대상) 다양성 적당한 편 매우 다양하고 확장성 높음 생태계 & 유지보수 전통적, 유지보수 상태는 다소 정체 활발한 개발과 업데이트 🎯 어떤 프레임워크가 좋을까? Serilog를 추천하는 이유: 최신 기술 : ASP.NET Core와 완벽히 통합, 구조적 로깅이 뛰어나 JSON 로그 처리, 분석에 최적화됨. 높은 생산성 : 설정과 유지보수가 쉬움. 코드 기반 및 JSON 설정으로 직관적이고 빠른 개발이 가능. 확장성 : 파일, 콘솔, DB, Elasticsearch, Seq 등 다양한 Sink를 제공해 향후 확장성이 좋음. 🚀 결론 요약 Log4Net을 추천할 때Serilog를 추천할 때 기존 시스템과 호환이 필수 최신 ASP.NET Core 프로젝트 XML 설정 선호 JSON, 코드 기반 설정 선호 구조적 로깅 필요 없음 구조적 로깅과 분석 필요

C#으로 아두이노와의 시리얼 통신

  1. 들어가며 최근 IoT와 임베디드 시스템 개발이 증가하면서 PC와 아두이노 간의 통신을 효율적으로 처리하는 방법이 중요해졌습니다. 그중에서도 가장 널리 쓰이는 방법 중 하나가 바로  시리얼(Serial) 통신 입니다. 이번 글에서는 C#을 이용해 아두이노와의 시리얼 통신을 완벽히 이해하고 구현하는 방법을 자세히 소개하겠습니다. 2. 시리얼 통신이란? 시리얼 통신은 데이터를 한 번에 한 비트씩 순차적으로 전송하는 방식입니다. USB 포트를 통해 아두이노와 PC 간 데이터를 주고받을 때 주로 사용됩니다. 3. 준비물 아두이노(UNO, MEGA 등) PC 및 Visual Studio USB 케이블 4. 아두이노에서의 시리얼 통신 설정 아두이노 IDE에서 다음과 같은 코드를 작성하여 아두이노 보드에 업로드합니다. void setup () { Serial . begin ( 9600 ); // Baud rate 설정 } void loop () { if ( Serial . available ()) { char c = Serial . read (); // PC에서 받은 데이터 읽기 Serial . print ( "Received: " ); Serial . println (c); // 읽은 데이터를 다시 PC로 전송 } } 5. C#에서의 시리얼 통신 설정 C#에서는 System.IO.Ports 네임스페이스의 SerialPort 클래스를 사용합니다. 예제 코드 using System; using System.IO.Ports; class Program { static SerialPort port; static void Main () { port = new SerialPort( "COM3" , 9600 ); // 포트번호와 Baud rate 설정 port.Open(); port.DataReceived +...