Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix EventEmitter global to all Cam objects. #137

Merged
merged 4 commits into from
May 15, 2020

Conversation

bl0ggy
Copy link
Contributor

@bl0ggy bl0ggy commented Feb 20, 2020

Using util.inherits makes EventEmitter global to all Cam objects.
It is recommended to extend instead of using util.inherit, which fixes the problem, but it is not possible as we don't use classes.
This pull request fixes that by instantiating an EventEmitter in the Cam constructor and creating on and emit functions.
I also added a condition on listeners in _eventRequest to avoid _eventRequest/_eventPull/pullMessages loop when we unsubscribe while waiting for a pullMessages response (which is almost always the case). The listeners are also removed in unsubscribe because we could never subscribe anymore as we create a PullPointSubscription only if there is no listeners.

The code below shows that the EventEmitter is global. Also include a console.log of the listeners length here, right after Cam.prototype.on('newListener', function(name) { to see how it increases as you add more cameras.

const Cam = require('onvif').Cam;

let c1 = new Cam({
    hostname: '192.168.1.101',
    username: 'admin',
    password: 'admin',
},function(res) {
    console.log(res);
    c1.on('event', function (data) {
        console.log('c1 event', data);
    });
});
let c2 = new Cam({
    hostname: '192.168.1.102',
    username: 'admin',
    password: 'admin',
},function(res) {
    console.log(res);
    c2.on('event', function (data) {
        console.log('c2 event', data);
    });
});

To test the loop, keep only one camera with on('event'), then add a setTimeout() that will unsubscribe the camera after a while, and add console.logs at the begining of functions _eventRequest, _eventPull and pullMessages.

Jessy added 2 commits February 20, 2020 08:27
Avoid subcription loop when we unsubscribe before pullMessage returns a response.
@coveralls
Copy link

coveralls commented Feb 20, 2020

Coverage Status

Coverage decreased (-0.6%) to 86.708% when pulling be39c3d on bl0ggy:fix_static_EventEmitter into 2a7f9fe on agsh:master.

@RogerHardiman
Copy link
Collaborator

Just a thought (and I've not had much time to look at this).
But should we convert the Cam object into a proper JS Class?

@bl0ggy
Copy link
Contributor Author

bl0ggy commented Feb 20, 2020

That would be better of course, but that would break the code of people using NodeJS below v6. Maybe for version 1.0.0 of this repository.

@RogerHardiman
Copy link
Collaborator

Have invited Andrew and Chris to review

@brilthor
Copy link

@bl0ggy I'm seeing an issue with the current codebase where when multiple cam objects are created and I register to listen to each using the cam.on('event', ... after a time only one remains in the polling loop. Is this what is fixed by this MR or is that an unrelated issue?

@RogerHardiman
Copy link
Collaborator

Hi all and especially to @bl0ggy and @brilthor
@bl0ggy has done lots of Pull Requests which all look good and make lots of improvements.
I've been so busy recently since the lockdown in the UK that I've not had time to go through and merge them all yet. Sorry about that.

@brilthor
Copy link

Answering my own question above: from some initial testing it does look like this fixes the issue I described

@bl0ggy
Copy link
Contributor Author

bl0ggy commented May 15, 2020

@brilthor Yes this PR fixes the issue you explain. The problem is that the EventEmitter is common to all Cam objects. When you try to listen to event with one camera, we count how many listeners are listening to that event, if the count is 0 we create a PullPointSubscription. So when you try to listen to event with another camera, the count will not be 0 anymore as the EventEmitter is the same for all cameras, so no PullPointSubscription is created anymore.

@RogerHardiman
Copy link
Collaborator

Many thanks for the change and the PR.
Sorry it took a while to merge.

@RogerHardiman RogerHardiman merged commit 316a99b into agsh:master May 15, 2020
@agsh
Copy link
Owner

agsh commented May 15, 2020

@bl0ggy @RogerHardiman Hi! And very big sorry for the late reply and I'll maybe revert this merge.

This is definitely my huge mistake to wrote this in events.js:

Cam.prototype.on('newListener', () => { ... });

And you are absolutely right in putting subscription to the newListener event into the constructor. And this is the bug point.

But are you sure, that we need to add eventEmitter property? IMHO we can refuse it and everything should work ok. Maybe also add EventEmitter.call(this); at the top of the constructor.

@RogerHardiman
Copy link
Collaborator

Hi @agsh
Thanks for the feedback. I had a quick look at the PR, ran a test and accepted the merge after there was a 2nd user hitting the bug.

So if you need to revert and change the code, then go ahead.

@agsh
Copy link
Owner

agsh commented May 15, 2020

@brilthor @bl0ggy @RogerHardiman
I think, I found a better solution. Can you please check and review this PR #161?
If it works and fixes the problem with two and more cams it'll be great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants