ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 아두이노의 데이터를 웹 페이지에 전송하기
    Arduino/Java Serial통신 2020. 11. 24. 19:06

    아두이노에서 데이터를 가져오는 내용은 아래의 내용에서 가지고 왔다.

    designatedroom87.tistory.com/316

     

    아두이노와 자바의 시리얼 통신(아두이노에서 자바로 0과 1을 전송)

    자바에서 시리얼 통신을 설정하지 않았다면 아래의 글을 참고하자. designatedroom87.tistory.com/315 Java 시리얼 통신 기본 설정 아래의 사이트에서 다운을 받는다. rxtx.qbang.org/wiki/index.php/Download#x64..

    designatedroom87.tistory.com

     

    PC(JAVA) - 하드웨어 값을 WEB SERVER로 전송
    전송을 하는 수단을 URL요청을 통해 데이터를 전송
    JAVA Serial 통신은 콘솔창으로 대부분 제어하므로 값을 확인하기가 불편
    그래서 단순히 제어값을 오고 가는 용도로 사용
    데이터를 웹 상에서 확인하면 편하므로 웹 브라우저를 이용하여 데이터를 확인한다.
    PC(WEB 브라우저) - WEB SERVER에 접속하고 데이터를 데이터베이스를
    실시간으로 확인하는 작업을 하게 된다.

     

     

    아두이노의 데이터를 웹 페이지에 전송하기 위해서는 프로젝트를 새로 만들어야 한다.

    마우스 우클릭해서 New에서 Dynamic Web Project를 선택하고 Next를 선택한다.

    아래와 같이 프로젝트 이름을 적고 Next를 선택한다. 그리고 Next를 선택한다.

     

    그리고 아래와 같이 web.xml을 체크한다. 그리고 Finish를 선택한다.

     

    SerialCom 프로젝트의 lib 폴더의 RXTXcomm.jar 파일과 rxtxSerial.dll 파일을 복사해서 

    현재 프로젝트의 WebContent/WEB-INF/lib 폴더에 붙여넣는다.

    그리고 두 가지 설정을 해야 한다.

    1. 자바 시리얼 기본 설정 하기

    designatedroom87.tistory.com/315?category=903927

     

    Java 시리얼 통신 기본 설정

    자바에서는 Serial을 바로 사용하지 못한다. 그래서 자바가 하드웨어적으로 단독적으로 사용하지 못해서 C언어의 도움을 받아야 한다. 아래의 사이트에서 다운을 받는다. rxtx.qbang.org/wiki/inde

    designatedroom87.tistory.com

    2. 현재 프로젝트 외의 다른 프로젝트의 서버를 종료하고 현재의 프로젝트 서버만 실행하고 설정하기

    아래의 글을 조금만 내려가 보면 설정하는 방법이 있다.

    designatedroom87.tistory.com/313

     

    MVC(Model View Control)2

    아래의 내용을 먼저 보도록 하자. designatedroom87.tistory.com/310?category=901206 MVC(Model View Control)1 아래의 내용을 살펴보자. designatedroom87.tistory.com/303?category=901206 게시판 만들기 우선,..

    designatedroom87.tistory.com

     

     

    일단, 0~9까지의 데이터를 자바로 송신하는 내용이다. 아래의 내용을 복사해서 아두이노에 업로드하자.

    그리고 업로드 시에 PORT 번호를 반드시 확인하자.

    아래는 소스는 0과 1을 반복적으로 전송하는 부분인데, 이 부분을 아두이노에 업로드를 했다.

    아두이노 소스 파일

    더보기
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
      Serial.write('0');
    
      delay(1000);
    
      Serial.write('1');
    
      delay(1000);
    }

     

    아두이노 소스 파일

    delay를 2000으로 준 이유는 1000을 주면 자바에서 두 번 읽어들이므로 2000을 주면 한 번씩 읽어들인다.

    (1000을 넣고 결과를 확인해보자.)

    더보기
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
    }
    
    char g_Num = '0';
    
    void loop() {
      // put your main code here, to run repeatedly:
      Serial.write(g_Num++);
    
      if (g_Num > '9')
        g_Num = '0';
        
      delay(2000);
    }

     

     

    웹과 아두이노의 통신이 가능하다.
    웹 요청이 오면 컨트로럴가 시리얼로부터 데이터를 달라고 요청한다.
    이 데이터를 가지고 view를 만들어서 다시 클라이언트에게 전송하면 된다.

     

    아두이노가 데이터(0~9) 전송하고 자바가 이를 수신해서 웹 상으로 전송하려는 것이다. 

    자바에서 http URL 요청으로 웹에 보낸다.
    보낼 data가 9라고 한다면 http://localhost.9090/serialdata?data=9로 실어서 보낸다.

    데이터를 보낼 때, 위의 URL을 보내서 data값만 받아서 처리하면 된다.
    이 방식이 가장 쉬울 듯하다.

     

    자바에서 Main.java를 실행하면 된다. 데이터의 입력에 따라 F5를 눌러 데이터 값을 갱신한다.

    F5를 누르기 싫으면 웹 소켓을 이용하면 된다.

    이는 나중에 한다.

     

    WEB-INF폴더에 serial 폴더를 하나 만들자. WEB-INF/serial에 index.jsp파일을 만든다.

    아래의 jsp파일의 용도는 아두이노에서 얻은 데이터를 출력할 웹 페이지이다.

    index.jsp 파일 내용

    더보기
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>Hello</title>
    	<link href='http://fonts.googleapis.com/css?family=Lato:100' rel='stylesheet' type='text/css'>
    	<style>
    		body {
    			background-color: hsl(0, 60%, 65%);
    			transition: background-color 1s;
    		}
    
    		h1 {
    			font-family: 'Lato', sans-serif;
    			font-size: 120px;
    			font-weight: 100;
    			color: white;
    			text-align: center;
    			margin: 60px;
    		}
    
    		h1:before{
    			content: attr(class) ":";
    			font-size: 22px;
    			position: relative;
    			top: -69px;
    			left: 0;
    			text-transform: uppercase;
    		}
    </style>
    </head>
    <body>
    	<h1 class="data">${data}ºC</h1>
    </body>
    </html>

     

    그리고 기존의 파일에 두 개의 Controller 서블릿이 필요하다.

    src폴더의 하위에 패키지를 하나 만드는데 이름을 serial 이라 하고, 여기에 서블릿 파일들을 만든다.

    SerialController.java

    더보기
    package serial;
    
    import java.io.IOException;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet("/serial")
    public class SerialController extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
    	public void init(ServletConfig config) 
    			throws ServletException {}
    
    	protected void service(HttpServletRequest request, HttpServletResponse response) 
    			throws ServletException, IOException {
    		
    		//	데이터의 내용을 index.jsp에게 넘긴다.
    		//request.setAttribute("data", DataProc.getRecvData());
    		//System.out.println("data : " +DataProc.getRecvData());
    		
    		RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/serial/index.jsp");
    		
    		//	페이지로 밀어주는 작업
    		dispatcher.forward(request, response);
    	}
    	
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
    			throws ServletException, IOException {}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
    			throws ServletException, IOException {}
    }

    SerialDataController.java

    더보기
    package serial;
    
    import java.io.IOException;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet("/serialdata")
    public class SerialDataController extends HttpServlet {
    	private static final long serialVersionUID = 1L;
        
    	public void init(ServletConfig config) throws ServletException {
    			}
    	
    	protected void service(HttpServletRequest request, HttpServletResponse response) 
    			throws ServletException, IOException {
    		System.out.println("접속");
    		
    		//	1. 데이터를 받는다.
    		String data = request.getParameter("data");
    		
    		System.out.println("url data : " +data);
    		
    		//	받은 데이터를 웹 브라우저로 보내줘야 하는데, 들어온 데이터를 전역 저장소 객체(내장 객체)에 저장한다.
    		//	이 서버에 데이터가 저장 된다.
    		ServletContext app = request.getServletContext();
    		
    		app.setAttribute("data", data);
    	}
    
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
    			throws ServletException, IOException {}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
    			throws ServletException, IOException {}
    }

     

     

    아래의 5개의 자바 파일은 앞에서 한 내용이다.

    약간 내용이 바뀐 부분이 있다.

    5개의 파일들은 모두 src/serial에 만들도록 한다.

    DataProc.java

    더보기
    package serial;
    
    public class DataProc {
    	String recvData;
    	public DataProc() {}
    		
    	public void print() {
    		System.out.println("DataProc:"+recvData);
    	}
    	
    	public void setRecvData(String recvData) { this.recvData=recvData; }
    
    	public String getRecvData() {return recvData;}
    }

     

    아래의 Main.java에서 connect메소드에는 반드시 아두이노의 PORT 번호가 입력해야 한다.

    Main.java

    더보기
    package serial;
    
    public class Main {
    	public static void main(String[] args) 
    	{
    		try {
    			
    			(new Serial()).connect("COM6");
    		}
    		catch(Exception e) 
    		{
    			e.printStackTrace();
    		}
    	}
    }

    Serial.java

    더보기
    package serial;
    
    import java.io.InputStream;
    import java.io.OutputStream;
    
    import gnu.io.CommPort;
    import gnu.io.CommPortIdentifier;
    import gnu.io.SerialPort;
    
    public class Serial 
    {
    	void connect(String port) 
    	{
    		CommPort commPort = null;
    		SerialPort serialPort = null;
    		
    		try 
    		{
    			CommPortIdentifier com = CommPortIdentifier.getPortIdentifier(port);
    			
    			//	com포트를 확인하는 작업
    			if (com.isCurrentlyOwned())
    				System.out.println("Error : "+port +"포트를 사용중입니다.");
    			
    			//	포트가 열려있으면
    			else
    			{
    				commPort = com.open(this.getClass().getName(),2000);
    				
    				//	획득한 포트를 객체가 사용할 수 있는지 여부 확인
    				if (commPort instanceof SerialPort)	//	commPort가 SerialPort로 사용할 수 있는지 확인
    				{
    					serialPort = (SerialPort)commPort;
    					
    					//	정상적으로 포트를 사용할 수 있을 경우
    					//	포트에 필요한 정보를 입력해 준다.
    					serialPort.setSerialPortParams(
    							9600,						//	바운드레이트 
    							SerialPort.DATABITS_8, 
    							SerialPort.STOPBITS_1, 
    							SerialPort.PARITY_NONE);	//	오류제어 비트
    				}
    				System.out.println("comport성공");
    				
    				InputStream in = serialPort.getInputStream();
    				OutputStream out = serialPort.getOutputStream();
    				
    				(new Thread(new SerialRead(in))).start();
    				new Thread(new SerialWrite(out)).start();
    			}
    		}	//	end try
    		catch(Exception e) {}
    	}
    }

     

    SerialRead.java

    자바에서 바로 Web Server로 직접 가지 못한다.
    자바에서 웹 서버 접속을 url활용
    자바에서 웹으로 가기 위해서는 소켓을 만들던 인터페이스가 필요하다.
    String targetURL = "http://localhost:9090/serialdata?data="+s;
    serialdata라는 url로 s라는 데이터를 전송한다.

    URL url = new URL(targetURL); <- url을 하나 만든다. 
    만들어진 url을 open한다.

    tcp/ip통신이므로 

    while((temp=br.readLine())!=null) { }

    conn.disconnect();

    br.close();

    위의 세 문장이 필요하다.

    즉, 몇 번의 데이터 송/수신 후에 종료가 되어야 한다. 

    더보기
    package serial;
    import java.io.*;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    /*
    	아두이노가 데이터(0~9) 전송하고 자바가 이를 수신해서
    	웹 상으로 전송하려는 것
    	
    	자바에서 http URL 요청으로 웹에 보낸다.
    	보낼 data가 9라고 한다면 
    	http://localhost.9090/serialdata?data=9로 실어서 보낸다
    	데이터를 보낼 때, 위의 URL을 보내서 data값만 받아서 처리하면
    	가장 쉬울 듯하다.
    	
    	SerialRead 클래스가 데이터를 읽어오는 클래스이다.
    	
    	서버를 실행하면 "접속" 이라고 뜬다.
    */
    
    //	값을 읽는 클래스로, 이는 Thread로 구현해야 한다.
    public class SerialRead implements Runnable
    {
    	InputStream in;
    	
    	public SerialRead(InputStream in){this.in = in;}
    	
    	@Override
    	public void run() 
    	{
    		byte[] buffer = new byte[1024];
    		int len = -1;
    		
    		try 
    		{
    			//	buffer에 저장하고나서, 그 길이를 반환한다.
    			while ((len = this.in.read(buffer)) > -1)
    			{
    				//	System.out.println(new String(buffer,0,len));
    				//	new DataProc(new String(buffer,0,len));
    				String s = new String(buffer,0,len);
    				/*
    				if (len != 0) 
    					new DataProc(s);
    				*/
    				HttpURLConnection conn = null;
    				
    				//	들어온 데이터가 있는 경우에만 동작을 한다.
    				if (len != 0) 
    				{
    					//	데이터를 url 형태로 변형시킨다. s가 데이터이다.
    					System.out.println(s);
    					
    					String targetURL = "http://localhost:9090/serialdata?data="+s;
    					
    					System.out.println(targetURL);
    			
    					URL url = new URL(targetURL);	//	URL은 String클래스와 비슷하나, 파싱까지 해준다.
    					
    					try 
    					{
    						//	http에 접속
    						conn = (HttpURLConnection) url.openConnection();	//	소켓을 열겠다는 요청
    						
    						//	스트림을 통해 데이터를 받는다.
    						BufferedReader br = new BufferedReader(
    								new InputStreamReader(conn.getInputStream()));
    						
    						String temp = null;
    						
    						while ((temp = br.readLine()) != null) {}
    						
    						br.close();
    						conn.disconnect();
    					}
    					catch(Exception e) {}
    				}
    			}
    		} 
    		catch (IOException e) {e.printStackTrace();}
    	}
    }

    SerialWrite.java

    더보기
    package serial;
    import java.io.IOException;
    import java.io.OutputStream;
    
    public class SerialWrite implements Runnable 
    {
    	OutputStream out;
    	
    	public SerialWrite(OutputStream out) {this.out = out;}
    	
    	@Override
    	public void run() 
    	{
    		int c = 0;
    		
    		try 
    		{
    			while ((c = System.in.read()) > -1)
    			{
    				out.write(c);
    			}
    		} catch (IOException e) {e.printStackTrace();}
    	}
    }

     

    2개의 파일을 실행시켜야 한다.

    반드시 아두이노에 소스 파일이 업로드되어 있어야 한다.

    우선 Main.java를 선택하고 우클릭을 해서 아래의 그림과 같이 Java Application을 실행해야 한다.

    아래는 콘솔 창의 결과로 0,1 데이터가 차례로 입력되어야 하는데 10이 나오는 이유는

    한 번에 1과 0의 데이터를 동시에 읽어 들인 결과이다.

    아두이노에서 delay함수를 1000이 아닌 2000으로 설정하면 된다.

    수정한 아두이노 소스 파일은 아래에 있다.

    그리고 SerialController.java 파일을 선택해서 우클릭 해서 Run on Server를 실행한다.

    그리고 F5을 누르면 0과 1이 번갈아 웹 페이지에 표시됨을 알 수 있다.

    아래는 각 각 웹 페이지의 결과들이다.

    그리고 2개의 파일을 실행했으므로, 2번 종료를 해줘야 한다.

    아래와 같이 오른쪽 붉은 사각형을 클릭하고 나서, Console 창으로 이동한다.

    아래와 같이 Terminate해줘야 한다.

     

    수정한 아두이노 소스 파일

    기존의 delay함수의 매개변수를 1000이 아닌 2000으로 설정하면 된다.

    더보기
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
      Serial.write('0');
    
      delay(2000);
    
      Serial.write('1');
    
      delay(2000);
    }

     

     

     

    아두이노와 포텐시오미터를 연결해서 포텐시오미터의 값을 읽어 웹에 전송하는 것도 가능하다.

    실행하는 순서는 위와 같다.

    우선 아래는 아두이노의 소스이다.

    아두이노 소스 파일

    더보기
    //  A0핀을 입력핀으로 설정
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
    }
    
    //  포텐시오미터의 값을 리턴하는 함수
    int PotenValue()
    {
      return analogRead(A0);
    }
    
    char str[8];
    
    void loop() {
      // put your main code here, to run repeatedly:
      // Serial.write("123");
      //  String sNum = "123";  Serial.println(sNum.toInt());
      int poten = PotenValue();
    
      sprintf(str,"%d",poten);
      
      Serial.write(str);
      
      //Serial.println();
      
      delay(2000);  //  2초 지연해야 자바에서 데이터를 한 번씩 읽어들인다.
    }

     

     

    위에서 아두이노가 보내온 데이터를 읽어 웹 페이지에 갱신하기 위해서 F5를 계속 눌러서 새로고침을 하였는데

    이를 코딩으로 제어해보자. 즉 실시간 데이터 전송받기가 가능하다.

     

    WEB-INF/serial/index.jsp 파일을 수정하면 된다.

    그리고 아두이노 소스는  0~ 9를 출력하는 내용을 업로드 하자.

    index.jsp

    더보기
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>Hello</title>
    	<link href='http://fonts.googleapis.com/css?family=Lato:100' rel='stylesheet' type='text/css'>
    	<style>
    		body {
    			background-color: hsl(0, 60%, 65%);
    			transition: background-color 1s;
    		}
    
    		h1 {
    			font-family: 'Lato', sans-serif;
    			font-size: 120px;
    			font-weight: 100;
    			color: white;
    			text-align: center;
    			margin: 60px;
    		}
    
    		h1:before{
    			content: attr(class) ":";
    			font-size: 22px;
    			position: relative;
    			top: -69px;
    			left: 0;
    			text-transform: uppercase;
    		}
    </style>
    </head>
    
    <body>
    	<h1 class="data">${applicationScope.data}ºC</h1>
    	<script>
    	
    	setInterval(function(){location.href="/serial"}, 1000);
    	
    	</script>
    </body>
    
    </html>

     

    아두이노 소스 파일

    더보기
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
    }
    
    byte i = '0';
    
    void loop() {
      // put your main code here, to run repeatedly:
      Serial.write(i++);
    
      if (i == '9')
          i = '0';
    
      delay(2000);
    }

     

    Main.java를 실행하고 나서, SerialController.java를 실행하면 된다.

    댓글

Designed by Tistory.