zabsalahid / serialport-gsm

SerialPort-GSM is a simplified plugin for communicating with gsm modems. (Primarily for sms) (Focused in PDU mode)
MIT License
88 stars 46 forks source link

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client #131

Open 94maldini opened 1 year ago

94maldini commented 1 year ago

I always get the error "node:_http_outgoing:576" and have run the solutions on the internet but nothing works, and here is the full code, please help me in this problem.

log

Modem Received: +CMGS: 160
Modem Received:
Modem Received: OK
Call callback for: 0001000C91261841438663000011F4F29C0EB2C940EA701B14A3E96034→
node:_http_outgoing:576
    throw new ERR_HTTP_HEADERS_SENT('set');
    ^

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:372:5)
    at ServerResponse.setHeader (node:_http_outgoing:576:11)
    at ServerResponse.header (C:\node\api-sms2\node_modules\express\lib\response.js:794:10)
    at ServerResponse.json (C:\node\api-sms2\node_modules\express\lib\response.js:275:10)
    at C:\node\api-sms2\index.js:25:13
    at Immediate.<anonymous> (C:\node\api-sms2\node_modules\serialport-gsm\lib\functions\modem.js:703:15)
    at processImmediate (node:internal/timers:468:21) {
  code: 'ERR_HTTP_HEADERS_SENT'
}

full code

const express = require('express');
const GSMModem = require('serialport-gsm');
const ModemMode = 'PDU'; // modem mode "sms" and "pdu"
const PortModem = 'COM6'; // modem port "com5"
const PortApp = '1234'; // port api
const app = express();

var modem = GSMModem.Modem();
let options = {
    baudRate: 9200,
    // autoDeleteOnReceive: true,
    enableConcatenation: true,
    incomingCallIndication: true,
    incomingSMSIndication: true,
    customInitCommand: 'AT+CNMI=3,1,0,0,1',
    logger: console
};

app.get('/test', (req, res) => {
    const currentTime = new Date();
    const hours = currentTime.getHours();
    const minutes = currentTime.getMinutes();
    const formattedTime = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
    modem.sendSMS("6281XXXXXXX", `test 62 time ${formattedTime}`, false, (result) => {
        res.json({
            pesan: "send masage"
        });
    });
});

modem.open(PortModem, options, function (err, result) {
    if (err) {
        console.log("error in open modem", err);
    }
    if (result) {
        console.log("modem open", result);
        modem.setModemMode((msg, err) => {
            if (err) {
                console.log(`Error Setting Modem Mode - ${err}`);
            } else {
                console.log(`Set Mode: ${JSON.stringify(msg)}`);
            }
        }, ModemMode);
    }
});

modem.on('onSendingMessage', data => {
    console.log(`Mengirim Pesan: ` + JSON.stringify(data));
});

app.listen(PortApp, () => {
    console.log(`Server berjalan di http://localhost:${PortApp}`);
});
KillerJulian commented 1 year ago

👀 I gues you should take a look to this: https://stackoverflow.com/questions/7042340/error-cant-set-headers-after-they-are-sent-to-the-client

It will not be a mistake of this library. Can it be that when res.json() is executed, the HTTP request is already timed out?

94maldini commented 1 year ago

👀 I gues you should take a look to this: https://stackoverflow.com/questions/7042340/error-cant-set-headers-after-they-are-sent-to-the-client

It will not be a mistake of this library. Can it be that when res.json() is executed, the HTTP request is already timed out?

I've done a lot of solutions that are on the internet, and what you gave me but the error still appears to me, can you fix my code?

Apollon77 commented 1 year ago

What has that to do with this library? The library is not using any HTTP or express stuff.

The callback on send is called potentially twice! Please look at the result content and act accordingy. So I assume that the first callback (which means message queued) already triggers your response sending, so the second callback call (message sent) is then triggerng the error.

94maldini commented 1 year ago

What has that to do with this library? The library is not using any HTTP or express stuff.

The callback on send is called potentially twice! Please look at the result content and act accordingy. So I assume that the first callback (which means message queued) already triggers your response sending, so the second callback call (message sent) is then triggerng the error.

yes i know that, but how to make the callback not to send second time, since i removed "onSendingMessage" the error still reappears.

why am i asking here, because i think the problem is in the callback of this repo, i have tried many ways to solve this error in various ways but this error always appears, so i ask here

Apollon77 commented 1 year ago

Please log the allback result parameter and post that log. In fact you need to add logic to only do your res.json call in ONE of the cases the callback is called. In this case the callback is defined to be executed multiple times!

94maldini commented 1 year ago

Please log the allback result parameter and post that log. In fact you need to add logic to only do your res.json call in ONE of the cases the callback is called. In this case the callback is defined to be executed multiple times!

Server berjalan di http://localhost:1234
modem open {
  status: 'success',
  request: 'connectModem',
  data: { modem: 'COM6', status: 'Online' }
}
Modem Write: AT+CMGF=0
Modem Received: AT+CMGF=0
Activate Message Processing for: AT+CMGF=0
Modem Received:
Modem Received: OK
Call callback for: AT+CMGF=0
Set Mode: {"status":"success","request":"modemMode","data":"PDU_Mode"}
Modem Write: 
Modem Write: AT+CMGS=28
Modem Received: AT+CMGS=28
Activate Message Processing for: AT+CMGS=28
Modem Received: 
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:372:5)
    at ServerResponse.setHeader (node:_http_outgoing:576:11)
    at C:\node\api-sms2\index.js:28:13
    at EventEmitter.modem.sendSMS (C:\node\api-sms2\node_modules\serialport-gsm\lib\functions\modem.js:729:7)       
    at C:\node\api-sms2\index.js:27:11
    at Layer.handle [as handle_request] (C:\node\api-sms2\node_modules\express\lib\router\layer.js:95:5)
    at next (C:\node\api-sms2\node_modules\express\lib\router\route.js:144:13)
    at Route.dispatch (C:\node\api-sms2\node_modules\express\lib\router\route.js:114:3)
    at Layer.handle [as handle_request] (C:\node\api-sms2\node_modules\express\lib\router\layer.js:95:5)
    at C:\node\api-sms2\node_modules\express\lib\router\index.js:284:15
Modem Write: 0001000C91261841438663000011F4F29C0EB2C940EA701B0483E96433→
Modem Received: > 
Mengirim Pesan: {"status":"Sending SMS","request":"sendingSMS","data":{"messageId":"Z5mfr1P1tiVzZpJMbHaaEguWH","message":"test 62 jam 00:23","recipient":"628114346836","response":"Message Currently Sending"}}
Modem Received: 
Modem Received: +CMGS: 174
Modem Received:
Modem Received: OK
Call callback for: 0001000C91261841438663000011F4F29C0EB2C940EA701B0483E96433→
node:_http_outgoing:576
    throw new ERR_HTTP_HEADERS_SENT('set');
    ^

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:372:5)
    at ServerResponse.setHeader (node:_http_outgoing:576:11)
    at C:\node\api-sms2\index.js:28:13
    at Immediate.<anonymous> (C:\node\api-sms2\node_modules\serialport-gsm\lib\functions\modem.js:703:15)
    at processImmediate (node:internal/timers:468:21) {
  code: 'ERR_HTTP_HEADERS_SENT'
}

this is the log of the result of the full code above

fkanvaly commented 6 months ago

Here is a solution that works

const express = require("express");
const bodyParser = require("body-parser");
const serialportgsm = require("serialport-gsm");

// Initialize modem
let modem = serialportgsm.Modem();
let options = {
  baudRate: 9600,
  autoDeleteOnReceive: true,
  enableConcatenation: true,
  incomingCallIndication: true,
  incomingSMSIndication: true,
  customInitCommand: "AT+CNMI=3,1,0,0,1",
  logger: console,
};

// Specify the path to your device
let path = "/dev/tty.wchusbserial1110";
modem.open(path, options, {});

modem.on("open", (data) => {
  modem.initializeModem((d) => {
    console.log("Modem initialized");
    console.log(d);
  });
});

modem.on("onSendingMessage", (result) => {
  console.log("onSendingMessage", result);
});

// Set up Express server
const app = express();
app.use(bodyParser.json());

// Define the API endpoint for sending SMS
app.get("/sendSMS", async (req, res) => {
  const { number, message } = req.query;
  if (!number || !message) {
    return res
      .status(400)
      .send("Missing number or message in query parameters");
  }

  try {
    const sendResult = await new Promise((resolve, reject) => {
      modem.sendSMS(number, message, true, (response) => {
        if (response.error) {
          reject(response.error);
        } else {
          resolve(response);
        }
      });
    });

    console.log(sendResult);
    res.send({ sendResult });
  } catch (error) {
    console.error(error);
    res.status(500).send("Failed to send message");
  }
});

// Start the server
const PORT = 3330;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});