I have two commands Start and Stop. When I execute Start, the state is set to ON, and I want to read some data, then to wait some time (variable TimePause), and I want to do that continuously until I execute command Stop.
def read_Data(self, attr):
…
if (self.get_state() in [PyTango.DevState.RUNNING.ON]):
DO SOMETHING
self.attr_Data_read= data i have read;
time.sleep(TimePause)
attr.set_value(self.attr_Data_read)[/i]
But, in this way, I have to wait TimePause seconds for all atributes to update their values.
How can I do this so that one atribute is updated every TimePause seconds, and other attributes update their values by polling?
I hope I was clear and that someone can help me with this.
Let me clarify my understanding to the problem and later suggest you a solution.
While you execute the function read_Data, you want to update a particular attribute at every TimePause seconds while other attributes get updated by their polling.
Issue:
Now, the problem you are facing is because you have used sleep in the read_Data function, the main thread for your device is paused too. Hence, other attributes are taking the sleep time to update the values.
Solution: You can create start a new read_Data thread when the Start command is fired. In the read_Data thread, you can include the logic of TimePause. You also need to add the logic to stop the read_Data thread when the Stop command is executed. In this way, your custom thread will run in parallel to the main thread and other attributes will get updated based on their polling.
I hope, I was able to understand the problem and clarify myself.
I have wrote code below, is this OK? I have some errors, just want to check if I am on a good way. t_read_Data is a thread, variable t_start is set to 1 when I execute command Start, and it is set to 0 when I execute command Stop.
[i]import thread
def t_read_Data():
while(self.t_start==1)
DO_SOMETHING
self.attr_Data_read= data i have read;
time.sleep(TimePause)
attr.set_value(self.attr_Data_read())
Yes, you are on the correct path. There is no need to specify in POGO that you created a new thread.
Creating a new Thread subclass is worth exploring.
Feel free to let us know if you find any issues in between.
I have solved problem, and now everything works just fine.
I will try to do this with Thread subclass also.
Thank you very much for your help, I really appreciate it!
TCoutInho, I have not seen your post till now. Thank you for your help.
I have tried what you proposed, and I like the idea, but I have next problem:
Let’s say that polling is executed every 3 seconds and that I change my data values every 500ms.
In your way, read_MyAttribute will be called every 3 seconds, which means that attribute will be updated by every 6th data value.
I’ve used set_value in the thread because I wanted every time I get new data value to update my attribute.
How can I solve this problem without calling set_value in the thread?
I hope I was clear, please tell me if I should be more specific or clearer.
in C++, I think you don’t get any memory leak if you fire a change or archive event after having invoked set_value from a thread. You will need to declare in Pogo that you will push events by user code for this attribute and add a call to the PyTango equivalent of C++ Tango::Attribute::fire_change_event() method (I’m no PyTango expert so I don’t know the exact syntax in PyTango).
You might also consider using the externally triggered polling advanced feature from Tango (See 7.3.5 section from the Tango book), using trigger_attr_polling() method. Again, I don’t know how you do that in PyTango.
First let me say that I assume when you said polling you were not talking about tango polling since you asked to start your own thread. Therefore, the solution I proposed does not involve tango polling.
In practice, my proposal only solves the problems I mentioned before (*)
When a client asks to read the value of the attribute MyAttribute, on the server side, the method read_MyAttribute is invoked. What it is doing is fetching the last value updated by the thread and send it back to the client. In other words, the client always gets the last value which was updated by the thread.
If the client reads more often than the value is updated by the loop thread then of course it will read several times the same value. The only solution I know is to increase the polling frequency.
(*) actually it solves also a problem that occurs if a client reads more often than the server updates the value.
Thank you for answers guys, I will definitely try trigger_attr_polling() Reynald, it looks interesting.
I have one more question, though. In Tango manual, page 84, is said:
Does this mean that only difference between polling and refreshing period (which is set from AtkPanel) is that refreshing period only calls readAttribute, while polling also calls always_executed_hook and read_attr_hardware?
And If I am right, attribute’s value is displayed in AtkPanel whenever metod readAttribute is called?
I recommend you to experiment by yourself by putting traces into the code to see what is executed and when.
I think ATK does something like that (pseudo-code) for your attributes which are not configured to send events:
while true do
foreach attribute from List of Attributes to be refreshed/displayed do
deviceproxy.read_attribute(attribute.name)
end_foreach
sleep(refreshing_period_ms)
end_while
On your server side, I think you will receive many requests to read single attributes (I think read_attributes is not used in this case by atkpanel).
So on your server side, for each single read_attribute request coming from atkpanel to read AAA attribute, the following methods will be executed if the attribute AAA is not polled:
always_executed_hook
read_attr_hardware
read_AAA
If the attribute is polled, the server will return the latest value from the polling buffer cache.
In this case, the polling thread will take care of executing the 3 methods above once every polling period (which might be different than the Atkpanel refreshing period).