How to memorize a READ attribute

Hi all,

as I understood it from the documentation and from experience, it is only possible to memorize READ_WRITE attributed.
In my case, I need to implement a counter as an attribute, which is increased whenever the position of the according motor is changed.
So writing the counter by the user is not intended.
Unfortunately, the hardware does not allow for storing the value, so it must be implemented in the TangoDS.

But how can I memorize the value of the counter when restarting the TangoDS?
Is there any workaround? I thought of using a property instead, which is written in the delete_device() method.

Best

Daniel
Hello,
In your case, you may use a property to store the data. You may push_back the data to the tango database everytime the counter is updated (this will prevent any some dataloss if the device crashes).

But you can also set the attribute to READ_WRITE and not implement anything in the write_you_counter function, this way it may be easier for you to deal with it using the memorized property.

Best Regards
Guillaume DI FRANCO
Thales - Software Engineer Manager
Hi,

I would store the counter value in an attribute property of your counter attribute to achieve that.
Memorized attributes are stored under attribute properties named "__value" (2 underscores).
"__value" attributes properties are considered special in Tango.
For performance reasons, their history is not saved in the Tango DB as for the other properties (By default, the 10 last values are saved in the history for all the other device and attribute properties. And you can see this history via jive).

The idea of Guillaume to save it in a property every time the value changes is good to handle the cases when the device server crashes (but of course, this never happens smile ).
If the counter changes at very high speed, I would discourage to save the counter value in the Tango DB because it might have an impact on your Tango Database responsiveness.

Here is a code example saving a value in a __value attribute property:


// Save counter value into DB under Counter->__value attribute property
Tango::DbDatum m_attr("counter"), m_val("__value");
Tango::DbData db_data;

short nu = 1;
m_attr << nu;
db_data.push_back(m_attr);
m_val << my_counter_value;
db_data.push_back(m_val);

try
{
Tango::Database *db = Tango::Util::instance()->get_database();
db->put_device_attribute_property(device_name, db_data);
}
catch(Tango::DevFailed &e)
{
ERROR_STREAM << "Exception caught while trying to save Counter value into the Tango Database:"
<< std::endl << e << std::endl;
}


And another example showing a way to retrieve the last saved value of the attribute property:


Tango::DevLong counter_val = 0;
try
{
Tango::DbData db_data;
db_data.push_back(Tango::DbDatum("counter"));
// you could add other attribute names here
// db_data.push_back(Tango::DbDatum("another_attribute"));
Tango::Database *db = Tango::Util::instance()->get_database();
db->get_device_attribute_property(device_name, db_data);

for (unsigned int i=0; i<db_data.size(); i++)
{
long nb_prop = 0;
db_data >> nb_prop;

for (int j=0; j<nb_prop; j++)
{
i++;
string &prop_name = db_data.name;
if (prop_name == "__value")
{
db_data >> counter_val ;
break;
}
}
}
}
catch(Tango::DevFailed &e)
{
ERROR_STREAM << "Exception caught while trying to get last counter value from Tango DB (Counter __value attribute property):"
<< std::endl << e << std::endl;
}
DEBUG_STREAM << "Last counter value = " << counter_val << std::endl;
Rosenberg's Law: Software is easy to make, except when you want it to do something new.
Corollary: The only software that's worth making is software that does something new.
Hi guys,

many thanks for the quick responses!

We also had the ideas of Guillaume with the property or with a write-method which does nothing.

However, using the __value attribute property is of course another nice idea.
As the counter is not increasing very fast < 1Hz we could save the counter value every time we change it, but I could also live with saving it only on delete in the delete_device method - since our DSs never crash :)

BTW, is there a reason why memorizing READ attributes is not implemented out of the box?
Would it be worth an issue?

Best

Daniel
dschick
BTW, is there a reason why memorizing READ attributes is not implemented out of the box?
Would it be worth an issue?

I guess there has never been a strong demand for that but that's of course an idea for the future. We encountered this use case already where I work.
Feel free to create an issue where we could discuss this possibility (and not forget about this idea).
I guess this feature will not be in the top priority features to be implemented because there is a work-around with the existing features.
If you're willing to create an issue, I would suggest to create this issue in the TangoTickets repository : https://gitlab.com/tango-controls/TangoTickets/-/issues/new

Kind regards,
Reynald
Rosenberg's Law: Software is easy to make, except when you want it to do something new.
Corollary: The only software that's worth making is software that does something new.
Just a small addition, recipe how to do this in pytango. Thanks to Yury Matveev.

  • set the attribute flags memorized = True and hw_memorized = True
  • define a attribute write method called only once to init the attribute with DB value
  • save value with Tango Util Database db.put_device_attribute_property method.


class DevWithMemorizedROAttr(Device):
def init_device(self):
super().init_device()
self.db = Util.instance().get_database()
self.attr_name ="my_attribute"
self.attr_val : int = 0
self.initialized = False # flag: run once at init

@attribute(dtype=int, memorized=True, hw_memorized = True, access= AttrWriteType.READ_WRITE)
async def my_attribute(self):
return self.attr_val

@my_attribute.write # Only one call at init i.o. to write value from config DB
def set_my_attr(self, val):
if not self.initialized:
self.initialized = True
self.attr_val = val
def memorize_attr_vaule(self):
inst_name = self.get_name() # Tango instance name
self.db.put_device_attribute_property(inst_name, {self.attr_name: {"__value": self.attr_val}})

Edited 3 weeks ago
 
Register or login to create to post a reply.