-
Notifications
You must be signed in to change notification settings - Fork 13
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
New to Ember.Net - advice needed #18
Comments
Strange, you should be able to get exactly the same notifications through the dynamic Interface as you do through the static interface (it's the same implementation after all).
For this purpose you will need to subscribe to the PropertyChanged event of all parameters. |
I've parsed the tree down to the Parameter level and attached a handler to the PropertyChanged event. After changing the same parameter value in TinyEmber+, the PropertyChanged event does not fire. Re-reading the documentation it says that the consumer will automatically send GetDirectory commands to get updates for all declared parameters. If you could update your dynamic console application example to show this working that would be great. |
On a slightly different subject - I used the sample code to try and walk a Junger frame at a customer site and it threw and exception with: "The remote host has failed to answer a KeepAliveRequest within half the timeout period". The Enmber+ Viewer can connect and I am able to view the tree. However, in the message window it reports a Glow Error: Glow DTD version mismatch: found version 2.10, expected 2.31! |
http://lawo.github.io/ember-plus-sharp/html/7cdb703a-14dd-42d3-8ea2-28a9b8af6663.htm |
The standard keep-alive timeout is 3 seconds. Some providers struggle to answer KA requests when they are busy, please see whether increasing the timeout changes anything. http://lawo.github.io/ember-plus-sharp/html/7345C981.htm
I'm not the author of the Ember+ Viewer, but I believe you can safely ignore that message. |
I assume this has been resolved. If not, feel free to reopen. |
Yes, thank you. With our driver architecture I will investigate the S101 interface as I need a more polling style approach |
You can do polling with Ember+ Sharp, I just don't understand why you'd want that? Can you please explain? |
The drivers run as hidden console applications. They handle multiple physical devices with each Device being polled at a custom frequency. When the polling is due, a worker thread is launched that runs to completion. I'd therefore want to create the connection to the Ember device on start-up (or after an error), and then read the contents of the configured tree items during the poll task. |
You can certainly do that, namely by awaiting Consumer.CreateAsync and then immediately calling Consumer.Dispose. You can still call the Consumer.Root getter afterwards and process the retrieved data. However, as you might have noticed already, Consumer.CreateAsync is often rather resource-hungry, especially for large trees. This is because the data describing the part of the tree you are interested in needs to be queried, received and parsed. But, after this initial setup phase, only changes are sent back and forth, which tends to be orders of magnitude cheaper. So, if at all possible, I would advise you to keep your Consumer objects connected, which gives you immediate access to all the current data when the polling is due. |
Thanks. I did run tests based on your description above but I only got updated parameter data if I disposed of the consumer and then re-created it (I can't await the on-change method described in the documentation as it blocks until the data changes). If I still use the consumer approach I will look to implement a static interface to greatly reduce the number of tree elements. |
No, if you keep your consumer alive then the values of all parameters should always be identical to the values of their respective provider parameters. Changes are automatically and continually propagated back and forth until you call Consumer.Dispose(). If that doesn't work for you then this sounds like a bug.
If I understand your scenario correctly, then you don't have to wait for the PropertyChanged event to fire. In your polling handler, you'd simply take the already existing Consumer object and grab whatever data you need from the tree and process it (remember that all properties of all elements are continually kept in sync). |
OK, I'll re-run my test and if it doesn't work I'll post the code here. Thanks again! |
Quick question: To implement the polling interval, are you by any chance calling Thread.Sleep? |
Yes, it was used in my previous test where I created a loop to monitor the tree values. |
Ahh, this is almost certainly the problem then. Thread.Sleep blocks the current thread, which is something you should almost never do in code that uses async and await. Please try something like |
Good spot! Using Task.Delay allows the tree updates to come through (it shows my lack of knowledge of the async environment). I'll need to think about a different driver implementation as the code has to be wrapped by an AsyncPump.Run() and this doesn't exit unless the client/consumer is disposed. I could implement a poll-style with static elements to reduce the tree size but connecting/disconnecting seems every inefficient and will put a needless load on the remote device. The other approach is to have the AsyncPump.Run() active for the lifetime of the driver. Now that I am getting updates this seems the best approach. |
Right, you must call both
Correct. |
Using the updated test application to try against a real Junger frame, I am getting an error of form: 'The provider failed to send the children for the element with the path..." |
The default for the buffer size of 8192 should be adequate for pretty much all applications.
That's probably not necessary either...
Yes, most likely you need to increase the default of 10000 passed to |
I've set all timeouts to 60000 and now I don't get an error but the Consumer.CreateAsync hasn't returned (after apprimately 5 minutes of waiting). The Ember+ Viewer can connect and view all items. Note that the Junger Frame has 20 modules present. |
Hmm, that's odd. Can you please share the snippet of code that you use to connect? Thanks. |
Please find attached log file as requested: |
Thank you very much, this confirms my suspicion. I will fix this as soon as I can. |
No problem. Thank you for your support. |
The bug should be fixed. As expected, the performance hit is rather hefty (+~70%). I will try to optimize this further. May I ask you to try again with the current release? Thanks for your patience! |
Using the static tree data is being returned 👍 |
Depending on how long you can afford to wait for
Not currently, but it shouldn't be too hard to implement. |
Let me clarify: There's no way to use the static interface programmatically. After all, the compiler must know the types so that you can access their properties in your program. However, the dynamic interface can be extended, so that only the relevant nodes are requested from the provider. |
This was my understanding. It would be the most efficient approach for my driver interface too. Is this something you could implement in the near future? |
Define "near future" ;-). Seriously, I'm currently swamped with other work, but I'll probably have something usable in two weeks. Can you test and implement with the static interface in the mean time? |
If you could have something to test in two weeks that would be fantastic - I am not wishing to add to your stress levels and thank you for your continued support. I can perform some more basic testing but with the configurable nature of our system there can be many permutations of driver setup so the static approach isn't really a viable solution. |
BTW, have you had a look at the mixed interface part of the tutorial yet? Depending on how configurable your system is, the mixed interface approach could help you to confine the full retrieval of data to the branches you're interested in. |
I have taken another look at the mixed mode. I would need to perform a detailed site survey to review how all the frames are populated (currently not all the equipment has Ember enabled). This would only be a temporary solution as it would be fixed for one manufacturer. |
Ok, understood. I'll let you know as soon as I have something usable. |
As always, things took longer than anticipated. Now that I'm on it, it turns out that #21 will require quite a bit of effort to get right. With all the other stuff that's currently on my plate, I'm afraid it will be at least another two weeks before I might have something for you to try. Sorry! |
Ok. Thanks for your continued support. |
I've pushed a commit that shows how the interface for #21 will probably look like. If you like, you can have a look at:
|
It looks like I'm done. Please have a look at the new release and let me know whether the new feature works as you would expect. Here are direct links to the documentation:
|
Sorry, I've been busy on other projects. I'll try and test this later today. Thanks |
Sorry for the delay. I've rebuilt by solution and confirmed that by testing with TinyEmber the original approach works. I'm trying to understand how I define the items I am interested in. For example, using the Sapphire example, if I just wanted to access "Sapphire/Sources/FPGM 1/Fader/dB Value" and "Sapphire/Sources/FPGM 2/Fader/dB Value" how would this be achieved? |
In the Main Method you'd call CreateAsync and pass ChildrenRetrievalPolicy.DirectOnly. When CreateAsync returns, the Children property of Consumer.Root will contain the node with the identifier "Sapphire", but the "Sapphire" node itself does not yet have any children. You'd then set the ChildrenRetrievalPolicy property of the "Sapphire" node to ChildrenRetrievalPolicy.DirectOnly and await Consumer.SendAsync. When SendAsync returns the Children property of the "Sapphire" should contain its direct children (the nodes "identity" and "Sources"). You'd then repeat the process with the "Sources" node and so forth until you have all children you are interested in. |
Perfect. I'll implement and report back |
This is working fine with TinyEmber 👍 . I'll now test it with a Junger frame |
Congratulations! 👍 |
Thank you so much for your support |
You're welcome, I'm glad I could help. |
I've gone through the console application tutorial and can parse the tree loaded into TinyEmber+. I'm struggling to get data changes once running - creating a handler for PropertyChanged of a Parameter is not getting called. I can get a data update by using the same method as described in the static approach to reacting to changes. However, my driver will need to receive all parameter changes for a dynamic environment. I am wondering if I am missing a trick to get my consumer updated? I am running the Ember+ Viewer and can see update messages received as I change data in TinyEmber+ - this is what I need in my application :-)
The text was updated successfully, but these errors were encountered: