question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Error: No valid WebSocket class provided

See original GitHub issue

Good morning,

I am trying to add the reconnect websocket to my code, but the debug of the red node gives me the error “Error: No valid WebSocket class provided”

my code is this:

`const WS = require(‘ws’); const WebSocket = require(‘ws’); const uuidv4 = require(‘uuid/v4’); const events = require(‘events’); const EventEmitter = events.EventEmitter; const Logger = require(‘./utils/logdata’); const debug = require(‘debug’)(‘anl:ocpp:cp:server:json’); const ReconnectingWebSocket = require(‘reconnecting-websocket’); let ee = new EventEmitter(); module.exports = function(RED) { ‘use strict’; function OCPPChargePointJNode(config) { RED.nodes.createNode(this, config); debug(‘Starting CP client JSON node’); const CALL = 2; const CALLRESULT = 3;

// for logging...
const msgTypeStr = ['unknown', 'unknown', 'received', 'replied', 'error'];

const msgType = 0;
const msgId = 1;
const msgAction = 2;
const msgCallPayload = 3;
const msgResPayload = 2;
var obj = require('./global.json'); 
var node = this;

node.reqKV = {};

this.remotecs = RED.nodes.getNode(config.remotecs);
this.url = obj.url;
this.cbId = obj.cbId;
this.ocppVer = this.ocppver;
this.name = obj.nombre || config.name || this.remotecs.name;
this.command = config.command;
this.cmddata = config.cmddata;
this.logging = config.log || false;
this.pathlog = config.pathlog;

const options = {
    WebSocket: WS, // custom WebSocket constructor
    connectionTimeout: 1000,
    maxRetries: 10,
};

const logger = new Logger(this, this.pathlog, this.name);
logger.enabled = (this.logging && (typeof this.pathlog === 'string') && this.pathlog !== '');

let csUrl = `${this.url}/${this.cbId}`;

logger.log('info', `Realizando conexion websocket a ${csUrl}`);

let rws = new ReconnectingWebSocket(csUrl, options);

ws.on('open', function(){
  logger.log('info', `Connectado a ${csUrl}`);
  node.log(`Connectado a ${csUrl}`);
  debug(`Connectado a ${csUrl}`);
  node.status({fill: 'green', shape: 'dot', text: 'Conectado...'});
  node.wsconnected = true;
});
ws.on('terminate', function(){
  logger.log('info', `Closing websocket connectio to ${csUrl}`);
  node.log(`Conexion terminada a ${csUrl}`);
  debug(`Conexion terminada a ${csUrl}`);
  node.status({fill: 'red', shape: 'dot', text: 'Cerrado...'});
  node.wsconnected = false;
});
ws.on('close', function() {
  logger.log('info', `Closing websocket connectio to ${csUrl}`);
  node.status({fill: 'red', shape: 'dot', text: 'Cerrado...'});
  node.wsconnected = false;
});
ws.on('error', function(err){

  node.log(`Error de Websocket: ${err}`);
  debug(`Error de Websocket: ${err}`);
});

ws.on('message', function(msgIn) {
  debug('Got a message ');
  let msg = {};
  msg.ocpp = {};
  msg.payload = {};

  msg.ocpp.ocppVersion = '1.6j';

  let response = [];
  let id = uuidv4();

  let msgParsed;


  if (msgIn[0] != '[') {
    msgParsed = JSON.parse('[' + msgIn + ']');
  } else {
    msgParsed = JSON.parse(msgIn);
  }

  logger.log(msgTypeStr[msgParsed[msgType]], JSON.stringify(msgParsed));

  if (msgParsed[msgType] == CALL) {
    debug(`Got a CALL Message ${msgParsed[msgId]}`);
    // msg.msgId = msgParsed[msgId];
    msg.msgId = id;
    msg.ocpp.MessageId = msgParsed[msgId];
    msg.ocpp.msgType = CALL;
    msg.ocpp.command = msgParsed[msgAction];
    msg.payload.command = msgParsed[msgAction];
    msg.payload.data = msgParsed[msgCallPayload];

    let to = setTimeout(function(id) {
      // node.log("kill:" + id);
      if (ee.listenerCount(id) > 0) {
        let evList = ee.listeners(id);
        let x = evList[0];
        ee.removeListener(id, x);
      }
    }, 1000, id);

    // This makes the response async so that we pass the responsibility onto the response node
    ee.once(id, function(returnMsg) {
      clearTimeout(to);
      response[msgType] = CALLRESULT;
      response[msgId] = msgParsed[msgId];
      response[msgResPayload] = returnMsg;

      logger.log(msgTypeStr[response[msgType]], JSON.stringify(response).replace(/,/g, ', '));

      ws.send(JSON.stringify(response));

    });
    node.status({fill: 'green', shape: 'dot', text: `message in: ${msg.ocpp.command}`});
    debug(`${ws.url} : message in: ${msg.ocpp.command}`);
    node.send(msg);
  } else if (msgParsed[msgType] == CALLRESULT) {
    debug(`Got a CALLRESULT msgId ${msgParsed[msgId]}`);
    msg.msgId = msgParsed[msgId];
    msg.ocpp.MessageId = msgParsed[msgId];
    msg.ocpp.msgType = CALLRESULT;
    msg.payload.data = msgParsed[msgResPayload];

    if (node.reqKV.hasOwnProperty(msg.msgId)){
      msg.ocpp.command = node.reqKV[msg.msgId];
      delete node.reqKV[msg.msgId];
    } else {
      msg.ocpp.command = 'unknown';
    }

    node.status({fill: 'green', shape: 'dot', text: `response in: ${msg.ocpp.command}`});
    debug(`response in: ${msg.ocpp.command}`);
    node.send(msg);

  }

});

ws.on('ping', function(){
  debug('Got Ping');
  ws.send('pong');
});
ws.on('pong', function(){
  debug('Got Pong');
});



this.on('input', function(msg) {

  if (node.wsconnected == true){

    let request = [];
    let messageTypeStr = ['unknown', 'unknown', 'request', 'replied', 'error'];

    debug(JSON.stringify(msg));

    request[msgType] = msg.payload.msgType || CALL;
    request[msgId] = msg.payload.MessageId || uuidv4();

    if (request[msgType] == CALL){
      request[msgAction] = msg.payload.command || node.command;

      if (!request[msgAction]){
        const errStr = 'ERROR: Missing Command in JSON request message';
        node.error(errStr);
        debug(errStr);
        return;
      }


      let cmddata;
      if (node.cmddata){
        try {
          cmddata = JSON.parse(node.cmddata);
        } catch (e){
          node.warn('OCPP JSON client node invalid payload.data for message (' + msg.ocpp.command + '): ' + e.message);
          return;
        }

      }

      request[msgCallPayload] = msg.payload.data || cmddata || {};
      if (!request[msgCallPayload]){
        const errStr = 'ERROR: Missing Data in JSON request message';
        node.error(errStr);
        debug(errStr);
        return;
      }

      node.reqKV[request[msgId]] = request[msgAction];
      debug(`Sending message: ${request[msgAction]}, ${request}`);
      node.status({fill: 'green', shape: 'dot', text: `request out: ${request[msgAction]}`});
    } else {
      request[msgResPayload] = msg.payload.data || {};
      debug(`Sending response message: ${JSON.stringify(request[msgResPayload])}`);
      node.status({fill: 'green', shape: 'dot', text: 'sending response'});
    }
    
    logger.log(messageTypeStr[request[msgType]], JSON.stringify(request).replace(/,/g, ', '));

    ws.send(JSON.stringify(request));
  }
});

this.on('close', function(){
  node.status({fill: 'red', shape: 'dot', text: 'Closed...'});
  logger.log('info', 'Websocket closed');
  debug('Closing CP client JSON node..');
  ws.close();
});

} // register our node RED.nodes.registerType(‘CP client JSON’, OCPPChargePointJNode); };`

Thank you very much for your possible help

Cheers!

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:10

github_iconTop GitHub Comments

4reactions
Makeshiftcommented, Feb 22, 2021

I’m also confused as how to actually use this library. An incredibly basic invocation that I’d expect to work given the docs is:

const WS = require("ws");
const ReconnectingWebSocket = require("reconnecting-websocket");
const ws = new ReconnectingWebSocket("wss://<url>/", { WebSocket: WS });

However, this fails with the error in the title.

It appears that no matter what, getGlobalWebSocket is called during connection, which is weird as I just tested this syntax and it works in vanilla JavaScript at least (that is, getGlobalWebSocket is not called if this._options has a populated WebSocket:

const {
            maxRetries = DEFAULT.maxRetries,
            connectionTimeout = DEFAULT.connectionTimeout,
            WebSocket = getGlobalWebSocket(),
        } = this._options;

Unfortunately I’m not really able to dig into this as the compiled JS is horrible to debug and I haven’t got anything set up to debug TS, but it appears that _options isn’t available within the _connect function.

EDIT:

Nevermind, I’m just dumb.

const WS = require("ws");
const ReconnectingWebSocket = require("reconnecting-websocket");
const ws = new ReconnectingWebSocket("wss://<url>/", [], { WebSocket: WS });
1reaction
chrisn-aucommented, Jun 14, 2020

Ok, the addEventListener callback simply takes an event object as a parameter. So I believe it should be

ws.addEventListener('close', (event) => {
              let code = event.code;
              let reason = event.reason;
              console.log('Event: close', code, reason)
              EventHandler('close', resStream.id, resStream.postTo, ws, { code, reason })
            })

Let me know how it goes

Read more comments on GitHub >

github_iconTop Results From Across the Web

reconnecting-websocket - UNPKG
The CDN for reconnecting-websocket. ... 83, function CloseEvent(code, reason, target) { ... 506, throw Error('No valid WebSocket class provided');.
Read more >
pladaria/reconnecting-websocket | Build 162 - Coveralls.io
Returns true if given argument looks like a WebSocket class ... throw Error('No valid WebSocket class provided');
Read more >
reconnecting-websocket - npm
Start using reconnecting-websocket in your project by running `npm i ... So this documentation should be valid: MDN WebSocket API.
Read more >
WebSocketError Enum (System.Net.WebSockets)
Indicates the WebSocket is an invalid state for the given operation (such as being closed or aborted). NativeError, 3. Indicates that an unknown...
Read more >
WebSockets work without valid authorization token (Spring ...
... 403 error code if no valid token was provided when connecting to SockJS. I add this security configuration to my project: public...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found