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:
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:
|
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>