Study & Project ✏️/node.js 🐣

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

JM 2022. 2. 10. 19:01
반응형

앞의 글에서는

Web(mobile) - Sever - Arduino

의 연결을 테스트했다

 

이번 글에서는 Web에서 입력한 메세지로 Arduino를 제어하는 걸 해보겠다.


오늘의 목표

3. Front에서 websocket에 접근 후 아두이노에 변동사항 적용

 

여기서 Front라고 함은 브라우저에서 입력한 데이터를 말한다.

 

연결 방향은

Front에서 입력 -> Server가 다시 클라이언트에 메세지 전달 -> 아두이노가 해석 후 동작

간단하지만 꽤 복잡하다.

우선 기본 틀에서 천천히 보자

 

Front에서 입력을 하면 Server가 받고 다시 Client에게 보내는 부분

(만약에 받은 msg와 보내는 msg의 형식이 바뀌길 원한다면

io.emit 부분의 msg를 바뀌게 만들면 될 것 같다)

 

이제 아두이노가 해당 메세지를 받는 부분

// 아두이노 안의 해당 함수를 수정하면 된다.
void socketIOEvent(socketIOmessageType_t type, uint8_t * payload, size_t length) {
  switch (type) {
    case sIOtype_DISCONNECT:
      USE_SERIAL.printf("[IOc] Disconnected!\n");
      break;
    case sIOtype_CONNECT:
      USE_SERIAL.printf("[IOc] Connected to url: %s\n", payload);

      // join default namespace (no auto join in Socket.IO V3)
      socketIO.send(sIOtype_CONNECT, "/");
      break;
    case sIOtype_EVENT:
    {		// 아두이노가 메세지를 수신하는 지점
      USE_SERIAL.printf("[IOc] get event: %s\n", payload);
      // 비교를 위해서 문자열로 되어 있는 payload를 String 형식으로 바꿔주고
      String msg = (char*)payload;
      // 아두이노가 msg를 해석하고 동작할 코드
      // msg자체를 하나의 문자열로 보고 같을 경우에 동작하는 방법1
      if (msg == "[\"chat message\",\"1\"]") {
        digitalWrite(D1, HIGH);
        delay(1000);
        digitalWrite(D1, LOW);
      // msg라는 String에서 '2'라는 문자가 있으면 index위치를, 없다면 -1를 뱉는 indexOf() 방법2
      } else if (msg.indexOf('2') != -1) {
        digitalWrite(D1, HIGH);
        delay(2000);
        digitalWrite(D1, LOW);
      }
      break;
    }
    case sIOtype_ACK:
      USE_SERIAL.printf("[IOc] get ack: %u\n", length);
      hexdump(payload, length);
      break;
    case sIOtype_ERROR:
      USE_SERIAL.printf("[IOc] get error: %u\n", length);
      hexdump(payload, length);
      break;
    case sIOtype_BINARY_EVENT:
      USE_SERIAL.printf("[IOc] get binary: %u\n", length);
      hexdump(payload, length);
      break;
    case sIOtype_BINARY_ACK:
      USE_SERIAL.printf("[IOc] get binary ack: %u\n", length);
      hexdump(payload, length);
      break;
  }
}

웹과 아두이노간의 통신은 잘 이루어진다.

웹에서 1or2를 publish 하면

짜잔~ 불이 잘 들어온다.

1초, 2초 따로 잘 들어온다.

이제 아두이노에서 메세지를 보내는 것까지 하고 마무리하자.

아두이노 시리얼 창에서 메세지를 보낼 때는

아래의 line ending 없음을 꼭 체크해주자

시리얼 창에서 메세지를 입력하고

해당 메세지를 맞는 socket에 원하는 메세지로 변환시켜서 보내겠다.

// 아두이노 코드 안의 loop문을 이렇게 수정해주면 된다.
void loop() {
  socketIO.loop();
  // 아두이노 시리얼에서 입력 후 테스트 할 부분
  if (Serial.available()) {
    char c = Serial.read();
    DynamicJsonDocument doc(1024);
    JsonArray array = doc.to<JsonArray>();

    if (c == '0') {
      // add evnet name
      // Hint: socket.on('event_name', ....
      array.add("chat message");
      array.add("ESP8266BOARD");
    } else if (c == '1') {
      array.add("chat message");
      array.add("disconnect");
    } else if (c == '2') {
      array.add("chat message");
      array.add("잘 전송 되나?");
    }
    // 만들어 놓은 구조를 바탕으로 JSON Seriallize(직렬화)
    String output;
    serializeJson(doc, output);

    //시리얼모니터에 테스트 메세지 출력(전송한 메세지 출력)
    USE_SERIAL.println(output);

    // 서버로 전송
    // ["chat message", "원하는 메세지"]
    socketIO.sendEVENT(output);
  }
}

아두이노 시리얼 창에서 테스트해보면!

 웹에서도 잘 받아지는 걸 알 수 있다.


이제 남은 건

Server에서 예를 들어 2초에 한 번씩 아두이노로 데이터를 보내라는 신호를 보내고 ->

아두이노가 데이터를 보내면 ->

서버는 받은 데이터를 웹과 DB로 보내주는 역할을 하면 된다.

 

마지막 프로젝트에서 할 일

1. DB 생성 후 CRUD구성

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

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

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