Documentation:Tutorial:Events - MdsWiki
Navigation
Personal tools

From MdsWiki

(Difference between revisions)
Jump to: navigation, search
Revision as of 10:52, 26 June 2019 (edit)
Manduchi (Talk | contribs)
(Asynchronous events in MDSplus)
← Previous diff
Revision as of 11:04, 14 October 2021 (edit)
Manduchi (Talk | contribs)
(The Classes for Event Management)
Next diff →
Line 78: Line 78:
def main(arg): def main(arg):
eventObj=MyEvent(arg) eventObj=MyEvent(arg)
- eventObj.run()+ eventObj.start()
if __name__=="__main__": if __name__=="__main__":

Revision as of 11:04, 14 October 2021

Asynchronous events in MDSplus

In MDSplus it is possible to generate asynchronous events as well as waiting for them. Events are often used to synchronize data visualization in jScope: an update event name can be defined in the jScope Setup Data pop-up window, forcing an update of the displayed signal whenever such an event is received. Data acquisition events in this case are generated by the data acquisition routines (usually the methods of the devices involved in data acquisition).

There are two MDSplus executables which can be called from a console: wfevent <Event_name> and setevent <event_name> . The former suspends until an event with that name has been received; the latter generated such an event.

In MDSplus there exist several implementations of asynchronous events: the most recent uses UDP multicast, and therefore events can be exchanged among applications residing on different machines in the same LAN. In order to use Multicast events it is necessary to define the env variable UDP_EVENTS and users are recommended to use them. UDP events represent the most efficient implementation,
By default, MDSplus uses port 4000 and multicast address 224.0.0.175. Port and multicast address can be changed by defining environment variables mdsevent_port and mdsevent_address, respectively. In particular, a range of multicast addresses can be specified by specifying for mdsevent_address the format n.n.n.n-n (if a single address is specified, the format is n.n.n.n).

However, not always UDP messages can be transferred among subnetworks, so a different configuration is required in this case, using TCP/IP-based events. TCP/IP - based events rely on the mdsip server. In other words, if you want to receive remote events you need to have a mdsip server running on your machine. To configure TCP/IP events you need to:

  • undefine UDP_EVENTS
  • define env variable mds_event_server as the mdsip address (<ip address>[::port]) of the intended event receiver. If more than one machine has to be involved in event reception, define mds_event_server as the list, separated by a semicolon, of the mdsip addesses of the event receivers

The Classes for Event Management

MDSplus defines one class, Event, for event generation and reception. In addition to notification, MDSplus events can bring data, either raw or "packed" into Data instances. The event issuer can then optionally associate data top the event, which will be received by every listener for that event. Events can be generated by the following methods:

  • setevent(name) to generate an event with no associated data
  • seteventRaw(name, buffer) to generate an event carrying a buffer of bytes
  • setevent(name, Data) to generate an event carrying a Data instance

To handle event reception it is necessary to extend Event class by associating the actions to be executed upon event reception. Class Event in fact defines the virtual function run(), which is called after the class instantiation whenever the event with the specified name has been received. The overridden run() method can then retrieve received data by calling superclass' getData() or getRaw() methods. The following code shows how to define a new Event class called MyEvent whose action is to print the content of the received buffer. It is possible to test the programs using the command

setevent <event_name> <Data String>

which generates an event with the specified name and passing the second parameter as a string buffer.

C++

#include <mdsobjects.h>
using namespace MDSplus;
class MyEvent:public Event
{
public:
    MyEvent(char *name):Event(name){}
    void run()
    {
        int bufSize;
        char *name = getName(); //Get the name of the event
        char *date = getTime()->getDate(); //Get the event reception date in string format
        char *buf =  getRaw(&bufSize); //Get raw data
        char *str = new char[bufSize+1]; //Make it a string
        memcpy(str, buf, bufSize);
        str[bufSize] = 0;
        cout << "RECEIVED EVENT " << name << " AT " << date << " WITH DATA  " << str << "\n";
    }
};

Java:

import MDSplus.*;
class MyEvent extends Event
{
     public MyEvent(java.lang.String event)throws Exception
     {
         super(event);
    }
    public void run()
    {
        System.out.println("RECEIVED EVENT "+ getName()+" AT " + getTime().getDate()+" WITH DATA  " + new java.lang.String(getRaw()));
    }
}

Python:

import sys
from MDSplus import *

class MyEvent(Event):
       def run(self):
             print("RECEIVED EVENT " + self.getName())
             print(self.getTime())
             print(self.getRaw())

def main(arg):
      eventObj=MyEvent(arg)
      eventObj.start()

if __name__=="__main__":
      arg = str(sys.argv[1])
      main(arg)


Using the Python example, try the following. From the event receiver's terminal, you can execute the above Python code that will be listening for events (assuming the above code was saved in a file with the name "myevent.py"):

python myevent.py hi!

The receiver will be listening. Now, open a new terminal and execute:

setevent hi! my_data_string

The receiver's terminal will print on the screen something like the following:

RECEIVED EVENT hi!
1548967068.08605
Byte_Unsigned([109,121,95,100,97,116,97,95,115,116,114,105,110,103])
where the Byte_Unsigned(...) in this example is the data string received.