[졸업프로젝트-2] Dummy Data Server 만들기

진행 중인 졸업프로젝트 github Organization주소입니다.

https://github.com/smu-graduation-project

제 졸업프로젝트 명은 "센서 데이터 수집 기반의 모니터링 시스템 개발" 입니다.

진행 상황

생각보다 LoRa 센서 데이터처리에 시간이 걸려 task가 분담되지 않는 문제가 발생했습니다.

때문에 Lora Data가 아닌 더미데이터를 DB에 저장하는 코드를 만들어 서버를 돌리는 방법을 진행하려고 합니다.

해당 데이터를 기반으로 백엔드, 프론트엔드 작업이 진행되고,

lora gateway의 데이터를 받아 해당 더미데이터의 형식으로 변환해서, DB에 넣는 것을 개발하는 순서로 진행할 것 같습니다.

저희 프로젝트는 실시간 데이터 모니터링 시스템이기 때문에 DB에 데이터가 초단위로 업데이트 되는 것이 중요하여, 테스트를 위해 24시간 내내 돌아갈 것을 염두하여, 다른 프레임워크를 사용하지 않고, JDBC를 기반으로 간단하게 개발을 진행하였습니다.

데이터의 구조

data typedata name설명
LongidPrimary Key로 AUOT_INCREMENT 속성을 추가하였습니다.
intportEnd Node를 구분하는 데이터로, 데이터의 종류를 구분하는 것이라고 생각하면 될 것 같습니다.
intsequence데이터의 순서입니다.
timestampdate데이터 생성 날짜입니다.
doubledata센싱 데이터(dummy) 입니다.

코드는 아래와 같습니다.

Dummy Data Class

DB에 보낼 데이터를 구성하기 위한 자료구조로,
자동으로 생성되는 id, date를 제외한 나머지 3가지 데이터를 가지고 있습니다.

public class DummyData {

    /** id, port, sequence, date, data
     * port 별로 전압, 전류, 온도, 위치 값이 다르다.
     * sequence는 순서대로 1씩 증가한다.( sequence가 중간에 없는 경우는 sensor node에서 값을 제대로 보내지 못한 것이다.)
     * date는 이후에 날짜별로 데이터를 보여줘야 하는 경우 사용하면 좋을 것 같다.
     **/
	
    // DATA
	private int port;
    private int sequence;
    private double data; // 일단 double로 설정, 실제 데이터는 다를 수 있음.
    
    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public int getSequence() {
        return sequence;
    }

    public void setSequence(int sequence) {
        this.sequence = sequence;
    }

    public double getData() {
        return data;
    }

    public void setData(double data) {
        this.data = data;
    }
}

Random Dummy Data Class

dummy data를 만들어내는 부분입니다.

총 4가지 센서를 활용해 데이터를 센싱하는 것이 프로젝트의 목표이기 때문에
각 데이터에 해당하는 값을 만들어야 했습니다.

때문에 아래와 같이 int 배열을 사용하여 처리하였습니다.

public class RandomDummyData {

    DummyData dummy = new DummyData(); // dummy data의 구조를 가지는 객체
    Random random = new Random();
   
   private int[] ports = {10,11,12,13}; // 총 4개의 data를 의미
    private int[] sequences = {1,1,1,1};

    public DummyData makeDummyData(int index) {
        dummy.setPort(ports[index]);
        dummy.setSequence(sequences[index]++);
        dummy.setData(random.nextDouble()*100);
        return dummy;
    }
    
    // table 초기화 진행시, sequence도 초기화 진행
    public void resetSequence() {
    	sequences = {1,1,1,1};
   	}
    // 데이터 누락 발생시, 테스트용
    public void addSequence(int index) {
    	sequences[index]++;
    }
    
    // 테이블 초기화시, sequence도 초기화
    public void resetData() {
    	sequences = int[] new {1,1,1,1};
    }
}

Main Class

위의 코드를 기반으로 생성된 Dummy data를 기반으로
Main 함수에서 무한 반복문을 통해 데이터를 지속적으로 DB에 저장하도록 구성하였습니다.

public class Main {
    public static int DELAYTIME = 1; //데이터 전송 주기

    public static void main(String[] args) throws Exception {

        JDBCController jdbcController = new JDBCController();
        RandomDummyData randomDummyData = new RandomDummyData();

        Reader reader = new FileReader(Main.class.getResource("").getPath()+"settingJDBC.json");
        JSONParser parser = new JSONParser();
        Object obj = parser.parse(reader);

        JSONObject settingJDBC = (JSONObject)obj;

        Random random = new Random();

        Connection conn = null;

        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection((String)settingJDBC.get("JDBCURL"), (String)settingJDBC.get("MYSQLID"), (String)settingJDBC.get("MYSQLPASSWORD"));
            Statement stmt = conn.createStatement();

        } catch (SQLException | ClassNotFoundException e) {
            e.printStackTrace();
        }

        Long id = Long.valueOf(0); // 이후 시간을 유동적으로 변경하기 위해 Long type으로 설정

        while(true) {
            // 참고 : 하루 = 86,400초
            while(id.longValue() < 100000) {
            	// 1/10000확률로 데이터를 넘기지 않는다.(sequence 문제 발생)
                int rand = random.nextInt(10000);
                // index를 기반으로 sequence, prot 설정
                if (rand != 1) {
         			jdbcController.pushDummyData(randomDummyData.makeDummyData(0), conn);			
                }               
                else {
                	randomDummyData.addSequence(0); 	
                }
                if (rand != 2) {
                	jdbcController.pushDummyData(randomDummyData.makeDummyData(1), conn);	
 				}
                else {
                	randomDummyData.addSequence(1); 	
                }
 				if (rand != 3) {
 					jdbcController.pushDummyData(randomDummyData.makeDummyData(2), conn);	
                }
                else {
                	randomDummyData.addSequence(2); 	
                }
				if (rand != 4) {
                	jdbcController.pushDummyData(randomDummyData.makeDummyData(3), conn);
                }
                else {
                	randomDummyData.addSequence(3); 	
                }
                id++;

                try {
                    // 딜레이 시간
                    TimeUnit.SECONDS.sleep(DELAYTIME);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
            // 데이터의 지속적인 누적을 막기위해 테이블을 reset.
            System.out.println("reset table");
            randomDummyData.resetData();
            jdbcController.remakeTable(conn);
            id = Long.valueOf(0);
        }
    }
}

JDBC Controller Class

JDBC Controller는 DB로 보내는 쿼리를 각각 함수로 구현하였고,
parameter로 dummyData를 받아 형식에 맞춰 데이터를 DB로 보내는 일을 하는 객체로 만들었습니다.

public class JDBCController {

    private Statement stmt;
    public void pushDummyData(DummyData dummyData, Connection conn) {
        // data 입력
        try {
            stmt = conn.createStatement();
            stmt.executeUpdate("INSERT INTO dummyData (" +
                    "port, sequence, date, data)" +
                    "values ("+dummyData.getPort()+", "+dummyData.getSequence()+", now(), "+String.format("%.3f", dummyData.getData())+");");

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    // Table 제거 및 재생성
    public void remakeTable(Connection conn) {
        dropTable(conn);
        makeTable(conn);
    }

    private void makeTable(Connection conn) {
        // 테이블 만들기 (기준은 dummyData)
        try {
            stmt = conn.createStatement();
            stmt.executeUpdate(" CREATE TABLE dummyData ( " +
                    "id INT NOT NULL AUTO_INCREMENT," +
                    "port INT NOT NULL, " +
                    "sequence  INT NOT NULL," +
                    "date TIMESTAMP NOT NULL," +
                    "data DOUBLE," +
                    "PRIMARY KEY(id));");

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private void dropTable(Connection conn) {
        // 테이블 drop
        try {
            stmt = conn.createStatement();
            stmt.executeUpdate("DROP TABLE dummyData;");

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

실행결과

실시간으로 데이터가 DB에 잘 저장되는 것을 확인 할 수 있습니다.

좋은 웹페이지 즐겨찾기