Я хочу читать данные из последовательного порта и получать данные по запросу
Вот мой код
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, кто-нибудь может помочь?
Ваше событие данных от 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, чтобы данные можно было передавать по мере их появления.
Конечно... похоже, что в документах есть близкое мероприятие, вы можете просто обработчик этого события очистить очередь, когда это произойдет.
Могу ли я проверить, подключен ли порт в app.get()?
Мне нужны только последние данные, возвращенные из последовательного порта.
Спасибо за помощь, это работает хорошо, но есть одна проблема, когда я отключаю порт, он возвращает старые данные, возвращаемые из последовательного порта, можем ли мы это исправить?