2021년 7월 6일 화요일

IoT 연결을 위한 언리얼기반 인터넷 서버 데이터 실시간 획득 방법

이 글은 IoT 연결을 위한 언리얼기반 인터넷 서버 데이터 실시간 획득 방법을 간략히 설명한다. 이 글에서 사용하는 방법을 이용해 IoT와 언리얼을 연결해, 물리 세계와 가상 세계를 연결하는 간단한 메타버스, 디지털 트윈 앱을 개발할 수 있다.

물리 세계 - 센서 - 아두이노 - 시리얼포트 - 인터넷 서버 - 언리얼 - 가상 디지털 세계

언리얼 네트워크 통신 방법은 다양하다. 제일 편한 방법은 누군가 만들어놓은 플러그인을 사용하는 것이다. 그럼 코딩없이 블루프린트에서 데이터를 교환할 수 있다. 직접 개발하려면 C++을 사용해야 한다. 이 경우, 라이센스 비용 없이 기능을 구현할 수 있고, 실무적으로는 이런 방식이 복잡한 문제인 경우 유연성이 높아 자주 사용한다.

IoT 장치와 연결하기 위해서는 다양한 데이터소스와 연결하는 프로토콜을 구현해야 한다. 데이터소스는 Serial port, Socket, Websocket, HTTPsocket, MQTT, TCP/IP, UDP 외에 MySQL, MongoDB와 같은 데이터베이스가 될 수도 있다. C++로 구현할 경우, 언리얼 개발사에서 제공하는 예제가 그리 많지 않다. 그래서, 소스코드를 확인하고, 개발 문서를 체크해야 한다.

여기서는 대표적인 방법을 설명한다.

SocketIOClient 방법
이는 기본 제공하는 SocketIOClient 컴포넌트를 블루프린트에서 개발하는 방법이다. 개발 방법을 이해하기 쉽게, IoT에서 데이터를 받아 그 값을 인터넷으로 방송하는 new wind서버를 만든다. new wind 토픽의 값은 아두이노 센서에서 얻은 데이터로 한다. 개발 순서는 다음과 같다. 

1. 아두이노를 연결하고 펌웨어 설치(파일>예제>Firmata>StandardFirmataPlus 선택 후 업로드)(참고)
2. Socket이란 이름의 블루프린터를 액터를 파생받아 생성
3. 블루프린트를 다음과 같이 코딩함 
4. 서버 개발을 위한 폴더 생성 후 node 패키지 설치
npm install --save express
npm install johnny-five --save
npm install serialport
npm i socket.io
npm i http
npm i util

5. 서버를 server.js이름으로 코딩
해당 패키지의 메뉴얼(Johnney-five manual)을 참고해, 아두이노에서 센서 데이터를 가져와 변수로 저장한 후, 코드에서 io.emit() 에 해당하는 부분에 해당 변수값을 넣어준다. 

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var util = require('util');
var five = require('johnny-five'); // nw.require('nwjs-j5-fix').fix();
var SerialPort = require("serialport");

var clients = [];

io.on('connection', function(socket){
 clients.push(socket.id);
 var clientConnectedMsg = 'User connected ' + util.inspect(socket.id) + ', total: ' + clients.length;
 console.log(clientConnectedMsg);
socket.on('disconnect', function(){
  clients.pop(socket.id);
  var clientDisconnectedMsg = 'User disconnected ' + util.inspect(socket.id) + ', total: ' + clients.length;
  console.log(clientDisconnectedMsg);
 })
});

var sensorValue = 0;
var board = new five.Board();

board.on('ready', function () {
  var sensor = new five.Sensor("A0");
  // Scale the sensor's data from 0-1023 to 0-10 and log changes
  sensor.on("change", function() {
    sensorValue = this.scaleTo(0, 1000);
    // console.log(sensorValue);
  });
});

http.listen(3000, function(){
  console.log('listening on *:3000');
});

function getRandomInRange(min, max) {
  return Math.random() * (max - min) + min;
}
function sendWind() {
 console.log('Wind sent to user: ' + sensorValue);
 io.emit('new wind', sensorValue); // getRandomInRange(0, 360));
}
setInterval(sendWind, 3000);

6. 서버 실행
node server.js

7. 언리얼 레벨에 개발된 블루프린트 socket 액터를 드래그&드롭함
8. 언리얼 플레이

다음은 개발 결과이다. 서버로 부터 데이터를 네트워크로 잘 받아오고 있는 것을 확인할 수 있다.


FSocket 방법
C++을 이용해 다음 소켓 클래스를 직접 사용해 서버와 데이터를 주고 받는다.

FSocket* Socket = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(NAME_Stream, TEXT("default"), false);

FIPv4Address ip(127, 0, 0, 1);
TSharedRef<FInternetAddr> addr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
addr->SetIp(ip.Value);
addr->SetPort(65500);

bool connected = Socket->Connect(*addr);

레퍼런스

댓글 없음:

댓글 쓰기