[라즈베리파이] Node.js 를 이용해 간단한 서버 구축하기(4) – ESP32와 통신하기

이번에는 ESP32로부터 데이터를 받아 웹브라우저에 받은 데이터를 보여주는 코드를 구현해 보도록 하겠습니다.

ESP32가 JSON 형태로 데이터를 보내주면 서버에서는 이를 받아 파일로 저장하고 웹브라우저를 통해 사용자가 접속을 하면 저장된 데이터를 불러오는 코드입니다.

우선, HTTP 요청을 통해 들어오는 body를 파싱하기 위해 body-parser라는 모듈을 설치해야 합니다.

npm install body-parser

설치가 완료되면 다음 코드를 작성합니다.

[ index.js ]

var express = require('express')
var fs = require('fs')
var path = require('path');
var bodyParser = require('body-parser');
var app = express()

app.locals.pretty = true
app.set('views', './view_file')
app.set('view engine', 'pug')
app.use(bodyParser.json())
app.listen(3000, () => {
  console.log("Server has been started")
})

var dataFolderPath = path.join(__dirname, '/data')
var dataPath = path.join(dataFolderPath, '/data.txt') 

app.get("/", (req, res) => {
  res.redirect('/hello')
})

// 저장된 데이터가 있으면 데이터 출력
app.get("/hello", (req, res) => {
  if(!fs.existsSync(dataFolderPath) || !fs.existsSync(dataPath)) {
    res.render('hello', { title: 'Hello', message: 'Hello World!!!'})
  }
  else {
    fs.readFile(dataPath, 'utf-8', (err, data)=> {
      res.render('data', { title: 'Hello', data: data.split('\n')})
    })
  }
})

app.post("/data", (req, res) => {
  var recvData = req.body.data
  // 데이터 저장 폴더 및 데이터 저장 파일 생성
  if(!fs.existsSync(dataFolderPath)) {
    fs.mkdir(dataFolderPath)
  }

  if(!fs.existsSync(dataPath)) {
    fs.appendFile(dataPath, recvData+'\n', (error) => {
      if(error) {
        res.status(500).json({ 'msg': 'Internal server error' });
      }
      else {
        res.status(200).json({ 'msg': 'Data registered successfully' });
      }
    })    
  }
  else {
    fs.readFile(dataPath, 'utf-8', (err, data)=> {
      if(err) {
        res.status(500).json({ 'msg': 'Internal server error' });
      }
      else {
        // 10개 이상 데이터 추가 시 10개만 저장
        var dataArr = data.split('\n')
        if(dataArr.length < 10) {
          fs.appendFile(dataPath, recvData+'\n', (error) => {
            if(error) {
              res.status(500).json({ 'msg': 'Internal server error' });
            }
            else {
              res.status(200).json({ 'msg': 'Data registered successfully' });
            }
          })
        }
        else {
          dataArr.splice(dataArr.length-1, 1)
          dataArr.splice(0,dataArr.length - 9)
          dataArr.push(recvData)
          var file = fs.createWriteStream(dataPath);
          file.on('error', (err) => { if(err) console.log(err) })
          dataArr.forEach((item) => { file.write(item + '\n') })
          file.end();
          res.status(200).json({ 'msg': 'Data registered successfully' });
        }
      }
    })
  }
})

서버에서는 POST 요청에 의해 들어오는 JSON 형태의 값을 data.txt 파일에 저장하고 웹브라우저에서 http://localhost:3000/ 로 접속을 하면 data.txt  파일을 읽어와 데이터를 보여줍니다.

저장하는 데이터는 최근에 들어온 데이터 10개만 저장하도록 합니다.

[ data.pug ]

html
  head
    title= title
  body
    if data
        for val in data
            h1= val

데이터가 존재할 시 렌더링할 웹페이지를 구현한 pug 파일입니다. data 배열이 전달되면 이를 한 라인씩 화면에 출력합니다.

이로써 서버 쪽 준비는 완료되었습니다.

다음은 ESP32 에서 POST 요청을 하기 위한 코드를 짜 보도록 하겠습니다.

POST 요청 시 전송할 데이터를 JSON  형태로 만들기 위해 ArduinoJson 라이브러리가 필요합니다.

Arduino IDE 상단의 스케치 -> 라이브러리 포함하기 -> 라이브러리 관리에 들어가 ArduinoJson을 검색해 최신 Stable 버전인 5.13.2를 다운로드 받습니다.

그 후 아래와 같이 코드를 작성합니다.

[ HttpClient.ino ]

#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

const char* ssid     = "your_ssid";    // 와이파이 SSID
const char* password = "your_pw";      // 와이파이 비밀번호

void setup()
{
    Serial.begin(115200);
    delay(10);
    
    Serial.println();
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);

    WiFi.begin(ssid, password);

    // 와이파이망에 연결
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());  

}

void loop()
{
    HTTPClient http;
 
    http.begin("http://www.server_addr.com/data");        // 서버 주소
    http.addHeader("Content-Type", "application/json");

    // 랜덤 번호 생성
    esp_random();
    String num = String(random(0, 256));
    Serial.println("num : " + num);

    // JSON 데이터 생성
    StaticJsonBuffer<300> JSONbuffer;
    JsonObject& encoder = JSONbuffer.createObject();
    encoder["data"] = num;
    char buffer[300];
    encoder.prettyPrintTo(buffer, sizeof(buffer));

    // POST 후 결과 받음
    int httpResponseCode = http.POST(buffer);
    if(httpResponseCode>0){
        String response = http.getString();
        Serial.println(httpResponseCode);
        Serial.println(response);
    }else{
        Serial.print("Error on sending POST: ");
        Serial.println(httpResponseCode);
    }
 
    http.end();  // 리소스 해제
    delay(10000);
}

ESP32에서는 10초마다 한 번씩 0부터 255까지 숫자 중 하나를 랜덤하게 생성해 서버로 JSON  형태의 데이터를 전송합니다.

ESP32에 위의 코드를 업로드 하고 웹브라우저를 통해 결과를 확인하면 다음과 같이 출력됩니다.

참고자료

You may also like...