pcdshub / pytmc

Generate EPICS IOCs and records from TwinCAT projects - along with many TwinCAT project tools
https://pcdshub.github.io/pytmc/
Other
10 stars 11 forks source link

MNT: warn on misconfiguration of TwinCAT IDE/project settings #318

Closed klauer closed 1 year ago

klauer commented 1 year ago

The issue

When TwinCAT is not configured according to our setup guide (specifically independent project files), the user gets a confusing traceback while attempting to generate an IOC startup script that links NC axes back to their DUT_MotionStage (or ST_MotionStage):

Traceback (most recent call last):
 File "C:\miniconda\envs\ads-deploy-2.9.1\lib\site-packages\jinja2\environment.py", line 466, in getitem
  return obj[argument]
TypeError: 'Symbol_DUT_MotionStage' object is not subscriptable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
 File "C:\miniconda\envs\ads-deploy-2.9.1\Scripts\pytmc-script.py", line 33, in <module>
  sys.exit(load_entry_point('pytmc', 'console_scripts', 'pytmc')())
 File "c:\repos\pytmc\pytmc\bin\pytmc.py", line 91, in main
  func(**kwargs)
 File "c:\repos\pytmc\pytmc\bin\template.py", line 742, in main
  raise stashed_exception
 File "c:\repos\pytmc\pytmc\bin\template.py", line 735, in main
  rendered = render_template(template_text, template_args)
 File "c:\repos\pytmc\pytmc\bin\template.py", line 621, in render_template
  return env.get_template('template').render(context)
 File "C:\miniconda\envs\ads-deploy-2.9.1\lib\site-packages\jinja2\environment.py", line 1301, in render
  self.environment.handle_exception()
 File "C:\miniconda\envs\ads-deploy-2.9.1\lib\site-packages\jinja2\environment.py", line 936, in handle_exception
  raise rewrite_traceback_stack(source=source)
 File "<template>", line 156, in top-level template code
 File "C:\miniconda\envs\ads-deploy-2.9.1\lib\site-packages\jinja2\filters.py", line 409, in do_sort
  return sorted(value, key=key_func, reverse=reverse)
 File "C:\miniconda\envs\ads-deploy-2.9.1\lib\site-packages\jinja2\filters.py", line 112, in attrgetter
  item_i = environment.getitem(item_i, part)
 File "C:\miniconda\envs\ads-deploy-2.9.1\lib\site-packages\jinja2\environment.py", line 475, in getitem
  return getattr(obj, attr)
 File "c:\repos\pytmc\pytmc\parser.py", line 1585, in nc_axis
  link = self.nc_to_plc_link
 File "c:\repos\pytmc\pytmc\parser.py", line 1577, in nc_to_plc_link
  raise RuntimeError(f'No NC link to DUT_MotionStage found for '
RuntimeError: No NC link to DUT_MotionStage found for 'Main.M1'

This was a bit of a rabbit hole, because this error:

TypeError: 'Symbol_DUT_MotionStage' object is not subscriptable

Is due to Jinja confusingly doing the following:

  1. Trying motor.nc_axis and having it raise with the "No NC link found"
  2. Trying motor["nc_axis"] and having it raise because Symbol_DUT_MotionStage does not support __getitem__

The core of the issue is not the getitem exception, but rather that there was no NC link found. Yet the NC links clearly existed in the project! So what was going on?

When misconfigured (or in the default configuration), TwinCAT stores mappings inside the .tsproj file (and in fact there is no XTI file to speak of for a PLC project). While technically this is OK from what TwinCAT expects, pytmc assumes you've gone through the process listed below. So it finds no mappings where it expects, and it can't correlate your symbol with an NC axis.

The fix

  1. We want people to follow the guide
  2. But failing miserably with a confusing error is bad for them (and for me because I forget about this stuff)
  3. So this PR adds in support for the misconfiguration but is loud about it, such that when you build an IOC you see this:
    WARNING:pytmc.parser:TwinCAT/project settings misconfiguration; no mappings in XTI file.Please fix your environment and project.
    WARNING:pytmc.parser:TwinCAT/project settings misconfiguration; no mappings in XTI file.Please fix your environment and project.
    WARNING:pytmc.parser:TwinCAT/project settings misconfiguration; no mappings in XTI file.Please fix your environment and project.
    * Copying envPaths and fixing variables...

(Several times multiplied by the number of NC axes in your project) So it's loud but it should still generate the IOC.

Configuration reference

TwinCAT will bundle components of a PLC solution into 2-3 files by default. This default behavior will obscure/conflate changes between seemingly unrelated parts of the project. That means when you change a setting in an EtherCAT terminal, the overall project item will appear changed. So basically the project item always appears changed, and it's difficult to tell what caused it!

To keep things clear, you must tell TwinCAT to track project files individually. This guide shows how. > Do everything they suggest, ensuring:

  1. All options are set to True in Tools / Options / TwinCAT / XAE Environment / File settings: image
  2. Your PLC project instance has "Keep unrestored link info" checked: image
ZLLentz commented 1 year ago

If you're feeling green-checkmarky today you may consider fixing the recipe here: https://github.com/pcdshub/pytmc/blob/73bd2d9767f9b54b69766793cba9db57a4bd681f/conda-recipe/meta.yaml#L27

klauer commented 1 year ago

Is there a specific project we should add as a test case for this?

We could make a simple one or use this one: https://github.com/pcdshub/lcls-plc-polycapillary/commit/a71e6f465d6292be827a27026ce0eb820d3b2249

Or is it not worth the extra effort?

It is worth the effort but digging into the root cause of this exhausted me so I think it'll be this kind of scenario: "merge and then create a would-be-nice-to-have-a-real-test issue"

I also need to pull apart this commit at some point (separate TODO): https://github.com/pcdshub/pytmc/pull/317/commits/c487c4719f48fb3cc7d429383ef982dfc7062298

ZLLentz commented 1 year ago

I think it's totally reasonable to end it here and work on other things

ZLLentz commented 1 year ago

Look at all that GREEN

klauer commented 1 year ago

💚