Client Application

The client application (fcfClient) 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 fcfClient uses the standard interface module stdif and the application interface module fcfif to compose the payload of the messages. The fcfClient sends the messages using CII MAL request/reply.

$ fcfClient <serviceURI> <command> ["<parameters>"]

Where
      <serviceURI> destination of the command (e.g. zpb.rr://127.0.0.1:12081)
      <command>    command to be sent to the server (e.g. Init)
      <parameters> optional parameters of the command.

Warning

The URI shall not contain the ‘/’ at the end otherwise the client will hang trying to connect to a non existing server.

List of Commands

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

Client commands

Command

Parameters

Init

“”

Enable

“”

Disable

“”

State

“”

Status

“”

Setup

“”

Recover

“”

Reset

“”

Config

“”

DevNames

“”

SetLog

“<ERROR|INFO|DEBUG|TRACE>”

Simulate

“<device id1>, … ,[<device idn>]”

StopSim

“<device id1>, … ,[<device idn>]”

Ignore

“<device id1>, … ,[<device idn>]”

StopIgn

“<device id1>, … ,[<device idn>]”

HwInit

“<device id1>, … ,[<device idn>]”

HwEnable

“<device id1>, … ,[<device idn>]”

HwDisable

“<device id1>, … ,[<device idn>]”

HwReset

“<device id1>, … ,[<device idn>]”

StartDaq

“<daq id>”

StopDaq

“<daq id>”

Exit

“”

Warning

Due to the upgrade to CII, the payload of the SETUP command cannot be defined through a JSON file. For sending SETUP and other commands is better to use the Python interface.

Note

The HW commands like HwInit or HwEnable control the state of the controller associated to the device.

Examples

Note

The following examples assume the server is listening for incoming events under the URI zpb.rr://127.0.0.1:12081 in the local host.

Enabling debug level in the server

$ fcfClient zpb.rr://127.0.0.1:12081  SetLog "DEBUG"

Initialising the server

$ fcfClient zpb.rr://127.0.0.1:12081  Init ""

Moving the server to Operational state

$ fcfClient zpb.rr://127.0.0.1:12081  Enable ""

Executing a Setup command from the command line

This is not possible in this version using fcfClient utility. Please use the Python client library instead.

Python Client Library

It is possible to communicate with the Device Manager through clients developed in Python. The FCF provides a library that simplifies the interaction with the Device Manager (fcfclib). This is probably the easiest and more flexible way to interact with the Device Manager. The fcfclib encapsulates the creation of the payload for the Setup command by providing predefined methods.

Users might want to interact directly with FCF ICD binding methods. This is, of course possible, but it is outside the scope of this library.

Note

This Python client library was added in version 2.

Error Handling

The fcfclib reports as a RuntimeError exceptions that may be delivered by the Device Manager. Unfortunately a due to a limitation of CII MAL, we cannot get the source error message yet from the Python exception.

Classes

The fcfclib library provides internal classes to build the buffer for each devices. In addition, this library provides one class that encapsulates the user interface with the DeviceManager. This class is the DevmgrCommand class.

DevmgrCommand

The constructor of the DevmgrCommand class support two parameters: uri and timeout. The timeout is optional and has a default of one minute, expressed in milliseconds.

The class handles an internal buffer object that is used to build the payload of the Setup command. Each time the command is executed, the buffer is reset. The user can add multiple device settings into the internal buffer before executing the setup command.

The methods names of the class are shown in the tables below. They try to be self explanatory.

Methods for building Setup Payload

Method

parameters

close_shutter

device (string)

open_shutter

device (string)

switch_lamp_on

device (string)

switch_lamp_on_with_intensity

device (string), intensity (float)

switch_lamp_on_with_timer

device (string), timer (integer)

move_motor_abs_enc

device (string), position (integer)

move_motor_abs_pos

device (string), position (float)

move_motor_rel_enc

device (string), position (integer)

move_motor_rel_pos

device (string), position (float)

move_motor_name_pos

device (string), name (string)

drot_motor_abs_pos

device (string), position (float)

move_drot_posangle

device (string), position (float)

start_drot_sky_tracking

device (string)

start_drot_elev_tracking

device (string)

start_drot_user_tracking

device (string)

stop_drot_tracking

device (string)

move_adc_motor1_abs_pos

device (string), position (float)

move_adc_posangle

device (string), position (float)

start_adc_tracking

device (string)

stop_adc_tracking

device (string)

set_piezo_auto

device (string)

set_piezo_pos

device (string)

set_piezo_home

device (string)

move_piezo_in_user_units

device (string), pos1 (float), pos2 (float), pos3 (float)

move_piezo_in_bits_units

device (string), bit1 (integer), bit2 (integer), bit3 (integer)

switch_actuator_off

device (string)

switch_lamp_off

device (string)

switch_lamp_off

device (string)

Methods for Command Interface

Method

parameters

setup

None

status

device list (argv)

ignore

device list (argv)

simulate

device list (argv)

stop_ignore

device list (argv)

stop_simulate

device list (argv)

hw_init

device list (argv)

hw_enable

device list (argv)

hw_disable

device list (argv)

hw_reset

device list (argv)

devnames

None

devconfig

device

state

None

init

None

enable

None

enable

None

disable

None

reset

None

stop

None

Examples

Retrieving the Status

import fcfclib.devmgrCommands as fcs

uri = "zpb.rr://127.0.0.1:12081"
fcsif = fcs.DevMgrCommands(uri)
print(fcsif.status())

['shutter1.simulated = true', 'shutter1.lcs.state = Undefined', 'shutter1.lcs.substate = Undefined',
'lamp1.simulated = true', 'lamp1.lcs.state = Undefined', 'lamp1.lcs.substate = Undefined',
'lamp1.lcs.intensity = 0.000000', 'motor1.simulated = true', 'motor1.lcs.state = Undefined',
'motor1.lcs.substate = Undefined', 'motor1.lcs.pos_target = 0.000000',
'motor1.lcs.pos_actual = 0.000000', 'motor1.lcs.vel_actual = 0.000000',
'motor1.lcs.axis_enable = false', "motor1.pos_actual_name = ''",
'motor1.pos_enc = -2147483648', '', 'OK']

Executing a single Setup

import fcfclib.devmgrCommands as fcs

uri = "zpb.rr://127.0.0.1:12081"
fcsif = fcs.DevMgrCommands(uri)
# Move single motor1 to absolute position 100 in user units
# Fill the internal setup buffer
fcsif.move_motor_abs_pos("motor1", 100)
# Send setup command to the Device Manager listening in port 12081
fcsif.setup()

Executing a Setup with multiple devices

import fcfclib.devmgrCommands as fcs

uri = "zpb.rr://127.0.0.1:12081"
fcsif = fcs.DevMgrCommands(uri)
# Setup multiple devices at once
# Fill the internal setup buffer
fcsif.move_motor_abs_pos("motor1", 100)
fcsif.switch_lamp_off("lamp1")
fcsif.close_shutter("shutter1")
# Send setup command to the Device Manager listening on port 12081
fcsif.setup()

FCF CLI

The FCF python library provides an experimental command shell with simple commands aiming to simplify the interaction with the Device Manager. The FCF shell can be invoked issuing the command fcfcli.

Command Line Parameters

The fcfcli offers some few command line parameters. If no parameters are specified, the fcfcli will use the default name services and use nomad/consul to obtain the correct IP and port numbers of the Device Manager. The fcfcli shell commmands are not necessary using the same names as the MAL interfaces with the purpose to shorten the commands names. Commands that could take long time, are asynchronous so the shell can continue being used while answer from the previous command is not yet received.

Parameter

Description

–uri

if the URI is specified, the supcli will use it to connect to the server

–name

When using nomad, one could specifify the name of the service instead of the URI

–module

Custom interface library

Warning

The fcfcli shell assumes NOMAD/CONSUL services are up and running. If this is not the case then only –uri parameter can be used.

Warning

The URI shall not contain the ‘/’ at the end otherwise the client will hang trying to connect to a non existing server.

Note

The fcfcli shell was created for the Device Manager but since it uses the standard interface, it can be used for any server implementing this interface, although only for the standard events like init, enable, disable, etc.

fcfcli --uri zpb.rr://134.171.3.48:30269
fcfSh>?
Available command list:
-  close
-  daqstart
-  daqabort
-  daqstatus
-  daqstop
-  devinfo
-  devnames
-  devstatus
-  devconfig
-  disable
-  enable
-  help
-  ignore
-  init
-  move
-  move_by_name
-  move_by_speed
-  open
-  reset
-  setup_json_file
-  setup_json_string
-  setup_spf
-  simulate
-  start_track
-  state
-  status
-  get_config
-  stop
-  stop_ignore
-  stop_simulate
-  stop_track
-  switch_off
-  switch_on

Shell History

The FCF shells keeps its own history file under $HOME/.fcfSh.txt. The history can be accessed using the arrows keys.

Shell Completion

The FCF shell provides a completion capability for the supported commands using the Tab key.

Supported Shell Commands

Command

Parameters

Description

init

[<device>]

sends the init (stdif) event to the connected server. If a device is specified, it will forward the command to the given device instead.

enable

[<device>]

sends the enable (stdif) event to the connected server. If a device is specified, it will forward the command to the given device instead.

disable

[<device>]

sends the disable (stdif) event to the connected server. If a device is specified, it will forward the command to the given device instead.

reset

[<device>]

sends the reset (stdif) event to the connected server. If a device is specified, it will forward the command to the given device instead.

stop

sends the stop (stdif) event to the connected server

help

print the list of supported commands

daqstart

<daqid>

Start DAQ acquisition

daqabort

<daqid>

Abort DAQ acquisition

daqstatus

<daqid>

Get DAQ acquisition status

daqstop

<daqid>

Stop DAQ acquisition

devnames

Get the list of devices managed by the server

devstatus

[<dev1>,<devN>]

Get the detailed status of the devices managed by the server

devconfig

<device>

Get the actual configuration of a device (yaml formatting)

simulate

<device>

sends the simulate event to the connected server

stop_simulate

<device>

sends the stopsim event to the connected server

ignore

<device>

sends the ignore event to the connected server

stop_ignore

<device>

sends the stopign event to the connected server

setup_json_file

<file>

The setup commands uses a JSON file to set run-time parameters. The contents of the JSON file shall match the defined schema.

setup_json_string

<JSON string>

The setup commands uses a JSON format to set run-time parameters. The JSON string shall match the defined schema.

setup_spf

<string>

The setup commands uses a simple format to specify the parameters to be changed. Examples:

shutter1:action=”OPEN” lamp1:action=”ON”, actuator1:action:”OFF”

state

sends the GetState (stdif) event to the connected server

status

sends the GetStatus (stdif) event to the connected server

get_config

Get the server configuration (yaml formatting)

subset

This command is equivalent to the setup but instead of JSON format, it uses a simple parameter format (SPF), e.g. subset <device>:ON=false

close

<shutter device>

It closes a shutter

open

<shutter device>

It opens a shutter

switch_on

<lamp device>

It switch on a lamp or an actuator device

switch_of

<lamp device>

It switch off a lamp or an actuator device

move

<motor>,<pos>

It moves a motor to a target position

move_by_name

<motor>,<name>

It moves a motor using a named position

move_by_speed

<motor>,<speed>

It moves a motor in speed

start_track

<device>,<mode>

It start tracking for using a given mode

stop _track

<device>

It stops tracking

ctrl-d

Stop the shell

using devnames command

fcsSh> devnames
reply> = shutter1, lamp1, motor1, drot1, adc1, piezo1
OK

using devstatus command

fcsSh> devstatus lamp1
reply> = ['lamp1.lcs.state = Operational', 'lamp1.lcs.substate = On', 'lamp1.lcs.intensity = 0.000000', '', 'OK']
fcsSh>

using switch_off command

fcsSh> switch_off lamp1
fcsSh> reply> = OK setup completed.
fcsSh>

using move command

fcsSh> move motor1,50
fcsSh> reply> = OK setup completed.
fcsSh>

using setup command

This example uses a test JSON file (test.json).

[{
"id": "shutter1", "param": {
    "shutter": {
            "action": "OPEN"
            }
    }
},
{
"id": "lamp1", "param": {
    "lamp": {
            "action": "OFF"
            }
    }
},
{
"id": "motor1", "param": {
    "motor": {
        "action": "MOVE_ABS",
        "pos": 50,
        "unit": "UU"
            }
    }
}]
fcsSh> setup_json_file test.json
fcsSh> reply> = OK setup completed.
fcsSh>
fcsSh> setup_json_string [{"id": "shutter1", "param": { "shutter": {"action": "OPEN"}}}]
fcsSh> reply> = OK setup completed.
fcsSh>
fcsSh> setup_spf shutter1:action="OPEN"
fcsSh> reply> = OK setup completed.
fcsSh>

JSON Schema

JSON is used to compose the payload of the setup command. To minimize possible errors, the client python library validates the payload against a defined schema before sending the command to the server. The FCF provides a schema that covers all standard devices. Instrument implementing custom devices shall extend this schema definition.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "title": "FCF schema",
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "id": {
        "type": "string",
        "description": "device identifier."
      },
      "param": {
        "$ref": "#/definitions/param"
      }
    }
  },
  "definitions": {
    "param": {
      "type": "object",
      "properties": {
        "shutter": {
          "$ref": "#/definitions/shutter"
        },
        "actuator": {
          "$ref": "#/definitions/actuator"
        },
        "lamp": {
          "$ref": "#/definitions/lamp"
        },
        "motor": {
          "$ref": "#/definitions/motor"
        },
        "drot": {
          "$ref": "#/definitions/drot"
        },
        "adc": {
          "$ref": "#/definitions/adc"
        },
        "piezo": {
          "$ref": "#/definitions/piezo"
        }
      },
      "oneOf": [
                { "required":
                     [ "shutter" ] },
                { "required":
                     [ "actuator" ] },
                { "required":
                     [ "lamp" ] },
                { "required":
                     [ "motor" ] },
                { "required":
                     [ "drot" ] },
                { "required":
                     [ "adc" ] },
                { "required":
                     [ "piezo" ] }
                ]
    },
    "shutter": {
      "type": "object",
      "properties": {
        "action": {
          "type": "string",
          "enum": ["OPEN", "CLOSE"],
          "description": "Shutter action."
        }
      },
       "required": ["action"]
    },
     "actuator": {
      "type": "object",
      "properties": {
        "action": {
          "type": "string",
          "enum": ["ON", "OFF"],
          "description": "Actuator action."
        }
      },
       "required": ["action"]
    },
    "lamp": {
      "type": "object",
      "properties": {
        "action": {
          "type": "string",
          "enum": ["ON", "OFF"],
          "description": "Lamp action."
        },
        "intensity": {
          "type": "number",
          "minimum": 1,
          "maximum": 100,
          "description": "Lamp intensity."
        },
        "time": {
          "type": "integer",
          "minimum": 1,
          "description": "Lamp timer."
        }
      },
      "required": ["action"],
      "additionalProperties": false
    },
    "motor": {
      "type": "object",
      "properties": {
        "action": {
          "type": "string",
          "enum": ["MOVE_ABS", "MOVE_REL", "MOVE_BY_NAME", "MOVE_BY_SPEED"],
          "description": "Motor action."
        },
        "pos": {
          "type": "number",
          "description": "Motor position in user units."
        },
        "enc": {
          "type": "integer",
          "description": "Motor position in encoders."
        },
        "unit": {
          "type": "string",
          "enum": ["UU", "ENC"],
          "description": "Motor position unit."
        },
        "name": {
          "type": "string",
          "description": "Motor named position."
        },
        "speed": {
          "type": "number",
          "description": "Motor speed."
        }
      },
      "required": ["action"]
    },
    "drot": {
       "allOf": [{ "$ref": "#/definitions/motor" }],
      "properties": {
        "action": {
          "type": "string",
          "enum": ["MOVE_ABS", "MOVE_REL", "MOVE_BY_NAME", "MOVE_BY_SPEED", "MOVE_BY_POSANG", "START_TRACK", "STOP_TRACK"],
          "description": "Drot action."
        },
        "posang": {
          "type": "number",
          "description": "Motor position angle."
        },
         "mode": {
          "type": "string",
          "enum": ["ENG", "STAT", "SKY", "ELEV", "USER"],
          "description": "Drot mode."
        }
      },
      "required": ["action","mode"]
    },
    "adc": {
      "allOf": [{ "$ref": "#/definitions/motor" }],
      "properties": {
        "action": {
          "type": "string",
          "enum": ["MOVE_ABS", "MOVE_REL", "MOVE_BY_NAME", "MOVE_BY_SPEED", "MOVE_BY_POSANG", "START_TRACK", "STOP_TRACK"],
          "description": "Adc action."
        },
        "posang": {
          "type": "number",
          "description": "Motor position angle."
        },
        "axis": {
          "type": "string",
          "enum": ["ADC1", "ADC2"],
          "description": "Adc axis."
        },
         "mode": {
          "type": "string",
          "enum": ["ENG", "OFF", "AUTO"],
          "description": "Adc mode."
        }
      },
      "required": ["action","mode"]
    },
    "piezo": {
      "type": "object",
      "properties": {
        "action": {
          "type": "string",
          "enum": ["SET_AUTO", "SET_POS", "SET_HOME", "MOVE_ALL_BITS", "MOVE_ALL_POS"],
          "description": "Piezo action."
        },
        "pos1": {
          "type": "number",
          "description": "Piezo position 1 in volts."
        },
        "pos2": {
          "type": "number",
          "description": "Piezo position 2 in volts."
        },
        "pos3": {
          "type": "number",
          "description": "Piezo position 3 in volts."
        },
        "bit1": {
          "type": "integer",
          "description": "Piezo position 1 in bits."
        },
        "bit2": {
          "type": "integer",
          "description": "Piezo position 2 in bits."
        },
        "bit3": {
          "type": "integer",
          "description": "Piezo position 3 in bits."
        }
      },
      "required": ["action"]
    }
  }
}

Simple Parameter Format (SPF)

This is a custom format used to express the parameters for the setup command in an easy a simple way for users. You can include multiple parameters for one or more devices. The FCF client library will take this format and translate it to JSON internally to be able to check whether the syntax is correct before submitting the command to the server.

The format has the following syntax:

<device>:<parameter>=<value>[,<device>:<parameter>=<value>]...[,<device>:<parameter>=<value>]

The FCF client library provides a method where you can setup the FCF using a string with this format (setup_spf). For more information, see client interface description above.

fcsSh> setup_spf shutter1:action="OPEN",lamp1:action="ON",lamp1:intensity=80
fcsSh> reply> = OK setup completed.
fcsSh>