ChriD / node-raumkernel

A nodeJs lib for controlling the raumfeld multiroom system
MIT License
17 stars 7 forks source link

Multiple calls of certain functions #42

Open Alex9779 opened 6 years ago

Alex9779 commented 6 years ago

So playing with my node-red-contrib project and using it for a week now in my Home environment I realised that I might need something like a request broker managing all the calls to the kernel. Actions like adding a renderer to a zone or creating a new zone or dropping renderers from zones take "a lot of time". I managed to circumvent this on my nodes where I call an action on multiple room renderers at once by wating on the individual async calls and execute the next just when the last has finished but I have problems if I call actions against the kernel coming from different nodes at once. This can happen if I have multiple action and trigger them from the Home app or if I combine switches in the home app.

Thinking about creating an own broker where I register my nodes and queue the actions and the broker takes care of executing them all in the order they arrived I came to the conclusion that it might be better if the kernel would support this right away.

How do you handle this in your raumserver? Do you allow to send multiple requests at once or do you queue them there and send the call to the raumkernel in order? Or is that not possible with the raumserver?

ChriD commented 6 years ago

node-raumserver does allow multiple requests, it has no request stack But i am not sure what you want to achieve with your node-red project and why it's a problem there In fact its the same if you have 2 Smartphones and you start the Raumfeld android app on both of them. It would be the same problem you have.

Alex9779 commented 6 years ago

Yeah it would be but I don't want to have it in Node-Red so... The thing is that if I do it on one phone then the app waits or shows a progress it is doing something preventing you to do something else. Sometimes you can. Like selecting something to play in a room and while that room is setting up leaving the app or changing to another room, and the first action fails or does not happen or leaving the renderer in a state where it shows playing but does not. That's is all what I had. If I use a second phone and do things there it can get weird, that's true. Also with Home I have the ability to do several things at once because the app allows that and has no waiting timeout until something is finished. I hit that switch and then the other.

I want to create a backend to queue all those requests to prevent you from doing something wrong.

Take my node to play a playlist, I implemented a logic to find other zones which are already playing that playlist to not create a new zone playing the same playlist but adding the room to the zone. I wanted this because most of my renderes are close to each other and you can hear them. So if I would start a radio in one room and the same in an other and they are not in the same zone you might get that echo effect because they are playing no in synch. So I decided to check the system and add the room to that zone instead. To get switches to play a playlist in multiple rooms I changed that node to be able to get multiple room names at once, then I can handle the creation in the node itself. But when I have two button to play radio, one for each room, and I hit them both right after each other, then the first zone is not yet created but the second call also gets worked on and the result is that I get two zones. Well sometimes. Sometimes nothing gets played because the system can't handle both requests or just the last one starts playing...

That's why I thought about a broker, manager or whatever you wanna call it...

ChriD commented 6 years ago

Hmmm.. I may create a QueueManager which can handle such "queues" and which does have a "main" queue which will be processed every time if there are some items in it. But all the queueItems have to be matched to commands like the node-raumserver does with the request. This is a lot of work and there are still renderer actions without the ability to wait for their execution. So...

If you are willing to help on this stuff we may add this to the kernel. I'd create the manager and a base class for the "queueItem" and you can derive from the base class and create your queueItems for the actions you need?

Alex9779 commented 6 years ago

Hmmm sounds fine for me... I hope I can handle it... I really didn't create this issue becasue I wanted you to do all that stuff. I just thought this might be something good for the kernel too and so I decided to open the discussion.

So do you think that might be a good idea? I know this is thought a bit further even as the main Teufel app does, as I desribed earlier, because there you can actually try to do some things in a short time frame, but as also mentioned this leads to unexpected behaviour of the system...

ChriD commented 6 years ago

@Alex9779 Only to clarify, do you use the node-raumkernel or the node-raumserver? And do you have multiple instanced of node-raumkernel running or one?

Alex9779 commented 6 years ago

I am using the kernel. I do not have multiple instances of the kernel, I made a configuration node in node-red which is used by all the other nodes. That way I was able to ensure that the kernel is just loaded when there is at least one node. And all the node use that configuration node and the instance of the raumkernel of it. I might have multiple but thats just theoretical because I have the option to create multiple connections in that configuration node selecting the IP or bonjour discovery which would result in another configuration node starting another instance of the kernel. Actually as far as I can see you can setup just one Raumfeld system in one WIFI because you can't choose to create another host. You can just add to an existing and the very first device you set up is your host or you change later. I just copied that from other nodes which create connections to systems. I didn't care yet about that I should just allow the creation of one connection.

So to sum up, no in reality I will have only one instance of the raumkernel initialized in the configuration node when the first node gets configured.

For reference my project repo is here: https://github.com/Alex9779/node-red-contrib-raumfeld