Hey there ![]()
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/>
               <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/>
           <b>true : </b>Success<br/>
           <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!