Study & Project ✏️/node.js 🐣

[socket.io] 프로젝트 준비5 - 아두이노 Socket.io

JM 2022. 2. 15. 22:40
반응형

이번 주말에는 일이 있어서 공부를 하나도 못했다.

저번 글 이후로 Socket.io를 계속 공부했었는데

Socket.io는 꾸준히, 탄탄하게 개발되고 있는 좋은 프로젝트 같다.

 

이번 글에서는

2. Sever에서 DB에 데이터 보내기

3. 아두이노에서 보내는 데이터는 다른 이름의 socket으로 보내기

4. 웹으로 아두이노 데이터 보내기

중에서


2. Sever에서 DB에 데이터 보내기

3. 아두이노에서 보내는 데이터는 다른 이름의 socket으로 보내기

를 해보겠다.

 

첫 번째 문제점

서버에서 아두이노로 데이터를 요청할 때,

setInterval()말고는 대안이 없었다는 것이었다.

 

근데 이 setInterval()을 함수로 만들어서 사용하게 되면

setInterval()을 마구 호출했을 때

마치 여러 함수를 여러 개 실행하는 현상이 발생했다.

 

간단하게 코드로 설명하자면

function startRequest() {
	setInterval(() => {
        io.emit('request',9999);
    },3000);
}

io.on('connection', (socket) => {
  socket.on('join',(nick) => {
    if(nick == "Arduino!") {
      //함수가 여러번 호출됨
      startRequest();
      console.log("Arduino is connected");
    }else {

    }
  });
 }

 

두 번째 문제점

첫 번째 상태를 해결하기 위해서

function이 아닌 변수를 호출하는 방법을 사용했을 때,

종료 메시지 없이!!!

서버가 종료되고 다시 시작하면

startRequest를 재시작하는 것이었다.

 

그래서 해결 방법은

1. 함수가 아닌 변수로 호출되게 만들었다.

2. flag를 세워서 재시작하더라도 startRequest를 재시작하지 않게 만들었다.

// socket이 connection 상태일때
io.on('connection', (socket) => {
  socket.on('join',(nick) => {
    if(nick == "Arduino!") {
      isRequest = true;
      request;
      console.log("Arduino is connected");
    }else {

    }
  });
  
  socket.on('disconnect', (nick) => {
    console.log(`${nick} disconnected`);
    if (nick == "Arduino!") {
      isRequest = false;
    } else {

    }
  });
});

아래는 해당 결과다

보면 여러 번 중복해서 호출해도 3초에 한 번만

setInterval()함수를 실행하는 걸 볼 수 있고,

종료 명령 없이 서버를 종료 후 재시작해도

flag 때문에 request소켓으로 9999를 보내지 않는다.

이제 앞에 했던 mariaDB와

이 코드들을 짬뽕시켜서 테이블 안에 넣어주겠다.

const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);

const { Server } = require("socket.io");
const io = new Server(server);

var mysql      = require('mysql');
var connection = mysql.createConnection({
  host     : 'localhost',
  user     : 'root',
  password : 'choi2350',
  database : 'testdb1'
});
connection.connect();

// localhost:3000으로 방문 시 index.html로 라우팅
app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});

var isRequest = false;

var request = setInterval(() => {
  if(isRequest) {
    io.emit('request', 9999);
    var sql = 'INSERT INTO project VALUES(\'arduino\',' + temp + ')'
    connection.query(sql, function(err, rows, fields){
      if(err){
        console.log(err);
      } else {
        console.log(rows);
      }
    });
  }
}, 3000);

var temp;

// socket이 connection 상태일때
io.on('connection', (socket) => {
  socket.on('join',(nick) => {
    if(nick == "Arduino!") {
      isRequest = true;
      request;
      console.log("Arduino is connected");
    }else {

    }
  });

  // 아두이노에서 데이터를 받는 부분
  socket.on('request', (msg) => {
    temp = msg;
    console.log(temp);
  });
  
  socket.on('disconnect', (nick) => {
    console.log(`${nick} disconnected`);
    if (nick == "Arduino!") {
      isRequest = false;
    } else {

    }
  });
});

// server는 localhost:3000
server.listen(3000, () => {
  console.log('listening on *:3000');
});

테이블 안에 데이터가 잘 쌓이는 걸 확인할 수 있다.

 

이제 남은 건 해당 데이터를 다시 웹으로 emit 해주고

html을 좀 그럴싸하게 바꿔서 포장하는 것까지 해보겠다.

 

생각보다 복잡한 프로젝트였지만 나중에 Socket.io를 사용할 때 유용할 것 같다.

 

나중에 다른 프로젝트를 하게 되면 sql의 자리에

클라우드로 데이터를 보내는 코드가 들어갈 수도 있을 것 같다.