Websocket connection error?

Hey there :slight_smile:

I am developing a custom node. When I do not enter valid input for rectangleItems the node succeeds, however as soon as I enter some values for rectangleItems the node stops working and I get the error in the console: WebSocket connection to 'ws://localhost:1880/comms' failed

See my code:

`var HTTPS = require('https');
var XML = require('pixl-xml');
const sihelper = require("./siwall-helper.js")
var _action = 'CreateViewAndSetOnScreen';

module.exports = function (RED) {
    function SiWallCreateViewAndSetOnScreen(config) {
        RED.nodes.createNode(this, config);
        var node = this;
        this.server = RED.nodes.getNode(config.server);
        if (this.server) {
            node.on('input', function (msg) {
                node.send("trying to start")
                if (!msg.screen) { msg.screen = config.screen }
                if (!msg.rectangleItems) { msg.rectangleItems = config.rectangleItems }
                if (msg.screen && msg.rectangleItems) {
                    // Construct SOAP request payload
                    var xmls = sihelper.SetSoapPayload(
                        _action,
                        `<v1:CreateViewAndSetOnScreen>
                            <v1:screenId>${msg.screen}</v1:screenId>
                            <v1:rectangleItems>${msg.rectangleItems}</v1:rectangleItems>
                        </v1:CreateViewAndSetOnScreen>`
                    );
                    node.send(xmls)
                    node.send("start")
                    callback = function (response) {
                        var str = ''
                        response.on('data', function (chunk) {
                            str += chunk;
                        });
                        response.on('end', function () {
                            var _xml = XML.parse(str);
                            var result = _xml['s:Body']['CreateViewAndSetOnScreenResponse']['CreateViewAndSetOnScreenResult'];
                            if (result == 'false'){
                                node.status({fill: 'red', shape: 'ring', text: result + 'check if you configured everything correctly'});                                
                            }
                            if (result == 'true'){
                                node.status({fill: 'green', shape: 'ring', text: "success"});                                
                            }
                            msg.payload = result;                       
                            node.send(msg);
                        });
                    }
                    var req = HTTPS.request(sihelper.SetSoapOptions(this.server.host, this.server.port, _action), callback);
                    req.on('error', function(err) {
                        if(err.code == 'ENOTFOUND'){
                            node.status({fill: 'red', shape: 'ring', text: 'host not reachable' });
                            msg.payload = 'Check Server Connection';
                        } else if(err.code == 'ECONNREFUSED'){
                            node.status({fill: 'red', shape: 'ring', text: 'VMS not reachable' });
                            msg.payload = 'Check if Siveillance Video Client is running';
                         } else {
                            node.status({fill: 'red', shape: 'ring', text: err.code });
                            msg.payload = err.message;
                        }
                        node.send(msg);
                    });
                    req.write(xmls);
                    req.end();
                }
                else {
                    msg.payload = 'Error: msg.screen or msg.rectangleItems not set';
                    node.status({ fill: 'red', shape: 'ring', text: msg.payload });
                    node.send(msg);
                }
            });
        }
    }
    RED.nodes.registerType("siwall-createviewandsetonscreen", SiWallCreateViewAndSetOnScreen);
}
`
`<script type="text/javascript">
    RED.nodes.registerType('siwall-createviewandsetonscreen', {
        category: 'SiWall',
        paletteLabel: 'CreateViewAndSetOnScreen',
        color: '#009999',
        defaults: {
            name: { value: "CreateViewAndSetOnScreen" },
            server: { value: "", type: "siwall-server" },
            screen: { value: 0 },
            rectangleItems: { value: "" },
        },
        inputs: 1,
        outputs: 1,
        icon: "font-awesome/fa-plus-square",
        align: 'left',
        inputLabels: "msg.screen: number, msg.rectangleItems: list of rectangleItem",
        label: function () {
            return this.name || "SiWall CreateViewAndSetOnScreen";
        },
        oneditprepare: function () {
            const scope = this;
            let screenOptions = [];

            // variables used for initizalizing icons
            let manualScreen = true;

            function manualInputScreen() {
                // GET CURRENT SELECTED VALUE
                var current = $('#node-input-screen').val();
                // REMOVE SELECT FIELD
                $('#input-select-toggle-screen').empty();
                // CREATE NEW INPUT FIELD
                $('#input-select-toggle-screen').append('<input type="number" id="node-input-screen" placeholder=0 style="width: 100%" value="' + current + '" />');
                // CHANGE BUTTON ICON
                var button = $("#node-config-input-scan-screens");
                var buttonIcon = button.find("i");
                buttonIcon.removeClass("fa-pencil");
                buttonIcon.addClass("fa-search");
            }

            function searchAndSelectScreen() {
                // Aktuell ausgewählten Server auslesen
                var server = RED.nodes.node($('#node-input-server option:selected').val());
                // View auslesen
                var current = $('#node-input-screen').val();
                // Benachrichtigung für Views Suche auslösen
                var notification = RED.notify(scope._("Searching all Screens..."), { type: "compact", modal: true, fixed: true });

                if (server) {
                    _address = server.host;
                    _port = server.port;
                    $.getJSON('siwall-getscreens?host=' + _address + '&port=' + _port, function (data) {
                        // Optionen fĂĽr dropdown vorbereiten
                        data.forEach(function (screen) {
                            //if (camera.value)
                            
                            screenOptions[screen['b:Id']] = { value: screen['b:Id'], label: screen['b:Name'] };
                        });
                    })
                        .done(function () {
                            // Alle Screens in dropdown darstellen & aktuelle vorselektieren
                            $("#node-input-screen").typedInput({
                                types: [
                                    {
                                        value: current,
                                        options: Object.values(screenOptions)
                                    }
                                ]
                            });
                            
                            // Icon von Knopf ändern
                            var button = $("#node-config-input-scan-screens");
                            var buttonIcon = button.find("i");
                            buttonIcon.removeClass("fa-search");
                            buttonIcon.addClass("fa-pencil");
                        }).fail(function () {
                            RED.notify(scope._("Request error"), "error");
                        })
                        .always(function () {
                            // CLOSE SEARCH NOTIFICATION
                            notification.close();
                        })
                }
                else {
                    //No Server configured
                    notification.close();
                    RED.notify(scope._("No Server configured"), "error");
                    return false;
                }
            }

            // TOGGLE SELECT/INPUT FIELD for Screens
            $('#node-config-input-scan-screens').click(function () {
                if (!manualScreen)  {
                    manualInputScreen();
                }
                else {
                    searchAndSelectScreen();
                }
                manualScreen = !manualScreen
            });

            // Function to add a new rectangleItem input fields
            function addRectangleItem() {
                const rectangleItemTemplate = `
                <div class="rectangle-item">
                    <div>
                        <label>Height: </label>
                        <input type="number" class="rectangle-height" required>
                    </div>
                    <br/>
                    <div>
                        <label>Width: </label>
                        <input type="number" class="rectangle-width" required
                    </div>
                    <br/>
                    <br/>
                    <div>
                        <label>X-Coordinate: </label>
                        <input type="number" class="rectangle-x" required>
                    </div>
                    <br/>
                    <div>
                        <label>Y-Coordinate: </label>
                        <input type="number" class="rectangle-y" required>
                    </div>
                    <br/>

                    <button class="delete-rectangle-item red-ui-button" type="button" style="color:red"><i class="fa fa-trash"></i></button>
                    <br/>
                    <br/>
                </div>`;

                $('#rectangleItemsContainer').append(rectangleItemTemplate);
            }

            // Function to delete a rectangleItem when the delete button is clicked
            $('#rectangleItemsContainer').on('click', '.delete-rectangle-item', function () {
                $(this).closest('.rectangle-item').remove();
            });

            // Event listener for adding a new rectangleItem
            $('#addRectangleItemBtn').click(addRectangleItem);

        },
        oneditsave: function () {
            var rectangleItemsArray = [];

            $('.rectangle-item').each(function () {
                var rectangleItem = {
                    height: $(this).find('.rectangle-height').val(),
                    width: $(this).find('.rectangle-width').val(),
                    xCoordinate: $(this).find('.rectangle-x').val(),
                    yCoordinate: $(this).find('.rectangle-y').val()
                };
                // Build rectangleItems XML based on msg.rectangleItems array
                var rectangleItemXML = `<siw:RectangleItem><siw:Height>${rectangleItem.height}</siw:Height><siw:Width>${rectangleItem.width}</siw:Width><siw:X>${rectangleItem.xCoordinate}</siw:X><siw:Y>${rectangleItem.yCoordinate}</siw:Y></siw:RectangleItem>`;

                rectangleItemsArray += rectangleItemXML
            });

            // Save the rectangleItems array into the node's configuration
            this.rectangleItems = rectangleItemsArray;
            // Calling the default oneditsave function to save other properties
            console.log(this)
            }

    });
</script>

<script type="text/html" data-template-name="siwall-createviewandsetonscreen">
<div class="form-row">
    <h2>Create View and set on Screen X</h2>
    <b>Please ensure, that the Siveillance Video Client is running,
        <br />the right user is logged in,
        <br />and the SiWall Plugin ist installed and licensed.
        <br /><br />
    </b>
</div>
    <div class="form-row">
        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
        <input type="text" id="node-input-name" placeholder="Name">
    </div>
    <div class="form-row">
        <label for="node-input-server"><i class="fa fa-server"></i> Server</label>
        <input type="text" id="node-input-server" required>
    </div>
    <div class="form-row">
        <label for="node-input-screen"><i class="fa fa-window-maximize"></i> Screen</label>
        <div style="display: inline-flex; width: 70%">
            <div id="input-select-toggle-screen" style="flex-grow: 1;">
                <input type="number" id="node-input-screen" placeholder=0 style="width: 100%" title="screen" required>
            </div>
            <button id="node-config-input-scan-screens" type="button" class="red-ui-button" style="margin-left: 10px;">
                <i class="fa fa-search"></i>
            </button>
        </div>
    </div>
    <div class="form-row">
        <h3>View Windows</h3>
        <div for="node-input-rectangleItems" id="rectangleItemsContainer">
            <!-- This container will hold dynamically added rectangleItems -->
        </div>
        <button id="addRectangleItemBtn" type="button" class="red-ui-button"><i class="fa fa-plus"></i></button>
    </div>    
    </div>

    <div class="form-row">
        <br/>
        <h3>Node Message input:</h3>
            <b>msg.screen = number</b><br/>
            &nbsp;&nbsp;&nbsp;<b>example : </b>0<br/>
            <br/>
            <b>msg.rectangleItems = list of rectangleitem</b><br/>
            <br/>
        <h3>Node Message output:</h3>
        <b>msg.payload = true / false</b><br/>
        &nbsp;&nbsp;&nbsp;<b>true : </b>Success<br/>
        &nbsp;&nbsp;&nbsp;<b>false : </b>Failed<br/>
    </div>
</script>

<script type="text/html" data-help-name="siwall-createviewandsetonscreen">
    <p>Node that creates a view and sets that on screen x</p>

    <h3>Input</h3>
    <dl class="message-properties">
        <dt>screen<span class="property-type">string</span></dt>
        <dd>
            The screen on which the view should be created.
        </dd>
    </dl>

    <h3>Outputs</h3>
    <dl class="message-properties">
        <dt>payload<span class="property-type">boolean</span></dt>
        <dd>
            It returns true if the view has been set on the desired screen.<br>
            Returns false when there was an error.
        </dd>
    </dl>
</script>

Thanks for your help!

Welcome to the forums @hansimeister

I don't know for sure.... but these lines

node.send(xmls)
node.send("start")

shouldn't they be

node.send({payload:xmls})
node.send({payload:"start"})

The editor complains when you are not sending an object, so it will seem fair, it will also apply these constraints in custom nodes

This would make sense, given it is not firing this block if there is nothing to use.

I cant see anything else wrong - unless someone can see something else - I'm in eco mode now for the winter, so ... you know... :smiley:

Thank you for your response. Unfortunately this did not resolve the websocket comms issue.. Idk what this could be other similar custom nodes do work fine

Is the runtime still running? Because I'm having trouble finding the link with RED.comms

I finally managed to resolve it. The error was in the the code where JS failed to parse the request and then it crashed the whole node-red.

Yeah, if the runtime stops, the editor shows this error