Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REF: use pytmc template to generate everything; fix lots of things #86

Merged
merged 35 commits into from
Sep 6, 2022

Conversation

klauer
Copy link
Contributor

@klauer klauer commented Jul 8, 2022

Changes

  • pytmc >=2.14.0 now required
  • Use pytmc template from upcoming pytmc release to generate:
    • st.cmd
    • Database files
    • Archiver files
  • Removes load_plc_databases.cmd - everything is in st.cmd now
  • Adds a significant amount of version information to the header
  • Removes motion axes from IOC without pragma (*)
  • Style-wise, makes macro usage consistent in st.cmd: $()
  • Adds ability to easily specify the PLC hostname with an IOC Makefile override
  • make build should no longer copy to iocData directories (that can be done with make all or make iocdata)
  • Set setgid bit for iocData directories (2775 instead of 0775) by convention (make it easier for us to edit files there)
  • Automatically adds a route at PLC startup (optional but enabled by default)
  • Automatically determines the task IDs based on the project (-> no more error messages relating to invalid task array indices at boot)
  • Automatically sets max parameter count
  • Reworks how ads-ioc handles production mode settings: autosave/archive files go to $(IOC_DATA) during IOC boot
    • In development mode, the pre/post scripts are not run
  • Adds support for user-specified additional process database files

Issues / related PRs

Closes #85
Closes #83
Closes #81
Closes #79
Closes #80
Closes #70
Closes #20
Closes #87
Closes #88
Closes #89
Closes #90

Requires pcdshub/pytmc#290

Example header

#!/Users/klauer/Repos/ads-ioc/bin/rhel7-x86_64/adsIoc
################### AUTO-GENERATED DO NOT EDIT ###################
#
#         Project: plc-lfe-motion.tsproj
#        PLC name: lfe_motion (lfe_motion Instance)
# Generated using: pytmc 2.13.0+3.gb07d301
# Project version: v1.2.1-72-g23b9231
#    Project hash: 23b9231c2051ec40c3b1df7d0ebdea9d20175611
#
# Libraries:
#   LCLS General: * -> 2.4.2 (SLAC)
#   lcls-twincat-motion: * -> 1.6.0 (SLAC)
#   lcls-twincat-physics: * -> * (SLAC)
#   lcls2-cc-lib: * -> 1.1.2 (SLAC)
#   PMPS: * -> 2.2.0 (SLAC - LCLS)
#   Tc2_MC2: * (Beckhoff Automation GmbH)
#   Tc2_SerialCom: * (Beckhoff Automation GmbH)
#   Tc2_Standard: * (Beckhoff Automation GmbH)
#   Tc2_System: * (Beckhoff Automation GmbH)
#   Tc3_Module: * (Beckhoff Automation GmbH)
#
################### AUTO-GENERATED DO NOT EDIT ###################

st.cmd diff for ioc-lfe-motion:

diff --git a/iocBoot/ioc-lfe-motion/st.cmd b/iocBoot/ioc-lfe-motion/st.cmd
index f3daf87..7032a6b 100755
--- a/iocBoot/ioc-lfe-motion/st.cmd
+++ b/iocBoot/ioc-lfe-motion/st.cmd
@@ -1,11 +1,30 @@
-#!/reg/g/pcds/epics/ioc/common/ads-ioc/R0.4.1/bin/rhel7-x86_64/adsIoc
-###### AUTO-GENERATED DO NOT EDIT ##############
+#!/Users/klauer/Repos/ads-ioc/bin/rhel7-x86_64/adsIoc
+################### AUTO-GENERATED DO NOT EDIT ###################
+#    Project name: None (lfe_motion Instance)
+#        PLC name: lfe_motion
+# Generated using: pytmc 2.13.0+1.g96b963b
+# Project version: v1.2.1-72-g23b9231
+#    Project hash: 23b9231c2051ec40c3b1df7d0ebdea9d20175611
+#
+# Libraries:
+#   LCLS General: * -> 2.4.2 (SLAC)
+#   lcls-twincat-motion: * -> 1.6.0 (SLAC)
+#   lcls-twincat-physics: * -> * (SLAC)
+#   lcls2-cc-lib: * -> 1.1.2 (SLAC)
+#   PMPS: * -> 2.2.0 (SLAC - LCLS)
+#   Tc2_MC2: * (Beckhoff Automation GmbH)
+#   Tc2_SerialCom: * (Beckhoff Automation GmbH)
+#   Tc2_Standard: * (Beckhoff Automation GmbH)
+#   Tc2_System: * (Beckhoff Automation GmbH)
+#   Tc3_Module: * (Beckhoff Automation GmbH)
+#
+################### AUTO-GENERATED DO NOT EDIT ###################
 
 < envPaths
 
 epicsEnvSet("ADS_IOC_TOP", "$(TOP)" )
 
 epicsEnvSet("ENGINEER", "zlentz" )
 epicsEnvSet("LOCATION", "PLC:LFE:MOTION" )
 epicsEnvSet("IOCSH_PS1", "$(IOC)> " )
 epicsEnvSet("ACF_FILE", "$(ADS_IOC_TOP)/iocBoot/templates/unrestricted.acf")
@@ -569,8 +588,8 @@ dbLoadRecords("EthercatMCreadback.template", "PREFIX=$(MOTOR_PREFIX), MOTOR_NAME
 dbLoadRecords("EthercatMCdebug.template", "PREFIX=$(MOTOR_PREFIX), MOTOR_NAME=$(MOTOR_NAME), MOTOR_PORT=$(MOTOR_PORT), AXIS_NO=$(AXIS_NO), PREC=3")
 
 epicsEnvSet("AXIS_NO",         "33")
-epicsEnvSet("MOTOR_PREFIX",    "PLC:LFE:MOTION:")
-epicsEnvSet("MOTOR_NAME",      "Axis:33")
+epicsEnvSet("MOTOR_PREFIX",    "RTDSL0:DIODE:MMS:")
+epicsEnvSet("MOTOR_NAME",      "01")
 epicsEnvSet("DESC",            "Main.M33 / Axis 33")
 epicsEnvSet("EGU",             "mm")
 epicsEnvSet("PREC",            "3")
@@ -583,111 +602,6 @@ dbLoadRecords("EthercatMC.template", "PREFIX=$(MOTOR_PREFIX), MOTOR_NAME=$(MOTOR
 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")
 
-epicsEnvSet("AXIS_NO",         "34")
-epicsEnvSet("MOTOR_PREFIX",    "PLC:LFE:MOTION:")
-epicsEnvSet("MOTOR_NAME",      "Axis:34")
-epicsEnvSet("DESC",            "Main.M34 / Axis 34")
-epicsEnvSet("EGU",             "mm")
-epicsEnvSet("PREC",            "3")
-epicsEnvSet("AXISCONFIG",      "")
-epicsEnvSet("ECAXISFIELDINIT", "")
-epicsEnvSet("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), EGU=$(EGU) $(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")
-
-epicsEnvSet("AXIS_NO",         "35")
-epicsEnvSet("MOTOR_PREFIX",    "PLC:LFE:MOTION:")
-epicsEnvSet("MOTOR_NAME",      "Axis:35")
-epicsEnvSet("DESC",            "Main.M35 / Axis 35")
-epicsEnvSet("EGU",             "mm")
-epicsEnvSet("PREC",            "3")
-epicsEnvSet("AXISCONFIG",      "")
-epicsEnvSet("ECAXISFIELDINIT", "")
-epicsEnvSet("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), EGU=$(EGU) $(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")
-
-epicsEnvSet("AXIS_NO",         "36")
-epicsEnvSet("MOTOR_PREFIX",    "PLC:LFE:MOTION:")
-epicsEnvSet("MOTOR_NAME",      "Axis:36")
-epicsEnvSet("DESC",            "Main.M36 / Axis 36")
-epicsEnvSet("EGU",             "mm")
-epicsEnvSet("PREC",            "3")
-epicsEnvSet("AXISCONFIG",      "")
-epicsEnvSet("ECAXISFIELDINIT", "")
-epicsEnvSet("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), EGU=$(EGU) $(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")
-
-epicsEnvSet("AXIS_NO",         "37")
-epicsEnvSet("MOTOR_PREFIX",    "PLC:LFE:MOTION:")
-epicsEnvSet("MOTOR_NAME",      "Axis:37")
-epicsEnvSet("DESC",            "Main.M37 / Axis 37")
-epicsEnvSet("EGU",             "mm")
-epicsEnvSet("PREC",            "3")
-epicsEnvSet("AXISCONFIG",      "")
-epicsEnvSet("ECAXISFIELDINIT", "")
-epicsEnvSet("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), EGU=$(EGU) $(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")
-
-epicsEnvSet("AXIS_NO",         "38")
-epicsEnvSet("MOTOR_PREFIX",    "PLC:LFE:MOTION:")
-epicsEnvSet("MOTOR_NAME",      "Axis:38")
-epicsEnvSet("DESC",            "Main.M38 / Axis 38")
-epicsEnvSet("EGU",             "mm")
-epicsEnvSet("PREC",            "3")
-epicsEnvSet("AXISCONFIG",      "")
-epicsEnvSet("ECAXISFIELDINIT", "")
-epicsEnvSet("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), EGU=$(EGU) $(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")
-
-epicsEnvSet("AXIS_NO",         "39")
-epicsEnvSet("MOTOR_PREFIX",    "PLC:LFE:MOTION:")
-epicsEnvSet("MOTOR_NAME",      "Axis:39")
-epicsEnvSet("DESC",            "Main.M39 / Axis 39")
-epicsEnvSet("EGU",             "mm")
-epicsEnvSet("PREC",            "3")
-epicsEnvSet("AXISCONFIG",      "")
-epicsEnvSet("ECAXISFIELDINIT", "")
-epicsEnvSet("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), EGU=$(EGU) $(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")
-
-epicsEnvSet("AXIS_NO",         "40")
-epicsEnvSet("MOTOR_PREFIX",    "PLC:LFE:MOTION:")
-epicsEnvSet("MOTOR_NAME",      "Axis:40")
-epicsEnvSet("DESC",            "Main.M40 / Axis 40")
-epicsEnvSet("EGU",             "mm")
-epicsEnvSet("PREC",            "3")
-epicsEnvSet("AXISCONFIG",      "")
-epicsEnvSet("ECAXISFIELDINIT", "")
-epicsEnvSet("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), EGU=$(EGU) $(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")
-
 epicsEnvSet("AXIS_NO",         "41")
 epicsEnvSet("MOTOR_PREFIX",    "SL1L0:POWER:MMS:")
 epicsEnvSet("MOTOR_NAME",      "BOTTOM")
@@ -901,16 +815,19 @@ dbLoadRecords("EthercatMCdebug.template", "PREFIX=$(MOTOR_PREFIX), MOTOR_NAME=$(
 
 dbLoadRecords("iocSoft.db", "IOC=PLC:LFE:MOTION")
 dbLoadRecords("save_restoreStatus.db", "P=PLC:LFE:MOTION:")
-dbLoadRecords("caPutLog.db", "IOC=${IOC}")
+dbLoadRecords("caPutLog.db", "IOC=$(IOC)")
 
-## TwinCat System Databse files ##
-dbLoadRecords("TwinCAT_TaskInfo.db", "PORT=ASYN_PLC, PREFIX=PLC:LFE:MOTION")
-dbLoadRecords("TwinCAT_AppInfo.db", "PORT=ASYN_PLC, PREFIX=PLC:LFE:MOTION")
+## TwinCAT task and application databases ##
+dbLoadRecords("TwinCAT_TaskInfo.db", "PORT=$(ASYN_PORT), PREFIX=PLC:LFE:MOTION")
+dbLoadRecords("TwinCAT_AppInfo.db", "PORT=$(ASYN_PORT), PREFIX=PLC:LFE:MOTION")
 
 cd "$(IOC_TOP)"
 
-## Database files ##
-< "$(IOC_TOP)/load_plc_databases.cmd"
+## PLC Project Database files ##
+dbLoadRecords("lfe_motion.db", "PORT=,PREFIX=PLC:LFE:MOTION:,IOCNAME=$(IOC),IOC=$(IOC)")
+
+# Total records: 9270
+callbackSetQueueSize(20540)
 
 
 # Setup autosave
@@ -940,7 +857,7 @@ iocInit()
 iocLogInit()
 
 # Configure and start the caPutLogger after iocInit
-epicsEnvSet(EPICS_AS_PUT_LOG_PV, "${IOC}:caPutLog:Last")
+epicsEnvSet(EPICS_AS_PUT_LOG_PV, "$(IOC):caPutLog:Last")
 
 # caPutLogInit("HOST:PORT", config)
 # config options:
@@ -948,7 +865,7 @@ epicsEnvSet(EPICS_AS_PUT_LOG_PV, "${IOC}:caPutLog:Last")
 #       caPutLogOnChange    0: log only on value change
 #       caPutLogAll         1: log all puts
 #       caPutLogAllNoFilter 2: log all puts no filtering on same PV
-caPutLogInit("${EPICS_CAPUTLOG_HOST}:${EPICS_CAPUTLOG_PORT}", 0)
+caPutLogInit("$(EPICS_CAPUTLOG_HOST):$(EPICS_CAPUTLOG_PORT)", 0)
 
 # Start autosave backups
 create_monitor_set( "info_positions.req", 10, "" )

TODO

  • Do a full test on a real PLC project
  • Bump pytmc required version when released (do that first)

@klauer
Copy link
Contributor Author

klauer commented Jul 9, 2022

No rush on this, but I could use volunteer testers and reviewers maybe next week (@ZLLentz / @ghalym / @vespos perhaps?)

@klauer klauer changed the title REF: use pytmc template to generate everything REF: use pytmc template to generate everything; fix lots of things Jul 11, 2022
@klauer klauer marked this pull request as ready for review July 11, 2022 19:27
@ZLLentz
Copy link
Member

ZLLentz commented Jul 11, 2022

I'm going to review the code first, but I'd like to quickly ask: for testing the build, I just need to set up an environment with the pytmc PR branch, clone this repo, and point my IOC Makefile to this repo's clone?

@klauer
Copy link
Contributor Author

klauer commented Jul 11, 2022

I just need to set up an environment with the pytmc PR branch, clone this repo, and point my IOC Makefile to this repo's clone?

That's the right idea. I've been using the usual dev_path adjustment and tweaking make variables via the command-line:
PYTHONPATH=$HOME/dev_path:$PYTHONPATH make IOC_TOP=$HOME/Repos/ads-ioc

Copy link
Member

@ZLLentz ZLLentz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, this is looking good- next I want to try a few makefile variants using the example motion project

iocBoot/templates/Makefile.base Outdated Show resolved Hide resolved
@echo "Creating IOC data directory"
install --mode 0775 --group ps-ioc --directory $(IOC_DATA_PATH)/$(IOC_NAME)/{iocInfo,archive,logs,autosave}
install --mode 2775 --group ps-ioc --directory $(IOC_DATA_PATH)/$(IOC_NAME)/{iocInfo,archive,logs,autosave}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I always have to look these up: this is user rwx, group rwx, any r-x, setgid bit so that any can run with the same permissions as group.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also importantly, setgid ensures that permissions for new files underneath that directory get set consistently to that of the parent directory

{% endif %}
{% endfor %}
#
################### AUTO-GENERATED DO NOT EDIT ###################
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 for the verbose st.cmd comment header


< envPaths

epicsEnvSet("ADS_IOC_TOP", "$(TOP)" )

{% if add_plc_route | int != 0 %}
# Add a route to the PLC automatically:
system("${ADS_IOC_TOP}/scripts/add_route.sh {{ plc_host }} {{ ioc_host_ip_regex }}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm excited to see how well this works. I suspect the only time it fails is when the IOC launches prior to the PLC launch?

One question: where exactly is the ioc_host_ip_regex set up? I see the Makefile variable (in ALL CAPS) but nothing else.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect the only time it fails is when the IOC launches prior to the PLC launch?

Yes, but the IOC will also restart if it can't communicate with the PLC, so it should work out 🤞

One question: where exactly is the ioc_host_ip_regex set up? I see the Makefile variable (in ALL CAPS) but nothing else.

It's macro-ified here, along with all of the rest of the ads-ioc-specific variables:
https://github.com/klauer/ads-ioc/blob/1bf04d99caf4661ae9ebdedd6961a4242109bda1/iocBoot/templates/Makefile.base#L96


echo "Running ads-async to add a route to ${ioc_hostname} for IOC host ${ioc_hostname} (${ioc_host_ip})..."
set -x
$CONDA_BIN run ads-async route \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good application of this conda run option 👍

@@ -54,10 +95,12 @@ adsAsynPortDriverConfigure("$(ASYN_PORT)", "$(IPADDR)", "$(AMSID)", "$(AMS_PORT)

cd "$(ADS_IOC_TOP)/db"

{% set motors = get_motors(plc) %}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line item in PR description that I want to call out specifically: Removes motion axes from IOC without pragma (*)

Related change in pytmc: https://github.com/pcdshub/pytmc/pull/290/files#diff-6be6c30834f696fcba07dcfa6bc5e38c3caacea04cb25945a8f4f59233d55967R329

This requires that motion axes have a pytmc pragma for inclusion into the startup script.
I believe this would be a good change, but I'd like to confirm it before moving forward here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be clear: this stops us from creating the placeholder PVs for when someone has left a pragma off of the DUT_MotionStage instance? But it should still index the pragma'd motors correctly, skipping over the gaps? I think it's a good change (and I don't think most people will notice)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct - indexing and other functionality remains. The records for that axis just do not get created.

@@ -13,6 +13,7 @@ SHELL = /bin/bash

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Picking a random line for this to start a thread

Sample size 1 for running this on lcls-twincat-motion-example:

  • the files created are reasonable
  • error messages on make:
WARNING:pytmc.parser:Pytmc failed to figure out what to do with: /cds/group/pcds/epics-dev/zlentz/lcls-twincat-motion-example/lcls-twincat-motion-example/_Config/NC/NC.xti
Traceback (most recent call last):
  File "/cds/home/z/zlentz/pydev/pytmc/parser.py", line 2054, in _pre_load_xti_files
    key = get_key(xti_filename, xti)
  File "/cds/home/z/zlentz/pydev/pytmc/parser.py", line 2037, in get_key
    raise ValueError(f'Hmm: {candidates}')
ValueError: Hmm: [(<class 'pytmc.parser.Image'>, '1', 'nc.xti'), (<class 'pytmc.parser.Axis'>, '1', 'nc.xti'), (<class 'pytmc.parser.Axis'>, '2', 'nc.xti'), (<class 'pytmc.parser.Axis'>, '3', 'nc.xti')]
WARNING:pytmc.parser:Pytmc failed to figure out what to do with: /cds/group/pcds/epics-dev/zlentz/lcls-twincat-motion-example/lcls-twincat-motion-example/_Config/PLC/tc_mot_example.xti
Traceback (most recent call last):
  File "/cds/home/z/zlentz/pydev/pytmc/parser.py", line 2054, in _pre_load_xti_files
    key = get_key(xti_filename, xti)
  File "/cds/home/z/zlentz/pydev/pytmc/parser.py", line 2037, in get_key
    raise ValueError(f'Hmm: {candidates}')
ValueError: Hmm: [(<class 'pytmc.parser.Instance'>, '#x08502000', 'tc_mot_example.xti'), (<class 'pytmc.parser.POU'>, '{7b41e58a-08f0-4959-90b4-af08ef5cbf10}', 'tc_mot_example.xti')]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current runtime behavior is:

  • nothing happens, stalls on failed connections forever (plc is off)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried digging into those warnings a bit but came out empty-handed. My only guess is that the old project is saved slightly differently compared to our standards. At least it's not fatal...

@vespos
Copy link

vespos commented Aug 8, 2022

@klauer We are just done with the liquid jet experiments at XPP and we will take the PLC back to XCS. Are we at a point where we could test this in a real situation?

@klauer
Copy link
Contributor Author

klauer commented Aug 8, 2022

Yes, this is ready for testing (with the expectation that further work might be necessary, of course!)

Also, I may have limited ability to help in debugging/deploying this, depending on the scheduling of laser work this week.

@klauer
Copy link
Contributor Author

klauer commented Aug 10, 2022

Fixes above were after working with Vincent on ioc-xcs-ljh (and ioc-xpp-ljh):

  • Automatic route adding works 🎉
    • Important fix: system() calls have to happen after dbLoadDatabase (of course)
  • Confusion with lsi/lso records
    • I didn't understand how to use an lsi record and was trying to set VAL="the string".
    • DCT=no in the record reference manual means you can't set VAL at dbLoadRecords time
    • This should have been setting INP instead according to tech talk: field(INP, ["This is a long string with more than 40 characters”,])
  • A bunch of other syntax-related issues were fixed
  • The DISP field (disable puts) should be 0/1 and not false/true
  • Production IOC flag has been entirely reworked to be less annoying to use
    • Development IOC -> autosave/archive files generated in iocBoot directory
    • Production IOC -> autosave/archive files generated in $IOC_DATA
    • mkdir step removed from Makefile - this is left to IOC manager to handle
  • Saw another case of an IOC ID mismatch between PLC directory and IOC Manager
    • This can lead to a pretty major deployment issue.
    • I'm not sure if we can automatically detect this in any way or what...

@ZLLentz
Copy link
Member

ZLLentz commented Aug 11, 2022

Production IOC flag has been entirely reworked to be less annoying to use

I think the rework you describe here is great

Saw another case of an IOC ID mismatch between PLC directory and IOC Manager

What exactly is this issue? I seem to have forgotten

@klauer
Copy link
Contributor Author

klauer commented Aug 11, 2022

Saw another case of an IOC ID mismatch between PLC directory and IOC Manager
What exactly is this issue? I seem to have forgotten

I know you saw this already, but for the sake of looking back on this PR, the relevant issue is: #90

@klauer
Copy link
Contributor Author

klauer commented Aug 29, 2022

Any objections to merging and tagging this?

@slactjohnson
Copy link

@klauer LGTM

@slactjohnson slactjohnson self-requested a review September 6, 2022 17:05
@klauer klauer merged commit fc8a48a into pcdshub:master Sep 6, 2022
@klauer klauer deleted the ref_pytmc_template branch September 6, 2022 17:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment