Command-line Usage
Using pytmc
Once pytmc has been installed in a virtual environment the pytmc
command
can be called from the command line to generate .db files and more.
pytmc db
“pytmc-db” is a command line utility for generating epics records files from TwinCAT3 .tmc files. This program is designed to work in conjunction with ESS’s m-epics-twincat-ads driver.
usage: pytmc db [-h] [--dbd DBD] [--allow-errors] [--no-error-context]
[--plc PLC] [--debug]
[--archive-file ARCHIVE_FILE | --no-archive-file]
INPUT [OUTPUT]
Positional Arguments
- INPUT
Path to interpreted .tmc file, or a .tsproj project
- OUTPUT
Path to output .db file
Default: <_io.TextIOWrapper name=’<stdout>’ mode=’w’ encoding=’utf-8’>
Named Arguments
- --dbd, -d
Specify an expanded .dbd file for validating fields (requires pyPDB)
- --allow-errors, -i
Generate the .db file even if linter issues are found
Default: False
- --no-error-context
Do not show db file context around errors
Default: False
- --plc
The PLC name, if specifying a .tsproj file
- --debug
Raise exceptions immediately, such that the IPython debugger may be used
Default: False
- --archive-file
Save an archive configuration file. Defaults to OUTPUT.archive if specified
- --no-archive-file
Do not write the archive file, regardless of OUTPUT filename settings.
Default: False
pytmc stcmd
“pytmc-stcmd” is a command line utility for generating ESS/ethercatmc-capable EPICS startup st.cmd files directly from TwinCAT3 .tsproj projects.
Relies on the existence (and linking) of FB_MotionStage function blocks.
usage: pytmc stcmd [-h] [--plc PLC_NAME] [-p PREFIX] [--hashbang HASHBANG]
[--binary BINARY_NAME] [-n NAME] [--only-motor]
[--db-path DB_PATH] [--dbd DBD] [--delim DELIM] [--debug]
[--template TEMPLATE_FILENAME]
[--template-path TEMPLATE_PATH] [--allow-errors]
tsproj_project
Positional Arguments
- tsproj_project
Path to .tsproj project
Named Arguments
- --plc
PLC project name, if multiple exist
- -p, --prefix
PV prefix for the IOC
- --hashbang
Indicates to the shell which binary to use for the st.cmd script
Default: “../../bin/rhel7-x86_64/adsIoc”
- --binary
IOC application binary name
Default: “adsIoc”
- -n, --name
IOC name (defaults to project name)
- --only-motor
Parse the project only for motor records, skipping other variables with pytmc pragmas
Default: False
- --db-path
Path for db files
Default: “.”
- --dbd
Path to the IOC dbd file
- --delim
Preferred PV delimiter
Default: “:”
- --debug, -d
Post-stcmd, open an interactive Python session
Default: False
- --template
st.cmd Jinja2 template
Default: “stcmd_default.cmd”
- --template-path
Location where templates are stored
Default: “.”
- --allow-errors
Allow non-fatal errors to be ignored
Default: False
pytmc xmltranslate
Tool for making XML-formatted files human-readable
Output uses the following rules: For a line of xml that appears as the following: <tag attr=qual…> text </tag> tail
Note that tail takes precedence over text.
This program will output the following: {attrs:qual…} tag text tail
Tags contained by other tags are indented and printed on the following line.
This tool was created for exploring .tpy files but is well suited to reading any xml formatted file.
usage: pytmc xmltranslate [-h] [-d DEPTH] [-i INDENT_SIZE] input_file
Positional Arguments
- input_file
input file
Named Arguments
- -d, --depth
Recursive limit for exploring the file
Default: 7
- -i, --indent_size
Indent size for output formatting
Default: 4
pytmc debug
“pytmc-debug” is a Qt interface that shows information about how pytmc interprets TwinCAT3 .tmc files.
usage: pytmc debug [-h] [-d DBD] [-a] INPUT
Positional Arguments
- INPUT
Path to .tmc file
Named Arguments
- -d, --dbd
Specify an expanded .dbd file for validating fields (requires pyPDB)
- -a, --allow-no-pragma
Show all items, even those missing pragmas (warning: slow)
Default: False
pytmc pragmalint
“pytmc pragmalint” is a command line utility for linting PyTMC pragmas in a given TwinCAT project or source code file
usage: pytmc pragmalint [-h] [--markdown] [--verbose] filename
Positional Arguments
- filename
Path to .tsproj project or source code file
Named Arguments
- --markdown
Make output more markdown-friendly, for easier sharing
Default: False
- --verbose, -v
Show all pragmas, including good ones
Default: False
pytmc stcmd
“pytmc-stcmd” is a command line utility for generating ESS/ethercatmc-capable EPICS startup st.cmd files directly from TwinCAT3 .tsproj projects.
Relies on the existence (and linking) of FB_MotionStage function blocks.
usage: pytmc stcmd [-h] [--plc PLC_NAME] [-p PREFIX] [--hashbang HASHBANG]
[--binary BINARY_NAME] [-n NAME] [--only-motor]
[--db-path DB_PATH] [--dbd DBD] [--delim DELIM] [--debug]
[--template TEMPLATE_FILENAME]
[--template-path TEMPLATE_PATH] [--allow-errors]
tsproj_project
Positional Arguments
- tsproj_project
Path to .tsproj project
Named Arguments
- --plc
PLC project name, if multiple exist
- -p, --prefix
PV prefix for the IOC
- --hashbang
Indicates to the shell which binary to use for the st.cmd script
Default: “../../bin/rhel7-x86_64/adsIoc”
- --binary
IOC application binary name
Default: “adsIoc”
- -n, --name
IOC name (defaults to project name)
- --only-motor
Parse the project only for motor records, skipping other variables with pytmc pragmas
Default: False
- --db-path
Path for db files
Default: “.”
- --dbd
Path to the IOC dbd file
- --delim
Preferred PV delimiter
Default: “:”
- --debug, -d
Post-stcmd, open an interactive Python session
Default: False
- --template
st.cmd Jinja2 template
Default: “stcmd_default.cmd”
- --template-path
Location where templates are stored
Default: “.”
- --allow-errors
Allow non-fatal errors to be ignored
Default: False
pytmc summary
“pytmc-summary” is a command line utility for inspecting TwinCAT3 .tsproj projects.
usage: pytmc summary [-h] [--all] [--outline] [--boxes] [--code] [--plcs]
[--nc] [--symbols] [--types]
[--filter-types FILTER_TYPES] [--links] [--markdown]
[--debug]
filename
Positional Arguments
- filename
Path to project or solution (.tsproj, .sln)
Named Arguments
- --all, -a
All possible information
Default: False
- --outline
Outline XML
Default: False
- --boxes, -b
Show boxes
Default: False
- --code, -c
Show code
Default: False
- --plcs, -p
Show plcs
Default: False
- --nc, -n
Show NC axes
Default: False
- --symbols, -s
Show symbols
Default: False
- --types
Show TMC types and record suffixes, if available
Default: False
- --filter-types
Filter the types shown by name
- --links, -l
Show links
Default: False
- --markdown
Make output more markdown-friendly, for easier sharing
Default: False
- --debug, -d
Post-summary, open an interactive Python session
Default: False
pytmc template
“pytmc template” is a command line utility to expand a template based on a TwinCAT3 project (or XML-format file such as .TMC).
The template file is expected to be in Jinja template format.
The following dictionaries are available in the template context:
solutions - {solution_filename: [project_fn: {...}, ...], ...}
projects - {project_filename: {...}, ...}
others - {filename: {...}, ...}
If installed and available, git_info
will be available on each project.
The following helpers are available in the environment:
config_to_pragma
data_type_to_record_info
determine_block_type
element_to_class_name
enumerate_types
generate_records
get_boxes
get_data_type_by_reference
get_data_types
get_library_versions
get_links
get_linter_results
get_motors
get_nc
get_plc_by_name
get_pou_call_blocks
get_symbols
get_symbols_by_type
list_types
max
min
separate_by_classname
And the following filters:
epics_prefix
epics_suffix
pragma
title_fill
And the following variables:
pytmc_version
types
usage: pytmc template [-h] [-t TEMPLATES] [--macro MACROS] [--debug]
projects [projects ...]
Positional Arguments
- projects
Path to project or solution (.tsproj, .sln)
Named Arguments
- -t, --template
Template filename with optional output filename. In the form
input_filename[:output_filename]
.Defaults to ‘-’ (standard input -> standard output).- --macro, -m
Define a macro for the template in the form MACRO=VALUE
- --debug, -d
Post template generation, open an interactive Python session
Default: False
pytmc types
“pytmc-types” is a Qt interface that shows DataType-related information from a tmc file.
usage: pytmc types [-h] INPUT
Positional Arguments
- INPUT
Path to .tmc file
Templates
stcmd_default.cmd
#!{{hashbang}}
< envPaths
epicsEnvSet("IOCNAME", "{{name}}" )
epicsEnvSet("ENGINEER", "{{user}}" )
epicsEnvSet("LOCATION", "{{prefix}}" )
epicsEnvSet("IOCSH_PS1", "$(IOCNAME)> " )
cd "$(TOP)"
# Run common startup commands for linux soft IOC's
< /reg/d/iocCommon/All/pre_linux.cmd
# Register all support components
dbLoadDatabase("dbd/{{binary_name}}.dbd")
{{binary_name}}_registerRecordDeviceDriver(pdbbase)
cd "$(TOP)/db"
epicsEnvSet("ASYN_PORT", "{{asyn_port}}")
epicsEnvSet("IPADDR", "{{plc_ip}}")
epicsEnvSet("AMSID", "{{plc_ams_id}}")
epicsEnvSet("IPPORT", "{{plc_ads_port}}")
adsAsynPortDriverConfigure("$(ASYN_PORT)","$(IPADDR)","$(AMSID)","$(IPPORT)", 1000, 0, 0, 50, 100, 1000, 0)
{% if motors %}
epicsEnvSet("MOTOR_PORT", "{{motor_port}}")
epicsEnvSet("PREFIX", "{{prefix}}{{delim}}")
epicsEnvSet("ECM_NUMAXES", "{{motors|length}}")
epicsEnvSet("NUMAXES", "{{motors|length}}")
EthercatMCCreateController("$(MOTOR_PORT)", "$(ASYN_PORT)", "$(NUMAXES)", "200", "1000")
#define ASYN_TRACE_ERROR 0x0001
#define ASYN_TRACEIO_DEVICE 0x0002
#define ASYN_TRACEIO_FILTER 0x0004
#define ASYN_TRACEIO_DRIVER 0x0008
#define ASYN_TRACE_FLOW 0x0010
#define ASYN_TRACE_WARNING 0x0020
#define ASYN_TRACE_INFO 0x0040
asynSetTraceMask("$(ASYN_PORT)", -1, 0x41)
#define ASYN_TRACEIO_NODATA 0x0000
#define ASYN_TRACEIO_ASCII 0x0001
#define ASYN_TRACEIO_ESCAPE 0x0002
#define ASYN_TRACEIO_HEX 0x0004
asynSetTraceIOMask("$(ASYN_PORT)", -1, 2)
#define ASYN_TRACEINFO_TIME 0x0001
#define ASYN_TRACEINFO_PORT 0x0002
#define ASYN_TRACEINFO_SOURCE 0x0004
#define ASYN_TRACEINFO_THREAD 0x0008
asynSetTraceInfoMask("$(ASYN_PORT)", -1, 5)
#define AMPLIFIER_ON_FLAG_CREATE_AXIS 1
#define AMPLIFIER_ON_FLAG_WHEN_HOMING 2
#define AMPLIFIER_ON_FLAG_USING_CNEN 4
{% for motor in motors | sort(attribute='nc_axis.axis_number') %}
epicsEnvSet("AXIS_NO", "{{motor.nc_axis.axis_number}}")
epicsEnvSet("MOTOR_PREFIX", "{{motor|epics_prefix}}")
epicsEnvSet("MOTOR_NAME", "{{motor|epics_suffix}}")
epicsEnvSet("DESC", "{{motor.name}} / {{motor.nc_axis.name}}")
epicsEnvSet("EGU", "{{motor.nc_axis.units}}")
epicsEnvSet("PREC", "{{motor|pragma('precision', 3) }}")
epicsEnvSet("AXISCONFIG", "{{motor|pragma('axisconfig', '')}}")
epicsEnvSet("ECAXISFIELDINIT", "{{motor|pragma('additional_fields', '') }}")
epicsEnvSet("AMPLIFIER_FLAGS", "{{motor|pragma('amplifier_flags', '') }}")
EthercatMCCreateAxis("$(MOTOR_PORT)", "$(AXIS_NO)", "$(AMPLIFIER_FLAGS)", "$(AXISCONFIG)")
dbLoadRecords("EthercatMC.template", "PREFIX=$(MOTOR_PREFIX), MOTOR_NAME=$(MOTOR_NAME), R=$(MOTOR_NAME)-, MOTOR_PORT=$(MOTOR_PORT), ASYN_PORT=$(ASYN_PORT), AXIS_NO=$(AXIS_NO), DESC=$(DESC), PREC=$(PREC) $(ECAXISFIELDINIT)")
dbLoadRecords("EthercatMCreadback.template", "PREFIX=$(MOTOR_PREFIX), MOTOR_NAME=$(MOTOR_NAME), R=$(MOTOR_NAME)-, MOTOR_PORT=$(MOTOR_PORT), ASYN_PORT=$(ASYN_PORT), AXIS_NO=$(AXIS_NO), DESC=$(DESC), PREC=$(PREC) ")
dbLoadRecords("EthercatMCdebug.template", "PREFIX=$(MOTOR_PREFIX), MOTOR_NAME=$(MOTOR_NAME), MOTOR_PORT=$(MOTOR_PORT), AXIS_NO=$(AXIS_NO), PREC=3")
{% endfor %}
{% endif %}
{% for db in additional_db_files %}
dbLoadRecords("{{ db.file }}", "{{ db.macros }}")
{% endfor %}
cd "$(TOP)"
dbLoadRecords("db/iocAdmin.db", "P={{prefix}},IOC={{prefix}}" )
dbLoadRecords("db/save_restoreStatus.db", "P={{prefix}},IOC={{name}}" )
# Setup autosave
set_savefile_path( "$(IOC_DATA)/$(IOC)/autosave" )
set_requestfile_path( "$(TOP)/autosave" )
save_restoreSet_status_prefix( "{{prefix}}:" )
save_restoreSet_IncompleteSetsOk( 1 )
save_restoreSet_DatedBackupFiles( 1 )
set_pass0_restoreFile( "$(IOC).sav" )
set_pass1_restoreFile( "$(IOC).sav" )
# Initialize the IOC and start processing records
iocInit()
# Start autosave backups
create_monitor_set( "$(IOC).req", 5, "" )
# All IOCs should dump some common info after initial startup.
< /reg/d/iocCommon/All/post_linux.cmd
asyn_standard_file.jinja2
{% for r in records%}
{{r}}
{% endfor %}
asyn_standard_record.jinja2
record({{record.record_type}}, "{{record.pvname}}") {
{% if record.long_description %}
# {{ record.long_description }}
{% endif %}
{% for alias in record.aliases %}
alias("{{alias}}")
{% endfor %}
{% block add_fields %}{% endblock %}
{% for f in record.fields%}
field({{f}}, "{{record.fields[f]}}")
{% endfor %}
{% if record.autosave['pass1'] %}
info(autosaveFields, "{{ record.autosave['pass1'] | sort | join(' ') }}")
{% endif %}
{% if record.autosave['pass0'] %}
info(autosaveFields_pass0, "{{ record.autosave['pass0'] | sort | join(' ') }}")
{% endif %}
{% if record.archive_settings %}
{% if record.archive_settings['method'] == 'scan' and record.archive_settings['seconds'] == 1 %}
info(archive, "{{ record.archive_settings['fields'] | join(' ') }}")
{% else %}
info(archive, "{{ record.archive_settings['method'] }} {{ record.archive_settings['seconds'] }}: {{ record.archive_settings['fields'] | join(' ') }}")
{% endif %}
{% endif %}
{% if record.direction == "input" %}
field(ASG, "NO_WRITE")
{% endif %}
}