Client Application

The client application (devmgrClient) is a simple utility allowing to send commands to the Device Manager from the command line. In this context we use the words commands and events as synonyms. The devmgrClient uses the interface module modif (generated from a protobuf definition) to compose the payload of the messages. The devmgrClient sends the messages using the API from rad for request/reply (implemented with ZeroMQ).

$ devmgrClient [<timeout>] [<node>] [<port>] <command> ["<parameters>"]

Where
      <timeout>    reply timeout in msec, default=5000
      <node>       optional node or ip address, default=localhost
      <port>       optional port, default=5555
      <command>    command to be sent to the server (e.g. modif.ReqInit)
      <parameters> optional parameters of the command.

List of Commands

The commands (events) currently supported by the devmgrClient utility are:

Client commands
Command Parameters
modif.ReqInit “”
modif.ReqEnable “”
modif.ReqDisable “”
modif.ReqState “”
modif.ReqStatus “”
modif.ReqSetup <JSON filename>
modif.ReqRecover “”
modif.ReqReset “”
modif.ReqConfig “”
modif.ReqSetLog “<ERROR|INFO|DEBUG|TRACE>”
modif.ReqSimulate “<device id1>, … ,[<device idn>]”
modif.ReqStopSim “<device id1>, … ,[<device idn>]”
modif.ReqIgnore “<device id1>, … ,[<device idn>]”
modif.ReqStopIgn “<device id1>, … ,[<device idn>]”
modif.ReqBeginAcq “<filename prefix>, <data product id>”
modif.ReqEndAcq “”
modif.ReqExit “”

Examples

Note

The following examples assume the server is listening for incoming events under port 5577 in the local host.

Enabling debug level in the server

$ devmgrClient 5000  localhost  5577  modif.ReqSetLog "DEBUG"

Initialising the server

$ devmgrClient 5000  localhost  5577  modif.ReqInit ""

Moving the server to Operational state

$ devmgrClient 5000  localhost  5577  modif.ReqEnable ""

Executing a Setup command from the command line

In order to send a setup command to the Device Manager it is needed to define the parameters and action associated in a file using the JSON format. The content of this file will be converted to a protobuf message by the devmgrClient utility.

$ devmgrClient 50000  localhost  5577  modif.ReqSetup "<JSON file>"

An example of the JSON file is include below. This JSON files specifies to named position OFF for device motor1

{ "fcs": [
    {
        "id": "ins1.fcs1",
        "motor": [
            {
                "id": "motor1",
                "name": "OFF",
                "action": "MOVE_BY_NAME"
            }
        ]
    }
  ]
 }

Another example of a JSON file for setting up more than one device:

{ "fcs": [
    {
        "id": "ins1.fcs1",

        "shutter": [
            {
                "id": "shutter1",
                "action": "OPEN"
            }
        ],
        "shutter": [
            {
                "id": "shutter2",
                "action": "OPEN"
            }
        ],
        "shutter": [
            {
                "id": "shutter3",
                "action": "OPEN"
            }
        ]
     }
    ]
 }

Python Interface

It is possible to communicate with the Device Manager through clients developed in Python. The RAD provides the services that encapsulate the ZeroMQ messages and using the generated Protocol Buffer the library from the modif module, developers can create client applications that serialize and send messages to the server.

Note

The following Python example creates a message to open the shutter. It uses asyncio and zmq packages that are part of the ELT DevEnv.

import sys
import argparse
import logging
import asyncio
import signal
import concurrent
from functools import partial

import zmq.asyncio

# ICS RAD packages
from rad.core.run import run_with_cleanup
from rad.services.msg import MsgRequestor
from rad.services.msg import MsgReplier

# ICS FCF Interface Module
from devmgr.modif.requests_pb2 import *

zmq.asyncio.install()

loop = asyncio.get_event_loop()
zmq_ctx = zmq.asyncio.Context()

"""
RAD class that manages the ZMQ ELT message. Endpoint need to be
adapted to the correct one.
"""
requestor = MsgRequestor(endpoint = 'tcp://localhost:7577',
                         zmq_ctx = zmq_ctx,
                         loop = loop)
queue = asyncio.Queue(loop=loop)

"""
Defines a co-routine for opening the shutter
"""
async def open_shutter(loop, requestor):
    req = ReqSetup()
    fcs = req.fcs.add()
    fcs.id = "ins1.fcs1"
    shutter1 = fcs.shutter.add()
    shutter1.id = "shutter1"
    shutter1.action = Shutter.ActionShutter.Value('OPEN')
    fut = requestor.send(req)
    # Wait until it gets the reply
    rep = await asyncio.wait_for(requestor.receive(RepSetup), timeout=3)

"""Runs the co-rotine inside the event loop"""
run_with_cleanup(open_shutter (loop, requestor),
                 loop=loop, cleanup_timeout=5.0)