Set attribute value and push event
I wonder if there is any easy way to write value to attribute and push event with only one line of code.
I have a command which asks hardware for data. Then it returns data for few attributes, so my code looks like this:
Is there simpler way to set attribute and push event at the same time?
I'm thinking for creating property and push event in setter, but maybe there is some mechanism in PyTango? E.g. Attr1.set_value(val1) which sets attribute value and pushes event at the same time.
Second think is pushing invalid values. If you return None from attribute, it gives you Invalid Quality, but if you want to push event you need to write some value (even that value is invalid), then time, then AttrQuality, instead of just None. Anyway to fix this?
This would help clean the code a lot, especially if I have dozens of attributes.
Edit: command is polled, so it periodically reads data and attributes are also polled for periodic events.
Well, your implementation doesn't follow the "traditional way" to write a Tango device.
It should typically rely on MyDev.read_attr_hardware(self,data) rather than having this ReadData command.
In fact, I don't see which use case could lead you to this implementation. You have multiple clients consuming the attribute values? Who is triggering ReadData? Why doesn't it simply return the values (in case the caller is the only entity interested in the values)? Are you sure the events are necessary here?
Anyway, the answer to your question is no. There's no way to set the value of an attribute, then systematically (auto-)push a CHANGE_EVENT. This would violate the semantic of the event itself. If you decide to push your events by code, then it is your responsibility to do what the polling thread would do for you behind the scenes.
A simple way is to enable automatic polling of the attributes and configure the change event ranges for each of them. But please be aware of the fact that the automatic polling is only suitable for Devices with just a handful of simple attributes. Example:
Change events will then automatically be published by the polling loop in the DeviceServer:
nleclercq and Thomas, thanks for replies.
nleclercqActually, I've never heard about read_attr_hardware before. I will look into this.
I think my case is little more complicated, so I'll try to describe it:
I have 1 hardware device which communicates through socket.
I'm reading 26 values (then I have 26 attributes + state, status, connection state) from it. To do this I have 8 text commands. It is 8 because one command reads for example value A, B and C, second command read values D and E, third command reads F, G, C and D etc.
To set values in the device I need also to send text command, so to set attr B I need to send command with properly prepared values of A, B and C etc.
Each command takes about 200, 300ms to proceed (send and read back). Commands are grouped into 3-4 groups, which each group needs to be read in particular time. I need first and second command (so like first 5 attributes) to be read at least every second, another in 10 seconds, next 30s and last 1 minute.
I grouped each read and set command into tango commands and parse the answer or request accordingly to the spec (sometimes I need few additional letters to the request, sometimes colons, each request and answer have checksum, address and length of the message).
Setting value is not very common and rather expert is designated to do this (so set commands are on expert level - attribute can't be read on operator level and write on expert). You can execute read command, so if you set something in the device (through set command or different source), you can immediately read it and get update. In this case I'm also wondering about executing read after each set in the code (so you don't need to do it manually).
There are more additional commands, which 2 are like this (other are resets or executing provided by the user text command directly to the device)
For each command I'm using asyncio
I have one timer command which is polled every second and I have divider in it (so each command group is executed at the exact time I want). Because sometimes there is not enough time to get all data on time I have FIFO queue - sometimes most wanted attributes are read after 1.2 or 1.5 seconds from the last read, but that is acceptable.
When I get attribute value, I want it to be pushed immediately, so clients have most actual value at the shortest possible time. I also set polling on the attributes, so clients get periodic events with data after sometime if value hasn't changed enough - it's mostly important for the archiving, but also for some trends.
Now I've made something like this: