Help with a Node

Hi All

I am new to node-red and have been trying to use it to connect to a BLE battery monitor. After a little scratching of my head and a lot of googling, I have managed to get the nodes to connect (using node-red-contrib-noble-bluetooth) nodes.
After leaving the flow running for a while I get the following error message:
(node:3459) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 stateChange listeners added. Use emitter.setMaxListeners() to increase limit.

I have also had:
(node:26198) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 disconnect listeners added. Use emitter.setMaxListeners() to increase limit.

I have tracked the issue to the BLE device node, but am unsure what is happening internally.

It looks like each time I deploy a change to the flow, the node disconnects from the device. I then run a scan and it reconnects. After a number of repeats I get the error messages, usually the second one. I am assuming that the code in the node is not clearing all the listeners at each disconnect/reconnect.

I am new to node.js so am not sure if its node-red or the code underneath that's causing the issue.

"
function BLEDeviceNode(config) {
RED.nodes.createNode(this,config);
var node = this;
// disconnect function
function deviceDisconnected() {
node.status({});
var msg = {}
msg.connected = false;
msg.connectable = node._peripheral.connectable;
msg.peripheral = node._peripheral.id;
msg.address = node._peripheral.address;
msg.topic = "disconnected";
node.send(msg);
}

    node.on('input', function(msg) {
        // check to see if we have a valid peripheral
        //if not then red dot
        if (!msg.peripheral) {
            node.status({ fill: "red", shape: "dot", text: "invalid peripheral id" });
            return;
        }

       // not sure what this is doing, but looks like its checking for a valid object
        if(node._peripheral) {
            node._peripheral.removeListener('disconnect', deviceDisconnected);
        }

        node._peripheral = noble._peripherals[msg.peripheral];
        //node._services = null;
        //node._characteristics = null;
        var peripheral = node._peripheral;
        peripheral.connect(function(error) {
            if (error) {
               node.error("Error connecting: " + error);
               node.status({ fill: "red", shape: "dot", text: "error connecting" });
               return;
            }
            
            msg.connected = true;
            msg.connectable = peripheral.connectable;
            msg.rssi = peripheral.rssi;

            node.on('close', function(done) {
                peripheral.disconnect();
                done();
            });
            // think this is in the wrong place
            peripheral.once('disconnect', deviceDisconnected);
                           
            node.status({ fill: "green", shape: "dot", text: "connecting" });

            peripheral.discoverAllServicesAndCharacteristics(function(error, services, characteristics) {
                if (error) {
                   node.error("Error discovering services: " + error);
                   node.status({ fill: "red", shape: "dot", text: "error finding services" });
                   return;
                }

                var services_ = [];
                //node._services = services;
                services.forEach(function(value, index, array) {
                    var service_ = {};
                    service_.uuid = value.uuid;
                    service_.name = value.name;
                    service_.type = value.type;
                    var serviceChars_ = [];
                    value.characteristics.forEach(function(value_, index_, array_) {
                        var serviceChar_ = {};
                        serviceChar_.uuid = value_.uuid;
                        serviceChar_.serviceUuid = service_.uuid;
                        serviceChar_.name = value_.name;
                        serviceChar_.type = value_.type;
                        serviceChar_.properties = value_.properties;
                        serviceChars_.push(serviceChar_);
                    });
                    service_.characteristics = serviceChars_;
                    services_.push(service_);
                });
                msg.services = services_;
                                                             
                var characteristics_ = [];
                //node._characteristics = characteristics;
                characteristics.forEach(function(value, index, array) {
                    var characteristic_ = {};
                    characteristic_.uuid = value.uuid;
                    characteristic_.serviceUuid = value._serviceUuid;
                    characteristic_.name = value.name;
                    characteristic_.type = value.type;
                    characteristic_.properties = value.properties;
                    characteristics_.push(characteristic_);
                });
                msg.characteristics = characteristics_;
                msg.topic = "connected";
                msg._peripheral = peripheral;
                node.status({ fill: "green", shape: "dot", text: "connected" });
                node.send(msg);
           });

        });

    });

    node.on('close', function(done) {
        done();
    });
}
RED.nodes.registerType("BLE device",BLEDeviceNode);

this is the node code, I have marked a couple of areas I am not sure about, but can't see where the disconnect Listner is added or removed.

Any help would be appreciated.

Thanks

That is a warning not an error. You can probably ignore it. It isn't uncommon to exceed max listeners in Node-RED though generally node authors change the setting so that it doesn't happen.

That will be correct. Because when you (re)deploy the node, it shuts itself down before starting up again. It will clear up any open events and connections as it closes. That is normal behaviour so that changing configuration in the node gives you a known position to start from.

That is certainly possible, you may wish to check in with the node's author.

Bluetooth is notoriously hard to work with so I wouldn't be surprised to see some issues. On the other hand, Node-RED is pretty robust so some small issues in a node may not have any real issues for you. A little hard to predict however. You should monitor the memory use of the device running Node-RED to see if there really is a memory leak but even if there is, it may take weeks before it shows up as anything important.

The problem is after I get the warning, I can no longer access the device until I reset it or restart the flow, so my assumption is that until I can solve the disconnect issue I can't use the nodes.

I have left a message for the author, but I don't think the nodes are being maintained anymore, but they were the only ones I could get to work.

thanks

I get your frustration. I've felt it often in the past - especially when dealing with Bluetooth which is possibly the worst collection of rubbish standards I've ever had the misfortune to look at. Not helped by the thicket in "intellectual property" patents and licenses that locks it all up either.

I only use Bluetooth for my wireless headphones - and even those don't always play nice. I found nothing else to be worth it. And they really need the special dongle since laptop Bluetooth doesn't really seem capable even with a pretty new laptop.

Last time I tried it seriously, I had my office in the loft and I could pick up random phones going past in the street 2 floors lower but couldn't pick up devices on my desk.

But don't let that put you off :grinning_face_with_smiling_eyes: