Skip to content
Snippets Groups Projects
Commit 5a9ad124 authored by mwyman's avatar mwyman
Browse files

Began CRL implementation

parent 50b2f1c4
No related branches found
No related tags found
No related merge requests found
Showing
with 968 additions and 1 deletion
record(dfanout, "$(P)Filter$(N):filter$(M)_dfanout"){
field(DOL, "$(P)Filter$(N):filter_decode.$(DECODE) CP")
field(OMSL, "closed_loop")
field(OUTA, "$(P)Filter$(N):filter$(M) PP")
}
record(bo, "$(P)Filter$(N):filter$(M)"){
field(DESC, "$(MAT), $(THICK)")
field(ZNAM, "Out")
field(ONAM, "In")
field(DISV, "1")
field(OUT, "$(OUT)")
}
record(dfanout, "$(P)Filter$(N):filter$(M)_BW_dfanout"){
field(OMSL, "closed_loop")
field(DOL, "$(P)Filter$(N):filter$(M) CP")
field(OUTA, "$(P)Filter$(N):filter_encode.$(ENCODE)")
# field(FLNK, "$(P)Filter$(N):filter_encode PP")
}
record(bi, "$(P)Filter$(N):filter$(M)_RBV"){
field(DESC, "$(MAT), $(THICK)")
field(ZNAM, "Out")
field(ONAM, "In")
field(INP, "$(INP)")
}
record(dfanout, "$(P)Filter$(N):filter$(M)_RBV_dfanout"){
field(OMSL, "closed_loop")
field(DOL, "$(P)Filter$(N):filter$(M)_RBV CP")
field(OUTA, "$(P)Filter$(N):filter_RBV_encode.$(ENCODE)")
}
record(bo, "$(P)Filter$(N):filter$(M)_Lock"){
field(ZNAM, "Free")
field(ONAM, "Locked")
field(SDIS, "$(P)Filter$(N):filter$(M)_Enable")
field(DISV, "1")
}
record(bo, "$(P)Filter$(N):filter$(M)_Enable"){
field(ZNAM, "Enabled")
field(ONAM, "Disabled")
}
record(calcout, "$(P)Filter$(N):disableOut$(M)_calc"){
field(INPA, "$(P)Filter$(N):filter$(M)_Enable CP")
field(INPB, "$(P)Filter$(N):filter$(M)")
field(CALC, "A=1?0:B")
field(OUT, "$(P)Filter$(N):filter$(M) PP")
field(FLNK, "$(P)Filter$(N):lockEnable$(M)_calc")
}
record(calcout, "$(P)Filter$(N):lockEnable$(M)_calc"){
field(INPA, "$(P)Filter$(N):filter$(M)_Enable")
field(INPB, "$(P)Filter$(N):filter$(M)_Lock CP")
field(INPC, "$(P)Filter$(N):filter$(M)_RBV")
field(CALC, "A | B")
field(OUT, "$(P)Filter$(N):filter$(M).DISA PP")
field(FLNK, "$(P)Filter$(N):outMask$(M)_calc")
}
record(calcout, "$(P)Filter$(N):outMask$(M)_calc"){
field(INPA, "$(P)Filter$(N):filter$(M)_Enable")
field(INPB, "$(P)Filter$(N):filter$(M)_Lock")
field(INPC, "$(P)Filter$(N):filter$(M)_RBV")
field(CALC, "A | (B & !C)")
field(OUT, "$(P)Filter$(N):outMask_encode.$(MASK) PP")
field(FLNK, "$(P)Filter$(N):inMask$(M)_calc")
}
record(calcout, "$(P)Filter$(N):inMask$(M)_calc"){
field(INPA, "$(P)Filter$(N):filter$(M)_Enable")
field(INPB, "$(P)Filter$(N):filter$(M)_Lock")
field(INPC, "$(P)Filter$(N):filter$(M)_RBV")
field(CALC, "!A & (B & C)")
field(OUT, "$(P)Filter$(N):inMask_encode.$(MASK) PP")
}
# Activate python environment containing modules used by IOC
eval "$(conda shell.bash hook)"
conda activate /net/s100dserv/xorApps/epics/synApps_6_3/support/PyDevice-env/filters
# Put python library in path
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/net/s100dserv/xorApps/epics/synApps_6_3/support/PyDevice-env/filters/lib/
......@@ -15,7 +15,8 @@ Integrates x-ray filter attenuation calculations with control of filter devices.
Uses xraylib python module.
### 100idPyCRL
<upcoming...>
Integrate code for transfocator calculations with lens actuation. Uses xraylib
python module
### 100idPyBL
<upcoming...>
......
dbLoadRecords("$(CALC)/db/editSseq.db", "P=$(PREFIX),Q=$(INSTANCE)")
doAfterIocInit("seq &editSseq, 'P=$(PREFIX),Q=$(INSTANCE)'")
#- interpolation
dbLoadRecords("$(CALC)/calcApp/Db/interp.db", "P=$(PREFIX),N=2000")
dbLoadRecords("$(CALC)/calcApp/Db/interpNew.db", "P=$(PREFIX),Q=1,N=2000")
#- busy record
dbLoadRecords("$(BUSY)/busyApp/Db/busyRecord.db", "P=$(PREFIX),R=mybusy1")
dbLoadRecords("$(BUSY)/busyApp/Db/busyRecord.db", "P=$(PREFIX),R=mybusy2")
#- Soft function generator
#dbLoadRecords("$(CALC)/calcApp/Db/FuncGen.db","P=$(PREFIX),Q=fgen,OUT=$(PREFIX)m7.VAL")
### Load database record for alive heartbeating support.
#- IOCNM is name of IOC, RHOST specifies the remote server accepting hearbeats
dbLoadRecords("$(ALIVE)/aliveApp/Db/alive.db", "P=$(PREFIX),IOCNM=$(IOC),RHOST=164.54.100.11")
dbLoadRecords("$(ALIVE)/aliveApp/Db/aliveMSGCalc.db", "P=$(PREFIX)")
#- A set of scan parameters for each positioner. This is a convenience
#- for the user. It can contain an entry for each scannable thing in the
#- crate.
#dbLoadTemplate("substitutions/scanParms.substitutions", "P=$(PREFIX)")
################################################################################
# PyDevice Support for Filter attenuation calculations
################################################################################
# Next two lines set up some testing tools for energy -- can be commented out
epicsEnvSet("MONOE","testMonoE")
dbLoadRecords("${TOP}/db/energyTestTools.db","P=$(PREFIX), MONOE=$(MONOE), IDENERGY=testIDE")
dbLoadTemplate("substitutions/pyDeviceFilter.substitutions","P=$(PREFIX)")
pydev("filters_subFile = 'substitutions/pyDeviceFilter.substitutions'")
pydev("from pyDevFilters import filterBlock")
pydev("filters = filterBlock()")
# Update the next line for the beamline energy
epicsEnvSet("BLE","$(PREFIX)$(MONOE)")
dbLoadRecords("${TOP}/db/pyDevFilters.db","P=$(PREFIX), N=1, OBJ=filters, NUM=12, KEV=$(BLE)")
# After iocInit, need to setup attenuation lookup table
# filters_subFile - string holding name/rel. location of substitutions file loaded
# loaded in dbLoadTemplate
# 12 - number of filters in this case
# 8.5 - beam energy in keV used for the initial lookup table setup -- can be updated
# after startup
doAfterIocInit("pydev('filters.setupLookupTable(filters_subFile, 12, energy = 8.5)')")
# PyDevice Transfocator (NEEDS WORK)
#< examples/pydeviceCRL.cmd
###############################################################################
###############################################################################
iocInit
###############################################################################
# write all the PV names to a local file
dbl > dbl-all.txt
# Diagnostic: CA links in all records
dbcar(0,1)
# print the time our boot was finished
date
exit
TOP = ../..
include $(TOP)/configure/CONFIG
#ARCH = win32-x86
#ARCH = windows-x64-static
#ARCH = windows-x64-debug
#ARCH = windows-x64
#ARCH = cygwin-x86
#ARCH = linux-x86
ARCH = rhel9-x86_64
#ARCH = vxWorks-ppc32
#ARCH = vxWorks694-ppc32
#ARCH = vxWorks-ppc603
#TARGETS = cdCommands envPaths dllPath.bat modules.lua
TARGETS = envPaths modules.lua
include $(TOP)/configure/RULES.ioc
Assuming the EPICS_HOST_ARCH environment variable is set correctly,
start the ioc from this directory by executing the following command.
../../bin/${EPICS_HOST_ARCH}/xxx st.cmd
file configMenu.req P=$(P),CONFIG=$(CONFIG)
file softGlue_settings.req P=$(P),H=$(H)
# If you're loading an add-on package into softGlue, save its PVs too.
file softGlue_FPGAContent_Encoder_settings.req P=$(P),H=$(H)
#file softGlue_FPGAContent_octupole_settings.req P=$(P),H=$(H)
#file softGlue_FPGAContent_Encoder_settings.req P=$(P) H=softGlue:
git won't make an empty directory, but we need this directory to exist
### save_restore setup, change SAVE_PATH if you are having autosave manage its own NFS mount
iocshLoad("$(AUTOSAVE)/iocsh/autosave_settings.iocsh", "PREFIX=$(PREFIX), SAVE_PATH=$(TOP)/iocBoot/$(IOC)")
iocshLoad("$(AUTOSAVE)/iocsh/save_restore.iocsh", "PREFIX=$(PREFIX), POSITIONS_FILE=auto_positions, SETTINGS_FILE=auto_settings")
iocshLoad("$(AUTOSAVE)/iocsh/autosaveBuild.iocsh", "PREFIX=$(PREFIX), BUILD_PATH=autosave")
#- Note that you can restore a .sav file without also autosaving to it.
#set_pass0_restoreFile("octupole_settings.sav")
#set_pass1_restoreFile("octupole_settings.sav")
###
# Setup search path for .req files. Include the db folders of every module specified in RELEASE
luaCmd("modules=require('modules'); for mod,path in pairs(modules) do set_requestfile_path(path .. '/db') end")
# Debug-output level
save_restoreSet_Debug(0)
# Access Security
#dbLoadRecords("$(TOP)/100idPyApp/Db/Security_Control.db","P=$(PREFIX)")
#asSetFilename("$(TOP)/iocBoot/accessSecurity.acf")
#asSetSubstitutions("P=$(PREFIX)")
### caputRecorder
iocshLoad("$(CAPUTRECORDER)/iocsh/caputRecorder.iocsh", "PREFIX=$(PREFIX)")
### Scan-support software
iocshLoad("$(SSCAN)/iocsh/sscan.iocsh", "PREFIX=$(PREFIX), MAX_PTS=1000, REQ_FILE=saveData.req")
iocshLoad("$(AUTOSAVE)/iocsh/configMenu.iocsh", "PREFIX=$(PREFIX),CONFIG=scan1")
#- You could make scan configurations read-only:
#dbLoadRecords("$(AUTOSAVE)/asApp/Db/configMenu.db","P=$(PREFIX),CONFIG=scan1,ENABLE_SAVE=0")
### Stuff for user programming ###
iocshLoad("$(CALC)/iocsh/userCalc.iocsh", "PREFIX=$(PREFIX), ARRAY_SIZE=8000")
#- Load 10 more of all the user calcs, N=1 creates usercalcs 10-19
iocshLoad("$(CALC)/iocsh/userCalc_extra.iocsh", "PREFIX=$(PREFIX), N=1, ARRAY_SIZE=8000")
#- Load 20 userScripts
dbLoadRecords("$(LUA)/luaApp/Db/luascripts10.db", "P=$(PREFIX), R=set1:")
dbLoadRecords("$(LUA)/luaApp/Db/luascripts10.db", "P=$(PREFIX), R=set2:")
#- string sequence (sseq) records
iocshLoad("$(CALC)/iocsh/sseq.iocsh", "PREFIX=$(PREFIX), INSTANCE=ES:")
#- interpolation
dbLoadRecords("$(CALC)/calcApp/Db/interp.db", "P=$(PREFIX),N=2000")
dbLoadRecords("$(CALC)/calcApp/Db/interpNew.db", "P=$(PREFIX),Q=1,N=2000")
#- busy record
dbLoadRecords("$(BUSY)/busyApp/Db/busyRecord.db", "P=$(PREFIX),R=mybusy1")
dbLoadRecords("$(BUSY)/busyApp/Db/busyRecord.db", "P=$(PREFIX),R=mybusy2")
#- Soft function generator
#dbLoadRecords("$(CALC)/calcApp/Db/FuncGen.db","P=$(PREFIX),Q=fgen,OUT=$(PREFIX)m7.VAL")
### Load database record for alive heartbeating support.
#- IOCNM is name of IOC, RHOST specifies the remote server accepting hearbeats
dbLoadRecords("$(ALIVE)/aliveApp/Db/alive.db", "P=$(PREFIX),IOCNM=$(IOC),RHOST=164.54.100.11")
dbLoadRecords("$(ALIVE)/aliveApp/Db/aliveMSGCalc.db", "P=$(PREFIX)")
#- A set of scan parameters for each positioner. This is a convenience
#- for the user. It can contain an entry for each scannable thing in the
#- crate.
#dbLoadTemplate("substitutions/scanParms.substitutions", "P=$(PREFIX)")
################################################################################
# PyDevice Support for Transfocator
################################################################################
#CRL 1 (substitutions file NEEDS WORK)
dbLoadTemplate("substitutions/pyDeviceTfor.substitutions","P=$(PREFIX)")
pydev("filters_subFile = 'substitutions/pyDeviceTfor.substitutions'")
# python code NEEDS WORK
pydev("from pyTransfocator_single import singleTF")
pydev("CRL1 = singleTF()")
# DB file NEEDS WORK
dbLoadRecords(""${TOP}/db/pyDevCRLsingle.db","P=$(PREFIX), N=1, OBJ=CRL1"
################################################################################
# PyDevice Support for Filter attenuation calculations
################################################################################
# Next two lines set up some testing tools for energy -- can be commented out
epicsEnvSet("MONOE","testMonoE")
dbLoadRecords("${TOP}/db/energyTestTools.db","P=$(PREFIX), MONOE=$(MONOE), IDENERGY=testIDE")
dbLoadTemplate("substitutions/pyDeviceFilter.substitutions","P=$(PREFIX)")
pydev("filters_subFile = 'substitutions/pyDeviceFilter.substitutions'")
pydev("from pyDevFilters import filterBlock")
pydev("filters = filterBlock()")
# Update the next line for the beamline energy
epicsEnvSet("BLE","$(PREFIX)$(MONOE)")
dbLoadRecords("${TOP}/db/pyDevFilters.db","P=$(PREFIX), N=1, OBJ=filters, NUM=12, KEV=$(BLE)")
# After iocInit, need to setup attenuation lookup table
# filters_subFile - string holding name/rel. location of substitutions file loaded
# loaded in dbLoadTemplate
# 12 - number of filters in this case
# 8.5 - beam energy in keV used for the initial lookup table setup -- can be updated
# after startup
doAfterIocInit("pydev('filters.setupLookupTable(filters_subFile, 12, energy = 8.5)')")
[prefix]
$(P)
[status]
$(P)saveData_status
[message]
$(P)saveData_message
[filename]
$(P)saveData_fileName
[counter] # scan counter
$(P)saveData_scanNumber
[fileSystem] # scan file system
$(P)saveData_fileSystem
[subdir] # scan file subdirectory
$(P)saveData_subDir
[basename] # scan file base name
$(P)saveData_baseName
[fullPathName]
$(P)saveData_fullPathName
[realTime1D] # if nonzero, write 1D data as it comes in
$(P)saveData_realTime1D
[scanRecord] # specify scan records to be monitored
$(P)scanH
$(P)scan1
$(P)scan2
$(P)scan3
$(P)scan4
[extraPV]
$(P)saveData_comment1
$(P)saveData_comment2
file configMenu.req P=$(P),CONFIG=$(CONFIG)
file scan_settings.req P=$(P),S=scan2
file scan_settings.req P=$(P),S=scan1
file scan_settings.req P=$(P),S=scanH
# Shell prompt
epicsEnvSet("IOCSH_PS1", "$(IOC)> ")
# prefix used for all PVs in this IOC
epicsEnvSet("PREFIX", "100idPyCRL:")
#For devIocStats
epicsEnvSet("ENGINEER", "M. Wyman")
epicsEnvSet("LOCATION", "100id")
epicsEnvSet("GROUP", "BCDA")
# search path for database files
epicsEnvSet("EPICS_DB_INCLUDE_PATH", ".")
# search path for streamDevice protocol files
epicsEnvSet("STREAM_PROTOCOL_PATH", ".")
# search path for lua scripts
# epicsEnvSet("LUA_SCRIPT_PATH", "./scripts")
# Specify largest array CA will transport
# Note for N doubles, need N*8 bytes+some overhead
epicsEnvSet("EPICS_CA_MAX_ARRAY_BYTES", 64010)
#!/usr/bin/perl
use strict;
use FindBin;
###################################################################
# Set Environment Variables to be used by the rest of the scripts #
###################################################################
BEGIN
{
# Top level of the IOC folder
$ENV{TOP} = "$FindBin::RealBin/../../..";
# IOC prefix name, used to find the correct iocBoot directory and executable
$ENV{IOC_NAME}="100idPyCRL";
#########################
# IOC Executable Config #
#########################
# Name of the IOC executable file
#! $ENV{IOC_BINARY}="$ENV{IOC_NAME}";
$ENV{IOC_BINARY}="100idPy";
# Top-level bin directory for the IOC
$ENV{IOC_BIN_DIR}="$ENV{TOP}/bin";
#! $ENV{IOC_BIN_DIR}="/home/username/epics/synApps/support/100idPy/bin";
#! $ENV{IOC_BIN_DIR}="/home/username/epics/synApps/support/module/iocs/exampleIOC/bin";
# Architecture the IOC is built under
$ENV{EPICS_HOST_ARCH} //= "rhel9-x86_64";
#! $ENV{EPICS_HOST_ARCH} //= "linux-x86_64";
#! $ENV{EPICS_HOST_ARCH}="linux-x86_64-debug";
# Full path to the IOC executable
$ENV{IOC_BIN_PATH}="$ENV{IOC_BIN_DIR}/$ENV{EPICS_HOST_ARCH}/$ENV{IOC_BINARY}";
###########################
# IOC Startup File Config #
###########################
# Startup Script for the IOC to run
$ENV{IOC_STARTUP_FILE}="st.cmd.Linux";
#! $ENV{IOC_STARTUP_FILE}="st.cmd.Cygwin";
#! $ENV{IOC_STARTUP_FILE}="st.cmd.Win32";
#! $ENV{IOC_STARTUP_FILE}="st.cmd.Win64";
# Directory that contains the startup script
$ENV{IOC_STARTUP_DIR}="$ENV{TOP}/iocBoot/ioc$ENV{IOC_NAME}";
#! $ENV{IOC_STARTUP_DIR}="/home/username/epics/ioc/synApps/100idPy/iocBoot/ioc100idPyCRL";
# Full path to the startup file
$ENV{IOC_STARTUP_FILE_PATH}="$ENV{IOC_STARTUP_DIR}/$ENV{IOC_STARTUP_FILE}";
##########################
# Config For This Script #
##########################
# Directory that contains all the command modules to be loaded
$ENV{IOC_COMMAND_DIR}="$ENV{IOC_STARTUP_DIR}/softioc/commands";
#! $ENV{IOC_COMMAND_DIR}="/home/username/epics/ioc/synApps/100idPy/iocBoot/ioc100idPyCRL/softioc/commands";
$ENV{IOC_CMD}="$ENV{IOC_BIN_PATH} $ENV{IOC_STARTUP_FILE_PATH}";
# Required shell commands
$ENV{SCREEN}="screen";
$ENV{TELNET}="telnet";
$ENV{PROCSERV}="/APSshare/bin/procServ";
$ENV{NETCAT}="nc";
$ENV{ECHO}="echo";
##########################
# Config for PyDeviece #
##########################
#If PyDevice is to be used, source script needs to be set here
$ENV{PYDEV_STARTUP}="/net/s100dserv/xorApps/epics/synApps_6_3/ioc/100idPy/100idPyCRL_startup_env";
$ENV{PYDEV_IOC_CMD}="source $ENV{PYDEV_STARTUP}; $ENV{IOC_CMD}";
}
use Env;
use File::Spec;
use Module::Loaded;
use List::Util;
use lib "$IOC_COMMAND_DIR";
use _info;
use _commands;
#####################################################################
my $GET_SCREEN_PID=1;
#####################################################################
if (! -d $ENV{IOC_COMMAND_DIR})
{
print("Error: IOC command directory ($ENV{IOC_COMMAND_DIR}) doesn't exist.\n");
print("IOC_COMMAND_DIR in $FindBin::RealScript needs to be corrected.\n");
die;
}
#####################
# Parse Input #
#####################
_commands::call("_local", @ARGV);
#########################
# xxx.pl Commands #
#########################
This folder contains the commands that the xxx.pl script will recognize, both when running
locally or when running as a remote procServ command console.
Any file in this folder with the extension ".pm" will be loaded as a perl package when the
xxx.pl script is run. Any package using the "commands::" namespace will be registered as a
command that can be run, with the command name being equal to the package name. So, for
example, the package "commands::stop" would define the command "stop".
Within the package, one can define three different subroutines; _local, _remote, and _usage.
These functions, if they exist, are called when the command is invoked by a local script,
when invoked on a remote procServ command console, or when passed to the usage command. A
package doesn't need to define all of these functions, only the ones that will be used.
###############################
# Environment Variables #
###############################
The xxx.pl script exports environment variables that a command can use to access any files
and folders that may be necessary. At the beginning of the package, one can import the "Env"
package to bind environment variables to global scalar values so that they can be accessed
with just "$ENVIRONMENT_VARIABLE" rather than the full "$ENV{ENVIRONMENT_VARIABLE}".
The environment variables that the script exports are:
* TOP - Path to the top level folder of the IOC
* IOC_NAME - Name of the IOC, specifying which iocBoot directory to use
* IOC_BINARY - Name of the IOC executable
* IOC_BIN_DIR - Location of the /bin directory in the IOC
* EPICS_HOST_ARCH - Architecture of the IOC to run
* IOC_BIN_PATH - Full path to the IOC executable
* IOC_STARTUP_FILE - Name of the st.cmd file to run
* IOC_STARTUP_DIR - Directory to start the IOC in
* IOC_STARTUP_FILE_PATH - Full path to the st.cmd file to run
* IOC_COMMAND_DIR - Path to the /commands folder
* IOC_CMD - Shell command to be run by run/screen/procServ
* SCREEN - Name of screen command
* TELNET - Name of telnet command
* PROCSERV - Name of procServ command
* NETCAT - Name of netcat command
* ECHO - Name of echo command
##########################
# Utility Packages #
##########################
Two other utility packages provide functions necessary for commands to get info about the
system or to interact with the control systems available. To load these packages, perl must
be told where to find them using the IOC_COMMAND_DIR environment variable.
> use Env;
> use lib "$IOC_COMMAND_DIR";
> use _info;
> use _commands;
# _info
The _info package includes functions for getting information about running screen or procServ
processes, sending commands to a procServ process, and some common TCP tasks.
* _info::my_ip
Returns the current computer's ip address
* _info::get_port
Returns a port number >= 50000 that can be used for TCP traffic
* _info::procserv(<TYPE>, <INFO>)
TYPE - "COMMAND" or "CONSOLE"
INFO - "PREFIX", "PORT", "PID", "IP", or "SAME_HOST"
Returns information about a running procServ process. Information is parsed from info
files that are created by procServ while running. The command console is a manager console
that can launch and kill IOC processes. The console process is the IOC's shell console.
PREFIX - The prefix used for the procServ info and log files.
IP - The IP of the computer running the procServ instance
PORT - The port used
PID - The PID of the running process
SAME_HOST - Whether the IP of the procServ instance matches the IP of the computer running xxx.pl
* _info::get_local_pid
Returns the PID of a screen or procServ instance on the current computer running the IOC_CMD.
* _info::can_ping(<TYPE>)
TYPE - "COMMAND" or "CONSOLE"
Returns whether the given procServ instance can be reached
* _info::has_remote
Returns whether a command console is open for the IOC
* _info::is_local
Returns whether any potential running instances of the IOC would be on the current computer
* _info::ioc_up
Returns whether a running instance of the IOC can be found
* _info::send_cmd(<TYPE>, <CMD>)
TYPE - "COMMAND" or "CONSOLE"
CMD - The string to send
Sends the given command to the procServ instance
# _commands
The _commands package allows commands to properly call other commands.
* _commands::call(<TYPE>, <FUNC>, <ARGS>)
TYPE - "_local", "_remote", or "_usage"
FUNC - The function to call
ARGS - An array of args to be passed to the function
Calls commands::<FUNC>::<TYPE>(<ARGS>)
* _commands::listAll(<FILTER>)
FILTER - "_local", "_remote", "_usage"
Prints a "|" separated list of all functions that implement the function listed in FILTER.
##################
# TEMPLATE #
##################
package commands::<COMMAND NAME>; # Provide the command name to be recognized as
use Env; # Get environment variables as simple scalars
use lib "$IOC_COMMAND_DIR"; # Add IOC_COMMAND_DIR as a location to find packages
# Include utility packages
use _info;
use _commands;
sub _local # Called when there isn't a remote command console
{
my @params = @_;
my $first_arg = $params[0];
my $second_arg = $param[1];
}
sub _remote # Function that a remote command console can execute
{
}
sub _usage # Prints the usage of the function
{
print("<COMMAND NAME> <ARGS>");
}
1; # Necessary for perl packages
package _commands;
use Env;
use lib "$IOC_COMMAND_DIR/..";
my @loaded_cmds = ();
opendir my $dir, "$IOC_COMMAND_DIR";
while (readdir($dir))
{
next if($_ =~ /^\.$/);
next if($_ =~ /^\.\.$/);
next if($_ =~ /^_/);
if ($_ =~ /pm$/)
{
my $cmd_name = $_;
$cmd_name =~ s/\.pm//g;
eval "use commands::$cmd_name";
if ($!) { print ("$cmd_name: $!\n"); }
push ( @loaded_cmds, "$cmd_name");
}
}
closedir $dir;
sub call
{
my @parms = @_;
my ($FUNCTION, $SELECTION, @SEL_ARGS) = (@parms);
if (! defined $SELECTION) { $SELECTION = "usage"; }
if (! List::Util::first { $_ eq $SELECTION; } @loaded_cmds)
{
print("couldn't find command: $SELECTION\n");
}
else
{
if (eval "commands::${SELECTION}->can($FUNCTION)")
{
eval "commands::${SELECTION}::$FUNCTION(@SEL_ARGS)";
}
}
}
sub listAll
{
my @parms = @_;
my $FILTER = @parms[0];
my $first = 1;
foreach (sort @loaded_cmds)
{
next if(! eval "commands::$_->can($FILTER)");
if ($first) { $first = 0; }
else { print("|"); }
print($_);
}
}
1;
package _info;
use Env;
use Socket;
use IO::Socket;
use Sys::Hostname;
use strict;
my %procserv_info;
$procserv_info{"COMMAND"} = { "PREFIX" => "ioc${IOC_NAME}-command",
"PORT" => -1,
"PID" => -1,
"IP" => -1,
"SAME_HOST" => 0};
$procserv_info{"CONSOLE"} = { "PREFIX" => "ioc${IOC_NAME}-console",
"PORT" => -1,
"PID" => -1,
"IP" => -1,
"SAME_HOST" => 0};
sub my_ip
{
return inet_ntoa((gethostbyname(hostname))[4]);
}
sub parse
{
my @parms = @_;
my $PS_PROC = $parms[0];
my %output = %{$procserv_info{$PS_PROC}};
my $CHECK_FILE = "$output{PREFIX}.txt";
if (-e $CHECK_FILE && -f $CHECK_FILE)
{
open(my $filehandle, "<", "$CHECK_FILE");
my $line1 = <$filehandle>;
my $line2 = <$filehandle>;
close($filehandle);
$line1 =~ s/\R//g;
$line2 =~ s/\R//g;
my @pidline = split(/:/, $line1);
my @tcpline = split(/:/, $line2);
$output{"PID"} = $pidline[1];
$output{"IP"} = $tcpline[1];
$output{"PORT"} = $tcpline[2];
my $ip_addr = my_ip();
if ($ip_addr eq $tcpline[1])
{
$output{"SAME_HOST"} = 1;
}
}
return \%output;
}
sub procserv
{
my @parms = @_;
my $PS_PROC = $parms[0];
my $PS_INFO = $parms[1];
my $output = parse($PS_PROC);
return $output->{$PS_INFO};
}
sub update
{
if (procserv("COMMAND", "PID") != -1 && ! can_ping("COMMAND"))
{
print("ProcServ file open for command server, but cannot access IP/Port\n");
}
if (procserv("CONSOLE", "PID") != -1 && ! can_ping("CONSOLE"))
{
print("ProcServ file open for console server, but cannot access IP/Port\n");
}
}
sub get_local_pid
{
my $UID=$<;
my $ptable = `ps -u $UID x`;
foreach (split(/\n/, $ptable))
{
#Remove leading spaces
$_ =~ s/^\s+//;
#Split proc info, but don't break up command
my @splitline = split(/\s+/, $_, 5);
#[0] is PID, [4] is Command
if (index($splitline[4], ${IOC_CMD}) == 0)
{
return $splitline[0];
}
}
return 0;
}
sub can_ping
{
my @parms = @_;
my $PS_PROC = $parms[0];
my $data = parse($PS_PROC);
my $IP = $data->{"IP"};
my $PORT = $data->{"PORT"};
if ($PORT != -1)
{
my $exit_code = system("$NETCAT -z $IP $PORT");
return ($exit_code == 0);
}
return 0;
}
sub has_remote
{
return (procserv("COMMAND", "IP") != -1);
}
sub is_local
{
if (has_remote()) { return (procserv("COMMAND", "SAME_HOST") != 0); }
return 1;
}
sub ioc_up
{
if (has_remote()) { return can_ping("CONSOLE"); }
else { return get_local_pid(); }
}
sub send_cmd
{
my @parms = @_;
my ($PS_PROC, @CMDS) = (@parms);
my $data = parse($PS_PROC);
my $IP = $data->{"IP"};
my $PORT = $data->{"PORT"};
my $everything = join(" ", @CMDS);
my $throwaway =`$ECHO '$everything' | $NETCAT $IP $PORT`;
}
sub get_port()
{
my $ip = my_ip();
my $port_to_use = 50000;
while ($port_to_use <= 65535)
{
my $exit_code = system("$NETCAT -z $ip $port_to_use");
if ($exit_code != 0) { last; }
$port_to_use += 1;
}
return $port_to_use;
}
sub sanity_check()
{
#######################
# Sanity Checks #
#######################
if (! -d $ENV{IOC_STARTUP_DIR})
{
print("Error: Starting directory ($ENV{IOC_STARTUP_DIR}) doesn't exist.\n");
print("IOC_STARTUP_DIR in $FindBin::RealScript needs to be corrected.\n");
die;
}
if (! -f $ENV{IOC_BIN_PATH})
{
print("Error: No IOC executable at $ENV{IOC_BIN_PATH}\n");
print("IOC_BIN_PATH in $FindBin::RealScript needs to be corrected.\n");
die;
}
if (! -f $ENV{IOC_STARTUP_FILE_PATH})
{
print("Error: No IOC startup script at $ENV{IOC_STARTUP_FILE_PATH}\n");
print("IOC_STARTUP_FILE_PATH in $FindBin::RealScript needs to be corrected.\n");
return;
}
}
1;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment