Index
+ +A
+B
++ | + |
C
++ | + |
D
++ | + |
E
+F
++ | + |
G
+H
++ |
I
++ | + |
K
++ |
L
++ | + |
M
+
|
+ + |
N
++ | + |
O
++ | + |
P
+Q
++ |
R
++ | + |
S
+T
+U
++ | + |
V
++ | + |
W
++ | + |
diff --git a/index.html b/index.html index 5191393..400814d 100644 --- a/index.html +++ b/index.html @@ -1,9 +1,9 @@
- + -Go to the default documentation.
+Go to the default documentation.
\ No newline at end of file diff --git a/v2.17.0/_sources/getting_started.rst.txt b/v2.17.0/_sources/getting_started.rst.txt new file mode 100644 index 0000000..182a4cb --- /dev/null +++ b/v2.17.0/_sources/getting_started.rst.txt @@ -0,0 +1,68 @@ +Getting Started +=============== + +General Usage ++++++++++++++ +pytmc has various capabilities that can be accessed using the top-level ``pytmc`` program: + + 1. Generating EPICS database files (.db) based on a Beckhoff TwinCAT ``.tmc`` file (``pytmc db``) + 2. Introspecting ``.tmc`` files for their symbols and data types ( ``pytmc debug`` and ``pytmc types``) + 3. Generating full EPICS IOCs based on a provided template (``pytmc iocboot`` and ``pytmc stcmd``) + 4. Parsing, introspecting, and summarizing full TwinCAT projects (``pytmc summary``) + 5. Outlining any TwinCAT XML file (``pytmc xmltranslate``) + +In order for pytmc to work properly, the TwinCAT project and its +libraries require annotation. The resulting IOC depends upon EPICS ADS driver. This +driver is provided by the `European Spallation Source +Note
" + + "" + msg + "
"; + var parent = document.querySelector('div.body') + || document.querySelector('div.document') + || document.body; + parent.insertBefore(warning, parent.firstChild); + } + + +} + +function addVersionsMenu() { + // We assume that we can load versions.json from + // https://' + + '' + + _("Hide Search Matches") + + "
" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/v2.17.0/genindex.html b/v2.17.0/genindex.html new file mode 100644 index 0000000..be84746 --- /dev/null +++ b/v2.17.0/genindex.html @@ -0,0 +1,801 @@ + + + + + ++ | + |
+ | + |
+ | + |
+ | + |
+ |
+ | + |
+ |
+ | + |
|
+ + |
+ | + |
+ | + |
+ |
+ | + |
+ | + |
+ | + |
+ | + |
pytmc has various capabilities that can be accessed using the top-level pytmc
program:
+++
+- +
Generating EPICS database files (.db) based on a Beckhoff TwinCAT
.tmc
file (pytmc db
)- +
Introspecting
.tmc
files for their symbols and data types (pytmc debug
andpytmc types
)- +
Generating full EPICS IOCs based on a provided template (
pytmc iocboot
andpytmc stcmd
)- +
Parsing, introspecting, and summarizing full TwinCAT projects (
pytmc summary
)- +
Outlining any TwinCAT XML file (
pytmc xmltranslate
)
In order for pytmc to work properly, the TwinCAT project and its +libraries require annotation. The resulting IOC depends upon EPICS ADS driver. This +driver is provided by the European Spallation Source and is hosted on their bitbucket page.
+Marking the TwinCAT project determines how the EPICS record will be generated. +The marking process uses custom attribute pragmas to designate variables for +pytmc to process. The pragma should be applied just above the declaration of +the variable you wish to mark. You can read more about the TwinCAT pragma +system here.
+Best practices for SLAC projects are documented in the PCDS confluence page.
+Having issues with multiline pragmas and related things? See the PCDS flight +rules.
+Once installed pytmc and its components can be imported into a python program +or shell like any normal python package. Consult the source code documentation +for specifics.
+PCDS has recently focused its efforts on ads-deploy, for seamless development and +deployment of IOCs directly from the TwinCAT IDE. Behind the scenes, ads-deploy +takes care of the following steps using a docker container:
+$ git clone https://github.com/pcdshub/ads-ioc /path/to/ads-ioc
+$ pytmc iocboot /path/to/plc.tsproj /path/to/ads-ioc/iocBoot/templates/
+# Creates directories: ioc-plc-name1, ioc-plc-name2, ...
+# Creates Makefiles: ioc-plc-name/Makefile
+
+$ cd ioc-plc-name
+$ vim Makefile
+# Customize - if necessary - to add more db files or change pytmc stcmd options
+
+$ make
+# Shells out to pytmc stcmd;
+# Creates st.cmd, ioc-plc-name.db, envPaths
+
+$ ./st.cmd
+# Runs IOC
+
Pytmc helps developers automatically generate ADS based Epics records files +from Beckhoff’s TwinCAT3 projects.
+Pytmc is developed with these guidelines in mind.
+The source code is hosted on github.
+Issues and requests can be posted on the github issue tracker. Use the bug
tag for issues
+with intended features and the enhancement
tag can be used for feature
+requests. The question
tag will be treated like an ‘enhancements’ tag for
+the documentation but regular questions can be posted there as well.
SingularChain
+chains_from_symbol()
dictify_config()
expand_configurations_from_chain()
find_pytmc_symbols()
get_array_suffix()
get_pragma()
has_pragma()
make_fake_symbol_from_data_type()
normalize_config()
normalize_io()
parse_archive_settings()
parse_array_settings()
parse_update_rate()
record_packages_from_symbol()
separate_configs_by_pv()
split_field()
split_pytmc_pragma()
squash_configs()
BinaryRecordPackage
EPICSRecord
+EnumRecordPackage
FloatRecordPackage
+IntegerRecordPackage
RecordPackage
+StringRecordPackage
+TwincatTypeRecordPackage
TwincatTypeRecordPackage.asyn_input_port_spec
TwincatTypeRecordPackage.asyn_output_port_spec
TwincatTypeRecordPackage.asyn_update_options
TwincatTypeRecordPackage.generate_input_record()
TwincatTypeRecordPackage.generate_output_record()
TwincatTypeRecordPackage.io_direction
TwincatTypeRecordPackage.records
WaveformRecordPackage
+generate_archive_settings()
make_autosave_defaults()
sort_fields()
Action
ArrayInfo
+Axis
AxisPara
BaseType
BitOffs
BitSize
BoundDataType
Box
BuiltinDataType
Compile
DUT
+DataArea
DataType
+DataTypes
+Declaration
DefaultResolution
Device
EncPara
Encoder
Entry
+EnumInfo
EnumerationTextList
+EtherCAT
ExtendsType
+GVL
+Get
Implementation
+Instance
+Io
LibraryReference
Link
+Method
Module
+NC
+Name
Namespace
OwnerA
OwnerB
POU
+Pdo
PlaceholderReference
PlaceholderResolution
Plc
+PlcProject
Property
+RemoteConnections
+Resolution
ST
Safety
SafetyPlc
Set
SubItem
+Symbol
+Symbol_DUT_MotionStage
Symbol_ST_MotionStage
+System
T_MaxString
Task
+Tasks
+TcModuleClass
+TcSmItem
TcSmProject
+TopLevelPlc
+TopLevelProject
+Type
+case_insensitive_path()
element_to_class_name()
get_data_type_by_reference()
parse()
projects_from_solution()
separate_by_classname()
strip_namespace()
Download the code via the tagged releases posted on the github releases page or by cloning the source code +with the following:
+$ git clone https://github.com/pcdshub/pytmc.git
+
Create a python virtual environment using conda and install the pytmc in that +environment.
+Begin by creating an environment and replacing [env-name] with the +name of your environment. If you’re installing pytmc in a preexisting +environment, you may skip this step.
+$ conda create --name [env-name]
+
Activate your environment.
+$ source activate [env-name]
+
Install pip in the current environment if it is not already. If pip is not +installed in your environment, the system will default to using pip in the root +environment. When the root environment’s version of pip is used. Pip will +attempt to install the package in the root envirnoment as well.
+$ conda install pip
+
After cloning or unzipping the package, navigate to the base directory of
+pytmc. There you will find a file titled setup.py
and another titles
+requirements.txt
. Run the following commands from this directory. Make sure
+to install pip in this conda environment prior to installing tools with pip.
+Using pip in an environment lacking a pip installation will install pytmc in
+your root environment.
$ # Install pytmc's dependencies
+$ pip install -r requirements.txt
+$ # Install pytmc to your environment
+$ pip install .
+
Note
+The last line in the code snippet above has a ‘.’ at the end. It is very +difficult to see with certain browsers.
+If you’ve followed the previous steps correctly, pytmc should be installed now. +This can be tested by seeing if the following bash commands can be found.
+$ pytmc --help
+
Alternatively, a python shell can be opened and you can attempt to import +pytmc.
+>>> import pytmc
+
Note
+While all of these instructions should work with python environments +managed by virtualenv and pipenv, only conda has been tested.
+To develop pytmc it is best to use a development install. This allows changes +to the code to be immediately reflected in the program’s functionality without +needing to reinstall the code.This can be done by following the Installing in +an environment section but with one change. The following code snippet should +be removed:
+$ # Don't use this step for a development install
+$ pip install .
+
In place of the removed command, use the following to do a development install.
+$ # Use this command instead
+$ pip install -e .
+
Pytmc is capable of generating most of the DB file but some settings require +human direction. Developers set this configuration by adding an attribute +pragma to TwinCAT3 variables when they’re declared. These pragmas can be +appended to variables in project files and library files.
+TwinCAT data types and their corresponding record types are as follows:
+Data type |
+Lower bound |
+Upper bound |
+Memory space |
+Record Type |
+Scalar DTYP |
+Waveform DTYP |
+
---|---|---|---|---|---|---|
BOOL |
+0 |
+1 |
+8 bit |
+bi, bo |
+asynInt32 |
+asynInt8ArrayIn, asynInt8ArrayOut |
+
BYTE |
+0 |
+255 |
+8 bit |
+longin, longout |
+asynInt32 |
+asynInt8ArrayIn, asynInt8ArrayOut |
+
SINT |
+-128 |
+127 |
+8 bit |
+longin, longout |
+asynInt32 |
+asynInt8ArrayIn, asynInt8ArrayOut |
+
USINT |
+0 |
+255 |
+8 bit |
+longin, longout |
+asynInt32 |
+asynInt8ArrayIn, asynInt8ArrayOut |
+
WORD |
+0 |
+65535 |
+16 bit |
+longin, longout |
+asynInt32 |
+asynInt16ArrayIn, asynInt16ArrayOut |
+
INT |
+-32768 |
+32767 |
+16 bit |
+longin, longout |
+asynInt32 |
+asynInt16ArrayIn, asynInt16ArrayOut |
+
UINT |
+0 |
+65535 |
+16 bit |
+longin, longout |
+asynInt32 |
+asynInt16ArrayIn, asynInt16ArrayOut |
+
ENUM |
+0 |
+4294967295 |
+32 bit |
+longin, longout |
+asynInt32 |
+asynInt16ArrayIn, asynInt16ArrayOut |
+
DWORD |
+0 |
+4294967295 |
+32 bit |
+longin, longout |
+asynInt32 |
+asynInt32ArrayIn, asynInt32ArrayOut |
+
DINT |
+-2147483648 |
+2147483647 |
+32 bit |
+longin, longout |
+asynInt32 |
+asynInt32ArrayIn, asynInt32ArrayOut |
+
UDINT |
+0 |
+4294967295 |
+32 bit |
+longin, longout |
+asynInt32 |
+asynInt32ArrayIn, asynInt32ArrayOut |
+
LWORD |
+0 |
+2**64-1 |
+64 bit |
+N/A |
+N/A |
+N/A |
+
LINT |
+-2**63 |
+2**63-1 |
+64 bit |
+N/A |
+N/A |
+N/A |
+
ULINT |
+0 |
+2**64-1 |
+64 bit |
+N/A |
+N/A |
+N/A |
+
REAL |
+-3.4E+38 |
+3.4E+38 |
+32 bit |
+ai, ao |
+asynFloat64 |
+asynFloat32ArrayIn, AsynFloat32ArrayOut |
+
LREAL |
+-1.797693134862316e+308 |
+1.797693134862358e+308 |
+64 bit |
+ai, ao |
+asynFloat64 |
+asynFloat64ArrayIn, AsynFloat64ArrayOut |
+
STRING |
++ | + | Varies |
+waveform |
+asynFloat64 |
+asynInt8ArrayIn, asynInt8ArrayOut |
+
Lines marked as N/A are not supported by pytmc.
+At a minimum, developers must specify a PV. Specifying an IO direction for each +field is recommended but not required. This would look like the following:
+{attribute 'pytmc' := '
+ pv: TEST:MAIN:SCALE
+ io: i
+'}
+scale : LREAL := 0.0;
+
The {attribute 'pytmc' := '
and '}
specify the beginning and end of the
+pragma that pytmc will recognize. The middle two lines specify the
+configuration for this variable.
Pytmc uses a custom system of configuration where newlines and white space in
+a line is important. All lines begin with a title and the title ends before the
+colon. All parts thereafter are the ‘tag’ or the configuration state for this
+setting. Some title types such as field
can have multiple settings for a
+single PV.
A pragma could have multiple fields specified. For example, an ai
record
+TEST:MAIN:SCALE
would be generated from the following, with a slope of
+2.0 and an offset of 1.0, updating only at a rate of once per second:
{attribute 'pytmc' := '
+ pv: TEST:MAIN:SCALE
+ io: i
+ field: AOFF 1.0
+ field: ASLO 2.0
+'}
+scale : LREAL := 0.0;
+
This is an example of the simplest configuration a developer can provide to +instantiate a variable.
+{attribute 'pytmc' := '
+ pv: TEST:MAIN:SCALE
+ io: i
+'}
+scale : LREAL := 0.0;
+
The developer must specify the PV name (pv:
line). All other fields are
+optional. We recommend that the user specify the direction of the
+data (io:
line) however.
Pytmc needs no additional information but users have the option to override +default settings manually. For information on all the pragma fields, consult +the Pragma fields section.
+Variables declared inside of data structures can be processed by pytmc so long +as each level of encapsulation, all the way down to the first level, is marked +for pytmc.
+The instantiation of encapsulating data types only needs the pv:
line. The
+instantiation of a function block could resemble the following:
{attribute 'pytmc' := '
+ pv: TEST:MAIN:COUNTER_B
+'}
+counter_b : counter;
+
A variable declared within the counter
function block could resemble the
+following:
{attribute 'pytmc' := '
+ pv: VALUE
+ io: i
+'}
+value_d : DINT;
+
When combined, the PV specified at the instantiation of the user-defined data
+type will be appended to the beginning of the PV for all data types defined
+within. Each step further into a data structure can add an additional section
+to the PV. In the example above the final PV will be
+TEST:MAIN:COUNTER_B:VALUE
. The colons are automatically included.
This can be recursively applied to data types containing data types.
+Information other than the PV name name can be specified at the datatype +instantiation if you wish to make generalizations about the variables +contained inside. These generalizations are overridden if the same field is +specified either on a contained datatype or variable.
+For example the following code block will assign a field:
of DESC test
+to all the variables and datatypes that it contains unless they
+specify their own setting for DESC
.
{attribute 'pytmc' := '
+ pv: BASE
+ field: DESC test
+'}
+counter_b : counter;
+
{attribute 'pytmc' := '
+ pv: VALUE_F_R
+ field: DESC test
+ io: i
+'}
+value_d : DINT;
+
In instances where a single TwinCAT variable should be able to be both written +and read, multiple PVs can be specified. This allows multiple EPICS records to +be tied to a single TwinCAT variable.
+{attribute 'pytmc' := '
+ pv: TEST:MAIN:ULIMIT
+ io: io
+'}
+upper_limit : DINT := 5000;
+
In this case, two records will be generated: TEST:MAIN:ULIMIT
and
+TEST:MAIN:ULIMIT_RBV
.
By default, structures with a pragma will generate PVs for each array index, +including all encapsulated sub-elements that also have an associated pragma.
+Depending on the number of elements in the array, the PV name will be +zero-padded to aid in future expansion. Reminding ourselves that array bounds +are inclusive in TwinCAT, the following pragma:
+{attribute 'pytmc' := '
+ pv: MY:ARRAY
+'}
+myStructure : ARRAY [0..5] of DUT_MyStructure
+
would generate these prefixes:
+MY:ARRAY:00:
+MY:ARRAY:01:
+MY:ARRAY:02:
+MY:ARRAY:03:
+MY:ARRAY:04:
+MY:ARRAY:05:
+
The formatting of this may be customized, but it is not recommended to do so
+in general. Adding expand: :%.3d
would extend the zero-padding to 3 digits,
+regardless of the number of array elements.
It is also possible to select individual elements or a range of elements from
+a large array by way of the array
pragma.
To include only the first 2 elements (0 and 1) of this large 101 element array, +the following pragma could be used:
+{attribute 'pytmc' := '
+ pv: MY:ARRAY
+ array: 0..1
+'}
+myStructure : ARRAY [0..100] of DUT_MyStructure
+
The array pragma is flexible, allowing for the following:
+Array Pragma |
+Elements Selected |
+
---|---|
0, 1, 2 |
+0, 1, 2 |
+
0..2 |
+0, 1, 2 |
+
99.. |
+99, 100 |
+
..5 |
+0, 1, 2, 3, 4, 5 |
+
..5, 99 |
+0, 1, 2, 3, 4, 5, 99 |
+
Format: {field}: [value]
A pragma key or field (before the :
) and the value after the :
are used
+to generate records in EPICS.
This constructs the PV name that will represent this variable in EPICS. It is +the only mandatory configuration line. This line can be used on specific +variables as well as the instantiations of data types.
+Note
+$
may not be used in pragmas due to some TwinCAT limitations as of
+version 4024. An alternative character @
may be used in its place for
+pv names. This can also be customized using the macro_character
pragma
+key.
This is a field that defaults to ‘io’. Specify the whether the IOC can only
+read or also write the value. Values being sent from the PLC to the IOC should
+be marked as input with input
(or equivalently i
, ro
) and values
+being sent to the PLC from the IOC should be marked output
(or equivalently
+o
, rw
).
Note
+The following are valid for input-only (read-only) pragmas: input
, i
,
+and ro
.
The following are valid for input-output (read-write) pragmas: output
, io
,
+rw
, and o
.
Format: update: {rate}{s|Hz} [{poll|notify}]
Example: 1s
, 1s poll
, 2Hz notify
By default, any given PLC variable will be polled at a rate of T=1s (1Hz). +Other poll rates planned to be available by default may be selected on a +per-record (*) basis: T=.5s (2Hz), T=1s (1Hz), T=2s (.5hz), T=10s (.1Hz), and +T=50s (.02Hz), or as configured by the IOC startup script.
+By default, any given PLC variable will be bundled together to be polled at a +fixed rate. This is the recommend means of using the ADS IOC. Using one of the +default polling rates is the only supported method currently, though these +might be configurable in the future in the IOC startup script. New poll rates +cannot be created in the TwinCAT code.
+To customize the polling rate, specify the desired rate in either seconds or
+hertz in an update
pragma key. For example:
update: 1Hz
+update: 1s
+update: 0.5s
+update: 2Hz
+
The keyword poll
can also be used to explicitly mark it for polling:
update: 1s poll
+
For faster rates, an ADS concept of notifications, can be used. These are
+conceptually similar to callback-on-change in Python or camonitor
in the
+context of EPICS.
Use the notify
keyword in the update
setting to enable this:
update: 10Hz notify
+update: 0.1s notify
+
Note
+Adding too many of these notifications can significantly slow down a PLC,
+even when specified at slow rates. As such, notify
should be used
+sparingly.
(*) This is on the wishlist for ads-ioc. As of December 2019, all polled +records will be processed at a rate of 1 Hz/the IOC-configured poll rate.
+Integer and floating point values may have an EPICS-side scaling applied.
+Example:
+scale: 3.0
+offset: 1.0
+
Values will be scaled according to the following:
+readback_value = raw_value * scale + offset
+setpoint_value = (user_value - offset) / scale
+
Note
+If either scale
or offset
are applied to an integer symbol, the
+generated EPICS record type will no longer be a “long” integer input/output
+record but rather change to an analog input/output record.
Keep this in mind if using advanced “field” directives in your pragmas.
+If unspecified, scale
will be assumed to be 1.0 and offset
0.0.
Format: archive: {rate}{s|Hz} [{scan|monitor}]
Example: 1s
, 1s scan
, 2Hz monitor
Using the database-generating tool pytmc db
along with the pragma key
+archive
will automatically generate archiver appliance cron-job compatible
+.archive
files (i.e., those in $IOC_DATA/$IOC/archive/*.archive
).
+The cron job will read these files and automatically configure the archiver
+to archive the listed PVs.
Without an archive
pragma key, the default setting is 1s scan
. This
+means that your PVs will be archived at a rate of once per second, using the
+scan
method.
For more information on the two methods, see the EPICS Archiver Appliance +documentation.
+Note
+If the update frequency is slower than the specified archive frequency, the +archive frequency will be reduced.
+Note
+Large arrays will not be archived, regardless of pragma settings.
+Note
+Additional fields can be specified for archiving through the archive_fields
+key, which is a space-delimited list of field names.
Example: archive_fields: DESC PREC
This specifies additional field(s) to be set on the generated EPICS record(s). +Multiple field lines are allowed. These lines determine the PV’s behaviors such +as alarm limits and scanning frequency.
+The format is as follows:
+field: FIELD_NAME field value
+
This would correspond to a field in the record being generated as follows:
+record(ai, "my_record") {
+ ...
+ field(FIELD_NAME, "field value")
+}
+
While the SCAN
field is special in EPICS to specify the rate at which
+records should be updated, pytmc requires that such configuration be done
+through the update
pragma key (see Update rate).
Autosave fields for individual EPICS records are configured by default with +pytmc. It is possible to customize this behavior with additional pragmas, +optionally specifying different fields for input or output records.
+Pass 0 indicates restoring information prior to record initialization on IOC
+initialization, whereas pass 1 indicates restoring information after record
+initialization. Pass 0 is generally safe and does not cause record processing,
+whereas pass 1 is just as if one were to caput
to the record after starting
+the IOC. When in doubt, use pass 0 and/or ask an EPICS expert.
To apply to either input or output records, pragma keys autosave_pass0
or
+autosave_pass1
can be used.
To only apply to input records, pragma keys autosave_input_pass0
+autosave_input_pass1
can be used.
To only apply to output records, pragma keys autosave_output_pass0
+autosave_output_pass1
can be used.
For example, a pragma like the following:
+autosave_pass0: VAL DESC
+
Would result in both input and output records having these fields marked for +autosaving:
+record(ai, "my:record_RBV") {
+ ...
+ info(autosaveFields_pass0, "VAL DESC")
+}
+
+record(ao, "my:record") {
+ ...
+ info(autosaveFields_pass0, "VAL DESC")
+}
+
There is a special syntax to pragma a member of a structure differently +depending on the instance.
+Given this example function block:
+FUNCTION_BLOCK FB_Test
+VAR
+ {attribute 'pytmc' := 'pv: variable1'}
+ variable1 : LREAL := 0.0;
+
+ {attribute 'pytmc' := 'pv: variable2'}
+ variable2 : LREAL := 0.0;
+END_VAR
+END_FUNCTION_BLOCK
+
Adding these pragmas to two instances:
+{attribute 'pytmc' := '
+ pv: TEST:A
+ variable1.io: i
+ variable2.io: i
+'}
+fbTestA : FB_Test;
+
+{attribute 'pytmc' := '
+ pv: TEST:B
+ variable1.io: io
+ variable2.io: io
+'}
+fbTestB : FB_Test;
+
The above would result in two different io
settings for
+fbTestA.variable1
and fbTestB.variable1
.
There are some limitations on this preliminary feature. You may not add or +change the following fields for now:
+pv
+link
+field
+
The primary use case is expected to be array
, to limit the number of array
+instances generated with hard-coded upper bounds on encapsulated structures.
+ p | ||
+ |
+ pytmc | + |
+ |
+ pytmc.linter | + |
+ |
+ pytmc.parser | + |
+ |
+ pytmc.pragmas | + |
+ |
+ pytmc.record | + |
pytmc template
, which takes a TwinCAT project and jinja template source
+code to generate project-specific output, now expects all platforms to use
+the same delimiter (":"
) for template filename patterns. Examples include:
Read template from a.template
and write expanded version to a.txt
:
+pytmc template my.tsproj --template a.template:a.txt
Read template from a.template
and write results to standard output:
+pytmc template my.tsproj --template a.template
Read template from standard input and write results to standard output:
+pytmc template my.tsproj --template -
Read template from standard input and write results to /path/to/a.txt
:
+pytmc template my.tsproj --template -:/path/to/a.txt
Extended support for projects not correctly configured in TwinCAT with +“Independent Files” for all supported options. Generating EPICS IOCs +from such projects that also include NC axes should succeed with +a number of loud warnings to the user.
Fixed old release note syntax.
Type aliases will now find pytmc pragmas defined on their base types. +Previously these were ignored.
ST_MotionStage is now the canonical name for the motor struct, +matching our twincat style guide. Backwards compatibility is retained +for projects using DUT_MotionStage.
Fix an issue where macro substitution did not load properly for +motor base PVs in the st.cmd file generation.
Fix an issue where the version could fail to load in an edge case +where a git clone was included via symbolic link.
Ensure workflow secrets are used properly.
Fix issues related to documention building on the Github actions CI.
Python 3.9 is now the minimum supported version for pytmc.
+Fixes pre-commit repository settings for flake8.
Migrates from Travis CI to GitHub Actions for continuous integration testing, and documentation deployment.
Updates pytmc to use setuptools-scm, replacing versioneer, as its version-string management tool of choice.
Syntax has been updated to Python 3.9+ via pyupgrade
.
pytmc has migrated to modern pyproject.toml
, replacing setup.py
.
Sphinx 6.0 now supported for documentation building.
docs-versions-menu
is now used for documentation deployment on GitHub Actions.
This release doesn’t change any behavior of the library, but it does fix an error in the test suite that causes false failures.
+TST: test suite was using old kwarg, swap to new by @ZLLentz in #296
Safety PLC files loaded from _Config/SPLC by @klauer in https://github.com/pcdshub/pytmc/pull/289
Sort generated records by TwinCAT symbol name (tcname) by @klauer in https://github.com/pcdshub/pytmc/pull/293
The order of records in EPICS process database (.db) files will change for most users after this release. After the initial rebuild, users should expect to see smaller diffs on subsequent PLC project rebuilds.
Add all hooks required to allow transition of pytmc stcmd -> template by @klauer in https://github.com/pcdshub/pytmc/pull/290
+Adds helper commands to pytmc template, which can be used in Jinja templates:
+generate_records (create .db and .archive files)
get_plc_by_name
get_symbols_by_type
Adds variables to pytmc template environment, which can be used in Jinja templates: pytmc_version
Adds –macro option to pytmc template
Fixes some annotations + uncovered/untested functionality
Allows pytmc template to read/write multiple templates with parsing a project only once
Adds description field to autosave for all records, input and output
Adds alarm severity and limit fields to autosave for all relevant input and output records
Adds control limit (drive low/high) fields to autosave for relevant output records
CP link instead of CPP link by @klauer in https://github.com/pcdshub/pytmc/pull/283
Address CI-related failures and update pre-commit settings by @klauer in https://github.com/pcdshub/pytmc/pull/285
Jinja2 3.1 compatibility fix
Additional tests
Add EnumerationTextList
with get_source_code
support.
+Previously, these translatable types were missing.
Add actions, methods, and properties to the pytmc code
output.
Allow for pytmc code
to work with just a single code object,
+rather than requiring the whole project.
Add pytmc.__main__
such that
+python -m pytmc {code,summary} ...
works.
Fix rare bug in lines_between function, probably never hit.
Type annotation cleanups and fixes
Reduce memory consumption slightly by not caching the xml element +on every TwincatItem
Allow strings to be linked using the link:
pragma key. Previously,
+this was only implemented for numeric scalar values.
Added scale
and offset
pragma keys for integer and floating point
+symbols.
Fixed remaining slaclab
references, after the repository was moved to
+pcdshub
.
Add git information to the template tool if available.
Fix issues related to insufficient library dependency checking. Now, +all possible places where library version information is stored will +be checked.
Refactor the dependency-related twincat items and templating tools +to accomplish the above.
Move the repository landing zone from slaclab to pcdshub to take +advantage of our travis credits.
Redeploy doctr for pcdshub.
Add support for externally adding pragmas to members of structures and +function blocks.
Add support for partial pragmas of array elements.
Added text filter in pytmc debug
dialog.
Check maximum record length when generating the database file. This is a +constant defined at epics-base compile time, defaulting to 60.
Record names now displaying correctly in pytmc debug
dialog.
pytmc debug
no longer fails when it encounters types that extend
+built-in data types by way of ExtendsType
.
Fix issue with pass1 autosave not appropriately writing values to the PLC +on IOC startup.
Regenerate doctr deploy key.
Added handling for case where pragma is None
Lower array archive threshold to arrays with fewer than 1000 elements +to prevent our high-rate encoder and power meter readbacks. This is a good +threshold because it represents 1000Hz data with a 1Hz polling rate, a +very typical parameter.
Default APST and MPST fields to “On Change” for waveform PVs. These are +special waveform fields that tell monitors and the archiver when to take an +update, and previously they were set to “Always”, causing influxes of data +from static char waveform strings.
Split dev/docs requirements
Fix jinja naming
Relaxed end-of-pragma-line handling (any combination of ;
and newline are
+all accepted).
Reworked XTI file loading for “devices” and “boxes”. This aims to be more
+compatible with TwinCAT, which does not always relocate XTI files to be in
+the correct hierarchical directory location. It pre-loads all XTI files, and
+when the project is fully loaded, it dereferences XTI files based on a key
+including class
, filename
, and a small PLC-unique identifier
.
Better handling of data types in the project parser. Now supports data type +GUIDs, when available, for data type disambiguation. Note that these are not +always present.
Better handling of references, pointers, and pointer depth.
pytmc db --debug
allows developers to more easily target exceptions
+raised when generating database files.
Added more memory layout information for the benefit of other utilities such
+as ads-async
. Its ADS server implementation in conjunction with pytmc may
+be a good source of information regarding PLC memory layout in the future.
Started adding some annotations for clarity. May retroactively add more as +time permits.
Working fix for macro expansion character replacement for linked PVs
+(DOL
field). This means link: @(MACRO)PV
now works.
Tests will no longer be installed erroneously as a package on the system.
Tests have been moved into the pytmc package, and with it flake8 compliance.
Included an incomplete fix for macro expansion character replacement for
+linked PVs (DOL
field)
Fixes pragmalint bug that fails on an empty declaration section
Fixes issue where qtpy/pyqt not being installed may cause pytmc
+command-line tools to fail
Project-level data type summary
Create DataArea for data type summary if unavailable in .tmc
Add info(archive)
nodes for ads-ioc
+(#188)
Adjust defaults for binary record enum strings +(#191)
Better messages on pragma parsing failures +(#200)
Do not include fields only intended for input/output records in the +other (#205)
(Development) Fix package manifest and continuous integration
Fix FB_MotionStage pointer-handling in st.cmd generation
Fix off-by-one array bounds error
Expose actions in summary + generate more readable code block output
Fix autosave info node names
Ensure --allow-errors
is passed along to the database generation
+step when using pytmc stcmd
Allow pytmc db
to work with the .tsproj
file along with
+.tmc
file
Add initial “PV linking” functionality (to be completed + documented; +paired with lcls-twincat-general)
Fix bug where Enum info may be missing from the .tmc file
Show the chain name of a failed record generation attempt
Fix loading of _Config/IO
files in certain cases, though there is
+still work to be done here
+(#187
Debug tool option for showing variables which do not generate records (#159) “incomplete pragmas/chains”
Automatic generation of archive support files (#162)
Support customization of update rates via poll/notify (#151), looking forward to new m-epics-twincat-ads releases
Support record aliases (#150)
Description defaults to PLC variable path if unspecified (#152)
Pinned global variables are supported
Autosave support
Pypi integration
Linter/Debugger improvements
Debug shows relative paths
Record sorting is now deterministic
Fixed an issue where Enums weren’t being handled correctly
pytmc now allows the declaration/implementation to be None
allowing these
+sections to be empty without breaking
Some windows file reading issues have been resolved
Move pragma checking code to from Datatype.walk
to SubItem.walk
for
+an implementation more consistent with Symbol.walk
Add Support For NC axis parameters
.sln
files may now be passed to pytmc summary
pytmc
now identifies and handles T_MaxString
Adds support for arrays of complex datatypes.
Replaces FB_MotionStage support with DUT_MotionStage.
Converts ’_’ in project name in TC3 to ‘-’ in ioc name following convention.
stcmd
generation updated to match changes to pragmas
functionality solving some incompatibilites
Switch to DUT_MotionStage namespace allows motors above 0-9 range.
This tag includes the new pragma linting features for assessing whether +TwinCAT3 projects are PyTMC compatible.
+This feature can be accessed using this command:
+pytmc pragmalint [-h] [--markdown] [--verbose] filename
Pragmas can now be delimited with semicolons # Bugfixes
Spaces after the first semicolon in a pragma no longer break pragmas
Blank PV strings no longer lead to the creation of multiple colons in +a PV name
Single line pragmas are properly recognized now
This release rectifies several issues with the command line interface.
+The primary command is now pytmc
replacing the old makerecord
.
Tests for python 3.7 have been implemented.
+Incorporate support for a greater set of TwinCAT Datatypes.
+First major release.
+Primary features of .db and .proto file creation have been implemented. +Compatibility with enums, aliases, waveforms/arrays, field guessing +tools, and a user guide have not been implemented.
+This file contains the objects for taking in pytmc-parsed TMC files and +generating Python-level configuration information.
+Bases: object
A chain of data types, all with pytmc pragmas, representing a single piece +of data that should be accessible via EPICS/ADS
+item_to_config (dict) – Keys would be TwincatItem
s such as Symbol, and values would be
+dictionary configurations from parsed pytmc pragmas.
dict
+The chain of items (i.e., item_to_config keys)
+list
+The full TwinCAT name of the item
+str
+The user-specified PV name
+str
+The last item, which determines the overall data type
+list
+The final configuration based on the full chain of configurations
+dict
+Build all SingularChain instances from a Symbol
+Make a raw config list into an easier-to-use dictionary
+{‘title’: ‘io’, ‘tag’: ‘io_for_a’}, +{‘title’: ‘field’, ‘tag’: {‘f_name’: ‘fieldname’, ‘f_set’: ‘value’}}, +]
+Becomes:
+{'pv': 'a',
+ 'io': 'io_for_a',
+ 'field': {'fieldname': 'value'}}
+
Generate all possible configuration combinations
+For example, from a chain with two items:
+[item1, item2]
+
The latter of which has a configuration that creates two PVs (specified by +configuration dictionaries config1, config2), this function will return:
+[
+ [(item1, config1), (item2, config1)],
+ [(item1, config1), (item2, config2)],
+]
+
Special handling for arrays of complex types will unroll the array into +individual elements. That is, arr : ARRAY [1..5] of ST_Structure will be +unrolled into arr[1] through arr[5].
+Tuple of tuples. See description above.
+tuple
+Find all symbols in a tmc file that contain pragmas
+Return array index suffix based on the expand settings in the config.
+Get all pragmas with a certain tag.
+item (parser.SubItem, parser.Symbol, parser.Symbol subclass) – Representation of beckhoff variable or data structure
name (str, optional) – Accept tmc entries where the <Name> field equals the passed string
str
+Generator
[str
, None
, None
]
Does item have a pragma titled name?
+Create a _FakeSymbol
from the given data type.
data_type (pytmc.parser.DataType) – The TMC data type.
symbol_pragma_text (str) – The pragma text to attach.
name (str, optional) – The symbol name.
pragma_name (str, optional) – The pragma name to use (defaults to “pytmc”).
data_area_index (int, optional) – The data area to pretend the symbol exists in.
Parse and normalize pragma values into Python representations
+The following keys will be interpreted: io
, archive
, update
config (dict) – The configuration
+A shallow-copy of config
with parsed and normalized values
dict
+Normalize an ‘io’ specifier in a pragma into either ‘input’ or ‘output’
+io (str) – The I/O specifier from the pragma
+{‘input’, ‘output’}
+ValueError – If an invalid specifier is given
+Parse an ‘archive’ specifier in a pragma
+archive (str) – The archive specifier from the pragma.
+With keys {‘seconds’, ‘frequency’, ‘method’} +Where ‘method’ is one of: {‘scan’, ‘monitor’}
+dict
+ValueError – If an invalid pragma is supplied
+Parse an ‘array’ specifier in a pragma, yielding array elements.
+pragma (str) – The I/O specifier from the pragma.
dimensions (2-tuple) – Lower and upper-bound of the array corresponding to the pragma.
element (int) – Integer element of selected array indices.
+ValueError – If an invalid pragma is supplied
+Parse an ‘update’ specifier in a pragma
+update (str) – The update rate specifier from the pragma.
+With keys {‘seconds’, ‘frequency’, ‘method’} +Where ‘method’ is one of: {‘poll’, ‘notify’}
+dict
+ValueError – If an invalid pragma is supplied
+Create all record packages from a given Symbol
+Take in a pre-parsed pragma such as:
+[{'title': 'pv', 'tag': 'a'},
+ {'title': 'io', 'tag': 'io_for_a'},
+ {'title': 'pv', 'tag': 'b'},
+ {'title': 'io', 'tag': 'io_for_a'},
+ ]
+
Which was generated from:
+pv: a
+io: io_for_a
+pv: b
+io: io_for_b
+
And yield the following:
+('a', [{'title': 'io', 'tag': 'io_for_a'}])
+('b', [{'title': 'io', 'tag': 'io_for_b'}])
+
When applied to field line’s tag, break the string into its own dict
+string (str) – This is the string to be broken into field name and field setting
+Keys are ‘f_name’ for the field name and ‘f_set’ for the corresponding +setting.
+dict
+Return dictionaries for each line. +Derived from raw_config
+raw_config (str) – completely unformatted string from configuration. Defaults to +raw_config.
+This list contains a dictionary for each line broken up into two +keys: ‘title’ and ‘tag’.
+list
+Take a list of configurations, and squash them into one dictionary
+The key ‘pv’ will be a list of all PV segments found.
+Later configurations override prior ones.
+*configs (list of dict) – Configurations to squash. Original configs will not be modified.
+Record generation and templating
+Bases: TwincatTypeRecordPackage
Create a set of records for a binary Twincat Variable
+Bases: object
Representation of a single EPICS Record
+Render the provided template
+Update autosave settings from a pragma configuration
+To apply to either input or output records, pragma keys +autosave_pass0 or autosave_pass1 can be used.
+To only apply to input records, pragma keys autosave_input_pass0 +autosave_input_pass1 can be used.
+To only apply to output records, pragma keys autosave_output_pass0 +autosave_output_pass1 can be used.
+config (dict) – The pragma configuration dictionary
+Set PINI=1 if VAL is autosaved at pass1.
+This is a bandaid fix for unexplained behavior where the +autosave pass1 does not send values to the PLC unless +PINI=1.
+This is intended to be called for output records.
+Bases: TwincatTypeRecordPackage
Create a set of record for a ENUM Twincat Variable
+Bases: TwincatTypeRecordPackage
Create a set of records for a floating point Twincat Variable
+Generate the record to read values into to the IOC
+record – Description of input record
+EpicsRecord
Generate the record to write values back to the PLC
+This will only be called if the io_direction
is set to "output"
record – Description of output record
+EpicsRecord
Get the scale and offset for the analog record(s).
+Bases: TwincatTypeRecordPackage
Create a set of records for an integer Twincat Variable
+Bases: object
Base class to be inherited by all other RecordPackages
+The subclass must implement the records
property which returns the
+EPICSRecord
objects which will be rendered from the package.
+Optionally, RecordPackage
can have a configure
method which does
+the necessary setup before the record can be configured.
Select the proper subclass of TwincatRecordPackage
from chain
Generated EPICSRecord
objects
Jinja rendered entry for the RecordPackage
+string
+returns: Returns true if this record is fully specified and valid. +:rtype: bool
+Bases: TwincatTypeRecordPackage
RecordPackage for broadcasting string values
+Generate the record to read values into to the IOC
+record – Description of input record
+EpicsRecord
An auxiliary ‘lso’ link record to pass string PVs to the PLC.
+Generate the record to write values back to the PLC
+This will only be called if the io_direction
is set to "output"
record – Description of output record
+EpicsRecord
Number of elements in record
+All records that will be created in the package
+Bases: RecordPackage
The common parent for all RecordPackages for basic Twincat types
+This main purpose of this class is to handle the parsing of the pragma
+chains that will be shared among all variable types. This includes setting
+the appropriate asyn port together and handling the “io” directionality. If
+you have a TmcChain
but are not certain which class is
+appropriate use the from_chain()
class constructor and the correct
+subclass will be chosen based on the given variable information.
In order to subclass:
+input_rtyp
and output_rtyp
need to be provided. These
+are the EPICS RTYPs that are necessary for input and output variables.
If there are default values for fields, these can be provided in the
+field_defaults
. Setting this on a subclass will only override
+fields in parent classes that are redundant. In other words,
+default_fields
are inherited if not explicitly overwritten. Also
+note that these defaults are applied to both the input and output
+records.
dtyp
needs to be set to the appropriate value for the Twincat
+type.
The generate_input_record()
and generate_output_record()
+functions can be subclasses if further customisation is needed. This is
+not required.
Asyn input port specification (for INP field)
+Asyn output port specification (for OUT field)
+Input record update options (TS_MS or POLL_RATE)
+Generate the record to read values into to the IOC
+record – Description of input record
+EpicsRecord
Generate the record to write values back to the PLC
+This will only be called if the io_direction
is set to "output"
record – Description of output record
+EpicsRecord
Determine the direction based on the io config lines
+direction – {‘input’, ‘output’}
+str
+All records that will be created in the package
+Bases: TwincatTypeRecordPackage
Create a set of records for a Twincat Array
+Add field specifying DTYP without specifying array direction
+The following is taken from the EPICS wiki: “This field specifies the +device type for the record. Each record type has its own set of device +support routines which are specified in devSup.ASCII. If a record type +does not have any associated device support, DTYP and DSET are +meaningless.”
+Field type of value
+Generate the record to read values into to the IOC
+record – Description of input record
+EpicsRecord
Generate the record to write values back to the PLC
+This will only be called if the io_direction
is set to "output"
record – Description of output record
+EpicsRecord
Number of elements in record
+Generate an archive settings given a list of record packages
+packages (list of record packages)
+str – One line from the archiver settings file
+Create autosave defaults for a given record type.
+input_pass0 (List[str]) – Fields to save on the input record for pass 0 (pre-iocInit)
input_pass1 (List[str]) – Fields to save on the input record for pass 1 (post-iocInit)
output_pass0 (List[str]) – Fields to save on the output record for pass 0 (pre-iocInit)
output_pass1 (List[str]) – Fields to save on the output record for pass 1 (post-iocInit)
exclude_defaults (bool, optional) – Exclude the defaults normally used for all records.
Dictionary of defaults with keys “input” and “output”, under which +are keys “pass0” and “pass1”.
+dict
+Sort the ordered dict according to the sort_scheme given at instantiation. +Does NOT sort in place.
+unsorted (OrderedDict
) – An OrderedDict in need of sorting.
sort_lookup (Optional
[dict
]) – Requires a Dictionary, reverse lookup table for identifying sorting
+order. If left as None,
+default_settings.unified_ordered_field_list.unified_list
+is used.
last (Optional
[bool
]) – If True, place the alphabetized entries at the end, otherwise, place
+them at the start.
OrderedDict
TMC, XTI, tsproj parsing utilities
+Bases: _TwincatProjectSubItem
, _POUMember
[TcPOU] Code declaration for actions.
+Bases: _TmcItem
[TMC] Array information for a DataType or Symbol
+ARRAY [] OF ARRAY [] level
+Hook for subclasses; called after __init__
+Bases: TwincatItem
[XTI] A single NC axis
+Bases: TwincatItem
[XTI] Axis Parameters
+Has information on units, acceleration, deadband, etc.
+Bases: Type
[TMC] A reference to the data type of a symbol
+Bases: _TmcItem
Bases: _TmcItem
Bases: object
Binds a symbol or SubItem with array/pointer/etc information.
+Bases: _IoTreeItem
[XTI] A box / module
+Bases: object
[TMC] A built-in data type such as STRING, INT, REAL, etc.
+Bases: TwincatItem
[XTI] A code entry in a nested/virtual PLC project
+File to load is marked with ‘Include’ +May be TcTTO, TcPOU, TcDUT, GVL, etc.
+Bases: _TwincatProjectSubItem
[TcDUT] Data unit type (DUT)
+The declaration code; i.e., the top portion in visual studio
+The full source code - declaration only in the case of a DUT
+str
Bases: _TmcItem
[TMC] Container that holds symbols
+Bases: _TmcItem
[TMC or TSPROJ] A DataType with SubItems, likely representing a structure
+Globally unique identifier for the data type.
+Note
+This is not available for all data types.
+Bases: _TmcItem
[TMC or TSPROJ] Container of DataType
+Hook for subclasses; called after __init__
+Bases: _TwincatProjectSubItem
[TcDUT/TcPOU/TcGVL] Code declaration
+Bases: Resolution
Library default version resolution.
+Bases: _IoTreeItem
[XTI] Top-level IO device container
+Bases: TwincatItem
[XTI] Encoder parameters
+Includes such parameters as ScaleFactorNumerator, ScaleFactorDenominator, +and so on.
+Bases: TwincatItem
[XTI] Encoder
+Contains EncPara, Vars, Mappings, etc.
+Bases: TwincatItem
Pdo Entry, containing name and type information.
+The comment associated with the entry.
+Bases: _TmcItem
[TMC] Enum values, strings, and associated comments
+Bases: _TwincatProjectSubItem
[TcDUT] An enumerated text list type
+The declaration code; i.e., the top portion in visual studio
+The full source code - declaration only in the case of an ENUM
+str
Bases: TwincatItem
EtherCAT information for a given Box.
+Contains SyncMan, Fmmu, DcMode, Pdo, etc.
+Bases: _TmcItem
[TMC] A marker of inheritance / extension, found on DataType
+Globally unique identifier for the data type.
+Note
+This is not available for all data types.
+Namespace of the data type.
+The type name, without a namespace.
+Bases: _TwincatProjectSubItem
[TcGVL] A Global Variable List
+The declaration code; i.e., the top portion in visual studio
+The full source code - declaration only in the case of a GVL
+str
Bases: _POUPropertyMember
POU Property getter.
+Bases: _TwincatProjectSubItem
[TcDUT/TcPOU] Code implementation
+Structured text code if it exists:
+Bases: _TwincatProjectSubItem
[tsproj] PLC Instance.
+ + +Bases: TwincatItem
[XTI] Top-level IO container, which has devices
+Bases: TwincatItem
, _VersionItemMixin
Library reference.
+Bases: TwincatItem
[XTI] Links between NC/PLC/IO
+Hook for subclasses; called after __init__
+Bases: _TwincatProjectSubItem
, _POUMember
[TcPOU] Code declaration for function block methods.
+Bases: _TmcItem
[TMC] A Module
+Contains generated symbols, data areas, and miscellaneous properties.
+The ADS port assigned to the Virtual PLC
+Bases: TwincatItem
[tsproj or XTI] Top-level NC
+Hook for subclasses; called after __init__
+Bases: _TmcItem
Bases: TwincatItem
Type / library namespace information.
+Bases: TwincatItem
[XTI] For a Link between VarA and VarB, this is the parent of VarA
+Bases: TwincatItem
[XTI] For a Link between VarA and VarB, this is the parent of VarB
+Bases: _TwincatProjectSubItem
[XTI] A Program Organization Unit
+ + +A dictionary of all implementation call blocks
+The declaration code; i.e., the top portion in visual studio
+The full source code - declaration, implementation, and actions
+str
The implementation code; i.e., the bottom portion in visual studio
+The program name, determined from the declaration
+A dictionary of variables defined in the POU
+Bases: TwincatItem
Process data objects, part of an EtherCAT block.
+Bases: TwincatItem
, _VersionItemMixin
Library placeholder reference.
+Bases: TwincatItem
, _VersionItemMixin
Library placeholder resolution.
+Bases: TwincatItem
[tsproj] A project which contains Plc, Io, Mappings, etc.
+This can be an embedded Plc
node in a TopLeveLProject
or an
+external PLC project reference in a Plc
node marked with “File” or
+“PrjFilePath” attributes.
These can be found under TcSmProject
/ TopLevelProject
/ Plc
.
The AMS ID of the configured target
+Find any descendents that are instances of cls.
+cls (TwincatItem)
+Generator
[TypeVar
(T
), None
, None
]
Get the full source code, DUTs, GVLs, and then POUs
+str
The ADS port for the project
+Hook for subclasses; called after __init__
+A guess of the target IP, based on the AMS ID
+Bases: TwincatItem
The top-level of an external .plcproj
project -> PlcProject
.
Found in the .plcproj
file referenced via TcSmProject
/
+TopLevelProject
/ Plc
Bases: _TmcItem
, _TwincatProjectSubItem
, _POUMember
Two possibilities: +[TcPOU] Code declaration for function block properties +[TMC] A property containing a key/value pair
+Examples of TMC properties:
+ApplicationName (used for the ADS port)
+ChangeDate
+GeneratedCodeSize
+GlobalDataSize
+
The property key name
+The property value text
+Bases: TwincatItem
[StaticRoutes] Routes contained in the TwinCat configuration
+Hook for subclasses; called after __init__
+Bases: TwincatItem
Library version resolution.
+Bases: _TwincatProjectSubItem
[TcDUT/TcPOU] Structured text
+Bases: TwincatItem
[tsproj] A container for a safety PLC project (SafetyPlc)
+Bases: TwincatItem
[tsproj] A safety PLC project
+Found under TcSmProject
/ TopLevelProject
/ Safety
.
Bases: _POUPropertyMember
POU Property setter.
+Bases: _TmcItem
[TMC] One element of a DataType
+The sub item offset, in bits
+The sub item size, in bits
+The base type, including the namespace
+The base type
+Bases: _TmcItem
[TMC] A basic Symbol type
+This is dynamically subclassed into new classes for ease of implementation +and searching. For example, a function block defined as FB_MotionStage +will become Symbol_FB_MotionStage.
+ + + + +The base type name, including the namespace
+The base type name.
+alias of Symbol_ST_MotionStage
Bases: Symbol
[TMC] A customized Symbol, representing only ST_MotionStage
+M1 of Main.M1
+The NC Axis associated with the ST_MotionStage
+The Link for NcToPlc
+That is, how the NC axis is connected to the ST_MotionStage
+Main of Main.M1
+Bases: TwincatItem
[tsproj] Top-level system settings.
+`TcSmProject/TopLevelProject/System`
Bases: BuiltinDataType
Bases: TwincatItem
[tsproj] Task instance defined at the project-level (not per PLC).
+TcSmProject/TopLevelProject/System/Tasks/Task
Array index in SystemInfoVarList._TaskInfo.
+Task priority which also defines the task index.
+Bases: TwincatItem
[tsproj] Task container.
+TcSmProject/TopLevelProject/System/Tasks
Hook for subclasses; called after __init__
+Unique priority to task.
+Bases: _TwincatProjectSubItem
[TMC] The top-level TMC file
+Create a fake DataArea in a given parsed TcModuleClass (tmc).
+Some .tmc files (specifically for libraries) may not have a DataArea.
+These areas are required to enumerate data types for summaries and +documentation, due to how pytmc operates internally.
+Bases: TwincatItem
[XTI] Top-level container for XTI files
+Visual Studio-level configuration changes the project layout significantly, +with individual XTI files being created for axes, PLCs, etc. instead of +updating the original tsproj file.
+The additional, optional, level of indirection here can make walking the +tree frustrating. So, we squash these TcSmItems - skipping over them in the +hierarchy - and pushing its children into its parent.
+The original container TcSmItem is accessible in those items through the +.container attribute.
+Bases: TwincatItem
[tsproj] A top-level TwinCAT tsproj
+The .tsproj
root node.
Contains a “top_level_plc” which can contain one or more PLC projects.
+The virtual PLC projects contained in this TcSmProject
+The virtual PLC projects in a dictionary keyed by link name
+Hook for subclasses; called after __init__
+Bases: TwincatItem
[XTI] Top-level PLC, contains one or more projects
+Hook for subclasses; called after __init__
+Bases: TwincatItem
[tsproj] A top-level project.
+Contains Io, System, Motion, Safety, TopLevelPlc, etc.
+Found in .tsproj
under TcSmProject
.
The AMS ID of the configured target
+A guess of the target IP, based on the AMS ID
+The top-level PLC associated with the project.
+This may contain one or more PLC projects.
+Bases: _TmcItem
[TMC] DataTypes/DataType/SubItem/Type
+The referenced type name.
+The base type, including the namespace
+The base type, including the namespace
+The referenced type name.
+Match a path in a case-insensitive manner, returning the actual filename as +it exists on the host machine
+Required on Linux to find files in a case-insensitive way. Not required on +OSX/Windows, but platform checks are not done here.
+path (pathlib.Path or str) – The case-insensitive path
+path – The case-corrected path
+pathlib.Path
+FileNotFoundError – When the file can’t be found
+Determine the Python class name for an element
+element (lxml.etree.Element)
parent (TwincatItem, optional) – The parent to assign to the new element.
tuple[str, type[TwincatItem]]
+class_name (str)
base_class (class)
Get a data type from the project, falling back to the tmc file.
+Parse a given tsproj, xti, or tmc file.
+item
+TwincatItem
+Find project filenames from a solution.
+fn (str, pathlib.Path) – Solution filename
exclude (list or None) – Exclude certain extensions. Defaults to excluding .tcmproj
Take in a list of TwincatItem, categorize each by their class name (based +on XML tag), and return a dictionary keyed on that.
+For example:
+<a> <a> <b> <b>
+
Would become:
+{'a': [<a>, <a>],
+ 'b': [<b>, <b>]
+ }
+
children (list) – list of TwincatItem
+Categorized children
+dict
+Strip off {{namespace}} from: {{namespace}}tag
+str
Bases: object
An expanded EPICS dbd file
+fn (str or file) – dbd filename
+The dbd filename
+str
+pyPDB parsed dbd nodes
+list
+Bases: Results
Container for dbdlint results, with easier-to-access attributes
+Extends pyPDB.dbdlint.Results
+Each error or warning has dictionary keys:
+{name, message, file, line, raw_message, format_args}
+
List of errors found
+list
+List of warnings found
+list
+returns: success – True if the linting process succeeded without errors +:rtype: bool
+Lint a db (database) file using its database definition file (dbd) using +pyPDB.
+dbd (DbdFile or str) – The database definition file; filename or pre-loaded DbdFile
db (str) – The database filename or text
full (bool, optional) – Validate as a complete database
warn_quoted (bool, optional) – A node argument isn’t quoted
warn_varint (bool, optional) – A variable(varname) node which doesn’t specify a type, which defaults +to ‘int’
warn_spec_comm (bool, optional) – Syntax error in special #: comment line
warn_ext_link (bool, optional) – A DB/CA link to a PV which is not defined. Add ‘#: external(“pv.FLD”)
warn_bad_field (bool, optional) – Unable to validate record instance field due to a previous error +(missing recordtype).
warn_rec_append (bool, optional) – Not using Base >=3.15 style recordtype “*” when appending/overwriting +record instances
DBSyntaxError – When a syntax issue is discovered. Note that this exception contains + file and line number information (attributes: fname, lineno, results)
+results
+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” 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]
+
Path to interpreted .tmc file, or a .tsproj project
+Path to output .db file
+Default: <_io.TextIOWrapper name=’<stdout>’ mode=’w’ encoding=’utf-8’>
+Specify an expanded .dbd file for validating fields (requires pyPDB)
+Generate the .db file even if linter issues are found
+Default: False
+Do not show db file context around errors
+Default: False
+The PLC name, if specifying a .tsproj file
+Raise exceptions immediately, such that the IPython debugger may be used
+Default: False
+Save an archive configuration file. Defaults to OUTPUT.archive if specified
+Do not write the archive file, regardless of OUTPUT filename settings.
+Default: False
+“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
+
Path to .tsproj project
+PLC project name, if multiple exist
+PV prefix for the IOC
+Indicates to the shell which binary to use for the st.cmd script
+Default: “../../bin/rhel7-x86_64/adsIoc”
+IOC application binary name
+Default: “adsIoc”
+IOC name (defaults to project name)
+Parse the project only for motor records, skipping other variables with pytmc pragmas
+Default: False
+Path for db files
+Default: “.”
+Path to the IOC dbd file
+Preferred PV delimiter
+Default: “:”
+Post-stcmd, open an interactive Python session
+Default: False
+st.cmd Jinja2 template
+Default: “stcmd_default.cmd”
+Location where templates are stored
+Default: “.”
+Allow non-fatal errors to be ignored
+Default: False
+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
+
input file
+Recursive limit for exploring the file
+Default: 7
+Indent size for output formatting
+Default: 4
+“pytmc-debug” is a Qt interface that shows information about how pytmc +interprets TwinCAT3 .tmc files.
+ +usage: pytmc debug [-h] [-d DBD] [-a] INPUT
+
Path to .tmc file
+Specify an expanded .dbd file for validating fields (requires pyPDB)
+Show all items, even those missing pragmas (warning: slow)
+Default: False
+“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
+
Path to .tsproj project or source code file
+Make output more markdown-friendly, for easier sharing
+Default: False
+Show all pragmas, including good ones
+Default: False
+“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
+
Path to .tsproj project
+PLC project name, if multiple exist
+PV prefix for the IOC
+Indicates to the shell which binary to use for the st.cmd script
+Default: “../../bin/rhel7-x86_64/adsIoc”
+IOC application binary name
+Default: “adsIoc”
+IOC name (defaults to project name)
+Parse the project only for motor records, skipping other variables with pytmc pragmas
+Default: False
+Path for db files
+Default: “.”
+Path to the IOC dbd file
+Preferred PV delimiter
+Default: “:”
+Post-stcmd, open an interactive Python session
+Default: False
+st.cmd Jinja2 template
+Default: “stcmd_default.cmd”
+Location where templates are stored
+Default: “.”
+Allow non-fatal errors to be ignored
+Default: False
+“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
+
Path to project or solution (.tsproj, .sln)
+All possible information
+Default: False
+Outline XML
+Default: False
+Show boxes
+Default: False
+Show code
+Default: False
+Show plcs
+Default: False
+Show NC axes
+Default: False
+Show symbols
+Default: False
+Show TMC types and record suffixes, if available
+Default: False
+Filter the types shown by name
+Show links
+Default: False
+Make output more markdown-friendly, for easier sharing
+Default: False
+Post-summary, open an interactive Python session
+Default: False
+“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 ...]
+
Path to project or solution (.tsproj, .sln)
+Template filename with optional output filename. In the form input_filename[:output_filename]
.Defaults to ‘-’ (standard input -> standard output).
Define a macro for the template in the form MACRO=VALUE
+Post template generation, open an interactive Python session
+Default: False
+“pytmc-types” is a Qt interface that shows DataType-related information from a +tmc file.
+ +usage: pytmc types [-h] INPUT
+
Path to .tmc file
+#!{{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
+
{% for r in records%}
+{{r}}
+
+{% endfor %}
+
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 %}
+}
+