tango-controls / pytango

This project was moved to gitlab.com
http://pytango.rtfd.io
54 stars 44 forks source link

Event issue with 9.3.1/2 #311

Closed stufisher closed 5 years ago

stufisher commented 5 years ago

There seems to be some issue with eventing in 9.3.2. This worked ok in 9.2.5a.

If i build a test device using the high level Device server api events look to be emitted ok, however using Device_4Impl results is nothing being emitted.

Heres my test case:

HLAPI:

from PyTango.server import run
from PyTango.server import Device
from PyTango.server import command, attribute
from PyTango import EventType, AttrQuality

class EventDevice(Device):
    def init_device(self):
        self.set_change_event("attr", True, False)

    @attribute
    def attr(self):
        return 0.

    @command
    def send_event(self):
        self.push_change_event("attr", 1.)

    @command
    def send_event_with_timestamp(self):
        self.push_change_event("attr", 2., 3., AttrQuality.ATTR_WARNING)

    @command(dtype_in=str)
    def add_dyn_attr(self, name):
        attr = attribute(
            name=name,
            dtype='float',
            fget=self.read)
        self.add_attribute(attr)

    @command(dtype_in=str)
    def delete_dyn_attr(self, name):
        self._remove_attribute(name)

    def read(self, attr):
        attr.set_value(1.23)

if __name__ == '__main__':
    run([EventDevice])

LLAPI:

import PyTango
import sys

class EventDevice(PyTango.Device_4Impl):

    def __init__(self,cl, name):
        PyTango.Device_4Impl.__init__(self,cl,name)
        self.debug_stream("In " + self.get_name() + ".__init__()")
        EventDevice.init_device(self)

    def init_device(self):
        self.debug_stream("In " + self.get_name() + ".init_device()")
        self.get_device_properties(self.get_device_class())
        self.attr_attr_read = 0.0
        self.set_change_event("attr", True, False)

    def read_attr(self, attr):
        self.debug_stream("In " + self.get_name() + ".read_Position()")
        self.attr_attr_read = 1.0
        attr.set_value(self.attr_attr_read)

    def send_event(self):
        self.debug_stream("In " + self.get_name() + ".send_event()")
        self.push_change_event("attr", 1.)

class EventClass(PyTango.DeviceClass):
    class_property_list = {}
    device_property_list = {}
    cmd_list = {
        'send_event': 
        [[PyTango.DevVoid,"Test events"],
         [PyTango.DevVoid,""]],
    }

    attr_list = {
        'attr':
            [[PyTango.DevDouble,
            PyTango.SCALAR,
            PyTango.READ]],
        }

    def __init__(self, name):
        PyTango.DeviceClass.__init__(self, name)
        self.set_type(name)
        print("In EventClass constructor")
        self.set_change_event("attr", True, False)

def main():
    try:
        py = PyTango.Util(sys.argv)
        py.add_class(EventClass,EventDevice,'EventDevice')

        U = PyTango.Util.instance()
        U.server_init()
        U.server_run()

    except PyTango.DevFailed as e:
        print('-------> Received a DevFailed exception:',e)
    except Exception as e:
        print('-------> An unforeseen exception occurred....',e)

if __name__ == '__main__':
    main()

and my test script:

import PyTango
import time

def on_event(data):
    print("on_event", data)

dev = PyTango.DeviceProxy('id00/event/test')
dev.subscribe_event("attr", PyTango.EventType.CHANGE_EVENT, on_event)

try:
    while True:
        time.sleep(1)
        dev.send_event()
except KeyboardInterrupt:
    exit()

With a device running the HLAPI, events are emitted every 1s as expected. With my LLAPI device you get an event on first subscription, then nothing.

[el7 test]$ python test_events.py
on_event EventData[
     attr_name = 'tango://el7.localdomain:10000/id00/event/test/attr'
    attr_value = DeviceAttribute(data_format = tango._tango.AttrDataFormat.SCALAR, dim_x = 1, dim_y = 0, has_failed = False, is_empty = False, name = 'attr', nb_read = 1, nb_written = 0, quality = tango._tango.AttrQuality.ATTR_VALID, r_dimension = AttributeDimension(dim_x = 1, dim_y = 0), time = TimeVal(tv_nsec = 0, tv_sec = 1570452004, tv_usec = 582967), type = tango._tango.CmdArgType.DevDouble, value = 0.0, w_dim_x = 0, w_dim_y = 0, w_dimension = AttributeDimension(dim_x = 0, dim_y = 0), w_value = None)
        device = EventDevice(id00/event/test)
           err = False
        errors = ()
         event = 'change'
reception_date = TimeVal(tv_nsec = 0, tv_sec = 1570452004, tv_usec = 583050)]

Installed versions are:

pytango                   9.3.1            py37ha8d69ae_1    tango-controls
tango                     9.3.2                h6bb024c_0    tango-controls

If i conda install pytango=9.2.5 llapi device works

pytango                   9.2.5            py37ha8d69ae_1    tango-controls
tango                     9.2.5a               h6bb024c_0    tango-controls

This came from trying to understand why Lima had stopped emitting events. It is implemented using Device_4Impl: https://gitlab.esrf.fr/limagroup/Lima-tango-python/issues/17

tiagocoutinho commented 5 years ago

The example you show is flawless. Could be a strange bug in the server.

I will have a look tomorrow. Thanks for reporting.

tiagocoutinho commented 5 years ago

@stufisher,

@jairomoldes noticed that inheriting from Device_4Impl instead of Device_5Impl on (Py)Tango 9.3.x seems to be the cause for the problem.

The bug was reported in Tango C++ project (see here)

There is a simple fix which is to inherit from PyTango.LatestDeviceImpl instead of PyTango.Device_XImpl.

The LatestDeviceImpl member exists in PyTango for some time but the the Lima code pre-dates its existence so I will make a PR in the Lima project.

Thanks for reporting.

andygotz commented 5 years ago

@jairomoldes thanks for noticing this!