Чтение данных последовательного порта с использованием узла js

Я хочу читать данные из последовательного порта и получать данные по запросу

Вот мой код

const http = require('http');
const hostname = 'localhost';
const { SerialPort } = require('serialport')
const { ReadlineParser } = require('@serialport/parser-readline')
const { io } = require('socket.io');
let express = require('express')

const serialPort = new SerialPort({ 
    path: 'COM4',
    baudRate: 9600 ,
})
const parser = serialPort.pipe(new ReadlineParser({ delimiter: '\r\n' }))
let app = express();
var port = 8080;

const server = http.createServer(app);

server.listen(port, hostname, () => {
  console.info(`Server running at http://${hostname}:${port}/`);
});
app.get('/get_data', function(req, res) {
    parser.on('data', function(data) {
        res.json({'weight': data});
    });
});

Когда я пытаюсь получить данные, я получаю ERR_HTTP_HEADERS_SENT: невозможно установить заголовки после их отправки клиенту Мне нужны данные последовательного порта при запросе с локального хоста: 8080/get_data, кто-нибудь может помочь?

🤔 А знаете ли вы, что...
Node.js обладает большой активной сообществом разработчиков и поддерживается множеством компаний.


39
1

Ответ:

Решено

Ваше событие данных от parser, вероятно, срабатывает более одного раза, что означает, что вы будете вызывать res.json более одного раза. Как вы можете видеть в экспресс-документация API, res.json устанавливает заголовок content-type... таким образом, вы можете вызвать его только один раз для каждого запроса. Отсюда ошибка.

Я думаю, что обычно в такой ситуации нужно установить систему очередей. Простая версия может быть выполнена с использованием массива, хотя, если вы использовали это на рабочем сервере, возможно, лучше использовать подходящую систему очередей сообщений (например, rabbitMQ, kafka, AWS SQS и т. д.).

Вот пример того, как вы можете использовать массив:

const queue = [];
parser.on('data', function(data) {
  // push new data onto end of queue (array)
  queue.push(data);
});
app.get('/get_data', function(req, res) {
  if (req.params.getFullQueue === 1) {
    // empty complete contents of current queue,
    // sent to client as an array of { weight: x } objects
    const data = queue.splice(0, queue.length)
      .map(x => ({ weight: x }));
    res.json(data);
  } else {
    // get oldest enqueued item, send it only
    res.json({ weight: queue.shift() });
  }
});

if/else в app.get предназначен для иллюстрации этих двух вариантов, в зависимости от того, что вы хотели использовать. В производственной среде вы, вероятно, захотите реализовать разбиение на страницы или, возможно, даже веб-сокет или EventSource, чтобы данные можно было передавать по мере их появления.